吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 9070|回复: 13
收起左侧

[原创] NP1160DEMO全保护ShellCode-TLS部分完整逆向

[复制链接]
XuZhenG 发表于 2009-2-7 14:55
寒假要结束了。。。
可能未来一年半时间内我在论坛上将不会发表主题了。
毕竟高考还是(***)的制度。
逆向再搞也不能在高考中取得加分。

Special thanks to fly , 海风 , Nooby , hmily , a__p 哥,多了我就不列举了,
反正感谢所有曾经帮助过我的人们。


最后,

再见,珍重……


首先声明,最新的NoobyProtect版本太萎缩运行太慢不好玩。。。
我直接从HDD里面拉出来一个历史的1160版本DEMO加了个全保护试炼搞一下。。。

感谢Nooby同学提供给我们这么好的学习机会


TLS部分代码完整跟踪:

开始又是代码解密

01075F83    9C              pushfd
01075F84    53              push    ebx
01075F85    51              push    ecx
01075F86    E8 00000000     call    calc_nps.01075F8B
01075F8B    8B1C24          mov     ebx, dword ptr ss:[esp]
01075F8E    83C3 25         add     ebx, 25
01075F91    33C9            
xor     ecx, ecx
01075F93    874B FC         xchg    dword ptr ds:[ebx-4], ecx
01075F96    83F9 00         cmp     ecx, 0
01075F99    74 06           
je      short calc_nps.01075FA1
01075F9B    8033 60         xor     byte ptr ds:[ebx], 60            
; 异或解密代码
01075F9E    43              inc     ebx
01075F9F  ^ E2 FA           loopd   short calc_nps.01075F9B
01075FA1    83C4 04         add     esp, 4
01075FA4    59              
pop     ecx
01075FA5    5B              pop     ebx
01075FA6    9D              popfd
01075FA7    E9 04000000     jmp     calc_nps.01075FB0
01075FAC    0000            add     byte ptr ds:[eax], al
01075FAE    0000            add     byte ptr ds:[eax], al
01075FB0    837C24 08 01    cmp     dword ptr ss:[esp+8], 1
01075FB5    0F85 1C010000   
jnz     calc_nps.010760D7
01075FBB    68 20F6D17E     push    7ED1F620                        
; 此处。。。
01075FC0    810424 EB683582 add     dword ptr ss:[esp], 823568EB
01075FC7    64
:FF35 0000000>push    dword ptr fs:[0]                 
; 安装结构化异常处理
01075FCE    64:8925 0000000>mov     dword ptr fs:[0], esp
01075FD5    60              pushad
01075FD6    CC              int3                                    
; int3触发异常


然后呢

0006F9A8   0006FA08  Pointer to next SEH record
0006F9AC   01075F0B  SE handler


很简单,拉到0x1075F0B处,设置int3断点(请注意是int3断点,千万不要用HE断点,看下面就知道)

拦下来
01075F0B    9C              pushfd                                           ; 这个就是异常处理了
01075F0C    53              push    ebx
01075F0D    51              push    ecx
01075F0E    E8 00000000     call    calc_nps.01075F13
01075F13    8B1C24          mov     ebx, dword ptr ss:[esp]
01075F16    83C3 25         add     ebx, 25
01075F19    33C9            
xor     ecx, ecx
01075F1B    874B FC         xchg    dword ptr ds:[ebx-4], ecx
01075F1E    83F9 00         cmp     ecx, 0
01075F21    74 06           
je      short calc_nps.01075F29
01075F23    8033 50         xor     byte ptr ds:[ebx], 50                    
; 又是代码解密,但这次是0x50
01075F26    43              inc     ebx
01075F27  ^ E2 FA           loopd   short calc_nps.01075F23
01075F29    83C4 04         add     esp, 4
01075F2C    59              
pop     ecx
01075F2D    5B              pop     ebx
01075F2E    9D              popfd
01075F2F    E9 04000000     jmp     calc_nps.01075F38
01075F34    0000            add     byte ptr ds:[eax], al
01075F36    0000            add     byte ptr ds:[eax], al
01075F38    60              pushad
01075F39    8B4424 24       mov     eax, dword ptr ss:[esp+24]               
; mov eax,pExceptionRecord
01075F3D    8B4C24 2C       mov     ecx, dword ptr ss:[esp+2C]               ; mov ecx,pContext
01075F41    8B30            mov     esi, dword ptr ds:[eax]                  ; mov esi,ExceptionCode
01075F43    0371 18         add     esi, dword ptr ds:[ecx+18]               ; /检测硬件断点捕获情况
01075F46    0371 14         add     esi, dword ptr ds:[ecx+14]
01075F49    81EE 03000080   sub     esi, 80000003
01075F4F    70 2B           
jo      short calc_nps.01075F7C                  
; 如果有硬件断点这里就跳了,NOP掉★
01075F51    8B99 C1000000   mov     ebx, dword ptr ds:[ecx+C1]               ; /检测是否为单步方式
01075F57    83E3 01         and     ebx, 1
01075F5A    3BF3            
cmp     esi, ebx
01075F5C    77 1E           ja      short calc_nps.01075F7C                  
; 如果TF位为1,这里就跳了, NOP掉★
01075F5E    8381 B8000000 0>add     dword ptr ds:[ecx+B8], 4                 ; Exception_Context中eip+=4 希望之后的异常后到这里执行
01075F65    8B81 B8000000   mov     eax, dword ptr ds:[ecx+B8]               ; 在这里放一个int3断点就能知道返回后所停的位置了★
01075F6B    8038 CC         cmp     byte ptr ds:[eax], 0CC                   ; 检测下次异常所停的地方是否有int3断点
01075F6E  ^ 0F84 96FFFFFF   je      calc_nps.01075F0A                        ; 如果有,则跳到非正常代码区,程序会出错退出,NOP掉★
01075F74    61              popad
01075F75    B8 00000000     mov     eax, 0                                   
; 如果没检测到调试器,eax=0
01075F7A    EB 06           jmp     short calc_nps.01075F82
01075F7C    61              popad
01075F7D    B8 FFFFFFFF     mov     eax, -1                                 
; 如果检测到调试器,eax=-1 (32-bit:0xFFFFFFFF)
01075F82    C3              retn                                             ; 返回到系统执行区


