AfxCodeHook Example - Remote Procedure Injection

posted 17 Oct 2010, 15:59 by Delphi Basics
{
  Remote Procedure Injection
  by Aphex

  This is a method of executing code in a remote process
  without using a DLL.
}

program RemExec;

uses
  Windows,

//structure to pass data to remote procedure
type
  TRemoteInfo = record
    MessageBox: function(hWnd: HWND; lpText, lpCaption: PChar; uType: UINT): Integer; stdcall;
    GetModuleHandle: function(lpModuleName: PChar): HMODULE; stdcall;
    LoadLibrary: function(lpLibFileName: PChar): HMODULE; stdcall;
    GetProcAddress: function(hModule: HMODULE; lpProcName: LPCSTR): FARPROC; stdcall;
    ExitProcess: procedure(uExitCode: UINT); stdcall;
    User32: pchar;
    MessageBoxA: pchar;
    Text: pchar;
    Title: pchar;
    Button: dword;
  end;

//procedure that runs injected inside another process
procedure RemoteThread(RemoteInfo: pointer); stdcall;
begin
  with TRemoteInfo(RemoteInfo^) do
  begin
    @MessageBox := GetProcAddress(GetModuleHandle(User32), MessageBoxA);
    if @MessageBox = nil then @MessageBox := GetProcAddress(LoadLibrary(User32), MessageBoxA);
    Button := MessageBox(0, Text, Title, MB_YESNO);
  end;
end;

procedure RemoteExecute;
const
  User32: pchar = 'user32';
  MessageBoxA: pchar = 'MessageBoxA';
  Title: pchar = 'afxCodeHook';
  Text: pchar = 'hello from notepad :)';
var
  RemoteInfo: TRemoteInfo;
  Process: dword;
  StartInfo: TStartupInfo;
  ProcInfo: TProcessInformation;
begin
  //create a process for testing
  ZeroMemory(@StartInfo, SizeOf(TStartupInfo));
  StartInfo.cb := SizeOf(TStartupInfo);
  CreateProcess(nil, 'notepad.exe', nil, nil, False, 0, nil, nil, StartInfo, ProcInfo);
  Process := ProcInfo.hProcess;

  //copy our strings into the remote process
  RemoteInfo.User32 := InjectString(Process, User32);
  RemoteInfo.MessageBoxA := InjectString(Process, MessageBoxA);
  RemoteInfo.Text := InjectString(Process, Text);
  RemoteInfo.Title := InjectString(Process, Title);

  //copy our API addresses to pass to the remote process
  @RemoteInfo.GetModuleHandle := GetProcAddress(GetModuleHandle('kernel32'), 'GetModuleHandleA');
  @RemoteInfo.LoadLibrary := GetProcAddress(GetModuleHandle('kernel32'), 'LoadLibraryA');
  @RemoteInfo.GetProcAddress := GetProcAddress(GetModuleHandle('kernel32'), 'GetProcAddress');
  @RemoteInfo.ExitProcess  := GetProcAddress(GetModuleHandle('kernel32'), 'ExitProcess');

  //inject our function and data into the process
  InjectThread(Process, @RemoteThread, @RemoteInfo, SizeOf(TRemoteInfo), True);

  //check results
  if RemoteInfo.Button = 6 then
    MessageBox(0, 'User clicked yes.', 'afxCodeHook', 0)
  else if RemoteInfo.Button = 7 then
    MessageBox(0, 'User clicked no.', 'afxCodeHook', 0);

  //kill notepad
  TerminateProcess(Process, 0);
end;

begin
  RemoteExecute;
end.
Comments