Welcome Write-Up
Pwnable.xyz의 첫 번째 문제 Welcome이다.
50점의 점수를 가지고 있기 때문에, 점수 상 그렇게 어려운 문제는 아니다.
Binary
바이너리는 64bit 실행파일이며, Shared Object로 PIE가 적용되어 있다.
또한, Stripped상태로 Symbol정보가 모두 지워진 상태다.
또한, 모든 보호기법이 적용된 상태이다.
여기서 살짝 유추해볼 수 있는 것이 '일단 Memory Exploit은 아니겠구나' 이다.
따라서, 일반적인 Exploit방법보다는 Tricky한 방법으로 시선을 맞추는 놓는 것도 좋은 접근법이다.
바이너리도 크게 복잡하지 않다.
malloc(0x40000)을 한 뒤, 할당된 주소를 출력해주고 있다.
그 뒤, scanf( )로 malloc( )할 Size를 사용자 입력을 받고 Size만큼 Data를 입력 받는다.
중요 포인트는 다음 두 박스이다.
첫 번째 박스는 Size-1에 0을 입력해주고, 두 번째 박스는 처음 할당했던 v3가 0인지 확인하고 있다.
v3에 0이 저장되어 있으면, system("cat /flag")로 Flag를 출력해준다.
우리는 저 포인트를 이용해서 Flag값을 얻어내면 된다.
Solve
GDB로 확인한 v5[size - 1] = 0; 구문이다.
v5[size - 1] 참조를 PTR [rbp+rdx*1 - 0x1]로 하고 있음을 확인할 수 있는데, 이때 레지스터를 보면 답을 얻을 수 있다.
RDX의 값은 scanf( )에서 입력받은 Size값이다. 여기에서는 0x4141414141414141로 입력했다.
RBP값은 0이기 때문에, v5[size - 1]은 PTR [rdx - 1]과 같다.
따라서, v5[size - 1]은 0x4141414141414140으로, 해당 주소를 참조하면서 Segmentation Fault가 발생하게 된다.
이제 해당 주소를 v3로 맞춰주면 되는데, 문제에서 v3의 주소를 출력해주고 있기 때문에 간단하게 해결 가능하다.
from pwn import *
p = remote("svc.pwnable.xyz",30000)
p.recvuntil("Leak: ")
leak = int(p.recv(14),16)
p.recvuntil(": ")
p.sendline(str(int(leak+1)))
p.recvuntil(": ")
p.sendline("")
p.interactive()