133 lines
3.6 KiB
Ruby
133 lines
3.6 KiB
Ruby
# This file is part of Metasm, the Ruby assembly manipulation suite
|
|
# Copyright (C) 2006-2009 Yoann GUILLOT
|
|
#
|
|
# Licence is LGPL, see LICENCE in the top-level directory
|
|
|
|
# This samples generates a binary loader that will load and patch a Win32 program in memory
|
|
# The patch data are read from assembly files named 'patch_<hex addr>.asm'
|
|
# The 1st mandatory argument is the name of the target binary to load
|
|
# The 2nd optional argument is the name of the loader to be generated
|
|
|
|
require 'metasm'
|
|
|
|
target = ARGV.shift
|
|
loader = ARGV.shift || "loader.exe"
|
|
|
|
abort "need a target binary name to load&patch" if not target
|
|
|
|
cpu = Metasm::Ia32.new
|
|
|
|
# assemble the patches, to put the binary in the C source
|
|
patches = Dir['patch_*.asm'].map { |f|
|
|
puts " [+] assembling #{f}"
|
|
addr = f[/patch_(.*)\.asm/, 1].to_i(16)
|
|
sc = Metasm::Shellcode.assemble_file(cpu, f)
|
|
sc.base_addr = addr
|
|
raw = sc.encode_string
|
|
[addr, raw]
|
|
}
|
|
|
|
|
|
# the C program skeleton
|
|
c_src = <<EOS
|
|
|
|
void main(void)
|
|
{
|
|
static PROCESS_INFORMATION pi;
|
|
static STARTUPINFO si = { .cb = sizeof(si) };
|
|
int i;
|
|
|
|
CreateProcess(#{target.inspect}, 0, 0, 0, 0, CREATE_SUSPENDED, 0, 0, &si, &pi);
|
|
|
|
#{patches.map { |addr, raw|
|
|
"WriteProcessMemory(pi.hProcess, (void*)#{'0x%X' % addr}, #{raw.inspect}, #{raw.length}, 0);"
|
|
}.join("\n\t")}
|
|
|
|
CloseHandle(pi.hProcess);
|
|
|
|
ResumeThread(pi.hThread);
|
|
CloseHandle(pi.hThread);
|
|
|
|
ExitProcess(0);
|
|
}
|
|
EOS
|
|
|
|
|
|
# the winapi definitions (generated by factorize_headers.rb)
|
|
c_hdr = <<EOS
|
|
#define CREATE_SUSPENDED 0x00000004
|
|
#define CreateProcess CreateProcessA
|
|
|
|
typedef int BOOL;
|
|
typedef unsigned char BYTE;
|
|
typedef char CHAR;
|
|
typedef unsigned long DWORD;
|
|
typedef void *HANDLE;
|
|
typedef const void *LPCVOID;
|
|
typedef void *LPVOID;
|
|
typedef unsigned int UINT;
|
|
typedef unsigned long ULONG_PTR;
|
|
typedef unsigned short WORD;
|
|
|
|
__stdcall BOOL CloseHandle __attribute__((dllimport))(HANDLE hObject);
|
|
__noreturn __stdcall void ExitProcess __attribute__((dllimport))(UINT uExitCode);
|
|
typedef BYTE *LPBYTE;
|
|
typedef const CHAR *LPCSTR;
|
|
typedef CHAR *LPSTR;
|
|
__stdcall DWORD ResumeThread __attribute__((dllimport))(HANDLE hThread);
|
|
typedef ULONG_PTR SIZE_T;
|
|
|
|
struct _PROCESS_INFORMATION {
|
|
HANDLE hProcess;
|
|
HANDLE hThread;
|
|
DWORD dwProcessId;
|
|
DWORD dwThreadId;
|
|
};
|
|
|
|
struct _SECURITY_ATTRIBUTES {
|
|
DWORD nLength;
|
|
LPVOID lpSecurityDescriptor;
|
|
BOOL bInheritHandle;
|
|
};
|
|
|
|
typedef struct _PROCESS_INFORMATION *LPPROCESS_INFORMATION;
|
|
typedef struct _SECURITY_ATTRIBUTES *LPSECURITY_ATTRIBUTES;
|
|
typedef struct _PROCESS_INFORMATION PROCESS_INFORMATION;
|
|
__stdcall BOOL WriteProcessMemory __attribute__((dllimport))(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten);
|
|
|
|
struct _STARTUPINFOA {
|
|
DWORD cb;
|
|
LPSTR lpReserved;
|
|
LPSTR lpDesktop;
|
|
LPSTR lpTitle;
|
|
DWORD dwX;
|
|
DWORD dwY;
|
|
DWORD dwXSize;
|
|
DWORD dwYSize;
|
|
DWORD dwXCountChars;
|
|
DWORD dwYCountChars;
|
|
DWORD dwFillAttribute;
|
|
DWORD dwFlags;
|
|
WORD wShowWindow;
|
|
WORD cbReserved2;
|
|
LPBYTE lpReserved2;
|
|
HANDLE hStdInput;
|
|
HANDLE hStdOutput;
|
|
HANDLE hStdError;
|
|
};
|
|
|
|
typedef struct _STARTUPINFOA *LPSTARTUPINFOA;
|
|
typedef struct _STARTUPINFOA STARTUPINFOA;
|
|
|
|
__stdcall BOOL CreateProcessA __attribute__((dllimport))(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation);
|
|
typedef STARTUPINFOA STARTUPINFO;
|
|
EOS
|
|
|
|
|
|
puts c_src, ''
|
|
|
|
# compile the loader
|
|
Metasm::PE.compile_c(cpu, c_hdr+c_src).encode_file(loader)
|
|
|
|
puts " [+] #{loader} saved"
|