第四章

OllyMachine API

在设计OllyMachine虚拟机时,我感觉到只依靠基本指令是不足以完成一些更高级的操作的,因此,我定义了一系列异常丰富的API供程序员使用,通过它们可以与OllyDbg和用户更好地交互,更有效地实现我们所期望的功能。

4.1  Hello World!

就像所有的程序设计教程一样,我先来给大家示范一段Hello World:

// Method 1:
lds reg01, "Hello World!"
push reg01
msg

// Method 2:
push "Hello World!"
msg

// Method 3:
invoke msg, "Hello World!"

4.2  调用方式

我设计的API调用方式类似于x86机器,即使用堆栈作为传递参数的“中转站”。就拿上面的Hello World为例:

lds reg01, "Hello World!"
push reg01
msg

// another way:
push "Hello World!"
msg

上面这个程序是用来打印经典的“Hello World!”程序的。在这个例子中,msg是一个用来显示字符串的API,它只有一个参数,这个参数必须是一个寄存器,寄存器中储存着字符串的偏移地址;或者是一个由双引号包围起来的字符串。

想必大家已经明白了,调用API时,如果有参数,必须使用push指令把参数按照从右向左的顺序入栈,然后再调用API名字。API运行结束后,堆栈会自动平衡,无需程序员手动调整。

那么什么叫做“从右向左的顺序入栈”呢?我们来看一个例子:

push 16
push 0xFF
PrintNum

这个程序的运行结果是弹出一个对话框,显示16进制数0xFF出来。

在这个例子中,我们调用了API函数:PrintNum。

PrintNum有两个参数,它的原型是:

PrintNum 数值,进制

如果是从右向左地把参数入栈的话,那么“进制”就应该是先入栈的,随后就是“数值”。可以看到,在例子中,我们的确是先push了16进去(表示“进制”为16进制),然后才push了0xFF进去(表示“数值”为0xFF),最后调用API的名字,这与我们的API函数调用约定相符合。

4.3  更简便的调用方式

从0.11版开始,可以使用invoke宏来调用API,例如:

push 16
push 0xFF
PrintNum

invoke PrintNum, 0xFF, 16

跟MASM32中的invoke宏一样,是不是更简便了呢?^_^

4.4  返回值

有的时候,我们需要在API执行完毕后提供一些返回值,以便进行下一步的处理。例如:

lds reg01, "Are you sure?"
push reg01
msgyn

// another way:
push "Are you sure?"
msgyn

API函数MsgYN会弹出一个对话框提示用户选择“是/否”,这时我们必须知道用户的选择是什么,才能进行下一步的动作。

在OllyMachine虚拟机中,所有的API函数都遵循这样一个约定:如果该API有返回值,则返回值会储存在reg00中(类似于在Win32系统中,返回值储存在eax中)。因此,程序员在调用完API函数后要注意reg00的值,如果处理不当,可能会造成一些不预期的结果。

在上面的例子中,如果用户输入了“Y”,则reg00的值就会为1(表示成功),如果用户输入了“N”,则reg00的值就会为0(表示失败)。

4.5  基本输入输出API

OllyMachine虚拟机提供了几个输入输出API,以便与用户进行基本的交互:

4.5.1  MSG

函数原型

MSG message

说明

MSG弹出一个对话框,显示字符串message。

参数

返回值


示例

invoke msg, reg01, "Hello World!"

4.5.2  MSGYN

函数原型

MSGYN message

说明

MSGYN弹出一个对话框,显示字符串message,并且要求用户输入Y/N继续。

参数

返回值

成功:1
失败:0

示例

invoke msgyn, "Are you sure to continue?"

cmp reg00, 1
je Continue
halt
Continue:
// ...

4.5.3  PrintNum

函数原型

PrintNum Value, Base

说明

PrintNum用Base进制来计算Value的值,并且用一个对话框来显示结果。

参数

返回值


示例

invoke PrintNum, 0x100, 16

4.5.4  PrintBuf

函数原型

PrintBuf address, len

说明

PrintBuf用一个对话框来显示从内存地址address处开始的len个字节。

参数

返回值


示例

invoke PrintBuf, eip, 10

4.5.5  PrintBufToDump

函数原型

PrintBufToDump address

