Skip to content

Instantly share code, notes, and snippets.

@toptensoftware
Last active October 11, 2016 05:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save toptensoftware/31e26b7327e461a151c8f359e3bfe210 to your computer and use it in GitHub Desktop.
Save toptensoftware/31e26b7327e461a151c8f359e3bfe210 to your computer and use it in GitHub Desktop.
Fake demonstration of calling Windows API from 16-bit code
public class FakeUserDll : ModuleBase
{
public FakeUserDll()
{
}
// A reference back to the machine
Machine _machine;
// Address of the 16-bit MessageBox thunk
uint _addressMessageBoxThunk;
// Called by module manager when module loaded
public override void Init(Machine machine)
{
// Save the machine reference
_machine = machine;
// Create a thunk in the 16-bit world that will call our C# MessageBox() function
_addressMessageBoxThunk = machine.CreateSystemThunk(MessageBox, 12, false);
}
// The ordinal number of the MessageBox function as exported from the user.dll
const ushort ORD_MESSAGEBOX = 0x0001;
// Called by Module16 when linking
public override uint GetProcAddress(ushort ordinal)
{
// Is caller asking for the MessageBox function?
if (ordinal == ORD_MESSAGEBOX)
return _addressMessageBoxThunk;
// Unknown function
return 0;
}
// Import the real MessageBox function from the real Windows (P/Invoke)
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int MessageBox(IntPtr hWnd, string message, string title, int options);
// Handler for the thunk created in Init.
// ie: when 16-bit code calls the MessageBox thunk, execution will land here
void MessageBox()
{
// Parameters to 16-bit MessageBox are:
// HWND hWnd - 2 byte parent window handle
// LPCSTR pszMessage - 4 byte far string pointer to message
// LPCSTR pszTitle - 4 byte far string pointer to title
// int flags - 2 byte integer flags
// Read parameters from the VM stack
ushort hWnd = _machine.ReadWord(_machine.ss, (ushort)(_machine.ss + 4));
uint pszMessage = _machine.ReadDWord(_machine.ss, (ushort)(_machine.ss + 6));
uint pszTitle = _machine.ReadDWord(_machine.ss, (ushort)(_machine.ss + 10));
ushort flags = _machine.ReadWord(_machine.ss, (ushort)(_machine.ss + 14));
// Only null parent windows are supported atm
if (hWnd != 0)
throw new VirtualException("No window handle mapping yet");
// Read the strings from the VM memory
string strMessage = _machine.ReadString(pszMessage);
string strTitle = _machine.ReadString(pszTitle);
// Call the real deal
int retv = MessageBox(IntPtr.Zero, strMessage, strTitle, (int)flags);
// Setup the return value
_machine.ax = (ushort)(short)retv;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment