我有这样的C代码:
#include <stdio.h>
void x(int argc, char** argv) {
printf(argv[0]);
}
int main(int argc, char** argv) {
char* secret = "SECRET";
if (argc < 2)
x(argc, argv);
}
我现在想做一个格式字符串攻击来打印shell的秘密。但是,我不知道如何获取我想要argv [0]的字符串以及如何从另一个范围访问数据(因为从x开始,它不可能直接解决指针秘密。
我该怎么做?
答案 0 :(得分:6)
在unix中,程序以execve
(或其中一个包装器,例如execlp
)启动。所有exec*
函数都允许您传递argv
的任意字符串,包括argv[0]
。
如果您是从shell以交互方式执行此操作,请查看内置的exec
:
( exec -a '%x...' ./prog )
parens创建子shell,exec
加载并运行./prog
到子shell进程中,-a
的参数用作argv[0]
。
至于如何访问变量,请查看生成的汇编代码。如果secret
存储在堆栈中并且printf
从堆栈中提取参数,则可以通过指定足够的%x
指令(后跟%s
来获得所需的结果})。
答案 1 :(得分:3)
argv[0]
包含程序名称,通常是您调用程序的字符串。对于使用./a.out
执行的程序,argv[0]
将指向./a.out
。
您的格式字符串攻击需要修改argv[0]
。这意味着您需要将可执行文件重命名为符合您需要的格式字符串。
我将您的程序更改为从argv[1]
读取并删除了argc < 2
限制。在%s
打印之前,我使用了%d
并添加了"SECRET"
。为什么%d
?我认为堆栈与int
的倍数(%d
打印)对齐,因为sizeof(int)
通常是自然字大小。
最后,我想出了%d%d%d%d%d%d%d%d%d%d%d%d%s
。这会从堆栈中打印一些值(如果有某种“跳过”格式化程序以避免实际打印这些值,我会使用它),弹出这些值,最后打印"SECRET"
。
请注意,这是未定义的行为,完全取决于您的计算机。