Featured image of post PWN-4

PWN-4

二进制漏洞与利用——格式化字符串漏洞

[TOC]

前言:本期有所借鉴其他博主的讲解资料,内容有所重合,如有侵权随时下架重置。

FMT介绍

格式化字符串函数:将计算机内存中表示的数据转化为我们人类可读的字符串格式。

函数 介绍
printf 输出到stdout
fprintf 输出到指定FILE流
vprintf 根据参数列表格式化输出道stdout
vfprintf 根据参数列表格式输出道指定FILE流
sprintf 输出到字符串
snprintf 输出到指定字节数到字符串
vsprintf 根据参数列表格式化输出到字符串
vsnprintf 根据参数列表格式化输出指定字节到字符串
setproctitle 设置argv
syslog 输出日志
err,verr,warn,vwarn等 。。。

用printf()为例子,第一个参数就是格式化字符串:

%d ~ 十进制——输出十进制整数

%s ~ 字符串——从内存中读取字符串

%x ~ 十六进制——输出十六进制数

%c ~ 字符——输出字符

%p ~ 指针——指针地址

%n ~ 到目前为止所写的字符数

格式化字符串漏洞原理的利用

来看一种攻击案例,最简单的攻击方法,只需要输入一串%s就可以

%s%s%s%s%s%s%s%s%s%s%s%s%s%s

学过C语言都知道,每一个%s,会使printf()从栈上取一个数字,把该数字看做成地址,接着打印出该地址所指向的内存内容,这不就是隔山打牛吗?一个%s就能窃取隔壁的东西,有时这不太可取,万一你获取的数字是非法地址?所以有可数字对应的内容可能不存在,或者这个地址被保护的,那么程序就会因此崩溃或者停滞不前。

在Linux中,存取无效的指针会引起进程收到SIGSEGV信号,从而使程序非正常终止并产生核心转储。

泄露内存(案例)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#include<stdio.h>
int main(void)
{
    char s[100];
    int a = 1, b = 0x22222222, c = -1;
    scanf("%s", s);
    printf("%08x.%08x.%08x.%s\n",a, b, c, s);
    printf(s);
    return 0;
}

编译一下:

1
gcc -m32 -fno-stack-protector -no-pie -o exp exp.c

在printf函数上面下个断点,然后r运行,输入%08x.%08x.%08x

调试参数变量一一对应

最后更新于 2025-10-04