C 如何将数组作为函数调用?
我有一个十六进制值的数组,表示汇编指令。C 如何将数组作为函数调用?,c,arrays,C,Arrays,我有一个十六进制值的数组,表示汇编指令。 我想将HelloWorld数组作为printf的参数 (int)&HelloWorld是获取数组地址的正确方法还是有更好的解决方案? 如何将代码[]作为函数调用 我尝试使用函数指针,但程序跳转到内存中的其他地方,最终在无效指令下崩溃 这是我的密码: #include <stdio.h> #include <stdlib.h> #include <windows.h> #include <errno.h>
我想将HelloWorld数组作为printf的参数 (int)&HelloWorld是获取数组地址的正确方法还是有更好的解决方案?
如何将代码[]作为函数调用
我尝试使用函数指针,但程序跳转到内存中的其他地方,最终在无效指令下崩溃 这是我的密码:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <errno.h>
int main()
{
int HelloWorld[15] =
{
// Hello World
0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x2C, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x00
};
int Code[50] =
{
// PUSH [DWORD PTR] DS:<address of array HelloWorld>
0xFF, 0x35, (int)&HelloWorld,
// CALL <address of function printf>
0xE8, (int)&printf,
// ADD esp, 4
0x83, 0xC4, 0x04,
// RET
0xC3
};
long unsigned int ProtectionCode = 0;
// Change protection to read, write, execute
int ChangeProtect = VirtualProtect(Code, 50, PAGE_EXECUTE_READWRITE,
&ProtectionCode);
if(ChangeProtect == 0)
{
printf("Error: %s\n", strerror(errno));
return 1;
}
void (*CodePtr)() = &Code;
(*CodePtr)();
return 0;
}
#包括
#包括
#包括
#包括
int main()
{
int HelloWorld[15]=
{
//你好,世界
0x48、0x65、0x6C、0x6C、0x6F、0x2C、0x20、0x57、0x6F、0x72、0x6C、0x64、0x00
};
整数代码[50]=
{
//推送[DWORD PTR]DS:
0xFF、0x35(内部)和HelloWorld,
//召唤
0xE8,(int)和printf,
//添加esp,4
0x83,0xC4,0x04,
//RET
0xC3
};
长无符号整数保护码=0;
//将保护更改为读、写、执行
int ChangeProtect=VirtualProtect(代码,50,第页\u执行\u读写,
&保护代码);
if(ChangeProtect==0)
{
printf(“错误:%s\n”,strerror(errno));
返回1;
}
void(*CodePtr)(=&Code;
(*编码器)();
返回0;
}
感谢您的帮助。此版本在我的windows上运行良好:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <errno.h>
char HelloWorld[15] =
{
// Hello World
0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x2C, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x00
};
void __attribute__((used)) foo(void)
{
int (*p)(const char *, ...) = printf;
p(HelloWorld);
}
int main()
{
unsigned char Code[] ={
0x55,
0x89, 0xe5,
0x83, 0xec, 0x28,
0xc7, 0x45, 0xf4, 0x78, 0x8c, 0x40, 0x00,
0xc7, 0x04, 0x24, 0x04, 0xa0, 0x40, 0x00,
0x8b, 0x45, 0xf4,
0xff, 0xd0,
0x90,
0xc9,
0xc3,
};
long unsigned int ProtectionCode = 0;
// Change protection to read, write, execute
int ChangeProtect = VirtualProtect(Code, 50, PAGE_EXECUTE_READWRITE,
&ProtectionCode);
if(ChangeProtect == 0)
{
printf("Error: %s\n", strerror(errno));
return 1;
}
void (*CodePtr)() = &Code;
(*CodePtr)();
return 0;
}
#包括
#包括
#包括
#包括
char HelloWorld[15]=
{
//你好,世界
0x48、0x65、0x6C、0x6C、0x6F、0x2C、0x20、0x57、0x6F、0x72、0x6C、0x64、0x00
};
void uuu属性uuu((已用))foo(void)
{
int(*p)(常量字符*,…)=printf;
p(HelloWorld);
}
int main()
{
无符号字符代码[]={
0x55,
0x89,0xe5,
0x83,0xec,0x28,
0xc7、0x45、0xf4、0x78、0x8c、0x40、0x00、,
0xc7、0x04、0x24、0x04、0xa0、0x40、0x00,
0x8b,0x45,0xf4,
0xff,0xd0,
0x90,
0xc9,
0xc3,
};
长无符号整数保护码=0;
//将保护更改为读、写、执行
int ChangeProtect=VirtualProtect(代码,50,第页\u执行\u读写,
&保护代码);
if(ChangeProtect==0)
{
printf(“错误:%s\n”,strerror(errno));
返回1;
}
void(*CodePtr)(=&Code;
(*编码器)();
返回0;
}
foo只是从以下代码中提取:)“我有一个十六进制值的数组,表示汇编指令。”——汇编指令不应该是一堆int。它们应该是包含指令的字符串,例如
“mov eax,3”
。然后通过使用asm
关键字来运行此操作。您正在尝试的任何类似于函数指针强制转换的行为都是未定义的行为,并且只有在您的编译器文档表明您可以这样做的情况下才能可靠地工作。假设您使用x86_32或x86_64:问题是,内存中的“0xff,0x35”确实存储为“ff 00 00 35 00 00…”,而您希望使用“ff 35…”。当您尝试使用机器代码创建缓冲区时,必须更加小心。您还可以尝试将缓冲区写入文件,并使用objdump对其进行反汇编,以验证其格式是否正确。否则,函数调用看起来正常。此问题与堆栈溢出上的其他问题重复;不时询问如何执行包含机器指令的数据。首先,答案取决于平台,因此您必须指定正在使用的操作系统。第二,你必须得到正确的机器代码。指令大小固定的机器可以使用int
数组,或者最好是unsigned int
,但对于英特尔来说,unsigned char
数组是更好的方法。第三,您需要调用操作系统例程来更改页面映射并刷新指令缓存。此问题确实比原始问题有更多问题,因此可以重新打开以解决这些问题。但它们是基本错误,可能应该单独涵盖。使用(uintptr\t)&HelloWorld
是获取地址以供动态准备的指令使用的一种方法,但也可能有其他方法。但是,对于x86体系结构,指令流必须以字节序列的形式写入,而不是int
,地址(或偏移量或使用的任何内容)必须以字节的形式复制到该序列中,而不是作为一个整体int
或uintpttr\t
。