一个Themida加壳的程序LOADER破解,Themida,脱壳技术 2008年06月23日 星期一 下午 05:50 【文章标题】: 一个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 ("\x72\x12\x68\x3C\x60\x40\x00\x6A\x00\xFF\x15\xA0\x50\x40\x00\x33") //这个是壳解码后没有改动的程序代码 #define NEW_CODE ("\xEB\x12\x68\x3C\x60\x40\x00\x6A\x00\xFF\x15\xA0\x50\x40\x00\x33") //要修改后的代码 #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 { 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 !\n"); //恢复目标程序执行 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_WRITE|PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION, FALSE, dwProcessId); if(hProcess == NULL) return FALSE; int cbSize = (strlen(m_szDllName) 1); LPVOID lpRemoteDllName = VirtualAllocEx(hProcess, NULL, cbSize, MEM_COMMIT, PAGE_READWRITE); WriteProcessMemory(hProcess, lpRemoteDllName, m_szDllName, cbSize, NULL); HMODULE hModule=GetModuleHandle("kernel32.dll"); LPTHREAD_START_ROUTINE pfnStartRoutine = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "LoadLibraryA"); //用远程进程的LoadLibraryA函数的入口点做为远程线程的入口点,线程运行就相当于运行了LoadLibraryA HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, pfnStartRoutine, lpRemoteDllName, 0, NULL); if(hRemoteThread == NULL) { CloseHandle(hProcess); return FALSE; } WaitForSingleObject(hRemoteThread, INFINITE); CloseHandle(hRemoteThread); CloseHandle(hProcess); m_dwProcessId=dwProcessId; return TRUE; } 附件为全部源代码 -------------------------------------------------------------------------------- 【经验总结】 如果没有Loader检测,不需要注入到explorer了,直接用代码CreateProcess然后用上面的CrackIt函数就可以解决问题了。 有检测只好找办法绕过去了。不知道有没有更简单的方法。 本文是写给跟我一样菜鸟的,搞不定壳的,高手就别笑了。 |
|小黑屋|最新主题|手机版|微赢网络技术论坛 ( 苏ICP备08020429号 )
GMT+8, 2024-9-29 21:28 , Processed in 0.257160 second(s), 12 queries , Gzip On, MemCache On.
Powered by Discuz! X3.5
© 2001-2023 Discuz! Team.