Link Search Menu Expand Document

On this page

Metasploit::Framework::Compiler::Windows is a wrapper of Metasm specifically for compiling C code for the Windows platform. The purpose of the wrapper is to support default headers, such as stdio.h, stdio.h, String.h, Windows.h, or some other important headers that you might use while writing in C.

EXE example

c_template = %Q|#include <Windows.h>

int main(void) {
  LPCTSTR lpMessage = "Hello World";
  LPCTSTR lpTitle = "Hi";
  MessageBox(NULL, lpMessage, lpTitle, MB_OK);
  return 0;
}|

require 'metasploit/framework/compiler/windows'


## Save as an exe variable
exe = Metasploit::Framework::Compiler::Windows.compile_c(c_template)

## Save the binary as a file
Metasploit::Framework::Compiler::Windows.compile_c_to_file('/tmp/test.exe', c_template)

DLL example

c_template = %Q|#include <Windows.h>

BOOL APIENTRY DllMain __attribute__((export))(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) {
  switch (dwReason) {
    case DLL_PROCESS_ATTACH:
      MessageBox(NULL, "Hello World", "Hello", MB_OK);
      break;
    case DLL_THREAD_ATTACH:
      break;
    case DLL_THREAD_DETACH:
      break;
    case DLL_PROCESS_DETACH:
      break;
  }

  return TRUE;
}

// This will be a function in the export table
int Msg __attribute__((export))(void) {
  MessageBox(NULL, "Hello World", "Hello", MB_OK);
  return 0;
}
|

require 'metasploit/framework/compiler/windows'
dll = Metasploit::Framework::Compiler::Windows.compile_c(c_template, :dll)

To load a DLL, you can use the LoadLibrary API:

#include <Windows.h>
#include <stdio.h>

int main(void) {
  HMODULE hMod = LoadLibrary("hello_world.dll");
  if (hMod) {
    printf("hello_world.dll loaded\n");
  } else {
    printf("Unable to load hello_world.dll\n");
  }
}

Or call the function in export with rundll32:

rundll32 hell_world.dll,Msg

Printf()

Methods like printf() won’t actually print anything, because it’s not connected up to stdout. If you want to use printf() for debugging purposes, consider using OutputDebugString, or MessageBox.

Custom Headers

Currently, the Metasm wrapper does not support custom headers from an arbitrary location. To work around this, you can place your headers in data/headers/windows, and then add that file name in lib/metasploit/framework/compiler/headers/windows.h.

Code Randomization

Metasploit::Framework::Compiler supports obfuscation that randomizes code at the source code level, and then compile. There are two methods we can use:

  • Metasploit::Framework::Compiler::Windows.compile_random_c
  • Metasploit::Framework::Compiler::Windows.compile_random_c_to_file

Metasploit::Framework::Compiler::Windows.compile_random_c_to_file example:

require 'msf/core'
require 'metasploit/framework/compiler/windows'

c_source_code = %Q|
#include <Windows.h>

int main() {
  const char* content = "Hello World";
  const char* title = "Hi";
  MessageBox(0, content, title, MB_OK);
  return 0;
}|

outfile = "/tmp/helloworld.exe"
weight = 70 # This value is used to determine how random the code gets.
Metasploit::Framework::Compiler::Windows.compile_random_c_to_file(outfile, c_source_code, weight: weight)