★ NOP掉 上述三处 跳转之后就可以放心大胆的用int3断点和HE断点了,
不过建议使用 int3 断点 和 F9
shift + F9 有时候会把OD的 int3断点交到程序的异常处理过程中去

然后剩下来的代码就会像花指令一样,没隔几个就会出现int3,用上面的这个过程检测调试器,Nop掉以上三处之后
在指定位置放一个int3断点,这样每次都能知道下次代码所停的位置。。。

然后我们就需要超常的耐心和毅力,因为NP的特点就是萎缩


有效代码抠出来分析:

01075FDA    8B4424 2C       mov     eax, dword ptr ss:[esp+2C]               ; eax = ImageBaseAddress;
01075FE2    8B0C24          mov     ecx, dword ptr ss:[esp]                  ; ecx = ImageBaseAddress;
01075FE5    2BC1            sub     eax, ecx                                 ; eax -= ecx;
01075FEB    05 52010200     add     eax, 20152                               ; eax += 0x20152;
01075FF0    BB 1B300000     mov     ebx, 301B                                ; ebx = 0x301B;
01075FF9    FE0408          inc     byte ptr ds:[eax+ecx]                    ; / (BYTE *)(eax+ecx) += 1;
01075FFC    40              inc     eax                                      ; eax += 1;
01076001    4B              dec     ebx                                      ; ebx-=1
01076002  ^ 75 F5           jnz     short calc_nps.01075FF9                  ; \循环


以上那个循环的作用是从RVA = 20152的程序内存开始,Size = 301B处每个字节+1

Nooby老师精彩点评:
这个是用来干掉输入表的,因为TLS执行的时候已经不需要了.加壳后程序无IAT,所以TLS里干掉,反dump.



下面
01076008    B8 A02B3554     mov     eax, 54352BA0                            ; eax = 0x54352BA0;
01076011    80B8 6329D2AC E>cmp     byte ptr ds:[eax+ACD22963], 0E9          ; 判断0x1075503处是否为jmp far (0xE9)
01076018  ^ 0F85 96FFFFFF   jnz     calc_nps.01075FB4                        ; 这里 Nooby 老师说不能跳,★
0107601E    81B0 8029D2AC C>xor     dword ptr ds:[eax+ACD22980], 2CFE1EC0    ; 异或
01076028    B8 02000000     mov     eax, 2                                   ; eax=2;



★ 此处不能跳,
如果单步跟踪,会发现cmp x1,x2 实际上是相等的,但是jnz会跳。
如果在后面的代码(不跳才会执行)下int3断点,再F9就会过去,没有问题,
至于为什么还没有搞明白,Nooby老师来讲解一下

Nooby老师精彩点评:
这个查的是EP的CC,OD把你忽悠了


下面有一个cpuid指令,关于这个指令的详细内容可以在这里查询
http://www.sandpile.org/ia32/cpuid.htm
但是cpuid及后面那个循环作用不明(可能是垃圾指令)

Nooby老师精彩点评:
demo版限制,仅限本机,否则无法解密壳数据.