说明

PrintBufToDump把从内存地址address处开始的数据显示到Dump窗口里。

参数

返回值

成功:1
失败:0

示例

invoke PrintBufToDump, eip

4.5.6  PrintBufToNewDump

函数原型

PrintBufToNewDump title, address, len

说明

PrintBufToNewDump首先创建一个新的Dump窗口,窗口名为title,
然后把从内存地址address处开始的长度为len的数据显示到新的Dump窗口里。

参数

返回值

成功:新的Dump窗口的句柄(HWND)
失败:0

示例

invoke PrintBufToNewDump, "New Dump Window", eip, 0x100

4.5.7  UpdateDumpBuf

函数原型

UpdateDumpBuf hwnd, address, len

说明

从address地址开始,取len个字节,然后更新到某个Dump窗口中,该窗口通过hwnd来定位。
一般来说,这个hwnd是由PrintBufToNewDump的返回值来取得的。

参数

返回值

成功:1
失败:0

示例

// 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

4.5.8  InputText

函数原型

InputText title

说明

InputText会弹出一个对话框让用户输入一串字符串,对话框的标题为title中的字符串。
注意:标题的长度不能大于 256 个字节,用户输入的字符串不能大于 4096 个字节。

参数

返回值

成功:1
失败:0(用户按下CANCEL按钮,或者用户输入的字符串大于 4096 个字节)

如果运行成功,用户输入的字符串可以通过FreeBufferReg访问,字符串的长度储存在FreeBufferSizeReg中。

示例

// ask user's name
invoke InputText, "Please input your name"

// print user's name
invoke msg, FreeBufferReg

4.5.9  InputHexLong

函数原型

InputHexLong value, title

说明

InputHexLong会弹出一个对话框让用户输入一个16进制数,对话框的标题为title中的字符串,初始值为value。
注意:标题的长度不能大于 256 个字节。

参数

返回值

把用户输入的数值储存在reg00中。
如果用户按了CANCEL,则reg00的值为value原来的值。

示例

invoke InputHexLong, eip, "Please input EIP"
invoke PrintNum, reg00, 16

4.6  内存操作API

OllyMachine可以很方便地与内存数据打交道:

4.6.1  ReadMemLong

函数原型

ReadMemLong address, len

说明

ReadMemLong读取在address地址处的len个字节数据,并且储存在寄存器reg00中返回。
len 只能在1~4之间,小于1的话会被设置为1,大于4的话会被设置为4。

参数

返回值

成功:读到的数据。
失败:-1

示例

invoke ReadMemLong, eip, 4

4.6.2  WriteMemLong

函数原型

WriteMemLong address, value, len

说明

WriteMemLong把len个字节长的value值写到address地址处。
len 只能在1~4之间,小于1的话会被设置为1,大于4的话会被设置为4。

参数

返回值

成功:1
失败:0

示例

invoke WriteMemLong, eip, 0x9090, 2

4.6.3  WriteMemHexes

函数原型

WriteMemHexes address, hexes

说明

把hexes写到address地址处。

参数

返回值

成功:1
失败:0

示例

invoke WriteMemHexes, eip, "e800000000"

4.6.4  ReadFileIntoMem

函数原型

ReadFileIntoMem filename, addrbase, filesize

说明

把文件filename读入内存中,自动分配一段内存给它。
分配的内存的起始地址在addrbase,文件的大小在filesize。
注意!使用完后一定要用VirtualFreeEx来释放这段内存,否则会造成内存泄漏!!!

参数

返回值

成功:1
失败:0

示例

// 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

4.6.5  DumpMem

函数原型

DumpMem address, len, filename

说明

DumpMem把从address地址处的len个字节dump到filename里面去,如果文件已存在,则覆盖。

参数

返回值

成功:1
失败:0

示例

// example1:
invoke DumpMem, eip, 10, "c:\test.bin"

// example2:
invoke InputText, "Please input filename"
invoke DumpMem, eip, 10, FreeBufferReg

4.6.6  DumpMemAppend

函数原型

DumpMemAppend address, len, filename

说明

DumpMemAppend把从address地址处的len个字节dump到filename里面去,如果文件已存在,则添加数据到文件末尾。

参数

返回值

成功:1
失败:0

