首页
社区
课程
招聘
[原创]两种方法搞定ACProtect 1.09(Anti-Debug + Code Splicing + Stolen Code)
发表于: 2006-8-10 08:17 10650

[原创]两种方法搞定ACProtect 1.09(Anti-Debug + Code Splicing + Stolen Code)

2006-8-10 08:17
10650
【文章标题】: 两种方法搞定ACProtect 1.09(Anti-Debug + Code Splicing + Stolen Code)
【文章作者】: wynney
【软件名称】: Calories
【下载地址】: 打包下载
【保护方式】: Anti-Debug + Code Splicing + Stolen Code
【编写语言】: Borland Delphi 4.0 - 5.0
【操作平台】: XP SP2
【作者声明】: 凑热闹~^_^
--------------------------------------------------------------------------------
【详细过程】
  一、前言
  
  前几天在某国外论坛上看到某老外求助脱这个软件,遂下载下来瞧了瞧,蛮有点意思。很巧合,在看雪论坛上同样看到了某兄
  弟关于Anti-Debug求助,突然想起了这个软件。对于这个有点心得,于是,抽空就写这篇文章。这里说的两种方
  法,其实只是前面的反Anti-Debug + 找Stolen Code + 找伪OEP的方法不一样而已,后面修复IAT、处理Code Splicing的方法
  是一样的。所以我将把两种方法的反Anti-Debug + 找Stolen Code + 找伪OEP的过程分开来讲,修复IAT、处理Code Splicing
的方法放在最后一起讲

  
  
  二、方法一
      
  2.1、反Anti-Debug + 找Stolen Code + 找伪OEP
      
       使用看雪老大的HideOD插件,设置如下:
       1、选上:Process32Next,HideNtDebutBit,None
       2、忽略除了内存访问、指定异常外的所有异常(也就是说这2个不打勾)
  
       OD载入目标程序,HideOD插件点下HIDE,单步F8一下
  

00645000 C> 60 pushad ; EP,F8
00645001 85F5 test ebp,esi ; ESP=0012FFA4
00645003 46 inc esi
00645004 E8 01000000 call Calories.0064500A
00645009 - 73 83 jnb short Calories.00644F8E

  
  hr 0012FFA4
  Shit+F9,中断在最后一次内存访问异常
  
  

0064B08E CD 01 int 1 ; 中断在最后一次内存访问异常
0064B090 40 inc eax
0064B091 40 inc eax
0064B092 0BC0 or eax,eax
0064B094 0F85 B6000000 jnz Calories.0064B150

  
  注意看堆栈
  
  

0012FF58 /0012FFE0 指针到下一个 SEH 记录
0012FF5C |0064B072 SE 句柄 ;右键--转存中跟随,看转存窗口
0012FF60 |53C89D53

  
  

0064B072 0C245C8B ;右键--断点--内存访问,Shit+F9中断下来
0064B076 00B88383
0064B07A 33020000

  
  

0064B072 8B5C24 0C mov ebx,dword ptr ss:[esp+C] ; 中断在这,F2,继续Shit+F9
0064B076 8383 B8000000 02 add dword ptr ds:[ebx+B8],2
0064B07D 33C0 xor eax,eax
0064B07F C3 retn

  
  

0064B177 8B048E mov eax,dword ptr ds:[esi+ecx*4] ; 中断在这,F2,继续Shit+F9
0064B17A 8B5C8E 04 mov ebx,dword ptr ds:[esi+ecx*4+4]
0064B17E 2BC3 sub eax,ebx

  
  

0064B18B 89048E mov dword ptr ds:[esi+ecx*4],eax ; 中断在这,此时取消2个F2断点,1个内存访问断点,在retn处F4
0064B18E 49 dec ecx
0064B18F ^ EB E1 jmp short Calories.0064B172
0064B191 61 popad
0064B192 61 popad
0064B193 C3 retn ; 3个断点取消完毕后,F4

  
  中断在retn后,Ctrl+T-->命令是一个-->push ebp-->Ctrl+F11运行跟踪,由于我们开始下的hr esp的缘故会中断在Stolen Code处
  
  

