個人360破解考題答案

直接貼上答案中提供的文檔,以下(別人博客中文章編輯得十分漂亮,各類高亮,但這個對我來講太難了。。):算法

 

運行「破解考題.exe」後,使用遠程注入工具「RemoteDll.exe」將「patch.dll」注入到進程「破解考題.exe」,以後便可使用「keygen.exe」生成註冊碼進行註冊。函數

如:
MyNameIsMrWrong
6B707743323168447730652B5A68315639572F74566E75564D3251364F48305432522B6F4441697848334F766749494E5846365249575647363873326A516A756F326B62工具

MrWrong
45784F625156694C304D70355A68315639572F74566E75564D3251364F48305432522B6F4441697848334F766749494E5846365249575647363873326A516A756F326B62加密


代碼開發環境:win7 x64 sp1線程


程序不徹底分析以下:1.首先脫掉壓縮殼便於分析。調試

2.脫殼後分析發現,有以下代碼:
if ( CreateMutexW(0, 0, Name) )
{
  if ( GetLastError() == 0xB7 )
  {
    CreateThread(0, 0, sub_401BC0, 0, 0, 0); //建立線程,線程內還會建立線程,解密用於校驗的部分代碼,
  }
  else    //是第一個實例,則以調試方式運行本身的副本
  {
    Filename = 0;
    memset(&v10, 0, 0x206u);
    memset(&StartupInfo.lpReserved, 0, 0x40u);
    StartupInfo.cb = 68;
    GetModuleFileNameW(0, &Filename, 0x208u);
    if ( CreateProcessW(&Filename, 0, 0, 0, 0, 1u, 0, 0, &StartupInfo, &ProcessInformation) )
    {
      DebugEvent.dwDebugEventCode = 0;
      memset(&DebugEvent.dwProcessId, 0, 0x5Cu);
      while ( WaitForDebugEvent(&DebugEvent, 0xFFFFFFFF) )
      {
        if ( DebugEvent.dwDebugEventCode == 8 )   //單步調試副本,直到副本output一個DebugString
          break;
        ContinueDebugEvent(DebugEvent.dwProcessId, DebugEvent.dwThreadId, 0x10002u);
      }
      DebugSetProcessKillOnExit(0);
      DebugActiveProcessStop(ProcessInformation.dwProcessId);
      ExitProcess(0);
    }
  }
}
orm

3.用於校驗的部分代碼是經過文件的crc32校驗以及哈希值加密的,若是改變文件則沒法正確解密。正確解密後經過與地址00541702處 call VirtualProtect,修改此段動態申請內存爲PAGE_EXECUTE_READWRITE
權限。我並不打算在這以前修改程序中的任何數據,因此這一塊東西並不擔憂,就此打住。blog

4.解密出來的這部分代碼分析(註冊碼校驗過程):
(1)註冊碼全是數字,兩兩組合後爲一段字符串,記爲」A「,對A進行base64解密(base64解密函數爲相對於這塊動態申請的內存偏移爲0x1000,記爲sub_off_1000),base64解密後,獲得的數據記爲」B「。
(2)」B」將經過函數sub_off_1A90解密獲得"C",內部固定使用祕鑰"lingdux_keygen",是512位的加解密方式,但此解密函數我未弄明白是什麼算法,僅懷疑是AES512,(固不下鉤子的註冊機沒法給出)。
(3)計算Username字符串的MD5值,記爲「D」。
(4)對於「C」,需知足以下關係。
C[0] == D[0];
C[1] == D[2];
C[2] == D[4];
C[3] == D[6];
C[5] == D[8];
C[6] == D[10];
C[7] == D[12];
C[8] == D[14];
(5)使用函數sub_off_1DD0+祕鑰「lingdux」,解密一串二進制(爲弄明白的二進制串,記爲」Q「),獲得固定字符串:」Success「,因爲sub_off_1A90函數未弄明白,寫出註冊機的想法心灰意冷,而且上班工做繁忙,這裏就無論他了。
可是這個"Q"確定是由」C「的後面部分變形而來。
(6)計算字符串」Success「的MD5值,獲得二進制序列: 505a83f220c02df2f85c3810cd9ceb38,並與程序中存儲的二進制序列比較。若是不是則功虧一簣。進程


註冊機沒法作出,就將沒弄明白的地方HOOK住,變成已知的。
以下:
int __stdcall hook_off_1a90(void)
{
  BYTE* p; //[in] & [out]
  _asm
  {
    mov p, ecx
  }
  //作註冊機時,可對p中的數據進行加密,我沒有進行加密了,直接原封不動。
  // some_encrypt(p,64);
  return 1;
}內存

還有一處hook,是爲了hook_off_1a90的時機,即在即將調用上文中」校驗的部分代碼「時。
00401A20 ; DWORD __stdcall sub_401A20(LPVOID lpThreadParameter)
00401A20 lpThreadParameter= dword ptr 4
00401A20
00401A20 push offset dword_5B40A8
00401A25 call dword_5B40A0 //此處下刀
00401A2B add esp, 4
00401A2E xor eax, eax
00401A30 retn 4
00401A30 StartAddress endp

鉤子源碼部分以下:
int __stdcall hook_5b40a0(int np)
{
  _asm
  {
    pushad
    pushfd
  }
  static BOOL patched = FALSE;
  if(!patched)
  {
    patched = TRUE;
    DWORD addr = (DWORD)g_5b40a0 - 0x1F20 + 0x2167 + 1;
    DWORD call_offset = (DWORD)hook_off_1a90 - addr - 4;
    *(DWORD*)addr = call_offset; //hooked hook_off_1a90
  }
  _asm
  {
    popfd
    popad
  }
  int ret = g_5b40a0(np);
  return ret;
}

其它部分和原註冊算法一致,僅在未知之處略施手段,變未知爲已知。
時間有限,遠程注入工具則使用一款經典的工具」RemoteDll.exe「。
學海無涯,失誤之處敬請諒解。


by:MrWrong 郵箱:rongguozhen@foxmail.com 20140428

 

文件: http://files.cnblogs.com/MrWrong/360.rar

相關文章
相關標籤/搜索