欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

脱壳手记---themida(1.8.5.5)

脱壳手记---themida(1.8.5.5)

【文章标题】:脱壳手记---themida(1.8.5.5)
【文章作者】: qqmcc
【下载地址】:  sayhello.rar
载入OD后,先看看Memory map,看到多了个壳段(图1)
 
00401000下硬件写入断点
两次shift+f9断在
00618D04    F3:A4           REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
这里写入代码段,之后去00401000看看


00401000    55              PUSH EBP

00401001    8BEC            MOV EBP,ESP

00401003    51              PUSH ECX

00401004    53              PUSH EBX

00401005    56              PUSH ESI

00401006    57              PUSH EDI

00401007    68 30604000     PUSH 00406030        ; ASCII "hello"

0040100C    6A 65           PUSH 65

0040100E    6A 00           PUSH 0

00401010    90              NOP

00401011    90              NOP   00401012    90              NOP

00401013    90              NOP

00401014    90              NOP

00401015    90              NOP

00401016    8BF0            MOV ESI,EAX

00401018    56              PUSH ESI

00401019    6A 00           PUSH 0

0040101B    90              NOP

0040101C    90              NOP   ;下硬件写入断点

0040101D    90              NOP

0040101E    90              NOP

0040101F    90              NOP

00401020    90              NOP

00401021    56              PUSH ESI

00401022    6A 00           PUSH 0

00401024    90              NOP

00401025    90              NOP

00401026    90              NOP

00401027    90              NOP

00401028    90              NOP

00401029    90              NOP

0040102A    8BF0            MOV ESI,EAX


并没有完全解码,继续找未解码处下硬件写入断点:
006229B1    AA              STOS BYTE PTR ES:[EDI]  
分析一下这里的代码,F8单步:
发现填充的是一个call
00401018    56              PUSH ESI
00401019    6A 00           PUSH 0
0040101B    90              NOP
0040101C    E8 FBF34F02     CALL 0290041C
继续跟一下:

006229DB    8B85 B1250E0A   MOV EAX,DWORD PTR SS:[EBP+A0E25B1]

006229E1    2BC7            SUB EAX,EDI

006229E3    83E8 04         SUB EAX,4                    ;取得CALL偏移

006229E6    AB              STOS DWORD PTR ES:[EDI]      ;填充CALL偏移

006229E7    AD              LODS DWORD PTR DS:[ESI]      ;将[esi]赋值eax

                                                        [esi]是一张表见(图2)

006229E8    C746 FC 0000000>MOV DWORD PTR DS:[ESI-4],0    ;清零

006229EF  ^ E9 11FFFFFF     JMP 00622905   ;这里跳回去看是都还有需要处理的”nop”


--------------------------------------------------------------------------------------------------------------------------------

00622905    MOV DWORD PTRSS:[EBP+A0E04DD],ESI     ;比较[esi]的值                    

0062290B    83F8 FF         CMP EAX,-1           ;比较是否为FFFFFFFF

0062290E    0F85 20000000   JNZ 00622934         ;不是就跳走

00622914    813E DDDDDDDD   CMP DWORD PTR DS:[ESI],DDDDDDDD ;比较当前[esi]是否为DDDDDDDD

0062291A    0F85 14000000   JNZ 00622934                 ;不是跳走,应为结束标记以控制循环

00622920    C706 00000000   MOV DWORD PTR DS:[ESI],0    ;当前[ESI]填0, 

00622926    83C6 04         ADD ESI,4                    ;处理下一个[ESI+4]

00622929    89B5 DD040E0A   MOV DWORD PTR SS:[EBP+A0E04DD],ESI

0062292F  ^ E9 E6F6FFFF     JMP 0062201A    ;关注这个跳转,新一轮的解码处理

00622934    C1C0 03         ROL EAX,3

00622937    0385 45180E0A   ADD EAX,DWORD PTR SS:[EBP+A0E1845]

0062293D    83BD 9D190E0A 0>CMP DWORD PTR SS:[EBP+A0E199D],1

00622944    0F84 9D000000   JE 006229E7