0065FAF3 55 push ebp ; Stolen Code第一句
0065FAF4 8BEC mov ebp,esp ; Stolen Code第二句
0065FAF6 90 nop
0065FAF7 90 nop
0065FAF8 90 nop
0065FAF9 60 pushad
0065FAFA 60 pushad
0065FAFB E8 00000000 call Calories.0065FB00

55 8B EC

  
  删除硬件断点,Alt+M-->00401000段F2-->Shift+F9中断在伪OEP
  
  

00569498 42 inc edx ; OEP
00569499 44 inc esp
0056949A A6 cmps byte ptr ds:[esi],byte pt>
0056949B B9 04000000 mov ecx,4 ; 中断在这里,FOEP
005694A0 6A 00 push 0
005694A2 6A 00 push 0

  

  
  
  
  三、方法二
  
  3.1、反Anti-Debug + 找Stolen Code + 找伪OEP
      
       OD的隐藏插件设置随便(我设置的是全部勾选上),忽略所有的异常!OD载入目标程序
  
  

00645000 C> 60 pushad ; EP
00645001 85F5 test ebp,esi ; ESP=0012FFA4
00645003 46 inc esi
00645004 E8 01000000 call Calories.0064500A

  
  Ctrl+G-->CreateToolhelp32Snapshot-->找到段尾-->F2下断
  
  

7C864835 5E pop esi
7C864836 C9 leave
7C864837 C2 0800 retn 8 ; CreateToolhelp32Snapshot的段尾,F2

  
  F9运行,中断下来,注意看EAX=6C(在你那里可能不是这个值)-->右键归零(把EAX清0)
  再次F9,此时注意看EAX=68(在你那里可能不是这个值)-->再次右键归零(把EAX清0)
  此时EAX的值就是Anti-Debug的校验值,所以,清除为0,就可以防止Anti-Debug
  取消7C864837处的断点,F9运行,由于前面下hr ESP的缘故,中断在Stolen Code
  
  

0065FAF3 55 push ebp ; Stolen Code第一句
0065FAF4 8BEC mov ebp,esp ; Stolen Code第二句
0065FAF6 90 nop
0065FAF7 90 nop
0065FAF8 90 nop

55 8B EC

  
  硬件断点不要取消,继续F9,第2次硬件中断
  
  

0065FAFA 60 pushad ; 第2次硬件中断
0065FAFB E8 00000000 call Calories.0065FB00
0065FB00 5E pop esi

  
  硬件断点不要取消,继续F9,第3次硬件中断
  
  

0065FE8F 60 pushad ; 第3次硬件中断
0065FE90 E8 00000000 call Calories.0065FE95
0065FE95 5E pop esi
0065FE96 83EE 06 sub esi,6

  
  硬件断点不要取消,继续F9,第4次硬件中断
  
  

0065FECB /EB 01 jmp short Calories.0065FECE ; 第4次硬件中断
0065FECD -|E9 FF25D4FE jmp FF3A24D1
0065FED2 65:009B 94560000 add byte ptr gs:[ebx+5694],bl
0065FED9 0000 add byte ptr ds:[eax],al
0065FEDB 0000 add byte ptr ds:[eax],al
0065FEDD 0000 add byte ptr ds:[eax],al

  
  此时可以删除硬件断点,F8
  
  

0065FECE - FF25 D4FE6500 jmp dword ptr ds:[65FED4] ; F8到了这里,继续F8,即可来到FOEP
0065FED4 9B wait
0065FED5 94 xchg eax,esp
0065FED6 56 push esi
0065FED7 0000 add byte ptr ds:[eax],al
0065FED9 0000 add byte ptr ds:[eax],al
0065FEDB 0000 add byte ptr ds:[eax],al
0065FEDD 0000 add byte ptr ds:[eax],al
0065FEDF 0043 46 add byte ptr ds:[ebx+46],al

  
  

