x86汇编指令脚本虚拟机
简介:这是一个可以直接解释执行从idapro里面提取出来的x86汇编代码的虚拟机。
非常精简,整体架构上不能跟那些成熟的虚拟机相比,主要目标是够用、能用、轻量就行。
项目主页
特性:跨平台运行支持,可以在widows、liux、macosx以及adroid,ios上运行x86的汇编代码。。
支持常用x86汇编指令(例如,逻辑操作,跳转,循环,调用,压栈等指令)
支持函数间跳转,以及第三方api调用
支持参数传入,以及运行结束后,返回值的获取
虚拟机的运行粒度为单个函数,函数间的跳转可以通过多个虚拟机实例来完成(轻量的,性能影响不大)
支持线程安全
暂时不支持arm64,只能在32位下运行(有兴趣的同学可以自行修改)
例子我们先从ida中提取一段汇编代码,这段汇编主要是pritf库函数打印外部传入的数值
sub_hello proc ear arg_0 = dword ptr 8 .data format db \"hello: %x\", 0ah, 0dh, 0 off_5A74B0 dd offset loc_6B2B50 ; DATA XREF: sub_589100+1832�r dd offset loc_58A945 ; jump table for switch statemet .code ; hi push ebp ;hello mov ebp, esp loc_6B2B50: ; CODE XREF: sub_6B2B40+8�j push eax mov eax, [ebp+arg_0] push eax mov eax, offset format push eax call pritf add esp, 4 pop eax mov ecx, 1 jmp ds:off_5A74B0[ecx*4]loc_58A945: push eax mov eax, [ebp+arg_0] push eax mov eax, offset format push eax call pritf add esp, 4 pop eax ed: mov esp, ebp pop ebp ret sub_hello edp如果用c来调用的话,就是"
sub_hello(31415926);输出结果:
hello: 31415926hello: 31415926接下来我们把这段汇编直接放到我们的虚拟机里面执行:
static tb_void_t vm86_demo_proc_exec_hello(tb_uit32_t value){ // 上述汇编代码的字符串表示 static tb_char_t cost s_code_sub_hello[] = {"sub_hello proc ear \\arg_0 = dword ptr 8 \\.data \\ format db \"hello: %x\", 0ah, 0dh, 0 \\ \\off_5A74B0 dd offset loc_6B2B50 ; DATA XREF: sub_589100+1832�r \\ dd offset loc_58A945 ; jump table for switch statemet \\ \\.code \\ ; hi\\ push ebp ;hello \\ mov ebp, esp \\ \\ loc_6B2B50: ; CODE XREF: sub_6B2B40+8�j\\ push eax \\ mov eax, [ebp+arg_0] \\ push eax \\ mov eax, offset format \\ push eax \\ call pritf \\ add esp, 4 \\ pop eax \\ \\ mov ecx, 1\\ jmp ds:off_5A74B0[ecx*4]\\ \\loc_58A945:\\ push eax \\ mov eax, [ebp+arg_0] \\ push eax \\ mov eax, offset format \\ push eax \\ call pritf \\ add esp, 4 \\ pop eax \\ \\ ed:\\ mov esp, ebp \\ pop ebp \\ ret \\sub_hello edp \\ " }; // 定义一个虚拟机 vm86_machie_ref_t machie = vm86_machie(); if (machie) { // 锁定虚拟机,保证线程安全(这个根据需要,可选) tb_spilock_ref_t lock = vm86_machie_lock(machie); tb_spilock_eter(lock); // 获取虚拟机的堆栈 vm86_stack_ref_t stack = vm86_machie_stack(machie); // 编译上面的汇编代码,并生成一个过程对象的引用 vm86_proc_ref_t proc = vm86_text_compile(vm86_machie_text(machie), s_code_sub_hello, sizeof(s_code_sub_hello)); if (proc) { // 添加汇编里面需要调用到的外部库函数 vm86_machie_fuctio_set(machie, "pritf", vm86_demo_proc_fuc_pritf); // 初始化调用参数 vm86_stack_push(stack, value); // 执行这个汇编代码 vm86_proc_doe(proc); // 恢复堆栈,获取返回值(这里是void的,传ull就行了) vm86_stack_pop(stack, tb_ull); } // 解锁虚拟机 tb_spilock_leave(lock); } }it mai(it argc, char** argv){ // 执行这个汇编函数:sub_hello(0x31415926) vm86_demo_proc_exec_hello(0x31415926); }ok,那么输出结果当然也是:
hello: 31415926hello: 31415926编译需要先安装xmake
在macosx上编译$ sudo brew istall xmake$ xmake f -a i386$ xmake在liux上编译$ git cloe https://github.com/waruqi/xmake.git$ cd xmake$ sudo ./istall$$ cd vm86$ xmake f -a i386$ xmake在widows上编译下载 https://github.com/waruqi/xmake/archive/master.zip
解压运行里面的istall.bat安装xmake后进行编译:
$ xmake编译adroid版本$ cd vm86$ xmake f -p adroid --dk=/xxx/dk$ xmake运行运行测试程序:
$ xmake r demo后话最后,在项目的idc目录下,有两个脚本工具:export_fuctio.idc 和 export_data.idc 可以用来辅助我们从ida中导出指定的汇编函数和数据
评论