首页
社区
课程
招聘
[原创]NoobyProtect 1.0.0.1 最小保护 完全修复 手记
发表于: 2009-8-21 11:31 11194

[原创]NoobyProtect 1.0.0.1 最小保护 完全修复 手记

2009-8-21 11:31
11194
NoobyProtect 1.0.0.1 最小保护 完全修复 手记

第一句:膜拜Nooby,hc版主
第二句:感谢yangjt的热心解答测试,感谢sessiondiy的大力支持

天哪,这玩意太变态了。这个壳拖拖拉拉搞了近半年,终于完成了1个脱壳……汗……还是1001的最小保护……

不过不管怎么说终于修复成功了。第一次觉得notepad的界面如此亲切……:lol

进入正题,这个手记将会分5部分写出

1 NoobyProtect 1.0.0.1最小保护 加密技术概貌

2 脚本实现分析

3 脚本使用方法

4 脚本插件出现的BUG

5 展望未来的np
==========================================================================
1 NoobyProtect 1.0.0.1最小保护 IAT加密技术概貌

最小保护没有加密代码段。
但是处理IAT极为猥琐
比如说开头这段
正常的程序为
0100739D > $  6A 70         PUSH 70
0100739F   .  68 98180001   PUSH NOTEPAD.01001898
010073A4   .  E8 BF010000   CALL NOTEPAD.01007568
010073A9   .  33DB          XOR EBX,EBX
010073AB   .  53            PUSH EBX                                 ; /pModule => NULL
010073AC   .  8B3D CC100001 MOV EDI,DWORD PTR DS:[<&KERNEL32.GetModu>; |kernel32.GetModuleHandleA
010073B2   .  FFD7          CALL EDI                                 ; \GetModuleHandleA


而np程序为
0100739D    6A 70           PUSH 70
0100739F    68 98180001     PUSH NOTEPAD_.01001898
010073A4    E8 BF010000     CALL NOTEPAD_.01007568
010073A9    33DB            XOR EBX,EBX
010073AB    53              PUSH EBX
010073AC    E8 638D0400     CALL NOTEPAD_.01050114 //这句被和谐了
010073B1    2F              DAS
010073B2    FFD7            CALL EDI


可以看到,由于10073B2还是CALL EDI,说明np还把类似 mov e**,dword ptr[iat]一类的代码给抽走

再看一段正常的

01007411  POP ECX
01007412  OR DWORD PTR DS:[100AB9C],FFFFFFFF
01007419  OR DWORD PTR DS:[100ABA0],FFFFFFFF
01007420  CALL DWORD PTR DS:[<&msvcrt.__p__fmode>] ;  msvcrt.__p__fmode


被np后
01007411  POP ECX
01007412  OR DWORD PTR DS:[100AB9C],FFFFFFFF
01007419  OR DWORD PTR DS:[100ABA0],FFFFFFFF
01007420  CALL NOTEPAD_.0105042E


可见,call [iat]也被抽走了

而被抽走的是什么模样呢
0105042E   PUSHAD
0105042F   PUSHFD
01050430   CALL NOTEPAD_.01050435
01050435   MOV EBX,DWORD PTR SS:[ESP]
01050438   ADD EBX,23
0105043B   XOR EAX,EAX
0105043D   XCHG DWORD PTR DS:[EBX-4],EAX
01050440   CMP EAX,0
01050443   JE SHORT NOTEPAD_.0105044C
01050445   XOR BYTE PTR DS:[EBX],0D0
01050448   INC EBX
01050449   DEC EAX
0105044A   JNZ SHORT NOTEPAD_.01050445
0105044C   POP EAX
0105044D   POPFD
0105044E   POPAD
0105044F   JMP NOTEPAD_.01050458

像IMP之类的东西只能跳楼了,关于IAT的具体技术分析,
参见(建议参照两部分内容看2)

yangjt的“NoobyProtect SE Demo 1.6.1.0 IAT加密初探 ”
http://www.unpack.cn/viewthread.php?tid=39288&extra=page%3D3

我的“NPSE 1.0.0.1 API保护 一点点的研究”
http://www.unpack.cn/viewthread.php?tid=30985
==========================================================================
2 脚本实现分析

面对满屏的CALL ***,有什么好办法?很自然想到脚本

脚本大概做的工作是这几样

1 搜索所有的call,如果是加密的call,就继续,否则跳过

2 对call的handler解密,获取API的名称和DLL名称,并得到该DLL的本机地址

3 将本机地址写入新内存,将该CALL修复成原来代码

下面将具体分析……

脚本初始化
gmi eip,CODEBASE
mov findtemp,$RESULT
alloc 2000
add $RESULT,100            //做IAT用
mov newiat,$RESULT
mov nnewiat,newiat

进行搜索
startfind:
findop findtemp,#E8????????# //查找所有call

cmp $RESULT,0  //找不到就大功告成啦
je overfind

mov savelast,$RESULT //存一下找到的地址


mov temp,[$RESULT+1]
add temp,$RESULT
add temp,5
mov myeip,temp
mov temp,[temp]
cmp temp,e89c60  //对该CALL的头3字节判断,以达到判断是否为np加密的call
jnz next //不是去死



    mov b,myeip
    mov calleip,myeip
    findop b,#8033??#  //找到关键一句
    mov temp1,$RESULT
    add temp1,2  
    mov xorbyte,[temp1] //得到xor的常数
    mov ecx,xorbyte
    mov xorbyte,cl  //将xor的常数赋到xorbyte中


这里需要用到真实的例子讲解
我们不难发现,所有的call handler都是这样的
0105042E     60               PUSHAD
0105042F     9C               PUSHFD
01050430     E8 00000000      CALL NOTEPAD_.01050435
01050435     8B1C24           MOV EBX,DWORD PTR SS:[ESP]
01050438     83C3 23          ADD EBX,23
0105043B     33C0             XOR EAX,EAX
0105043D     8743 FC          XCHG DWORD PTR DS:[EBX-4],EAX
01050440     83F8 00          CMP EAX,0
01050443     74 07            JE SHORT NOTEPAD_.0105044C
01050445     8033 D0          XOR BYTE PTR DS:[EBX],0D0  //******
01050448     43               INC EBX
01050449     48               DEC EAX
0105044A   ^ 75 F9            JNZ SHORT NOTEPAD_.01050445
0105044C     58               POP EAX
0105044D     9D               POPFD
0105044E     61               POPAD
0105044F     E9 04000000      JMP NOTEPAD_.01050458

很显然,1050445是最关键一句,因为他直接解码了下面jmp以后的程序,我们findop b,#8033??#要找的就是这句话
而??显然就是xor的常数
    mov xorstart,b
    add xorstart,2a
    add xorstart,1b
    mov temp1,[xorstart+1]
    mov eax,[xorstart+8]

为什么xorstart=关键地址+2a+1b?
01050170     68 75133576      PUSH 76351375
01050175     810424 8EEDCF8A  ADD DWORD PTR SS:[ESP],8ACFED8E

运行
d 76351375+8acfed8e,
6B 65 72 6E 65 6C 33 32 2E 64 6C 6C              kernel32.dll
00 47 65 74 4D 6F 64 75 6C 65 48 61 6E 64 6C 65 41 00        GetModuleHandleA.

嘿嘿,想到了什么?
原来NPSE为了避免给API下断点(其实就算下了也不会断下,请见参考文章),每次运行API的时候都会检测原来的
API有没有断点,有了断点自然就让你happy一下,重新开始了
我们就从这里入手,拿到函数的地址
    
    add xorstart,1b        //解码
    mov temp1,[xorstart+1]
    mov eax,[xorstart+8]
    mov temp2,eax
    xor temp1,xorbyte
    xor temp2,xorbyte
    shl xorbyte,8
    xor temp1,xorbyte
    xor temp2,xorbyte
    shl xorbyte,8
    xor temp1,xorbyte
    xor temp2,xorbyte
    shl xorbyte,8
    xor temp1,xorbyte
    xor temp2,xorbyte
        
    add temp1,temp2
    mov shijidll,temp1

    find temp1,#2e646c6c# //因为函数名和dll名是连着的,所以搜索.dll
    add $RESULT,5         //+5就是函数名
    mov shijifunc,$RESULT



然后是
#inc "fixiat.txt"
我们来看看……
len [shijidll] //得到dll名长度
readstr [shijidll],$RESULT //读取dll名
mov sdll,$RESULT
len [shijifunc] //得到function长度
readstr [shijifunc],$RESULT//读取function名
mov sfunc,$RESULT
gpa sfunc,sdll //得到函数本机地址


mov realapi,$RESULT 
mov [newiat],realapi //写入新地址IAT

有了这个剩下的也不好办,因为还要判断被和谐的是哪种类型的

对比比较
这是抽掉mov edi,[iat]类型的
010501C5     83C4 04          ADD ESP,4
010501C8     61               POPAD
010501C9     64:8F05 00000000 POP DWORD PTR FS:[0]
010501D0     83C4 04          ADD ESP,4
010501D3     8B3D EF010501    MOV EDI,DWORD PTR DS:[10501EF]
010501D9     830424 01        ADD DWORD PTR SS:[ESP],1
010501DD     C3               RETN

这是抽掉call [iat]类型的
010504CC     D383 C4046164    ROL DWORD PTR DS:[EBX+646104C4],CL
010504D2     8F05 00000000    POP DWORD PTR DS:[0]
010504D8     83C4 04          ADD ESP,4
010504DB     FF6424 D4        JMP DWORD PTR SS:[ESP-2C]

比较发现什么?
把第二个call [iat]的程序弄得正常一点
010504CD     83C4 04          ADD ESP,4
010504D0     61               POPAD
010504D1     64:8F05 00000000 POP DWORD PTR FS:[0]
010504D8     83C4 04          ADD ESP,4
010504DB     FF6424 D4        JMP DWORD PTR SS:[ESP-2C]

当两次add esp,4后,call [iat]执行的是Jmp,因为函数已经结束,而mov e**,[iat]还
必须进行赋值,并且跳过一个字节
嘿嘿……那还犹豫什么?
不幸的是
某些特殊函数(目前估计是原来的jmp [iat])不是add esp,4
01050042     83C4 08          ADD ESP,8
01050045     FF6424 D0        JMP DWORD PTR SS:[ESP-30]

所以我们就只能搜索#83c4#了

看代码

find calleip,#83c4#
add $RESULT,3
find $RESULT,#83c4#
add $RESULT,3           //找两次add esp,?,再到下一行代码

mov ebx,[$RESULT]
cmp bl,ff               //首字节判断
jnz fixexx              //如果不是jmp dword [iat](call [iat]),就走
mov [savelast],#FF15#   //call [iat]的头两个字节是FF15,
mov temp,savelast
add temp,2
mov [temp],newiat       //填入IAT
jmp overiat
fixexx:

opcode $RESULT          //case 如果不是jmp
//此时的代码为MOV E??,DWORD PTR DS:[IAT]
mov temp,$RESULT_1
alloc 100
mov [$RESULT],temp      //到个临时空间里玩玩
add $RESULT,4
readstr [$RESULT],3     //读取E??
mov temp,savelast

scmp $RESULT,"EAX",3


到这里还都挺顺利的,为啥还要判断是不是EAX
呵呵,这又是一个脚本的BUG。
编译mov eax,dword ptr[401000]时,脚本会给你写成
0100739D >    8B05 00104000  MOV EAX,DWORD PTR DS:[401000]
而实际应该是
0100739D >    A1 00104000    MOV EAX,DWORD PTR DS:[401000]
可见脚本修改的多占了一个字节,那下面一句基本就完蛋了
所以针对是不是EAX的问题还要手修一下
scmp $RESULT,"EAX",3
jnz fixexx_1
 mov [savelast],a1  //eax填入
 inc savelast
 mov [savelast],newiat
jmp overiat
fixexx_1:
mov temp2,"mov "   //如果不是eax
add temp2,$RESULT
add temp2,",dword ptr["
itoa newiat
add temp2,$RESULT
add temp2,"]"      //以上字符串组合就是mov e**,[newiat]
asm savelast,temp2 //修复一下

终于到最后了……
opcode savelast
add savelast,$RESULT_2   //为查找下一个做准备
mov findtemp,savelast
jmp startfind

==========================================================================
3 脚本使用方法

1 到达OEP;)估计先运行后再DUMP,用插件找也行(感谢hc版主)
2 运行脚本,泡杯咖啡
3 用UIF修复
对于UIF的使用方法介绍一下(感谢yangjt)



