CreateRemoteThread says file doesn't exist, but it DOES exist

292 views Asked by At

I am trying to inject a .dll into another process's memory, by using Interop.

This is my C# code:

class Program
{
        static void Main(string[] args)
        {
            var result = Inject(Process.GetProcessesByName("notepad")[0].Id);

            Console.WriteLine(result);

            if (result < 0)
                throw new Win32Exception(Marshal.GetLastWin32Error());

            Console.ReadLine();
        }

        [DllImport("Testing.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int Inject(int dwProcessId);
}

The code for the function Inject is this (notice the comment on return -6):

//C++ .dll that does actually exists
const char* DLL_NAME = "C:\\Users\\Bruno\\Source\\Repos\\CourseGuidance\\InteropTesting\Debug\\Loader.dll";

TESTING_API DWORD Inject(DWORD dwProcessId)
{
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);

    if (hProcess == NULL)
        return -1;

    HMODULE hModule = GetModuleHandleW(L"kernel32.dll");

    if (hModule == NULL)
        return -2;

    FARPROC pLoadLibrary = GetProcAddress(hModule, "LoadLibraryA");

    if (pLoadLibrary == NULL)
        return -3;

    LPVOID pMemory = VirtualAllocEx(hProcess, NULL, strlen(DLL_NAME) + 1, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

    if (pMemory == NULL)
        return -4;

    BOOL result = WriteProcessMemory(hProcess, pMemory, DLL_NAME, strlen(DLL_NAME) + 1, NULL);

    if (!result)
        return -5;

    HANDLE hThread = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE) pLoadLibrary, pMemory, 0, NULL);

    if (hThread == NULL)
        return -6;

    WaitForSingleObject(hThread, INFINITE);

    VirtualFreeEx(hProcess, pMemory, strlen(DLL_NAME) + 1, MEM_RELEASE);

    CloseHandle(hThread);

    CloseHandle(hProcess);

    return 0;
}

I think the error I am getting might be misleading, since the file does exist in that folder. I also thought the error could be because of LoadLibraryA, which is for ASCII, even tried using LoadLibraryW, but I still got the same issue.

If someone has an idea of what could be wrong, could you provide me the right direction?

1

There are 1 answers

0
Raymond Chen On

You did not declare Inject as SetLastError=true. Therefore, the value you got from Marshal.GetLastWin32Error is garbage:

Marshal.GetLastWin32Error Method

Returns the error code returned by the last unmanaged function that was called using platform invoke that has the DllImportAttribute.SetLastError flag set.

You can use this method to obtain error codes only if you apply the System.Runtime.InteropServices.DllImportAttribute to the method signature and set the SetLastError field to true. The process for this varies depending upon the source language used: C# and C++ are false by default, but the Declare statement in Visual Basic is true.