网上的一个很普通的DLL注入代码,突发奇想:看能否通过寄存器给线程my_threadProc传个参数过去,很可惜的是VC2010的调试器总是崩溃,查看不到变量及寄存器的数值,发到这里求高手答疑,先谢谢了。
代码附上:
#include <TlHelp32.h>
typedef struct _RemoteParam {
DWORD dwLoadLibrary;
WCHAR szDLLName[128];
} RemoteParam, * PRemoteParam;
//定义LoadLibrary类型的函数指针
typedef HMODULE (__stdcall *PFN_LOADLIBRARY)(WCHAR *lpLibFileName);
//线程函数定义
void My_threadProc()
{
DWORD dwParam;
_asm MOV dwParam,EDX
RemoteParam* pRP = (RemoteParam*)dwParam;
PFN_LOADLIBRARY pfnLoadLibrary;
pfnLoadLibrary=(PFN_LOADLIBRARY)pRP->dwLoadLibrary;
pfnLoadLibrary(pRP->szDLLName);
return;
}
class CDllInjector {
bool enableDebugPriv();
public:
CDllInjector();
int InstallHook(LPCTSTR lpRunFileName,LPCTSTR lpDllName);
};
bool CDllInjector::enableDebugPriv()
{
HANDLE hToken;
LUID sedebugnameValue;
TOKEN_PRIVILEGES tkp;
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
return false;
}
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue)) {
CloseHandle(hToken);
return false;
}
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = sedebugnameValue;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL)) {
CloseHandle(hToken);
return false;
}
return true;
}
CDllInjector::CDllInjector() {
}
int CDllInjector::InstallHook(LPCTSTR lpRunFileName,LPCTSTR lpDllName)
{
enableDebugPriv();
CONTEXT context;
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
memset(&context,0,sizeof(context));
context.ContextFlags = CONTEXT_CONTROL;
ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO));
siStartInfo.cb = sizeof(STARTUPINFO);
DWORD bOk = CreateProcessW(NULL,
(LPWSTR)lpRunFileName, // command line
NULL, // process security attributes
NULL, // primary thread security attributes
FALSE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL,// current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
if(bOk==0) return -1;
WaitForInputIdle(piProcInfo.hProcess,-1);
//定义线程参数结构体变量
RemoteParam remoteData;
ZeroMemory(&remoteData, sizeof(RemoteParam));
//填充结构体变量中的成员
LPVOID lpFunc=GetProcAddress(GetModuleHandle(TEXT("Kernel32.dll")),"LoadLibraryW");
if (lpFunc == NULL){
return -2;
}
remoteData.dwLoadLibrary =(DWORD)lpFunc;
wsprintfW(remoteData.szDLLName,TEXT("%s"),lpDllName);
DWORD remoteDataSize=sizeof(RemoteParam);
RemoteParam* pRemoteParam = (RemoteParam*)VirtualAllocEx(piProcInfo.hProcess,NULL,remoteDataSize,MEM_COMMIT,PAGE_READWRITE);
if (!pRemoteParam) {
return -3;
}
DWORD dwHasWrite;
if(!WriteProcessMemory(piProcInfo.hProcess,pRemoteParam,&remoteData,remoteDataSize,&dwHasWrite)){
VirtualFreeEx(piProcInfo.hProcess,pRemoteParam,remoteDataSize,MEM_COMMIT);
return -4;
}
if(dwHasWrite != remoteDataSize) {
VirtualFreeEx(piProcInfo.hProcess,pRemoteParam,remoteDataSize,MEM_COMMIT);
return -5;
}
DWORD dwThreadSize =4096;
void* pRemoteThread = VirtualAllocEx(piProcInfo.hProcess,0,dwThreadSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!pRemoteThread) {
VirtualFreeEx(piProcInfo.hProcess,pRemoteParam,remoteDataSize,MEM_COMMIT);
return -6;
}
//将线程体拷贝到宿主进程中
if (!WriteProcessMemory(piProcInfo.hProcess,pRemoteThread, &My_threadProc, dwThreadSize, &dwHasWrite)) {
VirtualFreeEx(piProcInfo.hProcess,pRemoteParam,remoteDataSize,MEM_COMMIT);
VirtualFreeEx(piProcInfo.hProcess,pRemoteThread,dwThreadSize,MEM_COMMIT);
return -7;
}
if(dwHasWrite != dwThreadSize) {
VirtualFreeEx(piProcInfo.hProcess,pRemoteParam,remoteDataSize,MEM_COMMIT);
VirtualFreeEx(piProcInfo.hProcess,pRemoteThread,dwThreadSize,MEM_COMMIT);
return -8;
}
//挂起目标进程的主线程
SuspendThread(piProcInfo.hThread);
//获取目标线程的CPU上下文信息
if(!GetThreadContext(piProcInfo.hThread,&context)) return -9;
//更改Eip指令为我们拷贝好的threadProc函数
context.Eip =(DWORD)pRemoteThread;
context.Edx=(DWORD)pRemoteParam;//求解:是否能达到传递参数到my_threadPro线程?
//设置目标线程的CPU上下文信息
if(!SetThreadContext(piProcInfo.hThread,&context)) return -10;
//唤醒目标线程,
ResumeThread(piProcInfo.hThread);
//目标线程此时就会执行我们的threadProc函数了,执行完后还会继续沿着自己原先的代码序列执行下去。
return 0;
}