DLL Injection crashes target application on Windows 10 2019 - what can cause the crash? and how to fix the code?

-1

I have DLL injection mechanism that helps me to perform actions on another process. this DLL injects the code successfully on many machines - but I have 1 new machine with windows 10 2019 and only here it crashes the target application. I'm an experienced C# developer but know nothing in C++. this code was taken from SnoopX open source project with some additions I added(for logging purposes). this is my injection DLL code, can you please help me find weak spots that can cause the target process to crash? (it seems from the dump file that the CreateRemoteThread call causing the crash)

#include "stdafx.h"
#include "Injector.h"
#include <vcclr.h>
#include <stdio.h>
#include <conio.h>


EXTERN_C IMAGE_DOS_HEADER __ImageBase;

WCHAR DllPath[MAX_PATH] = { 0 };

#pragma data_seg(".shared")
LPTHREAD_START_ROUTINE _routine = 0;
#pragma data_seg()

using namespace System;
using namespace System::IO;
using namespace System::Diagnostics;
using namespace SnoopXInjector;
//using namespace std;
std::string GetLastErrorAsString();

#pragma managed(push, off)

void LoadImagePath()
{
    ::GetModuleFileNameW((HINSTANCE)&__ImageBase, DllPath, _countof(DllPath));
}

#pragma managed(pop)

String^ GetLogPath()
{
    auto applicationDataPath = Environment::GetFolderPath(Environment::SpecialFolder::LocalApplicationData);

    if (!Directory::Exists(applicationDataPath))
    {
        Directory::CreateDirectory(applicationDataPath);
    }

    auto logPath = applicationDataPath + "\\SnoopXInjector.log";

    return logPath;
}

void Injector::Initialize()
{
    LogMessage("Injector initialization");
}

void LogMessage(String^ message)
{
    try
    {
        File::AppendAllText(GetLogPath(), DateTime::Now.ToString("MM/dd/yyyy HH:mm:ss") + " : " + message + Environment::NewLine);
    }
    catch (Exception^ ex)
    {
        Console::WriteLine(ex->Message); // Print the error message.
        Console::WriteLine(ex->StackTrace); //String that contains the stack trace for this exception.
    }
}

void Injector::LogMessage(String^ message)
{
    ::LogMessage(message);
}

DWORD StartThread(HANDLE hProcess, LPTHREAD_START_ROUTINE function, wchar_t * data)
{
    LogMessage("StartThread method on thread:" + GetCurrentThreadId());
    try
    {
        auto buffLen = (wcslen(data) + 1) * sizeof(wchar_t);
        void* remoteData = ::VirtualAllocEx(hProcess, NULL, buffLen, MEM_COMMIT, PAGE_READWRITE);

        if (remoteData)
        {
            LogMessage("VirtualAllocEx successful");

            ::WriteProcessMemory(hProcess, remoteData, data, buffLen, NULL);

            LogMessage("WriteProcessMemory successful");
            auto hThread = ::CreateRemoteThread(hProcess, NULL, 0,
                function, remoteData, 0, NULL);
            if (!hThread)
            {
                LogMessage("CreateRemoteThread(): failed");
            }
            else
            {
                LogMessage("CreateRemoteThread successful:" + GetThreadId(hThread));
            }
            std::string error = GetLastErrorAsString();
            String^ newSystemString = gcnew String(error.c_str());
            LogMessage(newSystemString);

            ::WaitForSingleObject(hThread, INFINITE);
            LogMessage("WaitForSingleObject successful");

            LogMessage("Thread finished");

            DWORD exitCode;
            ::GetExitCodeThread(hThread, &exitCode);

            ::CloseHandle(hThread);

            ::VirtualFreeEx(hProcess, remoteData, 0, MEM_RELEASE);

            return exitCode;
        }
    }
    catch (Exception^ ex)
    {
        LogMessage(ex->Message); // Print the error message.
        LogMessage(ex->StackTrace); //String that contains the stack trace for this exception.
        return 0;
    }
    return 0;
}

