ACProtect 1.22b脱壳手记----NOTEPAD.EXE

[ 来源:http://www.91now.com/down/ | 作者: | 时间:2008-4-18 | 浏览: 人次 ]

 

010220AC    90               NOP 
010220AD    90               NOP 
010220AE    8BB5 F6DE4000    MOV ESI,DWORD PTR SS:[EBP+40DEF6] 
010220B4    53               PUSH EBX 
010220B5    50               PUSH EAX 
010220B6    E8 CABCFFFF      CALL NOTEPAD_.0101DD85 
010220BB    8BD8             MOV EBX,EAX 
010220BD    58               POP EAX 
010220BE    33C3             XOR EAX,EBX 
010220C0    C606 68          MOV BYTE PTR DS:[ESI],68 
010220C3    8946 01          MOV DWORD PTR DS:[ESI+1],EAX 
010220C6    C746 05 81342400 MOV DWORD PTR DS:[ESI+5],243481 
010220CD    895E 08          MOV DWORD PTR DS:[ESI+8],EBX 
010220D0    C646 0C C3       MOV BYTE PTR DS:[ESI+C],0C3 
010220D4    5B               POP EBX 
010220D5    8BC6             MOV EAX,ESI 
010220D7    8385 F6DE4000 0D ADD DWORD PTR SS:[EBP+40DEF6],0D 
010220DE    5E               POP ESI 
010220DF    8907             MOV DWORD PTR DS:[EDI],EAX  ;③ 这里把API写入正确的IAT里 
010220E1    8385 2DDE4000 04 ADD DWORD PTR SS:[EBP+40DE2D],4  ;d EDI 就可以看到程序原本的 
010220E8  ^ E9 C6FEFFFF      JMP NOTEPAD_.01021FB3  ;IAT跳转表 
010220ED    83C6 14          ADD ESI,14 
010220F0    8B95 31DE4000    MOV EDX,DWORD PTR SS:[EBP+40DE31] 
010220F6  ^ E9 28FEFFFF      JMP NOTEPAD_.01021F23 
010220FB    60               PUSHAD        \;④ 上面的①②改掉后,用F4直接运行到这里 
010220FC    E8 00000000      CALL NOTEPAD_.01022101    |;也可下硬件断点,F9运行,断下后 
01022101    5E               POP ESI        |;再把①②处改会原来的代码. 
01022102    83EE 06          SUB ESI,6        |;一定要改回去,不然壳会在最后 
01022105    B9 09020000      MOV ECX,209      |;效验并解密伪OEP处代码时出错! 
0102210A    29CE             SUB ESI,ECX      | 
0102210C    BA BAA8FF62      MOV EDX,62FFA8BA      | 
01022111    C1E9 02          SHR ECX,2        | 
01022114    83E9 02          SUB ECX,2        | 
01022117    83F9 00          CMP ECX,0        | 
0102211A    7C 1A            JL SHORT NOTEPAD_.01022136    | 
0102211C    8B048E           MOV EAX,DWORD PTR DS:[ESI+ECX*4]  | 
0102211F    8B5C8E 04        MOV EBX,DWORD PTR DS:[ESI+ECX*4+4]  | 
01022123    2BC3             SUB EAX,EBX      | 
01022125    C1C8 1F          ROR EAX,1F        | 
01022128    33C2             XOR EAX,EDX      | 
0102212A    81C2 D82567EC    ADD EDX,EC6725D8      | 
01022130    89048E           MOV DWORD PTR DS:[ESI+ECX*4],EAX  | 
01022133    49               DEC ECX        | 
01022134  ^ EB E1            JMP SHORT NOTEPAD_.01022117  /;这段循环是把010220F6前的代码 
01022136    61               POPAD      ;恢复加密,这样的循环在Acpr里 
01022137    61               POPAD      ;随处可见,每段解密后的执行代码后 
01022138    C3               RETN         ;都会有这样的恢复加密的循环 

PS:在③处d edi后,可以在内存窗口里随便找一个字节,把它随便改成别的值,然后再改会原来的值,这样OD就会把之后写入该内存页所有的值用红色高亮显示,在④处断下后,在内存窗口里找到最前面的用红色显示的值,它的地址就是IAT了!我这里看到的是01001000,用ImportREC得到输入表时RAV里填的就是01001000-01000000=1000 


——————————————————————————————————— 

3.快速到达处理Stolen code的地方 

我们已经在01010F19下了硬件访问断点,在做完上面的处理后,按F9运行,就会直接断在开始处理Stolen code的地方,如下 
        . 
        . 
        . 
        . 
010236D1    61               POPAD 
010236D2    56               PUSH ESI 
010236D3    BE E50E0101      MOV ESI,NOTEPAD_.01010EE5 
010236D8    890E             MOV DWORD PTR DS:[ESI],ECX 
010236DA    5E               POP ESI 
010236DB    FF35 E50E0101    PUSH DWORD PTR DS:[1010EE5] 
010236E1    893C24           MOV DWORD PTR SS:[ESP],EDI 
010236E4    57               PUSH EDI 
010236E5    BF 190F0101      MOV EDI,NOTEPAD_.01010F19 
010236EA    893D E10E0101    MOV DWORD PTR DS:[1010EE1],EDI 
010236F0    5F               POP EDI 
010236F1    FF35 E10E0101    PUSH DWORD PTR DS:[1010EE1]                ; NOTEPAD_.01010F19 
010236F7    8B3C24           MOV EDI,DWORD PTR SS:[ESP] 
010236FA    8F05 DD0E0101    POP DWORD PTR DS:[1010EDD]                 ; NOTEPAD_.01010F19 
01023700    892F             MOV DWORD PTR DS:[EDI],EBP    ;EDI=01010F19 
01023702    8B3C24           MOV EDI,DWORD PTR SS:[ESP]    ;断在这儿   
01023705    8F05 F90E0101    POP DWORD PTR DS:[1010EF9] 
0102370B    FF35 190F0101    PUSH DWORD PTR DS:[1010F19] 
01023711    8925 150F0101    MOV DWORD PTR DS:[1010F15],ESP 
01023717    893D BD0E0101    MOV DWORD PTR DS:[1010EBD],EDI 
0102371D    90               NOP 
0102371E    90               NOP 
0102371F    60               PUSHAD 
01023720    50               PUSH EAX 
01023721    E8 01000000      CALL NOTEPAD_.01023727 
        . 
        . 
        . 
        . 
    从这段代码起Acpr开始处理Stolen code,具体的Stolen code我不是很在行,几位老大已经分析的清晰透彻了. 
    Acpr对Stolen code处理的代码是分段解密后再执行的,因为我们前面在这个内存页里改过数据,所以所有重新写入的代码都是用红色高亮显示了,这就给我们用F4快速执行过解密代码带来了方便,具体方法是在最后一句高亮显示的代码开始向上找0F85 xxFFFFFF(JNZ xxxxxxxx)远程跳转语句,然后F4到它下面的一句上,有的0F85 xxFFFFFF的语句会因为它前后的代码环境而不被OD显示出来,这是可以Crtl+G到0F85 xxFFFFFF的地址,也可以找到高亮显示的最后一个E8 010000 或EB 01,然后F4到其上,再F7几步就可以看到0F85 xxFFFFFF(JNZ xxxxxxxx)了 
    处理Stolen code的前几段代码都是对堆栈的处理,要是不分析Stolen code的话可以不用管,但是后面几段因为会包含到程序OEP的Call,如果执行这些Call的话,就有可能因为执行了Replace Code而改变程序的数据结构. 
    我的处理方法是把这些Call先nop掉,在执行完nop后,在把Call的代码恢复回去,例如:下面代码执行到①处CALL DWORD PTR DS:[100115C] 时把它先用nop填充掉,等走完nop后再把CALL DWORD PTR DS:[100115C]写回去,但②③会用到EAX指针,我们跳过了Call,所以到②和③时会出错,于是一不做二不休,把②③的代码也按刚才的方法干掉  


01028D7E   /E9 04000000     JMP NOTEPAD_.01028D87 
01028D83   |66:BD 27CC      MOV BP,0CC27 
01028D87   \61              POPAD 
01028D88    FF15 5C110001   CALL DWORD PTR DS:[100115C]                ; msvcrt.__p__fmode ① 
01028D8E    891D 110F0101   MOV DWORD PTR DS:[1010F11],EBX          
01028D94    FF35 110F0101   PUSH DWORD PTR DS:[1010F11] 
01028D9A    C705 0D0F0101 4>MOV DWORD PTR DS:[1010F0D],NOTEPAD_.010088> 
01028DA4    8B1D 0D0F0101   MOV EBX,DWORD PTR DS:[1010F0D]             ; NOTEPAD_.010065D0 
01028DAA    8B0B            MOV ECX,DWORD PTR DS:[EBX] 
01028DAC    8B1C24          MOV EBX,DWORD PTR SS:[ESP] 
01028DAF    8F05 090F0101   POP DWORD PTR DS:[1010F09] 
01028DB5    8908            MOV DWORD PTR DS:[EAX],ECX      ;② 
01028DB7    FF15 4C110001   CALL DWORD PTR DS:[100114C]                ; msvcrt.__p__commode 
01028DBD    53              PUSH EBX 
01028DBE    893424          MOV DWORD PTR SS:[ESP],ESI 
01028DC1    57              PUSH EDI 
01028DC2    BF 40880001     MOV EDI,NOTEPAD_.01008840 
01028DC7    8BF7            MOV ESI,EDI 
01028DC9    5F              POP EDI 
01028DCA    8B16            MOV EDX,DWORD PTR DS:[ESI] 
01028DCC    8B3424          MOV ESI,DWORD PTR SS:[ESP] 
01028DCF    8F05 050F0101   POP DWORD PTR DS:[1010F05] 
01028DD5    8910            MOV DWORD PTR DS:[EAX],EDX      ;③ 
01028DD7    90              NOP 
01028DD8    60              PUSHAD 
01028DD9    E8 01000000     CALL NOTEPAD_.01028DDF 

PS:每段处理Stolen code的代码前总要走好几段解密代码,鼠标滚轮费的紧啊,偶的食指也隐隐作痛了    越往后走F4就越要甚用,不然一不小心就会跟飞,不放心的话最好用F7步入,最后来到下面: 

01029A80    E8 6245FFFF      CALL NOTEPAD_.0101DFE7    ;EBP=00C0F000 
01029A85    8DB5 80B04100    LEA ESI,DWORD PTR SS:[EBP+41B080]  ;EBP+41B080=102A080,就是前面我们 
01029A8B    8DBD 1EE34000    LEA EDI,DWORD PTR SS:[EBP+40E31E]  ;记下的GetProcAddress的地址! 
01029A91    B9 05000000      MOV ECX,5 
01029A96    F3:A5            REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI] 
01029A98    40               INC EAX        ;这里把包含GetProcAddress在内 
01029A99    EB 01            JMP SHORT NOTEPAD_.01029A9C  ;的5个API地址Copy到[101D31E] 

这5个API是壳的IAT里的,依次是GetProcAddress.GetModuleHandleA.LoadLibraryA.ExitProcess.MessageBoxA 
     这段之后再经过一段解密代码就到了壳解密伪OEP处代码并跳向伪OEP的地方,所以如果要快速到达伪OEP,就可以在前面我们得到GetProcAddress的地址时,在它上面下硬件访问断点!

广告位