0062294A    813E AAAAAAAA   CMP DWORD PTR DS:[ESI],AAAAAAAA

00622950    0F85 12000000   JNZ 00622968


[esi]数据截取(图2):

FFFFFFFF DDDDDDDD作为结束的话,那至少有五个元素,分别分析前面三个元素做什么用。

0062201A    C785 31110E0A 0>MOV DWORD PTR SS:[EBP+A0E1131],0;;从跳转到这里开始分析

00622024    C785 F5110E0A 0>MOV DWORD PTR SS:[EBP+A0E11F5],0

0062202E    83BD 723F1E0A 0>CMP DWORD PTR SS:[EBP+A1E3F72],0

00622035    0F84 08000000   JE 00622043

0062203B    8D9D 3D2C1D0A   LEA EBX,DWORD PTR SS:[EBP+A1D2C3D]

00622041    FFD3            CALL EBX

00622043    FF85 9D120E0A   INC DWORD PTR SS:[EBP+A0E129D]

00622049    83BD 9D120E0A 6>CMP DWORD PTR SS:[EBP+A0E129D],64 ;处理的元素大于0x64则进行一次校验

00622050    0F82 62000000   JB 006220B8     ;可以改成jmp忽略校验

00622056    C785 9D120E0A 0>MOV DWORD PTR SS:[EBP+A0E129D],1

00622060    60              PUSHAD

00622061    8DB5 4A401E0A   LEA ESI,DWORD PTR SS:[EBP+A1E404A]

00622067    8DBD B55C1E0A   LEA EDI,DWORD PTR SS:[EBP+A1E5CB5]

0062206D    2BFE            SUB EDI,ESI

0062206F    8BD7            MOV EDX,EDI    ;校验数据长度

00622071    8BBD 41150E0A   MOV EDI,DWORD PTR SS:[EBP+A0E1541]

00622077    83C9 FF         OR ECX,FFFFFFFF               ;初始化校验值

0062207A    33C0            XOR EAX,EAX

0062207C    8A06            MOV AL,BYTE PTR DS:[ESI]    ;校验数据起始地址

0062207E    32C1            XOR AL,CL

00622080    46              INC ESI

00622081    8B0487          MOV EAX,DWORD PTR DS:[EDI+EAX*4];查校验码表

00622084    C1E9 08         SHR ECX,8                  

00622087    33C8            XOR ECX,EAX                

00622089    4A              DEC EDX

0062208A  ^ 0F85 EAFFFFFF   JNZ 0062207A              ;循环检验

00622090    8BC1            MOV EAX,ECX

00622092    F7D0            NOT EAX                         ;得到最终验证码

00622094    3985 ED090E0A   CMP DWORD PTR SS:[EBP+A0E09ED],EAX ;校验比较



006220B8    B9 9CE7F31D     MOV ECX,1DF3E79C

006220BD    BA C4498C24     MOV EDX,248C49C4

006220C2    AD              LODS DWORD PTR DS:[ESI]

006220C3    89B5 DD040E0A   MOV DWORD PTR SS:[EBP+A0E04DD],ESI

006220C9    C746 FC 0000000>MOV DWORD PTR DS:[ESI-4],0

006220D0    3D EEEEEEEE     CMP EAX,EEEEEEEE     

006220D5    0F85 20000000   JNZ 006220FB

006220DB    813E DDDDDDDD   CMP DWORD PTR DS:[ESI],DDDDDDDD; EEEEEEEEDDDDDDDD实际上应为表全部处理完毕标识

006220E1    0F85 14000000   JNZ 006220FB

006220E7    C706 00000000   MOV DWORD PTR DS:[ESI],0

006220ED    83C6 04         ADD ESI,4

006220F0    89B5 DD040E0A   MOV DWORD PTR SS:[EBP+A0E04DD],ESI

006220F6    E9 F9080000     JMP 006229F4         ;跳出处理循环,到此处后可在代码段下访问断点来到OEP

006220FB    8BD8            MOV EBX,EAX

