简体   繁体   English

进程注入器在 CreateRemoteThread 上崩溃

[英]Process Injector Crashes on CreateRemoteThread

I have created a process DLL injector in C for detection engineering purposes, it seems to work great on test processes I spawn in a shell (maybe because they are in the same path, or something with non-shells and printf) but whenever I test it on a random process it crashes said process at the CreateRemoteThread step, wondering if any of you could help thanks.我在 C 中创建了一个用于检测工程目的的进程 DLL 注入器,它似乎在我在 shell 中生成的测试进程上工作得很好(可能是因为它们在同一路径中,或者是非 shell 和 printf 的东西)但是每当我测试时它在一个随机进程中它在 CreateRemoteThread 步骤崩溃了该进程,想知道你们是否可以提供帮助,谢谢。

Here is the command I use if that helps (Bash): ./ProcessInjector.exe [PID] C:\\Users\\wsam\\Documents\\Process-Injection\\bad_dll.dll这是我使用的命令(Bash):./ProcessInjector.exe [PID] C:\\Users\\wsam\\Documents\\Process-Injection\\bad_dll.dll

EDIT: I noticed if I take out all code in the bad_dll.dll while loop it succeeds in creating a thread and doesn't crash the process, why is that?编辑:我注意到如果我在循环中取出 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 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);
    }
}

Here is my very basic example of a dll injector using VirtualAllocEx, CreateRemoteThread & LoadLibrary:这是我使用 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;
}

This code includes grabbing the null terminator of your path string:此代码包括获取路径字符串的空终止符:

strlen(dllpath) + 1

EDIT: I noticed if I take out all code in the bad_dll.dll while loop it succeeds in creating a thread and doesn't crash the process, why is that?编辑:我注意到如果我在循环中取出 bad_dll.dll 中的所有代码,它会成功创建一个线程并且不会使进程崩溃,这是为什么?

I believe your Infinite Loop in DllMain is the cause of your problem, it never returns.我相信您在 DllMain 中的无限循环是您问题的原因,它永远不会返回。 When you remove the code in the loop, your compiler is optimizing away the loop and therefore it stops crashing.当您删除循环中的代码时,您的编译器正在优化循环,因此它停止崩溃。

Everyone says never to call CreateThread() from DllMain but millions of people are doing it without any issues.每个人都说永远不要从 DllMain 调用 CreateThread(),但数百万人在这样做时没有任何问题。 The concern is in regards to loader deadlock but I've been injecting DLLs for 5 years and never had a single problem, that is my experience and the roots of my beliefs are born in experience.担心是关于加载程序死锁,但我已经注入 DLL 5 年了,从来没有遇到过任何问题,这是我的经验,我的信念根源于经验。 You should at least be aware of the possible issues by reading and following links in this question .您至少应该通过阅读并点击此问题中的链接了解可能存在的问题

Disregarding all the CRT in DLLMain hate I suggest you do:忽略 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;
}

In this manner, both CreateThread and DllMain return 99.9999% of the time.以这种方式,CreateThread 和 DllMain 都返回 99.9999% 的时间。

This is a proof of concept based on my experience.这是基于我的经验的概念证明。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM