CALL指令有多少ç§å†™æ³•
æœ€è¿‘æœ‰ä¸€ä¸ªéœ€æ±‚ï¼Œç»™ä½ ä¸ªåœ°å€ï¼Œçœ‹çœ‹è¿™ä¸ªåœ°å€å‰é¢æ˜¯ä¸æ˜¯ä¸€ä¸ªCALL指令(请åŒå¦ä»¬è‡ªè¡Œè”想该需求的æ¥æºï¼‰ã€‚作为团队的救ç«é˜Ÿå‘˜+ç‚®ç°ï¼Œè¿™ä¸ªç®€å•çš„事情自然è½åœ¨äº†æˆ‘的头上。
这个事情很简å•ï¼Œä½œä¸ºä¸€ä¸ªå–„于站在别人肩膀上的程åºå‘˜æˆ‘们å¯ä»¥è€ƒè™‘使用 libdisasm;如果è¦è€ƒè™‘x64,就试试udis86;如果需è¦ç”¨Python,就有Python包装好的 pydasm。ä¸è¿‡è¿™ä¸¤ä¸ª400KB+的库,显然ä¸å€¼å¾—为了一个CALL指令导入到编译出æ¥å¤§å°ä»…ä»…100Kä¸åˆ°çš„项目代ç 里é¢ã€‚
那么就自己抽一个CALL指令解ç 逻辑出æ¥å¥½äº†ã€‚这个逻辑的å¤æ‚æ€§åœ¨äºŽï¼Œä½ æ— æ³•çŸ¥é“å‰é¢ä¸€ä¸ªCALLæŒ‡ä»¤æœ‰å¤šé•¿ã€‚å› æ¤ï¼Œé¦–先需è¦æžšä¸¾å‡ºæ‰€æœ‰çš„CALLæŒ‡ä»¤æ ¼å¼ã€‚
Intelæœ‰å…¬å¼€çš„æŒ‡ä»¤é›†æ ¼å¼æ–‡æ¡£ï¼Œä½ 需è¦çš„是第二å·çš„上åŠéƒ¨åˆ†ï¼ŒæŒ‡ä»¤é›†ä»ŽA到M。这篇文档的难度超出一般人想象,里é¢æœ‰ä¼—å¤šæ™¦æ¶©çš„æ ‡è¯†ã€ä¸Žç¡¬ä»¶ç´§å¯†ç›¸å…³çš„介ç»ï¼Œæ‹¿åˆ°è¿™åŽï¼Œå³ä½¿ç›´æŽ¥ç¿»åˆ°ç›®å½•çš„CALL 指令一节,也ä¸è§å¾—能够弄清楚。ä¸ç›¸ä¿¡ï¼Ÿæˆ‘们就翻到那里看看:
虽然很明确的列出,第一列是指令的二进制形å¼ï¼Œç¬¬äºŒåˆ—是指令的汇编形å¼ï¼Œä½†æ˜¯é¢å¯¹ç€ E8 cw, FF/2è¿™æ ·çš„æ ‡è¯†ï¼Œä¸€æ ·ä¸çŸ¥é“ç©¶ç«Ÿå¯¹åº”çš„äºŒè¿›åˆ¶æ ¼å¼æ˜¯ä»€ä¹ˆæ ·çš„。
那好,我们就从ç†è§£è¿™äº›æ ‡è¯†å¼€å§‹ã€‚文档å‘å‰ç¿»ï¼Œæœ‰ä¸€ä¸ªä¸“门的节(3.1.1 Instruction Formatï¼‰è®²è¿°è¿™äº›æ ‡è¯†çš„å«ä¹‰ã€‚这里抽出其ä¸ä¸¤ä¸ªç”¨å¾—ç€çš„翻译一下:
è¡¨æ ¼ä¸çš„“Opcodeâ€åˆ—列出了所有的所有å¯èƒ½çš„æŒ‡ä»¤å¯¹åº”çš„äºŒè¿›åˆ¶æ ¼å¼ã€‚有å¯èƒ½çš„è¯ï¼ŒæŒ‡ä»¤ä»£ç 使用åå…进制显示它们在内å˜å½“ä¸çš„å—节。除了这些16进制代ç 之外的部分使用下é¢çš„æ ‡è®°ï¼š
cb, cw, cd, cp, co, ct — opcodeåŽé¢è·Ÿç€çš„一个1å—节(cb),2å—节(cw),4å—节(cd),6å—节 (cp),8å—节(co) 或者 10å—节(ct) 的值。这个值用æ¥è¡¨ç¤ºä»£ç å移地å€ï¼Œæœ‰å¯èƒ½çš„è¯è¿˜åŒ…括代ç 段寄å˜å™¨çš„值。
/digit — digit为0到7之间的数å—,表示指令的 ModR/M byte åªä½¿ç”¨ r/må—段作为æ“作数,而其regå—段作为opcode的一部分,使用digit指定的数å—。
红å—部分ä¸çŸ¥é“什么å«ä¹‰ï¼Ÿæ²¡å…³ç³»ï¼Œæˆ‘们先ä¸çœ‹å®ƒã€‚对于cb/cw之类的,基本上能够简å•çœ‹æ˜Žç™½å…¶ä¸çš„一些指令å«ä¹‰äº†ï¼š
E8 cw çš„å«ä¹‰æ˜¯ï¼šå—节 0xE8 åŽé¢è·Ÿç€ä¸€ä¸ª2å—节æ“作数表示è¦è·³è½¬åˆ°çš„地å€ä¸Žå½“å‰åœ°å€çš„å移é‡ã€‚
E8 cd çš„å«ä¹‰æ˜¯ï¼šå—节 0xE8 åŽé¢è·Ÿç€ä¸€ä¸ª4å—节的æ“作数表示è¦è·³è½¬çš„地å€ä¸Žå½“å‰åœ°å€çš„å移é‡ã€‚
9A cd çš„å«ä¹‰æ˜¯ï¼šå—节 0x9A åŽé¢è·Ÿç€ä¸€ä¸ª6å—节的æ“作数表示è¦è·³è½¬çš„地å€å’Œä»£ç 段寄å˜å™¨çš„值。
那么,åŒæ ·çš„0xE8开头的指令,CPU如何区分åŽé¢çš„æ“作数是2å—节还是4å—节?ç”案是和CPU的模å¼æœ‰å…³ï¼Œåœ¨å®žæ¨¡å¼ä¸‹ï¼Œ0xE8接å—2å—节æ“作数,而32ä½ä¿æŠ¤æ¨¡å¼ä¸‹æŽ¥å—4个å—节,64ä½ä¿æŠ¤æ¨¡å¼ä¸‹åŒæ ·æŽ¥å—4å—节,åŒæ—¶éœ€è¦å¯¹è¯¥æ“作数进行带符å·æ‰©å±•ã€‚
å› æ¤ï¼ŒCALL指令的å‰ä¸¤ç§æ ¼å¼æ˜¯ï¼šE8 xx xx xx xx,和 9A xx xx xx xx xx xx。一个是5å—节长,一个是7å—节长。其实E8 é‚£ç§ï¼Œå°±æ˜¯æˆ‘们在汇编指令里é¢å†™ CALL lable之åŽäº§ç”Ÿçš„,最常è§çš„CALL指令。
然åŽæ˜¯ä¸‹é¢çš„FF /2。这个是0xFFå—节åŽé¢è·Ÿä¸Šä¸€ä¸ªblablabla的东西。这个blablabla的东西是什么呢?è¦è§£é‡Šè¿™ä¸ªï¼Œé¦–先需è¦çŸ¥é“红å—æ ‡å‡ºæ¥çš„部分,å³ModR/M是什么东西。
这个è¦å…ˆå›žåˆ°æœ€åŸºæœ¬çš„一个问题:IA32çš„æŒ‡ä»¤æ ¼å¼ã€‚
å…¶ä¸æ¯ä¸ªéƒ¨åˆ†æ˜¯ä»€ä¹ˆå«ä¹‰å‘¢ï¼Ÿ
首先是指令å‰ç¼€ã€‚有å°è±¡çš„应该记得当年å¦ä¹ 微机原ç†çš„时候æ到过得循环å‰ç¼€ repnz/repne,这个å‰ç¼€å°±æ˜¯è¢«ç¼–ç 在指令的å‰é¢éƒ¨åˆ†çš„。æ¯ä¸ªå‰ç¼€æœ€å¤šä¸€ä¸ªå—节,一æ¡æŒ‡ä»¤æœ€å¤š4个å‰ç¼€ã€‚
然åŽæ˜¯æŒ‡ä»¤ä»£ç (opcodeï¼‰ï¼Œè¿™éƒ¨åˆ†æ ‡è¯†äº†æŒ‡ä»¤æ˜¯ä»€ä¹ˆã€‚è¿™ä¸ªæ˜¯æŒ‡ä»¤å½“ä¸å”¯ä¸€å¿…需的部分。å‰é¢ä¾‹å当ä¸çš„ 0xE8,0xFF都是opcode。
å†åŽé¢å°±æ˜¯æˆ‘们è¦é‡ç‚¹å…³å¿ƒçš„ ModR/Må—段了,还有和它密切相关的SIBå—节。手册2.1.3当ä¸æœ‰å¯¹äºŽå®ƒä»¬çš„详细æ述。
许多指令需è¦å¼•ç”¨åˆ°ä¸€ä¸ªåœ¨å†…å˜å½“ä¸çš„值作为æ“作数,这ç§æŒ‡ä»¤éœ€è¦ä¸€ä¸ªç§°ä¸ºå¯»å€æ¨¡å¼æ ‡è¯†å—节(addressing-form specifier byte),或者å«åšModR/Må—节紧跟在主opcodeåŽé¢ã€‚ModR/Må—节包å«ä¸‹é¢ä¸‰ä¸ªéƒ¨åˆ†çš„ä¿¡æ¯ï¼š
- mod(模å¼ï¼‰åŸŸï¼Œè¿žåŒr/m(寄å˜å™¨/内å˜ï¼‰åŸŸå…±åŒæž„æˆäº†32个å¯èƒ½çš„值:8个寄å˜å™¨å’Œ24个寻å€æ¨¡å¼ã€‚
- reg/opcode(寄å˜å™¨/æ“作数)域指定了8个寄å˜å™¨æˆ–者é¢å¤–çš„3个å—节的opcode。究竟这三个å—节用æ¥åšä»€ä¹ˆç”±ä¸»opcode指定。
- r/m(寄å˜å™¨/内å˜ï¼‰åŸŸå¯ä»¥æŒ‡å®šä¸€ä¸ªå¯„å˜å™¨ä½œä¸ºæ“作数,或者å¯ä»¥å’Œmod域è”åˆç”¨æ¥æŒ‡å®šå¯»å€æ¨¡å¼ã€‚有时候,它和mod域一起用æ¥ä¸ºæŸäº›æŒ‡ä»¤æŒ‡å®šé¢å¤–çš„ä¿¡æ¯ã€‚
这一段有些晦涩。其æ„æ€è§£é‡Šä¸€ä¸‹æ˜¯è¿™æ ·çš„:一个指令往往需è¦å¼•ç”¨ä¸€ä¸ªåœ¨å†…å˜å½“ä¸çš„值,典型的就是如mov:
MOV eax, dword ptr [123456]
MOV eax, dword ptr [esi]
这其ä¸çš„ 123456 或者 esi 就是 MOV 指令引用的内å˜åœ°å€ï¼Œè€ŒMOV关心的是这个地å€å½“ä¸çš„内容。这个时候,需è¦æŸç§æ–¹å¼æ¥ä¸ºæŒ‡ä»¤æŒ‡å®šè¿™ä¸ªæ“作数的类型:是一个立å³æ•°è¡¨ç¤ºçš„地å€ï¼Œè¿˜æ˜¯ä¸€ä¸ªå˜æ”¾åœ¨å¯„å˜å™¨å½“ä¸çš„地å€ï¼Œæˆ–者,就是寄å˜å™¨æœ¬èº«ã€‚
这个用æ¥åŒºåˆ†æ“作数类型的指令å—节就是 ModR/M,确切的说是其ä¸çš„5个ä½ï¼Œå³modå’Œr/m域。剩下的三个ä½ï¼Œå¯èƒ½ç”¨æ¥åšé¢å¤–的指令å—èŠ‚ã€‚å› ä¸ºï¼ŒIA32的指令个数已ç»è¿œè¶…过一个å—节所能表示的256ä¸ªäº†ã€‚å› æ¤ï¼Œæœ‰çš„指令就è¦å¤ç”¨ç¬¬ä¸€ä¸ªå—节,然åŽä¾æ®ModR/M当ä¸çš„reg/opcode域进行区分。
现在回头看å‰é¢çš„红å—æ ‡è¯†çš„éƒ¨åˆ†ï¼Œèƒ½ä¸èƒ½ç†è§£ /digit è¿™ç§è¡¨ç¤ºæ³•äº†ï¼Ÿ
对于SIB的介ç»ï¼Œæˆ‘们先忽略,看看对于CALL指令的枚举我们已ç»èƒ½åšä»€ä¹ˆäº†ã€‚
CALL指令的表示法:FF /2,是 0xFF åŽé¢è·Ÿç€ä¸€ä¸ª /digit 表示的东西。就是说,0xFFåŽé¢éœ€è¦è·Ÿä¸€ä¸ª ModR/M å—节,ModR/Må—节使用 reg/opcode 域 = 2 。那么,reg/opcode = 2 çš„å—节有32个,æ£å¦‚ModR/M的解释,这32个值代表了32ç§ä¸åŒçš„寻å€æ–¹å¼ã€‚是哪32ç§å‘¢ï¼Ÿæ‰‹å†Œä¸Šé¢æœ‰å¼ 表:
éžå¸¸å¤æ‚çš„ä¸€å¼ è¡¨ã€‚çŽ°åœ¨å°±çœ‹çœ‹è¿™å¼ è¡¨æ€Žä¹ˆè¯»ã€‚
首先是列的定义。由于 reg/opcode 域å¯ä»¥ç”¨æ¥è¡¨ç¤ºopcode,也å¯ä»¥ç”¨æ¥è¡¨ç¤ºregï¼Œå› æ¤åŒä¸€ä¸ªå€¼åœ¨ä¸åŒçš„指令当ä¸å¯èƒ½ä»£è¡¨ä¸åŒçš„å«ä¹‰ã€‚在表当ä¸ï¼Œå°±è¡¨çŽ°ä¸ºæ¯ä¸€åˆ—的表头都有很多个ä¸åŒçš„表示。我们需è¦å…³å¿ƒçš„就是 opcode 这一个。注æ„看我用红圈圈出æ¥çš„部分,这一列就是 opcode=2 的一列。而我们需è¦çš„ CALL 指令,也就是在这一列当ä¸ï¼Œ0xFFåŽé¢éœ€è¦è·Ÿç€çš„内容。
行的定义就是ä¸åŒçš„寻å€æ¨¡å¼ã€‚æ£å¦‚手册所说,mod + R/M域,共5个å—节,定义了32ç§å¯»å€æ¨¡å¼ã€‚0x10 – 0x17 对应于寄å˜å™¨å¯»å€ã€‚例如指令 CALL dword ptr [eax] :[eax]寻å€å¯¹åº”的是 0x10ï¼Œå› æ¤ï¼Œè¯¥æŒ‡ä»¤å¯¹åº”的二进制就是 FF 10。åŒç†ï¼Œ CALL dword ptr [ebx] 是 FF 13,CALL dword ptr [esi] 是 FF 16,这些指令都是2个å—节。有人也许问 CALL word ptr [eax] 是什么?抱æ‰ï¼Œè¿™ä¸æ˜¯ä¸€ä¸ªåˆæ³•çš„32ä½æŒ‡ä»¤ã€‚
0x50-0x57部分需è¦å¸¦ä¸€ä¸ª disp8ï¼Œå³ 8bit ç«‹å³æ•°ï¼Œä¹Ÿå°±æ˜¯ä¸€ä¸ªå—节。这个是基地å€+8ä½å移é‡çš„寻å€æ¨¡å¼ã€‚例如 CALL dword ptr [eax+10] 就是 FF 50 10 。注æ„虽然表当ä¸å†™çš„是 [eax] + disp8 è¿™ç§å½¢å¼ï¼Œä½†æ˜¯å¹¶ä¸è¡¨ç¤ºæ˜¯å–å¾— eax 指å‘的地å€å½“ä¸çš„值å†åŠ 上 disp8,而是在eaxä¸ŠåŠ ä¸Šdisp8å†è¿›è¡Œå¯»å€ã€‚å› æ¤å†™æˆ [eax+disp8] æ›´ä¸å®¹æ˜“引起误解。åŽé¢çš„disp32ä¹Ÿæ˜¯ä¸€æ ·çš„ã€‚è¿™ä¸ªç±»åž‹æŒ‡ä»¤æ˜¯3个å—节。
0x90 – 0x97部分需è¦å¸¦ disp32,å³4å—节立å³æ•°ã€‚这个是基地å€+32ä½å移é‡ã€‚例如 CALL dword ptr [eax+12345] 就是 FF 90 00 01 23 45。有趣的是, CALL dword ptr [eax+10] 也å¯ä»¥å†™æˆ FF 90 00 00 00 10。至于汇编æˆå“ªä¸ªäºŒè¿›åˆ¶å½¢å¼ï¼Œè¿™æ˜¯æ±‡ç¼–器的选择。这个类型的指令是6个å—节。
0xD0 – 0xD7部分则直接是寄å˜å™¨ã€‚这边引用的寄å˜å™¨çš„类型有很多,但是在CALL指令当ä¸åªèƒ½å¼•ç”¨é€šç”¨å¯„å˜å™¨ï¼Œå› æ¤ CALL eax 就是 FF D0,è‡åæ˜è‘—çš„ CALL esp 就是 FF D4ã€‚æ³¨æ„ CALL eax å’Œ CALL [eax] 是ä¸ä¸€æ ·çš„。这些指令也是2个å—节。
仔细的人也许主è¦åˆ°äº†ï¼Œåœ¨è¡¨å½“ä¸ï¼Œ0x14, 0x15, 0x54å’Œ0x94是ä¸ä¸€æ ·çš„。0x15比较简å•ï¼Œè¿™ä¸ªè¦æ±‚ ModR/MåŽé¢è·Ÿä¸Šä¸€ä¸ª32ä½ç«‹å³æ•°ä½œä¸ºåœ°å€ã€‚å³å¸¸è§çš„ CALL dword ptr [004F778e] è¿™ç§æ ¼å¼çš„,直接跳转到一个固定内å˜åœ°å€å¤„å˜æ”¾çš„值,常è§äºŽè°ƒç”¨Windows的导出表。对应的二进制是 FF 15 00 4F 77 8E ,有6个å—节。
0x14,0x54,0x94部分是最å¤æ‚çš„ï¼Œå› ä¸ºè¿™ä¸ªæ—¶å€™ï¼ŒModR/Mä¸è¶³ä»¥æŒ‡å®šå¯»å€æ–¹å¼ï¼Œè€Œæ˜¯éœ€è¦ä¸€ä¸ªé¢å¤–çš„å—节,这个å—节就是指令当ä¸çš„第4个å—节,SIB。åŒæ ·åœ¨æ‰‹å†Œçš„2.1.3,紧跟ç€ModR/M的定义:
æŸäº›ç‰¹å®šçš„ModR/Må—节需è¦ä¸€ä¸ªåŽç»å—节,称为SIBå—节。32ä½æŒ‡ä»¤çš„基地å€+å移é‡ï¼Œä»¥åŠ 比例*åç§»é‡ çš„å½¢å¼çš„寻å€æ–¹å¼éœ€è¦SIBå—节。 SIBå—节包括下列信æ¯ï¼š
- scale(比例)域指定了放大的比例。
- index(å移)域指定了用æ¥å˜æ”¾åç§»é‡ çš„å¯„å˜å™¨ã€‚
- base (基地å€ï¼‰åŸŸç”¨æ¥æ ‡è¯†å˜æ”¾åŸºåœ°å€çš„寄å˜å™¨ã€‚
0x14, 0x54, 0x94就是这里所说的“特定的ModR/Må—节。这个å—节åŽé¢è·Ÿç€çš„SIB表示了一个å¤æ‚的寻å€æ–¹å¼ï¼Œå…¸åž‹çš„è§äºŽè™šå‡½æ•°è°ƒç”¨ï¼š
CALL dword ptr [ecx+4*eax]
就是调用ecx指å‘的虚表当ä¸çš„第eax个虚函数。这个指令当ä¸ï¼Œå› 为没有立å³æ•°ï¼Œå› æ¤FFåŽé¢çš„å—节就是0x14,而 [ecx+4*eax] 就需è¦ç”¨SIBå—节æ¥è¡¨ç¤ºã€‚在这个指令当ä¸ï¼Œecx就是 Base,4是Scale,eax是Index。
那么,Base, Scaleå’ŒIndex是如何确定的呢?手册上åŒæ ·æœ‰ä¸€å¼ 表(åˆæ˜¯å·¨å¤§çš„表):
列是Base,行是Index*Scale,例如[ecx+4*eax] 就是0x81。
æ ¹æ®è¿™å¼ 表,CALL dword ptr [ecx+4*eax] 就是 FF 14 81 。由æ¤å¯è§ï¼Œå¯¹äºŽ 0x14系列的æ¥è¯´ï¼ŒCALL指令就是 3个å—节。
而 0x54 带 8bit ç«‹å³æ•°ï¼Œå°±æ˜¯å¯¹åº”于 CALL指令:CALL dword ptr [ecx+4*eax+xx],这个指令就是 FF 54 81 xx,是4个å—节。
åŒç†ï¼Œ0x94带32ä½ç«‹å³æ•°ï¼Œå¯¹åº”于CALL指令:CALL dword ptr [ecx+4*eax+xxxxxxxx],这个指令就是 FF 94 81 xx xx xx xx,是7个å—节。
OK,截æ¢åˆ°ç›®å‰ï¼Œæˆ‘们基本上能够列出常è§çš„CALLæŒ‡ä»¤çš„æ ¼å¼äº†ï¼š
指令 | äºŒè¿›åˆ¶å½¢å¼ |
CALL rel32 | E8 xx xx xx xx |
CALL dword ptr [EAX] | FF 10 |
CALL dword ptr [ECX] | FF 11 |
CALL dword ptr [EDX] | FF 12 |
CALL dword ptr [EBX] | FF 13 |
CALL dword ptr [REG*SCALE+BASE] | FF 14 xx |
CALL dword ptr [abs32] | FF 15 xx xx xx xx |
CALL dword ptr [ESI] | FF 16 |
CALL dword ptr [EDI] | FF 17 |
CALL dword ptr [EAX+xx] | FF 50 xx |
CALL dword ptr [ECX+xx] | FF 51 xx |
CALL dword ptr [EDX+xx] | FF 52 xx |
CALL dword ptr [EBX+xx] | FF 53 xx |
CALL dword ptr [REG*SCALE+BASE+off8] | FF 54 xx xx |
CALL dword ptr [EBP+xx] | FF 55 xx |
CALL dword ptr [ESI+xx] | FF 56 xx |
CALL dword ptr [EDI+xx] | FF 57 xx |
CALL dword ptr [EAX+xxxxxxxx] | FF 90 xx xx xx xx |
CALL dword ptr [ECX+xxxxxxxx] | FF 91 xx xx xx xx |
CALL dword ptr [EDX+xxxxxxxx] | FF 92 xx xx xx xx |
CALL dword ptr [EBX+xxxxxxxx] | FF 93 xx xx xx xx |
CALL dword ptr [REG*SCALE+BASE+off32] | FF 94 xx xx xx xx xx |
CALL dword ptr [EBP+xxxxxxxx] | FF 95 xx xx xx xx |
CALL dword ptr [ESI+xxxxxxxx] | FF 96 xx xx xx xx |
CALL dword ptr [EDI+xxxxxxxx] | FF 97 xx xx xx xx |
CALL EAX | FF D0 |
CALL ECX | FF D1 |
CALL EDX | FF D2 |
CALL EBX | FF D3 |
CALL ESP | FF D4 |
CALL EBP | FF D5 |
CALL ESI | FF D6 |
CALL EDI | FF D7 |
CALL FAR seg16:abs32 | 9A xx xx xx xx xx xx |
有了这个列表,写一段代ç æ¥å®Œæˆæœ€åˆæˆ‘们的需求也就ä¸éš¾äº†ã€‚
请教一下,如果CALL指令是其他指令的æ“作数或æ“作数的一部分,如add指令,然åŽè¿™ä¸ªadd指令和å‰ä¸€æ¡add指令的æ“作数å¯èƒ½ç»„æˆä¸€ä¸ªæ–°çš„å¯è¯†åˆ«çš„指令,åƒè¿™ç§æƒ…况,如何识别æŸä¸ªåœ°å€çš„å‰ä¸€æ¡æŒ‡ä»¤åˆ°åº•æ˜¯ä¸€ä¸ªcall指令或者是其他的指令,谢谢。。。
@ç« ç«
ä½ è¯´çš„è¿™ä¸ªé—®é¢˜çš„ç¡®å˜åœ¨ï¼Œä¾‹å¦‚å‰é¢ä¸€ä¸ªæŒ‡ä»¤æ£å¥½æ˜¯ mov eax, ffffff10,则也会被认为是一个callæŒ‡ä»¤ï¼Œå› ä¸ºä»£ç 检查到å‰é¢æ˜¯ ff 10 就直接认为是一个call [eax] 了。
è¿™ç§æ˜¯æ²¡æœ‰åŠžæ³•çš„ï¼Œå› ä¸ºCPU执行是自上而下解æžï¼ŒæŒ‡ä»¤é›†åªè¦ä¿è¯æ£å‘解æžçš„时候没有æ§ä¹‰å³å¯ï¼›è€Œè¿™è¾¹çš„代ç æ˜¯è‡ªä¸‹è€Œä¸Šçš„æŽ¨ç®—ï¼Œæ˜¯æ— æ³•é¿å…æ§ä¹‰çš„ã€‚å› æ¤è¿™ç§æ‰‹æ®µåªæ˜¯å¯å‘å¼è§„则的当ä¸çš„一部分,必须和其他的规则åˆå¹¶è€ƒè™‘æ‰è¡Œã€‚
å“‡ï¼Œæ¥¼ä¸»ä½ çœŸçš„å¥½åŽ‰å®³~å…‰æ˜¯ç ”ç©¶æ–‡æ¡£å°±å¾ˆéœ€è¦è€å¿ƒå’Œæ¯…åŠ›äº†ï¼Œä½ å±…ç„¶æŠŠè‹±æ–‡æ‰‹å†Œç»™ç ”ç©¶æ¸…æ¥šäº†â€¦â€¦
intel的指令集手册我也有收集,但是光看目录的规模就头大……
这个Mod R\M我以å‰çœ‹ä¸€æœ¬x86教程的时候就有å¦ï¼Œå½“时就是看到这里,实在没看懂就放弃了åŽæ¥æ²¡å†ç¢°ï¼Œä»Šå¤©çœ‹åˆ°åšä¸»çš„æ–‡ç« ï¼Œæ„Ÿåˆ°åšä¸»çœŸçš„相当的niubilityï¼è®²çš„太清楚了ï¼
今天真的收获很大ï¼æˆ‘本æ¥æ˜¯å‘觉windowsé‡Œé»˜è®¤æƒ…å†µä¸‹ï¼Œæ ˆä¸Šçš„æ•°æ®å¯ä»¥ç•…é€šæ— é˜»çš„æ‰§è¡Œï¼ŒäºŽæ˜¯åŽé¢å®žéªŒçš„时候æœâ€œcall 指令编ç e8â€æ‰¾åˆ°è¿™é‡Œçš„。
å¯¹äº†ï¼Œå…³äºŽæ¥¼ä¸Šç« ç« ç«¥éž‹è¯´çš„è¿™ä¸ªæƒ…å†µï¼Œæˆ‘ç‰¹æ„åšäº†ä¸ªå®žéªŒï¼Œå°æ”¹äº†ä¸€ä¸‹åšä¸»ä½ 的程åºï¼Œ
在内å˜ä¸ä»ŽIsAddressAfterCallInstruction这个函数一路æœç´¢åˆ°main函数åŽé¢ä¸€æ®µï¼Œ
å‘è§‰è¿˜çœŸæ˜¯å¾ˆå¤šç« ç« ç«¥éž‹è¯´çš„è¿™ä¸ªæƒ…å†µã€‚
代ç 在:http://codepad.org/J8gKdO8B
(似乎有å¬è¯´æŸäº›ç³»ç»Ÿé‡Œçš„å¯æ‰§è¡Œå†…å˜åŒºåŸŸæ˜¯ä¸å¯è¯»çš„ï¼Œè¿™æ ·çš„è¯æˆ‘è¿™ç§åšæ³•è‚¯å®šä¸è¡Œï¼Œä¸è¿‡windows里没有这ç§æƒ…况)。
也就是说,有一åŠä»¥ä¸Šçš„call指令都是由于指令ä¸çš„ç«‹å³æ•°äº§ç”Ÿçš„误报~感觉如果自己å†æŽ¢ç´¢ä¸€ä¸‹è¿™ä¸ªæ–¹é¢ï¼Œè¿‡æ»¤æŽ‰ä¸€äº›è¯¯æŠ¥ä¹Ÿä¼šå¾ˆæœ‰è¶£çš„~~
ç¥åšä¸»ä¸€åˆ‡é¡ºåˆ©~~
ä½ çš„è¿™ç§æœæ³•å½“然会有大é‡çš„è¯¯æŠ¥ï¼Œå› ä¸ºæ˜¯å®Œå…¨åŸºäºŽé™æ€çš„匹é…。
é™æ€åˆ†æžè¿˜æ˜¯ä½¿ç”¨CPUçš„æ–¹å¼ï¼ŒæŒ‰æŒ‡ä»¤æ‰§è¡Œé¡ºåºä»Žå‰å‘åŽæ‰«ææ›´é 谱一些。
实际的应用当ä¸è¿™æ®µå°ä»£ç 是用æ¥åœ¨åŠ¨æ€æ‰§è¡Œå½“ä¸ä¸æ–下é¢ï¼Œå¹¶ä¸”进行åå‘推æ–使用的。
一个常用的场景是shellcode检测。在这ç§æƒ…况下é¢ï¼Œæ£€æµ‹çš„æ—¶å€™ï¼Œæ— æ³•èŽ·å–之å‰çš„调用åºåˆ—ï¼Œå› æ¤éœ€è¦é€šè¿‡å推的方å¼è¿›è¡Œã€‚
而去误报的è¯ï¼Œå¯ä»¥é€šè¿‡äºŒæ¬¡æ ¡éªŒï¼Œå³æ ¹æ®æŒ‡ä»¤è®¡ç®—该callæŒ‡ä»¤çš„ç›®æ ‡ï¼Œçœ‹è¯¥ç›®æ ‡æ˜¯å¦æ˜¯ä¸€æ®µåˆç†çš„å¯æ‰§è¡Œå†…å˜ã€‚
@Zhang Cong
呵呵,谢谢大虾解ç”~
å¦å¤–ï¼Œåœ¨çœ‹åˆ°ç« ç« çš„è¿™ç§è¯´æ³•ä¹‹å‰ï¼Œæˆ‘想到的一ç§æƒ…况其实就是,
这些“å¯ç–‘的地å€â€ä¹‹å‰å¯èƒ½æ ¹æœ¬å°±ä¸æ˜¯æœ‰æ•ˆçš„指令。
也就是说æŸäº›å—节是跟在return或是jmp这一类指令的åŽé¢ï¼Œå®Œå…¨æ²¡æœ‰æ‰§è¡Œçš„æœºä¼šï¼Œå› æ¤æœ‰åžƒåœ¾æ•°æ®ä¹Ÿä¸å¥‡æ€ªã€‚
好问,解决了我的很多困惑
和您碰到了相åŒçš„问题,技术永远在进æ¥ï¼ŒåŸºç¡€æ°¸è¿œä¸å˜ã€‚å¦ä¹ 了。我å‰å‡ 天在年会上应该å¬è¿‡å’Œæ‚¨ç›¸åŒçš„åå—,太巧了,希望有一天能æˆä¸ºå’Œä½ ä¸€æ ·çš„å¤§ä½¬ã€‚