006220FD    3385 A9050E0A   XOR EAX,DWORD PTR SS:[EBP+A0E05A9]

00622103    C1C8 03         ROR EAX,3

00622106    2BC2            SUB EAX,EDX

00622108    C1C0 10         ROL EAX,10

0062210B    33C1            XOR EAX,ECX

0062210D    899D A9050E0A   MOV DWORD PTR SS:[EBP+A0E05A9],EBX

00622113    3D 00000100     CMP EAX,10000     

00622118    0F83 45000000   JNB 00622163

0062211E    813E BBBBBBBB   CMP DWORD PTR DS:[ESI],BBBBBBBB

00622124    0F85 39000000   JNZ 00622163

0062212A    C706 00000000   MOV DWORD PTR DS:[ESI],0

00622130    83C6 04         ADD ESI,4

00622133    89B5 DD040E0A   MOV DWORD PTR SS:[EBP+A0E04DD],ESI

00622139    8B9D F1230E0A   MOV EBX,DWORD PTR SS:[EBP+A0E23F1]

0062213F    8B0B            MOV ECX,DWORD PTR DS:[EBX]

00622141    8BD0            MOV EDX,EAX

00622143    60              PUSHAD

00622144    8BC2            MOV EAX,EDX

00622146    2B85 310A0E0A   SUB EAX,DWORD PTR SS:[EBP+A0E0A31]

0062214C    C1E0 02         SHL EAX,2

0062214F    0385 A1050E0A   ADD EAX,DWORD PTR SS:[EBP+A0E05A1]

00622155    96              XCHG EAX,ESI

00622156    AD              LODS DWORD PTR DS:[ESI]

00622157    03C1            ADD EAX,ECX

00622159    894424 1C       MOV DWORD PTR SS:[ESP+1C],EAX

0062215D    61              POPAD

0062215E    E9 7C000000     JMP 006221DF

0062215E    E9 7C000000     JMP 006221DF

00622163    51              PUSH ECX

00622164    52              PUSH EDX

00622165    33C9            XOR ECX,ECX

00622167    8B95 2D0B0E0A   MOV EDX,DWORD PTR SS:[EBP+A0E0B2D];[esi]表中取得的第一个元素将和[EBP+A0E0B2D]数组的元素一一对比

                                    它是取得原始API的一个KEY

0062216D    3B02            CMP EAX,DWORD PTR DS:[EDX]

0062216F    0F84 38000000   JE sayhello.006221AD  ;找到后跳转到后续执行

00622175    83C2 04         ADD EDX,4

00622178    41              INC ECX          ;此时的ecx将是[EBP+A0E0B2D]表的数组下标

00622179    3B8D 59040E0A   CMP ECX,DWORD PTR SS:[EBP+A0E0459]

0062217F  ^ 0F85 E8FFFFFF   JNZ sayhello.0062216D

00622185    8DB5 2F3F1E0A   LEA ESI,DWORD PTR SS:[EBP+A1E3F2F]

0062218B    8DBD 2D010E0A   LEA EDI,DWORD PTR SS:[EBP+A0E012D]

00622191    AC              LODS BYTE PTR DS:[ESI]

00622192    84C0            TEST AL,AL

00622194    0F84 06000000   JE sayhello.006221A0

0062219A    AA              STOS BYTE PTR ES:[EDI]

0062219B  ^ E9 F1FFFFFF     JMP sayhello.00622191

006221A0    B8 00000000     MOV EAX,0

006221A5    8D8D 734B0E0A   LEA ECX,DWORD PTR SS:[EBP+A0E4B73]

006221AB    FFE1            JMP ECX

006221AD    898D C9310E0A   MOV DWORD PTR SS:[EBP+A0E31C9],ECX

006221B3    5A              POP EDX

006221B4    59              POP ECX

006221B5    56              PUSH ESI

006221B6    8B9D F1230E0A   MOV EBX,DWORD PTR SS:[EBP+A0E23F1]

006221BC    8B0B            MOV ECX,DWORD PTR DS:[EBX]

006221BE    8B85 C9310E0A   MOV EAX,DWORD PTR SS:[EBP+A0E31C9]