4 DUMP,注意顺序!
5 用IMP修复,不用说了吧
6 用PE工具删掉TLS,优化OK

如果还出现问题,那又是脚本的BUG。比如修复这个记事本时


呵呵,你只有先改下脚本
//cmp $RESULT,10047a4(本例)
//jnz debug_1
//pause
改完了一直TAB,直到

readstr [shijidll],$RESULT
mov sdll,$RESULT
len [shijifunc]
readstr [shijifunc],$RESULT

知道API后记录,让他运行,结束后再到那个CALL里手工修复一下,再UIF……
==========================================================================
4 脚本插件出现的BUG

群里的朋友请原谅我那天的不冲动,当一个脚本运行10几分钟以后出现一个BUG让你前功尽弃,
就算神也要发火的…………

总之先膜拜插件作者,接着提出一些很不方便的BUG,顺便提供下临时的解决方案,以备下次使用

1 inc或dec几次后莫名其妙变成别的值
试下
mov temp,***
inc temp
mov ***,temp


2 有时候mov eax,temp会出现错误

先执行一句 mov temp,0
(尽管你原来的temp就是数值型的)

3 对eax不优化导致的问题

手填……

4 gpa出错

……暂无解决方法
==========================================================================
5 展望未来的np

其实np是个很ws的……
建议更加ws

1 取消对原api的0cch判断
2 加载DLL内存镜像后删除原DLL的输入表信息
3 ……无语……再WS就不是人了

膜拜nooby
==========================================================================
另外再次感谢yangjt

[课程]Linux pwn 探索篇!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (14)
雪    币: 740
活跃值: (952)
能力值: ( LV9,RANK:160 )
在线值:
发帖
回帖
粉丝
2
上传附件;)

脚本
脚本.rar

试炼品 NOTEPAD_npse.rar

出炉的(NAG没去,TLS清零就OK了) okokok.rar
上传的附件:
2009-8-21 11:34
0
雪    币: 609
活跃值: (237)
能力值: ( LV12,RANK:441 )
在线值:
发帖
回帖
粉丝
3
我是来膜拜Lz的
2009-8-21 11:34
0
雪    币: 740
活跃值: (952)
能力值: ( LV9,RANK:160 )
在线值:
发帖
回帖
粉丝
4
继续上传

npse101原程序 npse_public.rar
上传的附件:
2009-8-21 11:35
0
雪    币: 740
活跃值: (952)
能力值: ( LV9,RANK:160 )
在线值:
发帖
回帖
粉丝
5
……yangjt真是速度
2009-8-21 11:35
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
6
你们都太坏了
2009-8-21 12:00
0
雪    币: 1844
活跃值: (35)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
7
够朋友了吧,多次跟进XX
2009-8-21 12:45
0
雪    币: 740
活跃值: (952)
能力值: ( LV9,RANK:160 )
在线值:
发帖
回帖
粉丝
8
嘿嘿,谢谢LS,LSS AND。。。。。捧场
2009-8-21 13:05
0
雪    币: 716
活跃值: (162)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
9
很精彩,支持
2009-8-21 13:24
0
雪    币: 740
活跃值: (952)
能力值: ( LV9,RANK:160 )
在线值:
发帖
回帖
粉丝
10
谢谢捧场;)
2009-8-21 18:13
0
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
膜拜楼主跟Nooby
2009-9-11 11:50
0
雪    币: 333
活跃值: (46)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
12
好文章!!!
2010-3-12 19:01
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
UIF修复可能存在跨平台问题哦~~大家使用需要小心

谢谢 学习了
2010-5-1 23:12
0
雪    币: 239
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
膜拜Lz膜拜Lz
2010-5-10 15:47
0
雪    币: 239
活跃值: (42)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
脱壳真的很烦!难道是我太笨?
2011-1-12 11:46
0
游客
登录 | 注册 方可回帖
返回
//