使用 C 崩溃记事本进行 DLL 注入

Posted

技术标签:

【中文标题】使用 C 崩溃记事本进行 DLL 注入【英文标题】:DLL injection using C crash notepad 【发布时间】:2020-01-04 22:57:08 【问题描述】:

我使用 C 和 DLL 创建了一个 DLL 注入程序。当我尝试运行程序时,目标进程崩溃(我尝试了记事本和 cmd)。我将注入器编译为 64 位和 DLL。用 Visual Studio 编译的程序和 DLL。

经过一番检查,如果我删除CreateRemoteThread,程序不会崩溃,并且DLL注入(当然没有执行DLL)。

我尝试使用RUNDLL32.exe 来检查是否是DLL 的问题,并且我已经能够看到消息框。

喷油器:

#include <Windows.h>
#include <stdio.h>

int main() 
    // The DLL path we want to inject and the target process id.
    LPCSTR dllpath = "C:\\Users\\....\\hello-world.dll";
    int processID = 2980;

    printf("#### Starting ####\n");

    // Open target process handle    
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processID);
    if (hProcess == NULL) 

        //close handles
        CloseHandle(hProcess);

        printf("[!] Unable to find the target process id: %d\n" , processID);
        return 1;
    
    printf("[+] Open target process handle\n");

    // Getting targt memory address for the dll path
    LPVOID dllpathMemoryAddr = VirtualAllocEx(hProcess, NULL, strlen(dllpath) + 1, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if (dllpathMemoryAddr == NULL) 

        //close handles
        CloseHandle(hProcess);

        printf("[!] Unable to get memory address of target process for the dllpath");
        return 1;
    
    printf("[+] Allocate the memory address to store the dllpath\n");

    // Writing the dll path to the target memory address
    BOOL succeedWrite = WriteProcessMemory(hProcess, dllpathMemoryAddr, dllpath, strlen(dllpath) + 1, NULL);
    if (!succeedWrite) 

        //close handles
        CloseHandle(hProcess);

        printf("[!] Unable to write to the memory address of target process the dllpath\n");
        return 1;
    
    printf("[+] Writed the dllpath to memory\n");

    // Getting LoadLibreryA address
    FARPROC loadLibAddr = 
        (GetModuleHandle(TEXT("kernel32.dll")), "LoadLibraryA");
    if (loadLibAddr == NULL) 
        // free the memory 
        VirtualFreeEx(hProcess, dllpathMemoryAddr, 0, MEM_RELEASE);

        //close handles
        CloseHandle(hProcess);

        printf("[!] Unable to get the memory address of LoadLibraryA function\n");
        return 1;
    
    printf("[+] Allocate the memory address to LoadLibraryA function\n");

    // Create remote thread on the remote process to load the dll
    HANDLE rThread = CreateRemoteThread(hProcess, 0, 0, (LPTHREAD_START_ROUTINE)loadLibAddr, dllpathMemoryAddr, 0, NULL);
    if (rThread == NULL) 
        // free the memory 
        VirtualFreeEx(hProcess, dllpathMemoryAddr, 0, MEM_RELEASE);

        //close handles
        CloseHandle(hProcess);

        printf("[!] Unable to create thread to execute the LoadLibraryA function\n the error: %u\n", GetLastError());
        return 1;
    
    printf("[+] Created remote thread to execute the dll\n");
    // Waiting to opertion to complete
    WaitForSingleObject(rThread, INFINITE);

    // free the memory 
    VirtualFreeEx(hProcess, dllpathMemoryAddr, 0, MEM_RELEASE);

    //close handles
    CloseHandle(hProcess);
    CloseHandle(rThread);

    printf("#### DLL INJECTED ####\n");


    return TRUE;

DLL

#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <windows.h>

extern "C" __declspec(dllexport)
BOOL APIENTRY DllMain(HMODULE hModule,
                      DWORD ul_reason_for_call,
                      LPVOID lpReserved) 
  switch (ul_reason_for_call) 
    case DLL_PROCESS_ATTACH:
      MessageBox(NULL, "Hello world!", "Hello World!", NULL);
      break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
      break;
  
  return TRUE;

输出:

#### Starting ####
[+] Open target process handle
[+] Allocate the memory address to store the dllpath
[+] Writed the dllpath to memory
[+] Allocate the memory address to LoadLibraryA function
[+] Created remote thread to execute the dll
#### DLL INJECTED ####

【问题讨论】:

评论不用于扩展讨论;这个对话是moved to chat。 【参考方案1】:

如果我正确理解了 OP 的 cmets,主要问题是 OP 最初使用了以下行(在编辑问题之前):

BOOL succeedWrite = WriteProcessMemory(hProcess, dllpathMemoryAddr, dllpath, strlen(dllpath), NULL);

通过写入strlen(dllpath) 而不是strlen(dllpath) + 1 字节,OP 没有将字符串的终止空字符写入远程进程。因此,当将该非终止字符串作为函数参数传递给LoadLibraryA 时,远程进程可能会崩溃。

正如 cmets 部分所指出的,代码还存在一些其他问题,但这些问题不太可能是导致崩溃的原因。

【讨论】:

以上是关于使用 C 崩溃记事本进行 DLL 注入的主要内容,如果未能解决你的问题,请参考以下文章

使用挂钩函数时应用程序崩溃

将 dll 注入 Windows 10 记事本

我在试着做一个木马Loader注入记事本然后CreateRemoteThread启动DLL 但是似乎注入成功,DLL没有启动

c#打开cad更新的同时更新dll

dll文件怎么打开

FreeLibraryAndExitThread 在卸载注入的 DLL 时使程序崩溃