当前位置: 移动技术网 > 网络运营>安全>加解密 > 一个Themida加壳的程序LOADER破解

一个Themida加壳的程序LOADER破解

2018年03月25日  | 移动技术网网络运营  | 我要评论

【文章标题】: 一个themida加壳的程序LOADER 破解
【文章作者】: rockhard
【作者邮箱】: wnh1@sohu.com
【软件名称】: test.exe
【加壳方式】: themida
【保护方式】: themida
【使用工具】: ollydbg,VC
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  遇到一个程序,在Ollydbg修改某些关键点可以运行了,但由于用THEMIDA加壳了,水平菜,脱不掉壳,每次只能在
  OLLYDBG中运行,想给他写个LOADER加载,然后修改内存。发现用CreateProcess 、ShellExecute和WinExec运行起来就报错,
  看来是加了LOADER的ANTI了。不能脱壳,只能在LOADER上做文章了。
  
  
  最直接的想法就是模拟explorer启动它,然后再修改。整个思路是这样:
  
  1、创建一个Event,用于进程间同步。
  2、将DLL注入到explorer中,
  3、Loader 调用WaitForObject进入等待状态。
  4、DLL 的DLL_PROCESS_ATTACH中创建一线程,用CreateProcess启动目标程序,这地方用CREATE_SUSPENDED标志,免得跑飞了
  5、DLL中用OpenEvent找到上面Event ,通知一次,激活LOADER线程。
  6、LOADER 查找目录程序,然后不断的SUSPEND目标进程,查看要修改的地方有没有已解码,如果已解码,PATCH,没有,将目标进程恢复运行一小段时间。
  
  源代码中没有什么注释,这儿帖出部分写上注释:
  
  PATCH代码段如下:
  //////////////////////////////////////////////////////////////////////////
  /**
    *  dwProcessID : Process ID which wanted to patch
    *
    *  return      : return TRUE if patch successfully ,otherwise return FALSE
    */
  
  #define PATCH_ADDRESS   0x401019      //目标进程中要PATCH 的地址
  #define PATCH_SIZE      16            //从目标进程中读取的字节数
  #define KEY_CODE        ("x72x12x68x3Cx60x40x00x6Ax00xFFx15xA0x50x40x00x33") //这个是壳解码后没有改动的程序代码
  #define NEW_CODE        ("xEBx12x68x3Cx60x40x00x6Ax00xFFx15xA0x50x40x00x33") //要修改后的代码
  #define TRY_TIMES       400  //只试搜索N次,如果还没出现,就不再查找了。
  
  
  BOOL CrackIt(DWORD dwProcessID)
  {
    BOOL bContinueRun=TRUE;
    BOOL bPatchSucess =FALSE;
    DWORD dwTryTimes=0;
    DWORD dwOldProtection,dwDummy;
  
    HANDLE hProcess =OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessID);
    VirtualProtectEx (hProcess, (LPVOID)PATCH_ADDRESS, PATCH_SIZE,PAGE_EXECUTE_READWRITE, &dwOldProtection);
  
    //如果PATCH成功,设置bContinue为假,或尝试了N次后还不能找到要修改的代码,放弃了。
    while(bContinueRun && ++dwTryTimes<TRY_TIMES)
    {
      BYTE OldKeyCode[17];
  
      //让目标程序运行3ms 然后停下来,此时读目标程序的进程,查看是否已解码了
      SuspendResumeProcess(dwProcessID,FALSE);
      Sleep(3);
      SuspendResumeProcess(dwProcessID,TRUE);
  
      //读目标进程要PATCH地址处的数据
      ReadProcessMemory(hProcess, (LPVOID)PATCH_ADDRESS, OldKeyCode, PATCH_SIZE,&dwDummy);
  
      //判断是不是完全解码出来了
      if( !memcmp(OldKeyCode,(BYTE *)KEY_CODE, 16) ){
  
        //相同,说明已解码了,写入我们的新值
        WriteProcessMemory(hProcess, (LPVOID)PATCH_ADDRESS, NEW_CODE, PATCH_SIZE,&dwDummy);
        //we have patched ,stop check :-)
        bPatchSucess=TRUE;
        bContinueRun=false;
      }
    }
    VirtualProtectEx(hProcess, (LPVOID)PATCH_ADDRESS, PATCH_SIZE,dwOldProtection, &dwDummy);
  
    //for debug
    if(dwTryTimes >= TRY_TIMES)
      OutputDebugString("Cannot Match Code In Program ! ");
  
    //恢复目标程序执行
    SuspendResumeProcess(dwProcessID,FALSE);
  
    return bPatchSucess;
  
  }


另外,在创建目标进程时不能写入绝对路径,不知道什么原因,后来通过SetCurrentDirectory改变工作目录解决了这个问题:
  #define WORK_DIRECTORY          "C:\test"
  #define CRACK_PROGRAM_NAME      "test.exe"  //这地方如果写成c:\test\test.exe传给CreateProcess尽管目标程序运行,但explorer会出错.不明白
  
  DWORD WINAPI StartProcess(LPVOID lpParam)
  {
    STARTUPINFO si = { sizeof(si) };
    PROCESS_INFORMATION pi;
  
    si.dwFlags = STARTF_USESHOWWINDOW;
    si.wShowWindow = TRUE;
  
    SetCurrentDirectory(WORK_DIRECTORY); //IMPORTANT!!
  
    BOOL bRet = CreateProcess(NULL, CRACK_PROGRAM_NAME,
      NULL, NULL, FALSE,  CREATE_SUSPENDED,
      NULL, NULL, &si,  &pi);
  
    if(bRet){
      CloseHandle (pi.hThread);
      CloseHandle (pi.hProcess);
    }
  
    HANDLE hEvent = OpenEvent(EVENT_ALL_ACCESS,FALSE,EVENT_OBJECT_NAME);
    SetEvent(hEvent);
  
    return 0;
  }
  
  注入到explorer的代码(感谢CSDN上的kesummer帮助):
  BOOL CInjector::InjectModuleInto(DWORD dwProcessId)
  {
    //不要给自己注入
    if(GetCurrentProcessId() == dwProcessId)
      return FALSE;
  
    //下面一段代码用于在explorer中查找dll是不是已经注入过了。
    BOOL bFound = FALSE;
    MODULEENTRY32 me32 = { 0 };
    me32.dwSize = sizeof(MODULEENTRY32);
  
    HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
    if(Module32First(hModuleSnap, &me32)) {
      do{
        if(lstrcmpiA(me32.szExePath, m_szDllName) == 0) {
          bFound = TRUE;
          break;
        }
      }
      while(Module32Next(hModuleSnap, &me32));
    }
    CloseHandle(hModuleSnap);
  
    if(bFound)  return FALSE;
  
  
    HANDLE hProcess = OpenProcess(
      PROCESS_VM

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网