示例

// example1:
invoke DumpMemAppend, eip, 10, "c:\test.bin"

// example2:
invoke InputText, "Please input filename"
invoke DumpMemAppend, eip, 10, FreeBufferReg

4.6.7  DumpAsPE

函数原型

DumpAsPE filename, eip

说明

DumpAsPE把内存镜像dump成为一个PE文件,该PE文件的Entry Point为eip。

参数

返回值

成功:1
失败:0

示例

invoke DumpAsPE, "c:\test.exe", eip

4.7  搜索和替换API

4.7.1  FindOpcode

函数原型

FindOpcode address, opcode

说明

FindOpcode从address地址处开始往后搜寻opcode,并返回第一个找到的地址。

参数

返回值

成功:返回找到的地址
失败:-1

示例

invoke FindOpcode, eip, 0x90

4.7.2  Find

函数原型

Find address, code

说明

Find从address地址处开始往后搜寻code,并返回第一个找到的地址。
支持通配符“??”:一个不确定的字节必须由一个“??”来表示。

参数

返回值

成功:返回找到的地址
失败:-1

示例

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

4.7.3  ReverseFind

函数原型

ReverseFind address, code

说明

ReverseFind从address地址处开始往前搜寻code,并返回第一个找到的地址。
支持通配符“??”:一个不确定的字节必须由一个“??”来表示。

参数

返回值

成功:返回找到的地址
失败:-1

示例

// Reverse find some: PUSHAD, CALL XXXXXXXX
invoke ReverseFind, eip, "60e8"
invoke PrintNum, reg00, 16

// Reverse find:
//   CALL XXXXXXXX
//   PUSH 0
invoke ReverseFind, eip, "e8????????6a00"
invoke PrintNum, reg00, 16

4.7.4  Search

函数原型

Search address, code

说明

Search从address地址处开始往后搜寻code,并返回第一个找到的地址。
支持通配符“??”:一个不确定的字节必须由一个“??”来表示。

Search与Find的不同之处在于,Search并不会从一个合法的Opcode的起始地址开始搜寻。
例如:

004010DC 55             PUSH EBP
004010DD 8BEC           MOV EBP,ESP
004010DF 6A FF          PUSH -1

如果用invoke Find, eip, "EC6AFF",那么不会找到,返回-1;
如果用invoke Search, eip, "EC6AFF",那么会返回004010DE。

参数

返回值

成功:返回找到的地址
失败:-1

示例

invoke Search, eip, "e8????????"   // Search a CALL XXXXXXXX
invoke PrintNum, reg00, 16

// Search:
//   CALL XXXXXXXX
//   PUSH 0
invoke Search, eip, "e8????????6a00"
invoke PrintNum, reg00, 16

4.7.5  ReverseSearch

函数原型

ReverseSearch address, code

说明

ReverseSearch从address地址处开始往前搜寻code,并返回第一个找到的地址。
支持通配符“??”:一个不确定的字节必须由一个“??”来表示。

ReverseSearch与ReverseFind的不同之处在于:
ReverseSearch并不会从一个合法的Opcode的起始地址开始搜寻。

例如:

004010DC 55             PUSH EBP
004010DD 8BEC           MOV EBP,ESP
004010DF 6A FF          PUSH -1

如果用invoke ReverseFind, eip, "EC6AFF",那么不会找到,返回-1;
如果用invoke ReverseSearch, eip, "EC6AFF",那么会返回004010DE。

参数

返回值

成功:返回找到的地址
失败:-1

示例

// 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

4.7.6  GetPrevOpAddr

函数原型

GetPrevOpAddr address, N

说明

GetPrevOpAddr返回从address地址开始的往前第N条指令的地址。

参数

返回值

成功:返回找到的地址
失败:-1

示例

invoke GetPrevOpAddr, eip, 1
invoke PrintNum, reg00, 16  // Let's see what we got!

4.7.7  GetNextOpAddr

函数原型

GetNextOpAddr address, N

说明

GetNextOpAddr返回从address地址开始的往后第N条指令的地址。

参数

返回值

成功:返回找到的地址
失败:-1

示例

invoke GetNextOpAddr, eip, 1
invoke PrintNum, reg00, 16  // Let's see what we got!

4.7.8  GetProcAddress

函数原型

GetProcAddress funcname, dllname

说明

GetProcAddress返回在dllname中的funcname的地址。

参数

返回值

成功:返回找到的地址
失败:-1

示例

invoke GetProcAddress, "MessageBoxA", "user32.dll"
invoke PrintNum, reg00, 16  // Let's see what we got!

4.7.9  Fill

函数原型

Fill address, len, value

说明

Fill把len个字节长的value值写到address地址处。

参数

返回值

成功:1
失败:0

示例

// fill 10 bytes "NOP" to address starting from EIP
invoke Fill, eip, 10, 0x90

4.7.10  ReplaceBytes

函数原型

ReplaceBytes address, find, repl, len

说明

ReplaceBytes从address地址处开始往后搜寻字节码find,并且用repl来替换find,一共替换len次。

参数

返回值

成功:返回找到的地址
失败:-1

示例

invoke ReplaceBytes, eip, 0x90909090, 0x51515151, 1

4.7.11  ReplaceBytesEx

函数原型

ReplaceBytesEx address, len, find, repl

说明

从address地址开始,在len个字节范围内,把find替换成repl。
支持通配符“??”:一个不确定的字节必须由一个“??”来表示。
注意:
1、find和repl的长度必须相同。例如假如find为"60e8??",表示3个字,那么repl也必须是3个字节。
2、在find里面的"??"不会被替换。例如假如find为"60e8??",repl为"123456"
   那么替换后将会是"1234??",原来的"??"所表示的那个字节不变。

参数

返回值

成功:1,表示至少有一个替换。
失败:0,表示没有替换。

示例

invoke ReplaceBytesEx, eip, 10, "60e8??", "909090"

4.7.12  CopyBytesTo

函数原型

CopyBytesTo addrsrc, addrdest, len

说明

把addrsrc地址处开始的len个字节拷贝到addrdest处。

参数

返回值

成功:1
失败:0

示例

invoke CopyBytesTo, eip, 0x401000, 10

4.8  汇编API

汇编:

4.8.1  ASM

函数原型

ASM address, command

说明

ASM函数对字符串command进行汇编,然后写进address地址处。

参数

返回值

成功:1
失败:0

示例

invoke asm, eip, "mov eax, edx"

4.8.2  __asm

函数原型

__asm { }

说明

内嵌汇编功能,必须使用以下的形式调用:
__asm
{
mov eax, 1
push 0
call ExitProcess
}

注意事项:
1、可以使用“//”、“;”作为行注释,“/* */”作为块注释。
2、不允许使用OllyMachine的寄存器。
3、内嵌汇编也是要经过编译的,如果编译后的大小超过2046个字节,则必须把一个大的__asm{}块分开成几个小的块。

例如:

__asm
{
mov eax, 1
// ...
// ...
mov ecx, 1
}

如果编译器提示内嵌汇编经过编译后的字节数太大的话,则可以把这个大的块分成两个小块:

__asm
{
mov eax, 1
// ...
}
__asm
{
// ...
mov ecx, 1
}

一直这样分解下去,直到编译器不出错误提示为止。
实际上2046个字节对于大多数情况来说应该已经足够了,如果不够的话我可以增加。

参数


返回值


示例

__asm
{
mov eax, 1

push 0
call ExitProcess
}

4.8.3  Analyse

函数原型

Analyse address

说明

Analyse函数对address地址处开始的指令进行分析。

参数

返回值

成功:1
失败:0

示例

invoke Analyse, eip

4.9  运行API

通过以下API,可以做到控制OllyDbg运行的目的:

4.9.1  RunToReturn

函数原型

RunToReturn

说明

RunToReturn会一直运行被调试进程的代码,直到遇到ret指令为止。
运行效果相当于在OllyDbg的主界面按住Ctrl+F9。

参数


返回值


示例

RunToReturn // 一直运行,直到遇到ret指令为止

4.9.2  RunToUserCode

函数原型

RunToUserCode

说明

有时候,跟踪会运行到很深的系统DLL中,执行RunToUserCode能够很快地返出来,
即运行到第一个不是系统DLL的指令。
运行效果相当于在OllyDbg的主界面按Alt+F9。

参数


