《文档管理助手》的pj
使用工具:
winhex 10.0
regshot
trw2000
IDA pro 4.15
hiew 6.40
PEiDentifier v0.7
AspackDIE
目标
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"
希望大家指正,谢谢。
