我是靠谱客的博主 自然帅哥,最近开发中收集的这篇文章主要介绍C/C++ 远程线程注入,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

  • DLL文件如果不被进程加载就无效了
  • 方法是强制让某进程加载DLL文件,强制手段通过创建远程线程将DLL注入到某个指定的进程中

使用CreateRemoteThread()函数创建远程线程

HANDLE CreateRemoteThread(
    HANDLE hProcess,       // handle to process
    LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD
    DWORD dwStackSize,      // initial stack size
    LPTHREAD_START_ROUTINE lpStartAddress, // thread function
    LPVOID lpParameter,      // thread argument
    DWORD dwCreationFlags,     // creation option
    LPDWORD lpThreadId      // thread identifier
);

HANDLE WINAPI CreateThread(
    LPSECURITY_ATTRIBUTES lpThreadAttributes,
    DWORD dwStackSize,
    LPTHREAD_START_ROUTINE lpStartAddress,
    LPVOID lpParameter,
    DWORD dwCreationFlags,
    LPDWORD lpThreadId
)
{
    return CreateRemoteThread(GetCurrentProcess(),
    lpThreadAttributes,
    dwStackSize,
    lpStartAddress,
    lpParameter,
    dwCreationFlags,
    lpThreadId);
}

GetCurrentProcess()函数的功能是获取当前进程的句柄
CreateRemoteProcess()函数是注入到其他进程的,其第一个参数是指定某进程的句柄。得到目标进程的PID(进程ID),就可以通过==OpenProcess()==函数获取该进程的句柄。

除了hProcess参数以外,关键的参数就只有lpStartAddress和lpParameter两个了。lpStartAddress指定线程函数的地址lpParameter指定传递给线程函数的参数。每个进程的地址空间是隔离的,那么新创建的线程函数的地址也应该在目的进程中,而不应该在本进程中,同样的传递给线程函数的参数也应该在目的进程中。

注入DLL,线程函数的功能也就是加载DLL文件。加载DLL文件的方法是调用LoadLibrary()函数。

HMODULE LoadLibrary(
    LPCTSTR lpFileName // file name of module
);

DWORD WINAPI ThreadProc(
LPVOID lpParameter // thread data
);

可以直接把LoadLibrary()函数作为线程函数创建到指定进程中。LoadLibrary()的参数是要加载的DLL文件的路径。这样,使用CreateRemoteThread()就可以创建一个远程线程了。

那就是如何将LoadLibrary()函数的地址放到目标进程空间中,还有如何把DLL文件路径也保存到目标进程空间中。

LoadLibrary()函数在Kernel32.dll这个系统DLL中,而Kernel32.dll这个DLL文件在任何进程中的加载位置都是相同的,也就是说,LoadLibrary()函数的地址在任何进程中的地址都是相同的,因此只要在进程中获取LoadLibrary()函数的地址后,该地址在目标进程中也是可以使用的。至于要注入的DLL文件如何写入目标进程中,那么就要依赖一个API函数了,

BOOL WriteProcessMemory(
    HANDLE hProcess,   // handle to process
    LPVOID lpBaseAddress,  // base of memory area
    LPVOID lpBuffer,   // data buffer
    DWORD nSize,    // number of bytes to write
    LPDWORD lpNumberOfBytesWritten // number of bytes written
);
该函数的功能是把lpBuffer中的内容写到hProcess指定进程中的
lpBaseAddress地址处
hProcess:指定进程的进程句柄。
lpBaseAddress:指定写入内存的起始地址。
lpBuffer:指定要写入的内容的缓冲区。
nSize:指定写入内容的长度。
lpNumberOfBytesWritten:接收实际写入内容的长度。

使用该函数可以把DLL文件的地址写入目标进程中,这样就可以在目标进程中用LoadLibrary()加载该DLL文件。但是WriteProcessMemory()第二个参数是指定写入的起始地址,这个地址明显在目标进程中,那么这个地址是哪个地址?目标进程中的哪块内存允许把DLL文件的路径写进去呢?如何确定应该写入目标进程的哪个地址。应该先在目标进程中申请一块内存,然后把DLL文件的路径写入进去,这样就可以解决了。
在目标进程申请内存的函数如下

LPVOID VirtualAllocEx(
    HANDLE hProcess,   // process to allocate memory
    LPVOID lpAddress,   // desired starting address
    SIZE_T dwSize,    // size of region to allocate
    DWORD flAllocationType,  // type of allocation
    DWORD flProtect    // type of access protection
);
参数说明如下。
(1)hProcess:指定要申请内存的进程句柄。
(2)lpAddress:指定申请的起始位置。
(3)dwSize:指定申请的长度。
(4)flAllcationType:指定申请内存的状态类型。
(5)flProtect:指定申请内存的内存属性。
该函数的返回值返回目标进程申请到的内存块的起始地址。

对于DLL的卸载使用的API函数如下:

BOOL FreeLibrary(
HMODULE hModule // handle to DLL module
);
该函数的参数是要卸载的模块的句柄。
CString strdWord="FFF9AA1D"; DWORD dwWord=_tcstoul(strdWord,NULL,16); //16进制还可以是2、8、10进制
CString strdWord="124572112121"; DWORD dwWord=_tcstoul(strdWord,NULL,10); // 10进制 

按照以上的方式,使用getpid获取指定名称进程pid,传入OpenProcess打开进程获取进程句柄。但是会发现这时候进程是无法打开的,或者说进程不能以完全访问的权限打开,因此必须提高本地程序的权限,这是远程注入线程引发的第一个问题

//获取进程name的ID
DWORD getPid(LPTSTR name)
{
    HANDLE hProcSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);//获取进程快照句柄
    assert(hProcSnap!=INVALID_HANDLE_VALUE);
    PROCESSENTRY32 pe32;
    pe32.dwSize=sizeof(PROCESSENTRY32);
    BOOL flag=Process32First(hProcSnap,&pe32);//获取列表的第一个进程
    while(flag)
    {
        if(!_tcscmp(pe32.szExeFile,name))
        {
            CloseHandle(hProcSnap);
            return pe32.th32ProcessID;//pid
        }
        flag=Process32Next(hProcSnap,&pe32);//获取下一个进程
    }
    CloseHandle(hProcSnap);
    return 0;
}

最后

以上就是自然帅哥为你收集整理的C/C++ 远程线程注入的全部内容,希望文章能够帮你解决C/C++ 远程线程注入所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(33)

评论列表共有 0 条评论

立即
投稿
返回
顶部