metasploit-framework/lib/metasm/samples/win32genloader.rb

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"