我正在处理C中的格式字符串漏洞,并试图通过终端中给定的printf命令打印"argc“整数的值。
我当前的代码是:
int main (int argc, char **argv) {
char buffer[32];
*More variables*
strncpy(buffer, argv[1], sizeof(buffer));
printf(buffer);
*More printf's*
}我可能需要使用格式说明符将整数argc的内容打印到终端中,但我似乎找不到解决方案。我所有的猜测都会得到所有的argv堆栈寄存器(%rsi,%rdx,%rcx,%r8d,%r9d)。
格式字符串应在终端中给出,如下例所示:
./format-string %d_%s是否有可能获得ARGC值?如果是,我该怎么做?
发布于 2020-10-18 20:28:39
我试图在评论中要求一些澄清,但你没有回答,所以我假设你在一个符合SYS V x86-64 ABI的环境中工作。
当调用main时,argc在rdi中,但很快就会被对strncpy和printf本身的调用覆盖:
main:
sub rsp, 40
mov rsi, QWORD PTR [rsi+8]
mov edx, 32
mov rdi, rsp ;OOOPS
call strncpy
mov rdi, rsp ;OOOPS
xor eax, eax
call printf
xor eax, eax
add rsp, 40
ret上面的代码是compiled output of your sample program (清理后)。
但是,SYSVx86-64ABI上的glibc不会合成argc本身(就像Windows的对应产品一样,请参阅GetCommandLine和类似的内容),在创建程序时,该值将作为堆栈上的第一个值传递(请参阅ABI规范的图3.9 )。

因此,您可以通过使用跳过前k-1个参数的%d格式,即%k$d,通过printf达到它,其中k是要找到的数字。
要查找k,您只需找到调用printf时的rsp和argc地址之间的偏移量。
但是,因为在创建进程时argc位于堆栈的底部,所以这相当于查找printf调用点的rsp和rsp的初始值之间的偏移量。
所以使用gdb:
gdb --args format-string test
b _start
r
i r rsp
0x7fffffffdfa0 The initial value of RSP
b printf
c
i r rsp
0x7fffffffd9d8 The value AFTER printf is called. Add 8 to find it BEFORE the call
q现在0x7fffffffdfa0 - (0x7fffffffd9d8 + 8) = 0x110
0x110字节是34个参数(0x110/8 = 0x22),由于前四个参数在寄存器中,我们也需要跳过它们,加上4。最后,计数是以1为基础的,并且包括差值,因此我们需要在计数中加上2。最后一个值是,对于我的示例环境,为34 +4+2= 40,导致命令:
./format-string '%40$d'发布于 2020-10-18 19:50:42
printf使用system v x86-64位ABI,它规定要在寄存器rdi、rsi、rdx、rcx、r8、r9中传递的函数的所有参数,如果存在,则进一步的值参数将以相反的顺序传递到堆栈,因此在您的情况下,您将需要传递多个%p (取决于堆栈上已存在的数据数量),我们使用%p,因为我们希望将数据打印为64位值。简而言之,将多个%p传递给printf将首先查看寄存器,然后查看存储到堆栈中的参数(从内存中读取)。所以
%p%p%p%p%p%p%p%p%p /* will print registers values first extra %p will start to read up from stack (feel free to add as you want but keep in mind it will result in segmentation fault eventually if reached a specific area in memory but not sure when)*/发布于 2020-10-18 19:18:58
整数使用%d,字符串使用%s
#include <stdio.h>
int main (int argc, char **argv)
{
char buffer[32] = {0};
strncpy(buffer, argv[1], sizeof(buffer));
printf("argc = %d and argv[1] = %s\n", argc, buffer);
return 0;
}https://stackoverflow.com/questions/64412632
复制相似问题