查看單個文章
舊 2003-12-12, 03:46 AM   #1
psac
榮譽會員
 
psac 的頭像
榮譽勳章
UID - 3662
在線等級: 級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時
註冊日期: 2002-12-07
住址: 木柵市立動物園
文章: 17381
現金: 5253 金幣
資產: 33853 金幣
預設 一種非明碼比較程序的註冊------NS-SHAFT註冊碼破解

NS-SHAFT的兩個小遊戲一個是向上逃命的,一個是向下逃命的。
暫且叫向上逃命的為「是男人就上100層」,向下逃命的就叫做「是男人就是100層」。
絕對有難度!!鬼子的東西就是變態。
這麼簡單的程序將然要500日元的註冊費(我漢化的把那個漢化掉了,原版上有提示)
向我這些窮人,只能拿它來研究了。
並且對破解「一種非明碼比較」程序的思路經驗進行總結,以饗讀者。

下載位址:http://202.102.229.61/zhima
保護方式:例外,異常
使用工具:OllyDbg1.09C漢化版,VC++6.0(寫註冊機用)
操作系統:win2000
破解難度:有一定難度

破解程序

一、解除軟體保護。
由於用的是例外,異常來進行保護,所以alt+O開啟OllyDbg的「偵錯選項」,選項「異常」標籤
把「忽略」的複選框選項除了最下邊的那一個不選其他統統選上。然後就可以放心的載入程序了。
OllyDbg就是強大,沒得說,對付鬼子的變態保護很有一套。感謝迎刃兄的指導。

二、對軟體註冊方式的分析。
這個軟體註冊時要求輸入用戶名和註冊號,用戶名不起任何作用,主要是對註冊碼進行檢驗。
兩個程序註冊碼之間的差別只有一條指令。這裡我拿「向上100層」舉例。那條指令我會特別註釋。
開啟程序-〉執行。
在反彙編框中,滑鼠右鍵-〉搜尋-〉當前模組中的名稱(其實也就是當前領空所有被使用的API函數)。
找到GetDlgItemTextA對著它點右鍵,選項「搜尋匯入參考」。全部設為斷點。
前期工作做完了。選項「註冊」。輸入用戶名,輸入註冊碼(7位,後面有解釋)。確定。被斷下來了。
我們可以看到下面緊接著就是出錯的提示框的CALL,能跳過它的只有JNZ 120.0040302F這個。
00402FE1 . 8D85 FCFDFFFF LEA EAX,DWORD PTR SS:[EBP-204]
00402FE7 . 50 PUSH EAX
00402FE8 . E8 C0010000 CALL 120.004031AD
00402FED . 83C4 04 ADD ESP,4
00402FF0 . 85C0 TEST EAX,EAX
00402FF2 . 0F85 37000000 JNZ 120.0040302F
所以,比較的核心程式碼肯定在CALL 120.004031AD這個裡面,F7進入。
這裡就是比較位數的不能大於7位。
004031BB . 8A48 07 MOV CL,BYTE PTR DS:[EAX+7] //取第8個,
004031BE . 85C9 TEST ECX,ECX //ECX必須為零所以第8位必須位0x00也就是什麼都不能有
004031C0 . 0F84 07000000 JE 120.004031CD
往下看就是比較的核心了。
可以發現比較程序經常使用的一個函數就是CALL 120.00403317。看看裡面是什麼呢??
00403317 /$ 55 PUSH EBP
00403318 |. 8BEC MOV EBP,ESP
0040331A |. 53 PUSH EBX
0040331B |. 56 PUSH ESI
0040331C |. 57 PUSH EDI
0040331D |. 33C0 XOR EAX,EAX
0040331F |. 8A45 08 MOV AL,BYTE PTR SS:[EBP+8] //取一個字串
00403322 |. 83F8 61 CMP EAX,61 //是小寫字母嗎???
00403325 |. 0F8C 0B000000 JL 120.00403336
0040332B |. 33C0 XOR EAX,EAX
0040332D |. 8A45 08 MOV AL,BYTE PTR SS:[EBP+8]
00403330 |. 83E8 20 SUB EAX,20 //是轉化為大寫,
00403333 |. 8845 08 MOV BYTE PTR SS:[EBP+8],AL
00403336 |> 33C0 XOR EAX,EAX
00403338 |. 8A45 08 MOV AL,BYTE PTR SS:[EBP+8]
0040333B |. 83F8 41 CMP EAX,41 //是大寫字母嗎???
0040333E |. 0F8C 0B000000 JL 120.0040334F
00403344 |. 33C0 XOR EAX,EAX
00403346 |. 8A45 08 MOV AL,BYTE PTR SS:[EBP+8]
00403349 |. 83E8 07 SUB EAX,7 //是大寫減0x07
0040334C |. 8845 08 MOV BYTE PTR SS:[EBP+8],AL
0040334F |> 33C0 XOR EAX,EAX
00403351 |. 8A45 08 MOV AL,BYTE PTR SS:[EBP+8]
00403354 |. 83E8 30 SUB EAX,30 //不管是數字還是字母統統減0x30
00403357 |. E9 00000000 JMP 120.0040335C
0040335C |> 5F POP EDI
0040335D |. 5E POP ESI
0040335E |. 5B POP EBX
0040335F |. C9 LEAVE
00403360 \. C3 RETN
對這個函數的功能總結:
數字-0x30
小寫字母-0x20-0x07-0x30
大寫字母-0x07-0x30
好了讓我們在分析核心的程式碼:試煉碼:ljylhqn (這個試煉碼可是有一定的含義呦)
----------------第一個開始-----------------
00403211 > 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8] //傳遞給EAX試煉碼,這裡下斷點是個不錯的注意
00403214 . 8A40 05 MOV AL,BYTE PTR DS:[EAX+5] //取註冊碼第6位
00403217 . 50 PUSH EAX
00403218 . E8 FA000000 CALL 120.00403317 //計算得到EAX=1A
0040321D . 83C4 04 ADD ESP,4
00403220 . 33DB XOR EBX,EBX
00403222 . 8AD8 MOV BL,AL //EBX=1A
00403224 . 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8] //傳遞給EAX試煉碼
00403227 . 8A40 02 MOV AL,BYTE PTR DS:[EAX+2] //取註冊碼第3位
0040322A . 50 PUSH EAX
0040322B . E8 E7000000 CALL 120.00403317 //計算得到EAX=22
00403230 . 83C4 04 ADD ESP,4
00403233 . 33C9 XOR ECX,ECX
00403235 . 8AC8 MOV CL,AL //ECX=22
00403237 . BE 24000000 MOV ESI,24
0040323C . 8D4459 1C LEA EAX,DWORD PTR DS:[ECX+EBX*2+1C] //一個計算,結果EAX=72。下100層的計算是[ECX+EBX*2+1D]
00403240 . 99 CDQ
00403241 . F7FE IDIV ESI //eax除以24,計算後EAX為商,EDX為餘數
00403243 . 8BDA MOV EBX,EDX
00403245 . 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
00403248 . 8A00 MOV AL,BYTE PTR DS:[EAX] //取註冊碼第1位
0040324A . 50 PUSH EAX
0040324B . E8 C7000000 CALL 120.00403317 //計算得到EAX=15
00403250 . 83C4 04 ADD ESP,4
00403253 . 33C9 XOR ECX,ECX
00403255 . 8AC8 MOV CL,AL
00403257 . 3BD9 CMP EBX,ECX //一個是6一個是15肯定不一樣所以eax應該等於6根據
00403259 . 0F85 AC000000 JNZ 120.0040330B //CALL 120.00403317逆推註冊碼第一位應該是數字6也就是0x36
----------------第二個開始-----------------//和第一個類似區別,區別在於位置
0040325F . 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
00403262 . 8A40 04 MOV AL,BYTE PTR DS:[EAX+4]
00403265 . 50 PUSH EAX
00403266 . E8 AC000000 CALL 120.00403317
0040326B . 83C4 04 ADD ESP,4
0040326E . 33DB XOR EBX,EBX
00403270 . 8AD8 MOV BL,AL
00403272 . 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
00403275 . 8A40 01 MOV AL,BYTE PTR DS:[EAX+1]
00403278 . 50 PUSH EAX
00403279 . E8 99000000 CALL 120.00403317
0040327E . 83C4 04 ADD ESP,4
00403281 . 33C9 XOR ECX,ECX
00403283 . 8AC8 MOV CL,AL
00403285 . BE 24000000 MOV ESI,24
0040328A . 8D4459 1C LEA EAX,DWORD PTR DS:[ECX+EBX*2+1C]
0040328E . 99 CDQ
0040328F . F7FE IDIV ESI
00403291 . 8BDA MOV EBX,EDX
00403293 . 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
00403296 . 8A40 06 MOV AL,BYTE PTR DS:[EAX+6]
00403299 . 50 PUSH EAX
0040329A . E8 78000000 CALL 120.00403317
0040329F . 83C4 04 ADD ESP,4
004032A2 . 33C9 XOR ECX,ECX
004032A4 . 8AC8 MOV CL,AL
004032A6 . 3BD9 CMP EBX,ECX
004032A8 . 0F85 5D000000 JNZ 120.0040330B
----------------第三個開始-----------------//差不多一模一樣
004032AE . 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
004032B1 . 8A40 06 MOV AL,BYTE PTR DS:[EAX+6]
004032B4 . 50 PUSH EAX
004032B5 . E8 5D000000 CALL 120.00403317
004032BA . 83C4 04 ADD ESP,4
004032BD . 33DB XOR EBX,EBX
004032BF . 8AD8 MOV BL,AL
004032C1 . 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
004032C4 . 8A00 MOV AL,BYTE PTR DS:[EAX]
004032C6 . 50 PUSH EAX
004032C7 . E8 4B000000 CALL 120.00403317
004032CC . 83C4 04 ADD ESP,4
004032CF . 33C9 XOR ECX,ECX
004032D1 . 8AC8 MOV CL,AL
004032D3 . BE 24000000 MOV ESI,24
004032D8 . 8D4459 1C LEA EAX,DWORD PTR DS:[ECX+EBX*2+1C]
004032DC . 99 CDQ
004032DD . F7FE IDIV ESI
004032DF . 8BDA MOV EBX,EDX
004032E1 . 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
004032E4 . 8A40 03 MOV AL,BYTE PTR DS:[EAX+3]
004032E7 . 50 PUSH EAX
004032E8 . E8 2A000000 CALL 120.00403317
004032ED . 83C4 04 ADD ESP,4
004032F0 . 33C9 XOR ECX,ECX
004032F2 . 8AC8 MOV CL,AL
004032F4 . 3BD9 CMP EBX,ECX
004032F6 . 0F85 0F000000 JNZ 120.0040330B
----------------結束-----------------
從程式碼看一共比較3次:
第一次比較:取第六位(ebx)和第三位(ecx)經CALL 120.00403317處理。然後經0040323c計算除0x24取餘數存入ebx
再取第一位經CALL 120.00403317處理存入eax。然後比較eax和ebx。相等則以,不等則死

