1

Hello I'm new to learning process injection, and having some trouble injecting a process with C++. I'm using CreateRemoteThread and WriteProcessMemory method. However I get Access violation executing location xxxx. the program breaks in my injected function with the said error. i checked through the disassembler and see a call that go to an invalid address, but i have no idea what's going on. i'm working with VS2019 on win10 64 bit, but the project build is x86. i've attached the screen shot of disassembler and error box, also below is my code. i will appreciate any assistant and help. thanks.

disassembly screen

disassembly screen_2

stack frame

the error

#include "stdafx.h" 

//Declearations and structure defination
#if !defined INJCODE_H
#define INJCODE_H

int GetWindowTextRemoteA(HANDLE hProcess, HWND hWnd, LPSTR  lpString);
int GetWindowTextRemoteW(HANDLE hProcess, HWND hWnd, LPWSTR lpString);


#ifdef UNICODE
#define GetWindowTextRemote GetWindowTextRemoteW
#else
#define GetWindowTextRemote GetWindowTextRemoteA
#endif // !UNICODE

#endif // !defined(INJCODE_H)


typedef LRESULT(WINAPI* SENDMESSAGE)(HWND, UINT, WPARAM, LPARAM);

typedef struct {
    HWND    hwnd;
    SENDMESSAGE     fnSendMessage;  // pointer to user32!SendMessage

} INJDATA, * PINJDATA;

//---------------------------------------------------------------------
// ThreadFunc
// Notice: - the code being injected;
//it breaks in this function

static DWORD WINAPI ThreadFunc(INJDATA* pData)
{
    int nXferred = 0;   // number of chars retrieved by WM_GETTEXT

    pData->fnSendMessage(pData->hwnd, WM_CLOSE, 0, 0);

    return nXferred;
}

//---------------------------------------------------------------------
//Process injection routine

