【文章标题】: 【原创】ErShu's CrackMe 分析 附注册机
【文章作者】: lifestill
【作者邮箱】: zhong_sf@sina.com
【软件名称】: LErShu's Keygenme
【附件下载】: Crack Me.rar
最近因为考试 ,实在无聊 , 基本上的同学都放假了 ,就差我了, 还得考试
因此 ,心情感觉十分压抑 , 只好找个CrackMe 让自己淡定......:
转入正题, 这个CrackMe 很简单 ,根据szAccount(用户名)计算serial ,计算分三步:
step1. 一个循环 根据szAccount 按一定规则计算出三个 下文 待用结果 值, 分别是Ebp ,Ebx ,nTmp14(即esp+0x14 ,只是给它个名字,便于操作) .这三个中间值将在下文中用到
step2. 通过4个循环 , 每个循环5次 ,每个循环使用一个 上个step1中计算三个中间值,外加 VolumeNumber (经过了简单的改变) , 每个循环将相应的中间值经过计算计算出5个字符, 这分别的5个字符组成一个长为20个字符的字符串, 这个就是 serial 的中间值 szSerialTmp
step3. 在这一步中将step2中 szSerialTmp ,因为在step2中 组建的20个字符不一定都为可 视的字符 ,那么在这一步中就是将这20个字符经过一定的计算转化为可视的字符,若原来为可视的字符 则不改变它.
整个过程就是如此, 简单吧, 在这,还有个简单心得想和大家分享下 ,就是将一大段代码分模块 ,在每个模块中明确 这个模块的的目的是最重要的, 即这一段代码的输出值, 并且这个输出值将在后文中用到. 这个值就是我们所要关注的.其它的一些变量可能都是辅助于得到这个输出值. 这样在分析每段代码时目的就很确了, 整个过程也就更加明了了. 是吧, 不知道这样说对不对啊.
下面我们来看代码吧:
1.入口点,bp MessageBoxA 或 bp GetWindowTextA ,经过几步回溯之后便可很容易来到程序入口:
00401590 . 6A FF push -0x1
00401592 . 68 381E4000 push Crack_Me.00401E38 ; SE 处理程序安装
00401597 . 64:A1 0000000>mov eax,dword ptr fs:[0]
0040159D . 50 push eax
0040159E . 64:8925 00000>mov dword ptr fs:[0],esp
004015A5 . 51 push ecx
004015A6 . 56 push esi
004015A7 . 8BF1 mov esi,ecx
004015A9 . 6A 01 push 0x1
004015AB . E8 6A050000 call <jmp.&MFC42.#6334> ; 这是MFC.UpdateData() ,在里层 间接调用GetWindowTextA
004015B0 . 8B4E 60 mov ecx,dword ptr ds:[esi+0x60]
004015B3 . 8D46 60 lea eax,dword ptr ds:[esi+0x60]
004015B6 . 8B51 F8 mov edx,dword ptr ds:[ecx-0x8]
004015B9 . 85D2 test edx,edx
004015BB . 75 20 jnz XCrack_Me.004015DD
004015BD . 6A 00 push 0x0
004015BF . 6A 00 push 0x0
004015C1 . 68 38304000 push Crack_Me.00403038 ; ASCII "User Name is empty!"
004015C6 . 8BCE mov ecx,esi
004015C8 . E8 47050000 call <jmp.&MFC42.#4224>
004015CD . 5E pop esi
004015CE . 8B4C24 04 mov ecx,dword ptr ss:[esp+0x4]
004015D2 . 64:890D 00000>mov dword ptr fs:[0],ecx
004015D9 . 83C4 10 add esp,0x10
004015DC . C3 retn
004015DD > 8D5424 04 lea edx,dword ptr ss:[esp+0x4]
004015E1 . 50 push eax
004015E2 . 52 push edx
004015E3 . 8BCE mov ecx,esi
004015E5 . E8 66000000 call Crack_Me.00401650 ; _CalcSerial(...) 所有都计算在里面,F7跟进
004015EA . 8B46 64 mov eax,dword ptr ds:[esi+0x64]
004015ED . C74424 10 000>mov dword ptr ss:[esp+0x10],0x0 ; _CalcSerial(..) 之后马上与输入的假码比较_mbscmp
004015F5 . 50 push eax ; /s2
004015F6 . 8B4424 08 mov eax,dword ptr ss:[esp+0x8] ; |
004015FA . 50 push eax ; |s1
004015FB . FF15 C8214000 call dword ptr ds:[<&MSVCRT._mbscmp>] ; \_mbscmp
00401601 . 83C4 08 add esp,0x8
00401604 . 85C0 test eax,eax
00401606 . 6A 00 push 0x0
00401608 . 6A 00 push 0x0
0040160A . 75 0E jnz XCrack_Me.0040161A
0040160C . 68 28304000 push Crack_Me.00403028 ; ASCII "Great! pf! pf!"
00401611 . 8BCE mov ecx,esi
00401613 . E8 FC040000 call <jmp.&MFC42.#4224> ; MFC.MessageBox("Crack Success")
00401618 . EB 15 jmp XCrack_Me.0040162F
0040161A > 68 20304000 push Crack_Me.00403020 ; ASCII "fail!"
0040161F . 8BCE mov ecx,esi
00401621 . E8 EE040000 call <jmp.&MFC42.#4224> ; MFC.MessageBox("Crack Failed")
00401626 . 6A 00 push 0x0
00401628 . 8BCE mov ecx,esi
0040162A . E8 EB040000 call <jmp.&MFC42.#6334>
0040162F > 8D4C24 04 lea ecx,dword ptr ss:[esp+0x4]
00401633 . C74424 10 FFF>mov dword ptr ss:[esp+0x10],-0x1
0040163B . E8 C0030000 call <jmp.&MFC42.#800>
00401640 . 8B4C24 08 mov ecx,dword ptr ss:[esp+0x8]
00401644 . 5E pop esi
00401645 . 64:890D 00000>mov dword ptr fs:[0],ecx
0040164C . 83C4 10 add esp,0x10
0040164F . C3 retn
2.通过上面代码应该很清楚这步要做什么了, 没错, F7跟进 _CalcSerial(....) ,这个函数包含上面提到的所有step ,我们慢慢 分开来看:
2.1 这是初始化工作, 在这步中 ,最主要是得到了 VolumeNumber,
00401590 . 6A FF push -0x1
00401592 . 68 381E4000 push Crack_Me.00401E38 ; SE 处理程序安装
00401597 . 64:A1 0000000>mov eax,dword ptr fs:[0]
0040159D . 50 push eax
0040159E . 64:8925 00000>mov dword ptr fs:[0],esp
004015A5 . 51 push ecx
004015A6 . 56 push esi
004015A7 . 8BF1 mov esi,ecx
004015A9 . 6A 01 push 0x1
004015AB . E8 6A050000 call <jmp.&MFC42.#6334> ; 这是MFC.UpdateData() ,在里层 间接调用GetWindowTextA
004015B0 . 8B4E 60 mov ecx,dword ptr ds:[esi+0x60]
004015B3 . 8D46 60 lea eax,dword ptr ds:[esi+0x60]
004015B6 . 8B51 F8 mov edx,dword ptr ds:[ecx-0x8]
004015B9 . 85D2 test edx,edx
004015BB . 75 20 jnz XCrack_Me.004015DD
004015BD . 6A 00 push 0x0
004015BF . 6A 00 push 0x0
004015C1 . 68 38304000 push Crack_Me.00403038 ; ASCII "User Name is empty!"
004015C6 . 8BCE mov ecx,esi
004015C8 . E8 47050000 call <jmp.&MFC42.#4224>
004015CD . 5E pop esi
004015CE . 8B4C24 04 mov ecx,dword ptr ss:[esp+0x4]
004015D2 . 64:890D 00000>mov dword ptr fs:[0],ecx
004015D9 . 83C4 10 add esp,0x10
004015DC . C3 retn
004015DD > 8D5424 04 lea edx,dword ptr ss:[esp+0x4]
004015E1 . 50 push eax
004015E2 . 52 push edx
004015E3 . 8BCE mov ecx,esi
004015E5 . E8 66000000 call Crack_Me.00401650 ; _CalcSerial(...) 所有都计算在里面,F7跟进
004015EA . 8B46 64 mov eax,dword ptr ds:[esi+0x64]
004015ED . C74424 10 000>mov dword ptr ss:[esp+0x10],0x0 ; _CalcSerial(..) 之后马上与输入的假码比较_mbscmp
004015F5 . 50 push eax ; /s2
004015F6 . 8B4424 08 mov eax,dword ptr ss:[esp+0x8] ; |
004015FA . 50 push eax ; |s1
004015FB . FF15 C8214000 call dword ptr ds:[<&MSVCRT._mbscmp>] ; \_mbscmp
00401601 . 83C4 08 add esp,0x8
00401604 . 85C0 test eax,eax
00401606 . 6A 00 push 0x0
00401608 . 6A 00 push 0x0
0040160A . 75 0E jnz XCrack_Me.0040161A
0040160C . 68 28304000 push Crack_Me.00403028 ; ASCII "Great! pf! pf!"
00401611 . 8BCE mov ecx,esi
00401613 . E8 FC040000 call <jmp.&MFC42.#4224> ; MFC.MessageBox("Crack Success")
00401618 . EB 15 jmp XCrack_Me.0040162F
0040161A > 68 20304000 push Crack_Me.00403020 ; ASCII "fail!"
0040161F . 8BCE mov ecx,esi
00401621 . E8 EE040000 call <jmp.&MFC42.#4224> ; MFC.MessageBox("Crack Failed")
00401626 . 6A 00 push 0x0
00401628 . 8BCE mov ecx,esi
0040162A . E8 EB040000 call <jmp.&MFC42.#6334>
0040162F > 8D4C24 04 lea ecx,dword ptr ss:[esp+0x4]
00401633 . C74424 10 FFF>mov dword ptr ss:[esp+0x10],-0x1
0040163B . E8 C0030000 call <jmp.&MFC42.#800>
00401640 . 8B4C24 08 mov ecx,dword ptr ss:[esp+0x8]
00401644 . 5E pop esi
00401645 . 64:890D 00000>mov dword ptr fs:[0],ecx
0040164C . 83C4 10 add esp,0x10
0040164F . C3 retn
00401650 /$ 6A FF push -0x1 ; --------------
00401652 |. 68 6F1E4000 push Crack_Me.00401E6F ; SE 处理程序安装
00401657 |. 64:A1 0000000>mov eax,dword ptr fs:[0]
0040165D |. 50 push eax
0040165E |. 64:8925 00000>mov dword ptr fs:[0],esp
00401665 |. 83EC 34 sub esp,0x34
00401668 |. 33C0 xor eax,eax
0040166A |. 53 push ebx
0040166B |. 894424 21 mov dword ptr ss:[esp+0x21],eax
0040166F |. 55 push ebp
00401670 |. 894424 29 mov dword ptr ss:[esp+0x29],eax
00401674 |. 56 push esi ; 一系列初始化 ,不必在此纠结
00401675 |. 894424 31 mov dword ptr ss:[esp+0x31],eax
00401679 |. 33DB xor ebx,ebx
0040167B |. 894424 35 mov dword ptr ss:[esp+0x35],eax
0040167F |. 57 push edi
00401680 |. 8D4C24 18 lea ecx,dword ptr ss:[esp+0x18]
00401684 |. 895C24 20 mov dword ptr ss:[esp+0x20],ebx
00401688 |. 885C24 2C mov byte ptr ss:[esp+0x2C],bl
0040168C |. 894424 3D mov dword ptr ss:[esp+0x3D],eax ; --------------
00401690 |. E8 55040000 call <jmp.&MFC42.#540> ; CString()
00401695 |. 6A 0A push 0xA ; /pFileSystemNameSize = 0000000A
00401697 |. 53 push ebx ; |pFileSystemNameBuffer
00401698 |. 53 push ebx ; |pFileSystemFlags
00401699 |. 8D4C24 1C lea ecx,dword ptr ss:[esp+0x1C] ; |
0040169D |. 53 push ebx ; |pMaxFilenameLength
0040169E |. 51 push ecx ; |pVolumeSerialNumber
0040169F |. 6A 0C push 0xC ; |MaxVolumeNameSize = C (12.)
004016A1 |. BE 01000000 mov esi,0x1 ; |
004016A6 |. 53 push ebx ; |VolumeNameBuffer
004016A7 |. 68 50304000 push Crack_Me.00403050 ; |RootPathName = "C:\"
004016AC |. 897424 6C mov dword ptr ss:[esp+0x6C],esi ; |
004016B0 |. 895C24 34 mov dword ptr ss:[esp+0x34],ebx ; |
004016B4 |. 33ED xor ebp,ebp ; |这个函数主要是要得到 VolumeNumber ,其余不必理会
004016B6 |. 895C24 30 mov dword ptr ss:[esp+0x30],ebx ; |
004016BA |. FF15 00204000 call dword ptr ds:[<&KERNEL32.GetVolumeI>; \GetVolumeInformationA
004016C0 |. 8B4424 10 mov eax,dword ptr ss:[esp+0x10] ; eax = VolumeNumber
004016C4 |. 8B5424 58 mov edx,dword ptr ss:[esp+0x58]
004016C8 |. 35 26038319 xor eax,0x19830326 ; eax = VolumeSerialNumber xor 0x19830326
004016CD |. 83C9 FF or ecx,0xFFFFFFFF
004016D0 |. 8B12 mov edx,dword ptr ds:[edx] ; edx = szAcctount 即你输入的用户名
004016D2 |. 894424 10 mov dword ptr ss:[esp+0x10],eax
004016D6 |. 8BFA mov edi,edx
004016D8 |. 33C0 xor eax,eax
004016DA |. F2:AE repne scas byte ptr es:[edi]
004016DC |. F7D1 not ecx
004016DE |. 49 dec ecx
004016DF |. 895424 1C mov dword ptr ss:[esp+0x1C],edx
004016E3 |. 8BF9 mov edi,ecx ; edi = nAcctLen 即用户名长度
2.2 这步就是上面提到的step1了,具体见step1:
004016ED |. 897424 58 mov dword ptr ss:[esp+0x58],esi ; nTmp58 = esi
004016F1 |. 0F8C AF000000 jl Crack_Me.004017A6 ; while (esi-1 < AcctLen)
004016F7 DD05 30254000 fld qword ptr ds:[0x402530] ; {
004016FD |. EB 04 jmp XCrack_Me.00401703
004016FF |> 8B5424 1C /mov edx,dword ptr ss:[esp+0x1C]
00401703 |> 8A5C32 FF mov bl,byte ptr ds:[edx+esi-0x1] ; bl = szAcct[esi-1]
00401707 |. DB4424 58 |fild dword ptr ss:[esp+0x58]
0040170B |. 0FBEC3 |movsx eax,bl
0040170E |. DD5C24 24 |fstp qword ptr ss:[esp+0x24] ; nTmp24 = nTmp58 其实二者都等于 esi
00401712 |. 894424 58 |mov dword ptr ss:[esp+0x58],eax
00401716 |. DB4424 58 |fild dword ptr ss:[esp+0x58]
0040171A |. 0FBECB |movsx ecx,bl ; 这个while 循环 的计算结果放在 ebx ,ebp
0040171D |. D9FA |fsqrt ; nTmp14(即esp+0x14) 三个变量中 ,后面将用这3个值
0040171F |. 0FAFCE |imul ecx,esi
00401722 |. DC4C24 24 |fmul qword ptr ss:[esp+0x24]
00401726 |. DC05 28254000 |fadd qword ptr ds:[0x402528] ; sto = sqrt(szAcct[esi-1]) * nTmp24 + 1.0
0040172C |. 0FAFCE |imul ecx,esi
0040172F |. 894C24 58 |mov dword ptr ss:[esp+0x58],ecx
00401733 |. DB4424 58 |fild dword ptr ss:[esp+0x58]
00401737 |. DEC9 |fmulp st(1),st ; sto *= szAcct[esi-1] * esi * esi
00401739 D8C1 fadd st,st(1) ; sto += st1
0040173B |. E8 36040000 |call <jmp.&MSVCRT._ftol>
00401740 |. 99 |cdq
00401741 |. DDD8 |fstp st
00401743 |. B9 A0860100 |mov ecx,0x186A0
00401748 |. F7F9 |idiv ecx ; 1.计算 nTmp14
0040174A |. 895424 14 |mov dword ptr ss:[esp+0x14],edx ; nTmp14 = ftol(st0) % 0x186A0
0040174E |. 0FBED3 |movsx edx,bl
00401751 |. 895424 58 |mov dword ptr ss:[esp+0x58],edx
00401755 |. DB4424 58 |fild dword ptr ss:[esp+0x58]
00401759 |. DD05 20254000 |fld qword ptr ds:[0x402520]
0040175F |. E8 0C040000 |call <jmp.&MSVCRT._CIpow>
00401764 |. DC4C24 24 |fmul qword ptr ss:[esp+0x24] ; sto = szAcct[esi-1]^2 * nTmp24 其实 nTmp == esi
00401768 |. E8 09040000 |call <jmp.&MSVCRT._ftol> ; eax =_ftol(sto) + esi * ebp
0040176D |. DB4424 14 |fild dword ptr ss:[esp+0x14]
00401771 |. 8BCE |mov ecx,esi
00401773 |. 0FAFCD |imul ecx,ebp
00401776 |. D9C0 |fld st ; st1 = sto
00401778 |. D9FA |fsqrt ; sto = sqrt(nTmp14)
0040177A |. 03C1 |add eax,ecx
0040177C |. B9 A0860100 |mov ecx,0x186A0
00401781 |. 99 |cdq
00401782 |. F7F9 |idiv ecx ; 2.计算 ebp
00401784 |. 8BEA |mov ebp,edx ; ebp = eax % 0x186A0
00401786 |. E8 EB030000 |call <jmp.&MSVCRT._ftol>
0040178B |. 03C5 |add eax,ebp ; eax = _ftol(sto) + ebp
0040178D |. B9 A0860100 |mov ecx,0x186A0
00401792 |. 99 |cdq
00401793 |. F7F9 |idiv ecx
00401795 |. 46 |inc esi
00401796 |. 3BF7 |cmp esi,edi
00401798 |. 897424 58 |mov dword ptr ss:[esp+0x58],esi ; 3.计算 ebx nTmp58 = esi
0040179C |. 8BDA |mov ebx,edx ; ebx = (_ftol(st0)+ebp) % 0x186A0
0040179E |.^ 0F8E 5BFFFFFF \jle Crack_Me.004016FF ; }
004017A4 |. DDD8 fstp st
很明确,在这步中得到了三个输出值 Ebp ,Ebx ,nTmp14(esp+0x14) , 对应的C语言代码如下:
//step1 : _Calc nEbp ,nEbx ,nTmp14
for (i = 1 ;i <= lstrlen(szAcct) ;i++)
{
st0 = (sqrt(szAcct[i-1]) * i + 1.0);
st0 = st0 * (szAcct[i-1]*i*i) + st1;
FtoInt = st0;
nTmp14 = FtoInt % 0x186A0;
FtoInt = st0 = szAcct[i-1]*szAcct[i-1]*i;
FtoInt += (nEbp*i);
nEbp = FtoInt % 0x186A0;
st1 = st0 = nTmp14;
FtoInt = sqrt(st0) + nEbp;
nEbx = FtoInt % 0x186A0;
}
2.3 这是step2部分的代码具体实现 ,同样,详细见step2:
004017A6 |> \33C0 xor eax,eax ; while (eax < 5) 结果放于 Buf2c 中
004017A8 |> 8BD0 /mov edx,eax ; {
004017AA |. 8B4C24 14 |mov ecx,dword ptr ss:[esp+0x14]
004017AE |. 0FAFD0 |imul edx,eax
004017B1 |. 0FAFD0 |imul edx,eax
004017B4 |. 8D540A 1F |lea edx,dword ptr ds:[edx+ecx+0x1F]
004017B8 |. 81E2 7F000080 |and edx,0x8000007F ; edx = (eax^3 + nTmp14 + 0x1F) & 0x8000007F
004017BE |. 79 05 |jns XCrack_Me.004017C5 ; if (edx < 0)
004017C0 |. 4A |dec edx ; edx-- ;edx |= 0xFFFFFF80 ;edx++
004017C1 |. 83CA 80 |or edx,0xFFFFFF80
004017C4 |. 42 |inc edx
004017C5 |> 885404 2C |mov byte ptr ss:[esp+eax+0x2C],dl ; Buf2c[eax] = dl
004017C9 |. 40 |inc eax
004017CA |. 83F8 05 |cmp eax,0x5
004017CD |.^ 7C D9 \jl XCrack_Me.004017A8 ; }
004017CF |. B8 05000000 mov eax,0x5 ; while (eax < 0xA) 结果继续放于 Buf2c 中
004017D4 |> 8BC8 /mov ecx,eax ; {
004017D6 |. 0FAFC8 |imul ecx,eax
004017D9 |. 0FAFC8 |imul ecx,eax
004017DC |. 8D5429 1F |lea edx,dword ptr ds:[ecx+ebp+0x1F]
004017E0 |. 81E2 7F000080 |and edx,0x8000007F ; edx = (eax^3 + ebp + 0x1F) & 0x8000007F
004017E6 |. 79 05 |jns XCrack_Me.004017ED ; if (edx < 0)
004017E8 |. 4A |dec edx ; edx-- ;edx |= 0xFFFFFF80 ;edx++
004017E9 |. 83CA 80 |or edx,0xFFFFFF80
004017EC |. 42 |inc edx
004017ED |> 885404 2C |mov byte ptr ss:[esp+eax+0x2C],dl ; Buf2c[eax] = dl
004017F1 |. 40 |inc eax
004017F2 |. 83F8 0A |cmp eax,0xA
004017F5 |.^ 7C DD \jl XCrack_Me.004017D4 ; }
004017F7 |. B8 0A000000 mov eax,0xA
004017FC |> 8BC8 /mov ecx,eax ; while (eax < 0xA) 结果继续放于 Buf2c 中
004017FE |. 0FAFC8 |imul ecx,eax ; {
00401801 |. 0FAFC8 |imul ecx,eax
00401804 |. 8D5419 1F |lea edx,dword ptr ds:[ecx+ebx+0x1F]
00401808 |. 81E2 7F000080 |and edx,0x8000007F ; edx = (eax^3 + ebx + 0x1F) & 0x8000007F
0040180E |. 79 05 |jns XCrack_Me.00401815 ; if (edx < 0)
00401810 |. 4A |dec edx ; edx-- ;edx |= 0xFFFFFF80 ;edx++
00401811 |. 83CA 80 |or edx,0xFFFFFF80
00401814 |. 42 |inc edx
00401815 |> 885404 2C |mov byte ptr ss:[esp+eax+0x2C],dl ; Buf2c[eax] = dl
00401819 |. 40 |inc eax
0040181A |. 83F8 0F |cmp eax,0xF
0040181D |.^ 7C DD \jl XCrack_Me.004017FC ; }
0040181F |. B8 0F000000 mov eax,0xF
00401824 |> 8BC8 /mov ecx,eax ; while (eax < 0xA) 结果继续放于 Buf2c 中
00401826 |. 8B5424 10 |mov edx,dword ptr ss:[esp+0x10]
0040182A |. 0FAFC8 |imul ecx,eax
0040182D |. 0FAFC8 |imul ecx,eax
00401830 |. 8D4C11 1F |lea ecx,dword ptr ds:[ecx+edx+0x1F]
00401834 |. 81E1 7F000080 |and ecx,0x8000007F ; ecx = (eax^3 + VolumeNumber + 0x1F) & 0x8000007F
0040183A |. 79 05 |jns XCrack_Me.00401841 ; if (ecx < 0)
0040183C |. 49 |dec ecx ; edx-- ;edx |= 0xFFFFFF80 ;edx++
0040183D |. 83C9 80 |or ecx,0xFFFFFF80
00401840 |. 41 |inc ecx
00401841 |> 884C04 2C |mov byte ptr ss:[esp+eax+0x2C],cl ; Buf2c[eax] = cl
00401845 |. 40 |inc eax
00401846 |. 83F8 14 |cmp eax,0x14
00401849 |.^ 7C D9 \jl XCrack_Me.00401824 ; }
0040184B |. 33D2 xor edx,edx
同样 ,对应的C代码也附上:
char szSerial[100] = {0};
//step2: Construct string
_CstStr(0 ,szSerial ,nTmp14);
_CstStr(5 ,szSerial ,nEbp);
_CstStr(10 ,szSerial ,nEbx);
_CstStr(15 ,szSerial ,nVoSerial);
void _CstStr(
int ndexStart,
char* lpBuf,
int nKey
)
{
int nTmp = 0;
for (int i = 0 ;i < 0x5 ;i++ ,ndexStart++)
{
nTmp = ndexStart*ndexStart*ndexStart + nKey + 0x1F;
nTmp &= 0x8000007F;
if (nTmp < 0)
{
nTmp--;
nTmp |= 0xFFFFFF80;
nTmp++;
}
lpBuf[ndexStart] = nTmp;
}
}
2.4 最后就是字符转化工作了, 如step3 所述:
0040184D |. 33C9 xor ecx,ecx ; while (ecx < 0x8c)
0040184F |> 8A4414 2C /mov al,byte ptr ss:[esp+edx+0x2C] ; {
00401853 |. 3C 30 |cmp al,0x30 ; al = byte Buf2c[edx]
00401855 |. 7C 04 |jl XCrack_Me.0040185B
00401857 |. 3C 39 |cmp al,0x39
00401859 |. 7E 29 |jle XCrack_Me.00401884
0040185B |> 3C 41 |cmp al,0x41 ; 这个循环旨在将 Buf2c 中所有字节转化数字或字母
0040185D |. 7C 04 |jl XCrack_Me.00401863
0040185F |. 3C 5A |cmp al,0x5A
00401861 |. 7E 21 |jle XCrack_Me.00401884
00401863 |> 3C 61 |cmp al,0x61
00401865 |. 7C 04 |jl XCrack_Me.0040186B
00401867 |. 3C 7A |cmp al,0x7A ; if (al 不是数字 或 字母)
00401869 |. 7E 19 |jle XCrack_Me.00401884 ; {
0040186B |> 0FBEC0 |movsx eax,al ; while (al == 数字 或 字母)
0040186E |. 8D4408 1F |lea eax,dword ptr ds:[eax+ecx+0x1F] ; {
00401872 |. 25 7F000080 |and eax,0x8000007F ; eax = (al + ecx + 0x1F) & 0x8000007F
00401877 |. 79 05 |jns XCrack_Me.0040187E ; Buf2c[edx] = al
00401879 |. 48 |dec eax ; }
0040187A |. 83C8 80 |or eax,0xFFFFFF80
0040187D |. 40 |inc eax
0040187E |> 884414 2C |mov byte ptr ss:[esp+edx+0x2C],al
00401882 |.^ EB CB |jmp XCrack_Me.0040184F ; }
00401884 |> 83C1 07 |add ecx,0x7
00401887 |. 42 |inc edx
00401888 |. 81F9 8C000000 |cmp ecx,0x8C
0040188E |.^ 7C BF \jl XCrack_Me.0040184F ; }
00401890 |. 8D4C24 2C lea ecx,dword ptr ss:[esp+0x2C]
00401894 |. 8D5424 18 lea edx,dword ptr ss:[esp+0x18]
00401898 |. 51 push ecx
00401899 |. 68 4C304000 push Crack_Me.0040304C ; ASCII "%s"
0040189E |. 52 push edx
0040189F |. E8 82020000 call <jmp.&MFC42.#2818> ; str.Format()
004018A4 |. 83C4 0C add esp,0xC
004018A7 |> 8B7424 54 mov esi,dword ptr ss:[esp+0x54]
004018AB |. 8D4424 18 lea eax,dword ptr ss:[esp+0x18]
004018AF |. 50 push eax
004018B0 |. 8BCE mov ecx,esi
004018B2 |. E8 69020000 call <jmp.&MFC42.#535> ; Cstring(&str)
004018B7 |. C74424 20 010>mov dword ptr ss:[esp+0x20],0x1
004018BF |. 8D4C24 18 lea ecx,dword ptr ss:[esp+0x18]
004018C3 |. C64424 4C 00 mov byte ptr ss:[esp+0x4C],0x0
004018C8 |. E8 33010000 call <jmp.&MFC42.#800> ; ~Cstring
004018CD |. 8B4C24 44 mov ecx,dword ptr ss:[esp+0x44]
004018D1 |. 8BC6 mov eax,esi ; eax = szSerial
004018D3 |. 5F pop edi
004018D4 |. 5E pop esi
004018D5 |. 5D pop ebp
004018D6 |. 5B pop ebx
004018D7 |. 64:890D 00000>mov dword ptr fs:[0],ecx
004018DE |. 83C4 40 add esp,0x40
004018E1 \. C2 0800 retn 0x8
如下便是对应的C代码咯:
char szChar = 0;
for (i = 0 ,j = 0 ;i < 20 ;i++ ,j += 0x7)
{
szChar = szSerial[i];
while (szChar < 0x30 || (szChar>0x39 && szChar<0x41) ||
(szChar>0x5A && szChar < 0x61) || szChar > 0x7A)
{
szChar = (szChar+j+0x1F) & 0x8000007F;
if (szChar < 0)
{
szChar--;
szChar &= 0xFFFFFF80;
szChar++;
}
szSerial[i] = szChar;
}
}
3. 经过上面的step就得到了真正的serial, 下面是完整的注册机代码:
#include <stdio.h>
#include <math.h>
#include <windows.h>
void _CstStr(
int ndexStart,
char* lpBuf,
int nKey
)
{
int nTmp = 0;
for (int i = 0 ;i < 0x5 ;i++ ,ndexStart++)
{
nTmp = ndexStart*ndexStart*ndexStart + nKey + 0x1F;
nTmp &= 0x8000007F;
if (nTmp < 0)
{
nTmp--;
nTmp |= 0xFFFFFF80;
nTmp++;
}
lpBuf[ndexStart] = nTmp;
}
}
int main()
{
unsigned long nVoSerial = 0;
GetVolumeInformation("C:\\" ,NULL ,0 ,&nVoSerial ,NULL ,0 ,NULL ,0);
nVoSerial ^= 0x19830326;
char szAcct[50] = {0};
printf("Enter Account: ");
scanf("%s" ,szAcct);
double st0 ,st1 = 0;
int i ,j ,FtoInt ,nTmp14 ,nEbx ,nEbp = 0;
//step1 : _Calc nEbp ,nEbx ,nTmp14
for (i = 1 ;i <= lstrlen(szAcct) ;i++)
{
st0 = (sqrt(szAcct[i-1]) * i + 1.0);
st0 = st0 * (szAcct[i-1]*i*i) + st1;
FtoInt = st0;
nTmp14 = FtoInt % 0x186A0;
FtoInt = st0 = szAcct[i-1]*szAcct[i-1]*i;
FtoInt += (nEbp*i);
nEbp = FtoInt % 0x186A0;
st1 = st0 = nTmp14;
FtoInt = sqrt(st0) + nEbp;
nEbx = FtoInt % 0x186A0;
}
char szSerial[100] = {0};
//step2: Construct string
_CstStr(0 ,szSerial ,nTmp14);
_CstStr(5 ,szSerial ,nEbp);
_CstStr(10 ,szSerial ,nEbx);
_CstStr(15 ,szSerial ,nVoSerial);
//step3: modify if the byte of szSerial
//not char or number
char szChar = 0;
for (i = 0 ,j = 0 ;i < 20 ;i++ ,j += 0x7)
{
szChar = szSerial[i];
while (szChar < 0x30 || (szChar>0x39 && szChar<0x41) ||
(szChar>0x5A && szChar < 0x61) || szChar > 0x7A)
{
szChar = (szChar+j+0x1F) & 0x8000007F;
if (szChar < 0)
{
szChar--;
szChar &= 0xFFFFFF80;
szChar++;
}
szSerial[i] = szChar;
}
}
return printf("Serial: %s\n" ,szSerial);
}
晚安, 各位朋友们
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课