我试图在64位Linux上实现C中格式字符串漏洞的简单示例。这是我的源代码:
void not_called() {
printf("Exploited\n");
}
int main(int argc, char **argv) {
// Buffer overflow vulnerability
char buffer[256];
gets(buffer);
// User may input the format string
printf(buffer);
}
我输入以下字符串给程序
AAAABBBB-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x
结果是
AAAABBBB-8608002c-f458fe00-fbad2288-78252d78-252d7825-5e5c51a8-0-41414141-2d78252d-78252d78-252d7825-2d78252d
我可以将AAAA视为41414141
而不是BBBB跟随我的预期,因为它是缓冲区中相同输入字符串的组成部分。
这是某种保护机制还是我误解了什么?我的目标是覆盖返回地址,我需要读取8个字节(AAAABBBB),因为我在64位机器上工作。
漏洞利用字符串的伪代码看起来像这样
RETRNPTR%[decimal address of not_called - 8]u%[offset of RETRNPTR]$n
RETRNPTR是存储当前堆栈帧中返回地址的内存地址。
所以我最关心的是,8个字节的RETRNPTR似乎并不像我期望的那样在内存中持续存在。第二个问题是,%n是int-pointer,意味着只写入4个字节。我也很困惑,AAAA之前的那些价值来自哪里。
答案 0 :(得分:2)
首先,您要问的是具有未定义行为的代码;代码的行为确实应该被一个临时的C程序员认为是未定义的大部分内容。
现在,为什么你没有看到{{each ChildProduct where ChildProduct.ParentID === $index}}
。我认为这是因为你在x86-64系统上运行这个程序。调用约定是对堆栈上的值进行64位推送;但是BBBB
打印一个32位%x
; 64位堆栈值的32个最低有效位。要打印64位int
值,请使用long
。
(另外,在x86-64的System-V API上,6个第一个整数/指针参数根本不在堆栈上;它们位于%lx
,RDI
,{{1} },RSI
,RDX
和RCX
寄存器。)
例如我输入了:
R8
并获得输出
R9