bool^ Injector::Launch(Int32 processId, String^ assembly, String^ className, String^ methodName)
{
    try
    {
        auto assemblyClassAndMethod = assembly + "|" + className + "|" + methodName;
        LogMessage("Assembly Class and Method to load:" + assemblyClassAndMethod);
        pin_ptr<const wchar_t> acmLocal = PtrToStringChars(assemblyClassAndMethod);

        HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
        if (!hProcess)
        {
            LogMessage("failed to get process handle");
            return false;
        }


        LogMessage("Got process handle");

        LoadImagePath();

        auto kernel = ::GetModuleHandle(L"kernel32");
        (HMODULE)StartThread(hProcess, (LPTHREAD_START_ROUTINE)::GetProcAddress(kernel, "LoadLibraryW"), DllPath);
        LogMessage("Library loaded");

        if (_routine)
        {
            LogMessage("Entered If _routine case");
            StartThread(hProcess, _routine, (wchar_t*)acmLocal);
        }

        ::CloseHandle(hProcess);
        LogMessage("Completed launch function");
        return true;
    }
    catch (Exception^ ex)
    {
        LogMessage(ex->Message); // Print the error message.
        LogMessage(ex->StackTrace); //String that contains the stack trace for this exception.
        return false;
    }
}

__declspec(dllexport)
DWORD WINAPI ThreadStart(void* param)
{
    LogMessage("ThreadStart method on thread:" + GetCurrentThreadId());
    try
    {

        //CoInitialize(NULL);

        String^ acmLocal = gcnew String((wchar_t *)param);

        LogMessage(String::Format("acmLocal = {0}", acmLocal));
        cli::array<String^>^ acmSplit = acmLocal->Split('|');

        LogMessage(String::Format("About to load assembly {0}", acmSplit[0]));
        auto assembly = Reflection::Assembly::LoadFile(acmSplit[0]);
        if (assembly == nullptr)
        {
            LogMessage("Assembly loading returned null");
            return 0;
        }

        LogMessage(String::Format("About to load type {0}", acmSplit[1]));
        auto type = assembly->GetType(acmSplit[1]);
        if (type == nullptr)
        {
            LogMessage("Getting type returned null");
            return 0;
        }

        LogMessage(String::Format("Just loaded the type {0}", acmSplit[1]));
        auto methodInfo = type->GetMethod(acmSplit[2], Reflection::BindingFlags::Static | Reflection::BindingFlags::Public);
        if (methodInfo == nullptr)
        {
            LogMessage("Getting method returned null");
            return 0;
        }


        LogMessage(String::Format("About to invoke {0} on type {1}", methodInfo->Name, acmSplit[1]));
        auto returnValue = methodInfo->Invoke(nullptr, nullptr);
        if (returnValue == nullptr)
        {
            returnValue = "NULL";
        }
        LogMessage(String::Format("Return value of {0} on type {1} is {2}", methodInfo->Name, acmSplit[1], returnValue));
    }
    catch (Exception^ e)
    {
        LogMessage(e->Message); // Print the error message.
        LogMessage(e->StackTrace); //String that contains the stack trace for this exception.
    }
    return 0;
}

//Returns the last Win32 error, in string format. Returns an empty string if there is no error.
std::string GetLastErrorAsString()
{
    //Get the error message, if any.
    DWORD errorMessageID = ::GetLastError();
    if (errorMessageID == 0)
        return std::string(); //No error message has been recorded

    LPSTR messageBuffer = nullptr;
    size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);

    std::string message(messageBuffer, size);

    //Free the buffer.
    LocalFree(messageBuffer);

    return message;
}

#pragma managed(push, off)

BOOLEAN WINAPI DllMain(IN HINSTANCE hDllHandle,
    IN DWORD     nReason,
    IN LPVOID    Reserved)
{
    _routine = (LPTHREAD_START_ROUTINE)&ThreadStart;
    return true;
}

#pragma managed(pop)

when trying to debug this C++ code when attaching Visual studio to the target process - the target process crashes and the attachment fails with the following error: "has exited with code -1073741819 (0xc0000005) 'Access violation'" does it help?

c++
dll-injection
asked on Stack Overflow Nov 30, 2020 by Ori Cohen • edited Nov 30, 2020 by Ori Cohen

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0