这篇主要介绍的是spritf函数引起的格式化字符串漏洞 总体的利用方式和printf是一样的
先来看一下sprintf函数的用法 其一共有三个参数 在不使用格式化字符的情况下 第三个参数可有可无
#include<stdio.h>void vuln(){ char buf[0x20]; sprintf(buf,"hello\n"); printf(buf);}int main(){ vuln();}主要的作用就是把hello这个字符串读入到buf数组变量中 来看一下运行的结果

如果使用上格式化字符
#include<stdio.h>void vuln(){ char buf[0x20]; char a[0x20] = "hello"; sprintf(buf,"%s\n",a); printf(buf);}int main(){ vuln();}
这里可能会误解为传入到buf中的值是%shello 随后是给予printf函数利用格式化字符串输出 其实不然 这里替换成puts来试一下
#include<stdio.h>void vuln(){ char buf[0x20]; char a[0x20] = "hello"; sprintf(buf,"%s",a); puts(buf);}int main(){ vuln();}断点打在sprintf函数这里来看一下

来看执行后0x7fffffffe050地址的值会被赋值成什么

由此可见 这里的格式化字符实际是决定vararg参数存储的类型 如果我们替换成%p呢

印证了猜想 那么%n呢 这个printf最强大的漏洞 可以做到任意地址写任意值 在这里是否奏效呢
#include<stdio.h>void vuln(){ char buf[0x20]; sprintf(buf,"a%7$n");}int main(){ vuln();}不同于其他格式化字符 %n在sprintf就可以起到任意写的作用 同时又和printf一样 默认是修改4个字节 如果想要修改8字节 就需要lln


如果我们修改蓝框中的值 使其占满8字节 再来覆盖看看


本质还是和printf差不多 在关键的任意写这块漏洞利用上