这两天仔细研究了下hook api,很难得,我电脑win7 64位,经过3天各种调试、终于有了眉目了,虽然还是有未知小bug,不过应该都能解决。。。 先在网上遍搜api hook相关信息和文档和代码,最后把一些看起来比较正常的代码整合到一起,写到我的代码里,同时把我逆向过的一部分Unlocker代码也弄进去了。 遇到的第一个难题:无论如何注入的代码总也运行不起来,就连xp都不行。。。后来加入各种调试输出语句,排了一些错,还是不行。。看网上有人说想在win7 64位成功必须用Unicode字符串,于是我把一些地方改了,包括Process32FirstW,然而本来很好用的Process32First改了以后,不知道为什么总获取不到信息了,最后仔细在msdn里找了一下,原来第二个参数要对一个成员初始化。。。网上的代码很不正规,图省事就直接贴上去了。。。 第二个问题困扰了我2天:注入进程后总是是目标程序崩溃。。。百思不得其解,网上的代码也是都有问题的,没发现有能用的(64位win7),xp我没装,于是没管。网上的解决办法也不对。第一天晚上,突然发现release版的居然可以用了,注入到目标程序可以显示出对话框,但是点了以后还是程序崩溃。。网上全是求助帖,没看到有真正解决的!!!好水。可是第二天早上,我才发现只有release可以,debug居然不行!!!最后最后我实在没招了用ida看了一下,原来如此啊,,debug里为了调试程序,每一个自己写的函数都是由2个函数实现的,其中一个调用另一个,我把一个函数代码写到另一个进程中后,只是把最外层那个函数调用了,而注入的目标进程肯定是没有里面那个函数的,因为我没法写到进程里,而且极难实现。。连函数在哪里都无法得知的,微软弄得很复杂的。release版由于优化了,只有一个调用函数,所以能正常注入。。。 最后我的解决办法是:利用外壳函数一个性质,外壳函数的内部汇编实现是jmp+偏移地址,这里暂且将外壳函数用func1表示,真正的函数用func2表示。那么有func1() {func2();} 汇编写法就是jmp addr 其中addr为func2函数位置相对于jmp的下一条指令的偏移;这个指令长度5字节,这条指令本身占5字节(jmp1字节),因此只需要读取func1这个函数指针偏移位置为1的地方,读取4字节即可,然后把结果加上func1所在地址,就是func2的绝对地址了。此时把func2写入即可。 做了这些以后,本以为万无一失了,谁知道还是不行,目标进程还是挂掉了。。于是我把写入到内存的那些func2函数代码看了一下,居然和直接汇编得到的(文件中的)不一样。。。,(很茫然,我觉得应该是用来调试的指令吧),总有字节被硬生生替换为0xcc...这是个特权指令,一运行程序就崩了。。。而且程序运行的时候内存里的函数居然也是这个。。。无解。最后想到的办法就是把func2硬编码了,直接编译出来,取得汇编代码相对应的16进制机器码,作为数组直接写到进程中,在执行,这样总不会弄什么猫腻了吧,结果真的可以,对话框有了。。。只有几个烦人的bug都被我调好了,现在仍然有bug,不过可以通过func2让目标进程加载dll了。
func2由于是注入函数,不能有任何直接的东西,比如这个程序自身的指针,字符串,api统统不能用,想用都要传到参数中才行。而且下断点发现func2无法被断下来,,,估计微软没考虑到要为注入程序提供调试了,这个函数里外来的东西都不能直接用,现在仍有一处崩溃,还在查,不过release版倒是可以随便运行了。。呵呵
相关代码:
- [/align][align=left]DWORD RemoteInject(PROCESSENTRY32W* pInfo,DWORD len)
- {
- HMODULE hMod=GetModuleHandle("kernel32.dll");
- ASSERT(hMod != NULL);
- HANDLE hRemoteProcess=OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_WRITE | PROCESS_VM_READ | PROCESS_VM_OPERATION |
- PROCESS_CREATE_THREAD,FALSE,pInfo->th32ProcessID);
- #ifdef _DEBUG
- TRACE("hRemoteProcess=%d\n",hRemoteProcess);
- #endif
- if(hRemoteProcess)
- {
- #ifdef _DEBUG
- unsigned char codedata[] = //Debug版FuncToInject的字节码,随着FuncToInject函数变化而变化
- {
- 0x55, 0x8B, 0xEC, 0x81, 0xEC, 0xC0, 0x00, 0x00, 0x00, 0xB8, 0x01, 0x00, 0x00, 0x00, 0x8B, 0xE5,
- 0x5D, 0xC2, 0x04, 0x00
- };[/align][align=left] LPVOID pfnStartAddr=VirtualAllocEx(hRemoteProcess,NULL,sizeof(codedata),MEM_COMMIT,PAGE_EXECUTE_READWRITE);
- TRACE("pfnStartAddr=%d\n",pfnStartAddr);
- #else
- LPVOID pfnStartAddr=VirtualAllocEx(hRemoteProcess,NULL,len,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
- #endif[/align][align=left] if(pfnStartAddr)
- {
- SIZE_T NumberOfBytesWritten=0;[/align][align=left]#ifdef _DEBUG
- WriteProcessMemory(hRemoteProcess,pfnStartAddr,(LPVOID)codedata,sizeof(codedata),&NumberOfBytesWritten);
- #else
- WriteProcessMemory(hRemoteProcess,pfnStartAddr,(LPVOID)&FuncToInject,len,&NumberOfBytesWritten);
- #endif[/align][align=left]
- LPVOID ParamBuffer=VirtualAllocEx(hRemoteProcess,NULL,sizeof(InjectStruct),MEM_COMMIT,PAGE_EXECUTE_READWRITE);
- #ifdef _DEBUG
- TRACE("ParamBuffer=%d\n",ParamBuffer);
- #endif
- if(ParamBuffer && hMod)
- {
- InjectStruct RemoteFunc;
- RemoteFunc.MyLoadLibraryW=(MYLOADLIBRARYW)GetProcAddress(hMod,"LoadLibraryW");
- RemoteFunc.MyGetModuleHandleW=(MYGETMODULEHANDLEW)GetProcAddress(hMod,"GetModuleHandleW");
- RemoteFunc.MyGetProcAddress=(MYGETPROCADDRESS)GetProcAddress(hMod,"GetProcAddress");
- #ifdef TEST1
- HMODULE userhandle=GetModuleHandleA("user32.dll");
- RemoteFunc.MyMessageBoxW=(MYMESSAGEBOXW)GetProcAddress(userhandle,"MessageBoxW");
- ASSERT(RemoteFunc.MyMessageBoxW != NULL);
- #endif
- memcpy(&RemoteFunc.ProcInfo,pInfo,sizeof(PROCESSENTRY32W));
- ASSERT(RemoteFunc.MyLoadLibraryW != NULL);
- ASSERT(RemoteFunc.MyGetModuleHandleW != NULL);
- ASSERT(RemoteFunc.MyGetProcAddress != NULL);
- lstrcpyW(RemoteFunc.DllFullPath,L"C:\\Users\\Administrator\\Desktop\\TransParentEnDeSrc\\Debug\\TransParentEnDeSrc.dll");//打算做成软件包,路径写到注册表中[/align][align=left] WriteProcessMemory(hRemoteProcess,ParamBuffer,(LPVOID)&RemoteFunc,sizeof(InjectStruct),&NumberOfBytesWritten);[/align][align=left] //HANDLE NewThread=CreateRemoteThread(hRemoteProcess,NULL,1024,(LPTHREAD_START_ROUTINE)pfnStartAddr,ParamBuffer,0,NULL);
- HANDLE NewThread=MyCreateRemoteThread(hRemoteProcess,(LPTHREAD_START_ROUTINE)pfnStartAddr,ParamBuffer);
- #ifdef _DEBUG
- // TRACE("%S CreateRemoteThread:Getlasterror:%d\n",pInfo->szExeFile,GetLastError());
- #endif
- if(NewThread)
- WaitForSingleObject(NewThread,INFINITE);
- VirtualFreeEx(hRemoteProcess,ParamBuffer,0,MEM_RELEASE);
- CloseHandle(NewThread);
- }
- VirtualFreeEx(hRemoteProcess,pfnStartAddr,0,MEM_RELEASE);
- }
- #ifdef _DEBUG
- else
- {
- TRACE("失败:%d\n",GetLastError());
- }
- #endif[/align][align=left] CloseHandle(hRemoteProcess);
- }
- return 0;
- }[/align]
- [align=left]
- BOOL WINAPI FuncToInject(InjectStruct* INJECT)//此代码在拦截createprocess时也要用到
- {//注入函数中不能有任何内部指针,字符串,函数也最好作为指针存到参数中 注入函数无法调试。。。。
- if(INJECT->MyGetModuleHandleW(INJECT->DllFullPath)) return TRUE;//DLL已经加载直接返回
- HMODULE hMod=INJECT->MyLoadLibraryW(INJECT->DllFullPath);
- if(hMod == NULL)
- return FALSE;
- SETINFO setinfo=(SETINFO)INJECT->MyGetProcAddress(hMod,(const char*)MAKELONG(1,0));//获取第一个函数
- setinfo(&INJECT->ProcInfo);
- return TRUE;
- } [/align][align=left]
复制代码
|