Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Code Injection - A Generic Approach for 32bit and 64bit Versions

0.00/5 (No votes)
7 Mar 2014 1  
Code Injection - A Generic Approach for 32bit and 64bit Versions

Introduction

In my previous article, I released code for injecting into running explorer.exe on 32 bit platform which uses 32 bit instructions as shell code which were injected in the process.

Here, we will see a generic code which does not involve any shell code or assembly instructions that are hard coded in the injector, whereas it transfers this responsibility to compiler to prepare the proper assembly for 32 bit and 64 bit version.

Refer to my previous tip Code Injection.

Code

/*
    Application:    Code injection into a running process.
    Author:            _RT
    Dated:            07-March-2014
*/

#include <windows.h>
#include <fstream>
#include <stdlib.h>

#pragma comment(lib,"advapi32.lib")
#pragma comment(lib,"user32.lib")

typedef BOOL (WINAPI* CreatePrcssParam)(LPCTSTR, LPTSTR, LPSECURITY_ATTRIBUTES, 
    LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPCTSTR, LPVOID, LPVOID);

struct PARAMETERS{
    LPVOID CreateProcessInj;
    char lpApplicationName[50];
    char lpCommandLine[10];
    LPSECURITY_ATTRIBUTES lpProcessAttributes;
    LPSECURITY_ATTRIBUTES lpThreadAttributes;
    BOOL bInheritHandles;
    DWORD dwCreationFlags;
    LPVOID lpEnvironment;
    LPCTSTR lpCurrentDirectory;
    LPVOID lpStartupInfo;
    LPVOID lpProcessInformation;
};

int privileges();
DWORD myFunc(PARAMETERS * myparam);
DWORD Useless();    //used to calculate size of myFunc()

int main()
{
    privileges();

    _STARTUPINFOA si;
    PROCESS_INFORMATION pi;

    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));

    DWORD pid;
    GetWindowThreadProcessId(FindWindow(NULL, L"Start Menu"), &pid);

    HANDLE p;
    p = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
    if (p == NULL)
    {
        printf("ERROR");
        return 1; //error
    }

    char * AppName = "C:\\Windows\\notepad.exe";
    char * CmdLine = "";

  //Writing the structure vital for CreateProcess function
    LPVOID StrtUpInfo = VirtualAllocEx(p, NULL, sizeof(si), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    WriteProcessMemory(p, StrtUpInfo, &si, sizeof(si), NULL);

    LPVOID PrcssInfo = VirtualAllocEx(p, NULL, sizeof(si), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    WriteProcessMemory(p, PrcssInfo, &pi, sizeof(pi), NULL);
  //=========================================================

    PARAMETERS data = {0};
    HMODULE Kernel32 = LoadLibrary(L"Kernel32.dll");
    data.CreateProcessInj = GetProcAddress(Kernel32, "CreateProcessA");
    strcpy_s(data.lpApplicationName,AppName);
    strcpy_s(data.lpCommandLine, CmdLine);
    data.lpProcessAttributes = NULL;
    data.lpThreadAttributes = NULL;
    data.bInheritHandles = FALSE;
    data.dwCreationFlags = NULL;
    data.lpEnvironment = NULL;
    data.lpCurrentDirectory = NULL;
    data.lpStartupInfo = StrtUpInfo;
    data.lpProcessInformation = PrcssInfo;

    DWORD size_myFunc = (PBYTE)Useless - (PBYTE)myFunc;  //this gets myFunc's size

    //Writing the code part of myFunc -- Instructions to be executed
    LPVOID MyFuncAddress = VirtualAllocEx(p, NULL, size_myFunc, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    WriteProcessMemory(p, MyFuncAddress, (void*)myFunc, size_myFunc, NULL);

    //Writing the data part of myFunc -- Parameters of the functios
    LPVOID DataAddress = VirtualAllocEx(p, NULL, sizeof(PARAMETERS), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    WriteProcessMemory(p, DataAddress, &data, sizeof(PARAMETERS), NULL);

    HANDLE thread = CreateRemoteThread(p, NULL, 0, (LPTHREAD_START_ROUTINE)MyFuncAddress, DataAddress, 0, NULL);
    if (thread != 0){
        //injection completed, not we can wait for it to end and free the memory
        WaitForSingleObject(thread, INFINITE);   //this waits until thread thread has finished
        VirtualFree(MyFuncAddress, 0, MEM_RELEASE); //free myFunc memory
        VirtualFree(DataAddress, 0, MEM_RELEASE); //free data memory
        CloseHandle(thread);
        CloseHandle(p);  //don't wait for the thread to finish, just close the handle to the process
    }
    else{
        printf("Error!");
    }
    return EXIT_SUCCESS;
}

static DWORD myFunc(PARAMETERS * myparam){
    
    CreatePrcssParam CreatePrcss = (CreatePrcssParam)myparam->CreateProcessInj;
    BOOL result = CreatePrcss((LPCTSTR)myparam->lpApplicationName, NULL, 
    myparam->lpProcessAttributes, myparam->lpThreadAttributes, 
    myparam->bInheritHandles, myparam->dwCreationFlags, myparam->lpEnvironment, 
    myparam->lpCurrentDirectory, myparam->lpStartupInfo, myparam->lpProcessInformation);
    return 0;
}

static DWORD Useless(){
    return 0;
}

//this function is needed to get some extra privileges so your code will be able to work without conflicts with the system
int privileges(){
    HANDLE Token;
    TOKEN_PRIVILEGES tp;
    if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &Token))
    {
        LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
        tp.PrivilegeCount = 1;
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        if (AdjustTokenPrivileges(Token, 0, &tp, sizeof(tp), NULL, NULL) == 0){
            return 1; //FAIL
        }
        else{
            return 0; //SUCCESS
        }
    }
    return 1;
}

What you have to do is just compile this code in 32 bit mode if you want a 32 bit injector or in 64 bit mode if you need a 64 bit injector.

This code forces the arguments of CreateProcess function to be stack based and these parameters are passed using the lpParameter field of CreateRemoteThread function so there will be no unresolved addresses of parameters when the injection part is ported to a foreign process.

Other information on how to prevent code injection is explained in my previous tip.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here