006221C4    D1E0            SHL EAX,1

006221C6    0385 CD270E0A   ADD EAX,DWORD PTR SS:[EBP+A0E27CD]

006221CC    33F6            XOR ESI,ESI

006221CE    96              XCHG EAX,ESI

006221CF    66:AD           LODS WORD PTR DS:[ESI]

006221D1    C1E0 02         SHL EAX,2

006221D4    0385 A1050E0A   ADD EAX,DWORD PTR SS:[EBP+A0E05A1]

006221DA    96              XCHG EAX,ESI

006221DB    AD              LODS DWORD PTR DS:[ESI]

006221DC    03C1            ADD EAX,ECX              ;到这里eax出现了api地址,

此时我们明白第一个元素解析出API地址 

但是经过后面的实验,

这里有时候出现的只是API的字符串

006221DE    5E              POP ESI

006221DE    5E              POP ESI

006221DF    83BD E5030E0A 0>CMP DWORD PTR SS:[EBP+A0E03E5],1

006221E6    0F84 39000000   JE sayhello.00622225

006221EC    3B8D A1130E0A   CMP ECX,DWORD PTR SS:[EBP+A0E13A1]

006221F2    0F84 2D000000   JE sayhello.00622225

006221F8    3B8D 75200E0A   CMP ECX,DWORD PTR SS:[EBP+A0E2075]

006221FE    0F84 21000000   JE sayhello.00622225

00622204    3B8D C5080E0A   CMP ECX,DWORD PTR SS:[EBP+A0E08C5]

0062220A    0F84 15000000   JE sayhello.00622225

00622210    8D9D 8D541E0A   LEA EBX,DWORD PTR SS:[EBP+A1E548D]

00622216    FFD3            CALL EBX

00622218    8BF8            MOV EDI,EAX

0062221A    8985 B1250E0A   MOV DWORD PTR SS:[EBP+A0E25B1],EAX

00622220    E9 B4060000     JMP sayhello.006228D9

00622225    8D9D 8D541E0A   LEA EBX,DWORD PTR SS:[EBP+A1E548D]

0062222B    FFD3            CALL EBX               ;经过这个CALL后 ,eax确定为API地址

0062222D    83BD E5030E0A 0>CMP DWORD PTR SS:[EBP+A0E03E5],0 

找出之后还会比较是不是指定的几个API 

将API代码逻辑上复制到一个新地址,这里是28d0000 

0062277E    8D9D D7561E0A   LEA EBX,DWORD PTR SS:[EBP+A1E56D7]

00622784    FFD3            CALL EBX

00622786    8D9D BF591E0A   LEA EBX,DWORD PTR SS:[EBP+A1E59BF]

0062278C    FFD3            CALL EBX

0062278E    0F83 0C000000   JNB sayhello.006227A0

00622794    8385 A50F0E0A 0>ADD DWORD PTR SS:[EBP+A0E0FA5],5

0062279B  ^ E9 DEFFFFFF     JMP sayhello.0062277E

006227A0    8D9D E8591E0A   LEA EBX,DWORD PTR SS:[EBP+A1E59E8]

006227A6    FFD3            CALL EBX

006227A8    0F83 08000000   JNB sayhello.006227B6

006227AE    83C2 04         ADD EDX,4

006227B1    E9 32000000     JMP sayhello.006227E8

006227B6    8D9D 512F1C0A   LEA EBX,DWORD PTR SS:[EBP+A1C2F51]

006227BC    FFD3            CALL EBX

006227BE    0F83 0B000000   JNB sayhello.006227CF

006227C4    8BB5 A50F0E0A   MOV ESI,DWORD PTR SS:[EBP+A0E0FA5]

006227CA    E9 80070000     JMP sayhello.00622F4F

006227CF    8B8D A50F0E0A   MOV ECX,DWORD PTR SS:[EBP+A0E0FA5]

006227D5    89B5 A50F0E0A   MOV DWORD PTR SS:[EBP+A0E0FA5],ESI

006227DB    2BCE            SUB ECX,ESI

