winamp全集分析教程!

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

winamp V2.02 
                   程式獵人
簡介:這個軟體不用多說了,大家一定對它很熟悉了。
追蹤:name:dahuilang
      RN:01234567
  以前追蹤過這個程式,當時追蹤的版本已經忘記了,但是那時記得追蹤它很簡單就將它追
蹤出來了,因為只要設bpx hmemcpy後攔下後跳躍到程式中就可以了,沒有想到這個版本的
程式無法跳躍到正常程式中,那麼如何追蹤這個程式呢?
  先使用反彙編軟體W32對它進行反彙編吧。
:0041C11C 50                      push eax
:0041C11D 52                      push edx

* Possible StringData Ref from Data Obj ->"RegisteredTo"
                                  |
:0041C11E 683C504300              push 0043503C
:0041C123 FF35A43F4400            push dword ptr [00443FA4]

* Reference To: KERNEL32.GetPrivateProfileStringA, Ord:0111h
                                  |
:0041C129 FF1578754400            Call dword ptr [00447578]
:0041C12F 389D00FDFFFF            cmp byte ptr [ebp+FFFFFD00], bl
:0041C135 7467                    je 0041C19E

* Possible StringData Ref from Data Obj ->"!!!"
                                  |
:0041C137 6838504300              push 00435038
:0041C13C 8D8500FDFFFF            lea eaxdword ptr [ebp+FFFFFD00]
:0041C142 50                      push eax
:0041C143 E888AC0000              call 00426DD0
:0041C148 83C408                  add esp, 00000008
:0041C14B 85C0                    test eaxeax
:0041C14D 744F                    je 0041C19E
:0041C14F C745FCFFFFFFFF          mov [ebp-04], FFFFFFFF
:0041C156 8D4DFC                  lea ecxdword ptr [ebp-04]
:0041C159 8818                    mov byte ptr [eax], bl
:0041C15B 51                      push ecx
:0041C15C 83C003                  add eax, 00000003

* Possible StringData Ref from Data Obj ->"%d"
                                  |
:0041C15F 68C0234300              push 004323C0
:0041C164 50                      push eax
:0041C165 E8A6AD0000              call 00426F10
:0041C16A 83C40C                  add esp, 0000000C
:0041C16D 8D8D00FDFFFF            lea ecxdword ptr [ebp+FFFFFD00]
:0041C173 51                      push ecx
:0041C174 E83E670000              call 004228B7
:0041C179 83C404                  add esp, 00000004
:0041C17C 3945FC                  cmp dword ptr [ebp-04], eax
:0041C17F 751D                    jne 0041C19E
:0041C181 50                      push eax
:0041C182 8D8D00FDFFFF            lea ecxdword ptr [ebp+FFFFFD00]
:0041C188 51                      push ecx
:0041C189 8D9500F9FFFF            lea edxdword ptr [ebp+FFFFF900]

* Possible StringData Ref from Data Obj ->"----- 授 權 給 :   %s (%d) -----"
                                  |
:0041C18F 68D8514300              push 004351D8
:0041C194 52                      push edx

* Reference To: USER32.wsprintfA, Ord:0262h
                                  |
:0041C195 FF1554774400            Call dword ptr [00447754]
:0041C19B 83C410                  add esp, 00000010

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0041C135(C), :0041C14D(C), :0041C17F(C)
|
:0041C19E 80BD00F9FFFF00          cmp byte ptr [ebp+FFFFF900], 00
:0041C1A5 7515                    jne 0041C1BC
   我首先看到了這個字串,"----- 授 權 給 :   %s (%d) -----",在它上面有一個比
較的地方,那麼程式一定是比較註冊碼或註冊旗標吧,GetPrivateProfileStringA大家看到
這個函式了吧,那麼這個函式是呼叫ini檔案的(通常是這樣的),現在使用filemon來檢視
一下程式呼叫了什麼ini檔案呢?
  檢視後發現程式呼叫了在winamp.exe同目錄下的winamp.ini檔案,這裡的內容如下:
[Winamp]
……
RegisteredTo=
  分析後可知,程式是這樣將註冊碼和名字放在一起的,為name!!!RN。這個格式,因為可
以從上面看到程式使用了!!!。好了,現在是設在
RegisteredTo=dahuilang!!!01234567,然後在下面
:0041C17C 3945FC                  cmp dword ptr [ebp-04], eax
設斷了,下bpx 0041C17C 後執行程式,結果發現在[ebp-04]=0012d687,而eax=4E0C8C6,
這樣就可以得到註冊碼了。
  RN=4E0C8C6=81840326
  這個就是dahuilang的註冊碼了。OK,這個版本的註冊碼破解就算結束了。

 
Winamp 2.04
啟動winamp.exe
1. 把開關於”wiamp”,選Shareware.
2. 按 Enter Registration Info
3. Name: Peter Reg#:78787878
4. Ctrl+N
5. bpx getdlgitemtexta
6. 按 x 返回 再輸入一個數學(我用”9”)
7. 又被攔阻,到一個”User32!Getdlgitemtexta
8. F10,22次
9. 你會看見 0167:0041EF81 PUSH EAX
10. 我用 d eax 一看有 Peter我字眼,我就定比較地方一定在不遠的地方。
11. 本人彙編不好,只是知道Push eax。大概是輸入字元到eax中。要輸入字元不
就是要用的名字,d了一下果然是。
12. 再往下看:
0167:0041EF82  CALL  0042218 (也許是比比較的地方)
0167:0041EF87  ADD   ESP,BYTE+04
0167:0041EF8A CMP EAX,ESI
0167:0041EF8C JNZ 0041EF97
13. 想一下剛才我破解winamp skin maker v1.2時,不是Sun Bird翻譯了v1.05資料中的
14. ”CMP EAX,ESI” 不是用d而用?
15. 試一試:
16. ? EAX
17. DEC=67972642(會不會是註冊碼?)
18. HEX=40d2e22
19. ? EDI
20. DEC=787878789(不是我剛才用的假碼?)
21. HEX=2ef61385
22. CMP EAX,ESI(不就是兩個記存器比較?要比較就一定要有註冊碼嗎?)
23. 好試一下,果然是。Yeah!
24. 我再試一下進入0167:0041EF82  CALL  0042218 (也許是比比較的地方)
25. 可能本人技術不行,只能白作工。
這才是本人自己破解的第一個軟體,多謝我的師傅和Sun Bird大哥幫助!
我是用手打的,0167:0041EF82  CALL  0042218
                 ……….
                  0167:0041EF8C JNZ 0041EF97
