製作mIRC6.02序號產生器(給別人寫的初學者序號產生器教材) (14千字)
暑假裡迷起了irc,所以拿到了mIRC就順便把它keygen了。我用的是mIRC 6.02版。此軟體採用的是使用者名稱/註冊碼的保護,在軟體的幫助選單裡有註冊選項。
首先我們看看基本的註冊情況。填好相關的註冊碼和使用者名稱之後,點註冊會發現提示錯誤。之後自動清除了輸入的內容,但是還是可以繼續註冊。瞭解這些就夠了。
現在開始我們的破解之旅。
輸入好註冊碼和使用者名稱之後,進入trw,下斷點,bpx
GetDlgItemTextA,bpx GetWindowTextA。
因為這兩個是常用的獲取EDIT控制元件文字內容的函式啦。
點註冊,發現沒有攔截下來。
那麼就有兩種可能性了:第一,程式採用了其他的方法獲得文字內容,比如除了剛才的兩個斷點之外,還可以向EDIT控制元件傳送WM_GETTEXT訊息來獲得文字;第二,程式是用delphi編寫的,有自己獨立的獲取方式而不依靠windows提供的函式。
無論是哪種可能性,都可以用一種方法來解決,那就是下斷點bpx hmemcpy。這個號稱是9x平臺下的萬能斷點,只要是輸入註冊碼的,都可以用這個斷點來攔截。
下斷點,點註冊。終於攔截下來了。攔下後,下命令pmodule,回到mIRC程式裡,發現我們在call SendDlgItemMessageA的下面,原來它是用這個函式給對話方塊裡的EDIT控制元件傳送WM_GETTEXT訊息。
016F:004C688D 68A8A85700 PUSH DWORD
0057A8A8 <==============以後名字存放的地點
016F:004C6892 68E7030000
PUSH DWORD 03E7
016F:004C6897 6A0D
PUSH BYTE +0D <====================WM_GETTEXT的值
016F:004C6899 6883000000 PUSH DWORD 83
016F:004C689E FF7508 PUSH DWORD
[EBP+08]
016F:004C68A1 E8284B0900 CALL
`USER32!SendDlgItemMessageA`
016F:004C68A6 688FAC5700
PUSH DWORD 0057AC8F <=======+=======pmodule後我們就在這裡了
016F:004C68AB
68E7030000 PUSH DWORD 03E7
|_______以後我們輸入的註冊碼
016F:004C68B0 6A0D
PUSH BYTE +0D
存放的地點
016F:004C68B2 6882000000
PUSH DWORD 82
016F:004C68B7 FF7508
PUSH DWORD [EBP+08]
016F:004C68BA E80F4B0900
CALL `USER32!SendDlgItemMessageA`
016F:004C68BF
688FAC5700 PUSH DWORD 0057AC8F <==============註冊碼作為引數二
016F:004C68C4 68A8A85700 PUSH DWORD 0057A8A8
<==============姓名作為引數一
016F:004C68C9 E88FFBFFFF CALL
004C645D <====================呼叫函式(關鍵的函式)!!
016F:004C68CE 85C0
TEST EAX,EAX <====================測試函式返回值
016F:004C68D0 0F84B7000000 JZ NEAR 004C698D
<===============返回值如果等於0
就跳走(出錯的地方)
從我們看到的程式碼來看,004c645d處函式肯定是產生註冊碼並且進行比較的函式.因此我們應當跟進去,走到004C68C9的時候,F8跟進去.看到:
016F:004C645D 55 PUSH
EBP
016F:004C645E 8BEC MOV
EBP,ESP
016F:004C6460 53
PUSH EBX
016F:004C6461 56
PUSH ESI
016F:004C6462 57
PUSH EDI
016F:004C6463
8B750C MOV ESI,[EBP+0C]
016F:004C6466 8B5D08 MOV
EBX,[EBP+08]
016F:004C6469 BF440E5800 MOV
EDI,00580E44
016F:004C646E 6804010000 PUSH
DWORD 0104
016F:004C6473 6A00
PUSH BYTE +00
016F:004C6475 57
PUSH EDI
016F:004C6476 E8D55C0800
CALL 0054C150
016F:004C647B 83C40C
ADD ESP,BYTE +0C
016F:004C647E 6804010000
PUSH DWORD 0104
016F:004C6483 6A00
PUSH BYTE +00
016F:004C6485 68480F5800
PUSH DWORD 00580F48
016F:004C648A E8C15C0800
CALL 0054C150
016F:004C648F 83C40C
ADD ESP,BYTE +0C
016F:004C6492 56
PUSH ESI
016F:004C6493
57 PUSH EDI
016F:004C6494 8BF7 MOV
ESI,EDI
016F:004C6496 8BFB MOV
EDI,EBX
016F:004C6498 33C0
XOR EAX,EAX
016F:004C649A 83C9FF
OR ECX,BYTE -01
016F:004C649D F2AE
REPNE SCASB
016F:004C649F F7D1
NOT ECX
016F:004C64A1 2BF9
SUB EDI,ECX
016F:004C64A3
87F7 XCHG ESI,EDI
016F:004C64A5
8BC7 MOV EAX,EDI
016F:004C64A7 8BD1 MOV
EDX,ECX
016F:004C64A9 C1E902 SHR
ECX,02
016F:004C64AC F3A5
REP MOVSD
016F:004C64AE 8BCA
MOV ECX,EDX
016F:004C64B0 83E103
AND ECX,BYTE +03
016F:004C64B3 F3A4
REP MOVSB
016F:004C64B5 5F
POP EDI
016F:004C64B6
5E POP ESI
016F:004C64B7 56 PUSH
ESI
016F:004C64B8 57
PUSH EDI
016F:004C64B9 8BFE
MOV EDI,ESI
016F:004C64BB BE480F5800
MOV ESI,00580F48
016F:004C64C0 33C0
XOR EAX,EAX
016F:004C64C2
83C9FF OR ECX,BYTE -01
016F:004C64C5 F2AE REPNE SCASB
016F:004C64C7
F7D1 NOT ECX
016F:004C64C9 2BF9 SUB
EDI,ECX
016F:004C64CB 87F7 XCHG
ESI,EDI
016F:004C64CD 8BC7
MOV EAX,EDI
016F:004C64CF 8BD1
MOV EDX,ECX
016F:004C64D1 C1E902
SHR ECX,02
016F:004C64D4
F3A5 REP MOVSD
016F:004C64D6 8BCA
MOV ECX,EDX
016F:004C64D8
83E103 AND ECX,BYTE +03
016F:004C64DB F3A4 REP MOVSB
016F:004C64DD 5F POP
EDI
016F:004C64DE 5E
POP ESI
016F:004C64DF 68480F5800
PUSH DWORD 00580F48
016F:004C64E4 57
PUSH EDI
016F:004C64E5 E880FEFFFF
CALL 004C636A <==================call 後面緊跟test和跳轉的
016F:004C64EA 85C0 TEST
EAX,EAX 就要留意了
016F:004C64EC 740A JZ
004C64F8 <===eax=0就跳到失敗,所以在函式返回前不能
讓eax=0
016F:004C64EE B801000000 MOV
EAX,01 <========令eax=1,然後跳轉,不遠處就返回了,
016F:004C64F3 E991000000
JMP 004C6589 回到上面004c68ce的地方,上面要求
eax不等於0就註冊成功,這裡是1正好
滿足,所以這個004664E5大有文章.
前面的一大票程式碼看起來很難分析,其實暫時可以不管,因為這還是我們第一遍跟蹤.第一遍只要大概掌握程式碼的情況就可以了.我們注意到004C64E5
處的call和後面的test jz又構成了一個呼叫函式然後比較返回值的情況.而且它後面有mov eax,1 jmp 004c6589.這就可以肯定是判斷註冊碼是否合法的函式了.看看在call前面push
入棧的是哪些東西.在執行到0x4c64e4的時候,下命令d 580f48 可以看到註冊碼,d edi 看到名字.所以,這更加肯定了我們的推測,004c636a處的函式就是核心.在跟進去之前要記住,不能讓eax=0,不然就是註冊失敗的標誌.好了跟進來.
016F:004C636A 55 PUSH
EBP
016F:004C636B 8BEC MOV
EBP,ESP
016F:004C636D 83C4F4
ADD ESP,BYTE -0C
016F:004C6370 53
PUSH EBX
016F:004C6371 56
PUSH ESI
016F:004C6372
57 PUSH EDI
016F:004C6373 8B750C MOV
ESI,[EBP+0C]
016F:004C6376 FF7508 PUSH
DWORD [EBP+08] <==========d *(ebp+8)發現這是名字
016F:004C6379
E8525F0800 CALL 0054C2D0 <====這個函式是幹什麼的?
016F:004C637E 59 POP
ECX <=====執行完函式到了這裡,看看eax裡是什麼?是名字的
016F:004C637F 83F805
CMP EAX,BYTE +05 <==比較名字是不是大於5個字母
長度.
016F:004C6382 7307
JNC 004C638B
016F:004C6384 33C0
XOR EAX,EAX <==小於5就把eax清零,返回,就註冊失敗了.
016F:004C6386 E9C9000000 JMP 004C6454
016F:004C638B 6A2D PUSH
BYTE +2D <==0x2d就是字元"-"
016F:004C638D 56
PUSH ESI <==註冊碼
016F:004C638E
E89D5E0800 CALL 0054C230 <==這個函式跟蹤後發現是返回"-"在註冊碼中
016F:004C6393 83C408 ADD
ESP,BYTE +08 的位置.如果你輸入的註冊碼不含"-"就失敗
016F:004C6396 8BD8
MOV EBX,EAX
016F:004C6398 85DB
TEST EBX,EBX
016F:004C639A
7507 JNZ 004C63A3
016F:004C639C 33C0 XOR
EAX,EAX
016F:004C639E E9B1000000 JMP
004C6454
016F:004C63A3 C60300 MOV
BYTE [EBX],00 <===把"-"替換成0,就是說把我們輸入的
016F:004C63A6
56 PUSH ESI
註冊碼變成兩個字串
016F:004C63A7
E878ED0800 CALL 00555124
<===把註冊碼第一部分轉化成數值
(原來輸入的是字元)
016F:004C63AC 59
POP ECX
016F:004C63AD 8945FC
MOV [EBP-04],EAX <===把第一部分的數值放入這個地方
016F:004C63B0
C6032D MOV BYTE [EBX],2D
<===把註冊碼恢復成員來的樣子
016F:004C63B3 43
INC EBX
016F:004C63B4 803B00
CMP BYTE [EBX],00
016F:004C63B7 7507
JNZ 004C63C0
016F:004C63B9 33C0 XOR
EAX,EAX
016F:004C63BB E994000000 JMP
004C6454
016F:004C63C0 53
PUSH EBX
016F:004C63C1 E85EED0800
CALL 00555124 <===把註冊碼第二部分轉化成數值
016F:004C63C6 59 POP
ECX
016F:004C63C7 8945F8 MOV
[EBP-08],EAX <===存好
016F:004C63CA FF7508
PUSH DWORD [EBP+08] <===姓名
016F:004C63CD
E8FE5E0800 CALL 0054C2D0
<===取得姓名長度
016F:004C63D2 59
POP ECX
016F:004C63D3 8945F4
MOV [EBP-0C],EAX <===把長度存好
016F:004C63D6
33C0 XOR EAX,EAX
<===開始計算了
016F:004C63D8 33DB
XOR EBX,EBX
016F:004C63DA BA03000000
MOV EDX,03
016F:004C63DF 8B4D08
MOV ECX,[EBP+08]
016F:004C63E2 83C103
ADD ECX,BYTE +03 <===從姓名第三個字開始算
016F:004C63E5 3B55F4 CMP
EDX,[EBP-0C]
016F:004C63E8 7D1C
JNL 004C6406
016F:004C63EA 0FB631
MOVZX ESI,BYTE [ECX] <===取姓名裡的一個字元
016F:004C63ED
0FAF3485B8835600 IMUL ESI,[EAX*4+005683B8] <==與一個數相乘儲存在esi中
016F:004C63F5 03DE ADD
EBX,ESI <=累加起來 (這個數具體是什麼後面講)
016F:004C63F7 40
INC EAX
016F:004C63F8
83F826 CMP EAX,BYTE +26
016F:004C63FB 7E02 JNG
004C63FF
016F:004C63FD 33C0
XOR EAX,EAX
016F:004C63FF 42
INC EDX
016F:004C6400 41
INC ECX
016F:004C6401
3B55F4 CMP EDX,[EBP-0C]
016F:004C6404 7CE4 JL
004C63EA 迴圈完成迴圈計算後,ebx裡面就是計算的結果
016F:004C6406 3B5DFC
CMP EBX,[EBP-04] 比較ebx和開始獲得的註冊碼第一部分數值
016F:004C6409 7404 JZ
004C640F 相等就繼續計算第二部分
016F:004C640B 33C0
XOR EAX,EAX
不然就清0 eax滾蛋
016F:004C640D EB45 JMP
SHORT 004C6454
016F:004C640F 33C0
XOR EAX,EAX <==第二部分開始了
016F:004C6411 33DB XOR
EBX,EBX
016F:004C6413 BA03000000 MOV
EDX,03
016F:004C6418 8B4D08 MOV
ECX,[EBP+08]
016F:004C641B 83C103
ADD ECX,BYTE +03 <=還是從姓名的第3個字開始算
016F:004C641E
3B55F4 CMP EDX,[EBP-0C]
016F:004C6421 7D23 JNL
004C6446
016F:004C6423 0FB631 MOVZX
ESI,BYTE [ECX] <=取姓名裡的一個字
016F:004C6426 0FB679FF
MOVZX EDI,BYTE [ECX-01] <=取前一個字
016F:004C642A
0FAFF7 IMUL ESI,EDI
<=相乘
016F:004C642D 0FAF3485B8835600 IMUL
ESI,[EAX*4+005683B8] <=再與另一個數相乘
016F:004C6435 03DE
ADD EBX,ESI <=累加
(和上面的那個一樣後面講)
016F:004C6437 40
INC EAX
016F:004C6438 83F826
CMP EAX,BYTE +26
016F:004C643B 7E02
JNG 004C643F
016F:004C643D
33C0 XOR EAX,EAX
016F:004C643F 42 INC
EDX
016F:004C6440 41
INC ECX
016F:004C6441 3B55F4
CMP EDX,[EBP-0C]
016F:004C6444 7CDD
JL 004C6423
迴圈計算
016F:004C6446 3B5DF8 CMP
EBX,[EBP-08] 比較計算結果,和註冊碼第二部分數值
016F:004C6449 7404
JZ 004C644F 相同則跳到成功標誌
016F:004C644B 33C0 XOR
EAX,EAX
016F:004C644D EB05 JMP
SHORT 004C6454
016F:004C644F B801000000
MOV EAX,01 設立註冊碼比較成功標誌
016F:004C6454
5F POP EDI
016F:004C6455 5E POP
ESI
016F:004C6456 5B
POP EBX
016F:004C6457 8BE5
MOV ESP,EBP
016F:004C6459 5D
POP EBP
016F:004C645A
C20800 RET 08
好了,現在講一講上面兩次出現的[EAX*4+005683B8]是什麼意思.
在跟蹤到那個乘法的時候,下d 005683B8,會看到資料欄裡是這個樣子
0B000000 06000000 11000000 0C000000
0C000000 0E000000 05000000 0C000000
10000000 0A000000 0B000000 06000000
0E000000 0E000000 04000000 0B000000
06000000 0E000000 0E000000 04000000
0B000000 09000000 0C000000 0B000000
0A000000 08000000 0A000000 0A000000
10000000 08000000 04000000 06000000
0A000000 0C000000 10000000 08000000
0A000000 04000000 10000000 00000000
發現資料都是每4位元組出現一次,這就是為什麼用eax*4了.其實005683B8這個地址裡出現的資料是固定的,就是說這是個字典,每次計算註冊碼的時候到裡面來查一個數字然後跟名字的一個字母做乘法運算.那麼我怎麼才能知道這個字典是多大呢?那就看
016F:004C63F8 83F826 CMP
EAX,BYTE +26
和
016F:004C6438 83F826
CMP EAX,BYTE +26
都是把eax和0x26,也就是38來比較,所以一共有39個資料.就是除了0之外的那些.
至此,我們完全摸清了,mIRC的註冊碼的計算情況.當我們執行到016F:004C6406和016F:004C6446的時候各做一次? ebx顯示出十進位制值,然後把兩個值用"-"連結起來就是我們輸入名字所對應的註冊碼了,比如我的lllaaa[BCG]對應7591-674568.
好了,既然搞清楚了演算法,寫序號產生器也就容易了.下面我貼出序號產生器的c語言原始碼
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int
argc,char *argv[])
{
char dict[39]=
{
0x0b,0x06,0x11,0x0c,0x0c,0x0e,0x05,0x0c,0x10,0x0a,
0x0b,0x06,0x0e,0x0e,0x04,0x0b,0x06,0x0e,0x0e,0x04,
0x0b,0x09,0x0c,0x0b,0x0a,0x08,0x0a,0x0a,0x10,0x08,
0x04,0x06,0x0a,0x0c,0x10,0x08,0x0a,0x04,0x10
};
char name[255];
printf("Input your name please:");
gets(name);
int length=strlen(name);
if (length>=39)
{
printf("\nYour name is longer than 39 chars,please choose another
one.");
return 1;
}
int i=0;
long serial1=0,serial2=0;
for
(i=0;i<length-3;i++)
{
serial1+=name[i+3]*dict[i];
serial2+=name[i+3]*name[i+2]*dict[i];
}
printf("The
serial number is:%d-%d",serial1,serial2);
return
1;
}
本來源程式是支援名字超過39位元組的,但是我為了程式設計的簡單,就做了限制.
相關文章
- 序號產生器合集2024-03-17
- winzip序號產生器 (1千字)2001-04-12
- 如何製作VB程式記憶體序號產生器--國內某軟體的序號產生器(隱去軟體資訊)
(14千字)2002-08-04記憶體
- IrfanView 序號產生器分析(初級版)
(13千字)2015-11-15View
- 一個PostScript(RoPS)序號產生器分析。初學者看。 (21千字)2001-07-08
- 序號產生器制分析: (1千字)2001-11-19
- winzip的通用序號產生器 (2千字)2001-12-10
- Myeclipse 6.5 序號產生器2020-04-06Eclipse
- 一個CrackMe的破解以及序號產生器的製作
(4千字)2001-08-16
- EditPlus 2.01b 序號產生器的製作 (22千字)2001-09-10
- 美萍安全衛士V8.45序號產生器制作分析過程,及序號產生器! (11千字)2001-10-28
- Gif2Swf Ver 2.1 TC20序號產生器 && MASM32序號產生器 (4千字)2001-12-10ASM
- MP3 explorer 破解和序號產生器的製作2015-11-15
- 分享一個navicat序號產生器2024-04-02
- win10如何執行序號產生器_win10怎麼執行序號產生器2020-08-28Win10
- Kalua Cocktails 1.1完全破解,內附彙編序號產生器(用序號產生器編寫器,並有它的使用教程)
(22千字)2002-02-27AI
- supercapture3.0的版序號產生器!
(4千字)2002-04-23APT
- 序號產生器寫作教學。奉賢給想加入CCG和BCG的朋友。 (11千字)2001-10-21
- AlgoLab PtVector的破解及序號產生器的編寫 (17千字)2001-05-04Go
- EmEditor V3.29和它的序號產生器 (12千字)2015-11-15
- 《淺談利用RSA演算法防止非法序號產生器的製作》2004-05-20演算法
- WinAmp V2.11的序號產生器制分析(一)(初學者必讀) (12千字)2001-04-08
- 用C++編寫序號產生器的一點技巧2015-11-15C++
- Moho Pro 14 序號產生器啟用 附 安裝教程2023-11-22
- 用KEYMAKE製作記憶體序號產生器特殊一例
(11千字)2015-11-15記憶體
- 橋牌軟體Deep Finesse的序號產生器 (1千字)2015-11-15
- SAP CRM One Order的事件序號產生器制2020-02-11事件
- 菜鳥 學序號產生器編寫之 Android app2015-06-23AndroidAPP
- HappyIcon序號產生器TC原始碼 (1千字)2001-04-08APP原始碼
- NetTalk破解與序號產生器(高手勿進) (10千字)2001-09-20
- Navicat Premiumx64 使用序號產生器啟用2018-11-12REM
- xplorer2之破解和序號產生器2004-12-05
- 010
Editorv1.3破解(序號產生器)2004-05-17
- NewsReactor 1.0 Build 5009的序號產生器制分析 (16千字)2001-08-07ReactUI
- 另類序號產生器(一MFC程式的改造心得) (3千字)2001-09-10C程式
- SAP CRM呼叫中心裡的事件序號產生器制2020-03-10事件
- 貼彩虹狗破解工具的序號產生器 (727字)2001-07-01
- 《中華壓縮 6.01》註冊碼破解及序號產生器 (14千字)2001-08-19