返回值


示例

RunToUserCode

4.9.3  Run

函数原型

Run

说明

Run会使被调试进程运行起来。
运行效果相当于在OllyDbg的主界面按F9。

参数


返回值


示例

Run

4.9.4  AnimateInto

函数原型

AnimateInto

说明

执行AnimateInto操作。
运行效果相当于在OllyDbg的主界面按Ctrl+F7。

参数


返回值


示例

AnimateInto

4.9.5  AnimateOver

函数原型

AnimateOver

说明

执行AnimateOver操作。
运行效果相当于在OllyDbg的主界面按Ctrl+F8。

参数


返回值


示例

AnimateOver

4.9.6  StepInto

函数原型

StepInto

说明

StepInto会跟踪进当前的call里面去。
运行效果相当于在OllyDbg的主界面按F7。

参数


返回值

成功:1
失败:0

示例

StepInto

4.9.7  StepIntoS

函数原型

StepIntoS times

说明

StepIntoS执行times次StepInto操作。

参数

返回值

成功:1
失败:0

示例

invoke StepIntoS, 3

4.9.8  StepOver

函数原型

StepOver

说明

StepOver会跟踪进当前的call里面去。
运行效果相当于在OllyDbg的主界面按F8。

参数


返回值

成功:1
失败:0

示例

StepOver

4.9.9  StepOverS

函数原型

StepOverS times

说明

StepOverS执行times次StepOver操作。

参数

返回值

成功:1
失败:0

示例

invoke StepOverS, 3

4.9.10  ESTI

函数原型

ESTI

说明

ESTI运行效果相当于在OllyDbg的主界面按Shift+F7。

参数


返回值


示例

ESTI

4.9.11  ESTO

函数原型

ESTO

说明

ESTO运行效果相当于在OllyDbg的主界面按Shift+F9。

参数


返回值


示例

ESTO

4.9.12  GO

函数原型

GO address

说明

GO会执行到address地址处。

参数

返回值

成功:1
失败:0

示例

invoke go, 0x401005

4.10  Trace API

这部分API是跟Trace相关的。

4.10.1  TraceInto

函数原型

TraceInto

说明

TraceInto函数执行OllyDbg的“Trace Into”功能。

参数


返回值


示例

TraceInto

4.10.2  TraceOver

函数原型

TraceOver

说明

TraceOver函数执行OllyDbg的“Trace Over”功能。

参数


返回值


示例

TraceOver

4.10.3  TraceIntoCond

函数原型

TraceIntoCond condition

说明

TraceIntoCond函数会Trace Into到call里面,直到condition条件为真才结束。

参数

返回值


示例

// Will stop when eip > 0x40100A
invoke TraceIntoCond, "eip > 0x40100A"

4.10.4  TraceOverCond

函数原型

TraceOverCond condition

说明

TraceOverCond函数会Trace Over所有的calls,直到condition条件为真才结束。

参数

返回值


示例

// Will stop when eip > 0x40100A
invoke TraceOverCond, "eip > 0x40100A"

4.11  断点API

这部分API是跟断点相关的。

4.11.1  BP

函数原型

BP address

说明

BP函数在address地址处下无条件(unconditional)断点。

参数

返回值

成功:1
失败:0

示例

invoke BP, 0x401000
invoke BP, eip

4.11.2  BC

函数原型

BC address

说明

BC函数清除在address地址处的无条件(unconditional)断点。

参数

返回值

成功:1
失败:0

示例

invoke BC, 0x401000
invoke BC, eip

4.11.3  BPCND

函数原型

BPCND address, condition

说明

BPCND函数在address地址处下条件(conditional)断点,条件为condition

参数

返回值

成功:1
失败:0

示例

invoke BPCND, eip, "ecx==FFFFFFFF"

4.11.4  BPL

函数原型

BPL address, expression

说明

BPL函数在address地址处下无条件(unconditional)断点,然后把表达式expression显示在log窗口处。

参数

返回值

成功:1
失败:0

示例

// logs the value of eax everytime when EIP's address is passed
invoke BPL, eip, "eax"

4.11.5  BPLCND

函数原型

BPLCND address, expression, condition

说明

BPLCND函数在address地址处下条件(conditional)断点,然后把表达式expression显示在log窗口处。

