我想问:如果我把代码的机器指令存放在的数据区,那要如何执行这些代码呢?
------解决方案--------------------------------------------------------
下面给出一个具体的例子,在数组bytecode填充一些指令码,实现2个整数相加的功能。将函数指针g_fn_add指向这个数组,并调用函数指针g_fn_add指向的指令码计算整数a和b的值。
- C/C++ code
#include <stdio.h>#include <stdlib.h>typedef int (*lpfn_add_c)(int a, int b);char bin_pattern[]={ 0x8b, 0x44, 0x24, 0x08, 0x8b, 0x4c, 0x24, 0x04, 0x03, 0xc1, 0xc3,};int main(int argc, char* argv[]){ char bytecode[16]; int a,b,c; lpfn_add_c g_fn_add; memset(bytecode,0,sizeof(bytecode)); memcpy(bytecode,bin_pattern,sizeof(bin_pattern)); a=3; b=5; g_fn_add= (lpfn_add_c)(bytecode); c=g_fn_add(a,b); printf("a=%d,b=%d,a+b=%d\n",a,b,c); return 0;}
------解决方案--------------------------------------------------------
g_fn_add= (lpfn_add_c)(bytecode);
此句强转编译报错
error C2440: “类型转换”: 无法从“char [16]”转换为“lpfn_add_c”
------解决方案--------------------------------------------------------
VC++中可以这样过渡一下:
int *func_ptr = (int *)bytecode;
...
g_fn_add= (lpfn_add_c)func_ptr;
------解决方案--------------------------------------------------------
------解决方案--------------------------------------------------------
------解决方案--------------------------------------------------------
好久没有写汇编程序了,现在给出上面c程序的等价masm32汇编版本。
- Assembly code
.386.model flat ; 32 bit memory modeloption casemap :none ; case sensitiveWriteFile PROTO STDCALL:DWORD,:DWORD,:DWORD,:DWORD,:DWORDCloseHandle PROTO STDCALL:DWORDExitProcess PROTO STDCALL:DWORDwsprintfA PROTO C:DWORD,:VARARG includelib user32.libincludelib kernel32.lib .const_formatString db '%d+%d=%d',0dh,0ah,0 .data? ;非初值化的数据,不占可执行文件空间_buff db 128 dup (?)align 4_tmp1 dd ? _c dd ? .data ;初值化的数据fun_add db 8bh, 44h, 24h, 08h, 8bh, 4ch, 24h, 04h,03h, 0c1h, 0c3halign 4_a dd 3_b dd 5 .code_start: mov eax,_a mov edx,_b push eax push edx lea ebx, fun_add ;eax 执行函数的地址 call ebx mov _c, eax ;返回值 --> 全局变量 _c invoke wsprintfA, addr _buff, addr _formatString, _a, _b, _c add esp, 20 ;5 * dword? invoke WriteFile,7,OFFSET _buff,32,OFFSET _tmp1,0 ;输出到控制台,输出32个字符 invoke ExitProcess, 0end _start
------解决方案--------------------------------------------------------
API函数说明,
本程序使用了3个Windows API 函数,WriteFile,wsprintfA和ExitProcess。说明如下
1. WriteFile
第一个参数是7,7是标准输出文件的句柄。对于输出的字节数,这里简单的设为32,更好的方法应该先算出字符串的长度,传给WriteFile
2. wsprintfA 是一个windows API函数,类似于c语言库函数的sprintf
3. ExitProcess,退出进程。没有什么好讲的。