winamp全集分析教程!
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 eax, dword ptr [ebp+FFFFFD00]
:0041C142 50 push eax
:0041C143 E888AC0000 call 00426DD0
:0041C148 83C408 add esp, 00000008
:0041C14B 85C0 test eax, eax
:0041C14D 744F je 0041C19E
:0041C14F C745FCFFFFFFFF mov [ebp-04], FFFFFFFF
:0041C156 8D4DFC lea ecx, dword 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 ecx, dword 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 ecx, dword ptr [ebp+FFFFFD00]
:0041C188 51 push ecx
:0041C189 8D9500F9FFFF lea edx, dword 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的。再向下是一個 Call+ Cmp+ Jmp的程式段,這個 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 ebp, esp
:00401CD1 81EC00060000 sub esp, 00000600
:00401CD7 A050914400 mov al, byte 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 eax, eax
:00401CEC 8DBD01FAFFFF lea edi, dword ptr [ebp+FFFFFA01] <== 準備將記憶體清0
:00401CF2 F3 repz
:00401CF3 AB stosd
:00401CF4 66AB stosw
* Reference To: KERNEL32.GetPrivateProfileStringA, Ord:013Ah
|
:00401CF6 8B3534E14300 mov esi, dword 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 eax, dword 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 eax, dword 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 eax, dword 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 eax, eax
:00401D62 59 pop ecx
:00401D63 744F je 00401DB4 <== Eax=0就去死
:00401D65 802000 and byte ptr [eax], 00 <== 使得Rn以'\0'結束
:00401D68 33F6 xor esi, esi
:00401D6A 83C003 add eax, 00000003 <== Eax指向Irc:123456
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401D84(U)
|
:00401D6D 8A08 mov cl, byte ptr [eax] <== 取一個字元
:00401D6F 80F930 cmp cl, 30 <== 數字為有效字元,非數字表示完成
:00401D72 7C12 jl 00401D86
:00401D74 80F939 cmp cl, 39
:00401D77 7F0D jg 00401D86
:00401D79 0FBEC9 movsx ecx, cl <== Ecx中無用位清0
:00401D7C 8D14B6 lea edx, dword ptr [esi+4*esi] <= Edx=5*Esi
:00401D7F 40 inc eax <== Edx的初始值為0,這三條指令將字串變為數字
:00401D80 8D7451D0 lea esi, dword 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 eax, dword ptr [ebp+FFFFFE00]<== Eax指向Rn
:00401D8C 50 push eax
:00401D8D E83F350200 call 004252D1 <== !! 關鍵Call,由Rn計算得出Rc,儲存在Eax。具體分析請看(三)
:00401D92 3BC6 cmp eax, esi <== 比較Rc與Irc
:00401D94 59 pop ecx
:00401D95 751D jne 00401DB4 <== 不相等則GAME OVER,大家將此處NOP掉,看會發生什麼有趣的事情
:00401D97 50 push eax
:00401D98 8D8500FEFFFF lea eax, dword ptr [ebp+FFFFFE00]
:00401D9E 50 push eax
:00401D9F 8D8500FAFFFF lea eax, dword 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 eax, dword 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 eax, dword 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 eax, dword 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 eax, dword ptr [ebp+eax-00000480]
:00401ECE 50 push eax
:00401ECF 53 push ebx
:00401ED0 FF7508 push [ebp+08]
:00401ED3 FFD6 call esi
:00401ED5 8D8580FBFFFF lea eax, dword 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 edi, dword 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 di, ax
:00401F07 7405 je 00401F0E
:00401F09 663BFB cmp di, bx
: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 edi, dword ptr [ebp+08]
:00401F1B 8D4D80 lea ecx, dword 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 esi, eax
:00401F36 8D4580 lea eax, dword ptr [ebp-80]
:00401F39 50 push eax
:00401F3A E892330200 call 004252D1 <== !! 關鍵Call,由Rn計算得出Rc,儲存在Eax。具體分析請看(三)
:00401F3F 3BC6 cmp eax, esi <== 比較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 eax, eax
: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 ecx, dword ptr [esp+08] <== Ecx=442158,指向"!!!"+'\0'
:00435154 57 push edi
:00435155 53 push ebx
:00435156 56 push esi
:00435157 8A11 mov dl, byte ptr [ecx] <== Dl取得第一個'!'
:00435159 8B7C2410 mov edi, dword ptr [esp+10] <== Edi=Ebp-200=6DC4F8,即RI首址
:0043515D 84D2 test dl, dl
:0043515F 7469 je 004351CA <== Dl=0證明比較完成,跳下去準備返回(怎麼可能?!)
:00435161 8A7101 mov dh, byte ptr [ecx+01] <== 第二個'!'到Dh
:00435164 84F6 test dh, dh
:00435166 744F je 004351B7
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:004351A2(C), :004351B5(U)
|
:00435168 8BF7 mov esi, edi
:0043516A 8B4C2414 mov ecx, dword ptr [esp+14] <== Ecx=442158,指向"!!!"+'\0'
:0043516E 8A07 mov al, byte ptr [edi]
:00435170 46 inc esi
:00435171 38D0 cmp al, dl <== 看Al是否為'!'
:00435173 7415 je 0043518A
:00435175 84C0 test al, al
:00435177 740B je 00435184 <== Al為空則失敗
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00435182(C)
|
:00435179 8A06 mov al, byte ptr [esi]
:0043517B 46 inc esi
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0043518F(C)
|
:0043517C 38D0 cmp al, dl
:0043517E 740A je 0043518A <== 向下跳檢查RI中是否含三個'!'
:00435180 84C0 test al, al
: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 eax, eax
:00435189 C3 ret
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00435173(C), :0043517E(C)
|
:0043518A 8A06 mov al, byte ptr [esi] <== 從RI中!之後再讀一位元組
:0043518C 46 inc esi
:0043518D 38F0 cmp al, dh
:0043518F 75EB jne 0043517C <== 若不等, 則在Rn中含'!'
:00435191 8D7EFF lea edi, dword ptr [esi-01]
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004351B3(C)
|
:00435194 8A6102 mov ah, byte ptr [ecx+02]
:00435197 84E4 test ah, ah
:00435199 7428 je 004351C3
:0043519B 8A06 mov al, byte ptr [esi] <== 從Rn中取第三個'!'
:0043519D 83C602 add esi, 00000002
:004351A0 38E0 cmp al, ah
:004351A2 75C4 jne 00435168
:004351A4 8A4103 mov al, byte ptr [ecx+03] <== Al應取到0
:004351A7 84C0 test al, al
:004351A9 7418 je 004351C3 <== Al為空表示正常結束
:004351AB 8A66FF mov ah, byte ptr [esi-01]
:004351AE 83C102 add ecx, 00000002 <== 若正確,這裡不會被執行
:004351B1 38E0 cmp al, ah
:004351B3 74DF je 00435194
:004351B5 EBB1 jmp 00435168
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00435166(C)
|
:004351B7 33C0 xor eax, eax <== 跳到這裡則RI形式錯誤
:004351B9 5E pop esi
:004351BA 5B pop ebx
:004351BB 5F pop edi
:004351BC 8AC2 mov al, dl
:004351BE E933210000 jmp 004372F6
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00435199(C), :004351A9(C)
|
:004351C3 8D47FF lea eax, dword 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 eax, edi <== 也是正確出口
: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 ebp, esp
:004252D4 81EC00010000 sub esp, 00000100
:004252DA 53 push ebx
:004252DB 56 push esi
:004252DC 57 push edi
:004252DD 6A3F push 0000003F
:004252DF 33DB xor ebx, ebx
:004252E1 59 pop ecx <== Ecx=3F
:004252E2 209D00FFFFFF and byte ptr [ebp+FFFFFF00], bl
:004252E8 33C0 xor eax, eax
:004252EA 8DBD01FFFFFF lea edi, dword 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 eax, dword 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 esi, dword ptr [ebp+FFFFFF00]
:0042531A 33FF xor edi, edi
<== 至此,入口: 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 ecx, edi <== 隨著迴圈,Edi=0、2,4,6,8,A...
:00425325 83E10F and ecx, 0000000F
:00425328 D3E0 shl eax, cl <== 左移位
:0042532A 85C0 test eax, eax
:0042532C 7C04 jl 00425332 <== 是負數則向下跳
:0042532E 03D8 add ebx, eax <== 很少被執行到
:00425330 EB02 jmp 00425334 <== 迴圈次數為Rn長度
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0042532C(C)
|
:00425332 2BD8 sub ebx, eax <== 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 eax, ebx <== 中間結果送 Eax
:0042533E B940420F00 mov ecx, 000F4240 <== Ecx= 1,000,000(Dec)
:00425343 6BC025 imul eax, 00000025 <== Eax= Eax*37(Dec)
:00425346 99 cdq
:00425347 F7F9 idiv ecx
:00425349 8BCA mov ecx, edx <== 餘數送Ecx儲存,很重要(我跟到下面要返回的語句,向回找了半天才找到)
:0042534B 8BF2 mov esi, edx <== 餘數送Esi,到 425352繼續處理
:0042534D 6BC964 imul ecx, 00000064 <== Ecx=Ecx*100(Dec)
:00425350 33FF xor edi, edi
* Referenced by a (U)nconditional or (C)onditional Jump at Address: <== 到 425369的這個迴圈會被執行幾次
|:00425369(U)
|
:00425352 85F6 test esi, esi <== Esi是否為0
:00425354 7415 je 0042536B <== 是則跳出這一迴圈
:00425356 8BC6 mov eax, esi <== Esi->Eax,作處理準備
:00425358 6A64 push 00000064
:0042535A 99 cdq
:0042535B 5B pop ebx
:0042535C F7FB idiv ebx <== 被100(Dec)除
:0042535E 8BC6 mov eax, esi
:00425360 53 push ebx
:00425361 5E pop esi
:00425362 03FA add edi, edx <== Edi放餘數累加和
:00425364 99 cdq
:00425365 F7FE idiv esi
:00425367 8BF0 mov esi, eax <== 商被送到Esi
:00425369 EBE7 jmp 00425352
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00425354(C)
|
:0042536B 8D047F lea eax, dword 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 eax, edx <== 餘數送 Eax
:0042537F 03C1 add eax, ecx <== Eax= Eax+Ecx (看42534D),這是最終結果
:00425381 C9 leave
:00425382 C3 ret
* Referenced by a CALL at Address:
|:0042531D
|
:00425383 55 push ebp
:00425384 8BEC mov ebp, esp
:00425386 51 push ecx
:00425387 8065FC00 and byte ptr [ebp-04], 00
:0042538B 57 push edi
:0042538C 33C0 xor eax, eax
:0042538E 8D7DFD lea edi, dword ptr [ebp-03]
:00425391 66AB stosw
:00425393 6A04 push 00000004
:00425395 FF7508 push [ebp+08] <== 源字串地址壓棧
:00425398 AA stosb <== 從Ebp-04處建立了4位元組的臨時緩衝區
:00425399 8D45FC lea eax, dword ptr [ebp-04] <==
:0042539C 50 push eax <== 目標區地址壓棧
:0042539D E84E010100 call 004354F0 <== 又一次對這個CALL的呼叫,不過這次是從Esi處取 4 位元組到臨時緩衝區,我在這裡轉的頭暈,大家可以看一看。
:004253A2 0FB645FE movzx eax, byte ptr [ebp-02] <== 相當於 al=[Esi+2],高位是0,下同
:004253A6 0FB64DFC movzx ecx, byte ptr [ebp-04] <== cl=[Esi]
:004253AA 0FB655FD movzx edx, byte ptr [ebp-03] <== dl=[Esi+1]
:004253AE 33C1 xor eax, ecx <== Al^=Cl
:004253B0 83C40C add esp, 0000000C
:004253B3 0FB64DFF movzx ecx, byte ptr [ebp-01] <== cl=[Esi+3]
:004253B7 F7D1 not ecx <== !Ecx
:004253B9 F7D0 not eax <== !Eax
:004253BB 33CA xor ecx, edx <== Cl^=Dl
:004253BD 5F pop edi
:004253BE 03C1 add eax, ecx <== 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 ecx, dword ptr [esp+0C] <== 呼叫此Call前的倒數第三次Push,為100或4
:004354F4 57 push edi
:004354F5 85C9 test ecx, ecx
:004354F7 747A je 00435573 <== 兩處呼叫都不跳
:004354F9 56 push esi
:004354FA 53 push ebx
:004354FB 8BD9 mov ebx, ecx <==
:004354FD 8B742414 mov esi, dword ptr [esp+14] <== !! Esi為源字串地址,注意 @42539D呼叫時,每次都有Esi=Esi+1
:00435501 F7C603000000 test esi, 00000003 <== Esi低位元組是否為03
:00435507 8B7C2410 mov edi, dword 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 al, byte 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 al, al
: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 ebx, ecx
: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 al, byte ptr [esi]
:00435537 46 inc esi
:00435538 8807 mov byte ptr [edi], al
:0043553A 47 inc edi
:0043553B 84C0 test al, al
: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 eax, dword 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 ebx, ecx
: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 eax, dword 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 eax, dword ptr [esi] <--
:00435588 03D0 add edx, eax
:0043558A 83F0FF xor eax, FFFFFFFF
:0043558D 33C2 xor eax, edx
:0043558F 8B16 mov edx, dword ptr [esi]
:00435591 83C604 add esi, 00000004
:00435594 A900010181 test eax, 81010100 <-- 檢查 Eax取到的是否為0,手法很是怪異?!
:00435599 74DE je 00435579
:0043559B 84D2 test dl, dl
:0043559D 742C je 004355CB
:0043559F 84F6 test dh, dh
: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 edx, edx
: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 eax, eax
:004355D4 49 dec ecx
:004355D5 740A je 004355E1
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00435569(C)
|
:004355D7 33C0 xor eax, eax
* 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 eax, dword 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 edi, edi
xor ebx, ebx
loop1:
movzx eax, byte ptr [Esi+2]
movzx ecx, byte ptr [Esi]
movzx edx, byte ptr [Esi+1]
xor eax, ecx
movzx ecx, byte ptr [Esi+3]
not ecx
not eax
xor ecx, edx
add eax, ecx
mov ecx, edi
and ecx, 0x0000000F
shl eax, cl
test eax, eax
jl iflittle
add ebx, eax
jmp nextchar
iflittle:
sub ebx, eax
nextchar:
inc edi
inc edi
inc esi
cmp byte ptr [esi], 00
jne loop1 // the first loop
mov eax, ebx
mov ecx, 0x000F4240
imul eax, 0x00000025
cdq
idiv ecx
mov ecx, edx
mov esi, edx
imul ecx, 0x00000064
xor edi, edi
loop2:
test esi, esi
je over
mov eax, esi
push 0x00000064
cdq
pop ebx
idiv ebx
mov eax, esi
push ebx
pop esi
add edi, edx
cdq
idiv esi
mov esi, eax
jmp loop2 // the second loop
over:
lea eax, dword ptr [edi+2*edi]
push 0x00000004
cdq
pop esi
idiv esi
push 0x00000064
pop esi
cdq
idiv esi
mov eax, edx
add eax, ecx
mov value,eax
}
wsprintf(code, "%ld", value);
edtCode->Text = code;
}
//---------------------------------------------------------------------------
// 以上經編譯透過,沒有問題
Fpc @2001/03/26
<DIV ALIGN='right'>----------------------------------------------
沒有最好,只有最差!
希望FCG不會最差!DIV>
相關文章
- 哪有Python3教程全集下載2017-07-31Python
- 【原創】Winamp標題欄中文亂碼原因分析及修正2004-12-12
- Python教程百度雲全集網盤分享2017-09-07Python
- 2020版JavaScript基礎入門教程全集分享2020-01-09JavaScript
- Oracle命令全集2005-01-24Oracle
- DOS命令全集2011-12-13
- SQL操作全集2009-12-09SQL
- 破解 WinAmp Skin Maker v1.052015-11-15
- Java全集書籍2018-08-01Java
- Java面試題全集2017-09-25Java面試題
- 使用Windows訊息控制Winamp(VB) (轉)2007-12-09Windows
- 使用Windows訊息控制Winamp(Delphi) (轉)2007-12-09Windows
- Java面試題全集(下)2020-11-04Java面試題
- oracle許可權全集2015-11-24Oracle
- 最新技術精選|千鋒React教程+實戰全集資源免費領2019-12-18React
- 老羅android開發視訊教程全集百度網盤下載2018-10-22Android
- 【meil 】SQLServer Transact SQL全集(轉)2008-07-23SQLServer
- yum安裝及使用全集2016-04-04
- Go 實現 LeetCode 全集2020-03-29GoLeetCode
- .Net 執行緒安全集合2022-01-10執行緒
- 【Git 系列】基礎知識全集2021-11-19Git
- 中興通訊在招聘的全集2009-04-21
- 從原始碼分析非執行緒安全集合類的不安全迭代器2017-10-11原始碼執行緒
- WinAmp V2.11的序號產生器制分析(一)(初學者必讀) (12千字)2001-04-08
- 谷歌分析使用教程2022-11-24谷歌
- Java面試題全集學習筆記2017-07-26Java面試題筆記
- MySql常用命令大全集合2016-01-14MySql
- Spark API 全集(1):Spark SQL Dataset & DataFrame API2018-12-09SparkAPISQL
- 【Jenkins系列】-Pipeline語法全集2023-04-01Jenkins
- Bootstrap 前端資源大全集(持續更新)2018-06-26boot前端
- win2000 下 CMD命令全集2006-10-17
- CISCO 2811 路由器配置命令全集2009-09-03路由器
- 註冊你的LyricsShow! for Winamp v1.2
(3千字)2001-04-14CSS
- 註冊你的LyricsShow! for Winamp v1.2(zombieys) (1千字)2001-06-02CSS
- iResearch:Winamp十五週年興衰史 行業先驅者後勁乏力2012-07-26行業
- 電子技術應用專業資料全集2019-02-22
- Oracle9i 資料庫設計指引全集2005-03-21Oracle資料庫
- 思科認證CCNA專業英文詞彙全集(1)(轉)2007-08-12