01076031    0FA2            cpuid                                            ; | __in eax = 2h;
01076033    8ACA            mov     cl, dl                                   ; 我这里 dl = 0x78('x'),cl = 0
01076039    02CC            add     cl, ah                                   ; 我这里 ah = 0xB1 + cl = 0x29 (溢出)
0107603B    8B4424 2C       mov     eax, dword ptr ss:[esp+2C]               ; eax = ImageBaseAddress;
0107603F    8B1424          mov     edx, dword ptr ss:[esp]                  ; edx = ImageBaseAddress;
01076042    2BC2            sub     eax, edx                                 ; eax -= edx;
01076048    05 00400200     add     eax, 24000                               ; eax += 0x24000;
0107604D    BB 3D000000     mov     ebx, 3D                                  ; ebx = 0x3D;
01076056    300C10          xor     byte ptr ds:[eax+edx], cl                ; /又开始异或解密了? cl == 0x29
01076059    40              inc     eax
0107605A    4B              dec     ebx
0107605B  ^ 75 F9           jnz     short calc_nps.01076056                  
; \循环 ebx 作计数器 ebx == 0x3D
0107605D    8B4424 2C       mov     eax, dword ptr ss:[esp+2C]               ; eax = ImageBaseAddress;
01076061    05 51400200     add     eax, 24051                               ; eax += 0x24051;
0107606A    8BF4            mov     esi, esp                                 ; esi = esp;
0107606C    33DB            xor     ebx, ebx                                 ; ebx = 0;
0107606E    66:53           push    bx                                       ; push 0
01076070    44              inc     esp                                      ; esp += 1;
01076075    8A38            mov     bh, byte ptr ds:[eax]                    ; / bh = [eax]; // 0xD1
01076077    80FF 00         cmp     bh, 0
0107607A    74 08           
je      short calc_nps.01076084
0107607C    F6D7            not     bh                                       
; 用 not 来解密字串
0107607E    66:53           push    bx                                       ; push bh
01076080    44              inc     esp
01076081    40              inc     eax
01076082  ^ EB F1           jmp     short calc_nps.01076075                  
; \ 循环解密 ★
01076084    33DB            xor     ebx, ebx                                 ; ebx = 0;
0107608A    8BFC            mov     edi, esp                                 ; edi = (char *)"Protected by NoobyProtect"
0107608C    66:53           push    bx                                       ; push 0x0000
01076092    44              inc     esp
01076093    40              inc     eax
01076094    8A38            mov     bh, byte ptr ds:[eax]                    
; bh = byte [eax];
0107609A    80FF 00         cmp     bh, 0
0107609D    74 10           
je      short calc_nps.010760AF                  
; /又是一个循环
0107609F    F6D7            not     bh                                       ; not 解密
010760A5    66:53           push    bx                                       ; push bx
010760A7    44              inc     esp
010760A8    40              inc     eax
010760AD  ^\EB E5           jmp     short calc_nps.01076094                  
; \ 循环解密 ★
010760AF    8BD4            mov     edx, esp                                 ; edx = (char *)"NoobyProte媡"




上面有两个★环,密内容分
第一个

0006F960                                      00 50 72 6F              Pro
0006F970  74 65 63 74 65 64 20 62 79 20 4E 6F 6F 62 79 50  tected by NoobyP
0006F980  72 6F 74 65 63 74 2E                             rotect.

第二个

0006F960  4E 6F 6F 62 79 50 72 6F 74 65 8B 74              NoobyProte媡.   //
"媡" 是防伪标


010760B1    6A 40           push    40
010760B7    52              
push    edx                                      
; push (char *)"NoobyProte媡"
010760B8    57              push    edi                                      ; push (char *)"Protected by NoobyProtect"
010760B9    6A 00           push    0                                        ; push 0
010760BF    B8 F037B02A     mov     eax, 2AB037F0                            ; eax = 0x2AB037F0
010760C4    FF90 85F951D6   call    dword ptr ds:[eax+D651F985]              ; call user32.MessageBoxA


实际上调用 MessageBoxA
从SDK中可以找到
#define MB_ICONASTERISK             0x00000040L

所以,
上面的代码其实就是,
MessageBox(NULL,"Protected by NoobyProtect","NoobyProte媡",MB_ICONASTERISK);


传说中的 Nag... 就在这里了。。。


接下来。。。


010760CA    8BE6            mov     esp, esi                                 ; 恢复Stack
010760CC    61              popad                                            ; 恢复寄存器
010760CD    64:8F05 0000000>pop     dword ptr fs:[0]                         ; 恢复 SEH chain
010760D4    83C4 04         add     esp, 4
010760D7    33C0            
xor     eax, eax
010760D9    50              push    eax




在 push eax 之后,程序会触发int3异常,
由于SEH 已经被卸载,
所以系统会自动调用默认的异常处理程序处理异常。该异常将会被抛弃,并且TLS call back将会返回。
之后程序会被OD停在EP

至此,NP 1160 TLS callback 部分的代码戛然而止。



-------------------------------------告别-----------------------------------------
真的要远去了,再见……

calc_npse.rar

422.22 KB, 下载次数: 10, 下载积分: 吾爱币 -1 CB

免费评分

参与人数 1威望 +2 收起 理由
mycsy + 2 膜拜死了!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

zapline 发表于 2009-2-7 15:46
沙发
太佩服了
不知道还要学多久才能到这地步
creantan 发表于 2009-2-7 15:47
babaloveyou 发表于 2009-2-7 17:23
estelle 发表于 2009-2-7 19:32
太强了 精神我们学习
wgz001 发表于 2009-2-7 19:40
强大  膜拜加学习
有空的时候可以再来逛逛
祝学业有成  [s:371]
a2213572 发表于 2009-2-8 10:25
希望早日能再看到大大的教學!
419611868 发表于 2009-2-8 16:52
来看看了啊
老万 发表于 2009-3-4 19:18
太复杂了,继续努力学习。
paulbaby3000 发表于 2009-3-6 02:40
高考完再回来吧...
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 10:12

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表