高级ROP
参考:https://www.cnblogs.com/ichunqiu/p/9542224.html
参考:https://blog.youkuaiyun.com/qq_40827990/article/details/88856825
参考:https://blog.youkuaiyun.com/qq_41202237/article/details/107378159?spm=1001.2014.3001.5501
参考:https://wiki.x10sec.org/pwn/linux/user-mode/stackoverflow/x86/advanced-rop/ret2dlresolve/#no-relro
参考:https://ctf-wiki.org/pwn/linux/user-mode/stackoverflow/x86/advanced-rop/srop/#signal
参考:https://xz.aliyun.com/t/5236
1.原理
高级ROP相对于中级ROP和基本ROP来说,利用了更加底层的原理
1.1 ret2_dl_runtime_resolve
1.1.1 _dl_runtime_resolve()函数机制介绍
在基本rop的ret2libc里面,介绍了got表和plt表的延迟绑定技术,其中寻找一个函数的真实地址利用的就是ret2_dl_runtime_resolve(),这个函数用来对动态链接的函数进行重定位。
当我们第一次调用一个函数(比如puts())时,程序会查找需要链接的各种信息,再通过ret2_dl_runtime_resolve()将这个函数的正确地址写入到got.plt表内;第二次使用这个函数的时候,直接查got表,就知道这个函数的地址了。
下面对ret2_dl_runtime_resolve()函数的内部逻辑进行介绍:
函数: _dl_runtime_resolve(link_map_obj, reloc_index)
参数:
- link_map_obj:.dynamic段的基地址
- reloc_index:重定位索引(也就是要寻找的函数的索引,比如说gets()函数的索引就是0x20)
具体流程:
下面对流程进行文字介绍:
- 在.dynamic中可以在0x44偏移处找到.dynstr(动态字符串表)的基地址
- 在0x4c偏移处可以找到.dynsym(动态符号表)的基地址
- 在0x84偏移处可以找到.rel.plt(重定位表)的基地址
- .rel.plt(重定位表)的基地址加上二参reloc_index的重定位索引值,得到函数对应的Elf32_Rel结构体指针
- Elf32_Rel结构体中有两个成员变量:r_offset和r_info,将r_info右移8可以得到函数在.dynsym(动态符号表)中的下标,r_offset对应的是该函数的got表地址
- .dynsym(动态符号表)的基地址加上函数在.dynsym的下标,可以得到函数名在.dynstr(字符串表)中的偏移name_offset
- .dynstr(动态字符串表)的基地址加上name_offset就可以找到函数名了
- 找到函数名利用_dl_lookup_symbol_x()函数就可以找到当前函数的真实地址
- 将真实地址存储在该函数的r_offset(got表)内
使用类c伪代码进行介绍流程:
typedef struct {
Elf32_Addr r_offset;
Elf32_Word r_info;
} Elf32_Rel;
typedef struct {
Elf32_Word st_name; /* Symbol name (string tbl index) */
Elf32_Addr st_value; /* Symbol value */
Elf32_Word st_size; /* Symbol size */
unsigned char st_info; /* Symbol type and binding */
unsigned char st_other; /* Symbol visibility */
Elf32_Section st_shndx; /* Section index */
} Elf32_Sym;
typedef struct {
elf32_sword d_tag union {
elf32_word d_val elf32_addr d_ptr } d_un;
} Elf32_dyn;
struct link_map {
......
};
// 利用link_map_obj和reloc_index对函数的名字进行查找,返回函数名
void _dl_runtime_resolve(link_map link_map_obj, int reloc_index) {
Elf32_dyn dynamic_libc_base = link_map_obj; // 一参link_map_obj中存放的其实是一段地址,这个地址就是.dynamic段的基地址
Address dynstr_libc_base = *dynamic_libc_base[0x44]; // 在.dynamic中可以在0x44偏移处找到.dynstr(动态字符串表)的基地址
Elf32_Sym dynsym_libc_base = *dynamic_libc_base[0x4c]; // 在0x4c偏移处可以找到.dynsym(动态符号表)的基地址
Elf32_Rel rel_plt_libc_base = *dynamic_libc_base[0x84]; // 在0x84偏移处可以找到.rel.plt(重定位表)的基地址
Elf32_Rel target_function_offset = rel_plt_libc_base[reloc_index]; // .rel.plt(重定位表)的基地址加上二参reloc_index的重定位索引值(可以看做偏移)可以得到函数对应的Elf32_Rel结构体指针
Elf32_Addr function_offset = target_function_offset.r_offset; // 得到 r_offset,实际上是函数对应的got表地址
Elf32_Word function_info = target_function_offset.r_info; // 得到 r_info
int dynsym_offset = dynsym_libc_base[function_info >> 8]; // r_info右移8可以得到函数在.dynsym(符号表)中的下标
int name_offset = dynsym_libc_base[dynsym_offset]; // .dynsym(符号表)的基地址加上函数在.dynsym的下标,可以得到函数名在.dynstr(字符串表)中的偏移name_offset
string st_name = dynstr_libc_base[name_offset]; // .dynstr(字符串表)的基地址加上name_offset就可以找到函数名
...
_dl_lookup_symbol_x(st_name, ..., save_addr, ...); // 根据st_name获得函数的真实地址,存储在save_addr内
...
*function_offset = *save_addr; // 把save_addr内存储的真实地址放进对应的got表
}
1.1.2 利用思路
1.1.2.1 思路 1:直接控制重定位表项的相关内容
由于动态链接器最后在解析符号的地址时,是依据符号的名字进行解析的。因此,一个很自然的想法是直接修改动态字符串表 .dynstr,比如把某个函数在字符串表中对应的字符串修改为目标函数对应的字符串。但是,动态字符串表和代码映射在一起,是只读的。此外,类似地,我们可以发现动态符号表、重定位表项都是只读的。
但是,假如我们可以控制程序执行流,那我们就可以伪造合适的重定位偏移,从而达到调用目标函数的目的。然而,这种方法比较麻烦,因为我们不仅需要伪造重定位表项,符号信息和字符串信息,而且我们还需要确保动态链接器在解析的过程中不会出错。
1.1.2.2 思路 2 - 间接控制重定位表项的相关内容
既然动态链接器会从 .dynamic 节中索引到各个目标节,那如果我们可以修改动态节中的内容,那自然就很容易控制待解析符号对应的字符串,从而达到执行目标函数的目的。
1.1.2.3 思路 3 - 伪造 link_map
由于动态连接器在解析符号地址时,主要依赖于 link_map 来查询相关的地址。因此,如果我们可以成功伪造 link_map,也就可以控制程序执行目标函数。
1.2 SROP
SROP中的“S”指的是sigreturn(),在类 unix 系统发生 signal 的时候会被间接地调用,顾名思义,SROP就是利用sigreturn()函数来实现ROP。
1.2.1 signal机制
signal是类unix系统中进程之间的互相传递信息的一种方法。一般称为软中断或者软中断信号。signal机制的步骤如下图所示:
① 内核向某个进程发送signal信号,该进程会被暂时挂起,进入内核态
② 内核会为该进程保存相应的上下文,跳转到之前注册好的**signal handler(处理signal的函数)**中处理signal
③ signal handler执行完毕,signal返回,执行sigreturn
④ 内核为进程恢复之前保留的上下文,恢复进程的执行
备注:
-
②过程的栈帧如下图所示:其实,我们完全可以把signal handler当成一个普通的函数,那么在32位下,它的参数就是往上数2个单位,也就是siginfo,所以也就能够找到需要处理的signal是什么。sigreturn放在了返回地址的位置,也就是执行完signal handler就会去执行的流程。
-
④过程执行完毕,为了恢复保存的上下文,会将之前保存在栈上的寄存器数值,重新pop回对应的寄存器内,最后恢复进程的执行。
-
sigreturn在32位下系统调用号为77,64位下系统调用号为15.
x86和x64下的sigcontext不同,这里分别给出它们sigcontext:
x86下:
struct sigcontext {
unsigned short gs, __gsh;
unsigned short fs, __fsh;
unsigned short es, __esh;
unsigned short ds, __dsh;
unsigned long edi;
unsigned long esi;
unsigned long ebp;
unsigned long esp;
unsigned long ebx;
unsigned long edx;
unsigned long ecx;
unsigned long eax;
unsigned long trapno;
unsigned long err;
unsigned long eip;
unsigned short cs, __csh;
unsigned long eflags;
unsigned long esp_at_signal;
unsigned short ss, __ssh;
struct _fpstate * fpstate;
unsigned long oldmask;
unsigned long cr2;
};
x64:
struct _fpstate {
/* FPU environment matching the 64-bit FXSAVE layout. */
__uint16_t cwd;
__uint16_t swd;
__uint16_t ftw;
__uint16_t fop;
__uint64_t rip;
__uint64_t rdp;
__uint32_t mxcsr;
__uint32_t mxcr_mask;
struct _fpxreg _st[8];
struct _xmmreg _xmm[16];
__uint32_t padding[24];
};
struct sigcontext {
__uint64_t r8;
__uint64_t r9;
__uint64_t r10;
__uint64_t r11;
__uint64_t r12;
__uint64_t r13;
__uint64_t r14;
__uint64_t r15;
__uint64_t rdi;
__uint64_t rsi;
__uint64_t rbp;
__uint64_t rbx;
__uint64_t rdx;
__uint64_t rax;
__uint64_t rcx;
__uint64_t rsp;
__uint64_t rip;
__uint64_t eflags;
unsigned short cs;
unsigned short gs;
unsigned short fs;
unsigned short __pad0;
__uint64_t err;
__uint64_t trapno;
__uint64_t oldmask;
__uint64_t cr2;
__extension__ union {
struct _fpstate * fpstate;
__uint64_t __fpstate_word;
};
__uint64_t __reserved1 [8];
};
1.2.2 攻击原理
如果能够控制栈,也就能够将sigreturn和frame(func)部署到栈上,只需要触发sigreturn,就能够将frame(func)内保存的寄存器数值还原到对应的寄存器上。
比如,我们能够将:payload = syscall_ret + frame(func) 利用栈溢出打到程序的栈上,因为在64位程序下sigreturn的系统调用号为15,因此我们只需要控制rax为15,就能够使得syacall_ret变为调用sigreturn,然后就可以还原相关寄存器了,也就是实现对于寄存器的控制,从而为后续执行其他函数(system)做好准备。
而控制rax,我们可以使用read()函数写入15字节,那么rax作为返回值就会变为15。
因为是syscall_ret,那么执行完syacall (sigreturn)还会ret,我们在前面控制寄存器的时候可以控制eip,使得程序返回任意地址。
因此,我们可以进入如下组合获取shell:
payload = syscall_ret + frame(system),控制frame(system)内eip=syscall_ret或者int 80h。
一旦我们将这个payload放在栈上,执行syscall_ret,那么会获得system()相关的寄存器,然后程序再次执行syscall,也就是执行system,获得shell
和
1.2.3 相关工具介绍
pwntools已经集成了srop的相关工具,即SigreturnFrame(),利用该工具可以得到frame(func),我们以frame(read)为例:
read = SigreturnFrame()
read.rax = constants.SYS_read #read函数系统调用号
read.rdi = 0 #read函数一参
read.rsi = stack_addr #read函数二参
read.rdx = 0x400 #read函数三参
read.rsp = stack_addr #和rsi寄存器中的值保持一致,确保read函数写的时候rsp指向stack_addr
read.rip = syscall_ret #使得rip指向syscall的位置,在部署好read函数之后能直接调用
1.3 ret2VDSO
1.3.1 概述
VDSO(Virtual Dynamically-linked Shared Object)是将内核态的调用映射到用户态的地址空间中, 使得调用开销更小, 路径更好。
举个例子:传统的int 0x80有点慢, Intel和AMD分别实现了sysenter, sysexit和syscall, sysret, 即所谓的快速系统调用指令, 使用它们更快, 但是也带来了兼容性的问题. 于是Linux实现了vsyscall, 程序统一调用vsyscall, 具体的选择由内核来决定. 而vsyscall的实现就在VDSO中。(说人话就是linux实现了一个统一的接口vsyscall,完成触发系统调用的功能,放置在vdso内;vdso内还集成了其他类似的函数,既兼顾了兼容性,又让程序运行速度更快)
1.3.2 vdso.so内函数和gadget
vsdo分为32位和64位,但是因为32位下的函数和gadget更多,因此更容易利用。
看一下/bin/sh在哪里:
$ ldd /bin/sh
linux-vdso.so.1 (0x00007fffe95e8000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f14c5c54000)
/lib64/ld-linux-x86-64.so.2 (0x00007f14c5e7d000)
发现也是在vsdo中实现的。
不光是快速系统调用,glibc现在也提供了vdso的支持,open(), read(), write(), gettimeofday()都可以直接用VDSO中的实现, 使得这些调用更快, glibc更兼容, 内核新特性在不影响glibc的情况下也可以更快的部署.
进一步,我们看一下vsdo中内置的其他函数:
1.3.2.1 x86
看一下函数:
$ objdump -T vdso_x86.so
vdso_x86.so: file format elf32-i386
DYNAMIC SYMBOL TABLE:
00001050 g DF .text 0000000d LINUX_2.5 __kernel_vsyscall
00000d50 g DF .text 000002b2 LINUX_2.6 __vdso_gettimeofday
00001070 g DF .text 00000009 LINUX_2.5 __kernel_sigreturn
00001010 g DF .text 00000028 LINUX_2.6 __vdso_time
00000000 g DO *ABS* 00000000 LINUX_2.5 LINUX_2.5
00001080 g DF .text 00000008 LINUX_2.5 __kernel_rt_sigreturn
00000820 g DF .text 0000052f LINUX_2.6 __vdso_clock_gettime
00000000 g DO *ABS* 00000000 LINUX_2.6 LINUX_2.6
看一下里面有什么gadget:
$ ROPgadget --binary vdso_x86.so
Gadgets information
============================================================
0x00000817 : adc al, 0x31 ; rcr byte ptr [ebx + 0x5e], 0x5f ; pop ebp ; ret
0x000007e4 : adc al, 0x5b ; pop esi ; pop edi ; pop ebp ; ret
0x00000619 : adc byte ptr [ebp + 0xec54704], al ; or al, 0x41 ; ret 0x80e
0x00000ab6 : adc dword ptr [ebp - 0x1c], edx ; jmp 0x909
0x00000a81 : adc dword ptr [ebp - 0x1c], edx ; jmp 0x9c1
0x00000e82 : adc dword ptr [ebp - 0x1c], edx ; jmp 0xdca
0x00001039 : add al, 0x24 ; ret
0x0000089e : add al, 0x3b ; xchg dword ptr [ecx*8 - 0x2a8b0001], esi ; jmp 0x888
0x0000061b : add al, 0x47 ; lds ecx, ptr [esi] ; or al, 0x41 ; ret 0x80e
0x0000107f : add byte ptr [eax + 0xad], bh ; int 0x80
0x0000107d : add byte ptr [eax], al ; add byte ptr [eax + 0xad], bh ; int 0x80
0x0000107c : add byte ptr [eax], al ; add byte ptr [eax], al ; mov eax, 0xad ; int 0x80
0x00000b25 : add byte ptr [eax], al ; add byte ptr [eax], al ; xor eax, eax ; xor edx, edx ; jmp 0xa59
0x00000b81 : add byte ptr [eax], al ; add byte ptr [eax], al ; xor eax, eax ; xor edx, edx ; jmp 0xa8e
0x00000ed9 : add byte ptr [eax], al ; add byte ptr [eax], al ; xor eax, eax ; xor edx, edx ; jmp 0xe5a
0x00000b26 : add byte ptr [eax], al ; add byte ptr [ecx], dh ; sal byte ptr [ecx], 0xd2 ; jmp 0xa59
0x00000b82 : add byte ptr [eax], al ; add byte ptr [ecx], dh ; sal byte ptr [ecx], 0xd2 ; jmp 0xa8e
0x00000eda : add byte ptr [eax], al ; add byte ptr [ecx], dh ; sal byte ptr [ecx], 0xd2 ; jmp 0xe5a
0x00000e3f : add byte ptr [eax], al ; add esp, 0x5c ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x00001074 : add byte ptr [eax], al ; int 0x80
0x0000107e : add byte ptr [eax], al ; mov eax, 0xad ; int 0x80
0x00000f23 : add byte ptr [eax], al ; mov ebx, edx ; jmp 0xe41
0x00000b27 : add byte ptr [eax], al ; xor eax, eax ; xor edx, edx ; jmp 0xa59
0x00000b83 : add byte ptr [eax], al ; xor eax, eax ; xor edx, edx ; jmp 0xa8e
0x00000edb : add byte ptr [eax], al ; xor eax, eax ; xor edx, edx ; jmp 0xe5a
0x00000e40 : add byte ptr [ebx + 0x5e5b5cc4], al ; pop edi ; pop ebp ; ret
0x000010ab : add byte ptr [ebx], al ; add eax, dword ptr [ebx] ; ret
0x00000b28 : add byte ptr [ecx], dh ; sal byte ptr [ecx], 0xd2 ; jmp 0xa59
0x00000b84 : add byte ptr [ecx], dh ; sal byte ptr [ecx], 0xd2 ; jmp 0xa8e
0x00000edc : add byte ptr [ecx], dh ; sal byte ptr [ecx], 0xd2 ; jmp 0xe5a
0x00001032 : add cl, byte ptr [ecx - 0x3ca2a4f6] ; mov eax, dword ptr [esp] ; ret
0x00000ab3 : add dword ptr [ebp - 0x20], eax ; adc dword ptr [ebp - 0x1c], edx ; jmp 0x909
0x00000a7e : add dword ptr [ebp - 0x20], eax ; adc dword ptr [ebp - 0x1c], edx ; jmp 0x9c1
0x00000e7f : add dword ptr [ebp - 0x20], eax ; adc dword ptr [ebp - 0x1c], edx ; jmp 0xdca
0x000010ad : add eax, dword ptr [ebx] ; ret
0x00000ab1 : add edx, ecx ; add dword ptr [ebp - 0x20], eax ; adc dword ptr [ebp - 0x1c], edx ; jmp 0x909
0x00000a7c : add edx, ecx ; add dword ptr [ebp - 0x20], eax ; adc dword ptr [ebp - 0x1c], edx ; jmp 0x9c1
0x00000e7d : add edx, ecx ; add dword ptr [ebp - 0x20], eax ; adc dword ptr [ebp - 0x1c], edx ; jmp 0xdca
0x000007e2 : add esp, 0x14 ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x00000815 : add esp, 0x14 ; xor eax, eax ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x00000e41 : add esp, 0x5c ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x00000967 : add esp, 0x6c ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x0000087c : add esp, 0x6c ; xor eax, eax ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x0000103e : and al, 0xc3 ; mov ebx, dword ptr [esp] ; ret
0x0000103a : and al, 0xc3 ; mov ecx, dword ptr [esp] ; ret
0x00001042 : and al, 0xc3 ; mov edi, dword ptr [esp] ; ret
0x00000801 : and byte ptr [edi], cl ; inc ebp ; ret 0x450f
0x000007ff : and ecx, 0x20 ; cmovne eax, edx ; cmovne edx, esi ; jmp 0x7a1
0x00001141 : call 0x340ff6cf
0x00000d4e : call dword ptr [eax + 0x57e58955]
0x000007d5 : call dword ptr [ecx]
0x000010e6 : call dword ptr [edx]
0x000007f0 : cli ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x00000802 : cmovne eax, edx ; cmovne edx, esi ; jmp 0x7a1
0x00000805 : cmovne edx, esi ; jmp 0x7a1
0x00001045 : cmp al, 0x24 ; ret
0x0000089f : cmp eax, dword ptr [edi - 0x32cc] ; je 0x87c ; jmp 0x888
0x00000d41 : cmp ecx, -1 ; jne 0xa59 ; jmp 0xb22
0x00000c6b : cmp ecx, -1 ; jne 0xa8e ; jmp 0xb7e
0x00000ff4 : cmp ecx, -1 ; jne 0xe5a ; jmp 0xed6
0x00000e4b : cmp esi, 0x3b9ac9ff ; jbe 0xe0c ; jmp 0xdf1
0x00000e50 : cmp esi, dword ptr [esi - 0x47] ; jmp 0xdf1
0x0000071f : cmp esi, eax ; ja 0x717 ; pop esi ; pop edi ; pop ebp ; ret
0x000007cf : dec dword ptr [ebx - 0x32c37d] ; call dword ptr [ecx]
0x00001030 : enter 0x274, -0x77 ; or bl, byte ptr [ebx + 0x5d] ; ret
0x00000974 : fmul qword ptr [ebx - 0x32cb61] ; push esi ; ret
0x00000722 : hlt ; pop esi ; pop edi ; pop ebp ; ret
0x00000b24 : in al, dx ; add byte ptr [eax], al ; add byte ptr [eax], al ; xor eax, eax ; xor edx, edx ; jmp 0xa59
0x00000b80 : in al, dx ; add byte ptr [eax], al ; add byte ptr [eax], al ; xor eax, eax ; xor edx, edx ; jmp 0xa8e
0x00000ed8 : in al, dx ; add byte ptr [eax], al ; add byte ptr [eax], al ; xor eax, eax ; xor edx, edx ; jmp 0xe5a
0x00000a18 : in al, dx ; test esi, esi ; je 0x954 ; jmp 0x87c
0x00001054 : in eax, 0xf ; xor al, 0xcd ; sbb byte ptr [ebp + 0x5a], 0x59 ; ret
0x00000973 : inc ebp ; fmul qword ptr [ebx - 0x32cb61] ; push esi ; ret
0x00000803 : inc ebp ; ret 0x450f
0x00000806 : inc ebp ; salc ; jmp 0x7a1
0x00000620 : inc ecx ; ret 0x80e
0x0000061c : inc edi ; lds ecx, ptr [esi] ; or al, 0x41 ; ret 0x80e
0x00000969 : insb byte ptr es:[edi], dx ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x0000087e : insb byte ptr es:[edi], dx ; xor eax, eax ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x00001057 : int 0x80
0x00001072 : ja 0x1074 ; add byte ptr [eax], al ; int 0x80
0x00000721 : ja 0x717 ; pop esi ; pop edi ; pop ebp ; ret
0x000007e0 : jb 0x7ea ; add esp, 0x14 ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x00000715 : jbe 0x71f ; mov eax, esi ; mov edx, ecx ; pop esi ; pop edi ; pop ebp ; ret
0x00000e51 : jbe 0xe0c ; jmp 0xdf1
0x00001031 : je 0x1035 ; mov dword ptr [edx], ecx ; pop ebx ; pop ebp ; ret
0x000008a5 : je 0x87c ; jmp 0x888
0x00000a1b : je 0x954 ; jmp 0x87c
0x00000e8b : jge 0xe4d ; mov dword ptr [ebp - 0x28], esi ; jmp 0xec6
0x00001061 : jmp 0x1070
0x00000a10 : jmp 0x43891516
0x00000a3e : jmp 0x43891544
0x00000808 : jmp 0x7a1
0x00000b97 : jmp 0x859
0x00000a21 : jmp 0x87c
0x000008a7 : jmp 0x888
0x00000b90 : jmp 0x8bd
0x00000ab9 : jmp 0x909
0x00000961 : jmp 0x969
0x00000b9e : jmp 0x975
0x00000a84 : jmp 0x9c1
0x00000ad0 : jmp 0xa59
0x00000ac6 : jmp 0xa8e
0x00000ad8 : jmp 0xb12
0x00000d4a : jmp 0xb22
0x00000b38 : jmp 0xb6e
0x00000c74 : jmp 0xb7e
0x00000ef5 : jmp 0xd7b
0x00000e85 : jmp 0xdca
0x00000e53 : jmp 0xdf1
0x00000f0e : jmp 0xe41
0x00000ee1 : jmp 0xe5a
0x00000e90 : jmp 0xec6
0x00000ffd : jmp 0xed6
0x000010cc : jmp dword ptr [esi]
0x00000d44 : jne 0xa59 ; jmp 0xb22
0x00000c6e : jne 0xa8e ; jmp 0xb7e
0x00000ad6 : jne 0xab0 ; jmp 0xb12
0x00000b36 : jne 0xb10 ; jmp 0xb6e
0x00000ff7 : jne 0xe5a ; jmp 0xed6
0x00000e8e : jne 0xe68 ; jmp 0xec6
0x0000061d : lds ecx, ptr [esi] ; or al, 0x41 ; ret 0x80e
0x00000968 : les ebp, ptr [ebx + ebx*2 + 0x5e] ; pop edi ; pop ebp ; ret
0x0000087d : les ebp, ptr [ecx + esi - 0x40] ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x00000e42 : les ebx, ptr [ebx + ebx*2 + 0x5e] ; pop edi ; pop ebp ; ret
0x000007e3 : les edx, ptr [ebx + ebx*2] ; pop esi ; pop edi ; pop ebp ; ret
0x00000816 : les edx, ptr [ecx + esi] ; rcr byte ptr [ebx + 0x5e], 0x5f ; pop ebp ; ret
0x0000113f : lfence ; mov ebp, esp ; sysenter
0x00000800 : loope 0x822 ; cmovne eax, edx ; cmovne edx, esi ; jmp 0x7a1
0x0000113c : mfence ; lfence ; mov ebp, esp ; sysenter
0x00000ad5 : mov dword ptr [ebp - 0x28], esi ; jmp 0xb12
0x00000b35 : mov dword ptr [ebp - 0x28], esi ; jmp 0xb6e
0x00000e8d : mov dword ptr [ebp - 0x28], esi ; jmp 0xec6
0x00000ad2 : mov dword ptr [ebp - 0x40], ebx ; mov dword ptr [ebp - 0x28], esi ; jmp 0xb12
0x00000b32 : mov dword ptr [ebp - 0x40], ebx ; mov dword ptr [ebp - 0x28], esi ; jmp 0xb6e
0x00000e8a :