第二次比較:取第五位(ebx)和第二位(ecx)經CALL 120.00403317處理。然後經0040323c計算除0x24取餘數存入ebx
再取第七位經CALL 120.00403317處理存入eax。然後比較eax和ebx。相等則以,不等則死

第三次比較:取第七位(ebx)和第一位(ecx)經CALL 120.00403317處理。然後經0040323c計算除0x24取餘數存入ebx
再取第四位經CALL 120.00403317處理存入eax。然後比較eax和ebx。相等則以,不等則死

三、製作註冊機
通過推理這個軟體的註冊碼可以通過輸入任意一個7位字串串猜測出來。下面是我寫的註冊機的核心程式碼
void CNS_KGDlg::OnBnGetKey()
{
// TODO: Add your control notification handler code here
int ctmp1,ctmp2,ctmp3;
LPCSTR testKey1;
char testKey[8];
testKey[7]='\0';
UpdateData();
if(m_strKey.IsEmpty()||m_strKey.GetLength()!=7)//m_strKey是用戶輸入的任意7位註冊碼
{
MessageBox("您的輸入有誤","提示");
return;
}
testKey1=(LPCSTR)m_strKey;
strncpy(testKey,testKey1,7);
ctmp1=changechartoint(testKey[5]);
ctmp2=changechartoint(testKey[2]);
ctmp3=suanfa(ctmp1, ctmp2, m_nChk);
testKey[0]=changeinttochar(ctmp3);

ctmp1=changechartoint(testKey[4]);
ctmp2=changechartoint(testKey[1]);
ctmp3=suanfa(ctmp1, ctmp2, m_nChk);
testKey[6]=changeinttochar(ctmp3);

ctmp1=changechartoint(testKey[6]);
ctmp2=changechartoint(testKey[0]);
ctmp3=suanfa(ctmp1, ctmp2, m_nChk);
testKey[3]=changeinttochar(ctmp3);

m_strKey.Format("%s",testKey);
m_strNote.Format("幸福的芝麻製作"); //廣告
SetWindowText("http://zhimaxp.126.com"); //廣告
UpdateData(FALSE);

}

int CNS_KGDlg::changechartoint(char ch)
{
if(ch>=97)
{
ch-=32;
}
if(ch>=65)
{
ch-=7;
}
return ch-48;

}

int CNS_KGDlg::suanfa(char a, char b, int k)
{
int c;
if(k==0)
{
c=b+a*2+28;
return c%36;
}
else
{
c=b+a*2+29;
return c%36;
}
}

char CNS_KGDlg::changeinttochar(int nCh)
{
nCh+=48;
if(nCh>57)
nCh+=7;
if(nCh>90)
nCh+=32;
return nCh;
}
----------
程序下載:http://202.102.229.61/zhima
psac 目前離線  
送花文章: 3, 收花文章: 1631 篇, 收花: 3205 次