00569498 42 inc edx ; OEP
00569499 44 inc esp
0056949A A6 cmps byte ptr ds:[esi],byte pt>
0056949B B9 04000000 mov ecx,4 ; 来到这里,FOEP
005694A0 6A 00 push 0
005694A2 6A 00 push 0
005694A4 49 dec ecx

  

  
  四、还原Stolen Code + 试探性Dump + 修复IAT
  
  修补好Stolen Code之后
  

00569498 55 push ebp ; 修补好OEP,右键新建EIP
00569499 8BEC mov ebp,esp
0056949B B9 04000000 mov ecx,4
005694A0 6A 00 push 0

  
  试探性Dump:使用LoadPE纠正镜像,完整脱壳,打开ImportREC,OEP=00169498,获取输入表,有很多无效的,使用ACProtect插件修复
  最后有两个指针无效,根据经验判断全部还原成MessageBoxA,保存下树文件,FixDump!
  
  试运行程序发现无法运行。
  
  用另外一个OD载入脱壳修复的文件(我们到达OEP的OD还有用,不能关哦),细细查看,发现这里
  
  

005694D6 BA 9C985600 mov edx,Calories.0056989C
005694DB E8 E899EEFF call Calories.00452EC8 ;Enter
005694E0 8B0D 68F65600 mov ecx,dword ptr ds:[56F668] ; Calories.005707D8

  
  

00452EED 8BC3 mov eax,ebx
00452EEF E8 8CFFFFFF call Calories.00452E80
00452EF4 8B45 FC mov eax,dword ptr ss:[ebp-4]
00452EF7 8BD6 mov edx,esi
00452EF9 E8 EE13FBFF call Calories.004042EC ; Enter
00452EFE 75 06 jnz short Calories.00452F06

  
  

00404303 8B46 FC mov eax,dword ptr ds:[esi-4]
00404306 E8 AC222400 call Calories.006465B7 ; Enter
0040430B 77 02 ja short Calories.0040430F
0040430D 01C2 add edx,eax

  

  

......
......
006465B7 - FF25 BC721400 jmp dword ptr ds:[1472BC] ;来到这里
006465BD - FF25 C0721400 jmp dword ptr ds:[1472C0]
006465C3 - FF25 C4721400 jmp dword ptr ds:[1472C4]
006465C9 - FF25 C8721400 jmp dword ptr ds:[1472C8]
006465CF - FF25 CC721400 jmp dword ptr ds:[1472CC]
......
......
00646701 - FF25 98731400 jmp dword ptr ds:[147398]
00646707 - FF25 9C731400 jmp dword ptr ds:[14739C]
0064670D - FF25 A0731400 jmp dword ptr ds:[1473A0]
00646713 - FF25 A4731400 jmp dword ptr ds:[1473A4]
00646719 - FF25 A8731400 jmp dword ptr ds:[1473A8]
0064671F - FF25 AC731400 jmp dword ptr ds:[1473AC]
......
......

  
  呵呵,就是Code Splicing在作怪了。
  
  五、处理Code Splicing + Dump + Fix Dump
  
  这里使用Splicing Remover,在网上找到了一个Splicing Remover不完整的Delphi源码,幸好我学的就是Delphi,于是自己补充完整了!
  
  

00646701 - FF25 98731400 jmp dword ptr ds:[147398] ; 右键--转存中跟随--内存地址
00646707 - FF25 9C731400 jmp dword ptr ds:[14739C]
0064670D - FF25 A0731400 jmp dword ptr ds:[1473A0]
00646713 - FF25 A4731400 jmp dword ptr ds:[1473A4]
00646719 - FF25 A8731400 jmp dword ptr ds:[1473A8]
0064671F - FF25 AC731400 jmp dword ptr ds:[1473AC]
......
......


  发现Code Splicing所在区段为

  内存映射,项目 5
   地址=00140000
   大小=0000A000 (40960.)
   物主=         00140000 (自身)
   区段=
   类型=Priv 00021004
   访问=RW
   初始访问=RW
  
  打开Splicing Remover,按图示填写。Splicing Remover修复完毕之后,我们稍微找一个地方对比下(因为地方很多!)





  
  修复前:
  