参数

返回值

成功:1
失败:0

示例

// logs the value of eax everytime when EIP's address is passed and eax > 1
invoke BPLCND, eip, "eax", "eax > 1"

4.11.6  BPRM

函数原型

BPRM address, size

说明

下内存“读”断点于address地址处,长度为size个字节。

参数

返回值

成功:1
失败:0

示例

invoke BPRM, 0x401000, 0xff

4.11.7  BPWM

函数原型

BPWM address, size

说明

下内存“写”断点于address地址处,长度为size个字节。

参数

返回值

成功:1
失败:0

示例

invoke BPWM, 0x401000, 0xff

4.11.8  BPMC

函数原型

BPMC

说明

清除内存断点。

参数


返回值

成功:1
失败:0

示例

BPMC

4.11.9  BPHWS

函数原型

BPHWS address, mode

说明

下硬件断点于address地址处,模式可以为“Execute执行”、“Read读”、“Write写”,
由mode来决定:1为“Execute执行”、2为“Read读”、3为“Write写”,其他则会使API返回失败。

参数

返回值

成功:1
失败:0

示例

invoke BPHWS, 0x401000, 1 // mode - "Execute"

4.11.10  BPHWC

函数原型

BPHWC address

说明

清除address地址处的硬件断点。

参数

返回值

成功:1
失败:0

示例

invoke BPHWC, 0x401000

4.11.11  EOB

函数原型

EOB label

说明

EOB的作用是:当OllyMachine运行时遇到了断点,就会跳转到label处继续执行。

EOB是一个比较特殊的API,注意,调用它的时候不是用push的方式来传递参数,
而是直接跟label,例如:EOB LabelName

参数

返回值


示例

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!"

4.11.12  EOBINT3

函数原型

EOBINT3 label

说明

EOBINT3的作用是:当OllyMachine运行时遇到了int3断点,就会跳转到label处继续执行。

EOBINT3是一个比较特殊的API,注意,调用它的时候不是用push的方式来传递参数,
而是直接跟label,例如:EOBINT3 LabelName

参数

返回值


示例

EOBINT3 Break   // set up jump label

run             // run!

halt

// ... (some other instructions)

Break:          // jump to this label when occured int3
invoke msg, "Breakpoint occured!"

4.11.13  EOBHW

函数原型

EOBHW label

说明

EOBHW的作用是:当OllyMachine运行时遇到了Hardware断点,就会跳转到label处继续执行。

EOBHW是一个比较特殊的API,注意,调用它的时候不是用push的方式来传递参数,
而是直接跟label,例如:EOBHW LabelName

参数

返回值


示例

EOBHW Break     // set up jump label

run             // run!

halt

// ... (some other instructions)

Break:          // jump to this label when occured int3
invoke msg, "Breakpoint occured!"

4.11.14  EOBMEM

函数原型

EOBMEM label

说明

EOBMEM的作用是:当OllyMachine运行时遇到了memory断点,就会跳转到label处继续执行。

EOBMEM是一个比较特殊的API,注意,调用它的时候不是用push的方式来传递参数,
而是直接跟label,例如:EOBMEM LabelName

参数

返回值


示例

EOBMEM Break    // set up jump label

run             // run!

halt

// ... (some other instructions)

Break:          // jump to this label when occured int3
invoke msg, "Breakpoint occured!"

4.11.15  EOE

函数原型

EOE label

说明

EOE的作用是:当OllyMachine运行时遇到了异常(exception),就会跳转到label处继续执行。

EOE是一个比较特殊的API,注意,调用它的时候不是用push的方式来传递参数,
而是直接跟label,例如:EOE LabelName

参数

返回值


示例

EOE exception1      // set up jump label

run

halt

exception1:         // if any exceptions occured, jump to here
invoke msg, "Exception occured!"

4.11.16  COB

函数原型

COB

说明

COB会让脚本在遇到一个断点并处理了该断点后继续回到原位置运行。(清除EOB)

参数


返回值


示例

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

4.11.17  COE

函数原型

COE

说明

COE会让脚本在遇到一个异常并处理了该异常后继续回到原位置运行。(清除EOE)

参数


返回值


示例

EOE exception1      // set up jump label

