【文章标题】: 【原创】Lesco's Keygenme 分析 附注册机
【文章作者】: lifestill
【作者邮箱】: zhong_sf@sina.com
【软件名称】: Lesco's Keygenme
【附件下载】: kgme.zip
这个KeygenMe是得到登陆名szAcctount与PC用户名szUserName之后.
1. 调用 _CalcRetStr(szUserName.....) 得到 lpRetStr1 及 _CalcRetStr(szAccount)得到 lpRetstr2,到这是第一步骤.
2. 调用 _CalcRetstrCmb(lpRetStr1 ,lpRetStr2....)以一定的方式组合lpRetStr1 与lpRetStr2得到 lpRetStrCmb.到这是第二步骤,
3. 调用 _CalcEbx(szAccount......)计算得到Ebx这是第三步骤,
4. 在这一步骤中是根据第二步骤计算得到的lpRetStrCmb调用 _CalcCode(lpRetStrCmb.....)
计算组合了一份加密用的机器码lpCode, 再让程序跳到lpCode这段代码中去运行进行最后 的加 密.加密的对象就是将你输入的serial转化为16进制的nSerial 加密之后得到nSerialEncrypted ,最后将第三步骤计算得到的Ebx与nSerialEncrypted比较,相等则Crake OK!
总体大概就是这样,经过上面的过程分析,思路应该是比较清晰的... 哈哈
注:上面所提到的_Calc....()之类的函数在真正的程序中并未出现,在这里只是为是分析的方便而将一系列加密过程模块化,便于思路整理 ,便于理解 ,同时下面的讲解与注册机 也是基于这种模块的划分而进行的 . 如有不正确的地方 ,肯请看雪的各位大侠 赐教 ,
下面我们一步步来看:
1.首先是进攻的入口, 程序比较简单,因此大可不必通过下断找入口.
下面这段代码主要得到登陆名(szAccount)与序列号(szSerial),转而调用_CalcKernel(....),进 行主要加密过程,上面所说的所有步骤都包含这个函数中,这个函数返回(在Eax中)的是 将nSerialEncrypted与Ebx比较的结果,往下就是根据二者是否相等 MessageBox ,这是宏观的过程
0040158D > \8B7C24 14 mov edi,dword ptr ss:[esp+0x14] ; Case 3EA of switch 0040155C
00401591 . 6A 00 push 0x0 ; /lParam = 0
00401593 . 6A 00 push 0x0 ; |wParam = 0
00401595 . 6A 0E push 0xE ; |Message = WM_GETTEXTLENGTH
00401597 . 68 E8030000 push 0x3E8 ; |ControlID = 3E8 (1000.)
0040159C . 57 push edi ; |hWnd
0040159D . FF15 B4504000 call dword ptr ds:[<&USER32.SendDlgItemM>; \SendDlgItemMessageA
004015A3 . 8BF0 mov esi,eax
004015A5 . 85F6 test esi,esi
004015A7 . 75 1A jnz Xkgme.004015C3
004015A9 . 50 push eax ; /Style
004015AA . 50 push eax ; |Title
004015AB . 68 6C614000 push kgme.0040616C ; |Text = "No name entered"
004015B0 . 57 push edi ; |hOwner
004015B1 . FF15 B0504000 call dword ptr ds:[<&USER32.MessageBoxA>>; \MessageBoxA
004015B7 . 5F pop edi
004015B8 . 5E pop esi
004015B9 . 5D pop ebp
004015BA . B8 01000000 mov eax,0x1
004015BF . 5B pop ebx
004015C0 . C2 1000 retn 0x10
004015C3 > A1 C0664000 mov eax,dword ptr ds:[0x4066C0]
004015C8 . 8B2D 5C504000 mov ebp,dword ptr ds:[<&KERNEL32.HeapAll>; ntdll.RtlAllocateHeap
004015CE . 46 inc esi
004015CF . 56 push esi ; /HeapSize
004015D0 . 6A 08 push 0x8 ; |Flags = HEAP_ZERO_MEMORY
004015D2 . 50 push eax ; |hHeap => 00290000
004015D3 . FFD5 call ebp ; \HeapAlloc
004015D5 . 8BD8 mov ebx,eax
004015D7 . 56 push esi ; /Count
004015D8 . 53 push ebx ; |Buffer
004015D9 . 68 E8030000 push 0x3E8 ; |ControlID = 3E8 (1000.)
004015DE . 57 push edi ; |hWnd
004015DF . FF15 A8504000 call dword ptr ds:[<&USER32.GetDlgItemTe>; \GetDlgItemText() 得到登陆名szAccount
004015E5 . 6A 00 push 0x0 ; /lParam = 0
004015E7 . 6A 00 push 0x0 ; |wParam = 0
004015E9 . 6A 0E push 0xE ; |Message = WM_GETTEXTLENGTH
004015EB . 68 E9030000 push 0x3E9 ; |ControlID = 3E9 (1001.)
004015F0 . 57 push edi ; |hWnd
004015F1 . FF15 B4504000 call dword ptr ds:[<&USER32.SendDlgItemM>; \SendDlgItemMessageA
004015F7 . 8BF0 mov esi,eax
004015F9 . 85F6 test esi,esi
004015FB . 75 1A jnz Xkgme.00401617
004015FD . 50 push eax ; /Style
004015FE . 50 push eax ; |Title
004015FF . 68 58614000 push kgme.00406158 ; |Text = "No serial entered"
00401604 . 57 push edi ; |hOwner
00401605 . FF15 B0504000 call dword ptr ds:[<&USER32.MessageBoxA>>; \MessageBoxA
0040160B . 5F pop edi
0040160C . 5E pop esi
0040160D . 5D pop ebp
0040160E . B8 01000000 mov eax,0x1
00401613 . 5B pop ebx
00401614 . C2 1000 retn 0x10
00401617 > 8B0D C0664000 mov ecx,dword ptr ds:[0x4066C0]
0040161D . 46 inc esi
0040161E . 56 push esi
0040161F . 6A 08 push 0x8
00401621 . 51 push ecx
00401622 . FFD5 call ebp
00401624 . 8BE8 mov ebp,eax
00401626 . 56 push esi ; /Count
00401627 . 55 push ebp ; |Buffer
00401628 . 68 E9030000 push 0x3E9 ; |ControlID = 3E9 (1001.)
0040162D . 57 push edi ; |hWnd
0040162E . FF15 A8504000 call dword ptr ds:[<&USER32.GetDlgItemTe>; \GetDlgItemText() 得到序列号szSerial
00401634 . 55 push ebp ; --------------------------------------------------------
00401635 . 53 push ebx
00401636 . E8 A5FCFFFF call kgme.004012E0 ; _CalcKernel(AcctBuf ,PswBuf)所有的加密处理都在这里进行
0040163B . 83C4 08 add esp,0x8 ; eax返回的是上面说的nSerialEncrypted与Ebx的比较结果,相同则非0
0040163E . 84C0 test al,al ; ----这里测试比较结果,al = 0则wrong,
00401640 . 74 0E je Xkgme.00401650 ; 可见,爆破是相当简单的
00401642 . 6A 40 push 0x40
00401644 . 68 50614000 push kgme.00406150 ; ASCII "Great!"
00401649 . 68 F4604000 push kgme.004060F4 ; ASCII "Congratulations! You made it! I hope you didn't patch me!
Now write a keygen and a tutorial"
0040164E . EB 0C jmp Xkgme.0040165C
00401650 > 6A 10 push 0x10
00401652 . 68 EC604000 push kgme.004060EC ; ASCII "Wrong"
00401657 . 68 CC604000 push kgme.004060CC ; ASCII "No, that's not it. Try again"
0040165C > 57 push edi ; |hOwner
0040165D . FF15 B0504000 call dword ptr ds:[<&USER32.MessageBoxA>>; \MessageBoxA
2.上面的都不是重点,这时要做什么应该很清楚吧,没错, F7跟进_CalcKernel(.....),因为这个函数比较长,我们模块来看它,模块划分是基于上述步骤:
2.1.这段主要是上述步骤的第一步 ,GetUserName()得到 用户名(szUserName), 接着调用_CalcRetStr(szUserName..)计算得到一个szUserName返回字符串lpRetStr1 ,及_CalcRetStr(szAccount....)计算得到一个szAccount返回字符串lpRetStr2. 上代码
004012E0 /$ 81EC 14010000 sub esp,0x114
004012E6 |. 53 push ebx ; ebx = AcctBuf
004012E7 |. 55 push ebp ; ebp = PswBuf
004012E8 |. 56 push esi ; esi = nPswLen
004012E9 |. 8D4424 0C lea eax,dword ptr ss:[esp+0xC]
004012ED |. 57 push edi
004012EE |. 8D4C24 24 lea ecx,dword ptr ss:[esp+0x24]
004012F2 |. 50 push eax ; /pBufCount
004012F3 |. 51 push ecx ; |Buffer
004012F4 |. C74424 18 000>mov dword ptr ss:[esp+0x18],0x100 ; |
004012FC |. FF15 00504000 call dword ptr ds:[<&ADVAPI32.GetUserNam>; \GetUserName() 得到szUserName
00401302 |. 85C0 test eax,eax
00401304 |. 75 37 jnz Xkgme.0040133D
00401306 |. BF A8604000 mov edi,kgme.004060A8 ; ASCII "your username is definitly too long"
0040130B |. 83C9 FF or ecx,0xFFFFFFFF
0040130E |. F2:AE repne scas byte ptr es:[edi]
00401310 |. F7D1 not ecx
00401312 |. 2BF9 sub edi,ecx
00401314 |. 8D5424 24 lea edx,dword ptr ss:[esp+0x24]
00401318 |. 8BC1 mov eax,ecx
0040131A |. 8BF7 mov esi,edi
0040131C |. 8BFA mov edi,edx
0040131E |. C1E9 02 shr ecx,0x2
00401321 |. F3:A5 rep movs dword ptr es:[edi],dword ptr ds>
00401323 |. 8BC8 mov ecx,eax
00401325 |. 33C0 xor eax,eax
00401327 |. 83E1 03 and ecx,0x3
0040132A |. F3:A4 rep movs byte ptr es:[edi],byte ptr ds:[>
0040132C |. 8D7C24 24 lea edi,dword ptr ss:[esp+0x24]
00401330 |. 83C9 FF or ecx,0xFFFFFFFF
00401333 |. F2:AE repne scas byte ptr es:[edi]
00401335 |. F7D1 not ecx
00401337 |. 894C24 10 mov dword ptr ss:[esp+0x10],ecx
0040133B |. EB 04 jmp Xkgme.00401341
0040133D |> 8B4C24 10 mov ecx,dword ptr ss:[esp+0x10]
00401341 |> 49 dec ecx
00401342 |. 51 push ecx ; ecx = UserNameLen
00401343 |. 8D4C24 28 lea ecx,dword ptr ss:[esp+0x28]
00401347 |. 51 push ecx ; ecx = UserNameBuf
00401348 |. E8 13040000 call kgme.00401760 ; _SubCalcProc1(szUserName ,UserNameLen)返回字符串lpRetStr1
0040134D |. 8BAC24 300100>mov ebp,dword ptr ss:[esp+0x130]
00401354 |. 8BF0 mov esi,eax ; esi = lpRetStr1
00401356 |. 8BFD mov edi,ebp ; edi = szAccount
00401358 |. 83C9 FF or ecx,0xFFFFFFFF
0040135B |. 33C0 xor eax,eax
0040135D |. F2:AE repne scas byte ptr es:[edi]
0040135F |. F7D1 not ecx
00401361 |. 49 dec ecx
00401362 |. 51 push ecx
00401363 |. 55 push ebp
00401364 |. E8 F7030000 call kgme.00401760 ; _CalcRetStr (szAccount,nAcctLen)返回字符串lpRetStr2
00401369 |. 894424 28 mov dword ptr ss:[esp+0x28],eax
2.1.1.趁热打铁, 我们来分析下_CalcRetStr(....)过程, F7跟进.....
0040175E 90 nop
0040175F 90 nop ; _CalcRetStr (szBuf ,szBufLen)
00401760 /$ 55 push ebp ; {
00401761 |. 8B6C24 0C mov ebp,dword ptr ss:[esp+0xC] ; ebx =szBuf
00401765 |. 56 push esi
00401766 |. 8D442D 01 lea eax,dword ptr ss:[ebp+ebp+0x1]
0040176A |. 50 push eax
0040176B |. E8 1D030000 call kgme.00401A8D ; lpRetStr = Malloc (nSize)
00401770 |. 83C4 04 add esp,0x4
00401773 |. 33C9 xor ecx,ecx
00401775 |. 33D2 xor edx,edx
00401777 |. 8BF0 mov esi,eax ; esi = lpRetStr
00401779 |. 85ED test ebp,ebp
0040177B |. 76 3A jbe Xkgme.004017B7
0040177D |. 57 push edi
0040177E |. 8B7C24 10 mov edi,dword ptr ss:[esp+0x10] ; edi = szBuf edx = ecx = Counter = 0 开始
00401782 |> 8A0439 /mov al,byte ptr ds:[ecx+edi] ; while (ecx < nBufLen)
00401785 |. 83C2 02 |add edx,0x2 ; {
00401788 |. C1F8 04 |sar eax,0x4
0040178B |. 83E0 0F |and eax,0xF ; eax = Byte szBuf[ecx] 的高4位
0040178E |. 8A80 F0504000 |mov al,byte ptr ds:[eax+0x4050F0] ; 以eax 作下标 得: al = byte RandStr[eax]
00401794 |. 884416 FE |mov byte ptr ds:[esi+edx-0x2],al ; lpRetStr[edx-2] = al
00401798 |. 8A0439 |mov al,byte ptr ds:[ecx+edi]
0040179B |. 83E0 0F |and eax,0xF ; eax = Byte UserNameBuf[ecx] 的低4位
0040179E |. 41 |inc ecx
0040179F |. 3BCD |cmp ecx,ebp
004017A1 |. 8A80 F0504000 |mov al,byte ptr ds:[eax+0x4050F0] ; al = RandStr[eax];
004017A7 |. 884416 FF |mov byte ptr ds:[esi+edx-0x1],al ; lpRetStr[edx-1] = al
004017AB |.^ 72 D5 \jb Xkgme.00401782 ; }
004017AD |. C60432 00 mov byte ptr ds:[edx+esi],0x0 ; 字符串末尾写入0
004017B1 |. 8BC6 mov eax,esi
004017B3 |. 5F pop edi
004017B4 |. 5E pop esi
004017B5 |. 5D pop ebp
004017B6 |. C3 retn ; }
同时给出 对应的C语言源码吧,方便对应 :
代码中的 szRand1 是程序中全局的一份字符串 "6Ghd3iHRaSkL,;-Z";
char* _CalcRetstr(
char* szBuf,
int nBufLen
)
{
char szTmp;
char* lpBufRet = new char[nBufLen*2+1];
for (int i = 0 ;i < nBufLen ;i++)
{
szTmp = (szBuf[i] >> 4) & 0xF;
szTmp = szRand1[szTmp];
lpBufRet[i*2] = szTmp;
szTmp = szBuf[i] & 0xF;
szTmp = szRand1[szTmp];
lpBufRet[i*2+1] = szTmp;
}
lpBufRet[nBufLen*2] = 0;
return lpBufRet;
}
2.2 我们再往下看吧, 接下来的这部分当然就是上述步骤的第2步骤了,这部分调用 _CalcRetstrCmb()来按一定规则来组合第1步骤得到的2份返回字符串(lpRetStr1 ,lpRetStr2) 来得到 第3份数据 lpRetStCmb, 好,上代码
0040136D |. 8BF8 mov edi,eax
0040136F |. 83C9 FF or ecx,0xFFFFFFFF
00401372 |. 33C0 xor eax,eax
00401374 |. 83C4 10 add esp,0x10
00401377 |. F2:AE repne scas byte ptr es:[edi]
00401379 |. F7D1 not ecx
0040137B |. 49 dec ecx
0040137C |. 8BFE mov edi,esi
0040137E |. 8BD1 mov edx,ecx
00401380 |. 83C9 FF or ecx,0xFFFFFFFF
00401383 |. F2:AE repne scas byte ptr es:[edi]
00401385 |. F7D1 not ecx
00401387 |. 49 dec ecx
00401388 |. 03D1 add edx,ecx ; edx = PNewAddrRet1Len + PNewAddrRet2Len2
0040138A |. 895424 20 mov dword ptr ss:[esp+0x20],edx
0040138E |. 52 push edx ; /dwBytes
0040138F |. 8B15 C0664000 mov edx,dword ptr ds:[0x4066C0] ; |
00401395 |. 6A 40 push 0x40 ; |dwFlags = 40
00401397 |. 52 push edx ; |hHeap => 00290000
00401398 |. FF15 5C504000 call dword ptr ds:[<&KERNEL32.HeapAlloc>>; \RtlAllocateHeap
0040139E |. 8BD0 mov edx,eax ; edx = lpRetStrCmb
004013A0 |. 8BFE mov edi,esi
004013A2 |. 83C9 FF or ecx,0xFFFFFFFF
004013A5 |. 33C0 xor eax,eax
004013A7 |. 33DB xor ebx,ebx
004013A9 |. 895424 14 mov dword ptr ss:[esp+0x14],edx
004013AD |. F2:AE repne scas byte ptr es:[edi]
004013AF |. F7D1 not ecx
004013B1 |. 49 dec ecx
004013B2 |. 74 39 je Xkgme.004013ED ; 这个循环根据lpRetStr1 填写新分配的lpRetStrCmb前部分
004013B4 |. 8BFE mov edi,esi ; edi = esi = lpRetStr1
004013B6 |. 8BC2 mov eax,edx ; eax = edx = lpRetStrCmb
004013B8 |. 2BF8 sub edi,eax ; edi = lpRetStr1 - lpRetStrCmb
004013BA |. 897C24 1C mov dword ptr ss:[esp+0x1C],edi
004013BE |. EB 04 jmp Xkgme.004013C4 ; while(ebx < lpRetStr1Len)
004013C0 |> 8B7C24 1C /mov edi,dword ptr ss:[esp+0x1C] ; {
004013C4 |> 8A0C17 mov cl,byte ptr ds:[edi+edx] ; cl = lpRetStr1[i1]
004013C7 |. 33C0 |xor eax,eax
004013C9 |> 3888 C0504000 |/cmp byte ptr ds:[eax+0x4050C0],cl ; while( szRand[eax] != cl)
004013CF |. 74 06 ||je Xkgme.004013D7 ; {
004013D1 |. 40 ||inc eax ; eax++
004013D2 |. 83F8 10 ||cmp eax,0x10 ; if (eax >= 0x10) Break;
004013D5 |.^ 72 F2 |\jb Xkgme.004013C9 ; }
004013D7 |> 34 23 |xor al,0x23 ; 最终下标 al ^= 0x23
004013D9 43 inc ebx
004013DA 8802 mov byte ptr ds:[edx],al ; lpRetStrCmb[i2] = al
004013DC 8BFE mov edi,esi
004013DE 83C9 FF or ecx,0xFFFFFFFF
004013E1 33C0 xor eax,eax
004013E3 42 inc edx ; edx++ ebx++
004013E4 |. F2:AE |repne scas byte ptr es:[edi]
004013E6 |. F7D1 |not ecx
004013E8 |. 49 |dec ecx
004013E9 |. 3BD9 |cmp ebx,ecx
004013EB |.^ 72 D3 \jb Xkgme.004013C0 ; }
004013ED |> 8B7424 18 mov esi,dword ptr ss:[esp+0x18] ; esi = lpRetStr2
004013F1 |. 83C9 FF or ecx,0xFFFFFFFF
004013F4 |. 8BFE mov edi,esi
004013F6 |. 33C0 xor eax,eax
004013F8 |. 33D2 xor edx,edx
004013FA |. F2:AE repne scas byte ptr es:[edi]
004013FC |. F7D1 not ecx
004013FE |. 49 dec ecx
004013FF |. 74 2F je Xkgme.00401430 ; 这个循环根据lpRetStr2 填写新分配的lpRetStrCmb后部分
00401401 |. 8B4424 14 mov eax,dword ptr ss:[esp+0x14] ; eax = lpRetStrCmb
00401405 |. 03D8 add ebx,eax ; ebx = lpRetStrCmb+ lpRetStr1Len
00401407 |> 8A0C32 /mov cl,byte ptr ds:[edx+esi] ; while(edx < PNewAddrRet2Len){
0040140A |. 33C0 |xor eax,eax ; cl = PNewAddrRet2[edx]
0040140C |> 3888 C0504000 |/cmp byte ptr ds:[eax+0x4050C0],cl ; while (cl != RandStr2[eax])
00401412 |. 74 06 ||je Xkgme.0040141A ; {
00401414 |. 40 ||inc eax ; eax ++;
00401415 |. 83F8 10 ||cmp eax,0x10 ; if (eax >= 0x10) Break;
00401418 |.^ 72 F2 |\jb Xkgme.0040140C ; }
0040141A |> 34 23 |xor al,0x23 ; 最终下标 al ^= 0x23
0040141C |. 8BFE |mov edi,esi
0040141E |. 8803 |mov byte ptr ds:[ebx],al ; lpRetStrCmb[PNewAddrRet1Len + i] = al
00401420 |. 43 |inc ebx
00401421 |. 83C9 FF |or ecx,0xFFFFFFFF
00401424 |. 33C0 |xor eax,eax
00401426 |. 42 |inc edx ; edx++ ebx++
00401427 |. F2:AE |repne scas byte ptr es:[edi]
00401429 |. F7D1 |not ecx
0040142B |. 49 |dec ecx
0040142C |. 3BD1 |cmp edx,ecx
0040142E |.^ 72 D7 \jb Xkgme.
对应C语言代码 如下:
int _CalcRetComb(
char* lpRet1,
char* lpRet2,
int nLenRet1,
int nLenRet2,
char** lppRet
)
{
int i ,j;
char* lpBufRet = new char[nLenRet1+nLenRet2];
for (i = 0 ;i < nLenRet1 ;i++)
{
j = 0;
while (lpRet1[i] != szRand1[j])
{
if (++j >= 0x10)
break;
}
lpBufRet[i] = j ^ 0x23;
}
for (i = 0 ;i < nLenRet2 ;i++)
{
j = 0;
while (lpRet2[i] != szRand1[j])
{
if (++j >= 0x10)
break;
}
lpBufRet[i+nLenRet1] = j ^ 0x23;
}
*lppRet = lpBufRet;
return nLenRet1+nLenRet2;
}
2.3 下面就到了第3步了, 目标是计算Ebx ,分两步(两个循环)计算, 第2次计算接着使用上前次结果Ebx , 最终结果在Ebx上
00401430 |> \8BFD mov edi,ebp
00401432 |. 83C9 FF or ecx,0xFFFFFFFF
00401435 |. 33C0 xor eax,eax
00401437 |. 33F6 xor esi,esi
00401439 |. F2:AE repne scas byte ptr es:[edi]
0040143B |. F7D1 not ecx
0040143D |. 49 dec ecx
0040143E |. BB EA7D3862 mov ebx,0x62387DEA
00401443 74 46 je Xkgme.0040148B ; while(esi < AcctBufLen){
00401445 0FBE042E movsx eax,byte ptr ds:[esi+ebp]
00401449 |. 0FAFC0 |imul eax,eax ; eax *= AcctBuf[esi] * AcctBuf[esi]
0040144C |. 33D2 |xor edx,edx
0040144E |. BF 07000000 |mov edi,0x7
00401453 |. 8D0C40 |lea ecx,dword ptr ds:[eax+eax*2] ; ecx = 3*eax
00401456 |. C1E1 03 |shl ecx,0x3
00401459 |. 2BC8 |sub ecx,eax ; ecx = (ecx<<3) - eax
0040145B |. 8BC6 |mov eax,esi
0040145D |. F7F7 |div edi ; edx = esi % 7
0040145F |. 8BC1 |mov eax,ecx
00401461 |. 8BFD |mov edi,ebp
00401463 |. F7D0 |not eax
00401465 |. 0FAFC1 |imul eax,ecx
00401468 |. C1E0 02 |shl eax,0x2 ; eax = (ecx * ~ecx)<<2
0040146B |. 8B1495 D45040>|mov edx,dword ptr ds:[edx*4+0x4050D4]
00401472 |. 03D1 |add edx,ecx ; edx = Dword RandStr3[edx*4] + ecx
00401474 |. 83C9 FF |or ecx,0xFFFFFFFF
00401477 |. 33D0 |xor edx,eax
00401479 |. 33C0 |xor eax,eax
0040147B |. 33D3 |xor edx,ebx
0040147D |. 33D6 |xor edx,esi ; edx = edx ^ eax ^ ebx ^ esi
0040147F |. 46 |inc esi
00401480 |. F2:AE |repne scas byte ptr es:[edi]
00401482 |. F7D1 |not ecx
00401484 |. 49 |dec ecx
00401485 |. 8BDA |mov ebx,edx ; ebx = edx
00401487 |. 3BF1 |cmp esi,ecx
00401489 |.^ 72 BA \jb Xkgme.00401445 ; }
0040148B |> 8B4C24 10 mov ecx,dword ptr ss:[esp+0x10] ; ecx = UserNameLen+1
0040148F |. 33F6 xor esi,esi
00401491 |. 8D41 FF lea eax,dword ptr ds:[ecx-0x1] ; eax = UserNameLen
00401494 |. 85C0 test eax,eax
00401496 |. 894424 18 mov dword ptr ss:[esp+0x18],eax
0040149A |. 76 46 jbe Xkgme.004014E2
0040149C |. EB 07 jmp Xkgme.004014A5 ; while (esi < UserNameLen)
0040149E |> 8BAC24 280100>/mov ebp,dword ptr ss:[esp+0x128] ; {
004014A5 |> 0FBE0C2E movsx ecx,byte ptr ds:[esi+ebp] ; ecx = byte AcctBuf[esi]
004014A9 |. 8D7E 42 |lea edi,dword ptr ds:[esi+0x42] ; edi = esi + 0x42
004014AC |. 8BC6 |mov eax,esi
004014AE |. 33D2 |xor edx,edx
004014B0 |. BD 07000000 |mov ebp,0x7
004014B5 |. F7F5 |div ebp ; edx = esi % 7
004014B7 |. 0FAFC9 |imul ecx,ecx
004014BA |. 0FAFC9 |imul ecx,ecx
004014BD |. C1E1 03 |shl ecx,0x3 ; ecx = (ecx * ecx * ecx * ecx) >> 3
004014C0 |. 8BC1 |mov eax,ecx
004014C2 |. F7D0 |not eax
004014C4 |. 0FAFC1 |imul eax,ecx
004014C7 |. 8B1495 D45040>|mov edx,dword ptr ds:[edx*4+0x4050D4]
004014CE |. 03D1 |add edx,ecx ; edx = RandStr3[edx*4] + ecx
004014D0 |. C1E0 02 |shl eax,0x2 ; eax = (ecx * ~ecx) >> 2
004014D3 |. 33D0 |xor edx,eax
004014D5 |. 8B4424 18 |mov eax,dword ptr ss:[esp+0x18]
004014D9 |. 33D7 |xor edx,edi ; edx = edx ^ eax ^ edi
004014DB |. 33DA |xor ebx,edx ; ebx ^= edx
004014DD |. 46 |inc esi
004014DE |. 3BF0 |cmp esi,eax
004014E0 |.^ 72 BC \jb Xkgme.0040149E ; }
同样,C语言代码也来一份:
int _CalcEbx(
char* szAcct,
int nAcctLen,
int nUserNameLen
)
{
unsigned int nEbx = 0x62387DEA ,i ,nEax ,nEcx ,nEdx;
for (i = 0 ;i < nAcctLen ;i++)
{
nEax = szAcct[i]*szAcct[i];
nEcx = ((3*nEax)<<3) - nEax;
nEdx = i % 0x7;
nEdx = PnRand[nEdx] + nEcx;
nEax = (nEcx * ~nEcx)<<2;
nEdx = nEdx ^ nEax ^ nEbx ^ i;
nEbx = nEdx;
}
for (i = 0 ;i < nUserNameLen ;i++)
{
nEcx = (szAcct[i]*szAcct[i]*szAcct[i]*szAcct[i])<<0x3;
nEax = (nEcx * ~nEcx) << 2;
nEdx = i % 0x7;
nEdx = PnRand[nEdx] + nEcx;
nEdx = nEdx ^ nEax ^ (i+0x42);
nEbx ^= nEdx;
}
return nEbx;
}
2.4 这下Ebx也得到了 ,但第3步中计算得到的lpRetStrCmb还没有用上呢, 它将达步中用到, 这里主要是它(lpRetStrCmb) 来计算组合出用于你输入的szSerial转化成16进制的nSerial加密用 ,上代码
004014E2 8B8C24 2C0100>mov ecx,dword ptr ss:[esp+0x12C]
004014E9 |. 6A 10 push 0x10
004014EB |. 6A 00 push 0x0
004014ED |. 51 push ecx
004014EE |. E8 D5040000 call kgme.004019C8 ; strtoul (szSerial ,char ,base)将szSerial转化为nSerial
004014F3 |. 8B5424 2C mov edx,dword ptr ss:[esp+0x2C] ; edx =lpRetStrCmbLen
004014F7 |. 50 push eax ; eax = nSerial
004014F8 |. 8B4424 24 mov eax,dword ptr ss:[esp+0x24] ; eax = lpRetStrCmb
004014FC |. 52 push edx ; _CalcCode(...) 计算用于加密nSerial用的机器码lpCode
004014FD |. 50 push eax ; 并转而执行lpCode ,加密nSerial
004014FE |. E8 FDFAFFFF call kgme.00401000 ; _CalcCode(lpRetStrCmb ,lpRetStrCmbLen ,nSerial)
00401503 |. 83C4 18 add esp,0x18
00401506 |. 3BC3 cmp eax,ebx ; 这里将加密之后的nSerial(在eax中)与前面算出的Ebx比较
00401508 |. 0F94C0 sete al ; 相等则返回 0
0040150B |. 5F pop edi
0040150C |. 5E pop esi
0040150D |. 5D pop ebp
0040150E |. 5B pop ebx
0040150F |. 81C4 14010000 add esp,0x114
00401515 \. C3 retn
我们行F7跟进 _CalcCode(....)这个函数,看看里面怎么组织加密机器码lpCode的,这段比较长些
00401000 /$ 55 push ebp
00401001 |. 8BEC mov ebp,esp
00401003 |. 83EC 08 sub esp,0x8
00401006 |. 8B0D C0664000 mov ecx,dword ptr ds:[0x4066C0]
0040100C |. 53 push ebx
0040100D |. 8B5D 0C mov ebx,[arg.2]
00401010 |. 56 push esi
00401011 |. 57 push edi
00401012 |. 8D449B 01 lea eax,dword ptr ds:[ebx+ebx*4+0x1] ; nbyte = PNewAddrRet3Len * 5 + 1
00401016 |. 50 push eax ; /dwBytes
00401017 |. 6A 40 push 0x40 ; |dwFlags = 40
00401019 |. 51 push ecx ; |hHeap => 00290000
0040101A |. FF15 5C504000 call dword ptr ds:[<&KERNEL32.HeapAlloc>>; \RtlAllocateHeap
00401020 |. 8B55 10 mov edx,[arg.3] ; edx = nPsw
00401023 |. 33FF xor edi,edi
00401025 |. 8955 0C mov [arg.2],edx ; arg_2 = arg_3
00401028 |. 33D2 xor edx,edx
0040102A |. 85DB test ebx,ebx
0040102C |. 8945 FC mov [local.1],eax ; local.1 = ecx = lpCode
0040102F |. 0F86 43020000 jbe kgme.00401278
00401035 |. 8BC8 mov ecx,eax
00401037 |> 8B45 08 /mov eax,[arg.1] ; while (edi < lpRetStrCmb) {
0040103A |. 0FBE3407 |movsx esi,byte ptr ds:[edi+eax]
0040103E |. 83F6 23 |xor esi,0x23 ; esi = lpRetStrCmb[edi] ^ 0x23
00401041 |. 83FE 0F |cmp esi,0xF ; Switch (cases 0..F)
00401044 |. 0F87 1C020000 |ja kgme.00401266
0040104A |. FF24B5 941240>|jmp dword ptr ds:[esi*4+0x401294]
00401051 |> 8B35 A0604000 |mov esi,dword ptr ds:[0x4060A0] ; Case 0 of switch 00401041
00401057 |. 8BC1 |mov eax,ecx ; {
00401059 |. 83C2 05 |add edx,0x5 ; edx += 5
0040105C |. 8930 |mov dword ptr ds:[eax],esi ; *lpCode = Dword [0x4060A0]
0040105E |. 8BF1 |mov esi,ecx
00401060 |. 8945 F8 |mov [local.2],eax
00401063 |. A0 A4604000 |mov al,byte ptr ds:[0x4060A4]
00401068 |. 8846 04 |mov byte ptr ds:[esi+0x4],al ; *(lpCode + 4) = byte[0x4060A4]
0040106B |. 83C1 05 |add ecx,0x5 ; lpCode += 5
0040106E |. E9 F9010000 |jmp kgme.0040126C ; }
00401073 |> 8B35 98604000 |mov esi,dword ptr ds:[0x406098] ; Case 1 of switch 00401041
00401079 |. 8BC1 |mov eax,ecx ; {
0040107B |. 83C2 05 |add edx,0x5
0040107E |. 8930 |mov dword ptr ds:[eax],esi ; *lpCode = Dword [0x406098]
00401080 |. 8BF1 |mov esi,ecx
00401082 |. 8945 F8 |mov [local.2],eax
00401085 |. A0 9C604000 |mov al,byte ptr ds:[0x40609C]
0040108A |. 8846 04 |mov byte ptr ds:[esi+0x4],al ; *(lpCode+4) = byte[0x40609c]
0040108D |. 83C1 05 |add ecx,0x5 ; lpCode += 5
00401090 |. E9 D7010000 |jmp kgme.0040126C ; }
00401095 |> 8B35 90604000 |mov esi,dword ptr ds:[0x406090] ; Case 2 of switch 00401041
0040109B |. 8BC1 |mov eax,ecx
0040109D |. 83C2 05 |add edx,0x5
004010A0 |. 8930 |mov dword ptr ds:[eax],esi ; *lpCode = Dword [0x406090]
004010A2 |. 8BF1 |mov esi,ecx
004010A4 |. 8945 F8 |mov [local.2],eax
004010A7 |. A0 94604000 |mov al,byte ptr ds:[0x406094]
004010AC |. 8846 04 |mov byte ptr ds:[esi+0x4],al ; *(lpCode + 4) = byte [0x406094]
004010AF |. 83C1 05 |add ecx,0x5 ; lpCode += 5
004010B2 |. E9 B5010000 |jmp kgme.0040126C
004010B7 |> 66:8B35 8C604>|mov si,word ptr ds:[0x40608C] ; Case 3 of switch 00401041
004010BE |. 8BC1 |mov eax,ecx
004010C0 |. 83C2 03 |add edx,0x3
004010C3 |. 66:8930 |mov word ptr ds:[eax],si ; *lpCode = word [0x40608c]
004010C6 |. 8BF1 |mov esi,ecx
004010C8 |. 8945 F8 |mov [local.2],eax
004010CB |. A0 8E604000 |mov al,byte ptr ds:[0x40608E]
004010D0 |. 8846 02 |mov byte ptr ds:[esi+0x2],al ; *(lpCode+2) = byte [0x40608E]
004010D3 |. 83C1 03 |add ecx,0x3
004010D6 |. E9 91010000 |jmp kgme.0040126C
004010DB |> 66:A1 8860400>|mov ax,word ptr ds:[0x406088] ; Case 4 of switch 00401041
004010E1 |. 83C2 02 |add edx,0x2
004010E4 |. 66:8901 |mov word ptr ds:[ecx],ax
004010E7 |. 83C1 02 |add ecx,0x2
004010EA |. E9 7D010000 |jmp kgme.0040126C
004010EF |> 8B35 80604000 |mov esi,dword ptr ds:[0x406080] ; Case 5 of switch 00401041
004010F5 |. 8BC1 |mov eax,ecx
004010F7 |. 83C2 05 |add edx,0x5
004010FA |. 8930 |mov dword ptr ds:[eax],esi
004010FC |. 8BF1 |mov esi,ecx
004010FE |. 8945 F8 |mov [local.2],eax
00401101 |. A0 84604000 |mov al,byte ptr ds:[0x406084]
00401106 |. 8846 04 |mov byte ptr ds:[esi+0x4],al
00401109 |. 83C1 05 |add ecx,0x5
0040110C |. E9 5B010000 |jmp kgme.0040126C
00401111 |> 8B35 78604000 |mov esi,dword ptr ds:[0x406078] ; Case 6 of switch 00401041
00401117 |. 8BC1 |mov eax,ecx
00401119 |. 83C2 05 |add edx,0x5
0040111C |. 8930 |mov dword ptr ds:[eax],esi
0040111E |. 8BF1 |mov esi,ecx
00401120 |. 8945 F8 |mov [local.2],eax
00401123 |. A0 7C604000 |mov al,byte ptr ds:[0x40607C]
00401128 |. 8846 04 |mov byte ptr ds:[esi+0x4],al
0040112B |. 83C1 05 |add ecx,0x5
0040112E |. E9 39010000 |jmp kgme.0040126C
00401133 |> 8B45 0C |mov eax,[arg.2] ; Case 7 of switch 00401041
00401136 |. 8B35 70604000 |mov esi,dword ptr ds:[0x406070]
0040113C |. 35 DFED0D00 |xor eax,0xDEDDF
00401141 |. 83C2 05 |add edx,0x5
00401144 |. 8945 0C |mov [arg.2],eax
00401147 |. 8BC1 |mov eax,ecx
00401149 |. 8930 |mov dword ptr ds:[eax],esi
0040114B |. 8BF1 |mov esi,ecx
0040114D |. 8945 F8 |mov [local.2],eax
00401150 |. A0 74604000 |mov al,byte ptr ds:[0x406074]
00401155 |. 8846 04 |mov byte ptr ds:[esi+0x4],al
00401158 |. 83C1 05 |add ecx,0x5
0040115B |. E9 0C010000 |jmp kgme.0040126C
00401160 |> 8B35 68604000 |mov esi,dword ptr ds:[0x406068] ; Case 8 of switch 00401041
00401166 |. 8BC1 |mov eax,ecx
00401168 |. 83C2 05 |add edx,0x5
0040116B |. 8930 |mov dword ptr ds:[eax],esi
0040116D |. 8BF1 |mov esi,ecx
0040116F |. 8945 F8 |mov [local.2],eax
00401172 |. A0 6C604000 |mov al,byte ptr ds:[0x40606C]
00401177 |. 8846 04 |mov byte ptr ds:[esi+0x4],al
0040117A |. 83C1 05 |add ecx,0x5
0040117D |. E9 EA000000 |jmp kgme.0040126C
00401182 |> 66:8B35 64604>|mov si,word ptr ds:[0x406064] ; Case 9 of switch 00401041
00401189 |. 8BC1 |mov eax,ecx
0040118B |. 83C2 03 |add edx,0x3
0040118E |. 66:8930 |mov word ptr ds:[eax],si
00401191 |. 8BF1 |mov esi,ecx
00401193 |. 8945 F8 |mov [local.2],eax
00401196 |. A0 66604000 |mov al,byte ptr ds:[0x406066]
0040119B |. 8846 02 |mov byte ptr ds:[esi+0x2],al
0040119E |. 83C1 03 |add ecx,0x3
004011A1 |. E9 C6000000 |jmp kgme.0040126C
004011A6 |> 8B35 5C604000 |mov esi,dword ptr ds:[0x40605C] ; Case A of switch 00401041
004011AC |. 8BC1 |mov eax,ecx
004011AE |. 83C2 05 |add edx,0x5
004011B1 |. 8930 |mov dword ptr ds:[eax],esi
004011B3 |. 8BF1 |mov esi,ecx
004011B5 |. 8945 F8 |mov [local.2],eax
004011B8 |. A0 60604000 |mov al,byte ptr ds:[0x406060]
004011BD |. 8846 04 |mov byte ptr ds:[esi+0x4],al
004011C0 |. 83C1 05 |add ecx,0x5
004011C3 |. E9 A4000000 |jmp kgme.0040126C
004011C8 |> 8B35 54604000 |mov esi,dword ptr ds:[0x406054] ; Case B of switch 00401041
004011CE |. 8BC1 |mov eax,ecx
004011D0 |. 83C2 05 |add edx,0x5
004011D3 |. 8930 |mov dword ptr ds:[eax],esi
004011D5 |. 8BF1 |mov esi,ecx
004011D7 |. 8945 F8 |mov [local.2],eax
004011DA |. A0 58604000 |mov al,byte ptr ds:[0x406058]
004011DF |. 8846 04 |mov byte ptr ds:[esi+0x4],al
004011E2 |. 83C1 05 |add ecx,0x5
004011E5 |. E9 82000000 |jmp kgme.0040126C
004011EA |> 8B35 4C604000 |mov esi,dword ptr ds:[0x40604C] ; Case C of switch 00401041
004011F0 |. 8BC1 |mov eax,ecx
004011F2 |. 83C2 05 |add edx,0x5
004011F5 |. 8930 |mov dword ptr ds:[eax],esi
004011F7 |. 8BF1 |mov esi,ecx
004011F9 |. 8945 F8 |mov [local.2],eax
004011FC |. A0 50604000 |mov al,byte ptr ds:[0x406050]
00401201 |. 8846 04 |mov byte ptr ds:[esi+0x4],al
00401204 |. 83C1 05 |add ecx,0x5
00401207 |. EB 63 |jmp Xkgme.0040126C
00401209 |> 8B35 44604000 |mov esi,dword ptr ds:[0x406044] ; Case D of switch 00401041
0040120F |. 8BC1 |mov eax,ecx
00401211 |. 83C2 05 |add edx,0x5
00401214 |. 8930 |mov dword ptr ds:[eax],esi
00401216 |. 8BF1 |mov esi,ecx
00401218 |. 8945 F8 |mov [local.2],eax
0040121B |. A0 48604000 |mov al,byte ptr ds:[0x406048]
00401220 |. 8846 04 |mov byte ptr ds:[esi+0x4],al
00401223 |. 83C1 05 |add ecx,0x5
00401226 |. EB 44 |jmp Xkgme.0040126C
00401228 |> 8B35 3C604000 |mov esi,dword ptr ds:[0x40603C] ; Case E of switch 00401041
0040122E |. 8BC1 |mov eax,ecx
00401230 |. 83C2 05 |add edx,0x5
00401233 |. 8930 |mov dword ptr ds:[eax],esi
00401235 |. 8BF1 |mov esi,ecx
00401237 |. 8945 F8 |mov [local.2],eax
0040123A |. A0 40604000 |mov al,byte ptr ds:[0x406040]
0040123F |. 8846 04 |mov byte ptr ds:[esi+0x4],al
00401242 |. 83C1 05 |add ecx,0x5
00401245 |. EB 25 |jmp Xkgme.0040126C
00401247 |> 8B35 34604000 |mov esi,dword ptr ds:[0x406034] ; Case F of switch 00401041
0040124D |. 8BC1 |mov eax,ecx
0040124F |. 83C2 05 |add edx,0x5
00401252 |. 8930 |mov dword ptr ds:[eax],esi
00401254 |. 8BF1 |mov esi,ecx
00401256 |. 8945 F8 |mov [local.2],eax
00401259 |. A0 38604000 |mov al,byte ptr ds:[0x406038]
0040125E |. 8846 04 |mov byte ptr ds:[esi+0x4],al
00401261 |. 83C1 05 |add ecx,0x5
00401264 |. EB 06 |jmp Xkgme.0040126C
00401266 |> 68 3284FF0F |push 0xFFF8432 ; Default case of switch 00401041
0040126B |. C3 |retn
0040126C |> 47 |inc edi
0040126D |. 3BFB |cmp edi,ebx
0040126F |.^ 0F82 C2FDFFFF \jb kgme.00401037
00401275 |. 8B45 FC mov eax,[local.1]
00401278 |> 8A0D 30604000 mov cl,byte ptr ds:[0x406030] ; 最后写入指令 ret 的机器码 0xC3
0040127E |. 880C02 mov byte ptr ds:[edx+eax],cl ; lpCode[edx] = byte [0x406030]
00401281 |. 8B45 10 mov eax,[arg.3]
00401284 |. FF55 FC call [local.1] ; call lpCode 跳到 lpCode 执行对nSerial的加密
00401287 |. 8945 0C mov [arg.2],eax
0040128A |. 8B45 0C mov eax,[arg.2]
0040128D |. 5F pop edi
0040128E |. 5E pop esi
0040128F |. 5B pop ebx
00401290 |. 8BE5 mov esp,ebp
00401292 |. 5D pop ebp
00401293 \. C3 retn
计算出来的代码都是些数值运算指令,如( add ,sub ,rol ,ror ,not ,......)
因为上面这段代码是计算出机器码供 你输入的nSerial 加密用的, 加密之后得 nSerialEncrypted与 用登陆名(Account) 与 PC用户名(szUserName) 计算出来的Ebx 比较 来判断 szSerial是正确与否 , 因此我们要想 根据我们的 Ebx 得到 nSerial , 就必须用Ebx来反向执行这段加密机器码, 当然这还是不够的, 还必须修改一些指令为其对应的逆向操作指令. 如 add -- sub ,rol -- ror .....not 与 xor 指令不变. 就是这样
下面计算逆向指令代码的对应C语言表示 ,因为得反向执行计算出来的机器码,所以,计算前得让 lpRetStrCmb反向.
int _CalcCode(
char* lpRet3,
int nRet3Len,
char** lppRet
)
{
char* lpCode = new char[nRet3Len*5+1];
memset(lpCode ,0x90 ,nRet3Len*5+1);
int* Pdword ,i ,j;
short* Pword;
char* Pbyte;
for (i = 0 ,j = 0 ;i < nRet3Len ;i++)
{
switch(lpRet3[i] ^ 0x23)
{
case 0x0:
Pdword = (int*)(lpCode+j);
*Pdword = 0x32792835;
Pbyte = (char*)(lpCode+j+4);
*Pbyte = 0;
j += 5;
break;
case 0x1:
Pdword = (int*)(lpCode+j);
*Pdword = 0xD743D2D;
Pbyte = (char*)(lpCode+j+4);
*Pbyte = 0;
j += 5;
break;
case 0x2:
Pdword = (int*)(lpCode+j);
*Pdword = 0xDEFFFF35;
Pbyte = (char*)(lpCode+j+4);
*Pbyte = 0xC0;
j += 5;
break;
case 0x3:
Pword = (short*)(lpCode+j);
*Pword = 0xC8C1;
Pbyte = (char*)(lpCode+j+2);
*Pbyte = 0x13;
j += 3;
break;
case 0x4:
Pword = (short*)(lpCode+j);
*Pword = 0xD0F7;
j += 2;
break;
case 0x5:
Pdword = (int*)(lpCode+j);
*Pdword = 0x3478342D;
Pbyte = (char*)(lpCode+j+4);
*Pbyte = 0x02;
j += 5;
break;
case 0x6:
Pdword = (int*)(lpCode+j);
*Pdword = 0x85545435;
Pbyte = (char*)(lpCode+j+4);
*Pbyte = 0x00;
j += 5;
break;
case 0x7:
Pdword = (int*)(lpCode+j);
*Pdword = 0xDEDDF35;
Pbyte = (char*)(lpCode+j+4);
*Pbyte = 0x00;
j += 5;
break;
case 0x8:
Pdword = (int*)(lpCode+j);
*Pdword = 0x3472352D;
Pbyte = (char*)(lpCode+j+4);
*Pbyte = 0x00;
j += 5;
break;
case 0x9:
Pdword = (int*)(lpCode+j);
*Pdword = 0xC0C1;
Pbyte = (char*)(lpCode+j+2);
*Pbyte = 0x23;
j += 3;
break;
case 0xA:
Pdword = (int*)(lpCode+j);
*Pdword = 0x34FF5305;
Pbyte = (char*)(lpCode+j+4);
*Pbyte = 0x38;
j += 5;
break;
case 0xB:
Pdword = (int*)(lpCode+j);
*Pdword = 0xDEAD35;
Pbyte = (char*)(lpCode+j+4);
*Pbyte = 0x00;
j += 5;
break;
case 0xC:
Pdword = (int*)(lpCode+j);
*Pdword = 0x2374305;
Pbyte = (char*)(lpCode+j+4);
*Pbyte = 0x00;
j += 5;
break;
case 0xD:
Pdword = (int*)(lpCode+j);
*Pdword = 0xDEFE342D;
Pbyte = (char*)(lpCode+j+4);
*Pbyte = 0x00;
j += 5;
break;
case 0xE:
Pdword = (int*)(lpCode+j);
*Pdword = 0x485FD35;
Pbyte = (char*)(lpCode+j+4);
*Pbyte = 0x00;
j += 5;
break;
case 0xF:
Pdword = (int*)(lpCode+j);
*Pdword = 0x236FFA05;
Pbyte = (char*)(lpCode+j+4);
*Pbyte = 0x00;
j += 5;
break;
default:
return 0;
}
}
lpCode[j] = 0xc3; //最后写入 ret指令
*lppRet = lpCode;
return nRet3Len*5+1;
}
到这里分析算了完成了,下面来一份完整的 注册机代码吧.
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
unsigned long nPsw;
char* szRand1 = "6Ghd3iHRaSkL,;-Z";
int PnRand[] = {0x43275 ,0xAED2384 ,0xD377AE7,0xD54837D,
0xFE53743 ,0x3472389 ,0x23488 };
char* _CalcRetstr(
char* szBuf,
int nBufLen
)
{
char szTmp;
char* lpBufRet = new char[nBufLen*2+1];
for (int i = 0 ;i < nBufLen ;i++)
{
szTmp = (szBuf[i] >> 4) & 0xF;
szTmp = szRand1[szTmp];
lpBufRet[i*2] = szTmp;
szTmp = szBuf[i] & 0xF;
szTmp = szRand1[szTmp];
lpBufRet[i*2+1] = szTmp;
}
lpBufRet[nBufLen*2] = 0;
return lpBufRet;
}
int _CalcRetComb(
char* lpRet1,
char* lpRet2,
int nLenRet1,
int nLenRet2,
char** lppRet
)
{
int i ,j;
char* lpBufRet = new char[nLenRet1+nLenRet2];
for (i = 0 ;i < nLenRet1 ;i++)
{
j = 0;
while (lpRet1[i] != szRand1[j])
{
if (++j >= 0x10)
break;
}
lpBufRet[i] = j ^ 0x23;
}
for (i = 0 ;i < nLenRet2 ;i++)
{
j = 0;
while (lpRet2[i] != szRand1[j])
{
if (++j >= 0x10)
break;
}
lpBufRet[i+nLenRet1] = j ^ 0x23;
}
*lppRet = lpBufRet;
return nLenRet1+nLenRet2;
}
int _CalcEbx(
char* szAcct,
int nAcctLen,
int nUserNameLen
)
{
unsigned int nEbx = 0x62387DEA ,i ,nEax ,nEcx ,nEdx;
for (i = 0 ;i < nAcctLen ;i++)
{
nEax = szAcct[i]*szAcct[i];
nEcx = ((3*nEax)<<3) - nEax;
nEdx = i % 0x7;
nEdx = PnRand[nEdx] + nEcx;
nEax = (nEcx * ~nEcx)<<2;
nEdx = nEdx ^ nEax ^ nEbx ^ i;
nEbx = nEdx;
}
for (i = 0 ;i < nUserNameLen ;i++)
{
nEcx = (szAcct[i]*szAcct[i]*szAcct[i]*szAcct[i])<<0x3;
nEax = (nEcx * ~nEcx) << 2;
nEdx = i % 0x7;
nEdx = PnRand[nEdx] + nEcx;
nEdx = nEdx ^ nEax ^ (i+0x42);
nEbx ^= nEdx;
}
return nEbx;
}
int _CalcCode(
char* lpRet3,
int nRet3Len,
char** lppRet
)
{
char* lpCode = new char[nRet3Len*5+1];
memset(lpCode ,0x90 ,nRet3Len*5+1);
int* Pdword ,i ,j;
short* Pword;
char* Pbyte;
for (i = 0 ,j = 0 ;i < nRet3Len ;i++)
{
switch(lpRet3[i] ^ 0x23)
{
case 0x0:
Pdword = (int*)(lpCode+j);
*Pdword = 0x32792835;
Pbyte = (char*)(lpCode+j+4);
*Pbyte = 0;
j += 5;
break;
case 0x1:
Pdword = (int*)(lpCode+j);
*Pdword = 0xD743D2D;
Pbyte = (char*)(lpCode+j+4);
*Pbyte = 0;
j += 5;
break;
case 0x2:
Pdword = (int*)(lpCode+j);
*Pdword = 0xDEFFFF35;
Pbyte = (char*)(lpCode+j+4);
*Pbyte = 0xC0;
j += 5;
break;
case 0x3:
Pword = (short*)(lpCode+j);
*Pword = 0xC8C1;
Pbyte = (char*)(lpCode+j+2);
*Pbyte = 0x13;
j += 3;
break;
case 0x4:
Pword = (short*)(lpCode+j);
*Pword = 0xD0F7;
j += 2;
break;
case 0x5:
Pdword = (int*)(lpCode+j);
*Pdword = 0x3478342D;
Pbyte = (char*)(lpCode+j+4);
*Pbyte = 0x02;
j += 5;
break;
case 0x6:
Pdword = (int*)(lpCode+j);
*Pdword = 0x85545435;
Pbyte = (char*)(lpCode+j+4);
*Pbyte = 0x00;
j += 5;
break;
case 0x7:
Pdword = (int*)(lpCode+j);
*Pdword = 0xDEDDF35;
Pbyte = (char*)(lpCode+j+4);
*Pbyte = 0x00;
j += 5;
break;
case 0x8:
Pdword = (int*)(lpCode+j);
*Pdword = 0x3472352D;
Pbyte = (char*)(lpCode+j+4);
*Pbyte = 0x00;
j += 5;
break;
case 0x9:
Pdword = (int*)(lpCode+j);
*Pdword = 0xC0C1;
Pbyte = (char*)(lpCode+j+2);
*Pbyte = 0x23;
j += 3;
break;
case 0xA:
Pdword = (int*)(lpCode+j);
*Pdword = 0x34FF5305;
Pbyte = (char*)(lpCode+j+4);
*Pbyte = 0x38;
j += 5;
break;
case 0xB:
Pdword = (int*)(lpCode+j);
*Pdword = 0xDEAD35;
Pbyte = (char*)(lpCode+j+4);
*Pbyte = 0x00;
j += 5;
break;
case 0xC:
Pdword = (int*)(lpCode+j);
*Pdword = 0x2374305;
Pbyte = (char*)(lpCode+j+4);
*Pbyte = 0x00;
j += 5;
break;
case 0xD:
Pdword = (int*)(lpCode+j);
*Pdword = 0xDEFE342D;
Pbyte = (char*)(lpCode+j+4);
*Pbyte = 0x00;
j += 5;
break;
case 0xE:
Pdword = (int*)(lpCode+j);
*Pdword = 0x485FD35;
Pbyte = (char*)(lpCode+j+4);
*Pbyte = 0x00;
j += 5;
break;
case 0xF:
Pdword = (int*)(lpCode+j);
*Pdword = 0x236FFA05;
Pbyte = (char*)(lpCode+j+4);
*Pbyte = 0x00;
j += 5;
break;
default:
return 0;
}
}
lpCode[j] = 0xc3;
*lppRet = lpCode;
return nRet3Len*5+1;
}
int main()
{
int i = 0 ,j;
char szAcct[100] = {0};
printf("Enter Account:");
scanf("%s" ,szAcct);
char* lpRetstr2 = _CalcRetstr(szAcct ,lstrlen(szAcct));
int nTmp = 100;
char szUserName[100] = {0};
GetUserName(szUserName ,(unsigned long*)&nTmp);
char* lpRetstr1 = _CalcRetstr(szUserName ,lstrlen(szUserName));
char* lpRetCmb = NULL;
int nLenRetCmb = _CalcRetComb(lpRetstr1 ,lpRetstr2 ,lstrlen(lpRetstr1),
lstrlen(lpRetstr2) ,&lpRetCmb);
int nEbx = _CalcEbx(szAcct ,lstrlen(szAcct) ,lstrlen(szUserName));
char* lpRetCmbRevs = new char[nLenRetCmb+1];
for (i = 0 ,j = nLenRetCmb - 1 ;i < nLenRetCmb ;i++ ,j--)
lpRetCmbRevs[i] = lpRetCmb[j];
unsigned char* lpCodeRevs = NULL;
int nLenCodeRevs = _CalcCode(lpRetCmbRevs ,nLenRetCmb ,(char**)&lpCodeRevs);
__asm
{
mov eax ,nEbx
call lpCodeRevs
mov nPsw ,eax
}
printf("Serial: %x\n" ,nPsw);
delete[] lpRetstr1;
delete[] lpRetstr2;
delete[] lpRetCmb;
delete[] lpRetCmbRevs;
delete[] lpCodeRevs;
return 0;
}
:
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课