ano*_*ard 28 c casting function-pointers segmentation-fault
我正在试图弄清楚如何执行存储在内存中的机器代码.
我有以下代码:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
FILE* f = fopen(argv[1], "rb");
fseek(f, 0, SEEK_END);
unsigned int len = ftell(f);
fseek(f, 0, SEEK_SET);
char* bin = (char*)malloc(len);
fread(bin, 1, len, f);
fclose(f);
return ((int (*)(int, char *)) bin)(argc-1, argv[1]);
}
Run Code Online (Sandbox Code Playgroud)
上面的代码在GCC中编译得很好,但是当我尝试从命令行执行程序时,如下所示:
./my_prog /bin/echo hello
Run Code Online (Sandbox Code Playgroud)
程序段错误.我已经发现问题出在最后一行,因为评论它会阻止段错误.
我不认为我做得很对,因为我仍在考虑功能指针.
这个问题是错误的演员,还是其他什么?
小智 29
您需要一个具有写入执行权限的页面.如果您在unix下,请参阅mmap(2)和mprotect(2).你不应该使用malloc来做.
另外,阅读其他人所说的内容,您只能使用加载程序运行原始机器代码.如果您尝试运行ELF标头,它可能会发生段错误.
关于回复和下载的内容:
1- OP说他正在尝试运行机器代码,所以我回答了这个问题而不是执行可执行文件.
2-了解为什么不混合malloc和mman函数:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
int main()
{
char *a=malloc(10);
char *b=malloc(10);
char *c=malloc(10);
memset (a,'a',4095);
memset (b,'b',4095);
memset (c,'c',4095);
puts (a);
memset (c,0xc3,10); /* return */
/* c is not alligned to page boundary so this is NOOP.
Many implementations include a header to malloc'ed data so it's always NOOP. */
mprotect(c,10,PROT_READ|PROT_EXEC);
b[0]='H'; /* oops it is still writeable. If you provided an alligned
address it would segfault */
char *d=mmap(0,4096,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_PRIVATE|MAP_ANON,-1,0);
memset (d,0xc3,4096);
((void(*)(void))d)();
((void(*)(void))c)(); /* oops it isn't executable */
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它在Linux x86_64上显示了这种行为,其他实现肯定会出现其他丑陋行为.
ta.*_*.is 12
在我看来,你正在加载一个ELF图像,然后试图直接跳入ELF标题?http://en.wikipedia.org/wiki/Executable_and_Linkable_Format
如果您正在尝试执行另一个二进制文件,为什么不在您使用的任何平台上使用进程创建函数?
Ran*_*e42 12
使用malloc工作正常.
好的,这是我的最终答案,请注意我使用了原始海报的代码.我正在从磁盘加载,这个代码的编译版本到堆分配区域"bin",正如原始代码所做的那样(名称固定不使用argv,值0x674来自;
objdump -F -D foo|grep -i hoho
08048674 <hohoho> (File Offset: 0x674):
Run Code Online (Sandbox Code Playgroud)
这可以通过BFD(二进制文件描述符库)或其他东西在运行时查找,只要它们静态链接到同一组lib,就可以调用其他二进制文件(不仅仅是你自己).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
unsigned char *charp;
unsigned char *bin;
void hohoho()
{
printf("merry mas\n");
fflush(stdout);
}
int main(int argc, char **argv)
{
int what;
charp = malloc(10101);
memset(charp, 0xc3, 10101);
mprotect(charp, 10101, PROT_EXEC | PROT_READ | PROT_WRITE);
__asm__("leal charp, %eax");
__asm__("call (%eax)" );
printf("am I alive?\n");
char *more = strdup("more heap operations");
printf("%s\n", more);
FILE* f = fopen("foo", "rb");
fseek(f, 0, SEEK_END);
unsigned int len = ftell(f);
fseek(f, 0, SEEK_SET);
bin = (char*)malloc(len);
printf("read in %d\n", fread(bin, 1, len, f));
printf("%p\n", bin);
fclose(f);
mprotect(&bin, 10101, PROT_EXEC | PROT_READ | PROT_WRITE);
asm volatile ("movl %0, %%eax"::"g"(bin));
__asm__("addl $0x674, %eax");
__asm__("call %eax" );
fflush(stdout);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
运行...
co tmp # ./foo
am I alive?
more heap operations
read in 30180
0x804d910
merry mas
Run Code Online (Sandbox Code Playgroud)
您可以使用UPX来管理文件的加载/修改/执行.
PS抱歉上一个断开的链接:|