[fishc]-调试篇21-变形&多态NAG修改

本文已发于鱼c论坛

0x00. 分析

入口

00401288 > $  6A 00         push    0
0040128A      E8            db      E8
0040128B      EF            db      EF
0040128C      FF            db      FF
0040128D      FF            db      FF
0040128E      FF            db      FF
0040128F      A3            db      A3
00401290      30314000      dd      ReverseM.00403130
00401294   .  BF 11104000   mov     edi, 00401011
00401299   .  E8 71000000   call    0040130F
0040129E   >  E8 6EFDFFFF   call    00401011

入口处指令需要去除分析,或者调试窗口-取消勾选自动对主模块进行分析。

00401288 >  6A 00           push    0
0040128A    E8 EFFFFFFF     call    <jmp.&KERNEL32.GetModuleHandleA>
0040128F    A3 30314000     mov     dword ptr [403130], eax
00401294    BF 11104000     mov     edi, 00401011
00401299    E8 71000000     call    0040130F
0040129E    E8 6EFDFFFF     call    00401011
004012A3    33C0            xor     eax, eax

第1次解密

进入call 0040130F调用。

0040130F    B8 00104000     mov     eax, 00401000
00401314    8030 5A         xor     byte ptr [eax], 5A
00401317    40              inc     eax
00401318    3D 18124000     cmp     eax, <jmp.&USER32.BeginPaint>
0040131D  ^ 7C F5           jl      short 00401314
0040131F    C3              retn

;信息面板
00401218=<jmp.&USER32.BeginPaint>
eax=00401002 (ReverseM.00401002)

这次调用是将0x00401000 ~ 0x00401218处的数据与0x5A异或。

第2次解密

进入call 00401011调用。

00401011    33C0            xor     eax, eax                         ; ReverseM.00401218
00401013    66:C707 6A00    mov     word ptr [edi], 6A
00401018    83C7 02         add     edi, 2
0040101B    C707 687D3040   mov     dword ptr [edi], 40307D68
00401021    83C7 04         add     edi, 4
00401024    C607 00         mov     byte ptr [edi], 0
00401027    47              inc     edi
00401028    C707 68343040   mov     dword ptr [edi], 40303468
0040102E    83C7 04         add     edi, 4
00401031    C607 00         mov     byte ptr [edi], 0
00401034    47              inc     edi
00401035    66:C707 6A00    mov     word ptr [edi], 6A
0040103A    83C7 02         add     edi, 2
0040103D    C707 E8300200   mov     dword ptr [edi], 230E8
00401043    83C7 04         add     edi, 4
00401046    C607 00         mov     byte ptr [edi], 0
00401049    47              inc     edi
0040104A    66:C707 EB44    mov     word ptr [edi], 44EB	; 0x15 bytes at all
0040104F    83EF 24         sub     edi, 24
00401052    FFD7            call    edi
00401054    E8 C7020000     call    00401320
00401059    E8 64020000     call    004012C2
0040105E    EB 15           jmp     short 00401075

在第一次解密之前的入口部分,就有mov edi, 00401011,所以,第二次调用是将0x00401011 ~ 0x0x00401025部分解密,与第一次异或不同,这一次是纯替换。 而且,这部分代码其实是自己本身。

下面是解密后内容指令。可以看到弹窗的标题和文本参数为乱码,这一部分后面应该还会解密。

00401011   $  6A 00         push    0                                ; /Style = MB_OK|MB_APPLMODAL
00401013   .  68 7D304000   push    0040307D                         ; |Title = 乱码
00401018   .  68 34304000   push    00403034                         ; |Text = 乱码
0040101D   .  6A 00         push    0                                ; |hOwner = NULL
0040101F   .  E8 30020000   call    <jmp.&USER32.MessageBoxA>        ; \MessageBoxA
00401024   . /EB 44         jmp     short 0040106A
00401026     |00            db      00
00401027   . |47            inc     edi
00401028   . |C707 68343040 mov     dword ptr [edi], 40303468
0040102E   . |83C7 04       add     edi, 4
00401031   . |C607 00       mov     byte ptr [edi], 0
00401034   . |47            inc     edi
00401035   . |66:C707 6A00  mov     word ptr [edi], 6A
0040103A   . |83C7 02       add     edi, 2
0040103D   . |C707 E8300200 mov     dword ptr [edi], 230E8
00401043   . |83C7 04       add     edi, 4
00401046   . |C607 00       mov     byte ptr [edi], 0
00401049   . |47            inc     edi
0040104A   . |66:C707 EB44  mov     word ptr [edi], 44EB
0040104F   . |83EF 24       sub     edi, 24
00401052   . |FFD7          call    edi
00401054   . |E8 C7020000   call    00401320
00401059   . |E8 64020000   call    004012C2
0040105E   . |EB 15         jmp     short 00401075

进入0x00401052处的call edi调用,是第一次解密得到的指令。此时edi减去0x24后为0x00401000

第3次解密

00401000   > /B8 00304000   mov     eax, 00403000
00401005   > |8030 B3       xor     byte ptr [eax], 0B3
00401008   . |40            inc     eax
00401009   . |3D 28314000   cmp     eax, 00403128
0040100E   .^|7C F5         jl      short 00401005
00401010   . |40            inc     eax
00401011   $  6A 00         push    0                                ; /Style = MB_OK|MB_APPLMODAL
00401013   .  68 7D304000   push    0040307D                         ; |Title = 乱码
00401018   .  68 34304000   push    00403034                         ; |Text = 乱码
0040101D   .  6A 00         push    0                                ; |hOwner = NULL
0040101F   .  E8 30020000   call    <jmp.&USER32.MessageBoxA>        ; \MessageBoxA
00401024   . |EB 44         jmp     short 0040106A

这一次是解密0x00403000 ~ 0x00403127的数据,而MessageBoxA()的标题和文本参数就在这一范围内。

这一过程可以在数据窗口中观察。

00403000  E1 D6 C5 D6 C1 C0 D6 FE D6 E7 C6 C7 DC C1 DA D2  嶂胖晾筑昼魄芰谝
00403010  DF B3 E1 D6 C5 D6 C1 C0 D6 FE D6 E7 C6 C7 DC C1  叱嶂胖晾筑昼魄芰
00403020  DA D2 DF 89 93 E1 D6 DE DC C5 D6 93 C7 DB D6 93  谝邏撫洲芘謸芹謸
00403030  DD D2 D4 B3 EA DC C6 93 DD D6 D6 D7 93 C7 DC 93  菀猿贶茡葜肿撉軗
00403040  C1 D6 DE DC C5 D6 93 C7 DB D6 93 DD D2 D4 BE B9  林捃胖撉壑撦以竟
00403050  E7 C1 CA 93 C7 DC 93 D7 DC 93 DA C7 93 DA DD 93  缌蕮擒撟軗谇撢輷

解密后:

00403000  52 65 76 65 72 73 65 4D 65 54 75 74 6F 72 69 61  ReverseMeTutoria
00403010  6C 00 52 65 76 65 72 73 65 4D 65 54 75 74 6F 72  l.ReverseMeTutor
00403020  69 61 6C 3A 20 52 65 6D 6F 76 65 20 74 68 65 20  ial: Remove the
00403030  6E 61 67 00 59 6F 75 20 6E 65 65 64 20 74 6F 20  nag.You need to
00403040  72 65 6D 6F 76 65 20 74 68 65 20 6E 61 67 0D 0A  remove the nag..
00403050  54 72 79 20 74 6F 20 64 6F 20 69 74 20 69 6E 20  Try to do it in

00401010   .  40            inc     eax                              ;  ReverseM.00403128
00401011   $  6A 00         push    0                                ; /Style = MB_OK|MB_APPLMODAL
00401013   .  68 7D304000   push    0040307D                         ; |Title = "TutorialNag"
00401018   .  68 34304000   push    00403034                         ; |Text = "You need to remove the nag",CR,LF,"Try to do it in a two byte patch. ",CR,LF,"Regards!"
0040101D   .  6A 00         push    0                                ; |hOwner = NULL
0040101F   .  E8 30020000   call    <jmp.&USER32.MessageBoxA>        ; \MessageBoxA
00401024   .  EB 44         jmp     short 0040106A

往下执行,就可以弹出第一个NAG窗口了。

第1次加密

0x00401024jmp short 0040106A后,edi值仍为0x00401000,指令如下:

0040106A   >  83C7 11       add     edi, 11
0040106D   .  66:C707 6A0A  mov     word ptr [edi], 0A6A
00401072   .  83C7 02       add     edi, 2
00401075   >  C707 FF353431 mov     dword ptr [edi], 313435FF
0040107B   .  83C7 04       add     edi, 4
0040107E   .  66:C707 4000  mov     word ptr [edi], 40
00401083   .  83C7 02       add     edi, 2
00401086   .  66:C707 6A00  mov     word ptr [edi], 6A
0040108B   .  83C7 02       add     edi, 2
0040108E   .  C707 FF353031 mov     dword ptr [edi], 313035FF
00401094   .  83C7 04       add     edi, 4
00401097   .  66:C707 4000  mov     word ptr [edi], 40
0040109C   .  83C7 02       add     edi, 2
0040109F   .  C707 E8900000 mov     dword ptr [edi], 90E8
004010A5   .  83C7 04       add     edi, 4
004010A8   .  C607 00       mov     byte ptr [edi], 0
004010AB   .  47            inc     edi
004010AC   .  66:C707 EB2C  mov     word ptr [edi], 2CEB	;0x17 bytes at all
004010B1   .  83EF 15       sub     edi, 15
004010B4   .  FFD7          call    edi

