抹除花指令

系统 : Windows xp

程序 : 2015_nctf_re

程序下载地址 :http://pan.baidu.com/s/1hryN1Wg

要求 : 拆解Nag窗口 & 找出密钥

使用工具 :OD & IDA & PEID & Hex Workshop & CodeBlocks

可在看雪论坛中找到关于此程序的讨论:http://bbs.pediy.com/showthread.php?t=199609&highlight=%E8%8A%B1%E6%8C%87+%E6%8C%87%E4%BB%A4+%E4%BB%A4

 

花指令是一些专门用来迷惑反汇编软件的代码数据,而对于cpu来说,依旧还是会执行正确的代码。通过插入无效数据,干扰反汇编软件对PE文件的分析,导致其显示出很多无用的信息。

今天,我们逆向一个小程序,来加深对花指令的了解。

 

打开PEID拖入该程序,发现无壳。

双击运行2015_nctf_re,将会显示一个窗口:

抹除花指令_第1张图片

单击关闭,发现又弹出一个相同的对话框,关闭N次无效后,只好打开任务管理器结束该进程。

OD载入该程序,对MessageBoxA下断,F9运行后中断,接着回到程序领空:

00405B59  |.  FF75 14       push    dword ptr [ebp+14]               ; /Style
00405B5C  |.  FF75 10       push    dword ptr [ebp+10]               ; |Title
00405B5F  |.  FF75 0C       push    dword ptr [ebp+C]                ; |Text
00405B62  |.  FF75 08       push    dword ptr [ebp+8]                ; |hOwner
00405B65  |.  FF15 34344300 call    dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA
00405B6B  |.  8945 E4       mov dword ptr [ebp-1C], eax 00405B6E  |.  C745 FC FEFFF>mov     dword ptr [ebp-4], -2
00405B75  |.  E8 0B000000   call    00405B85
00405B7A  |.  8B45 E4       mov eax, dword ptr [ebp-1C] 00405B7D  |>  E8 5FB40100   call    00420FE1
00405B82  \.  C3            retn

一直跟踪下去,会发现代码又回到了405B59,据此分析,有一个循环在不停地显示该窗口:

004012FB   > \BE 00010000   mov     esi, 100
00401300   >  6A 00         push    0
00401302   .  6A 00         push    0
00401304   .  68 70894300   push    00438970
00401309   .  E8 F84A0000   call    00405E06
0040130E   .  83EE 01       sub     esi, 1
00401311   .^ 75 ED         jnz     short 00401300                   ; 判断语句
00401313   .  5F            pop edi 00401314   .  8D46 01       lea     eax, dword ptr [esi+1] 00401317   .  5E            pop esi 00401318   .  C3            retn

将401311处的跳转指令改为jz并保存。

打开Hex Workshop载入保存之后的程序,搜索ansi string“小兄弟,搞基吗?”,将其替换为“小兄弟,我是傻哔”。

重新打开效果如下:

抹除花指令_第2张图片

 

========================小剧场模式启动=======================》

“喂,110吗?”

“是的,你有什么事?”

“我要举报!有一个傻[哔]出现在我附近!”

“嗯?可傻[哔]不触犯法律啊。”

抹除花指令_第3张图片

“对了,你是怎么知道他是傻[哔]的?”

“嗨,也没什么,就是破解人家软件的时候发现的。”

。。。。。。。

“小朋友,下午来局子里喝杯茶吧~”

抹除花指令_第4张图片

========================小剧场模式关闭=======================》

用OD载入修改过的程序,对GetDlgItemTextA下断,运行后中断,接着返回程序领空:

