找回密码
 注册
搜索
热搜: 回贴

一个Themida加壳的程序LOADER破解,Themida,脱壳技术

2010-1-30 18:22| 发布者: admin| 查看: 123| 评论: 0|原作者: 墨元


一个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函数就可以解决问题了。

有检测只好找办法绕过去了。不知道有没有更简单的方法。



本文是写给跟我一样菜鸟的,搞不定壳的,高手就别笑了。




最新评论

QQ|小黑屋|最新主题|手机版|微赢网络技术论坛 ( 苏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.

返回顶部