run

invoke msg, "Continue!" // continue execution here because of COE

halt

exception1:         // if any exceptions occured, jump to here
invoke msg, "Exception occured!"

COE                 // removes EOE

4.12  模块API

这些API与模块(module)有关。

4.12.1  GMI

函数原型

GMI address, info

说明

GMI返回一个位于address地址处的模块(module)的信息。

参数

返回值

成功:相应的地址
失败:-1

示例

invoke GMI, eip, "ENTRYPOINT"
invoke PrintNum, reg00, 16

4.13  注释与标号API

这些API用来进行注释和标号操作:

4.13.1  Comment

函数原型

Comment address, text

说明

Comment函数在address地址处写入注释text。

参数

返回值

成功:1
失败:0

示例

invoke Comment, eip, "This is a comment!"

4.13.2  SetLbl

函数原型

SetLbl address, LabelName

说明

SetLbl函数在address地址处添加一个LabelName。

参数

返回值

成功:1
失败:0

示例

invoke SetLbl, eip, "This is a new label!"

4.14  日志API

这些API用来进行日志操作:

4.14.1  LogText

函数原型

LogText text

说明

LogText函数把text写到Log窗口。

参数

返回值

成功:1
失败:0

示例

invoke LogText, "This is a log!"

4.14.2  LogLong

函数原型

LogLong value

说明

LogLong函数把long类型的value数值写到Log窗口。
写入的数值以“LOG VALUE: 0xXXXXXXXX”的形式表示。

参数

返回值

成功:1
失败:0

示例

invoke LogLong, eip
invoke LogLong, 0x12345678

4.15  反反调试API

反反调试API,用来对抗反调试技巧:

4.15.1  HideOD

函数原型

HideOD

说明

HideOD改写 fs:[30]+2 处的值为0,使被调试进程无法得知OllyDbg的存在。
Windows XP Sp2 下同样有效。

参数


返回值

成功:1
失败:0

示例

HideOD

4.15.2  UnHideOD

函数原型

UnHideOD

说明

UnHideOD取消HideOD的作用。

参数


返回值

成功:1
失败:0

示例

UnHideOD

4.16  缓冲区API

字符串、缓冲区的API。

4.16.1  malloc

函数原型

malloc size, indexof reg

说明

malloc分配一块size大小的内存空间给reg。
注意:1、必须使用indexof作为reg的前缀,以便让汇编器知道reg的序号。2、reg不得为reg00!

参数

返回值

成功:1
失败:0

示例

// alloc 100 bytes memory to reg01
invoke malloc, 100, indexof reg01

4.16.2  free

函数原型

free indexof reg

说明

free用来释放通过malloc得到的内存空间。
注意:1、必须使用indexof作为reg的前缀,以便让汇编器知道reg的序号。2、reg不得为reg00!

参数

返回值

成功:1
失败:0

示例

// alloc 100 bytes memory to reg01
invoke malloc, 100, indexof reg01

// ...

// now free the space:
invoke free, indexof reg01

4.16.3  VirtualAllocEx

函数原型

VirtualAllocEx size, indexof reg

说明

分配一块size大小的内存空间给reg,该内存的属性为PAGE_EXECUTE_READWRITE。
注意:1、必须使用indexof作为reg的前缀,以便让汇编器知道reg的序号。2、reg不得为reg00!

参数

返回值

成功:1
失败:0

示例

// alloc 100 bytes memory to reg01
invoke VirtualAllocEx, 100, indexof reg01

4.16.4  VirtualFreeEx

函数原型

VirtualFreeEx indexof reg

说明

释放通过VirtualAllocEx得到的内存空间。
注意:1、必须使用indexof作为reg的前缀,以便让汇编器知道reg的序号。2、reg不得为reg00!

参数

返回值

成功:1
失败:0

示例

// alloc 100 bytes memory to reg01
invoke VirtualAllocEx, 100, indexof reg01

// ...

// now free the space:
invoke VirtualFreeEx, indexof reg01

4.16.5  strcpy

函数原型

strcpy indexof reg, text

说明

strcpy拷贝text到reg所在的内存空间。
注意:1、必须使用indexof作为reg的前缀,以便让汇编器知道reg的序号。2、reg不得为reg00!

