Lior Levin
Lior Levin

Reputation: 189

Injecting a dll into Windows 10 notepad

I'm trying to inject a dll into Windows 10 notepad. Both the injector and the dll are compiled in x64.

I'm using LoadLibrary to inject the dll into the notepad process. I am almost certain my method is working, because, well, the results says it does. But it doesn't seem to quiet work.

mydll.h:

#pragma once
#ifdef DLL_EXPORT
#define DECLDIR __declspec(dllexport)
#else
#define DECLDIR __declspec(dllimport)
#endif
extern "C"
{
    DECLDIR void Share();
    void Keep();
}

DllMain.cpp:

#include <Windows.h>

#define DLL_EXPORT
#include "mydll.h"

extern "C"
{
    DECLDIR void Share()
    {
        MessageBox(NULL, "Share function", "Share", MB_OK);
    }
    void Keep()
    {
        MessageBox(NULL, "Keep function", "Keep", MB_OK);
    }
}

BOOLEAN WINAPI DllMain(HINSTANCE hDllHandle, DWORD nReason, LPVOID Reserved)
{
    BOOLEAN bSuccess = TRUE;

    //  Perform global initialization.
    switch (nReason)
    {
    case DLL_PROCESS_ATTACH:
        DisableThreadLibraryCalls(hDllHandle);
        Share();
        Keep();
        break;
    case DLL_THREAD_ATTACH: break;
    case DLL_THREAD_DETACH: break;
    case DLL_PROCESS_DETACH: break;
    }

    return bSuccess;

}

Injector.h

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

class Injector
{
public:
    static bool inject(const char* targetProcName, const char* dllName);

private:
    static DWORD getTargetProcessID(const char* targetProcName);

};

Injector.cpp

#include "Injector.h"

/*
Function to inject a dll into a running process.
Input:
    targetProcName - The exe file name of the running process.
    dllName - The path to the dll.
Output: TRUE if success, FALSE if failed.
*/
bool Injector::inject(const char* targetProcName, const char* dllName)
{
    try
    {
        // Get the process id of the target process.
        DWORD targetProcID = getTargetProcessID(targetProcName);
        if (!targetProcID) {
            throw "Target process Was not found";
        }

        // Get a static address of the LoadLibrary function as a thread-start-routine function.
        LPTHREAD_START_ROUTINE funcLoadLibrary = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "LoadLibraryA");
        if (!funcLoadLibrary) {
            throw "Failed to retrieve a static function pointer to `LoadLbraryA`";
        }

        // Open the target process.
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, targetProcID);
        if (hProcess == INVALID_HANDLE_VALUE) {
            throw "Failed to open target process";
        }

        // Virtually allocate memory for the path of the dll in the target process.
        LPVOID pDllPathAddr = VirtualAllocEx(hProcess, 0, sizeof(dllName) + 1, MEM_COMMIT, PAGE_READWRITE);
        if (!pDllPathAddr) {
            throw "Failed to allocate memory in the target process";
        }

        // Write the dll path to the target process using WPM.
        WriteProcessMemory(hProcess, pDllPathAddr, (LPVOID)dllName, sizeof(dllName) + 1, NULL);

        // Create a remote thread in the target process with LoadLibrary to load our dll into the target process.
        HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL, NULL, funcLoadLibrary, pDllPathAddr, NULL, NULL);
        if (!hRemoteThread || hRemoteThread == INVALID_HANDLE_VALUE) {
            throw "Failed to load dll into target process";
        }

        // Wait until the remote thread is done loading the dll.
        WaitForSingleObject(hRemoteThread, INFINITE);
    }
    catch (const char* err) {
        std::cout << "An erro occurred: " << err << std::endl;
        return false;
    }

    return true;
}

/*
Function to retrieve the ID of a running process.
Input:
    targetProcName - The exe file name of the target process.
Output: The process's ID.
*/
DWORD Injector::getTargetProcessID(const char* targetProcName)
{
    // PROCESSENTRY32 is used to open and get information about a running process..
    PROCESSENTRY32 entry;
    entry.dwSize = sizeof(PROCESSENTRY32);

    // We use a th32snapprocess to iterate through all running processes.
    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);

    // Success check oon the snapshot tool.
    if (!hSnap) {
        throw "Snapshot tool failed to open";
    }

    // If a first process exist (there are running processes), iterate through
    // all running processes.
    DWORD ProcID = NULL;
    if (Process32First(hSnap, &entry)) {
        do 
        {
            // If the current process entry is the target process, store its ID.
            if (!strcmp(entry.szExeFile, targetProcName))
            {
                ProcID = entry.th32ProcessID;
            }
        }
        while (Process32Next(hSnap, &entry) && !ProcID);        // Move on to the next running process.
    }
    else {
        // If there was no first process, notify the user.
        throw "No running processes found";
    }

    return ProcID;
}

main.cpp

#include "Injector.h"

#define TARGET_PROC "notepad.exe"
#define DLL_NAME "../Debug/mydll.dll"

/*
Program to inject a dll into the notepad.exe process.
*/
int main()
{
    char fullname[MAX_PATH] = { 0 };
    GetFullPathName(DLL_NAME, MAX_PATH, fullname, NULL);
    bool success = Injector::inject(TARGET_PROC, fullname);

    std::cout << "Did the injecition succeded? " << success << std::endl;

    return 0;
}

The results says that the injection was a success, but I don't get the message box that I should be getting from the notepad process.

Upvotes: 2

Views: 3575

Answers (1)

GuidedHacking
GuidedHacking

Reputation: 3923

sizeof() will return the size of the pointer, not the number of characters.

You need to use strlen on the dllName in order to write the correct number of bytes into the target process.

Upvotes: 4

Related Questions