00404303 8B46 FC mov eax,dword ptr ds:[esi-4]
00404306 E8 AC222400 call Calories.006465B7 ; Enter
0040430B 77 02 ja short Calories.0040430F
0040430D 01C2 add edx,eax

  
  修复后:
  

00404303 8B46 FC mov eax,dword ptr ds:[esi-4]
00404306 8B57 FC mov edx,dword ptr ds:[edi-4] ; Enter
00404309 29D0 sub eax,edx
0040430B 77 02 ja short Calories.0040430F
0040430D 01C2 add edx,eax

  
  像这样的地方还有很多很多,大家有兴趣可以仔细看看找找,好现在我们需要重新Dump了!
  使用LoadPE纠正镜像,完整脱壳,打开ImportREC,直接载入我们保存的树文件,Fix Dump!
  
  运行正常!~最后优化减肥下吧!
  
  六、Splicing Remover主要代码(Delphi的)

  

procedure TForm1.Button1Click(Sender: TObject);
var PID,PHD,Start,Size,SPStart,SPSize,Cnt,I,Go,GJMP:DWORD;
Buf:byte; JMP:WORD;
MBuf:array[0..4] of byte;
begin
Memo1.Clear;
if Edit3.Text='' then Exit;
PID:=HextoInt(Edit3.Text);
Start:=HextoInt(Edit1.Text);
Size:=HextoInt(Edit2.Text);
SPStart:=HextoInt(Edit4.Text);
SPSize:=HextoInt(Edit5.Text);
PHD:=OpenProcess(PROCESS_ALL_ACCESS,False,PID);
for I:=Start to Start+Size do begin
ReadProcessMemory(PHD,Pointer(I),@Buf,Sizeof(Buf),Cnt);
if (Buf=$E8) and (I+8<Start+Size) then begin
ReadProcessMemory(PHD,Pointer(I+1),@Go,Sizeof(Go),Cnt);
ReadProcessMemory(PHD,Pointer(I+Go+5),@JMP,Sizeof(JMP),Cnt);
if JMP=$25FF then begin
ReadProcessMemory(PHD,Pointer(I+Go+7),@GJMP,Sizeof(GJMP),Cnt);
if (GJMP>=SPStart) and (GJMP<SPStart+SPSize) then begin
ReadProcessMemory(PHD,Pointer(GJMP),@GJMP,Sizeof(GJMP),Cnt);
if (GJMP>=SPStart) and (GJMP<SPStart+SPSize) then begin
Memo1.Lines.Add(inttohex(I,8)+' <-- '+inttohex(GJMP,8));
ReadProcessMemory(PHD,Pointer(GJMP),@MBuf,Sizeof(MBuf),Cnt);
WriteProcessMemory(PHD,Pointer(I),@MBuf,Sizeof(MBuf),Cnt);
end;
end;
end;
end;
end;
ShowMessage('修复完毕^_^');
end;

  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2006年08月10日 7:52:30

原程序已经脱壳文件打包下载,由于是QQ硬盘提供的链接,时效可能不久

点击下载附件

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 7
支持
分享
最新回复 (8)
雪    币: 303
活跃值: (461)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
学习
2006-8-10 08:49
0
雪    币: 0
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
3
高!
2006-8-10 09:03
0
雪    币: 44229
活跃值: (19955)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
4
最初由 wynney 发布
原程序已经脱壳文件打包下载,由于是QQ硬盘提供的链接,时效可能不久


为了减小体积,仅将原程序打个包传上来保存
上传的附件:
2006-8-10 09:07
0
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
太强了,学习,致敬!!
2006-8-10 14:11
0
雪    币: 233
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
6
支持  
2006-8-10 14:46
0
雪    币: 451
活跃值: (78)
能力值: ( LV12,RANK:470 )
在线值:
发帖
回帖
粉丝
7
Splicing Remover
老大能否提供一份完整的原代码?
2006-8-11 19:33
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
好文章,学习!
2006-8-11 21:00
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
好文章,学习!
2006-8-13 13:14
0
游客
登录 | 注册 方可回帖
返回
//