Quantcast
Channel: Active questions tagged crash - Stack Overflow
Viewing all articles
Browse latest Browse all 7188

Dll Injection - Injecting c# .Net dll into .Net x64 process only sometimes crashes the target application

$
0
0

I have a 64 bit process and i'm trying to inject C# .Net dll and invoke one of its methods using the below "Launch" method. this code was taken from SnoopX GitHub project with some changes i made by myself. the target process is usually injected successfully but sometimes it crashes when reaching CreateRemoteThread method.

the logs in case of success contains the following:

11/24/2019 12:21:19 : Assembly Class and Method to load:S:\MyLibrary.dll|MyLibrary.InjectedClass|GOBABYGO 11/24/2019 12:21:19 : Got process handle 11/24/2019 12:21:19 : VirtualAllocEx successful 11/24/2019 12:21:19 : WriteProcessMemory successful 11/24/2019 12:21:19 : CreateRemoteThread successful 11/24/2019 12:21:19 : WaitForSingleObject successful 11/24/2019 12:21:19 : Thread finished 11/24/2019 12:21:19 : Library loaded 11/24/2019 12:21:19 : Entered If _routine case 11/24/2019 12:21:19 : VirtualAllocEx successful 11/24/2019 12:21:19 : WriteProcessMemory successful 11/24/2019 12:21:19 : CreateRemoteThread successful 11/24/2019 12:21:19 : Thread started 11/24/2019 12:21:19 : acmLocal = S:\MyLibrary.dll|MyLibrary.InjectedClass|GOBABYGO 11/24/2019 12:21:19 : About to load assembly S:\MyLibrary.dll 11/24/2019 12:21:19 : About to load type MyLibrary.InjectedClass 11/24/2019 12:21:19 : Just loaded the type MyLibrary.InjectedClass 11/24/2019 12:21:19 : About to invoke GOBABYGO on type MyLibrary.InjectedClass 11/24/2019 12:21:19 : Return value of GOBABYGO on type MyLibrary.InjectedClass is True 11/24/2019 12:21:19 : WaitForSingleObject successful 11/24/2019 12:21:19 : Thread finished 11/24/2019 12:21:19 : Completed launch function

in case of failure i can see in the log only the following(i marked above the differences in Bold):

11/24/2019 13:15:45 : Assembly Class and Method to load:S:\MyLibrary.dll|MyLibrary.InjectedClass|GOBABYGO 11/24/2019 13:15:45 : Got process handle 11/24/2019 13:15:45 : VirtualAllocEx successful 11/24/2019 13:15:45 : WriteProcessMemory successful 11/24/2019 13:15:45 : CreateRemoteThread successful 11/24/2019 13:15:45 : WaitForSingleObject successful 11/24/2019 13:15:45 : Thread finished 11/24/2019 13:15:45 : Library loaded 11/24/2019 13:15:45 : Entered If _routine case 11/24/2019 13:15:45 : VirtualAllocEx successful 11/24/2019 13:15:45 : WriteProcessMemory successful 11/24/2019 13:15:45 : CreateRemoteThread successful 11/24/2019 13:15:56 : WaitForSingleObject successful 11/24/2019 13:15:56 : Thread finished 11/24/2019 13:15:56 : Completed launch function

i have to mention that i'm experienced C# developer, but knows nothing in C++.. so i'll be glad for any detailed instructions of how to find the accurate cause of the problem.

below is the Injector.cpp code:

            #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;

            #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 + "\\ManagedInjector.log";

                return logPath;
            }

            void Injector::Initialize()
            {
                try
                {
                    File::Delete(GetLogPath());
                }
                catch (const FileNotFoundException^)
                {
                    // ignored
                }
            }

            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)
            {
                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);
                        LogMessage("CreateRemoteThread successful");
                        if (!hThread)
                        { 
                            LogMessage("CreateRemoteThread(): failed");
                            getch();
                            return -1;
                        }

                        ::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)
            {
                try
                {
                    LogMessage("Thread started");

                    //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;
            }

            #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)

Thanks in advance for your assistance, have a wonderful day!


Viewing all articles
Browse latest Browse all 7188

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>