软件:quickchm v2.49简介:一个编译与反编译chm文件的软件
原来我是想找能将windows help格式的文件转换成chm文件的工具,于是找到了这个软件。但后来发觉还是不行。--------------------------------------------------------这个软件的主程序加了壳,用fi查看,是Aspack v2.1。用unaspack脱壳,启动程序,程序一闪而过,证明程序有自较检。反汇编程序,查找函数postquitmessage。* Referenced by a CALL at Addresses:|:004644A0 , :0049C69B |* Reference To: user32.PostQuitMessage, Ord:0000h |:004079C0 FF2598965000 Jmp dword ptr [00509698]:004079C6 8BC0 mov eax, eax有两个调用处,004644a0与0049c69b。用trw2000载入主程序,先在第一处下断点,---------------------------------------:0046448D E81E35FAFF Call 004079B0:00464492 85C0 test eax, eax:00464494 7411 je 004644A7:00464496 837DD812 cmp dword ptr [ebp-28], 00000012:0046449A 750B jne 004644A7 -------尝试改为jmp,虽然跳过自较检,但程序不能退出。:0046449C 8B45DC mov eax, dword ptr [ebp-24]:0046449F 50 push eax
* Reference To: user32.PostQuitMessage, Ord:0000h |:004644A0 E81B35FAFF Call 004079C0---------------------------------------在第二处下断点,---------------------------------------:004FC2BC 83FA00 cmp edx, 00000000:004FC2BF 7509 jne 004FC2CA:004FC2C1 3D20A10700 cmp eax, 0007A120:004FC2C6 7610 jbe 004FC2D8 ----------|--这里有两个地方跳过自较检退出,可先载入未脱:004FC2C8 EB02 jmp 004FC2CC | 壳的程序,观察原程序在哪个地方跳过。结果 | 发现原程序在004fc2c6处跳过。* Referenced by a (U)nconditional or (C)onditional Jump at Address: | 改为jmp 004fc2c6|:004FC2BF(C) || |:004FC2CA 7E0C jle 004FC2D8 ----------|
* Referenced by a (U)nconditional or (C)onditional Jump at Address:|:004FC2C8(U)|:004FC2CC A1405E5000 mov eax, dword ptr [00505E40]:004FC2D1 8B00 mov eax, dword ptr [eax]:004FC2D3 E8B803FAFF call 0049C690----------------------------------------用hex workshop编辑程序,将3d20a107007610eb02 改为 eb 即可跳过自较检退出。----------------------------------------
这个程序在启动时会要求注册,但反汇编看到这里好像并不较检注册码,只是将注册码保存起来。以下是破解注册码部分。----------------------------------------------------------:0050175B 55 push ebp:0050175C 6890195000 push 00501990:00501761 64FF30 push dword ptr fs:[eax]:00501764 648920 mov dword ptr fs:[eax], esp:00501767 8D55F8 lea edx, dword ptr [ebp-08]:0050176A A1A45B5000 mov eax, dword ptr [00505BA4]:0050176F 8B00 mov eax, dword ptr [eax]:00501771 8B80F8020000 mov eax, dword ptr [eax+000002F8]:00501777 E8B0A1F7FF call 0047B92C:0050177C 8D45E4 lea eax, dword ptr [ebp-1C]
* Possible StringData Ref from Code Obj ->"F0E1" -------- 这个字符串“F0E1”与注册码的计算有关 |:0050177F BAA8195000 mov edx, 005019A8 :00501784 E84F33F0FF call 00404AD8:00501789 8D55F4 lea edx, dword ptr [ebp-0C]:0050178C A1A45B5000 mov eax, dword ptr [00505BA4]:00501791 8B00 mov eax, dword ptr [eax]:00501793 8B8004030000 mov eax, dword ptr [eax+00000304]:00501799 E88EA1F7FF call 0047B92C:0050179E 8B45E4 mov eax, dword ptr [ebp-1C]----(ebp-1c)存放字符串“F0E1”:005017A1 E85A35F0FF call 00404D00 ---0040d00的这个call的作用是将eax中的字符串的长度存入eax中,后面常用到。:005017A6 8945F0 mov dword ptr [ebp-10], eax---(ebp-10)存放字符串“F0E1”的长度。:005017A9 33FF xor edi, edi ---------edi存放的是字符串“F0E1”的指针。:005017AB C745E801000000 mov [ebp-18], 00000001----(ebp-18)中存放的是假注册码的指针,以后每次+2:005017B2 BB80000000 mov ebx, 00000080 ------令ebx=80,这与计算注册码的第一二个字符有关:005017B7 C645E300 mov [ebp-1D], 00 ------初始化标志,(ebp-1d)存放的是注册是否成功的标志。:005017BB 8B45F8 mov eax, dword ptr [ebp-08]---将名字存入eax中:005017BE E83D35F0FF call 00404D00 ------名字长度存入eax,又一次用到这个函数了。:005017C3 8BF0 mov esi, eax:005017C5 83FE01 cmp esi, 00000001 :005017C8 0F8CA7000000 jl 00501875 ------如果名字长度小于1,则game over。
* Referenced by a (U)nconditional or (C)onditional Jump at Address:|:0050186F(C)|:005017CE 8B45F8 mov eax, dword ptr [ebp-08]----名字存入eax,esi存放的是名字的长度。:005017D1 0FB64430FF movzx eax, byte ptr [eax+esi-01]---将名字的第n位(从最后一位开始取)放入eax中。:005017D6 03C3 add eax, ebx --------eax+ebx,(即字符的ascii码+ebx),存放于eax中。:005017D8 B9FF000000 mov ecx, 000000FF--------令ecx=ffh,(十进制的255):005017DD 99 cdq:005017DE F7F9 idiv ecx --------eax÷ecx:005017E0 8BDA mov ebx, edx --------将余数存入ebx中:005017E2 3B7DF0 cmp edi, dword ptr [ebp-10]:005017E5 7D03 jge 005017EA -------- ]:005017E7 47 inc edi -------- ]:005017E8 EB05 jmp 005017EF ] ]->字符串“F0E1”的指针+1,如果到尾了,就重新指向头部。* Referenced by a (U)nconditional or (C)onditional Jump at Address: ]|:005017E5(C) ]| ]:005017EA BF01000000 mov edi, 00000001---------]
* Referenced by a (U)nconditional or (C)onditional Jump at Address:|:005017E8(U)|:005017EF 8B45E4 mov eax, dword ptr [ebp-1C]-----字符串“F0E1”放入eax:005017F2 0FB64438FF movzx eax, byte ptr [eax+edi-01]--将字符串“F0E1”的第n位(从头开始取)放入eax中。:005017F7 33D8 xor ebx, eax ---异或,结果存入ebx中。:005017F9 8D45EC lea eax, dword ptr [ebp-14]:005017FC 50 push eax:005017FD 895DD8 mov dword ptr [ebp-28], ebx:00501800 C645DC00 mov [ebp-24], 00:00501804 8D55D8 lea edx, dword ptr [ebp-28]:00501807 33C9 xor ecx, ecx
* Possible StringData Ref from Code Obj ->"%1.2x" ----以下这一大段是比较代码,作用大概是:用计算出来的结果 | (存入ebx中)转为ascii码,与假注册码的指针(指针存于ebp-:00501809 B8B8195000 mov eax, 005019B8 18中)所指向的字符相比较(每次比较两位)。比较的结果影响:0050180E E8C98BF0FF call 0040A3DC 标志ebp-1d,相等则置1,不相等则置0,相等则令指针+2,不:00501813 8D45D4 lea eax, dword ptr [ebp-2C] 相等则令指针不动。:00501816 50 push eax 我个人认为这段代码写的有的笨,其实只要一发现比较不相等,:00501817 8B45EC mov eax, dword ptr [ebp-14] 就跳去game over就行了,不用将整个假的注册码比较完。:0050181A E8E134F0FF call 00404D00:0050181F 8BC8 mov ecx, eax:00501821 8B55E8 mov edx, dword ptr [ebp-18]:00501824 8B45F4 mov eax, dword ptr [ebp-0C]:00501827 E83437F0FF call 00404F60:0050182C 8B45D4 mov eax, dword ptr [ebp-2C]:0050182F 8B55EC mov edx, dword ptr [ebp-14]:00501832 E81536F0FF call 00404E4C:00501837 0F9445E3 sete byte ptr [ebp-1D]:0050183B 8D45D0 lea eax, dword ptr [ebp-30]:0050183E 50 push eax:0050183F 8B45EC mov eax, dword ptr [ebp-14]:00501842 E8B934F0FF call 00404D00:00501847 8BC8 mov ecx, eax:00501849 8B55E8 mov edx, dword ptr [ebp-18]:0050184C 8B45F4 mov eax, dword ptr [ebp-0C]:0050184F E80C37F0FF call 00404F60:00501854 8B55D0 mov edx, dword ptr [ebp-30]:00501857 8B45EC mov eax, dword ptr [ebp-14]:0050185A E8ED35F0FF call 00404E4C:0050185F 750B jne 0050186C:00501861 8B45EC mov eax, dword ptr [ebp-14]:00501864 E89734F0FF call 00404D00:00501869 0145E8 add dword ptr [ebp-18], eax
* Referenced by a (U)nconditional or (C)onditional Jump at Address:|:0050185F(C)|:0050186C 4E dec esi:0050186D 85F6 test esi, esi:0050186F 0F8559FFFFFF jne 005017CE -------循环
* Referenced by a (U)nconditional or (C)onditional Jump at Address:|:005017C8(C)|:00501875 807DE300 cmp byte ptr [ebp-1D], 00:00501879 0F84D9000000 je 00501958 -------比较标志,如果为0,则game over。:0050187F B201 mov dl, 01 -------以下是注册成功的代码,将名字和注册码存放到:00501881 A1D0444400 mov eax, dword ptr [004444D0] 注册表中,以便启动软件时检查是否注册了。:00501886 E8452DF4FF call 004445D0:0050188B 8BD8 mov ebx, eax:0050188D BA02000080 mov edx, 80000002:00501892 8BC3 mov eax, ebx:00501894 E8D72DF4FF call 00444670:00501899 B101 mov cl, 01
* Possible StringData Ref from Code Obj ->"Software\Microsoft\DirectX"----竟然将名字和注册码存放在这里???奇怪!!! |:0050189B BAC8195000 mov edx, 005019C8:005018A0 8BC3 mov eax, ebx:005018A2 E8312EF4FF call 004446D8:005018A7 84C0 test al, al:005018A9 741E je 005018C9:005018AB 8B4DF8 mov ecx, dword ptr [ebp-08]
* Possible StringData Ref from Code Obj ->"Label_N" -----这里放名字 |:005018AE BAEC195000 mov edx, 005019EC:005018B3 8BC3 mov eax, ebx:005018B5 E83A34F4FF call 00444CF4:005018BA 8B4DF4 mov ecx, dword ptr [ebp-0C]
* Possible StringData Ref from Code Obj ->"Label_K" -----这里放注册码 |:005018BD BAFC195000 mov edx, 005019FC:005018C2 8BC3 mov eax, ebx:005018C4 E82B34F4FF call 00444CF4---------------------------------------------------------username:ben007regcode:F1120744EF62
以下是我个人写的注册机,本人乃菜鸟一只,编程水平不高,程序若有不妥之处,请指正。------------------------------------------------------------------------------------------------------------------data segmentmsg1 db 'The keygen for the Quickchm v2.49,created by ben007.',0ah,0dh,'$'input_msg db 'Please input the name:$'inputname db 15,?,10 dup(?),0ah,0dh,'$'regcode db 25 dup(?)output_msg db 0dh,0ah,'The regcode is:$'regcode_ptr dw 0dat db 'F0E1'lastnum dw 80hdata endsstack segment para stack 'stack'db 10 dup(?)stack endscode segmentassume cs:code,ds:data,ss:stackstart:mov ax,data mov ds,ax mov ah,09h lea dx,msg1 int 21h lea dx,input_msg int 21h mov ah,0ah lea dx,inputname int 21h xor ax,ax xor dx,dx xor di,di mov ch,0 mov cl,inputname+1 lea bx,inputname+2 mov si,cx dec sinext: mov al,byte ptr[bx+si] cbw add ax,lastnum mov dl,0ffh div dl mov dl,ah push bx lea bx,dat mov al,byte ptr[bx+di] cbw xor ax,dx mov lastnum,ax call changetoascii inc di cmp di,3 ja pointtohead jmp lppointtohead:mov di,0lp: pop bx dec si loop next mov ah,09h lea dx,output_msg int 21h lea bx,regcode mov di,regcode_ptr mov byte ptr[bx+di],'$' mov dx,bx int 21h mov ah,4ch int 21hchangetoascii proc push bx push di mov bh,0 mov bl,10h div bl lea bx,regcode cmp al,0ah jae alplus37h add al,30h jmp next1alplus37h:add al,37hnext1:cmp ah,0ah jae ahplus37h add ah,30h jmp next2ahplus37h:add ah,37hnext2:mov di,regcode_ptr mov byte ptr[bx+di],al inc di mov byte ptr[bx+di],ah inc di mov regcode_ptr,di pop di pop bx retchangetoascii endpcode endsend start ben007 2003.2.15