用trw2000 or soft-ice,能不能copy出來和抓圖?
說明一下這裡的破解過程以後出現Peter也就是我本人PeterChen!當然這篇也
不列外?

WinAmp V2.11的序號產生器制分析(一)(初學者必讀) 
    轉載本文請註明出處,並保持文章的完整性。本文不得用於任何商業場合,僅供學習和參考。 
作者: Fpc (感謝直接和間接提供幫助的所有朋友) 
目的: 分析序號產生器制 
工具: SI 4.05, Wdasm 8.93, Hedit 2.0 

軟體名稱:WinAmp Ver 2.11 
作    者: Nullsoft,Inc.      Apr 13,1999 
檔案大小:612KB 
編譯器  :VC++ 6.0 
授權方式:共享軟體 
使用平臺:Win95/98 
軟體簡介:著名的MP3播放器 

軟體來源:不清楚 
下載地址:請到各大專的下載網站自己查詢。 


    首先引用 WinAmp (WA) 關於中的一段:“Winamp is shareware, and may be previewed for 14 days. Continued use of Winamp after 14 days requires that you register it. winamp will neither cease functioning nor warn you of the end of the 14 day trial period. It is your responsibility to register.”。說的很明白,也是說到做到。共享軟體作成這樣,都不忍心去CRAK,它也的確沒有任何加密、干擾手段,真是不知該說些什麼。所以本文僅限於CRAK教學之用。 
    這個程式我看了三天(“當兵的,你不看我了”,“我都看了三天了”),其中有二天是在跟蹤。程式寫的很規範,也沒有加殼,所以需要的只是耐心。現在讓我給各位分析一下*COUGH* 


    1、 在WA選單中選擇“Nullsoft Winamp....”,顯示“About”對話方塊,選“Shareware”->“Enter Registration Info”進入註冊頁面。 
    2、 輸入: Name = Fpc ,Reg# = 123456 。“OK”竟未被啟用,應該是每輸入一次就作一次判斷。 
    3、 刪除Reg#中的‘6’,^D到SI中,下 bpx hmemcpy(萬能中斷,也是我最常用的); 
    4、 F5回來,在Reg#後加‘6’,立刻中斷到SI中,下 BD *阻斷,按F12 N次,發現始終在USER中,最後直接就返回到WA中,有點奇怪; 
    5、 還是刪除‘6’,^D到SI中,下 be hmemcpy 啟用中斷; 
    6、 再F5回來,仍輸入‘6’,立刻中斷到SI中。這次按F5,一次,二次,三次,返回到WA中。猜想第一次不知做什麼,第二次取 RegisterName(Rn),第三次是取InputedRegisterCode(Irc),OK; 
    7、 重複上面5、6兩步,不過這次在SI中按一次F5,N次F12,正確的回到WA領空,地址是 00401F28,向下看 @00401F2E是一個外部的 CALL呼叫(其實是GetDlgItemInt),是取 Irc的。再向下是一個 CallCmpJmp的程式段,這個 CALL 4252D1就是計算註冊碼的核心。要問我是怎麼知道的,就是:靜態分析+動態分析+嘗試+耐心。 


    上面簡要介紹了 SI動態攔截方式,若用 WDASM靜態分析需要查詢“Licensed to”字串,它不在 String資源中 :-( ,而是在 DATA中找到。分析的角度不同,得到的結果是類似的,我們當然要多瞭解和嘗試。這個串會在 @00401DA5 處找到,再向上還是對關鍵 Call 4252D1的呼叫。根據這一呼叫返回的註冊成功與否,程式用 wsprintfA列印不同的字串:“LICENSED TO:%s(%d)”或“UNREGISTERED SHAREWARE ......”,最後顯示在About對話方塊中。整個這一段程式碼是在選擇選單的第一項時執行,向上翻頁,記下的它的入口地址:401CCE。 
    關閉WA,開啟SI的 Symbol Loader,調入WA,然後 Load,這時在SI設斷:Bpx 401CCE。^D執行 WA。注意SI不會被啟用,除非你選擇了選單的第一項,下面藉助“程式”作分析,希望大家耐心看下去。 


;程式段(1),在顯示“About”時執行 

* Referenced by a CALL at Addresses: 
|:00401B9B  , :00401CB1  

:00401CCE 55                      push ebp 
:00401CCF 8BEC                    mov ebpesp 
:00401CD1 81EC00060000            sub esp, 00000600 
:00401CD7 A050914400              mov albyte ptr [00449150]        <== 0->al 
:00401CDC 53                      push ebx 
:00401CDD 56                      push esi 
:00401CDE 57                      push edi 
:00401CDF 888500FAFFFF            mov byte ptr [ebp+FFFFFA00], al        <== Ebp-600=6DC6F8-600 
:00401CE5 B9FF000000              mov ecx, 000000FF 
:00401CEA 33C0                    xor eaxeax 
:00401CEC 8DBD01FAFFFF            lea edidword ptr [ebp+FFFFFA01]    <== 準備將記憶體清0 
:00401CF2 F3                      repz 
:00401CF3 AB                      stosd 
:00401CF4 66AB                    stosw 

* Reference To: KERNEL32.GetPrivateProfileStringA, Ord:013Ah 
                                  | 
:00401CF6 8B3534E14300            mov esidword ptr [0043E134]        <== 準備功能呼叫 

* Possible StringData Ref from Data Obj ->"winamp.ini"            <== 檔名 
                                  | 
:00401CFC 687C214400              push 0044217C 
:00401D01 AA                      stosb                        <== 到此將Ebp-600到Ebp-200清為0 
:00401D02 8D8500FEFFFF            lea eaxdword ptr [ebp+FFFFFE00]    <== 緩衝區1 首址(控制程式碼?) 
:00401D08 6800020000              push 00000200                    <== 緩衝區長度為200 
:00401D0D BB50914400              mov ebx, 00449150 
:00401D12 50                      push eax 

* Possible StringData Ref from Data Obj ->"RegisteredTo" 
                                  | 
:00401D13 BF6C214400              mov edi, 0044216C            <== 讀內容 
:00401D18 53                      push ebx 
:00401D19 57                      push edi 

* Possible StringData Ref from Data Obj ->"WinampRegInfo" 
                                  | 
:00401D1A 685C214400              push 0044215C                <== 小節名 
:00401D1F FFD6                    call esi 

    這個Call將註冊資訊(RI)讀到 Ebp-200處,後面以0補足至 Ebp。當然,WA沒有註冊時,RI是不存在的,自己輸入的方式是: 
    在WIN9X系統目錄下,找“winamp.ini”檔案並開啟(什麼,沒有?不會自己生成一個!),新增[WinampRegInfo]小節,輸入RI。我的“winamp.ini”相關內容如下: 

[WinampRegInfo] 
RegisteredTo=Fpc!!!123456 

注意RI中,Fpc是Rn,123456是Irc,中間的“!!!”是必須的,在下面的分析中你會找到原因。 


:00401D21 80BD00FEFFFF00          cmp byte ptr [ebp+FFFFFE00], 00    <== 檢查RI是否為空 
:00401D28 7524                    jne 00401D4E                <== 正確則向下跳 
:00401D2A 68A0794500              push 004579A0 
:00401D2F 8D8500FEFFFF            lea eaxdword ptr [ebp+FFFFFE00] 
:00401D35 6800020000              push 00000200 
:00401D3A 50                      push eax 
:00401D3B 53                      push ebx 
:00401D3C 57                      push edi 
:00401D3D FF35E0594500            push dword ptr [004559E0] 
:00401D43 FFD6                    call esi                <== 不用關心是在讀什麼 
:00401D45 80BD00FEFFFF00          cmp byte ptr [ebp+FFFFFE00], 00 
:00401D4C 7466                    je 00401DB4                <== 這裡千萬不能去 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:00401D28(C) 

:00401D4E 8D8500FEFFFF            lea eaxdword ptr [ebp+FFFFFE00]<== 緩衝區1 首址 

* Possible StringData Ref from Data Obj ->"!!!" 
                                  | 
:00401D54 6858214400              push 00442158                <== 準備檢查RI中是否含有"!!!" 
:00401D59 50                      push eax 
:00401D5A E8F1330300              call 00435150                <== 這個Call有意思,錯誤則eax=0,正確則eax指向RI的!!!123456,我這裡返回值是6DC4FB 
:00401D5F 59                      pop ecx                    <== 對這個Call的分析見(二) 
:00401D60 85C0                    test eaxeax 
:00401D62 59                      pop ecx 
:00401D63 744F                    je 00401DB4                <== Eax=0就去死 
:00401D65 802000                  and byte ptr [eax], 00        <== 使得Rn以'\0'結束 
:00401D68 33F6                    xor esiesi 
:00401D6A 83C003                  add eax, 00000003            <== Eax指向Irc:123456 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:00401D84(U) 

:00401D6D 8A08                    mov clbyte ptr [eax]        <== 取一個字元 
:00401D6F 80F930                  cmp cl, 30                <== 數字為有效字元,非數字表示完成 
:00401D72 7C12                    jl 00401D86 
:00401D74 80F939                  cmp cl, 39 
:00401D77 7F0D                    jg 00401D86 
:00401D79 0FBEC9                  movsx ecxcl                <== Ecx中無用位清0 
:00401D7C 8D14B6                  lea edxdword ptr [esi+4*esi]    <= Edx=5*Esi 
:00401D7F 40                      inc eax                    <== Edx的初始值為0,這三條指令將字串變為數字 
:00401D80 8D7451D0                lea esidword ptr [ecx+2*edx-30]    <= 很有意思 
:00401D84 EBE7                    jmp 00401D6D 


  這一段以C來表示: 

  char Irc[6]="123456"        /* 當然註冊碼不止6位    */ 
  long Temp=0; 
  int i; 

  for( i=0; i<6; i++) 
  { 
      if( !isdigit( Irc[i] ) ) 
        break; 
    Temp*=10; 
    Temp+=Irc[i]-'0'; 
  } 


* Referenced by a (U)nconditional or (C)onditional Jump at Addresses: 
|:00401D72(C), :00401D77(C) 

:00401D86 8D8500FEFFFF            lea eaxdword ptr [ebp+FFFFFE00]<== Eax指向Rn 
:00401D8C 50                      push eax 
:00401D8D E83F350200              call 004252D1                <== !! 關鍵Call,由Rn計算得出Rc,儲存在Eax。具體分析請看(三) 
:00401D92 3BC6                    cmp eaxesi                <== 比較Rc與Irc 
:00401D94 59                      pop ecx 
:00401D95 751D                    jne 00401DB4                <== 不相等則GAME OVER,大家將此處NOP掉,看會發生什麼有趣的事情 
:00401D97 50                      push eax 
:00401D98 8D8500FEFFFF            lea eaxdword ptr [ebp+FFFFFE00] 
:00401D9E 50                      push eax 
:00401D9F 8D8500FAFFFF            lea eaxdword ptr [ebp+FFFFFA00] 

* Possible StringData Ref from Data Obj ->"----- LICENSED TO: %s (%d) -----" 
                                  | 
:00401DA5 6834214400              push 00442134 
:00401DAA 50                      push eax 

* Reference To: USER32.wsprintfA, Ord:02ACh 
                                  | 
:00401DAB FF1568E34300            Call dword ptr [0043E368]        <== 列印授權資訊 
:00401DB1 83C410                  add esp, 00000010 

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses: 
|:00401D4C(C), :00401D63(C), :00401D95(C) 

:00401DB4 80BD00FAFFFF00          cmp byte ptr [ebp+FFFFFA00], 00 
:00401DBB 5F                      pop edi 
:00401DBC 5E                      pop esi 
:00401DBD 5B                      pop ebx 
:00401DBE 751C                    jne 00401DDC 
:00401DC0 6A00                    push 00000000 
:00401DC2 6A00                    push 00000000 

* Possible Reference to String Resource ID=00018: "UNREGISTERED SHAREWARE VERSION - PLEASE REGISTER" 
                                  | 
:00401DC4 6A12                    push 00000012 
:00401DC6 E8C5A10200              call 0042BF90 
:00401DCB 50                      push eax 
:00401DCC 8D8500FAFFFF            lea eaxdword ptr [ebp+FFFFFA00] 
:00401DD2 50                      push eax 

* Reference To: USER32.wsprintfA, Ord:02ACh 
                                  | 
:00401DD3 FF1568E34300            Call dword ptr [0043E368]        <== 列印未授權資訊 
:00401DD9 83C414                  add esp, 00000014            <== 向下很長一段與分析無關 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:00401DBE(C) 

:00401DDC 8D8500FAFFFF            lea eaxdword ptr [ebp+FFFFFA00] 
:00401DE2 50                      push eax 

* Possible Reference to Dialog: DialogID_009C, CONTROL_ID:0483, "License" 
                                  | 
:00401DE3 6883040000              push 00000483 
:00401DE8 FF7508                  push [ebp+08] 

* Reference To: USER32.SetDlgItemTextA, Ord:022Ch 
                                  | 
:00401DEB FF1534E34300            Call dword ptr [0043E334] 
:00401DF1 C9                      leave 
:00401DF2 C3                      ret 

......... 


* Possible StringData Ref from Data Obj ->"!!!" 
                                  | 
:00401EAC 6858214400              push 00442158 
:00401EB1 50                      push eax 
:00401EB2 E829330300              call 004351E0 
:00401EB7 59                      pop ecx 
:00401EB8 8D8580FBFFFF            lea eaxdword ptr [ebp+FFFFFB80] 
:00401EBE 59                      pop ecx 
:00401EBF 57                      push edi 
:00401EC0 50                      push eax 
:00401EC1 E8FA330300              call 004352C0 
:00401EC6 59                      pop ecx 
:00401EC7 8D840580FBFFFF          lea eaxdword ptr [ebp+eax-00000480] 
:00401ECE 50                      push eax 
:00401ECF 53                      push ebx 
:00401ED0 FF7508                  push [ebp+08] 
:00401ED3 FFD6                    call esi 
:00401ED5 8D8580FBFFFF            lea eaxdword ptr [ebp+FFFFFB80] 

* Possible StringData Ref from Data Obj ->"winamp.ini" 
                                  | 
:00401EDB 687C214400              push 0044217C 
:00401EE0 50                      push eax 

* Possible StringData Ref from Data Obj ->"RegisteredTo" 
                                  | 
:00401EE1 686C214400              push 0044216C 

* Possible StringData Ref from Data Obj ->"WinampRegInfo" 
                                  | 
:00401EE6 685C214400              push 0044215C 

* Reference To: KERNEL32.WritePrivateProfileStringA, Ord:02E5h 
                                  | 
:00401EEB FF1530E14300            Call dword ptr [0043E130]            <== 這一段會在點選“OK”時執行,向ini檔案寫RI 

* Possible Reference to String Resource ID=00001: "You must first exit Winamp before uninstalling." 
                                  | 
:00401EF1 6A01                    push 00000001 
:00401EF3 FF7508                  push [ebp+08] 

* Reference To: USER32.EndDialog, Ord:00B9h 
                                  | 
:00401EF6 FF151CE44300            Call dword ptr [0043E41C] 
:00401EFC 8B7D10                  mov edidword ptr [ebp+10] 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:00401E6C(C) 

* Possible Reference to Dialog: DialogID_00BF, CONTROL_ID:048B, "" 
                                  | 
:00401EFF B88B040000              mov eax, 0000048B 
:00401F04 663BF8                  cmp diax 
:00401F07 7405                    je 00401F0E 
:00401F09 663BFB                  cmp dibx 
:00401F0C 7552                    jne 00401F60 

對關鍵 Call 004252D1的分析請見(三) 
WinAmp V2.11的序號產生器制分析(二)(初學者必讀) 
    轉載本文請註明出處,並保持文章的完整性。本文不得用於任何商業場合,僅供學習和參考。 
作者: Fpc (感謝直接和間接提供幫助的所有朋友) 
目的: 分析序號產生器制 
工具: SI 4.05, Wdasm 8.93, Hedit 2.0 


    程式段(2),輸入註冊資訊的每次輸入時執行:根據Rn計算Rc,若Irc=Rc則啟用“OK”表示可以將RI寫入“winamp.ini”檔案中 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:00401F07(C) 

:00401F0E C1EF10                  shr edi, 10 
:00401F11 6681FF0003              cmp di, 0300 
:00401F16 7548                    jne 00401F60 
:00401F18 8B7D08                  mov edidword ptr [ebp+08] 
:00401F1B 8D4D80                  lea ecxdword ptr [ebp-80] 
:00401F1E 6880000000              push 00000080 
:00401F23 51                      push ecx 
:00401F24 50                      push eax 
:00401F25 57                      push edi 
:00401F26 FFD6                    call esi                <== 讀Name文字框,將取得的Rn儲存在 Ebp-80處 
:00401F28 6A00                    push 00000000 
:00401F2A 6A00                    push 00000000 
:00401F2C 53                      push ebx 
:00401F2D 57                      push edi 

* Reference To: USER32.GetDlgItemInt, Ord:0103h 
                                  | 
:00401F2E FF152CE34300            Call dword ptr [0043E32C]        <== 讀Reg#文字框,返回值在 Eax中 
:00401F34 8BF0                    mov esieax 
:00401F36 8D4580                  lea eaxdword ptr [ebp-80] 
:00401F39 50                      push eax 
:00401F3A E892330200              call 004252D1                <== !! 關鍵Call,由Rn計算得出Rc,儲存在Eax。具體分析請看(三) 
:00401F3F 3BC6                    cmp eaxesi                <== 比較Rc與Irc 
:00401F41 59                      pop ecx 
:00401F42 750A                    jne 00401F4E 
:00401F44 807D8000                cmp byte ptr [ebp-80], 00 
:00401F48 7404                    je 00401F4E 

* Possible Reference to String Resource ID=00001: "You must first exit Winamp before uninstalling." 
                                  | 
:00401F4A 6A01                    push 00000001                <== “OK”為Enable 
:00401F4C EB02                    jmp 00401F50 

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses: 
|:00401F42(C), :00401F48(C) 

:00401F4E 6A00                    push 00000000                <== “OK”為Disable 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:00401F4C(U) 

* Possible Reference to String Resource ID=00001: "You must first exit Winamp before uninstalling." 
                                  | 
:00401F50 6A01                    push 00000001 
:00401F52 57                      push edi 

* Reference To: USER32.GetDlgItem, Ord:0102h 
                                  | 
:00401F53 FF1574E34300            Call dword ptr [0043E374] 
:00401F59 50                      push eax 

* Reference To: USER32.EnableWindow, Ord:00B7h 
                                  | 
:00401F5A FF1530E34300            Call dword ptr [0043E330]        <== 修改按鈕狀態 

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses: 
|:00401E43(C), :00401F0C(C), :00401F16(C) 

:00401F60 33C0                    xor eaxeax 
:00401F62 5B                      pop ebx 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:00401E36(U) 

:00401F63 5F                      pop edi 
:00401F64 5E                      pop esi 
:00401F65 C9                      leave 
:00401F66 C21000                  ret 0010 


    Call 435150 比較在RI中是否含有"!!!" 

入口:Ecx指向"!!!"+'\0' 
出口:錯誤則eax=0,正確則eax指向RI的!!!123456, 

* Referenced by a CALL at Addresses: 
|    有N處呼叫,我用了 Echo y|Format C:/u 

:00435150 8B4C2408                mov ecxdword ptr [esp+08]    <== Ecx=442158,指向"!!!"+'\0' 
:00435154 57                      push edi 
:00435155 53                      push ebx 
:00435156 56                      push esi 
:00435157 8A11                    mov dlbyte ptr [ecx]        <== Dl取得第一個'!' 
:00435159 8B7C2410                mov edidword ptr [esp+10]    <== Edi=Ebp-200=6DC4F8,即RI首址 
:0043515D 84D2                    test dldl 
:0043515F 7469                    je 004351CA                <== Dl=0證明比較完成,跳下去準備返回(怎麼可能?!) 
:00435161 8A7101                  mov dhbyte ptr [ecx+01]        <== 第二個'!'到Dh 
:00435164 84F6                    test dhdh 
:00435166 744F                    je 004351B7 

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses: 
|:004351A2(C), :004351B5(U) 

:00435168 8BF7                    mov esiedi 
:0043516A 8B4C2414                mov ecxdword ptr [esp+14]    <== Ecx=442158,指向"!!!"+'\0' 
:0043516E 8A07                    mov albyte ptr [edi
:00435170 46                      inc esi 
:00435171 38D0                    cmp aldl                <== 看Al是否為'!' 
:00435173 7415                    je 0043518A 
:00435175 84C0                    test alal 
:00435177 740B                    je 00435184                <== Al為空則失敗 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:00435182(C) 

:00435179 8A06                    mov albyte ptr [esi
:0043517B 46                      inc esi 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:0043518F(C) 

:0043517C 38D0                    cmp aldl 
:0043517E 740A                    je 0043518A                <== 向下跳檢查RI中是否含三個'!' 
:00435180 84C0                    test alal 
:00435182 75F5                    jne 00435179                <== 直到Al取到'!';若不跳則說明在遇到"!!!"之前,RI已經結束(RI中不含!!!),失敗 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:00435177(C) 

:00435184 5E                      pop esi 
:00435185 5B                      pop ebx 
:00435186 5F                      pop edi 
:00435187 33C0                    xor eaxeax 
:00435189 C3                      ret 


* Referenced by a (U)nconditional or (C)onditional Jump at Addresses: 
|:00435173(C), :0043517E(C) 

:0043518A 8A06                    mov albyte ptr [esi]        <== 從RI中!之後再讀一位元組 
:0043518C 46                      inc esi 
:0043518D 38F0                    cmp aldh 
:0043518F 75EB                    jne 0043517C                <== 若不等, 則在Rn中含'!' 
:00435191 8D7EFF                  lea edidword ptr [esi-01] 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:004351B3(C) 

:00435194 8A6102                  mov ahbyte ptr [ecx+02] 
:00435197 84E4                    test ahah 
:00435199 7428                    je 004351C3 
:0043519B 8A06                    mov albyte ptr [esi]        <== 從Rn中取第三個'!' 
:0043519D 83C602                  add esi, 00000002 
:004351A0 38E0                    cmp alah 
:004351A2 75C4                    jne 00435168 
:004351A4 8A4103                  mov albyte ptr [ecx+03]        <== Al應取到0 
:004351A7 84C0                    test alal 
:004351A9 7418                    je 004351C3                <== Al為空表示正常結束 
:004351AB 8A66FF                  mov ahbyte ptr [esi-01] 
:004351AE 83C102                  add ecx, 00000002            <== 若正確,這裡不會被執行 
:004351B1 38E0                    cmp alah 
:004351B3 74DF                    je 00435194 
:004351B5 EBB1                    jmp 00435168 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:00435166(C) 

:004351B7 33C0                    xor eaxeax                <== 跳到這裡則RI形式錯誤 
:004351B9 5E                      pop esi 
:004351BA 5B                      pop ebx 
:004351BB 5F                      pop edi 
:004351BC 8AC2                    mov aldl 
:004351BE E933210000              jmp 004372F6 

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses: 
|:00435199(C), :004351A9(C) 

:004351C3 8D47FF                  lea eaxdword ptr [edi-01]    <== 正確的出口,我是這裡返回的 
:004351C6 5E                      pop esi 
:004351C7 5B                      pop ebx 
:004351C8 5F                      pop edi 
:004351C9 C3                      ret 


* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:0043515F(C) 

:004351CA 8BC7                    mov eaxedi                <== 也是正確出口 
:004351CC 5E                      pop esi 
:004351CD 5B                      pop ebx 
:004351CE 5F                      pop edi 
:004351CF C3                      ret 

上面跳來跳去的有些亂(上跳下跳,左跳右跳,原來每個條件都不一般),不知大家看懂沒有,找原始碼跟一跟就明白啦! 

對關鍵 Call 004252D1的分析請見(三) 

WinAmp V2.11的序號產生器制分析(三)(初學者必讀) 
    轉載本文請註明出處,並保持文章的完整性。本文不得用於任何商業場合,僅供學習和參考。 
作者: Fpc (感謝直接和間接提供幫助的所有朋友) 
目的: 分析序號產生器制 
工具: SI 4.05, Wdasm 8.93, Hedit 2.0 

    下面是CALL  004252D1的核心程式,00401D8D是開啟選單“Nullsoft WinAmp...”(即“關於”)時的呼叫,第二次是輸入註冊資訊時的呼叫,第三次我也不清楚。 
這段程式負責由RegisterName(Rn)計算出RegisterCode(Rc),放到Eax中。 

* Referenced by a CALL at Addresses: 
|:00401D8D  , :00401F3A  , :004254FE  

:004252D1 55                      push ebp 
:004252D2 8BEC                    mov ebpesp 
:004252D4 81EC00010000            sub esp, 00000100 
:004252DA 53                      push ebx 
:004252DB 56                      push esi 
:004252DC 57                      push edi 

:004252DD 6A3F                    push 0000003F 
:004252DF 33DB                    xor ebxebx 
:004252E1 59                      pop ecx                <== Ecx=3F 
:004252E2 209D00FFFFFF            and byte ptr [ebp+FFFFFF00], bl 
:004252E8 33C0                    xor eaxeax 
:004252EA 8DBD01FFFFFF            lea edidword ptr [ebp+FFFFFF01] 
:004252F0 6800010000              push 00000100 
:004252F5 F3                      repz 
:004252F6 AB                      stosd 
:004252F7 FF7508                  push [ebp+08] 
:004252FA 66AB                    stosw 
:004252FC AA                      stosb                    <== 從4252E2到此將 Ebp-100到Ebp處清0 
:004252FD 8D8500FFFFFF            lea eaxdword ptr [ebp+FFFFFF00] 
:00425303 50                      push eax 
:00425304 E8E7010100              call 004354F0                <== 這次呼叫將Rn複製到Ebp-100,見分析。 
:00425309 83C40C                  add esp, 0000000C 
:0042530C 389D00FFFFFF            cmp byte ptr [ebp+FFFFFF00], bl 
:00425312 7428                    je 0042533C 
:00425314 8DB500FFFFFF            lea esidword ptr [ebp+FFFFFF00] 
:0042531A 33FF                    xor ediedi 
                                    <== 至此,入口: Edi=Ebx=0 
* Referenced by a (U)nconditional or (C)onditional Jump at Address:    <== !! 這個迴圈計算中間結果,很關鍵 
|:0042533A(C) 

:0042531C 56                      push esi 
:0042531D E861000000              call 00425383                <== 從Esi開始取4位元組,作運算,結果在Eax中。請看下面 
:00425322 59                      pop ecx 
:00425323 8BCF                    mov ecxedi                <== 隨著迴圈,Edi=0、2,4,6,8,A... 
:00425325 83E10F                  and ecx, 0000000F 
:00425328 D3E0                    shl eaxcl                <== 左移位 
:0042532A 85C0                    test eaxeax 
:0042532C 7C04                    jl 00425332                <== 是負數則向下跳 
:0042532E 03D8                    add ebxeax                <== 很少被執行到 
:00425330 EB02                    jmp 00425334                <== 迴圈次數為Rn長度 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:0042532C(C) 

:00425332 2BD8                    sub ebxeax                <== Ebx放累加結果 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:00425330(U) 

:00425334 47                      inc edi 
:00425335 47                      inc edi                <== Edi=Edi+2 
:00425336 46                      inc esi                <== Esi取Rn的下一個位元組 
:00425337 803E00                  cmp byte ptr [esi], 00    <== 檢查是否結束 
:0042533A 75E0                    jne 0042531C            <== 未完則繼續,迴圈次數為Rn長度 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:00425312(C) 

:0042533C 8BC3                    mov eaxebx                <== 中間結果送 Eax 
:0042533E B940420F00              mov ecx, 000F4240            <== Ecx= 1,000,000(Dec
:00425343 6BC025                  imul eax, 00000025            <== EaxEax*37(Dec
:00425346 99                      cdq 
:00425347 F7F9                    idiv ecx 
:00425349 8BCA                    mov ecxedx                <== 餘數送Ecx儲存,很重要(我跟到下面要返回的語句,向回找了半天才找到) 
:0042534B 8BF2                    mov esiedx                <== 餘數送Esi,到 425352繼續處理 
:0042534D 6BC964                  imul ecx, 00000064            <== Ecx=Ecx*100(Dec
:00425350 33FF                    xor ediedi 

* Referenced by a (U)nconditional or (C)onditional Jump at Address:    <== 到 425369的這個迴圈會被執行幾次 
|:00425369(U) 

:00425352 85F6                    test esiesi                <== Esi是否為0 
:00425354 7415                    je 0042536B                <== 是則跳出這一迴圈 
:00425356 8BC6                    mov eaxesi            <== Esi->Eax,作處理準備 
                                  
:00425358 6A64                    push 00000064 
:0042535A 99                      cdq 
:0042535B 5B                      pop ebx             
:0042535C F7FB                    idiv ebx            <== 被100(Dec)除 
:0042535E 8BC6                    mov eaxesi 
:00425360 53                      push ebx 
:00425361 5E                      pop esi 
:00425362 03FA                    add ediedx            <== Edi放餘數累加和 
:00425364 99                      cdq 
:00425365 F7FE                    idiv esi 
:00425367 8BF0                    mov esieax            <== 商被送到Esi 
:00425369 EBE7                    jmp 00425352 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:00425354(C) 

:0042536B 8D047F                  lea eaxdword ptr [edi+2*edi]    <== Eax=Edi*3 

                                  | 
:0042536E 6A04                    push 00000004 
:00425370 99                      cdq 
:00425371 5E                      pop esi 
:00425372 F7FE                    idiv esi                <== 再被4除 

                                  | 
:00425374 6A64                    push 00000064 
:00425376 5E                      pop esi 
:00425377 5F                      pop edi 
:00425378 99                      cdq 
:00425379 F7FE                    idiv esi                <== 再被100除 
:0042537B 5E                      pop esi 
:0042537C 5B                      pop ebx 
:0042537D 8BC2                    mov eaxedx                <== 餘數送 Eax 
:0042537F 03C1                    add eaxecx                <== EaxEax+Ecx (看42534D),這是最終結果 
:00425381 C9                      leave 
:00425382 C3                      ret 


* Referenced by a CALL at Address: 
|:0042531D  

:00425383 55                      push ebp 
:00425384 8BEC                    mov ebpesp 
:00425386 51                      push ecx 
:00425387 8065FC00                and byte ptr [ebp-04], 00 
:0042538B 57                      push edi 
:0042538C 33C0                    xor eaxeax 
:0042538E 8D7DFD                  lea edidword ptr [ebp-03] 
:00425391 66AB                    stosw 
:00425393 6A04                    push 00000004 
:00425395 FF7508                  push [ebp+08]                <== 源字串地址壓棧 
:00425398 AA                      stosb                    <== 從Ebp-04處建立了4位元組的臨時緩衝區 

:00425399 8D45FC                  lea eaxdword ptr [ebp-04]        <== 
:0042539C 50                      push eax                <== 目標區地址壓棧 
:0042539D E84E010100              call 004354F0                <== 又一次對這個CALL的呼叫,不過這次是從Esi處取 4 位元組到臨時緩衝區,我在這裡轉的頭暈,大家可以看一看。 
:004253A2 0FB645FE                movzx eaxbyte ptr [ebp-02]        <== 相當於 al=[Esi+2],高位是0,下同 
:004253A6 0FB64DFC                movzx ecxbyte ptr [ebp-04]        <==        cl=[Esi
:004253AA 0FB655FD                movzx edxbyte ptr [ebp-03]        <==        dl=[Esi+1] 
:004253AE 33C1                    xor eaxecx            <== Al^=Cl 
:004253B0 83C40C                  add esp, 0000000C 
:004253B3 0FB64DFF                movzx ecxbyte ptr [ebp-01]        <==        cl=[Esi+3] 
:004253B7 F7D1                    not ecx                <== !Ecx 
:004253B9 F7D0                    not eax                <== !Eax 
:004253BB 33CA                    xor ecxedx            <== Cl^=Dl 
:004253BD 5F                      pop edi 
:004253BE 03C1                    add eaxecx            <== Eax+=Ecx 
:004253C0 C9                      leave 
:004253C1 C3                      ret 


    call 004354F0,這個CALL是從源字串區向目標緩衝區複製字串,長度由呼叫前的壓棧決定;出口:將目標緩衝區地址送 Eax。 
裡面跳轉太多,看不明白關係不大,它沒有別的功能。 


* Referenced by a CALL at Addresses: 
|:00403EF8  , :00410333  , :00410517  , :00425304  , :0042539D  
|:00425B3F  , :00425BF1  , :004294AF  , :0042951D  , :00439DCA  

:004354F0 8B4C240C                mov ecxdword ptr [esp+0C]        <== 呼叫此Call前的倒數第三次Push,為100或4 
:004354F4 57                      push edi 
:004354F5 85C9                    test ecxecx 
:004354F7 747A                    je 00435573                <== 兩處呼叫都不跳 
:004354F9 56                      push esi 
:004354FA 53                      push ebx 
:004354FB 8BD9                    mov ebxecx                <== 
:004354FD 8B742414                mov esidword ptr [esp+14]        <== !! Esi為源字串地址,注意 @42539D呼叫時,每次都有Esi=Esi+1 

:00435501 F7C603000000            test esi, 00000003            <== Esi低位元組是否為03 
:00435507 8B7C2410                mov edidword ptr [esp+10]        <== !! 呼叫此Call前的最後一次Push,均為Eax,是目標地址 
:0043550B 7507                    jne 00435514                <== 大多數情況下不會跳 
:0043550D C1E902                  shr ecx, 02 
:00435510 756F                    jne 00435581                <== 會跳走 
:00435512 EB21                    jmp 00435535 

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses: 
|:0043550B(C), :00435527(C) 

:00435514 8A06                    mov albyte ptr [esi
:00435516 46                      inc esi 
:00435517 8807                    mov byte ptr [edi], al 
:00435519 47                      inc edi 
:0043551A 49                      dec ecx 
:0043551B 7425                    je 00435542 
:0043551D 84C0                    test alal 
:0043551F 7429                    je 0043554A 

* Possible Reference to String Resource ID=00003: "Uninstall canceled." 
                                  | 
:00435521 F7C603000000            test esi, 00000003 
:00435527 75EB                    jne 00435514 
:00435529 8BD9                    mov ebxecx 
:0043552B C1E902                  shr ecx, 02 
:0043552E 7551                    jne 00435581 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:0043557F(C) 

:00435530 83E303                  and ebx, 00000003 
:00435533 740D                    je 00435542 

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses: 
|:00435512(U), :00435540(C) 

:00435535 8A06                    mov albyte ptr [esi
:00435537 46                      inc esi 
:00435538 8807                    mov byte ptr [edi], al 
:0043553A 47                      inc edi 
:0043553B 84C0                    test alal 
:0043553D 742F                    je 0043556E 
:0043553F 4B                      dec ebx 
:00435540 75F3                    jne 00435535 

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses: 
|:0043551B(C), :00435533(C) 

:00435542 8B442410                mov eaxdword ptr [esp+10] 
:00435546 5B                      pop ebx 
:00435547 5E                      pop esi 
:00435548 5F                      pop edi 
:00435549 C3                      ret 


* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:0043551F(C) 

:0043554A F7C703000000            test edi, 00000003 
:00435550 7412                    je 00435564 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:00435562(C) 

:00435552 8807                    mov byte ptr [edi], al 
:00435554 47                      inc edi 
:00435555 49                      dec ecx 
:00435556 0F848A000000            je 004355E6 
:0043555C F7C703000000            test edi, 00000003 
:00435562 75EE                    jne 00435552 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:00435550(C) 

:00435564 8BD9                    mov ebxecx 
:00435566 C1E902                  shr ecx, 02 
:00435569 756C                    jne 004355D7 

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses: 
|:0043556F(C), :004355E4(C) 

:0043556B 8807                    mov byte ptr [edi], al 
:0043556D 47                      inc edi 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:0043553D(C) 

:0043556E 4B                      dec ebx 
:0043556F 75FA                    jne 0043556B 
:00435571 5B                      pop ebx 
:00435572 5E                      pop esi 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:004354F7(C) 

:00435573 8B442408                mov eaxdword ptr [esp+08] 
:00435577 5F                      pop edi 
:00435578 C3                      ret 


* Referenced by a (U)nconditional or (C)onditional Jump at Addresses: 
|:00435599(C), :004355B1(C) 

:00435579 8917                    mov dword ptr [edi], edx 
:0043557B 83C704                  add edi, 00000004 
:0043557E 49                      dec ecx 
:0043557F 74AF                    je 00435530                <== 處理完成則跳上去 

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:     
        <== 從這裡到返回處是將字串從[Esi]處複製到[Edi],長度與Ecx有關,不夠則在[Edi]後面補0 
|:00435510(C), :0043552E(C) 

:00435581 BAFFFEFE7E              mov edx, 7EFEFEFF        <-- 
:00435586 8B06                    mov eaxdword ptr [esi]    <-- 
:00435588 03D0                    add edxeax 
:0043558A 83F0FF                  xor eax, FFFFFFFF 
:0043558D 33C2                    xor eaxedx 
:0043558F 8B16                    mov edxdword ptr [esi
:00435591 83C604                  add esi, 00000004 
:00435594 A900010181              test eax, 81010100        <-- 檢查 Eax取到的是否為0,手法很是怪異?! 
:00435599 74DE                    je 00435579 
:0043559B 84D2                    test dldl 
:0043559D 742C                    je 004355CB 
:0043559F 84F6                    test dhdh 
:004355A1 741E                    je 004355C1 
:004355A3 F7C20000FF00            test edx, 00FF0000 
:004355A9 740C                    je 004355B7 
:004355AB F7C2000000FF            test edx, FF000000 
:004355B1 75C6                    jne 00435579                <== 跳走表示edx取到的各位元組均為非0 
:004355B3 8917                    mov dword ptr [edi], edx 
:004355B5 EB18                    jmp 004355CF 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:004355A9(C) 

:004355B7 81E2FFFF0000            and edx, 0000FFFF 
:004355BD 8917                    mov dword ptr [edi], edx 
:004355BF EB0E                    jmp 004355CF 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:004355A1(C) 

:004355C1 81E2FF000000            and edx, 000000FF 
:004355C7 8917                    mov dword ptr [edi], edx 
:004355C9 EB04                    jmp 004355CF 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:0043559D(C) 

:004355CB 33D2                    xor edxedx 
:004355CD 8917                    mov dword ptr [edi], edx 

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses: 
|:004355B5(U), :004355BF(U), :004355C9(U) 

:004355CF 83C704                  add edi, 00000004 
:004355D2 33C0                    xor eaxeax 
:004355D4 49                      dec ecx 
:004355D5 740A                    je 004355E1 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:00435569(C) 

:004355D7 33C0                    xor eaxeax 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:004355DF(C) 

:004355D9 8907                    mov dword ptr [edi], eax 
:004355DB 83C704                  add edi, 00000004 
:004355DE 49                      dec ecx 
:004355DF 75F8                    jne 004355D9 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:004355D5(C) 

:004355E1 83E303                  and ebx, 00000003 
:004355E4 7585                    jne 0043556B 

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 
|:00435556(C) 

:004355E6 8B442410                mov eaxdword ptr [esp+10] 
:004355EA 5B                      pop ebx 
:004355EB 5E                      pop esi 
:004355EC 5F                      pop edi 
:004355ED C3                      ret 

序號產生器 
    轉載本文請註明出處,並保持文章的完整性。本文不得用於任何商業場合,僅供學習和參考。 
作者: Fpc (感謝直接和間接提供幫助的所有朋友) 
工具: BC++ Builder 5.0(對ASM的相容性非常不錯,可惜我用的不熟) 

    寫教程真是很累的一件事,想起眾多前輩的妙文,就知道他們付出了什麼。不過在這過程中是學到了一些,尤其是那些自己原來不太明白之處,要去想清楚,否則錯誤連連,走在街上肯定被痛扁。有意把這一篇寫的很羅嗦,只是希望大家從中學到知識,如果再寫,一定會是很簡練。當然水平還是基礎級的,需要的只是耐心!! 
下面是序號產生器: 

//--------------------------------------------------------------------------- 
// KeyGen for WinAmp 2.11 by Fpc 
// edtName為輸入註冊姓名的文字框,edtCode為顯示註冊碼的文字框(只讀) 

void __fastcall TForm1::edtNameChange(TObject *Sender) 

char name[255], code[255] = " "; 
int i; 
long value = 0; 
for(i=0;i<255;i++) 
        name[i]='\0x0'; 

if(edtName->Text.IsEmpty()){ 
        edtCode->Text = ""; 
        return; 
        } 
strcpy(name, edtName->Text.c_str()); 

_asm 

    lea esi, name 
    xor ediedi 
    xor ebxebx 
loop1: 
    movzx eaxbyte ptr [Esi+2] 
    movzx ecxbyte ptr [Esi
    movzx edxbyte ptr [Esi+1] 
    xor eaxecx 
    movzx ecxbyte ptr [Esi+3] 
    not ecx 
    not eax 
    xor ecxedx 
    add eaxecx 
    mov ecxedi 
    and ecx, 0x0000000F 
    shl eaxcl 
    test eaxeax 
    jl iflittle 
    add ebxeax 
    jmp nextchar 

iflittle: 
    sub ebxeax 

nextchar: 
    inc edi 
    inc edi 
    inc esi 
    cmp byte ptr [esi], 00 
    jne loop1            // the first loop 

    mov eaxebx 
    mov ecx, 0x000F4240 
    imul eax, 0x00000025 
    cdq 
    idiv ecx 
    mov ecxedx 
    mov esiedx 
    imul ecx, 0x00000064 
    xor ediedi 

loop2: 
    test esiesi 
    je over 
    mov eaxesi 
                                  
    push 0x00000064 
    cdq 
    pop ebx             
    idiv ebx 
    mov eaxesi 
    push ebx 
    pop esi 
    add ediedx 
    cdq 
    idiv esi 
    mov esieax 
    jmp loop2                // the second loop 

over: 
    lea eaxdword ptr [edi+2*edi
    push 0x00000004 
    cdq 
    pop esi 
    idiv esi 
    push 0x00000064 
    pop esi 
    cdq 
    idiv esi 
    mov eaxedx 
    add eaxecx 
      mov value,eax 

  wsprintf(code, "%ld", value); 
  edtCode->Text = code; 

//--------------------------------------------------------------------------- 
// 以上經編譯透過,沒有問題 


                                    Fpc @2001/03/26

<DIV ALIGN='right'>----------------------------------------------
沒有最好,只有最差!
希望FCG不會最差!DIV>

相關文章