远程线程+hook=监控?
见字如面,我是东北码农。
今天文章的关键字是“远程线程”,会带大家使用远程线程+inlinehook实现一个简陋的监控系统,偷偷记录用户执行了哪些程序,可能就像你单位的监控系统一样。
关注微信“东北码农”,回复remotethread可获取代码地址。
下面是效果图,可以记录执行哪些程序、函数参数、执行时间。你也会发现一些有趣的事,例如有时仅仅打开一个目录,就会触发git的缓存进程。
1、双击启动程序时发生了什么?
实现功能前,我们需要了解当我们双击执行一个程序时,到底发生了什么?
1.1、桌面程序-explorer.exe
例如启动一个浏览器,第一步需要先在桌面找到浏览器的图标。在windows系统中,桌面进程是explorer.exe,有点类似linux的shell。如果你现在打开任务管理器,就可以发现explorer.exe进程,如果结束掉explorer.exe进程,桌面就会马上会消失。
1.2、双击执行时发生了什么?
当双击浏览器图标时,就会启动浏览器进程。桌面程序explorer.exe会调用CreateProcess接口,把各项参数填好去创建一个进程。CreateProcess有很多参数,我们监控时只需要关心前两个参数就好,程序执行路径和程序函数。
1.3、如何实现监控?
我们需要在explorer.exe进程空间内hook CreateProcess。就像发射炮弹一样,hook CreateProcess我们可以写到一个dll中,作为炮弹。现在的问题是如何让这枚炮弹发射到explorer.exe进程中。这里进入本文正题:远程线程dll注入。
2、远程线程注入实现
本章节会介绍如何实现一个通用的远程线程注入的小工具,并使用这个工具注入我们的dll到explorer.exe中。
相信对Windows底层编程和系统安全熟悉的人并不陌生,远程线程实现时需要借助于一个Windows API函数CreateRemoteThread,通过它可以在另外一个进程中注入一个线程并执行。
实现函数很简单,仅仅20行代码(没有做返回值判断,仅为了展示记录)代码如下:
static bool remotethread_inject(DWORD pid,const char* dll_path) {
HANDLE pro = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
// step1:在目标进程申请内存
int dll_path_len = strlen(dll_path )+1;
void* remote_buf = VirtualAllocEx(pro, NULL, dll_path_len, MEM_COMMIT, PAGE_READWRITE);
// step2:在目标进程写入dll路径
BOOL ret = WriteProcessMemory(pro, remote_buf, (LPVOID)dll_path, dll_path_len, NULL);
// step3:获取LoadLibraryA地址
auto load_func = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryA");
// step4:执行远程线程
HANDLE remote_thread = CreateRemoteThread(pro, NULL, 0, (LPTHREAD_START_ROUTINE)load_func, remote_buf, 0, NULL);
// step5:等待执远程线程行完毕
WaitForSingleObject(remote_thread, 10000);
return true;
}
远程线程注入dll,就是在目标进程中创建一个线程,执行LoadLibrary,加载我们的dll。
2.1、写入线程函数的参数
// step1:在目标进程申请内存
int dll_path_len = strlen(dll_path )+1;
void* remote_buf = VirtualAllocEx(pro, NULL, dll_path_len, MEM_COMMIT, PAGE_READWRITE);
// step2:在目标进程写入dll路径
BOOL ret = WriteProcessMemory(pro, remote_buf, (LPVOID)dll_path, dll_path_len, NULL);
首先需要把线程入口函数的参数,也就是dll的路径,写入目标进程。需要先在目标进程申请空间,再写入。
2.2、执行远程线程
// step3:获取LoadLibraryA地址
auto load_func = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryA");
// step4:执行远程线程
HANDLE remote_thread = CreateRemoteThread(pro, NULL, 0, (LPTHREAD_START_ROUTINE)load_func, remote_buf, 0, NULL);
// step5:等待执远程线程行完毕
WaitForSingleObject(remote_thread, 10000);
我们需要在目标进程中获取LoadLibrary的地址,因为LoadLibrary在kernel32.dll里,加载比较早,所以在每个进程内地址都一样,所以我们可以在本进程获取直接使用。
然后调用CreateRemoteThread执行远程线程,再调用WaitForSingleObject等待执行结束。
3、dll实现
3.1、dll入口函数
每个dll都有一个入口函数DllMain,在dll加载时会调用,我们把hook操作写在这里。
static bool init = false;
if (!init) {
init = true;
// 打开控制台
if (AllocConsole())
{
freopen("CONOUT$", "w", stdout);
freopen("CONIN$", "r", stdin);
SetConsoleTitleA("Console");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
printf("dll injectok!\n");
}
{
// 制作跳板
xx_mem_unprotect(tra_cw, 1024);
xx_make_trampoline(&CreateProcessW, tra_cw, 0xf);
// HOOK
xx_mem_unprotect(&CreateProcessW, 1024);
xx_setjmp(&CreateProcessW, &MyCreateProcessW);
}
}
先打开一个控制台,在控制台展示hook的信息。然后再进行hook,为了防止多次执行,使用static变量控制一下。
3.3、hook CreateProcess
char tra_cw[1024];
BOOL WINAPI MyCreateProcessW(
_In_opt_ LPCWSTR lpApplicationName,
_Inout_opt_ LPWSTR lpCommandLine,
_In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ BOOL bInheritHandles,
_In_ DWORD dwCreationFlags,
_In_opt_ LPVOID lpEnvironment,
_In_opt_ LPCWSTR lpCurrentDirectory,
_In_ LPSTARTUPINFOW lpStartupInfo,
_Out_ LPPROCESS_INFORMATION lpProcessInformation
) {
time_t now = time(nullptr);
printf("================\n");
printf("%s", ctime(&now));
wprintf(L"execute=%s\npara=%s\n\n" ,lpApplicationName,lpCommandLine );
auto ori = xx_trampoline_to_func(&CreateProcessW, tra_cw);
return (*ori)(lpApplicationName,
lpCommandLine,
lpProcessAttributes,
lpThreadAttributes,
bInheritHandles,
dwCreationFlags,
lpEnvironment,
lpCurrentDirectory,
lpStartupInfo,
lpProcessInformation);
}
hook以后,打印信息,再调用原函数,毕竟我们只是监控,如果想组织,就需要再额外加一些逻辑了。
4、远程线程+hook的其它应用
二者其实可以实现很多有意思的东西:可以hook connect、recv、send来监控网络流量;外挂也可以靠注入+hook实现外挂功能。大家可以开动脑筋做一些有意思的小程序。
最后,东北码农,求关注、点赞、转发,谢谢~