我有一组十六进制代码转换为汇编指令,我想在C中创建可以执行这些代码的程序。
unsigned char rawData[5356] = {
0x4C, 0x01, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x0C, 0x00, 0x00,
0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x2E, 0x74, 0x65, 0x78,
0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xB4, 0x05, 0x00, 0x00, 0xA4, 0x01, 0x00, 0x00, 0x68, 0x08, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x20, 0x00, 0x30, 0x60,
0x2E, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0x00, 0x30, 0xC0, 0x2E, 0x62, 0x73, 0x73, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x30, 0xC0, 0x2F, 0x34, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x14, 0x00, 0x00, 0x00, 0x58, 0x07, 0x00, 0x00, 0x32, 0x0C, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x10, 0x30, 0x60,
0x2F, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x6C, 0x07, 0x00, 0x00,...and so on
答案 0 :(得分:8)
使用x86是可能的。
这是一个小样本。使用write / exec权限分配页面并在那里复制您的操作码。
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/mman.h>
#include <unistd.h>
#endif
int main(){
char opcodes[] = { ..... };
#ifdef _WIN32
HANDLE mem_handle = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, 0, length, NULL);
void* mem_map = MapViewOfFile( mem_handle, FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE, 0x0, 0x0, length);
#else // posix
void* mem_map = mmap(NULL, sizeof(opcodes), PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
#endif
memcpy(mem_map, opcodes, sizeof(opcodes));
(( void(*)() )mem_map)();
return 0;
}
对于POSIX系统,请使用mmap()调用。
还阅读有关蹦床的内容。请参阅链接:http://pages.cs.wisc.edu/~weinrich/papers/method_dispatch.pdf
你没有说明这是一个完整的程序还是一个单一的功能。相对/绝对地址可能存在问题。
小注:此代码也适用于启用了MMU的PowerPC和ARM。
答案 1 :(得分:4)
声明一个函数指针然后调用该函数。
void (*f)(void) = (void (*)(void)) rawData;
f();
当然这是未定义的行为,并不能保证有效。
答案 2 :(得分:4)
在某些平台上,您不能只声明:
void (*f)(void) = (void (*)(void)) rawData;
并尝试
f();
运行已修改的代码。
由于数据页面可能无法执行。定义函数而不关心其内容的便捷方法是向项目中添加.s
文件。
将其编译为GNU as,并将其目标文件链接到最终程序。
例如:
<强>的main.c 强>
int main()
{
helloasm();
return 0;
}
<强> x.s 强>
代码就像C语句一样:printf("Hello ASM\n"); exit(11);
.global helloasm
helloasm:
.byte 0x48, 0xc7, 0xc7, 0x01, 0x00, 0x00, 0x00, 0xe8, 0x0b, 0x00, 0x00, 0x00, 0x48, 0x65, 0x6c, 0x6c
.byte 0x6f, 0x20, 0x41, 0x53, 0x4d, 0x21, 0x0a, 0x5e, 0x48, 0xc7, 0xc2, 0x0b, 0x00, 0x00, 0x00, 0xb8
.byte 0x01, 0x00, 0x00, 0x00, 0x0f, 0x05, 0xbf, 0x0b, 0x00, 0x00, 0x00, 0xb8, 0x3c, 0x00, 0x00, 0x00
.byte 0x0f, 0x05
编译&amp;运行
as x.s -o x.o
gcc main.c x.o -o main
./main
Hello ASM!
此外,如果您的hexed代码数组位于二进制文件中,例如 a.bin
hexdump -C a.bin
00000000 48 c7 c7 01 00 00 00 e8 0b 00 00 00 48 65 6c 6c |H...........Hell|
00000010 6f 20 41 53 4d 21 0a 5e 48 c7 c2 0b 00 00 00 b8 |o ASM!.^H.......|
00000020 01 00 00 00 0f 05 bf 0b 00 00 00 b8 3c 00 00 00 |............<...|
00000030 0f 05 |..|
00000032
然后您的 x.s 可能是:
.global helloasm
helloasm:
.incbin "a.bin"
答案 3 :(得分:1)
查看头文件elf.h。
您需要使用OPCodes完成这些结构中的字段。
在x86中有一个加载可执行文件的协议,但是在链接器将控件传递给加载的代码之后,它会崩溃。
在这里查看如何创建有效的可执行文件:
答案 4 :(得分:-1)
你难道不能将它们输出到文件然后使用system()
电话吗?这样您就不必担心该数组是否遵循C调用约定。