参数

返回值

成功:1
失败:0

示例

// alloc 100 bytes memory to reg01
invoke malloc, 100, indexof reg01

invoke strcpy, indexof reg01, "test"

// now free the space:
invoke free, indexof reg01

4.16.6  strcat

函数原型

strcat indexof reg, text

说明

strcat把text添加到reg所在的内存空间的末尾。
注意:1、必须使用indexof作为reg的前缀,以便让汇编器知道reg的序号。2、reg不得为reg00!

参数

返回值

成功:1
失败:0

示例

// alloc 100 bytes memory to reg01
invoke malloc, 100, indexof reg01

invoke strcpy, indexof reg01, "test"
invoke strcat, indexof reg01, "1234"

// now free the space:
invoke free, indexof reg01

4.16.7  strlen

函数原型

strlen mode, indexof reg / text

说明

strlen计算reg所在的内存空间的字符串的长度,或者是text的长度。
注意:1、必须使用indexof作为reg的前缀,以便让汇编器知道reg的序号。2、reg不得为reg00!

参数

返回值

成功:字符串的长度
失败:-1

示例

// alloc 100 bytes memory to reg01
invoke malloc, 100, indexof reg01

invoke strcpy, indexof reg01, "test"
invoke strlen, 0, indexof reg01     // reg mode
invoke PrintNum, reg00, 10

invoke strlen, 1, "1234567890"      // text mode
invoke PrintNum, reg00, 10

// now free the space:
invoke free, indexof reg01

4.16.8  ltoa

函数原型

ltoa value, indexof reg, radix

说明

ltoa把数值value用radix进制转换到reg所在的内存空间去。
注意:1、必须使用indexof作为reg的前缀,以便让汇编器知道reg的序号。2、reg不得为reg00!

参数

返回值

成功:1
失败:0

示例

// alloc 100 bytes memory to reg01
invoke malloc, 100, indexof reg01

// converts decimal value 874 to string, store in reg01
invoke ltoa, 874, indexof reg01, 10

// what we got?
invoke msg, reg01

// now free the space:
invoke free, indexof reg01

4.16.9  memcpy

函数原型

memcpy indexof reg, buffer, len

说明

memcpy拷贝buffer到reg所在的内存空间,长度为len。
注意:1、必须使用indexof作为reg的前缀,以便让汇编器知道reg的序号。2、reg不得为reg00!

参数

返回值

成功:1
失败:0

示例

// alloc 100 bytes memory to reg01
invoke malloc, 100, indexof reg01

invoke memcpy, indexof reg01, "test", 4

// now free the space:
invoke free, indexof reg01

4.17  辅助调试API

4.17.1  FindProcBegin

函数原型

FindProcBegin address

说明

FindProcBegin返回内存单元address所在的函数体的起始地址。
注意,如果模块没有被分析过(analyze),或者address不在某个函数体内,则会失败。

参数

返回值

成功:函数体的起始地址
失败:0

示例

invoke FindProcBegin, eip

4.17.2  FindProcEnd

函数原型

FindProcEnd address

说明

FindProcEnd返回内存单元address所在的函数体的终止地址。
注意,如果模块没有被分析过(analyze),或者address不在某个函数体内,则会失败。

参数

返回值

成功:函数体的终止地址
失败:0

示例

invoke FindProcEnd, eip

4.17.3  FindPrevProc

函数原型

FindPrevProc address

说明

FindPrevProc返回内存单元address所在的函数体的上一个函数的起始地址。
注意,如果模块没有被分析过(analyze),或者address不在某个函数体内,则会失败。

参数

返回值

成功:函数体的起始地址
失败:0

示例

invoke FindPrevProc, eip

4.17.4  FindNextProc

函数原型

FindNextProc address

说明

FindNextProc返回内存单元address所在的函数体的下一个函数的起始地址。
注意,如果模块没有被分析过(analyze),或者address不在某个函数体内,则会失败。

参数

返回值

成功:函数体的起始地址
失败:0

示例

invoke FindNextProc, eip

4.17.5  FollowCall

函数原型

FollowCall address

说明

FollowCall跳过一系列的jmp指令,直到:
1、某个不是jmp指令为止
2、或者某个指令是在另一个模块中