这个程序采用SendDlgItemMessageA 限制 文本框的输入 但我们只要 修改push
0040130D /$ 50 push eax 0040130E |. 33C0 xor eax,eax 00401310 |. A1 14324000 mov eax,dword ptr ds:[0x403214] 00401315 6A 00 push 0x0 00401317 6A 01 push 0x1 00401319 68 C5000000 push 0xC5 0040131E 68 E9000000 push 0xE9 ; |ControlID = E9 (233.) 00401323 50 push eax ; |hWnd => 02800232 ('KeygenMe #1 by Kostya',class='#32770') 00401324 |. E8 A1000000 call <jmp.&USER32.SendDlgItemMessageA> ; SendDlgItemMessageA 00401329 |. 33C0 xor eax,eax 0040132B |. A1 14324000 mov eax,dword ptr ds:[0x403214] 00401330 |. 6A 00 push 0x0 ; /lParam = 0 00401332 6A 01 push 0x1 ; |wParam = 1 00401334 68 00000000 push 0x0 00401339 |. 68 EA030000 push 0x3EA ; |ControlID = 3EA (1002.) 0040133E |. 50 push eax ; |hWnd => 02800232 ('KeygenMe #1 by Kostya',class='#32770') 0040133F |. E8 86000000 call <jmp.&USER32.SendDlgItemMessageA> ; SendDlgItemMessageA 00401344 |. 58 pop eax 00401345 . C3 retn程序实现 解除限制:
BOOL CKeygenDlg::EditCm(CString strPathName) { CFile pFile; if (!pFile.Open(strPathName,CFile::modeWrite|CFile::typeBinary|CFile::shareDenyNone,NULL)) { return FALSE; } BYTE Cnt1 = 0x50; BYTE Cnt2 = 0x01; BYTE My1 = 0x00; // pFile.Seek(0x718,CFile::begin); // pFile.Write(&Cnt1,0x1); // pFile.Seek(0x733,CFile::begin); // pFile.Write(&Cnt1,0x1); // pFile.Seek(0x549,CFile::begin); // pFile.Write(&Cnt2,0x1); pFile.Seek(0x720,CFile::begin); //改两个地方为PUSH 0 pFile.Write(&My1,0x1); pFile.Seek(0x735,CFile::begin); pFile.Write(&My1,0x1); pFile.Close(); return TRUE; }第一个加密地方:
004010FF |. 53 push ebx 00401100 |. FF35 0C324000 push dword ptr ds:[0x40320C] ; /hWnd = 01F80286 (class='Edit',parent=02800232) 00401106 |. E8 B3020000 call <jmp.&USER32.GetWindowTextLengthA> ; GetWindowTextLengthA 0040110B |. 33C9 xor ecx,ecx 0040110D |. 8BD8 mov ebx,eax 0040110F |. B8 0C304000 mov eax,KeygenMe.0040300C ; ASCII "administrator" 00401114 |. E8 B8010000 call KeygenMe.004012D1
{ 004012D1 /$ 8A10 mov dl,byte ptr ds:[eax] 004012D3 |. 6BC9 48 imul ecx,ecx,0x48 004012D6 |. 2BCA sub ecx,edx 004012D8 |. 83E9 6F sub ecx,0x6F 004012DB |. 8BD1 mov edx,ecx 004012DD |. 81F1 AFAC0B00 xor ecx,0xBACAF 004012E3 |. 40 inc eax 004012E4 |. 4B dec ebx 004012E5 |. 83FB 00 cmp ebx,0x0 004012E8 |.^ 75 E7 jnz XKeygenMe.004012D1 004012EA . C3 retn }接着 再次记录管理员账号
00401169 |. 33C0 xor eax,eax 0040116B |. 68 00304000 push KeygenMe.00403000 ; /pBufCount = KeygenMe.00403000 00401170 |. 68 0C304000 push KeygenMe.0040300C ; |Buffer = KeygenMe.0040300C 00401175 |. E8 62020000 call <jmp.&ADVAPI32.GetUserNameA> ; GetUserNameA 0040117A |. 33D2 xor edx,edx 0040117C |. 33C9 xor ecx,ecx 0040117E |.^ E9 7BFFFFFF jmp KeygenMe.004010FE
004010FF |. 53 push ebx 00401100 |. FF35 0C324000 push dword ptr ds:[0x40320C] ; /hWnd = 01F80286 (class='Edit',parent=02800232) 00401106 |. E8 B3020000 call <jmp.&USER32.GetWindowTextLengthA> ; GetWindowTextLengthA 0040110B |. 33C9 xor ecx,ecx 0040110D |. 8BD8 mov ebx,eax 0040110F |. B8 0C304000 mov eax,KeygenMe.0040300C ; ASCII "Administrator" 00401114 |. E8 B8010000 call KeygenMe.004012D1 00401119 |. EB 40 jmp XKeygenMe.0040115B
{ 004012D1 /$ 8A10 mov dl,byte ptr ds:[eax] 004012D3 |. 6BC9 48 imul ecx,ecx,0x48 004012D6 |. 2BCA sub ecx,edx 004012D8 |. 83E9 6F sub ecx,0x6F 004012DB |. 8BD1 mov edx,ecx 004012DD |. 81F1 AFAC0B00 xor ecx,0xBACAF 004012E3 |. 40 inc eax 004012E4 |. 4B dec ebx 004012E5 |. 83FB 00 cmp ebx,0x0 004012E8 |.^ 75 E7 jnz XKeygenMe.004012D1 004012EA . C3 retn }两次是相同的 如果输入administrator 作为账号 后面要多加一次加密 如果不相同则要加几次加密
折后两次加密最重要
00401197 |. E8 DE000000 call KeygenMe.0040127A ; CkSn1
{
0040127A /$ 55 push ebp
0040127B |. 8BEC mov ebp,esp 0040127D |. 33C0 xor eax,eax 0040127F |. 33DB xor ebx,ebx 00401281 |. 8B45 08 mov eax,[arg.1] 00401284 |. 8B5D 0C mov ebx,[arg.2] 00401287 |. 8BD0 mov edx,eax 00401289 |. 33D3 xor edx,ebx 0040128B |. 81F2 ACFF0000 xor edx,0xFFAC 00401291 |. 81F3 53050000 xor ebx,0x553 00401297 |. 03C3 add eax,ebx 00401299 |. 03DA add ebx,edx 0040129B |. 4B dec ebx 0040129C |. 03C3 add eax,ebx 0040129E |. C9 leave 0040129F . C2 0800 retn 0x8
} 0040119C |. A3 20324000 mov dword ptr ds:[0x403220],eax 004011A1 |. E8 A0010000 call KeygenMe.00401346 ; CkSn2
{
00401346 /$ A1 1C324000 mov eax,dword ptr ds:[0x40321C] 0040134B |. 8B1D 18324000 mov ebx,dword ptr ds:[0x403218] 00401351 |. 3BC3 cmp eax,ebx 00401353 |. 75 0E jnz XKeygenMe.00401363 00401355 |. 81F3 8E000000 xor ebx,0x8E 0040135B |. 03D8 add ebx,eax 0040135D |. 891D 18324000 mov dword ptr ds:[0x403218],ebx 00401363 > C3 retn
} 004011A6 |. FF35 1C324000 push dword ptr ds:[0x40321C] 004011AC |. 68 24324000 push KeygenMe.00403224 004011B1 |. E8 EC000000 call KeygenMe.004012A2 这些后面的函数将前两次加密得到的16进制 -》字符串 连接起来 004011B6 |. B8 24324000 mov eax,KeygenMe.00403224 004011BB |. 83C0 08 add eax,0x8 004011BE |. FF35 20324000 push dword ptr ds:[0x403220] 004011C4 |. 8D00 lea eax,dword ptr ds:[eax] 004011C6 |. 50 push eax 004011C7 |. E8 D6000000 call KeygenMe.004012A2 004011CC |. B8 24324000 mov eax,KeygenMe.00403224 004011D1 |. 83C0 10 add eax,0x10 004011D4 |. FF35 18324000 push dword ptr ds:[0x403218] 004011DA |. 8D00 lea eax,dword ptr ds:[eax] 004011DC |. 50 push eax 004011DD |. E8 C0000000 call KeygenMe.004012A2 004011E2 |. A1 10324000 mov eax,dword ptr ds:[0x403210] 004011E7 |. 50 push eax ; /hWnd => 03800274 (class='Edit',parent=02800232) 004011E8 |. E8 D1010000 call <jmp.&USER32.GetWindowTextLengthA> ; GetWindowTextLengthA 004011ED |. B9 00000000 mov ecx,0x0 004011F2 |. 83F8 18 cmp eax,0x18 004011F5 |.^ 0F85 20FFFFFF jnz KeygenMe.0040111B 004011FB |. 40 inc eax 004011FC |. 50 push eax ; /Count 004011FD |. 68 0C314000 push KeygenMe.0040310C ; |Buffer = KeygenMe.0040310C 00401202 |. 68 EA030000 push 0x3EA ; |ControlID = 3EA (1002.) 00401207 |. FF75 08 push [arg.1] ; |hWnd 0040120A |. E8 A9010000 call <jmp.&USER32.GetDlgItemTextA> ; GetDlgItemTextA 0040120F |. B8 0C314000 mov eax,KeygenMe.0040310C 00401214 |. E8 D2000000 call KeygenMe.004012EB 增加 字符 '-'
{
004012EB /$ BA 24324000 mov edx,KeygenMe.00403224 ; ASCII "36B02FE8B6297B092D2C3AE8" 004012F0 |. 83C2 04 add edx,0x4 004012F3 |. C602 2D mov byte ptr ds:[edx],0x2D 004012F6 |. 83C2 0A add edx,0xA 004012F9 |. C602 2D mov byte ptr ds:[edx],0x2D 004012FC |. BA 24324000 mov edx,KeygenMe.00403224 ; ASCII "36B02FE8B6297B092D2C3AE8" 00401301 |. C602 4B mov byte ptr ds:[edx],0x4B 00401304 |. 42 inc edx 00401305 |. C602 4F mov byte ptr ds:[edx],0x4F 00401308 |. 42 inc edx 00401309 |. C602 53 mov byte ptr ds:[edx],0x53 0040130C . C3 retn
} 00401219 |. B8 0C314000 mov eax,KeygenMe.0040310C 0040121E |. 83C0 04 add eax,0x4 00401221 |. 8038 2D cmp byte ptr ds:[eax],0x2D 00401224 |.^ 0F85 F1FEFFFF jnz KeygenMe.0040111B 0040122A |. 83C0 0A add eax,0xA 0040122D |. 8038 2D cmp byte ptr ds:[eax],0x2D 00401230 |.^ 0F85 E5FEFFFF jnz KeygenMe.0040111B 00401236 |. 68 24324000 push KeygenMe.00403224 0040123B |. 68 0C314000 push KeygenMe.0040310C 00401240 |. E8 1F010000 call KeygenMe.00401364 00401245 |. 8BC8 mov ecx,eax 00401247 |. 83F9 01 cmp ecx,0x1 0040124A |.^ 0F84 CBFEFFFF je KeygenMe.0040111B
这次学到东西 主要 是可以利用 原本程序的 汇编指令去制作 KEYGENME
:
BOOL CKeygenDlg::FindCM() { DWORD dwThreadId; DWORD dwProcessId; CString sClassName= ""; m_hPwnd = ::FindWindow(NULL,"KeygenMe #1 by Kostya");//得到窗口句柄 if(m_hPwnd == NULL) { return FALSE; } int hFunc=GetClassName(m_hPwnd,sClassName.GetBuffer(0),2000); if(hFunc != 0 && 0 <= sClassName.Find("#32770")) { if( dwThreadId = ::GetWindowThreadProcessId(m_hPwnd, &dwProcessId)) { m_hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId); if(m_hProcess != NULL) { return TRUE; } } } return FALSE; }
CString CKeygenDlg::GetCMInfo() { CString PathName; CString PName; PROCESSENTRY32 pe32; pe32.dwSize=sizeof(pe32); HANDLE hProcessSnap=::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); if(hProcessSnap==INVALID_HANDLE_VALUE) { SetDlgItemText(IDC_TISHI,"提示:CreateToolhelp32Snapshot调用失败!"); return -1; } BOOL bMore=::Process32First(hProcessSnap,&pe32); while(bMore) { char szProcessName[_MAX_PATH] = "unknown"; HANDLE hProcess = OpenProcess ( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pe32.th32ProcessID ) ; if ( hProcess ) { HMODULE hMod; DWORD cbNeeded; if (EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeeded) ) { GetModuleFileNameEx( hProcess, hMod, szProcessName, sizeof(szProcessName) ); PName = pe32.szExeFile; PName.MakeUpper(); if(PName.Find("KEYGENMENO1") == 0) { PathName = szProcessName; } } CloseHandle( hProcess ); } bMore=::Process32Next(hProcessSnap,&pe32); } ::CloseHandle(hProcessSnap); return PathName; }
int CKeygenDlg::KillProcess() { return ::TerminateProcess( m_hProcess, 4 ); }
DWORD CKeygenDlg::CLName(char *Name) { DWORD result; int len = strlen(Name); _asm{ mov eax,Name mov ebx,len xor edx,edx xor ecx,ecx L000: mov dl, byte ptr [eax] imul ecx, ecx, 0x48 sub ecx, edx sub ecx, 0x6F mov edx, ecx xor ecx, 0x0BACAF inc eax dec ebx cmp ebx, 0 jnz L000 mov result,ecx } return result; }
DWORD CKeygenDlg::CkSn1(DWORD code) { DWORD result; _asm{ xor eax, eax xor ebx, ebx mov eax, code mov ebx, code mov edx, eax xor edx, ebx xor edx, 0x0FFAC xor ebx, 0x553 add eax, ebx add ebx, edx dec ebx add eax, ebx mov result,eax } return result; }
DWORD CKeygenDlg::CkSn2(DWORD code) { DWORD result; _asm{ mov eax, code mov ebx, code xor ebx, 0x8E add ebx, eax mov result, ebx } return result; }
void CKeygenDlg::CkSn3(char *_addr,DWORD _code) { itoa(_code,_addr,16); } char * CKeygenDlg::GetSerial(DWORD _addr) { char *Serial = NULL; _asm{ mov edx, _addr add edx, 4 mov byte ptr [edx], 0x2D add edx, 0x0A mov byte ptr [edx], 0x2D mov edx, _addr mov byte ptr [edx], 0x4B inc edx mov byte ptr [edx], 0x4F inc edx mov byte ptr [edx], 0x53 } Serial = (char *)_addr; return Serial; }
STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory( &pi, sizeof(pi) ); ZeroMemory( &si, sizeof(si) ); //查找CM的窗口,确定程序是否已经启动! if(FindCM()) { CString PathName = GetCMInfo(); KillProcess(); //先PATCH掉它的限制 if(!EditCm(PathName)) SetDlgItemText(IDC_TISHI,"提示:解除CM的各种限制时出现问题了!"); if(!CreateProcess(PathName,NULL, NULL, NULL,FALSE, 0, NULL, NULL, &si, &pi)) SetDlgItemText(IDC_TISHI,"提示:启动进程失败!"); //再写一下它的算法了 const int nBufSize = 128; TCHAR chBuf[nBufSize]; ZeroMemory(chBuf,nBufSize); DWORD t_rst; DWORD dwRet = nBufSize; if (::GetUserName(chBuf,&dwRet)) { DWORD tmpsn = 0; char *tmpserial = new char[24]; m_Name = chBuf; tmpsn = CLName(chBuf); CkSn3(tmpserial,tmpsn); //itoa tmpserial += 8; t_rst = CkSn1(tmpsn); CkSn3(tmpserial,t_rst);//itoa tmpserial += 8; t_rst = CkSn2(tmpsn); CkSn3(tmpserial,t_rst);//itoa tmpserial -= 16; m_Serial = GetSerial((DWORD )tmpserial); } m_Serial.MakeUpper(); UpdateData(FALSE); SetDlgItemText(IDC_TISHI,"提示:操作完成,请自行验证用户名和序列号!"); } else SetDlgItemText(IDC_TISHI,"提示:请先启动CM,以便与解除CM的各种限制!"); }