006227DD    F7D9            NEG ECX        ;计算出当前API函数的当前指令字节数

006227DF    2BF1            SUB ESI,ECX

006227E1    F3:A4           REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[>

                                              将API原实现代码复制到一个新地址,这里是28c0000

006227E3  ^ E9 96FFFFFF     JMP sayhello.0062277E

在28e00000将28D0000代码变形

0062280E    8B85 9D110E0A   MOV EAX,DWORD PTR SS:[EBP+A0E119D]

00622814    50              PUSH EAX

00622815    57              PUSH EDI

00622816    8B85 F5000E0A   MOV EAX,DWORD PTR SS:[EBP+A0E00F5]

0062281C    50              PUSH EAX

0062281D    8D8D E12C1D0A   LEA ECX,DWORD PTR SS:[EBP+A1D2CE1]

00622823    FFD1            CALL ECX         ;这个CALL为代码变形并将变形的代码写入新地址

00622825    8BD0            MOV EDX,EAX

006228BD    8D85 73311D0A   LEA EAX,DWORD PTR SS:[EBP+A1D3173]

006228C3    FFD0            CALL EAX

006228C5    018D 7D110E0A   ADD DWORD PTR SS:[EBP+A0E117D],ECX

006228CB    8BBD B1250E0A   MOV EDI,DWORD PTR SS:[EBP+A0E25B1]

006228D1    8BB5 9D110E0A   MOV ESI,DWORD PTR SS:[EBP+A0E119D]

006228D7    F3:A4           REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[>

代码复制到[edi],此时EDI即为处理后的”API”地址

006228D9    8BB5 DD040E0A   MOV ESI,DWORD PTR SS:[EBP+A0E04DD]       ; sayhello.0061A414


以上对API代码的变形其实对于脱壳并不太重要,我们只要知道TMD将从[esi]表成员中第一个元素将得到API就足够了
然后处理第二个元素:
第二个元素解密出IAT的地址,然后将变形后的API代码地址填充进去

006228DF    AD              LODS DWORD PTR DS:[ESI] ; 处理下一个元素

006228E0    C746 FC 0000000>MOV DWORD PTR DS:[ESI-4],0 ; 取得元素值后清0

006228E7    C1C0 05         ROL EAX,5

006228EA    05 9CE7F31D     ADD EAX,1DF3E79C

006228EF    0385 45180E0A   ADD EAX,DWORD PTR SS:[EBP+A0E1845] ;得到IAT的VA

006228F5    8B8D B1250E0A   MOV ECX,DWORD PTR SS:[EBP+A0E25B1]

006228FB    8908            MOV DWORD PTR DS:[EAX],ECX ; 将处理的API地址填进去


(图3)

 
这里我们可以看出,IAT的起始地址是405000
继续分析第三个元素:
很快可以发现第三个元素得到的是代码中需要填充的nop地址,我们姑且称之为CALLAPI

006228FD    AD              LODS DWORD PTR DS:[ESI] ;下一个元素

006228FE    C746 FC 0000000>MOV DWORD PTR DS:[ESI-4],0

00622905    89B5 DD040E0A   MOV DWORD PTR SS:[EBP+A0E04DD],ESI

0062290B    83F8 FF         CMP EAX,-1   ;比较否处理完毕

0062290E    0F85 20000000   JNZ sayhello.00622934

00622914    813E DDDDDDDD   CMP DWORD PTR DS:[ESI],DDDDDDDD

0062291A    0F85 14000000   JNZ sayhello.00622934

00622920    C706 00000000   MOV DWORD PTR DS:[ESI],0

00622926    83C6 04         ADD ESI,4

00622929    89B5 DD040E0A   MOV DWORD PTR SS:[EBP+A0E04DD],ESI

0062292F  ^ E9 E6F6FFFF     JMP sayhello.0062201A

00622934    C1C0 03         ROL EAX,3

00622937    0385 45180E0A   ADD EAX,DWORD PTR SS:[EBP+A0E1845] ;得到CALLAPI地址

0062293D    83BD 9D190E0A 0>CMP DWORD PTR SS:[EBP+A0E199D],1

00622944    0F84 9D000000   JE sayhello.006229E7

0062294A    813E AAAAAAAA   CMP DWORD PTR DS:[ESI],AAAAAAAA ;这里有个AAAAAAAA标识

00622950    0F85 12000000   JNZ sayhello.00622968

00622956    83C6 04         ADD ESI,4

00622959    C746 FC 0000000>MOV DWORD PTR DS:[ESI-4],0

00622960    97              XCHG EAX,EDI

00622961    B0 E9           MOV AL,0E9    ;AAAAAAAA将为AL赋值E9

00622963    E9 03000000     JMP sayhello.0062296B

00622968    97              XCHG EAX,EDI

00622969    B0 E8           MOV AL,0E8 ;不是将为AL赋值E8


这里比较AAAAAAAA需要说明一下,它实际上是TMD判断原来代码中的FF15(“CALL 地址”)和FF25(”JMP 地址”),我们在修复的时候也需要判断,至于判断的方法也不一定要从这里,知道了流程,脚本的方法是很多的。

00622993    803F 90         CMP BYTE PTR DS:[EDI],90

00622996    0F84 08000000   JE 006229A4

0062299C    83C7 05         ADD EDI,5

0062299F    E9 43000000     JMP 006229E7

006229A4    83F8 50         CMP EAX,50

006229A7    0F82 0A000000   JB 006229B7

006229AD    B0 90           MOV AL,90

006229AF    AA              STOS BYTE PTR ES:[EDI]

006229B0    58              POP EAX

006229B1    AA              STOS BYTE PTR ES:[EDI]

006229B2    E9 24000000     JMP 006229DB

006229B7    58              POP EAX

006229B8    AA              STOS BYTE PTR ES:[EDI]

006229B9    807F FF E9      CMP BYTE PTR DS:[EDI-1],0E9

。。。。

。。。。

006229E6    AB              STOS DWORD PTR ES:[EDI];填充CALLAPI

006229E7    AD              LODS DWORD PTR DS:[ESI]

006229E8    C746 FC 0000000>MOV DWORD PTR DS:[ESI-4],0

006229EF  ^ E9 11FFFFFF     JMP 00622905


上面这一段随机运算,看是否在第一个”NOP”开始填写
然后将刚才得到的变形API地址计算偏移后填充到此处
上面分析完了一个API的处理过程,其实主要还是在于TMD的这个[esi]表,由于我们的程序比较简单,可能有些情况是没有涉及到的,比如校验,比如导入多个模块,但是大体流程都是这样的,只要掌握了就算难一点的程序脱壳也是没有问题的。 
校验只是超过0x64个API后进行一次,脚本中已经做过处理,增加几个模块无非是[esi]表中增加一个XXXXXXXX之类的标识符来判断一个导入模块处理结束。
至于脱壳脚本,我并没有打算给出一个通用的,通用的已经有了。这里脚本并不通用,主要是回顾一下流程,TMD的流程都是这样,高版本也仅是略有差异,顺着这个思路分析高版本也是很快的(当然并不是说恢复VM,仅脱壳而言,它不过是将一些API的处理过程放在VM代码中,然而蛛丝马迹总是能找到的),我们的脚本思路是后发制人,就是等TMD填充好之后我们重新填充回去。下面整理分析过程中得到的几个断点
HW 00401000   
ESTO
ESTO        ;代码段解码初步完毕,实际上可以不需要
0062201A ;解码表代码初始位置
0062222d ;此时eax为解码的API地址
006228fd;此时eax为IAT地址
0062294a; 这里得到的是代码中的CALLAPI
006228fd; 这个时候代码填入变形API地址,我们再改回来
006229e8;CALLAPI填充完毕
注意我的断点都是比实际得到的稍微后几步,这个看个人爱好。
下面是脚本:
-----------------------------------------------------------------------------------------

var iatadd

var apiadd

var calladd

bc

BPHWC

BPHWS 00401000,"w"

ESTO

ESTO

BPHWC 00401000

BPHWS 0062201A,"x" ;解码表代码初始位置

ESTO

BPHWC 0062201A

bp 006229f4

BPHWS 0062222d,"x"  ;eax为API地址

BPHWS 006228fd,"x"   ;eax为IAT地址,并且已填入变形API地址

BPHWS 0062294a,"x" ;这里得到的是代码中的CALLAPI

ESTO

mov [00602050],#EB6690909090# ;这里达到条件跳转到校验代码,改成jmp略过

apilb:

cmp eip,0062222d  ;看是否断在取API地址处

jne iatlb           ;不是则跳到IAT处理段

mov apiadd,eax     ;保存API地址

esto

iatlb:

cmp eip,006228fd ;看是否断在取IAT处

jne iatlb2

mov iatadd,eax     ;保存IAT地址

mov [iatadd],apiadd ;填入正确的API地址

esto

iatlb2:

cmp eip,0062222d     ;有些函数不需要在代码中填充,因此不会在0062294aCALLAPI处断下,直接返回继续下一个元素  

je apilb             

mov calladd,eax     ; 此时只能是断在0062294a处eax中的值为代码中需要填充callapi的地址

BPHWS 006229e8,"x" 

esto

find calladd,#E9#,2  ;看TMD填充的是否为E9,如果是我们需要改为FF25 JMP型

cmp $RESULT,0

jne fillff25

mov [calladd],#ff15# ;不为E9,则改成FF15型

mov [calladd+2],iatadd

jmp fillend

fillff25:

mov [calladd],#ff25#

mov [calladd+2],iatadd

fillend:

BPHWC 006229e8

esto

cmp eip,006229f4

je exit

jmp apilb

exit:

bc

bprm 00401000,4000  ; 跳到伪OEP

esto

ret


脚本运行完毕之后,来到(图4)

堆栈如(图5)

可以看出这是一段VC的头部(VC头部代码如下):

text:004183D7

.text:004183D7 55                      push    ebp

.text:004183D8 8B EC                   mov     ebp, esp

.text:004183DA 6A FF                   push    0FFFFFFFFh

.text:004183DC 68 18 CB 41 00          push    offset unk_41CB18 ;需要修改

.text:004183E1 68 2C 9D 41 00        push    offset unknown_libname_2 ;需要修改

.text:004183E6 64 A1 00 00 00 00       mov     eax, large fs:0

.text:004183EC 50                      push    eax

.text:004183ED 64 89 25 00 00 00 00    mov     large fs:0, esp

.text:004183F4 83 EC 58                sub     esp, 58h       ;需要修改

.text:004183F7 53                      push    ebx

.text:004183F8 56                      push    esi

.text:004183F9 57                      push    edi

.text:004183FA 89 65 E8                mov     [ebp+var_18], esp

.text:004183FD FF 15 74 B1 41 00       call    ds:GetVersion

.text:00418403 33 D2                   xor     edx, edx

.text:00418405 8A D4                   mov     dl, ah       ;以上为缺失的代码

.text:00418407 89 15 DC 22 42 00       mov     dword_4222DC, edx

.text:0041840D 8B C8                   mov     ecx, eax

.text:0041840F 81 E1 FF 00 00 00       and     ecx, 0FFh


以上三处需要修改的值可以再堆栈中找到:
$ ==>    > 028B002A
$+4      > 00622C78  sayhello.00622C78
$+8      > 00622786  sayhello.00622786
$+C      > 00622C78  sayhello.00622C78
$+10     > 00000000
$+14     > 0012FF40                              ;sub esp,14
$+18     > 00622786  sayhello.00622786
$+1C     > 0012FF9C  指向下一个 SEH 记录的指针
$+20     > 004020AC  SE 处理器                 ;第二个push值
$+24     > 004050B0  sayhello.004050B0           ;第一个push值
然后把修改后的代码贴到0040147e前面,dump之后去掉壳段用import REC修复一下就可以了。

上传的附件 sayhello.rar
image001.png
image002.png
image003.png
image004.png
image005.png

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功