《文档管理助手》的pj
使用工具:
winhex 10.0
regshot
trw2000
IDA pro 4.15
hiew 6.40
PEiDentifier v0.7
AspackDIE
目标网址:http://61.175.211.198/wlm/docman/docman10.exe
1.甄别和脱壳:用PEiDentifier v0.7扫描主文件docman.exe,发现其用ASPack 2.x modified - dXamn
压缩,故此用AspackDIE对其脱壳,得到unpacked.exe
2.运行和观察:
运行unpacked.exe,找到[注册]菜单,进行注册。首先,必须生成"注册申请"信息文件
在注册窗口中填入:注册名:dola1234 公司名:7triones_hardware.然后按确定,在桌面
上得到名为:dola1234 7triones_hardware.dat的"注册申请"信息文件。打开其进行观察
发现其内容如下:
[register]
userid=25001255117182133267124000077036091107165139053071043144211054050264238181044294044
0730970150860742690810590951550651481832671150661322630751350610851350
记录关键字[userid].
接着进行注册,文件选定刚刚生成的dola1234 7triones_hardware.dat,经过一段时间的
运算,程序报告"文件中没有可用的注册信息",记录这个message.
同时,注意到注册信息窗口中作者提供的限制信息"没有注册您只能使用26次",由此断定
程序在"注册表"或"文件"中保存了使用计数[明文或密文]。
3.进一步提取相关信息:
用 regshot提取两次运行之间注册表信息的差别,可得到如下的关键信息:
HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Registration\ProductDRemark:
"BB2631EA34FF8F7FC7CA97C5"
HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Registration\ProductDRemark:
"BB2631EB3612EF3A726CC669"
进一步测试,使用程序达到26次以上,这是在启动时强行要求注册,这时将注册表中的[ProductDRemark]
键值改为:"BB2631EA34FF8F7FC7CA97C5"后,又可以试用。由此判断,这可能就是注册与否和使用
次数的关键记录域。
4.寻找静态分析的切入点:
运行winhex 10.0,在运行unpacked.exe,使用winhex
10.0的内存编辑功能,在unpacked.exe
进程的主内存中搜寻前面记录的关键信息"文件中没有可用的注册信息",得到地址:0x005565C0;
5.静态分析:
用IDA PRO 4.15对目标进行反汇编.然后根据地址0x005565C0进行定位.见到如下的信息区:
CODE:005565BA
; CODE:00556532o
CODE:005565BA db '错误'
CODE:005565C0 aHave_None_Info dd 0
; DATA XREF: CODE:00556496o
CODE:005565C0 db '文件中不存在有效的注册信息'
CODE:005565DE aS dw 0
; DATA XREF: CODE:00556518o
CODE:005565DE db '提示'
CODE:005565E4 aSuccess_Register dd 0
; DATA XREF: CODE:0055651Do
CODE:005565E4 db '注册成功!感谢您的支持!'
CODE:00556600 aFailed_Register dd 0
; DATA XREF: CODE:00556537o
CODE:00556600 db '注册失败,请与作者联系!'
由XREF信息再定位到如下的程序段:
CODE:0055643E push
eax
CODE:0055643F mov
ecx, (offset aRegister+4)
CODE:00556444 mov
edx, (offset aRegister+4)
CODE:00556449 mov
eax, [ebp-8]
CODE:0055644C mov
ebx, [eax]
CODE:0055644E call
dword ptr [ebx]
CODE:00556450 mov
edx, [ebp-18h]
CODE:00556453 mov
eax, [ebp-4]
CODE:00556456 mov
eax, [eax+308h]
CODE:0055645C call
sub_44BE7C
CODE:00556461 push
0
CODE:00556463 lea
eax, [ebp-0Ch]
CODE:00556466 push
eax
CODE:00556467 mov
ecx, (offset aUserid+4);注意我们记录的关键字"Userid"
CODE:0055646C mov
edx, (offset aRegister+4);新出的关键字"Register"
CODE:00556471 mov
eax, [ebp-8]
CODE:00556474 mov
ebx, [eax]
CODE:00556476 call
dword ptr [ebx]
CODE:00556478 lea
edx, [ebp-1Ch]
CODE:0055647B mov
eax, [ebp-4]
CODE:0055647E mov
eax, [eax+308h]
CODE:00556484 call
sub_44BE4C
CODE:00556489 cmp
dword ptr [ebp-1Ch], 0
CODE:0055648D jnz
short loc_5564B1 ; 注意此条件跳转
CODE:0055648F push
10h
CODE:00556491 mov
ecx, (offset aA+2)
CODE:00556496 mov
edx, (offset aHave_None_Info+4) ; 无有用信息
CODE:0055649B mov
eax, ds:dword_598DBC
CODE:005564A0 mov
eax, [eax]
CODE:005564A2 call
sub_46C874
CODE:005564A7 call
sub_404288
CODE:005564AC jmp
loc_556557
CODE:005564B1 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
CODE:005564B1
CODE:005564B1 loc_5564B1:
; CODE XREF: CODE:0055648Dj
CODE:005564B1 xor
eax, eax
CODE:005564B3 pop
edx
CODE:005564B4 pop
ecx
CODE:005564B5 pop
ecx
CODE:005564B6 mov
fs:[eax], edx
CODE:005564B9 push
offset loc_5564D0
CODE:005564BE
CODE:005564BE loc_5564BE:
; CODE XREF: CODE:005564CEj
CODE:005564BE mov
dl, 1
CODE:005564C0 mov
eax, [ebp-8]
CODE:005564C3 mov
ecx, [eax]
CODE:005564C5 call
dword ptr [ecx-4];call到loc_5564D0处
CODE:005564C8 retn
CODE:005564C9 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
CODE:005564C9
CODE:005564C9 loc_5564C9:
; DATA XREF: CODE:0055642Eo
CODE:005564C9 jmp
loc_4040E0
CODE:005564CE ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
CODE:005564CE jmp
short loc_5564BE
CODE:005564D0 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
CODE:005564D0
CODE:005564D0 loc_5564D0:
; DATA XREF: CODE:005564B9o
CODE:005564D0 mov
eax, ds:dword_5989DC
CODE:005564D5 mov
byte ptr [eax], 1 ; ++置1++
CODE:005564D8 lea
edx, [ebp-20h]
CODE:005564DB mov
eax, [ebp-4]
CODE:005564DE mov
eax, [eax+308h]
CODE:005564E4 call
sub_44BE4C
CODE:005564E9 mov
ecx, [ebp-20h]
CODE:005564EC mov
edx, [ebp-0Ch]
CODE:005564EF mov
al, 1
CODE:005564F1 call
sub_510FF4
CODE:005564F6 call
sub_513534
CODE:005564FB mov
eax, ds:off_598B48
CODE:00556500 mov
eax, [eax]
CODE:00556502 call
sub_409884
CODE:00556507 call
sub_512854
CODE:0055650C mov
eax, ds:dword_5989DC
CODE:00556511 cmp
byte ptr [eax], 0 ; eax=59b504关键的旗帜单元
CODE:00556514 jz
short bad_cracker
CODE:00556516 push
40h
CODE:00556518 mov
ecx, (offset aS+2)
CODE:0055651D mov
edx, (offset aSuccess_Register+4) ; 成功
CODE:00556522 mov
eax, ds:dword_598DBC
CODE:00556527 mov
eax, [eax]
CODE:00556529 call
sub_46C874
CODE:0055652E jmp
short loc_556548
CODE:00556530 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
CODE:00556530
CODE:00556530 bad_cracker:
; CODE XREF: CODE:00556514j
CODE:00556530 push
10h
CODE:00556532 mov
ecx, (offset aA+2)
CODE:00556537 mov
edx, (offset aFailed_Register+4) ; 失败
CODE:0055653C mov
eax, ds:dword_598DBC
CODE:00556541 mov
eax, [eax]
CODE:00556543 call
sub_46C874
CODE:00556548
CODE:00556548 loc_556548:
; CODE XREF: CODE:0055652Ej
CODE:00556548 mov
eax, [ebp-4]
CODE:0055654B call
sub_468E08
CODE:00556550 mov
ds:byte_5A6960, 1
CODE:00556557
CODE:00556557 loc_556557:
; CODE XREF: CODE:00556402j
CODE:00556557
; CODE:005564ACj
CODE:00556557 xor
eax, eax
CODE:00556559 pop
edx
CODE:0055655A pop
ecx
CODE:0055655B pop
ecx
CODE:0055655C mov
fs:[eax], edx
CODE:0055655F push
offset loc_556591
CODE:00556564
CODE:00556564 loc_556564:
; CODE XREF: CODE:0055658Fj
CODE:00556564 lea
eax, [ebp-20h]
CODE:00556567 mov
edx, 2
CODE:0055656C call
sub_404840
CODE:00556571 lea
eax, [ebp-18h]
CODE:00556574 call
sub_40481C
CODE:00556579 lea
eax, [ebp-14h]
CODE:0055657C call
sub_40481C
CODE:00556581 lea
eax, [ebp-0Ch]
CODE:00556584 call
sub_40481C
CODE:00556589 retn
分析此段程序,其判断流程在IDA中是一目了然的。由以下信息
CODE:00556467 mov
ecx, (offset aUserid+4);注意我们记录的关键字"Userid"
CODE:0055646C mov
edx, (offset aRegister+4);新出的关键字"Register"
判断,程序是读取注册信息文件中的“USERID”和“REGISTER”信息进行校验的,而我们的注册信息文
件中没有REGISTER域,故此出现“文件中没有可用的注册信息”的错误提示。现在我们可以在注册信息
文件中添加“register”域如下:
[register]
userid=25001255117182133267124000077036091107165139053071043144211054050264238181044294044
0730970150860742690810590951550651481832671150661322630751350610851350
register=250012551171821332671240000770360911071651390530710431442110540502642381810442940
440730970150860742690810590951550651481832671150661322630751350610851350
在一次运行程序则没有了“文件中没有可用的注册信息”,而是“注册失败,请与作者联系!”
这就证明我们的判断是正确的。
进一步分析上面的程序,
CODE:0055650C mov
eax, ds:dword_5989DC
CODE:00556511 cmp
byte ptr [eax], 0 ; eax=59b504关键的旗帜单元
CODE:00556514 jz
short bad_cracker
发现eax=59b504是关键的旗帜单元,记录下来,并在TRW2000中下断点:BPM
59b504
然后重新启动unpacked.exe,遇到如下的断点序列:
51103A: MOV BYTE [0059B504],0
...
5111AC: SETZ [0059B504]
...
55611A: CMP BYTE [EAX],0
...
5564D5: MOV BYTE [EAX],1
...
511471: MOV BYTE [0059B504],0 <<<---在注册的流程当中,此处是最后的出点,我们可由此切入.
在IDA中分析511471附近的程序:
CODE:00511471 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
CODE:00511471
CODE:00511471 GHOST_GONIG:
; CODE XREF: sub_510FF4+32Dj
CODE:00511471 mov
ds:byte_59B504, 0 ; ++置0++
CODE:00511478 xor
eax, eax
CODE:0051147A push
ebp
CODE:0051147B push
offset unk_5114A0
CODE:00511480 push
dword ptr fs:[eax]
由交叉引用信息再到:
CODE:00511276 loc_511276:
; CODE XREF: sub_510FF4+F4j
CODE:00511276 call
sub_513534
CODE:0051127B lea
eax, [ebp+var_64]
CODE:0051127E mov
ecx, offset unk_51168C
CODE:00511283 mov
edx, ds:dword_59B518
CODE:00511289 call
sub_404B20
CODE:0051128E mov
eax, [ebp+var_64]
CODE:00511291 lea
ecx, [ebp+var_60]
CODE:00511294 mov
dx, 0E214h
CODE:00511298 call
sub_50D550
CODE:0051129D mov
eax, [ebp+var_60]
CODE:005112A0 lea
ecx, [ebp+var_5C]
CODE:005112A3 mov
dx, 0FF97h
CODE:005112A7 call
sub_50D550
CODE:005112AC mov
ecx, [ebp+var_5C]
CODE:005112AF mov
edx, (offset aProductdremark+4)
CODE:005112B4 mov
eax, [ebp+var_18]
CODE:005112B7 call
sub_473C88
CODE:005112BC
CODE:005112BC loc_5112BC:
; CODE XREF: sub_510FF4+DFj
CODE:005112BC
; sub_510FF4+27Aj ...
CODE:005112BC mov
eax, [ebp+var_18]
CODE:005112BF call
sub_473928
CODE:005112C4 mov
eax, [ebp+var_18]
CODE:005112C7 call
sub_40394C
CODE:005112CC
CODE:005112CC loc_5112CC:
; CODE XREF: sub_510FF4+80j
CODE:005112CC cmp
byte ptr [ebp+var_4+3], 0
CODE:005112D0 jz
loc_5114B6
CODE:005112D6 mov
[ebp+var_D], 0
CODE:005112DA mov
edx, 80000002h
CODE:005112DF mov
eax, [ebp+var_18]
CODE:005112E2 call
sub_473958
CODE:005112E7 mov
cl, 1
CODE:005112E9 mov
edx, (offset aSoftwareMicrosof+4)
CODE:005112EE mov
eax, [ebp+var_18]
CODE:005112F1 call
sub_4739BC
CODE:005112F6 test
al, al
CODE:005112F8 jz
loc_5114B6
CODE:005112FE lea
eax, [ebp+var_1C]
CODE:00511301 mov
edx, [ebp+var_C]
CODE:00511304 call
sub_4048B4
CODE:00511309 lea
edx, [ebp+var_68]
CODE:0051130C mov
eax, [ebp+var_1C] ; 注册信息文件中的数据
CODE:0051130F call
sub_4094C8
CODE:00511314 mov
edx, [ebp+var_68]
CODE:00511317 mov
eax, [ebp+var_8] ; 注册信息文件中的数据
CODE:0051131A call
calculate_register ; +++this call+++
CODE:0051131F test
al, al
CODE:00511321 jz
GHOST_GONIG ; ++置0++
CODE:00511327 xor
eax, eax
CODE:00511329 push
ebp
CODE:0051132A push
offset loc_51139C
CODE:0051132F push
dword ptr fs:[eax]
CODE:00511332 mov
fs:[eax], esp
CODE:00511335 call
sub_513534
CODE:0051133A lea
eax, [ebp+var_74]
CODE:0051133D mov
ecx, offset unk_511698
CODE:00511342 mov
edx, ds:dword_59B518
CODE:00511348 call
sub_404B20
CODE:0051134D mov
eax, [ebp+var_74]
CODE:00511350 lea
ecx, [ebp+var_70]
CODE:00511353 mov
dx, 0E214h
CODE:00511357 call
sub_50D550
CODE:0051135C mov
eax, [ebp+var_70]
CODE:0051135F lea
ecx, [ebp+var_6C]
CODE:00511362 mov
dx, 0FF97h
CODE:00511366 call
sub_50D550
CODE:0051136B mov
ecx, [ebp+var_6C]
CODE:0051136E mov
edx, (offset aProductdremark+4)
CODE:00511373 mov
eax, [ebp+var_18]
CODE:00511376 call
sub_473C88
CODE:0051137B mov
ds:byte_59B504, 1 ; ++置"1"++
CODE:00511382 mov
eax, [ebp+var_18]
CODE:00511385 call
sub_473928
CODE:0051138A mov
eax, [ebp+var_18]
CODE:0051138D call
sub_40394C
CODE:00511392 xor
eax, eax
CODE:00511394 pop
edx
CODE:00511395 pop
ecx
CODE:00511396 pop
ecx
CODE:00511397 mov
fs:[eax], edx
CODE:0051139A jmp
short loc_5113A6
CODE:0051139C ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
CODE:0051139C
CODE:0051139C loc_51139C:
; DATA XREF: sub_510FF4+336o
CODE:0051139C jmp
loc_403E2C
见到附近有关键旗帜的"置0"和"置1",是重点段需要动态跟踪.
6:动态跟踪:在TRW2000中下断点 BPX 5112BC,然后唤起程序进行注册,跟到51130C和511317处,见到注册
信息文件中的数据,userid和register的数据。进而断定51131A处的CALL是关键的比对函数,
跟入发现果然是注册校验算法只是过于繁复,为了快捷进行暴力pj。
CODE:00511321
jz GHOST_GONIG
; ++置0++
将00511321处的跳转改为: jnz
GHOST_gOING (使得注册流程倒入旗帜置1的路径)
7:Patch 程序:
运行hview6.40并以decode方式载入unpacked.exe,定位到111321偏移处,以反汇编方式[A]
对程序进行修改。
8:运行和注册:
运行修改后的unpacked.exe进行注册,输入信息如下:
姓名:dola1234
公司:7triones_hardware
注册信息文件:dola1234 7triones_hardware.dat
点击注册键,程序进行一会儿的校验后显示注册成功的信息。这时看help中的about
信息,显示程序已经注册给:dola1234
9:进一步的观察:
此时观察注册表中的最终信息:
HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Registration\ProductDRemark
[ProductDRemark]="BB21C32B078A1C6556DF"
记录此关键的键值.然后将此键值进行随意的修改如"BB21C32B078A1C6556DF",然后
再次启动程序,发现又成为了试用版本,这样我们就完全可以断定,"BB21C32B078A1C6556DF"
就是对应 [ 姓名:dola1234 公司:7triones_hardware
]的注册键值信息。
10:准备通用的注册文件:
将dola1234 7triones_hardware.dat和此键值一起提供。
简单的注册表导入文件:
REGEDIT4
[HKEY_LOCAL_MACHINE\Software\Microsoft\Internet
Explorer\Registration]
"ProductDRemark"="BB21C32B078A1C6556DF"
希望大家指正,谢谢。