When I designing the Virtual Machine, I strongly felt that the basic instructions could not accomplish the high-level operations. So, I wrote some libraries which called API for programmers.
Following Dennis Ritchie's example, it has become typical to begin learning a new programming language by creating the simple "Hello, World!" program. We aren't going to sidestep this tradition. Let's see a "Hello, World!" in OllyMachine:
// Method 1: lds reg01, "Hello World!" push reg01 msg // Method 2: push "Hello World!" msg // Method 3: invoke msg, "Hello World!"
The invoking method I designed is like x86 machine - use stack to pass parameters. Let's take the "Hello, World!" for example:
lds reg01, "Hello World!" push reg01 msg // another way: push "Hello World!" msg
"msg" is an API to print a string. It has only one parameter, this parameter must be a register, storing string's offset address, or a quote string.
Aha, when invoking APIs, if there're parameters, we must use PUSH instruction to push the parameters from right to left, then calling the API's name. When the API runs over, stack will balance automatically, we needn't deal with it.
So what the hell is "push the parameters from right to left"? Let's make an example:
push 16 push 0xFF PrintNum
This program's result is popping a MessageBox to show the hex 0xFF.
We invoked API: PrintNum, it has two parameters, its prototype is:
PrintNum Value, Base
If we push the parameters from right to left, then the "Base" should be first, later is "Value". We can see, in this example, we're surely push "16"(Base) first, then the "0xFF"(Value), and finally the API's name, it's match case with our invoking method.
From version 0.11, we could use INVOKE macro for API invoking, for example:
push 16 push 0xFF PrintNum invoke PrintNum, 0xFF, 16
Just like the same with MASM32's INVOKE macro, is it more easier to use? ^_^
Sometimes, we need to know what the API returns us, for example:
lds reg01, "Are you sure?" push reg01 msgyn // another way: push "Are you sure?" msgyn // yet another way: invoke msgyn, "Are you sure?"
The API "MsgYN" will show a dialog to let the user choose "Y/N", and we must know what the user chosed to decided what to do next.
In OllyMachine Virtual Machine, all API functions follow this rule:
If the API has return value, it will be stored in register REG00.
In the example above, if user chosed "Y", then REG00 will be 1 (means success), if user chosed "N", then REG00 will be 0 (means fail).
OllyMachine Virtual Machine supports some input & output APIs:
Prototype:
MSG message
Explanation:
MSG pops up a MessageBox to disaplay a message.
Parameters:
message : what we want to display
Return Value:
None
Example:
invoke msg, reg01, "Hello World!"
Prototype:
MSGYN message
Explanation:
MSGYN pops up a MessageBox to display a message, and request user to input Y/N
Parameters:
message : what we want to display
Return Value:
Succeeds: 1 Fails: 0
Example:
invoke msgyn, "Are you sure to continue?" cmp reg00, 1 je Continue halt Continue: // ...
Prototype:
PrintNum Value, Base
Explanation:
PrintNum use Base radix to calculate Value, and display the result in a MessageBox
Parameters:
Value : value to calculate
Base : radix
Return Value:
None
Example:
invoke PrintNum, 0x100, 16
Prototype:
PrintBuf address, len
Explanation:
PrintBuf pops up a MessageBox to display len bytes starting at address.
Parameters:
address : memory address starting at
len : length
Return Value:
None
Example:
invoke PrintBuf, eip, 10
Prototype:
PrintBufToDump address
Explanation:
PrintBufToDump prints the buffer starting at address to dump window.
Parameters:
address : buffer starting at
Return Value:
Succeeds: 1 Fails: 0
Example:
invoke PrintBufToDump, eip
Prototype:
PrintBufToNewDump title, address, len
Explanation:
PrintBufToNewDump firstly creates a new dump window, which has a title, then prints the buffer starting at address, length is len, to the new dump window.
Parameters:
title : title of the new dump window
address : buffer start at
len : length of the buffer
Return Value:
Succeeds: HWND of new dump window Fails: 0
Example:
invoke PrintBufToNewDump, "New Dump Window", eip, 0x100
Prototype:
UpdateDumpBuf hwnd, address, len
Explanation:
Update buffer which starting at address, length is len, to an existing dump window. Usually, the dump window's hwnd is getted from PrintBufToNewDump's return value.
Parameters:
hwnd : handle of dump window
address : buffer start at
len : length of the buffer
Return Value:
Succeeds: 1 Fails: 0
Example:
// Create a new dump window: invoke PrintBufToNewDump, "New Dump Window", eip, 0x100 // Save its hwnd: mov reg01, reg00 //... // Update it: invoke UpdateDumpBuf, reg01, eip, 0x200
Prototype:
InputText title
Explanation:
InputText pop up a dialog to let user input a string. Attention: title's length can't larger than 256 bytes, user's inputed string can't larger than 4096 bytes.
Parameters:
title : the title of the dialog
Return Value:
Succeeds: 1 Fails: 0 (User pressed CANCEL button, or user's inputed string larger than 4096 bytes.) If succeed, user's inputed string could be access by FreeBufferReg, the size of the string is stored in FreeBufferSizeReg.
Example:
// ask user's name invoke InputText, "Please input your name" // print user's name invoke msg, FreeBufferReg
Prototype:
InputHexLong value, title
Explanation:
InputHexLong pops up a dialog to let user input a hex number, which is initialized to value. Attention: title can't larget than 256 bytes.
Parameters:
value : initialized value
title : title of the dialog
Return Value:
Succeeds: store user's inputed hex number in reg00 Fails: if user pressed CANCEL button, store initialized value to reg00
Example:
invoke InputHexLong, eip, "Please input EIP" invoke PrintNum, reg00, 16
Prototype:
ReadMemLong address, len
Explanation:
ReadMemLong reads len bytes starting at address. If len < 1, it will be set to 1, if len > 4, it will be set to 4.
Parameters:
address : memory address starting at
len : length of data
Return Value:
Succeeds: len bytes read Fails: -1
Example:
invoke ReadMemLong, eip, 4
Prototype:
WriteMemLong address, valua, len
Explanation:
WriteMemLong writes len bytes value to memory address starting at address. If len < 1, it will be set to 1, if len > 4, it will be set to 4.
Parameters:
address : memory address starting at
value : what we want to write in
len : length of data
Return Value:
Succeeds: 1 Fails: 0
Example:
invoke WriteMemLong, eip, 0x9090, 2
Prototype:
WriteMemHexes address, hexes
Explanation:
Write hexes to address.
Parameters:
address : memory address starting at
hexes : data to write
Return Value:
Succeeds: 1 Fails: 0
Example:
invoke WriteMemHexes, eip, "e800000000"
Prototype:
ReadFileIntoMem filename, addrbase, filesize
Explanation:
Read file(filename) into memory, allocated memory for it. The starting address of memory which allocated for file is stored in addrbase, file's size is in filesize. ATTENTION! MUST use VirtualFreeEx to free the memory! Or it will cause memory leak!
Parameters:
filename : [in], filename to read
addrbase : [out], the starting address of memory which allocated for file
filesize : [out], file's size
Return Value:
Succeeds: 1 Fails: 0
Example:
// Read the file into the memory // reg01 = memory starting address // reg02 = filesize invoke ReadFileIntoMem, "test.exe", indexof reg01, indexof reg02 // Print the file contents byte by byte mov reg10, reg01 read_file_contents: invoke ReadMemLong, reg10, 1 invoke PrintNum, reg00, 16 inc reg10 dec reg02 cmp reg02, 0 jne read_file_contents // Remember to free the memory!!! invoke VirtualFreeEx, indexof reg01
Prototype:
DumpMem address, len, filename
Explanation:
Dumps memory of specified size from specified address to specified file
Parameters:
address : memory starting at
len : length
filename : filename
Return Value:
Succeeds: 1 Fails: 0
Example:
// example1: invoke DumpMem, eip, 10, "c:\test.bin" // example2: invoke InputText, "Please input filename" invoke DumpMem, eip, 10, FreeBufferReg
Prototype:
DumpMemAppend address, len, filename
Explanation:
Dumps memory of specified size from specified address to specified file, appending to that file if it exists.
Parameters:
address : memory startint at
len : length
filename : filename
Return Value:
Succeeds: 1 Fails: 0
Example:
// example1: invoke DumpMemAppend, eip, 10, "c:\test.bin" // example2: invoke InputText, "Please input filename" invoke DumpMemAppend, eip, 10, FreeBufferReg
Prototype:
DumpAsPE filename, eip
Explanation:
Dumps the executable to file with specified name.
Parameters:
filename : filename
eip : Entry Point
Return Value:
Succeeds: 1 Fails: 0
Example:
invoke DumpAsPE, "c:\test.exe", eip
Prototype:
FindOpcode address, opcode
Explanation:
Finds opcode starting at address for an instruction that begins with the specified bytes.
Parameters:
address : memory starting at
opcode : what we looking for
Return Value:
Succeeds: address found Fails: -1
Example:
invoke FindOpcode, eip, 0x90
Prototype:
Find address, code
Explanation:
Finds code starting at address for an instruction that begins with the specified bytes. Supports wildcard "??". One "??" for one byte.
Parameters:
address : memory starting at
code : what we looking for
Return Value:
Succeeds: address found Fails: -1
Example:
invoke Find, eip, "e8????????" // find a CALL XXXXXXXX invoke PrintNum, reg00, 16 // find: // CALL XXXXXXXX // PUSH 0 invoke Find, eip, "e8????????6a00" invoke PrintNum, reg00, 16
Prototype:
ReverseFind address, code
Explanation:
Reverse finds code starting at address for an instruction that begins with the specified bytes. Supports wildcard "??". One "??" for one byte.
Parameters:
address : memory starting at
code : what we looking for
Return Value:
Succeeds: address found Fails: -1
Example:
// Reverse find a CALL XXXXXXXX invoke ReverseFind, eip, "e8????????" invoke PrintNum, reg00, 16 // Reverse find: // CALL XXXXXXXX // PUSH 0 invoke ReverseFind, eip, "e8????????6a00" invoke PrintNum, reg00, 16
Prototype:
Search address, code
Explanation:
Searches code starting at address for an instruction that begins with the specified bytes. Supports wildcard "??". One "??" for one byte. The differences between "Search" and "Find" are, "Search" will not search from a starting address of a opcode. For example: 004010DC 55 PUSH EBP 004010DD 8BEC MOV EBP,ESP 004010DF 6A FF PUSH -1 if we use invoke Find, eip, "EC6AFF", then will find nothing, return -1. if we use invoke Search, eip, "EC6AFF", then will return 004010DE.
Parameters:
address : memory starting at
code : what we looking for
Return Value:
Succeeds: address found Fails: -1
Example:
// Search a CALL XXXXXXXX invoke Search, eip, "e8????????" invoke PrintNum, reg00, 16 // Search: // CALL XXXXXXXX // PUSH 0 invoke Search, eip, "e8????????6a00" invoke PrintNum, reg00, 16
Prototype:
ReverseSearch address, code
Explanation:
Searches code starting at address for an instruction that begins with the specified bytes. Supports wildcard "??". One "??" for one byte. The differences between "ReverseSearch" and "ReverseFind" are, "ReverseSearch" will not search from a starting address of a opcode. For example: 004010DC 55 PUSH EBP 004010DD 8BEC MOV EBP,ESP 004010DF 6A FF PUSH -1 if we use invoke ReverseFind, eip, "EC6AFF", then will find nothing, return -1. if we use invoke ReverseSearch, eip, "EC6AFF", then will return 004010DE.
Parameters:
address : memory starting at
code : what we looking for
Return Value:
Succeeds: address found Fails: -1
Example:
// Reverse search a CALL XXXXXXXX invoke ReverseSearch, eip, "e8????????" invoke PrintNum, reg00, 16 // Reverse search: // CALL XXXXXXXX // PUSH 0 invoke ReverseSearch, eip, "e8????????6a00" invoke PrintNum, reg00, 16
Prototype:
GetPrevOpAddr address, N
Explanation:
Calculate address of instruction which is N instructions forward from instruction at specified address.
Parameters:
address : address of current instruction
N : number of instructions to walk back
Return Value:
Succeeds: address of found instruction Fails: -1
Example:
invoke GetPrevOpAddr, eip, 1 invoke PrintNum, reg00, 16 // Let's see what we got!
Prototype:
GetNextOpAddr address, N
Explanation:
Calculate address of assembler instruction which is N instructions (maximally 127) back from instruction at specified address.
Parameters:
address : address of current instruction
N : number of instructions to walk forward
Return Value:
Succeeds: address of found instruction Fails: -1
Example:
invoke GetNextOpAddr, eip, 1 invoke PrintNum, reg00, 16 // Let's see what we got!
Prototype:
GetProcAddress funcname, dllname
Explanation:
Return address of funcname in dllname.
Parameters:
funcname : function name
dllname : dll name
Return Value:
Succeeds: function's address Fails: -1
Example:
invoke GetProcAddress, "MessageBoxA", "user32.dll" invoke PrintNum, reg00, 16 // Let's see what we got!
Prototype:
Fill address, len, value
Explanation:
Fill writes len value bytes to starting of address.
Parameters:
address : memory address starting at
len : length
value : data written into memory, it will only rserved the lowest byte. (for example: 0x12345678 will only writes 0x78)
Return Value:
Succeeds: 1 Fails: 0
Example:
// fill 10 bytes "NOP" to address starting from EIP invoke Fill, eip, 10, 0x90
Prototype:
ReplaceBytes address, find, repl, len
Explanation:
ReplaceBytes "find" starting at address, and replace it with "repl" for len times.
Parameters:
address : memory startint at
find : data for find
repl : replace with
len : replace times
Return Value:
Succeeds: return the "find"'s address. Fails: -1
Example:
invoke ReplaceBytes, eip, 0x90909090, 0x51515151, 1
Prototype:
ReplaceBytesEx address, len, find, repl
Explanation:
Starting from address, replace "find" to "repl", in len bytes. Supports wildcard "??". One "??" for one byte. Attention: 1. The length of "find" and "repl" must be the same. For example, if "find" is "60e8??", it is 3 bytes, then length of "repl" must also be 3 bytes. 2. The "??" in "find" will not be replaced. For example, if "find" is "60e8??", "repl" is "123456", then after replacement, it will be "1234??", the original byte of "??" will be kept.
Parameters:
address : address starting at
len : how many bytes?
find : bytes to be replaced
repl : replacement
Return Value:
Succeeds: 1, have at least one replacement. Fails: 0, no replacement.
Example:
invoke ReplaceBytesEx, eip, 10, "60e8??", "909090"
Prototype:
CopyBytesTo addrsrc, addrdest, len
Explanation:
Copy len bytes from addrsrc to addrdest.
Parameters:
addrsrc : source address
addrdest : destination address
len : length of bytes
Return Value:
Succeeds: 1 Fails: 0
Example:
invoke CopyBytesTo, eip, 0x401000, 10
Prototype:
ASM address, command
Explanation:
Converts command in ASCII form to binary 32-bit code.
Parameters:
address : address of the generated binary in memory
command : pointer to zero-terminated ASCII command
Return Value:
Succeeds: 1 Fails: 0
Example:
invoke asm, eip, "mov eax, edx"
Prototype:
__asm { }
Explanation:
Embedded asm, must invoke like the following type: __asm { mov eax, 1 push 0 call ExitProcess } Attention: 1. We can use "//", ";" for line comment, "/* */" for block comment. 2. It is not allowed to use registers of OllyMachine. 3. Embedded asm will be compiled, if the size of the compiled code greater than 2046 bytes, then we must separate a big __asm{} block into several smaller block. For example: __asm { mov eax, 1 // ... // ... mov ecx, 1 } If the assembler prompt that the size of compiled embedded asm is too big, then we must separate this big block into several smaller blocks: __asm { mov eax, 1 // ... } __asm { // ... mov ecx, 1 } Continue separating... until the assembler does not give you an error prompt any more. Actually I think 2046 bytes is enough for most of the situations, if not, please let me know.
Parameters:
None
Return Value:
None
Example:
__asm { mov eax, 1 push 0 call ExitProcess }
Prototype:
Analyse address
Explanation:
Analyzes executable code of specified module starting at address.
Parameters:
address : starting memory address
Return Value:
Succeeds: 1 Fails: 0
Example:
invoke Analyse, eip
Prototype:
RunToReturn
Explanation:
Executes "Run to return" in OllyDbg
Parameters:
None
Return Value:
None
Example:
RunToReturn
Prototype:
RunToUserCode
Explanation:
Executes "Run to user code" in OllyDbg
Parameters:
None
Return Value:
None
Example:
RunToUserCode
Prototype:
Run
Explanation:
Executes F9 in OllyDbg
Parameters:
None
Return Value:
None
Example:
Run
Prototype:
AnimateInto
Explanation:
Executes "Animate into" in OllyDbg
Parameters:
None
Return Value:
None
Example:
AnimateInto
Prototype:
AnimateOver
Explanation:
Executes "Animate over" in OllyDbg
Parameters:
None
Return Value:
None
Example:
AnimateOver
Prototype:
StepInto
Explanation:
Execute F7 in OllyDbg.
Parameters:
None
Return Value:
Succeeds: 1 Fails: 0
Example:
StepInto
Prototype:
StepIntoS times
Explanation:
Execute F7 times in OllyDbg.
Parameters:
times : times to step
Return Value:
Succeeds: 1 Fails: 0
Example:
invoke StepIntoS, 3
Prototype:
StepOver
Explanation:
Execute F8 in OllyDbg.
Parameters:
None
Return Value:
Succeeds: 1 Fails: 0
Example:
StepOver
Prototype:
StepOverS times
Explanation:
Execute F8 times in OllyDbg.
Parameters:
times : times to step
Return Value:
Succeeds: 1 Fails: 0
Example:
invoke StepOverS, 3
Prototype:
ESTI
Explanation:
Executes SHIFT-F7 in OllyDbg.
Parameters:
None
Return Value:
None
Example:
ESTI
Prototype:
ESTO
Explanation:
Executes SHIFT-F9 in OllyDbg.
Parameters:
None
Return Value:
None
Example:
ESTO
Prototype:
GO address
Explanation:
Executes to specified address (like G in SoftIce)
Parameters:
address : target address
Return Value:
Succeeds: 1 Fails: 0
Example:
invoke go, 0x401005
Tracing API:
Prototype:
TraceInto
Explanation:
Executes "Trace into" in OllyDbg
Parameters:
None
Return Value:
None
Example:
TraceInto
Prototype:
TraceOver
Explanation:
Executes "Trace over" in OllyDbg
Parameters:
None
Return Value:
None
Example:
TraceOver
Prototype:
TraceIntoCond condition
Explanation:
Traces into calls until cond is true
Parameters:
condition : stop condition
Return Value:
None
Example:
// Will stop when eip > 0x40100A invoke TraceIntoCond, "eip > 0x40100A"
Prototype:
TraceOverCond condition
Explanation:
Traces over calls until cond is true.
Parameters:
condition : stop condition
Return Value:
None
Example:
// Will stop when eip > 0x40100A invoke TraceOverCond, "eip > 0x40100A"
Prototype:
BP address
Explanation:
Set unconditional breakpoint at address.
Parameters:
address : memory address
Return Value:
Succeeds: 1 Fails: 0
Example:
invoke BP, 0x401000 invoke BP, eip
Prototype:
BC address
Explanation:
Clear unconditional breakpoint at addrress.
Parameters:
address : memory address
Return Value:
Succeeds: 1 Fails: 0
Example:
invoke BC, 0x401000 invoke BC, eip
Prototype:
BPCND address, condition
Explanation:
Set breakpoint on address addr with condition cond.
Parameters:
address : memory address
condition : condition that in zero-terminated ASCII cmd
Return Value:
Succeeds: 1 Fails: 0
Example:
invoke BPCND, eip, "ecx==FFFFFFFF"
Prototype:
BPL address, expression
Explanation:
Sets logging breakpoint at address addr that logs expression expr.
Parameters:
address : memory address
expression : expression that in zero-terminated ASCII cmd
Return Value:
Succeeds: 1 Fails: 0
Example:
// logs the value of eax everytime when EIP's address is passed invoke BPL, eip, "eax"
Prototype:
BPLCND address, expression, condition
Explanation:
Sets logging breakpoint at address addr that logs expression expr if condition cond is true
Parameters:
address : memory address
expression : expression that in zero-terminated ASCII cmd
condition : condition that in zero-terminated ASCII cmd
Return Value:
Succeeds: 1 Fails: 0
Example:
// logs the value of eax everytime when EIP's address is passed and eax > 1 invoke BPLCND, eip, "eax", "eax > 1"
Prototype:
BPRM address, size
Explanation:
Set memory breakpoint on read. Size is size of memory in bytes.
Parameters:
address : memory address
size : size of memory
Return Value:
Succeeds: 1 Fails: 0
Example:
invoke BPRM, 0x401000, 0xff
Prototype:
BPWM address, size
Explanation:
Set memory breakpoint on write. Size is size of memory in bytes.
Parameters:
address : memory address
size : size of memory
Return Value:
Succeeds: 1 Fails: 0
Example:
invoke BPWM, 0x401000, 0xff
Prototype:
BPMC
Explanation:
Clear memory breakpoint.
Parameters:
None
Return Value:
Succeeds: 1 Fails: 0
Example:
BPMC
Prototype:
BPHWS address, mode
Explanation:
Set hardware breakpoint. Mode can be 1 - "Execute", 2 - "Read", 3 - "Write"
Parameters:
address : breakpoint address
mode : 1 - "Execute", 2 - "Read", 3 - "Write"
Return Value:
Succeeds: 1 Fails: 0
Example:
invoke BPHWS, 0x401000, 1 // mode - "Execute"
Prototype:
BPHWC address
Explanation:
Delete hardware breakpoint at a specified address
Parameters:
address : breakpoint address
Return Value:
Succeeds: 1 Fails: 0
Example:
invoke BPHWC, 0x401000
Prototype:
EOB label
Explanation:
Transfer execution to some label on next breakpoint. Format: EOB LabelName
Parameters:
label : transfer label name
Return Value:
None
Example:
EOB Break // set up jump label invoke bp, 0x40100A // set breakpoint at 0x40100A run // run! will occur breakpoint at 0x40100A halt // ... (some other instructions) Break: // jump to this label when occured breakpoint invoke msg, "Breakpoint occured!"
Prototype:
EOBINT3 label
Explanation:
Transfer execution to some label on next int3 breakpoint. Format: EOBINT3 LabelName
Parameters:
label : transfer label name
Return Value:
None
Example:
EOBINT3 Break // set up jump label run // run! halt // ... (some other instructions) Break: // jump to this label when occured int3 invoke msg, "Breakpoint occured!"
Prototype:
EOBHW label
Explanation:
Transfer execution to some label on next hardware breakpoint. Format: EOBHW LabelName
Parameters:
label : transfer label name
Return Value:
None
Example:
EOBHW Break // set up jump label run // run! halt // ... (some other instructions) Break: // jump to this label when occured int3 invoke msg, "Breakpoint occured!"
Prototype:
EOBMEM label
Explanation:
Transfer execution to some label on next memory breakpoint. Format: EOBMEM LabelName
Parameters:
label : transfer label name
Return Value:
None
Example:
EOBMEM Break // set up jump label run // run! halt // ... (some other instructions) Break: // jump to this label when occured int3 invoke msg, "Breakpoint occured!"
Prototype:
EOE label
Explanation:
Transfer execution to some label on next exception. Format: EOE LabelName
Parameters:
label : transfer label name
Return Value:
None
Example:
EOE exception1 // set up jump label run halt exception1: // if any exceptions occured, jump to here invoke msg, "Exception occured!"
Prototype:
COB
Explanation:
Makes script continue execution after a breakpoint has occured (removes EOB)
Parameters:
None
Return Value:
None
Example:
EOB Break // set up jump label invoke GetNextOpAddr, eip, 1 invoke bp, reg00 // set breakpoint at next instruction run // run! will occur breakpoint at once! invoke msg, "Continue!" // continue execution here because of COB halt // ... (some other instructions) Break: // jump to this label when occured breakpoint invoke msg, "Breakpoint occured!" COB // removes EOB
Prototype:
COE
Explanation:
Makes script continue execution after an exception has occured (removes EOE)
Parameters:
None
Return Value