0040B45F  |.  FF75 10       push    dword ptr [ebp+10]               ; /Count
0040B462  |.  FF75 0C       push    dword ptr [ebp+C]                ; |Buffer
0040B465  |.  FF75 08       push    dword ptr [ebp+8]                ; |ControlID
0040B468  |.  FF71 20       push    dword ptr [ecx+20]               ; |hWnd
0040B46B  |.  FF15 68334300 call    dword ptr [<&USER32.GetDlgItemTe>; \GetDlgItemTextA
0040B471  |.  5D            pop     ebp                              ; 0012F82C
0040B472  |.  C2 0C00       retn    0C

继续跟踪:

0040141F   .  A1 3C524400   mov     eax, dword ptr [44523C]          ; 取出输入字串
00401424   .  51            push    ecx                              ; USER32.77D321CC
00401425   .  52            push edx 00401426   .  53            push ebx 00401427   .  E8 00000000   call    0040142C
0040142C  /$  5A            pop edx 0040142D  |.  83C2 07       add     edx, 7
00401430  |.  52            push    edx                              ; 等价于 jmp edx
00401431  \.  C3            retn                                     ; 跳入1433,则1432没有被执行
00401432 C4 db C4 00401433      5B            db      5B                               ; CHAR '['
00401434      5A            db      5A                               ; CHAR 'Z'
00401435      59            db      59                               ; CHAR 'Y'
00401436      51            db      51                               ; CHAR 'Q'
00401437      52            db      52                               ; CHAR 'R'
00401438      53            db      53                               ; CHAR 'S'
00401439      33            db      33                               ;
0040143A DB db DB 0040143B      74            db      74                               ;
0040143C      01            db      01
0040143D E8 db E8 0040143E      5B            db      5B                               ; CHAR '['
0040143F      5A            db      5A                               ; CHAR 'Z'
00401440      59            db      59                               ; CHAR 'Y'
00401441      80            db      80                               ;
00401442      30            db      30                               ; CHAR '0'

发现程序后面出现了一大段无用数据,继续运行,发现程序跟入了无用数据中,但寄存器的值却在不停的变换,说明该处指令被混淆过。选择40141F-401431处指令,右键->去除花指令->Obsidium即可去除花指令:

0040141F      A1 3C524400   mov     eax, dword ptr [44523C]          ; 取出输入字串
00401424      51            push    ecx                              ; USER32.77D321CC
00401425      52            push edx 00401426      53            push ebx 00401427      E8 00000000   call    0040142C
0040142C      5A            pop edx 0040142D      83C2 07       add     edx, 7
00401430      52            push    edx                              ; 等价于 jmp edx
00401431      C3            retn                                     ; 跳入1433,则1432没有被执行
00401432      C45B 5A       les ebx, fword ptr [ebx+5A] 00401435      59            pop ecx 00401436      51            push ecx 00401437      52            push edx 00401438      53            push ebx 00401439      33DB          xor     ebx, ebx                         ; 清空ebx
0040143B      74 01         je      short 0040143E                   ; 跳入143E,143D没有被执行
0040143D      E8 5B5A5980   call    80996E9D
00401442      306E 51       xor     byte ptr [esi+51], ch 00401445      52            push edx 00401446      53            push ebx 00401447      33DB          xor     ebx, ebx                         ; 清空ebx
00401449      74 01         je      short 0040144C                   ; 跳入144C,144B没有被执行

可以看到接下来的指令依旧有些奇怪,地址143B跳入143E,而该条指令的地址却是143D,有一个字节没有被执行。确定其是垃圾数据,用nop填充之(“剩余的用nop填充”不要打钩):

0040143B     /74 01         je      short 0040143E                   ; 跳入143E,143D没有被执行
0040143D     |90            nop
0040143E     \5B            pop ebx 0040143F      5A            pop edx 00401440      59            pop ecx 00401441      8030 6E       xor     byte ptr [eax], 6E               ; 第一个字符与6E异或
00401444      51            push ecx 00401445      52            push edx 00401446      53            push    ebx

之后的花指令都用此法抹除:

0040141F      A1 3C524400   mov     eax, dword ptr [44523C]          ; 取出输入字串
00401424      51            push ecx 00401425      52            push edx 00401426      53            push ebx 00401427      E8 00000000   call    0040142C
0040142C      5A            pop edx 0040142D      83C2 07       add     edx, 7
00401430      52            push    edx                              ; 等价于 jmp edx
00401431      C3            retn                                     ; 跳入1433,则1432没有被执行
00401432      90            nop
00401433      5B            pop ebx 00401434      5A            pop edx 00401435      59            pop ecx 00401436      51            push ecx 00401437      52            push edx 00401438      53            push ebx 00401439      33DB          xor     ebx, ebx                         ; 清空ebx
0040143B      74 01         je      short 0040143E                   ; 跳入143E,143D没有被执行
0040143D      90            nop
0040143E      5B            pop ebx 0040143F      5A            pop edx 00401440      59            pop ecx 00401441      8030 6E       xor     byte ptr [eax], 6E               ; 第一个字符与6E异或
00401444      51            push ecx 00401445      52            push edx 00401446      53            push ebx 00401447      33DB          xor     ebx, ebx                         ; 清空ebx
00401449      74 01         je      short 0040144C                   ; 跳入144C,144B没有被执行
0040144B      90            nop
0040144C      5B            pop ebx 0040144D      5A            pop edx 0040144E      59            pop ecx 0040144F      8070 01 62    xor     byte ptr [eax+1], 62             ; 第二个字符与62异或
00401453      51            push ecx 00401454      52            push edx 00401455      53            push ebx 00401456      33DB          xor     ebx, ebx                         ; 清空ebx
00401458      74 01         je      short 0040145B                   ; 跳入145B,145A没有被执行
0040145A      90            nop
0040145B      5B            pop ebx 0040145C      5A            pop edx 0040145D      59            pop ecx 0040145E      8070 02 76    xor     byte ptr [eax+2], 76             ; 第三个字符与76异或
00401462      51            push ecx 00401463      52            push edx 00401464      53            push ebx 00401465      33DB          xor     ebx, ebx                         ; 清空ebx
00401467      74 01         je      short 0040146A                   ; 跳入146A,1469没有被执行
00401469      90            nop
0040146A      5B            pop ebx 0040146B      5A            pop edx 0040146C      59            pop ecx 0040146D      8070 03 65    xor     byte ptr [eax+3], 65             ; 第四个字符与65异或
00401471      51            push ecx 00401472      52            push edx 00401473      53            push ebx 00401474      33DB          xor     ebx, ebx                         ; 清空ebx
00401476      74 01         je      short 00401479                   ; 跳入1479,1478没有被执行
00401478      90            nop
00401479      5B            pop ebx 0040147A      5A            pop edx 0040147B      59            pop ecx 0040147C      8070 04 7F    xor     byte ptr [eax+4], 7F             ; 第五个字符与7F异或
00401480      51            push ecx 00401481      52            push edx 00401482      53            push ebx 00401483      33DB          xor     ebx, ebx                         ; 清空ebx
00401485      74 01         je      short 00401488                   ; 跳入1488,1487没有被执行
00401487      90            nop
00401488      5B            pop ebx 00401489      5A            pop edx 0040148A      59            pop ecx 0040148B      8070 05 49    xor     byte ptr [eax+5], 49             ; 第六个字符与49异或
    ;省略一部分指令

异或操作都完成后,来到判断算法:

0040156C      8B0D 3C524400 mov     ecx, dword ptr [44523C]          ; 取出异或后的输入字串
00401572      0FB611        movzx   edx, byte ptr [ecx]              ; 判断首字符
00401575      85D2          test    edx, edx                         ; 非0则跳转出错
00401577      75 4A         jnz     short 004015C3                   ; 则退出
00401579      C645 FF 00    mov     byte ptr [ebp-1], 0              ; 一开始计数器置零
0040157D      EB 08         jmp     short 00401587
0040157F      8A45 FF       mov     al, byte ptr [ebp-1] 00401582      04 01         add     al, 1
00401584      8845 FF       mov     byte ptr [ebp-1], al 00401587      0FB64D FF     movzx   ecx, byte ptr [ebp-1] 0040158B      83F9 14       cmp     ecx, 14                          ; 计数器为0x14?
0040158E      7D 33         jge     short 004015C3                   ; 是则直接结束
00401590      0FB655 FF     movzx   edx, byte ptr [ebp-1] 00401594      0FB645 FF     movzx   eax, byte ptr [ebp-1] 00401598      8B0D 3C524400 mov     ecx, dword ptr [44523C]          ; 异或后字符地址存入ecx
0040159E      0FB60401      movzx eax, byte ptr [ecx+eax] 004015A2      3BD0          cmp     edx, eax                         ; 迭代字串的第n个字符是否等于n?
004015A4      75 19         jnz     short 004015BF                   ; 否则直接结束比较
004015A6      0FB64D FF     movzx   ecx, byte ptr [ebp-1] 004015AA      83F9 13       cmp     ecx, 13                          ; 计数器为0x13?
004015AD      75 0E         jnz     short 004015BD                   ; 否则跳转 继续循环
004015AF      6A 00         push    0
004015B1      6A 00         push    0
004015B3      68 84894300   push    00438984
004015B8      E8 49480000   call    00405E06
004015BD      90            nop
004015BE      90            nop
004015BF      90            nop
004015C0      90            nop
004015C1    ^ EB BC         jmp     short 0040157F
004015C3      5B            pop ebx 004015C4      8BE5          mov esp, ebp 004015C6      5D            pop ebp 004015C7      C3            retn

该处将我们输入的字串和一串固定的密钥进行异或,结果字串值应为0,1,2,3,4。。。。

写一段C代码实现逆算法:

#include <iostream>

using namespace std; int main() { char ch = 0x7F; string str = "nbve"; str += ch; str +="I6KWyoex>QDy #n";                        //粘合用来异或的字串

    string::iterator iter = str.begin(); for ( int i = 0 ; iter != str.end() ; iter++,i++ ){ *iter ^= i; } cout << str << endl; return 0; }

结果为:

抹除花指令_第5张图片

复制黏贴至程序:

抹除花指令_第6张图片

你可能感兴趣的:(抹除花指令)