ASProtect 2.3 SKE Build0319 Beta脱壳手记(无stolen OEP有stolen code)
【脱壳文件】自己写的一个加载DLL的DD(Delphi写的) M5n_ -Wcf
【加壳方式】ASProtect 2.3 SKE Build 03.19 Beta 除了Protect Original EntryPoint全部选项 LlpH;<
【作 者】h_f22 Qk Ms?o
【作者声明】水平很菜 请高手们多指教 #W!>~X%i_
【调试环境】WinXPSP2、OllyDBD110、LordPE、ImportREC :#x0ccOk
【脱壳过程】见下 s\}Pek-=z
PB`mhg*
一、前言 F0gfg9D1
}j Fo%
关于Aspr的文章论坛里面已经不少,各位大虾也都基本上把它研究透了。写此文的目的只在于自己学习 ,|U@S 7"b
和给跟我有相同问题的人一点提示。 9dB &!r9H
8x|RXqJuUf
Aspr变得越来越强,从没有stolen code到在OEP处偷一点,再到OEP处偷一堆,现在他终于在别处也开始偷了.等一下我们将看到在这个版本的Aspr中出现了一个的stolen code(不是stolen OEP),虽然他只偷了一个函数,也很容易找回来,但是这只是Beta版,正式版的时候又会是什么样呢?也许Aspr要变成超级猛壳了。 CS 51
-H,<zkQ:
加壳用的Aspr2.3时在工具区下载的。程序是自己用Delphi写的一个加载DLL的小工具。 `,50r\tl<%
nt7#1B-
二、加壳方式 !f @l@X
S"O*Ga
除了Protect Original EntryPoint(就是stolen OEP)以外的全部选项,虽然没选这个选项,Aspr却在别的地方偷了一点儿。 =i<E3K8"+
]t]7*<.*
三、过程 K! A2=
&(U nF}f
1、找到OEP和IAT E`%8dx%M|5
这个过程很简单。首先用OD加载目标程序,忽略除了INT3以外的全部异常,F9运行,停在第二个异常处,在内存映像中找到程序的代码段,下内存访问断点F2,运行,即停在OEP。 |THj.H=O
s xv/'D< &
aX+=M?6p
代码:-------------------------------------------------------------------------------- }as*=K
0045AF16 00 db 00 :G<s8Vi|
0045AF17 00 db 00 a b*,Al%*
0045AF18 14AD4500 dd Project1.0045AD14 y?o:VH]"
0045AF1C . 55 push ebp //OEP ; Project1.00400000 OwUME 4
0045AF1D . 8BEC mov ebp, esp 4!,pLek
0045AF1F . 83C4 F0 add esp, -10 ?i]@LqVI-
0045AF22 . B8 3CAD4500 mov eax, 0045AD3C }*<( "@l
0045AF27 . E8 E0B1FAFF call 0040610C T# ^(,l,
0045AF2C . A1 F4C04500 mov eax, [45C0F4] #0XVS$"Z2
0045AF31 . 8B00 mov eax, [eax] j(Vi?y2$
0045AF33 . E8 08E3FFFF call 00459240 \}1JQl? |
0045AF38 . 8B0D D8C14500 mov ecx, [45C1D8] ; Project1.0045DC04 'us,\(|_H
0045AF3E . A1 F4C04500 mov eax, [45C0F4] e Srx,
0045AF43 . 8B00 mov eax, [eax] s1G:.o|
0045AF45 . 8B15 B4A84500 mov edx, [45A8B4] ; Project1.0045A900 s2eD7=dn
-------------------------------------------------------------------------------- ~A&Oo7mnD
|=$iNH#.
aP{s=|z[ll
找到OEP=45AF1C,之后找IAT。由于这个程序是Delphi的,到代码段的前部就可以找到: @,VqT-PS2
YZ!S]68iYB
\dTqb%AN
代码:-------------------------------------------------------------------------------- Dm0FuN a
004011FD . 626A 65 bound ebp, [edx+65] BR;M5COjM
00401200 . 63748B C0 arpl [ebx+ecx*4-40], si =#+&r7=%k
00401204 $ E8 F7ED1501 call 01560000 //Advance Import protection的处理函数 =7R[UN{T"P
00401209 14 db 14 Ta1@|+*f)
0040120A 8BC0 mov eax, eax PGLi(D;XT
0040120C .- FF25 ACE14500 jmp [45E1AC] //45E1AC就是IAT的某个地址了 @M7G_OXG
00401212 . 8BC0 mov eax, eax [7 &_x+
00401214 .- FF25 A8E14500 jmp [45E1A8] ; ntdll.RtlUnwind -1:4d+;D
0040121A . 8BC0 mov eax, eax c3#Zj1BA'
0040121C $- FF25 A4E14500 jmp [45E1A4] ; kernel32.UnhandledExceptionFilter svc)%7J,<
00401222 . 8BC0 mov eax, eax 9Zjs(f] x
00401224 . E8 D7ED1501 call 01560000 x[st:e|k
00401229 . E4 8B in al, 8B iP=GM@i2#b
0040122B . C0FF 25 sar bh, 25 Q_f ! Z
0040122E ? C4E1 les esp, ecx ; 非法使用寄存器 aE} Qt\
00401230 ? 45 inc ebp /F+{,aB:n
00401231 ? 008B C0FF259C add [ebx+9C25FFC0], cl ~' *sf <Q
00401237 ? E1 45 loopde short 0040127E eZ6\(RZC*4
00401239 ? 008B C0E8BFED add [ebx+EDBFE8C0], cl Zn116uH
0040123F ? 15 012E8BC0 adc eax, C08B2E01 3IVd
-------------------------------------------------------------------------------- }Ix`$}Pf
a'4J]ri
:l$>@V@
沿着45E1AC处上下找一找就可以很容易的找到IAT了,从0045E12C到0045E744,长度620.很显然加密了: O%$z*1zL
R6 }g=+A
6C<\2+Y
代码:-------------------------------------------------------------------------------- ,_Gx)~tvqH
0045E0EC C0 E6 05 00 00 00 00 00 00 00 00 00 00 00 00 00 梨............. c&1v5
0045E0FC 3A FF 05 00 E4 E6 05 00 00 00 00 00 00 00 00 00 :?.滏......... UGhI"jqmQ
0045E10C 00 00 00 00 48 01 06 00 44 E7 05 00 00 00 00 00 ....H.D?..... gZ_>9~
0045E11C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ :~kn%W
0045E12C 8A 18 93 7C ED 10 92 7C 05 10 92 7C A1 9F 80 7C ??????? hO!PRhrn$
0045E13C 14 9B 80 7C 81 9A 80 7C 5D 99 80 7C BD 99 80 7C ?|??]?|?? R,Y*D]
0045E14C AB 14 81 7C EA 28 C0 8B 94 97 80 7C 7B 97 80 7C ??????{?| Cp eLJgc@
0045E15C 59 B8 80 7C C7 A0 80 7C AD 9C 80 7C F6 3D B4 E4 Y?|沁????翠 jJ`#Y$AJv
0045E16C 11 03 81 7C 73 F4 93 DC B0 C0 EB 01 4D 11 47 F7 ?s?馨离MG 4qISN:{C(
-------------------------------------------------------------------------------- 6c1WcN
#'C2IRC3
75 )'7vUiy
我们还得到了Advance Import Protection函数的地址(AIP call)01560000,记下待用。 G3&z;jU
q\XYb{Ss\
2、避开IAT加密 orc ^GD/v
这个过程比较简单,跟之前的Aspr没多大区别。首先用OD加载目标程序,忽略除了INT3以外的全部异常 >mL13`#\
F9运行停在第一个异常处,右键选择查找-〉所有参考文本字串,找到连着的两个85,双击找到这里: <sc>{b
v{*5Q-(QL
*L1:}|d+l;
代码:-------------------------------------------------------------------------------- _M;2]WBde
00E3872E F3:A5 rep movs dword ptr es:[edi], dword > 9"R)lb z
00E38730 66:A5 movs word ptr es:[edi], word ptr [es> '|PQjgjSz
00E38732 5E pop esi O4l9a6*gU
00E38733 EB 0A jmp short 00E3873F ^Ti 7RL
00E38735 68 C089E300 push 0E389C0 ; ASCII "85",CR,LF P] U
00E3873A E8 C5CEFDFF call 00E15604 \|>#D6b
00E3873F A1 78B9E300 mov eax, [E3B978] #02b}eG=
00E38744 8B00 mov eax, [eax] u~)v<.,$f;
00E38746 E8 410FFFFF call 00E2968C //F4到这里后F7步进 FJ6XE)&
00E3874B 84C0 test al, al )Ba p4I
00E3874D 75 0A jnz short 00E38759 [6EP0$b
00E3874F 68 C089E300 push 0E389C0 ; ASCII "85",CR,LF c<S.*&
00E38754 E8 ABCEFDFF call 00E15604 <+0C/'y]
00E38759 A1 40BAE300 mov eax, [E3BA40] .h})E
00E3875E 8B40 04 mov eax, [eax+4] H`+$hl3
00E38761 50 push eax M5^3AesT
00E38762 56 push esi =e& :A'%
00E38763 E8 3033FEFF call 00E1BA98 !LXWF2(
-------------------------------------------------------------------------------- K,`958~05
JrwSa2:
3f~`01UT
步入到00E38746处的call后向下找到这里: .88p|}7
o4g2 J'%
%8$?B%AO
代码:-------------------------------------------------------------------------------- '!qbM^|f
00E2979A /75 0A jnz short 00E297A6 |"D.>|J
00E2979C |68 F497E200 push 0E297F4 ; ASCII "180",CR,LF f5MFHC
00E297A1 |E8 5EBEFEFF call 00E15604 6]h,ld
00E297A6 \834424 08 04 add dword ptr [esp+8], 4 zFbtOI^
00E297AB 47 inc edi K| HTQSQQ
00E297AC EB 1A jmp short 00E297C8 OB!chm~
00E297AE 83C7 02 add edi, 2 UR}T'%+
00E297B1 8BC7 mov eax, edi X +vUu%j&
00E297B3 50 push eax }'KNZ
00E297B4 55 push ebp XC?D@m
00E297B5 8D4424 10 lea eax, [esp+10] |IT c,
00E297B9 50 push eax 9 ZfhsLUi
00E297BA 56 push esi e4$VM:~
00E297BB E8 6CFCFFFF call 00E2942C //F4到这里F7步入 ]PT^<<"SA5
00E297C0 0FB707 movzx eax, word ptr [edi] ,3C 4[K_a~
00E297C3 83C0 02 add eax, 2 69\pxOkY
00E297C6 03F8 add edi, eax O* ^am
00E297C8 8A1F mov bl, [edi] 'f4b1 nya*
00E297CA 47 inc edi f{DU6)
00E297CB 3A5E 34 cmp bl, [esi+34] 34>C{.=
00E297CE ^ 0F85 77FFFFFF jnz 00E2974B >2?T[S
00E297D4 8BDF mov ebx, edi !$$F
00E297D6 8B03 mov eax, [ebx] 7&h 9
00E297D8 85C0 test eax, eax K'! h @\
00E297DA ^ 0F85 0AFFFFFF jnz 00E296EA !U; U2
00E297E0 8A0424 mov al, [esp] ?vp`9 X
00E297E3 83C4 0C add esp, 0C B:45f J0>
00E297E6 5D pop ebp V!Q${3)Y
00E297E7 5F pop edi EX5;YWBq
00E297E8 5E pop esi gf 4;7p
00E297E9 5B pop ebx 8|~D-5^c
00E297EA C3 retn +J ,I?E]=
-------------------------------------------------------------------------------- !8TB5h)
#&\{3<;
w+79A)`
进入00E297BB处的Call后就是处理IAT的地方了,接下来就是找对应情况然后PATCH了: Rpw/Xc
FbZW|1'J*
?KJ06<
代码:-------------------------------------------------------------------------------- Bcl$~N
00E29447 83E8 02 sub eax, 2 LV#9eM$S.
00E2944A 0FB630 movzx esi, byte ptr [eax] Kqc!y^COH
00E2944D 8B45 10 mov eax, [ebp+10] 41A?
00E29450 83E8 02 sub eax, 2 %^pc6BM
00E29453 0FB600 movzx eax, byte ptr [eax] Y*GNhJJ
00E29456 3B43 2C cmp eax, [ebx+2C] 7\x0SP~
00E29459 76 06 jbe short 00E29461 L "
00E2945B 8943 2C mov [ebx+2C], eax %KM})auIO)
00E2945E EB 01 jmp short 00E29461 RE(4fk'=
00E29460 6933 C08A433B imul esi, [ebx], 3B438AC0 ~5=E#pn
00E29466 3BF0 cmp esi, eax //在这里下硬件断点 "kSl%e=
00E29468 75 5E jnz short 00E294C8 //这里改成jmp 01550000 跳到Patch代码中去 ~C Wh
00E2946A EB 01 jmp short 00E2946D 45Z}7< x
00E2946C C7 ??? ; 未知命令 l3EB25d
00E2946D 66:8B02 mov ax, [edx] mY D]39
00E29470 66:8945 FA mov [ebp-6], ax VS(8EH[N
00E29474 83C2 02 add edx, 2 I[2'm2
00E29477 8955 FC mov [ebp-4], edx E8<z>c
-------------------------------------------------------------------------------- l?`dga9 B
5Wfqld
W@6B|
在00E29466处下硬件断点,用F9不断运行,同时观察数据窗口里面IAT的变化,如果在ESI的某个值时IAT ?o R[*p
中的值被解码就是第一种或第二种情况,没有变化就是第三种情况。这里和前面的Aspr有点不同的是一共只有 ?m vS th
3种情况,也就是说没有处理GetProcAddress的情况,事实上如果你查看加密的IAT会发现GetProcAddress在里 /df-X\UAT
面。不知道是不是Beta版的关系还是Aspr觉得没什么必要? qR~/\4'h
ID f~D!
我这里的三种情况分别是:第一种B7 第二种CF 第三种82。接下来就是Patch了,用插件HidenOD分出一块空 x7B&n
间,贴上我自己写的一段代码,里面除了把第三种情况变成第二种情况以外还多出了另外其他情况的处理。如果有非 hH[x&3j
以上三种情况的ESI值出现Patch代码会自动停下来,不过运行前要不忽略INT3中断。如下: jI>a}"
r+: LvNS
A;JCLD N!
代码:-------------------------------------------------------------------------------- ^\AK#Rp6
01550000 - 0F84 67948DFF je 00E2946D //第一种 OZBp<iex8
01550006 81FE 82000000 cmp esi, 82 H&{6S6*
0155000C 0F84 0C000000 je 0155001E//第三种 [0ui$K
01550012 81FE CF000000 cmp esi, 0CF $1'jLSH
01550018 0F85 0A000000 jnz 01550028//不是前三种 ?$erZN?fc
0155001E BE CF000000 mov esi, 0CF 6)$+0 Z,A
01550023 - E9 A0948DFF jmp 00E294C8 yG*fN~I@>
01550028 CC int3 //如果出现不是前三种情况会停在这里 \]`&7aOz
01550029 ^ EB F3 jmp short 0155001E /9xQ:Pm+)
0155002B 90 nop 9_ZM-N8@
-------------------------------------------------------------------------------- ]Sp$/
q8M T,H0
-y?r{nFuR
二进制: v*)}U M
lR|bV=
0F 84 67 94 8D FF 81 FE 82 00 00 00 0F 84 0C 00 00 00 81 FE CF 00 00 00 0F 85 0A 00 00 00 BE CF SG=]l^gx
00 00 00 E9 A0 94 8D FF CC EB F3 90 00 00 00 00 M)HT#abH
W%sBF :
以上的代码原来用来处理Aspr2.1的现在用来Aspr2.3也一样,不过就目前看他永远不会自己停下来,因为不存在 gc-et7L. c
第四种情况。上面的代码稍微改一下就可以用在你自己的Aspr2.X上,不过要注意的是为了方便所有的转跳都是long的。 EbuIGhB
)-#6R)>&BF
把00E29468改成jmp 01550000,运行一下就可以得到了完整的IAT了(很有可能跑飞,注意保存数据): yU~qlmy.gk
,O1X=dqD
N+fH?5Q
代码:-------------------------------------------------------------------------------- 7h _hlg3
8A 18 93 7C ED 10 92 7C 05 10 92 7C A1 9F 80 7C 14 9B 80 7C 81 9A 80 7C 5D 99 80 7C BD 99 80 7C z]'}/2xl"
AB 14 81 7C 37 97 80 7C 94 97 80 7C 7B 97 80 7C 59 B8 80 7C C7 A0 80 7C AD 9C 80 7C E0 C6 80 7C -j^YNjy
11 03 81 7C D3 2F 88 7C 05 A4 80 7C EE 1E 80 7C 28 AC 80 7C 29 B5 80 7C 57 B3 80 7C 7E D4 80 7C )]E#JT!/Z
8D 2C 81 7C 66 AA 80 7C 59 35 81 7C D7 EF 80 7C A2 CA 81 7C 9F 0F 81 7C 8A 2B 86 7C 40 7A 95 7C B`B/3gsIc_
E1 EA 81 7C A9 2C 81 7C 00 00 00 00 B3 11 D3 77 E8 0F D2 77 EA 04 D5 77 90 0F D2 77 00 00 00 00 _vc.HA_(W
83 78 DA 77 1B 76 DA 77 F0 6B DA 77 00 00 00 00 50 48 0F 77 9D C9 11 77 59 4B 0F 77 00 00 00 00 'P-HL#ZI(
。。。。。。。 })wFv
-------------------------------------------------------------------------------- d`9oYH6/1
Bs.HO_$
Ql<tBW_
IAT建议复制出来,我们等一下要重来。 ucqq "n}
M`<&EwT~
3、处理AIP &C6bJ*y _
接下来就是处理AIP的函数了,首先来到OEP处,然后把刚才得到的IAT贴回去。之后分一段内存贴上我写的一段代码, @ZZ hc<S
这段代码也是用脱Aspr2.1改的,下面说说这段代码怎么用: 9c3? B2O
7T8"k
这段代码可以贴在任何地址处而不用修改任何一个字节,但是它需要一些变量,你在运行之前要填上这些变量。如果 btcZ-&G]
你的代码被贴在0040000,那么: }<}G>
kGj]64A)
0040000+100 程序代码段开始地址 W Lldmd- u
0040000+104 程序代码段结束地址+1 @A MxW129
0040000+108 ESP保存地址 6-NsT-v
0040000+10C 保存解码API地址 !Cl0:`?7`
0040000+110 IAT开始地址 I&ZMrDlkg>
0040000+114 IAT结束地址+4 Erg6a~7h!]
0040000+118 解码call地址 x_y:
0040000+11C 未找到API个数记录 x*dej9[3
[\CAE<=f
你需要填的是目标程序的代码段开始地址、程序代码段结束地址+1、IAT开始地址、IAT结束地址+4和解码call地址。 `KwJ@8[r{
其余的就不用管了,我们这里: z \p-*
5coc^\(V
程序代码段开始地址=00401000 ;> *[
程序代码段结束地址+1=0045B000 `~HOr.mz
IAT开始地址=0045E12C Y>i"c (?U
IAT结束地址+4=0045E748 F$zU^*~k
解码call地址(AIP call)=01560000 /W5 {*E$
'mZ h
注意x86的数据是big end,就是低位在前高位在后,别填倒了: '#Qdrp0
\x'?Z w]
填完后整个数据窗口应该是这样: `.wF1Wf
h;oXeiQh&
. 9_cnp`
代码:-------------------------------------------------------------------------------- ;K^C8IP
00FB0000 E8 00 00 00 00 5B 83 EB 05 8B 93 00 01 00 00 80 ?...[??...?v5*_E@
00FB0010 3A E8 0F 85 94 00 00 00 8B 42 01 03 C2 83 C0 05 :??...??? UV` Fq;C
00FB0020 3B 83 18 01 00 00 0F 85 80 00 00 00 90 90 90 90 ;?..?...?? SNo:JLU@=
00FB0030 90 90 90 90 90 90 90 90 60 89 A3 08 01 00 00 FF ????`?..?!WNL2A
00FB0040 E2 E8 00 00 00 00 5B 83 EB 46 89 83 0C 01 00 00 忤....[?F?... z%}:cLtaCx
00FB0050 8B A3 08 01 00 00 61 8B 8B 10 01 00 00 8B 83 0C ?..a?..?. ^}V EgE
00FB0060 01 00 00 39 01 0F 85 0D 00 00 00 66 C7 02 FF 25 ..9?...f?? Rx4]To:z;
00FB0070 89 4A 02 E9 34 00 00 00 83 C1 04 3B 8B 14 01 00 ??...?;?. 1.'Q"RaDI
00FB0080 00 0F 82 DC FF FF FF FF 83 1C 01 00 00 90 90 90 .????..? Z%):%os-lS
00FB0090 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ???????? :c dS+V
00FB00A0 90 90 90 90 90 90 90 90 90 90 90 90 42 3B 93 04 ??????B;? p\ '85Vks
00FB00B0 01 00 00 0F 82 56 FF FF FF EB FE 00 00 00 00 00 ..????.... 1y7n3?
00FB00C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ <?#LM^+BI
00FB00D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ "y0c\6e
00FB00E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ zMx]g
00FB00F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ >=+w> JQ
00FB0100 00 10 40 00 FC AF 45 00 44 FF 12 00 1E 31 32 76 .@.?E.D?.12v imxg-Ayr)
00FB0110 2C E1 45 00 44 E7 45 00 00 00 56 01 01 00 00 00 ,崤.D缗...V... ?YM yX2
-------------------------------------------------------------------------------- t,7Fj:*V|
E{mlN]
^%&gQt!
00FB0100处开始就是变量表了。 x1+ I?I
. +88z0}@
以下是代码(有点长,主要是为了以后加东西): `@x>F!Tu
{A.W#u:B
LBQH K;aw
代码:-------------------------------------------------------------------------------- ~D U/{c
00FB0000 E8 00000000 call 00FB0005 SOh V|G
00FB0005 5B pop ebx I +etQA,
00FB0006 83EB 05 sub ebx, 5 //用ebx取得代码所在地址 ebx是变量的基址 [ K|A
00FB0009 8B93 00010000 mov edx, [ebx+100] )mr' CYUu
00FB000F 803A E8 cmp byte ptr [edx], 0E8 >^iol:=.
00FB0012 0F85 94000000 jnz 00FB00AC //查找call xxxxxxx daNx|VP
00FB0018 8B42 01 mov eax, [edx+1] G1@ $Z'X
00FB001B 03C2 add eax, edx V,B;{U>J_
00FB001D 83C0 05 add eax, 5 //计算出call去哪里 ]!H6!KmG
00FB0020 3B83 18010000 cmp eax, [ebx+118] //比较一下是不是去AIP的call ` /,WdX@
00FB0026 0F85 80000000 jnz 00FB00AC //不是就继续找 ^ OZ_<~r
00FB002C 90 nop //是就处理 T:ltQ(_!{
00FB002D 90 nop 1`*l'{1
00FB002E 90 nop oL^XcU>
00FB002F 90 nop cuM?Zxe*
00FB0030 90 nop URAAk;+i
00FB0031 90 nop {mbX)W
00FB0032 90 nop _xwf='u
00FB0033 90 nop `?Ryu[Df
00FB0034 90 nop zG:BJ=[G
00FB0035 90 nop =MT"ZSBS
00FB0036 90 nop _/Ag7^$ni
00FB0037 90 nop ,[~m1J'
00FB0038 60 pushad J`6^GB2Sb
00FB0039 89A3 08010000 mov [ebx+108], esp //保存现场 VFPqU4~?G
00FB003F FFE2 jmp edx //去AIP的call /^] N#~
00FB0041 E8 00000000 call 00FB0046 //中断返回 RU-f2I( 7
00FB0046 5B pop ebx x-6qXg`-
00FB0047 83EB 46 sub ebx, 46 //重新取回变量基址 6+W`z-Lwl
00FB004A 8983 0C010000 mov [ebx+10C], eax //保存解码出的API函数地址 这里如果是Aspr2.1的要把eax改成edx ;b!kPDy
00FB0050 8BA3 08010000 mov esp, [ebx+108] 3_<OSf%/d
00FB0056 61 popad //恢复现场 ^^o1Rpv5e
00FB0057 8B8B 10010000 mov ecx, [ebx+110] //在IAT中查到该API函数地址所在 ^nO]1ox?R
00FB005D 8B83 0C010000 mov eax, [ebx+10C] .XZP@H p
00FB0063 3901 cmp [ecx], eax Ki?Ko_]p&
00FB0065 0F85 0D000000 jnz 00FB0078 //是否找到 yOfb Wt
00FB006B 66:C702 FF25 mov word ptr [edx], 25FF //找到就处理 这里要注意 一般Delphi都是jmp [xxxxx]就是 25FF N5E:*r F
00FB0070 894A 02 mov [edx+2], ecx //不过也不完全一定,适当的时候要自己改成15FF -^F>n2
00FB0073 E9 34000000 jmp 00FB00AC //找到就继续下一个 UPd"zM:5qN
00FB0078 83C1 04 add ecx, 4 tAlC 7
00FB007B 3B8B 14010000 cmp ecx, [ebx+114] //是否IAT结束 Xq- ?+'P&
00FB0081 ^ 0F82 DCFFFFFF jb 00FB0063 T/cMyJj"
00FB0087 FF83 1C010000 inc dword ptr [ebx+11C] //结束说明没有找到 未找到API个数记录 变量+1 GMt v?.|
00FB008D 90 nop U--*9j>
00FB008E 90 nop j5Wmn]5
00FB008F 90 nop 4BYAsp=`
00FB0090 90 nop qczU i
00FB0091 90 nop G_d=,gq
00FB0092 90 nop H1:I[yUx.y
00FB0093 90 nop @P+Coz
00FB0094 90 nop Ty:0 qx>w
00FB0095 90 nop }X)LKbV3
00FB0096 90 nop $q^22!,p
00FB0097 90 nop #vYt)b dy
00FB0098 90 nop 2E8%>IN E
00FB0099 90 nop y1\YZJ
00FB009A 90 nop $hYS
00FB009B 90 nop B}`[Nk 8
00FB009C 90 nop O5N_e
00FB009D 90 nop $6xD@
00FB009E 90 nop Ho</jjF4x(
00FB009F 90 nop Fy TF33/
00FB00A0 90 nop @8"mqhf/>p
00FB00A1 90 nop -z47@%x]
00FB00A2 90 nop #ub](kcRS
00FB00A3 90 nop "j F
00FB00A4 90 nop QidssOf
00FB00A5 90 nop 1 2TAl2
00FB00A6 90 nop l87ynD./
00FB00A7 90 nop ]!zVowz.*
00FB00A8 90 nop /bu> '\17
00FB00A9 90 nop %CJyYgeLXA
00FB00AA 90 nop ,2SO@
00FB00AB 90 nop 9bE6O%&T4n
00FB00AC 42 inc edx v:IW1u@6
00FB00AD 3B93 04010000 cmp edx, [ebx+104] %=- [Ul X
00FB00B3 ^ 0F82 56FFFFFF jb 00FB000F //代码段结束? me,ns"d
00FB00B9 - EB FE jmp short 00FB00B9 //原地等待 OV?d E|qg^
-------------------------------------------------------------------------------- O$ #d_7RJ:
L:Z^EyU
H:\p]
二进制: om;75tuD
-#" f6@fzu
E8 00 00 00 00 5B 83 EB 05 8B 93 00 01 00 00 80 3A E8 0F 85 94 00 00 00 8B 42 01 03 C2 83 C0 05 B( =i".G
3B 83 18 01 00 00 0F 85 80 00 00 00 90 90 90 90 90 90 90 90 90 90 90 90 60 89 A3 08 01 00 00 FF Vyhs{ay
E2 E8 00 00 00 00 5B 83 EB 46 89 83 0C 01 00 00 8B A3 08 01 00 00 61 8B 8B 10 01 00 00 8B 83 0C QswmT]N%
01 00 00 39 01 0F 85 0D 00 00 00 66 C7 02 FF 25 89 4A 02 E9 34 00 00 00 83 C1 04 3B 8B 14 01 00 $#l@;3ur
00 0F 82 DC FF FF FF FF 83 1C 01 00 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 8|MKI@??B
90 90 90 90 90 90 90 90 90 90 90 90 42 3B 93 04 01 00 00 0F 82 56 FF FF FF EB FE Dm/%%|
]EekLNJ/
这段代码贴上后还不算完,我们还要让壳的高级API保护的函数(AIP call)跳回到我们这段代码中,在Aspr2.1 =movyzUZ
中我们可以找一段syscom提供的特征码然后patch一个jmp就可以了,但是在Aspr2.3中这招行不通。前几天,有人发 \!0H,cEl
了Aspr2.2和2.3的脱文中提供的方法与Aspr2.1基本相同,但是在我这里行不通。我想可能是加壳时的选项不同导致的。 </t7 " Q@U
uy5?/hO
为了搞定这个问题只好自己跟一下这个call了,由于跟踪的过程比较繁琐,也很枯燥,就不详细写了。不过发现这个 o'B;c0a
call现在没办法在里面Patch代码,它采用一种层进式的检测修改的方式,每一段代码要先检测下面需要运行的代码是否 E`9o\\5
被修改,如果被修改就会在解码API的时候发生错误,而且,现在看来他也不走syscom提供特征码的那段代码了。 JYB;0$z
"@|)d`l
所以解决这种问题的最好方法就是脚本了(强烈感谢SHaG编写如此NB的插件,我对你的敬仰简直有如滔滔江水连绵不 jw$_c#."
绝。。。省略一千字)。 M8YwgV
Vj^3v*0%:1
在内存映像中查找如下内容:03 45 08 8B 00 03 45 08 8B 55 14 29 D0 89 45 FC 5A 8B 45 FC ewN7]A1r*
就是这里: w!J!Fws >F
$!:#i(A"
代码:-------------------------------------------------------------------------------- sNZa5:/b<D
00E358EF C1E0 02 shl eax, 2 ,?oour?0,
00E358F2 0342 1C add eax, [edx+1C] jTt]\iYrM
00E358F5 0345 08 add eax, [ebp+8] @~X.bFc9
00E358F8 8B00 mov eax, [eax] i?-c |CB
00E358FA 0345 08 add eax, [ebp+8] dt^Gw|#x
00E358FD 8B55 14 mov edx, [ebp+14] //API的地址在这里的EAX中昙花一现 在这里下硬件断点 wx_$.*nn&
00E35900 29D0 sub eax, edx //这里马上就加密了 @PL] (_<
00E35902 8945 FC mov [ebp-4], eax 3 }<"W&!
00E35905 5A pop edx L^nXC
00E35906 8B45 FC mov eax, [ebp-4] #\Ef8%#%k
-------------------------------------------------------------------------------- @Wbd;LI>
sgH -ipi
{D~oJklAN
在00E358FD处下硬件断点,然后回到我们的Patch代码处,在第一句上右键-〉此处新建EIP,之后运行这个脚本: ;ozH-[{P
Dx]-$(
d[-DHrc.g
代码:-------------------------------------------------------------------------------- 2MF^c+ (
loop: U/#|Z<K,B
run WebmuG
cob 9VPG9iu
mov eip,00FB0041//这里的地址是我们Patch代码的中断返回处 y LjAw3,
jmp loop FNe~r:[m{
-------------------------------------------------------------------------------- s%m1h@
Z2N>Vmyx*
kztR,R+?}
脚本运行后OD开始工作,等一段时间(比较慢),OD不闪了以后暂停脚本的运行,之后暂停程序的运行。顺序一定 _PV91dg)b
不要错,程序会停在最后一行代码处。 ,yZ2 KU9
;ELA 0
我们到前面看看,这时AIP call都已经修复了: uW6Fo~
NiPKN8E"
X(&,@JfONS
代码:-------------------------------------------------------------------------------- A.'f|o@ ;
004011FD . 626A 65 bound ebp, [edx+65] (Z~_<cYh
00401200 . 63748B C0 arpl [ebx+ecx*4-40], si f -Or
00401204 $- FF25 B0E14500 jmp [45E1B0] ; kernel32.GetStdHandle 4]rK0 U
0040120A 8BC0 mov eax, eax dXIhCnc
0040120C .- FF25 ACE14500 jmp [45E1AC] ; kernel32.RaiseException ,-q3xi<o
00401212 8BC0 mov eax, eax =xj*UsSJ}
00401214 .- FF25 A8E14500 jmp [45E1A8] ; ntdll.RtlUnwind 19ocmI
0040121A 8BC0 mov eax, eax ^E29B^(v\
0040121C $- FF25 A4E14500 jmp [45E1A4] ; kernel32.UnhandledExceptionFilter q<}`mAS.k
00401222 8BC0 mov eax, eax 7nwEua'b
00401224 $- FF25 A0E14500 jmp [45E1A0] ; kernel32.WriteFile 3op)arH
0040122A 8BC0 mov eax, eax 9:(D dO
0040122C $- FF25 C4E14500 jmp [45E1C4] ; user32.CharNextA 1z9w4Fz
00401232 8BC0 mov eax, eax KYe;5 oa
00401234 .- FF25 9CE14500 jmp [45E19C] ; kernel32.ExitProcess Li?u|lmn8
0040123A 8BC0 mov eax, eax lid} (ZT]
0040123C $- FF25 C0E14500 jmp [45E1C0] ; user32.MessageBoxA T~Z@8tQ"
00401242 8BC0 mov eax, eax 2&V~koN
00401244 $- FF25 98E14500 jmp [45E198] ; kernel32.FindClose |5Z mjL"8
0040124A 8BC0 mov eax, eax T&5^|?
。。。。。 ^5Gh
-------------------------------------------------------------------------------- Hcv(Heb 7
x`5wcTE
; _'&\90
4、Dump、修复和stolen code g!Q6 T
接下来就是Dump+Imp修复了。搞定后本以为大功告成,但却运行不了,难道有自校验?不对,这是我自己写的东西怎么会 E)w2~&
有自校验?只好用OD加载跟一下了,加载后按F9运行,OD提示不知如何运行,因为015A0000处不可读。一看就知道时壳内的地 a{R Ds,
址,看来这是Aspr2.3的新花样了。看看堆栈: bv"mi?>&S
N`,B mH;t
*&Ni X
代码:-------------------------------------------------------------------------------- hf (WoJs
0012FBE8 004503F0 返回到 dumped_.004503F0 来自 dumped_.00407FDC FGcS5Q$y1\
0012FBEC 0012FC34 NA %#XMb
0012FBF0 004503B8 dumped_.004503B8 lNb4*r<{
0012FBF4 00DB3684 ASCII "Form1" ]<&']~7
0012FBF8 00000000 G2wb4%9
0012FBFC 00413CA9 返回到 dumped_.00413CA9 J2j#-ug
0012FC00 00DB3684 ASCII "Form1" Lw 5 lt7p
0012FC04 00000000 WY1baxl:
-------------------------------------------------------------------------------- e.`KYy,
;*Nqr~TkI
}Myh^$lcG
重新加载,到004503F0处: ag1/xPk
-c$q40;
!}{
代码:-------------------------------------------------------------------------------- /X!1+O
004503E0 . F643 1D 02 test byte ptr [ebx+1D], 2 &0c6Jk@}
004503E4 . 75 0E jnz short 004503F4 z'a zL k>
004503E6 . 8B53 08 mov edx, [ebx+8] l0Ef *@s1
004503E9 . 8BC5 mov eax, ebp sJHwI8sj
004503EB . E8 EC7BFBFF call 00407FDC //这个call引发的异常 7N*F(prr/f
004503F0 . 85C0 test eax, eax )F'?Z3d
004503F2 . 74 3A je short 0045042E "*>v'vr]wu
004503F4 > 47 inc edi }~*UAMpR
004503F5 . 4E dec esi ]uvODQ^;
004503F6 .^ 75 DA jnz short 004503D2 Y AQF5M)
-------------------------------------------------------------------------------- '|7&_+/
Y&3p.i
F}(#t:g
看来上面的那个Call有问题了,在其上设断点,F7步进,看到了这个: MeQG|9vzC
<="O_YtU
Gb/ q.s
代码:-------------------------------------------------------------------------------- `xZH l)i
00407FDC 68 00005A01 push 15A0000 //这两句跳到壳里去了 ( w 3Zh,[
00407FE1 \. C3 retn //用retn当作转跳,相当于jmp 15A0000 m@(Wx2Y
00407FE2 B7 db B7 7l;v{L"z
00407FE3 68 db RDK(,koq~
-------------------------------------------------------------------------------- 0%h>
(+(Xh|Cf
T/|:x Pd
现在问题明白了,Aspr2.3在这里把这个函数偷走了。看来要带壳调一下加壳的程序了,用OD重新加载目标程序 avZ88"SA
(不是脱壳后的),来到OEP处,在00407FDC上下断,F9运行,停下后按两次F8,我们来到了壳里: |k'EJ
=}v4;LHB
8FfrJ9
代码:-------------------------------------------------------------------------------- aZ]?_21|
015A0000 56 push esi 5@`C$`JB
015A0001 57 push edi 8| i&N f#
015A0002 53 push ebx I\| WkXR1"
015A0003 8D744B 9A lea esi, [ebx+ecx*2-66] 4 \R=QD
015A0007 C1C6 1B rol esi, 1B }1Duan
015A000A C1C6 F7 rol esi, 0F7 _\a_(-%
015A000D 8D7420 3C lea esi, [eax+3C] ~u1I=HfQ~*
015A0011 8D740E C4 lea esi, [esi+ecx-3C] Hd24m1l9
015A0015 2BF1 sub esi, ecx QJ@kG'Z
015A0017 8D7C51 E7 lea edi, [ecx+edx*2-19] ~|.8S^rMA
015A001B EB 02 jmp short 015A001F 4_ 5s_s
015A001D CD20 8D7C4B16 vxdcall 164B7C8D .];2>e8
015A0023 83EF 16 sub edi, 16 >W@&Cwp
015A0026 8D7C35 E3 lea edi, [ebp+esi-1D] B]}:~ ^E
015A002A 2BFE sub edi, esi n|K,
015A002C 8D7C0A 63 lea edi, [edx+ecx+63] W3j`@WV>
015A0030 F3: prefix rep: k2|{?<J
015A0031 EB 02 jmp short 015A0035 6i-& TUF
015A0033 CD20 2BF9EB01 vxdjump 1EBF92B n'[H dj9
015A0039 - E9 8D7F9D09 jmp 0AF77FCB sh=a!;t^
015A003E C07403 8B 40 sal byte ptr [ebx+eax-75], 40 O(\U#RtY^
015A0043 FC cld %ae[)FOZ3C
015A0044 09D2 or edx, edx ^O"7dMPi(
015A0046 74 03 je short 015A004B Q^MBraj
015A0048 8B52 FC mov edx, [edx-4] D+x5S;U
015A004B B9 4EE14A00 mov ecx, 4AE14E ~&MSq?Wmj?
015A0050 B9 86C54000 mov ecx, 40C586 [A-L-]KX}k
015A0055 50 push eax al_X Q_3>
015A0056 2BCD sub ecx, ebp JZczy=h
015A0058 59 pop ecx ~v2 n.!n~
015A0059 39D1 cmp ecx, edx V6e>y6F
015A005B 76 02 jbe short 015A005F H* `Dy
015A005D 89D1 mov ecx, edx ~Sr_|F(X
015A005F 39C9 cmp ecx, ecx E3N-<@)(
015A0061 F3:A6 repe cmps byte ptr es:[edi], byte ptr> >wQ >hk|
015A0063 74 2A je short 015A008F =..#x h&
015A0065 8A5E FF mov bl, [esi-1] +n^-#np
015A0068 80FB 61 cmp bl, 61 b>$M68 `0
015A006B 72 08 jb short 015A0075 -u{_GIR4_
015A006D 80FB 7A cmp bl, 7A <Q:0X
015A0070 77 03 ja short 015A0075 ae~8'PN
015A0072 80EB 20 sub bl, 20 SWFU[ cryk
015A0075 8A7F FF mov bh, [edi-1] JV96ilYy
015A0078 80FF 61 cmp bh, 61 5 m|1]
015A007B 72 08 jb short 015A0085 B8Ud?]G 7
015A007D 80FF 7A cmp bh, 7A VuI\
015A0080 77 03 ja short 015A0085 'uod Y?V
015A0082 80EF 20 sub bh, 20 gfk I n3A
015A0085 38FB cmp bl, bh 6To^uiQ,<
015A0087 ^ 74 D8 je short 015A0061 3LjhC$0 %
015A0089 0FB6C3 movzx eax, bl dhA8l+
015A008C 0FB6D7 movzx edx, bh ;.~-a3U
015A008F 29D0 sub eax, edx M RmN_9*m
015A0091 5B pop ebx yE>v <l
015A0092 5F pop edi SphN Q*A
015A0093 5E pop esi +KMt!HoF
015A0094 C3 retn frmPwr&
015A0095 C3 retn .3(u>zVo
-------------------------------------------------------------------------------- + hFR>Z-j
+tR8 z
&D3YX
乍一看以为这个是壳里要处理什么东西,花指令跟别的地方也很像,试着跟踪看能不能找到原来的代码,可是这段代码 "{@whe#-r
老老实实的走到了015A0094就直接返回程序里去了!那么这个就是我们要找的被偷的代码?可是看起来还不太像,这段代码 APnSaZgs
显然有着Aspr花指令的风格,于是仔细看了看这段指令,把它改一下,并分析: * VHs{\b
*&j}Tg),K
j)?j9
代码:-------------------------------------------------------------------------------- R &C
015A0000 56 push esi [6nFn?kE
015A0001 57 push edi nYW8Vb4 6
015A0002 53 push ebx 2/[,YT* K7
015A0003 8D744B 9A lea esi, [ebx+ecx*2-66] wZ%+]>pSAM
015A0007 C1C6 1B rol esi, 1B UEgdq{R@Yd
015A000A C1C6 F7 rol esi, 0F7 [9d c?S
015A000D 8D7420 3C lea esi, [eax+3C] / |%I]
015A0011 8D740E C4 lea esi, [esi+ecx-3C] 0:r37uz
015A0015 2BF1 sub esi, ecx //从015A003到这句其实就是mov esi,eax @Vwi@>Q'~
015A0017 8D7C51 E7 lea edi, [ecx+edx*2-19] t,IF 'kit
015A001B EB 02 jmp short 015A001F 0(PcPGN 5*
015A001D 90 nop (BF!gjm>m>
015A001E 90 nop SBr(#%7
015A001F 8D7C4B 16 lea edi, [ebx+ecx*2+16] :=L.#
015A0023 83EF 16 sub edi, 16 ca2GG%4)3
015A0026 8D7C35 E3 lea edi, [ebp+esi-1D] T3{!]$7Qp
015A002A 2BFE sub edi, esi i\AcOH
015A002C 8D7C0A 63 lea edi, [edx+ecx+63] -rks.
015A0030 F3: prefix rep: 6Mr%pI
015A0031 EB 02 jmp short 015A0035 .)g|:T>
015A0033 90 nop f{_*Y[t
015A0034 90 nop _}yVS{p
015A0035 2BF9 sub edi, ecx [d(lwM
015A0037 EB 01 jmp short 015A003A vc?6f28
015A0039 90 nop qtE=eCO*
015A003A 8D7F 9D lea edi, [edi-63]//从015A0017到这句其实就是mov edi,edx mhWn uMJA
015A003D 09C0 or eax, eax 0Z PGLd2
015A003F 74 03 je short 015A0044 'cvu} AN
015A0041 8B40 FC mov eax, [eax-4] Yg|#0yY
015A0044 09D2 or edx, edx v9J .*O`
015A0046 74 03 je short 015A004B V]M
015A0048 8B52 FC mov edx, [edx-4] u>fXT6b-
015A004B B9 4EE14A00 mov ecx, 4AE14E ptZj+;eI;
015A0050 B9 86C54000 mov ecx, 40C586 42ct>_c
015A0055 50 push eax zXuA2e_)
015A0056 2BCD sub ecx, ebp FP YKsp
015A0058 59 pop ecx //从015A004B到这句其实就是mov eax,ecx sLO Ab
015A0059 39D1 cmp ecx, edx t.Sv+&NQ
015A005B 76 02 jbe short 015A005F -JH+3H#/
015A005D 89D1 mov ecx, edx .wMe7h^
015A005F 39C9 cmp ecx, ecx OSsjEzU#
015A0061 F3:A6 repe cmps byte ptr es:[edi], byte ptr [esi] 7 u@.3j
015A0063 74 2A je short 015A008F 3CW5]=X)d
015A0065 8A5E FF mov bl, [esi-1] x\ARJIK0>
015A0068 80FB 61 cmp bl, 61 s08y*F
015A006B 72 08 jb short 015A0075 9Ds?th D
015A006D 80FB 7A cmp bl, 7A %:?sSvl
015A0070 77 03 ja short 015A0075 #Ccma$Y`
015A0072 80EB 20 sub bl, 20 zZRR',,
015A0075 8A7F FF mov bh, [edi-1] 0jpgr}(q
015A0078 80FF 61 cmp bh, 61 G^X`p|
015A007B 72 08 jb short 015A0085 o{ ) a+]b
015A007D 80FF 7A cmp bh, 7A Gwe$o!`
015A0080 77 03 ja short 015A0085 \t"X4Xj_E
015A0082 80EF 20 sub bh, 20 w7%`?o]
015A0085 38FB cmp bl, bh g bb~ i\m
015A0087 ^ 74 D8 je short 015A0061 ,zj;sI$]
015A0089 0FB6C3 movzx eax, bl lyUeo/ny
015A008C 0FB6D7 movzx edx, bh ,yZ7N_ ID/
015A008F 29D0 sub eax, edx +tZjw
015A0091 5B pop ebx OW9 +M5N
015A0092 5F pop edi jRW{\\
015A0093 5E pop esi i/p*dBAi/P
015A0094 C3 retn JGT(9%$s
-------------------------------------------------------------------------------- G (\rc
cQHB4.y|
-ma'Ku
这个函数应该是Delphi的一个比较字符串的函数,看来的确是被偷的那段代码,不过他已经被壳改的很乱,不可能贴回到 ?QL _' (Z
原来位置了,只好在程序代码段后面找一块地方,把它贴上: lz L+rm44
ep+/Wl>;-
jAQ)uIMl
代码:-------------------------------------------------------------------------------- ;,66(C>-
0045AF66 0000 add [eax], al w_leq9z@
0045AF68 0000 add [eax], al KI,f,9xuX
0045AF6A 56 push esi %z- AD@D'"
0045AF6B 57 push edi J_4Gt 8ct
0045AF6C 53 push ebx Kt*J@=bQS
......... XO+s{1
......... !5Bs94?V*
0045AFF3 0FB6C3 movzx eax, bl Qj}RT^,g
0045AFF6 0FB6D7 movzx edx, bh PD%`qV
0045AFF9 29D0 sub eax, edx ,MXk7h{7
0045AFFB 5B pop ebx /QgJWcnOm
0045AFFC 5F pop edi ^|nv)
0045AFFD 5E pop esi 0ctvEmjf
0045AFFE C3 retn @YkrfN"^gx
0045AFFF 00 ??? ; 命令置于内存块尾 Tl_ P.?=
-------------------------------------------------------------------------------- K9t*r>WF9
?INZ)PF6[&
=#tM=@m
之后再把00407FDC处改一下,跳过来: ;Giz?PT'~
WU*rm"h
?67qCz@
代码:-------------------------------------------------------------------------------- i=KDeCT
00407FDC /E9 892F0500 jmp 0045AF6A .U}aALZ5
00407FE1 |C3 retn }_ ?200*5
00407FE2 |B7 68 mov bh, 68 ?*lK- :r
-------------------------------------------------------------------------------- [0ov&d?Q
>>dtn">
%+ujC
然后保存修改到文件中,运行一下。终于OK了。 /n7[@W,4
TR_& %T_
四、后记 8MY-J<;W
1=zjQ5RS4;
感谢你这么有耐心得看完这篇文章,希望对你有帮助。在这里更要感谢论坛里的牛人们,无数牛人的文章使我受益良多。 g{_] T"i$
$YsA]jj9"k
关于那段stolen code,其实这段代码可以恢复成和原来一样的,但是如果没有原来的代码我想很难分析出来,上面的分析 V()p'3xw
我也是照着我的源码分析的,联系到今后更多的情况时未知源码的,这种贴回来的方法更实用。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课