这一部分是将0x00401011 ~ 0x00401027的指令加密。

最后call edi时,减去0x15edi的值又变回0x00401011

00401011   $  6A 0A         push    0A
00401013   .  FF35 34314000 push    dword ptr [403134]
00401019   .  6A 00         push    0
0040101B   .  FF35 30314000 push    dword ptr [403130]               ;  ReverseM.00400000
00401021   .  E8 90000000   call    004010B6
00401026   .  EB 2C         jmp     short 00401054

执行后,弹出了第2个NAG窗口,然后跳到0x00401054

第2次加密

00401054   >  E8 C7020000   call    00401320
00401059   .  E8 64020000   call    004012C2
0040105E   .  EB 15         jmp     short 00401075

上面的指令是第1,2次解密得到的。

00401320  /$  B8 00304000   mov     eax, 00403000                    ;  ASCII "ReverseMeTutorial"
00401325  |>  8030 8D       /xor     byte ptr [eax], 8D
00401328  |.  40            |inc     eax
00401329  |.  3D 28314000   |cmp     eax, 00403128
0040132E  |.^ 7C F5         \jl      short 00401325
00401330  \.  C3            retn

加密0x00403000 ~ 0x00403127的数据,注意我们第2次解密的时候是与0xB3异或。

退出

上一次加密后返回,调用0x004012c2

004012C2  /$  50            push    eax                              ; /ExitCode = 403128
004012C3  \.  E8 B0FFFFFF   call    <jmp.&KERNEL32.ExitProcess>      ; \ExitProcess

整体流程

  1. 0040130F:解密0x00401000 ~ 0x00401218(XOR 0x5A)
  2. 00401011 :解密0x00401011 ~ 0x0x00401025
  3. 00401000:解密0x00403000 ~ 0x00403127(含窗口标题和文本)
  4. 0040106A:加密0x00401011 ~ 0x00401027
  5. 00401320:加密0x00403000 ~ 0x00403127

0x01. 打补丁

我们的目的是把第一个NAG去掉,即由第2次解密得到、第3次解密之后马上执行的0x0040101F处的call指令。

第1种方法

一个方法是使MessageBoxA()的第一个参数hOwner即父句柄无效:6A 00 | push 0x0改为6A 0A | push 0x1

这句参数入栈的指令是由第2次解密时的这一句得到的。

00401035    66:C707 6A00    mov     word ptr [edi], 6A

直接改为mov word ptr [edi], 0x016A是行不通滴,因为66:C707 6A00这一句指令又是由第一次解密时与0x5A异或得到哒 (- 。-)! 我们需要算一下与0x5A异或后得到0x01的字节。

0x01 ^ 0x5A == 0x5B,那么在运行前改把004010390x5A5B就行了。

00401034    1D 3C9D5D30     sbb     eax, 305D9D3C
00401039    5B              pop     ebx

保存后执行,成功地直接显示第二个NAG窗口。

第2种方法

在弹窗之前,直接执行下面的跳转。

00401011    6A 00           push    0
00401013   |68 7D304000     push    0040307D                         ; ASCII "TutorialNag"
00401018   |68 34304000     push    00403034                         ; ASCII "You need to remove the nag",CR,LF,"Try to do it in a two byte patch. ",CR,LF,"Regards!"
0040101D   |6A 00           push    0
0040101F   |E8 30020000     call    <jmp.&USER32.MessageBoxA>

修改后:00401011 EB 57 jmp short 0040106A

EB 57 XOR 5A == B1 0D ,所以回到找到第2次解密中对应的指令。

00401013    66:C707 6A00    mov     word ptr [edi], 6A
00401018    83C7 02         add     edi, 2

回到运行前的00401016

00401016    305A D9         xor     byte ptr [edx-27], bl

这里验证一下,30 5A XOR 5A == 6a 00,那么动手:

00000416    B1 0D           mov     cl, 0D

保存到执行文件,备份,成功去除第一个NAG。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值