//【标题】看雪论坛精华五 - 序列号 - DOSKEY CRACKME2
//【作者】oHuangKeo
//【时间】2005-02-26
//【备注】没事时我就看看《看雪论坛精华》,今看到这里,见原作者最后的注册程序是用VB代码写的,我也来动动手,用C写一下,一来练练技术,二来学好C语言。(破解前我没有看过原作者的分析)这个CrackME加过壳了,脱壳和跟踪我就不多说了,主要以跟踪过程后怎么写出注册程序为目的。在C代码中,为了大家容易读懂,我就没有简化,一条一条写出来的。希望对大家有点帮助。原程序可以在《看雪论坛精华五》中找到。
//http://www.ohko.com
//----------------
#include <stdio.h>
void main (int Param,char *commline[]) {
char* name = "ohko"; // 用户名
char SN[255] = {0}; // 存放算出的注册码
int eax,ebx,ecx,edx,esi;
/*
00403020 62 69 71 32 6A 72 78 63 2D 61 70 65 33 2A 64 73 biq2jrxc-ape3*ds
00403030 79 6E 68 7A 38 67 74 35 6F 37 66 30 75 6D 6C 34 ynhz8gt5o7f0uml4
00403040 76 31 39 77 36 2B 2F 6B 00 00 00 00 2D 61 70 65 v19w6+/k....-ape
00403050 6F 69 71 32 6A 72 6D 6C 34 78 63 73 77 36 79 6E oiq2jrml4xcsw6yn
00403060 68 37 66 30 75 76 31 39 2B 33 2F 6B 2A 64 62 7A h7f0uv19+3/k*dbz
00403070 38 67 74 35 00 00 00 00 68 37 66 30 75 76 31 39 8gt5....h7f0uv19
00403080 2B 33 2F 6B 6A 72 6D 6C 34 78 63 73 77 36 79 6E +3/kjrml4xcsw6yn
00403090 2A 64 62 7A 38 67 74 35 2D 61 70 65 6F 69 71 32 *dbz8gt5-apeoiq2
*/
char* tabA = "biq2jrxc-ape3*dsynhz8gt5o7f0uml4v19w6+/k"; // 表一
char* tabB = "-apeoiq2jrml4xcsw6ynh7f0uv19+3/k*dbz8gt5"; // 表二
char* tabC = "h7f0uv19+3/kjrml4xcsw6yn*dbz8gt5-apeoiq2"; // 表三
// 将用户名进行计算,然后从表一中得到一字符串。
/*
00401662 33F6 XOR ESI,ESI ; esi = 0 ; 后面循环要用的。
00401664 85C9 TEST ECX,ECX ; if ecx = 0 ; 用户名长度。
00401666 7E 2B JLE SHORT crackme2.00401693 ; go over
00401668 0FBE0430 MOVSX EAX,BYTE PTR DS:[EAX+ESI] ; eax = mid(name,i,1)
0040166C 8D0C80 LEA ECX,DWORD PTR DS:[EAX+EAX*4] ; ecx = eax+eax*4
0040166F 8D04C8 LEA EAX,DWORD PTR DS:[EAX+ECX*8] ; eax += ecx*8
00401672 B9 28000000 MOV ECX,28 ; ecx=28
00401677 99 CDQ ; edx = 0
00401678 F7F9 IDIV ECX ; eax /= ecx ; edx = eax % ecx
0040167A 8D4C24 0C LEA ECX,DWORD PTR SS:[ESP+C] ; 存放后面将要从码表中换来的字母的地址的地址
0040167E 8A92 20304000 MOV DL,BYTE PTR DS:[EDX+403020] ; 查表:dl = [edx+403020]
00401684 52 PUSH EDX
00401685 E8 16030000 CALL <JMP.&MFC42.#940_??YCString@@QAEABV0@D@Z> ; 把edx转换成数字:34 -> 4
0040168A 8B47 68 MOV EAX,DWORD PTR DS:[EDI+68] ; eax = &name
0040168D 46 INC ESI ; esi++
0040168E 3B70 F8 CMP ESI,DWORD PTR DS:[EAX-8] ; if esi < len(name)
00401691 >^ 7C D5 JL SHORT crackme2.00401668 ; go up
*/
esi = 0;
for( ; esi < strlen(name); esi++)
{
eax = name[esi];
ecx = eax*5;
eax = eax+ecx*8;
ecx = 0x28;
edx = 0;
edx = eax%ecx;
SN[esi] = tabA[edx];
}
// 将用户名再次进行计算,然后从表二中得到一字符串。与上面的字符串是边在一起的。
/*
00401693 8B47 68 MOV EAX,DWORD PTR DS:[EDI+68] ; eax = &name
00401696 33F6 XOR ESI,ESI ; esi = 0
00401698 8B48 F8 MOV ECX,DWORD PTR DS:[EAX-8] ; ecx = len(name)
0040169B 85C9 TEST ECX,ECX
0040169D 7E 2C JLE SHORT crackme2.004016CB
0040169F 0FBE0C30 MOVSX ECX,BYTE PTR DS:[EAX+ESI] ; ecx = mid(name,i,1)
004016A3 8BC1 MOV EAX,ECX ; eax = ecx
004016A5 C1E0 05 SHL EAX,5 ; eax<<5
004016A8 2BC1 SUB EAX,ECX ; eax -=ecx
004016AA B9 28000000 MOV ECX,28 ; ecx = 28
004016AF 99 CDQ ; edx = 0
004016B0 F7F9 IDIV ECX ; eax /= ecx ; edx = eax % ecx
004016B2 8D4C24 0C LEA ECX,DWORD PTR SS:[ESP+C] ; 同上,传入一个地址的地址
004016B6 8A92 4C304000 MOV DL,BYTE PTR DS:[EDX+40304C] ; 查表:dl = [edx + 40304c]
004016BC 52 PUSH EDX
004016BD E8 DE020000 CALL <JMP.&MFC42.#940_??YCString@@QAEABV0@D@Z>
004016C2 8B47 68 MOV EAX,DWORD PTR DS:[EDI+68] ; eax = &name
004016C5 46 INC ESI ; esi++
004016C6 3B70 F8 CMP ESI,DWORD PTR DS:[EAX-8] ; if esi<len(name)
004016C9 ^ 7C D4 JL SHORT crackme2.0040169F ; go up
*/
ebx = strlen(name);
esi = 0;
for( ; esi < strlen(name); esi++)
{
ecx = name[esi];
eax = ecx<<5;
eax -= ecx;
ecx = 0x28;
edx = 0x0;
edx = eax%ecx;
SN[ebx+esi] = tabB[edx];
}
//将算出来的字符串进行计算,然后从表三中行到字符串,这就是我们想要的注册码了。
/*
004016CB 8B4424 0C MOV EAX,DWORD PTR SS:[ESP+C] ; eax = &SN ; SN = 算出的注册码
004016CF 33F6 XOR ESI,ESI ; esi = 0
004016D1 8B48 F8 MOV ECX,DWORD PTR DS:[EAX-8] ; ecx = len(SN)
004016D4 85C9 TEST ECX,ECX ; if ecx = 0
004016D6 7E 2D JLE SHORT crackme2.00401705 ; go over
004016D8 0FBE0406 MOVSX EAX,BYTE PTR DS:[ESI+EAX] ; eax = mid(SN,i,1)
004016DC 8D0C80 LEA ECX,DWORD PTR DS:[EAX+EAX*4] ; ecx = eax + eax * 4
004016DF 8D0448 LEA EAX,DWORD PTR DS:[EAX+ECX*2] ; eax += ecx * 2
004016E2 B9 28000000 MOV ECX,28 ; ecx = 28
004016E7 99 CDQ ; edx = 0
004016E8 F7F9 IDIV ECX ; eax /= ecx ; edx = eax % ecx
004016EA 8D4C24 0C LEA ECX,DWORD PTR SS:[ESP+C] ; 同上,传入一个地址的地址
004016EE 8A92 78304000 MOV DL,BYTE PTR DS:[EDX+403078] ; 查表:dl = [edx+403078]
004016F4 52 PUSH EDX
004016F5 56 PUSH ESI
004016F6 E8 9F020000 CALL <JMP.&MFC42.#5856_?SetAt@CString@@QAEXHD@Z>
004016FB 8B4424 0C MOV EAX,DWORD PTR SS:[ESP+C] ; eax = &SN
004016FF 46 INC ESI ; esi++
00401700 3B70 F8 CMP ESI,DWORD PTR DS:[EAX-8] ; if esi<len(SN)
00401703 ^ 7C D3 JL SHORT crackme2.004016D8 ; go up
*/
esi = 0;
for( ; esi < strlen(SN); esi++)
{
eax = SN[esi];
ecx = eax*5;
eax += ecx*2;
ecx = 0x28;
edx = 0;
edx = eax%ecx;
SN[esi] = tabC[edx];
}
printf("用户名:%s\n注册码:%s\n",name,SN);
//飘过,飘过了。
/*
00401705 8B77 64 MOV ESI,DWORD PTR DS:[EDI+64]
00401708 8B58 F8 MOV EBX,DWORD PTR DS:[EAX-8]
0040170B 3B5E F8 CMP EBX,DWORD PTR DS:[ESI-8] ; if ebx != len(sn) ' sn = 输入的注册码
0040170E 75 34 JNZ SHORT crackme2.00401744 ; go over
00401710 33C9 XOR ECX,ECX ; ecx = 0
00401712 85DB TEST EBX,EBX ; if SN == ""
00401714 7E 0D JLE SHORT crackme2.00401723 ; go GOOD
00401716 8A1401 MOV DL,BYTE PTR DS:[ECX+EAX] ; dl = mid(SN,ecx+&SN,1)
00401719 3A140E CMP DL,BYTE PTR DS:[ESI+ECX] ; if dl != (&sn+ecx)
0040171C 75 26 JNZ SHORT crackme2.00401744 ; go over
0040171E 41 INC ECX ; ecx++
0040171F 3BCB CMP ECX,EBX ; if ecx < ebx
00401721 ^ 7C F3 JL SHORT crackme2.00401716 ; go up
00401723 68 B8304000 PUSH crackme2.004030B8 ; ASCII "Very good!,You are a clever student!"
00401728 8D4F 60 LEA ECX,DWORD PTR DS:[EDI+60]
0040172B E8 34020000 CALL <JMP.&MFC42.#860_??4CString@@QAEABV0@PBD@Z> ; 恭喜你,成功了。
*/
return 0;
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)