char buf[sizeof(shellcode)];
strcpy(buf, shellcode);
((void(*)())buf)();
我很难理解第三行的语法,我认为它使缓冲区成为函数?
答案 0 :(得分:3)
您对第三行是正确的。它使用buf
,将其衰减为指针,然后将该指针强制转换为函数指针。然后调用该函数。之所以起作用,是因为void(*)()
的意思是“指向不接受任何参数并返回void
的函数的指针”,并将其包装在括号中会将其转换为强制类型转换。现在,您有一个指向函数的指针,就可以像正常的函数名称一样调用它。
C标准不允许这样做,但是基于编译器的工作方式,这可能意味着它将buf
的地址视为内存中函数的地址,并尝试调用该函数。通常这是行不通的,因为OS会告诉CPU将内存buf
标记为不可执行,因此,当您假装它是一个函数时,CPU会抛出错误。我们假设操作系统没有执行此操作,或者您有足够老的CPU不支持该功能。
您没有向我们显示shellcode
的内容。由于计算机中的所有内容都是一个字节序列,包括计算机运行的已编译二进制代码,因此shellcode
可能包含可执行二进制代码。如果确实如此,那么这将导致该代码开始运行。
例如,如果您编译
void mycode()
{
puts("Hello, world!");
}
然后可以从生成的目标文件中提取功能mycode
的内容。如果将这些内容放入shellcode
中,那么问题中的代码将(假设编译器将指向函数的指针和指向数据的指针相同,并且操作系统或CPU不支持noexec内存) )将Hello, world!
打印到屏幕上。