int GetTextRemote(HANDLE hProcess, HWND hWnd, BYTE* pbString, bool fUnicode)
{
    HINSTANCE   hUser32;
    INJDATA* pDataRemote = 0;   // the address (in the remote process) where INJDATA will be copied to;
    DWORD* pCodeRemote = 0; // the address (in the remote process) where ThreadFunc will be copied to;
    HANDLE hThread = NULL; // the handle to the thread executing the remote copy of ThreadFunc;
    DWORD dwThreadId = 0;

    int nCharsXferred = 0; // number of chars retrieved by WM_GETTEXT in the remote thread;
    DWORD dwNumBytesXferred = 0; // number of bytes written/read to/from the remote process;

    __try {
        hUser32 = GetModuleHandle(__TEXT("user32"));
        if (hUser32 == NULL)
            __leave;

        // Initialize INJDATA and then 
        // copy it to the remote process
        INJDATA DataLocal = {
            hWnd,
            (SENDMESSAGE)GetProcAddress(hUser32, fUnicode ? "SendMessageW" : "SendMessageA")
        };

        if (DataLocal.fnSendMessage == NULL)
            __leave;

        // 1. Allocate memory in the remote process for INJDATA
        // 2. Write a copy of DataLocal to the allocated memory
        pDataRemote = (INJDATA*)VirtualAllocEx(hProcess, 0, sizeof(INJDATA), MEM_COMMIT, PAGE_READWRITE);
        if (pDataRemote == NULL)
            __leave;

        //WriteProcessMemory( hProcess, pDataRemote, &DataLocal, sizeof(INJDATA), &dwNumBytesXferred );
        if (WriteProcessMemory(hProcess, pDataRemote, &DataLocal, sizeof(INJDATA), &dwNumBytesXferred) == NULL) {
            __leave;
        }

        // Calculate the number of bytes that ThreadFunc occupies
        //const int cbCodeSize = ((LPBYTE) AfterThreadFunc - (LPBYTE) ThreadFunc);
        const int cbCodeSize = 0x5d; // derectly used

        pCodeRemote = (PDWORD)VirtualAllocEx(hProcess, 0, cbCodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
        if (pCodeRemote == NULL)
            __leave;

        if (WriteProcessMemory(hProcess, pCodeRemote, &ThreadFunc, cbCodeSize, &dwNumBytesXferred) == NULL) {
            __leave;
        }

        // Start execution of remote ThreadFunc
        hThread = CreateRemoteThread(hProcess, NULL, 0,
            (LPTHREAD_START_ROUTINE)pCodeRemote,
            pDataRemote, 0, &dwThreadId);
        if (hThread == NULL)
            __leave;

        WaitForSingleObject(hThread, INFINITE);
    }
    __finally {
        if (pDataRemote != 0)
            VirtualFreeEx(hProcess, pDataRemote, 0, MEM_RELEASE);

        if (pCodeRemote != 0)
            VirtualFreeEx(hProcess, pCodeRemote, 0, MEM_RELEASE);

        if (hThread != NULL) {
            GetExitCodeThread(hThread, (PDWORD)&nCharsXferred);
            CloseHandle(hThread);
        }
    }

    return nCharsXferred;
}

//---------------------------------------------------------------------
//winProc to create win32 process

#define ID_TIMER 1

int GetWindowTextRemoteA(HANDLE hProcess, HWND hWnd, LPSTR  lpString)
{
    return GetTextRemote(hProcess, hWnd, (BYTE*)lpString, false);
}

int GetWindowTextRemoteW(HANDLE hProcess, HWND hWnd, LPWSTR lpString)
{
    return GetTextRemote(hProcess, hWnd, (BYTE*)lpString, true);
}

TCHAR szAppName[] = TEXT("MenuDemo");

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static int idColor[5] = { WHITE_BRUSH, LTGRAY_BRUSH, GRAY_BRUSH, DKGRAY_BRUSH, BLACK_BRUSH };
    static int iSelection = IDM_BKGND_WHITE;
    HMENU hMenu;

    switch (message)
    {
    case WM_COMMAND:
        hMenu = GetMenu(hwnd);

        switch (LOWORD(wParam))
        {
        case IDM_FILE_NEW:

            _TCHAR ch[128]; 
            DWORD PID, TID;

            TID = ::GetWindowThreadProcessId(hwnd, &PID);
            if (PID) {
                MessageBeep(MB_OK);
                HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
                GetWindowTextRemote(hProcess, hwnd, ch);
            }
        case IDM_FILE_OPEN:
        case IDM_FILE_SAVE:
        case IDM_FILE_SAVE_AS:
            MessageBeep(0);
            return 0;

        case IDM_APP_EXIT:
            SendMessage(hwnd, WM_CLOSE, 0, 0);
            return 0;

        case IDM_EDIT_UNDO:
        case IDM_EDIT_CUT:
        case IDM_EDIT_COPY:
        case IDM_EDIT_PASTE:
        case IDM_EDIT_CLEAR:
            MessageBeep(0);
            return 0;

        case IDM_BKGND_WHITE: 
        case IDM_BKGND_LTGRAY: 
        case IDM_BKGND_GRAY: 
        case IDM_BKGND_DKGRAY:
        case IDM_BKGND_BLACK: 

            CheckMenuItem(hMenu, iSelection, MF_UNCHECKED);
            iSelection = LOWORD(wParam);

            CheckMenuItem(hMenu, iSelection, MF_CHECKED);

            SetClassLong(hwnd, GCL_HBRBACKGROUND, (LONG)GetStockObject
            (idColor[LOWORD(wParam) - IDM_BKGND_WHITE]));

            InvalidateRect(hwnd, NULL, TRUE);
            return 0;

        case IDM_TIMER_START:
            if (SetTimer(hwnd, ID_TIMER, 1000, NULL))
            {
                EnableMenuItem(hMenu, IDM_TIMER_START, MF_GRAYED);
                EnableMenuItem(hMenu, IDM_TIMER_STOP, MF_ENABLED);
            }
            return 0;

        case IDM_TIMER_STOP:
            KillTimer(hwnd, ID_TIMER);
            EnableMenuItem(hMenu, IDM_TIMER_START, MF_ENABLED);
            EnableMenuItem(hMenu, IDM_TIMER_STOP, MF_GRAYED);
            return 0;

        case IDM_APP_HELP:
            MessageBox(hwnd, TEXT("Help not yet implemented!"), szAppName, MB_ICONEXCLAMATION | MB_OK);
            return 0;

        case IDM_APP_ABOUT:
            MessageBox(hwnd, TEXT("Menu Demonstration Program\n") TEXT("(c) Charles Petzold, 1998"),
                szAppName, MB_ICONINFORMATION | MB_OK);
            return 0;
        }
        break;

    case WM_TIMER:
        MessageBeep(0);
        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

//---------------------------------------------------------------------
//main window procedure

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
    HWND hwnd;
    MSG msg;
    WNDCLASS wndclass;

    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = szAppName;
    wndclass.lpszClassName = szAppName;

    if (!RegisterClass(&wndclass))
    {
        MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
        return 0;
    }

    hwnd = CreateWindow(szAppName,                          
        TEXT("Menu Demonstration"),                         
        WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,              
        CW_USEDEFAULT,                                      
        CW_USEDEFAULT,                                                          
        CW_USEDEFAULT,                                      
        CW_USEDEFAULT,                                      
        NULL,                                               
        NULL,                                               
        hInstance,                                          
        NULL);                                              

    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
Puttin
  • 7
  • 3
  • Please trim your code to make it easier to find your problem. Follow these guidelines to create a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – Community May 13 '22 at 23:15
  • 3
    You can't blindly memcpy code. The function is calling out to other helper functions, and you didn't copy those other functions (or fix up the calls to them). If you're going to be doing code injection, you have to be very familiar with assembly language, because you're operating at a very low level. Note also that your function is operating without unwind codes, so if any exception occurs (even ones that are normally harmless), the process will probably crash. – Raymond Chen May 14 '22 at 00:11
  • 2
    This is basically the same issue as [CodeInjection using CreateRemoteThread and WriteProcessMemory](https://stackoverflow.com/questions/31605760/codeinjection-using-createremotethread-and-writeprocessmemory), just with C++ instead of Delphi as the programming language. – Raymond Chen May 14 '22 at 00:15
  • @Raymond thanks for your reply. I have checked but I couldn't figure out which function needed to be copied to the memory for the function call to use as you've pointed out for the memcpy. I will appreciate if you can let me know which function helper needed to be copied to memory. Also, I checked the link you provided in your comment and everything that was mentioned there has been handled in my code. – Puttin May 14 '22 at 12:11
  • I don't know what it is either. You'll have to reverse-engineer it to see what it is and transfer that function, plus all of the other things that function depends on. This is the cost of trying to operate on compiler-generated machine code: You didn't write the compiler, so you don't know what you're operating on. – Raymond Chen May 14 '22 at 13:57

0 Answers0