quickchm v2.49

看雪資料發表於2015-11-15

軟體: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:ben007
regcode:F1120744EF62

以下是我個人寫的序號產生器,本人乃菜鳥一隻,程式設計水平不高,程式若有不妥之處,請指正。
------------------------------------------------------------------------------------------------------------------
data segment
msg1 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 0
dat db 'F0E1'
lastnum dw 80h
data ends
stack segment para  stack 'stack'
db 10 dup(?)
stack ends
code segment
assume cs:code,ds:data,ss:stack
start: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 si
next: 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 lp
pointtohead:mov di,0
lp:   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 21h
changetoascii 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 next1
alplus37h:add al,37h
next1:cmp ah,0ah
     jae ahplus37h
     add ah,30h
     jmp next2
ahplus37h:add ah,37h
next2: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
     ret
changetoascii endp
code ends
end start
                                                                     ben007
                                                                  2003.2.15