Click here to Skip to main content
Click here to Skip to main content

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

, 7 Mar 2014
Rate this:
Please Sign up or sign in to vote.
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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Rt_
Engineer
India India
No Biography provided

Comments and Discussions

 
Questioncode injection triggered by explorer Pinmemberjojo_kurniawan12-May-14 14:18 
AnswerRe: code injection triggered by explorer PinprofessionalRt_19-May-14 18:57 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140814.1 | Last Updated 7 Mar 2014
Article Copyright 2014 by Rt_
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid