Lesson
5 minutes to read
We are given a binary file called main and its source code in C:
#include <stdio.h>
void under_construction(){
printf("This is under development\n");
}
void print_msg(char *user){
char formatter[0x20];
strncpy(formatter, user, 5);
for (size_t i = 0; i < 5; i++) formatter[i] = tolower(formatter[i]);
printf(strncmp(formatter, "admin", 5) == 0 ? "\nWelcome admin!\n\n" : "\nWelcome user!\n\n");
}
int main(int argc, char **argv){
char name[0x20] = {0};
unsigned long x, y;
printf("Enter your name: ");
scanf("%s", name);
print_msg(name);
return 0;
}
We are asked to answer some questions about binary exploitation.
Question 1
$ nc 94.237.63.93 58324
This is a quick lesson to get started with the basics.
◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉
◉ ◉
◉ HINT: Run 'file ./main' to get some information about the binary. ◉
◉ ◉
◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉
[*] Question number 0x1:
Is this a '32-bit' or '64-bit' ELF? (e.g. 1337-bit)
We must check if the binary is 32-bit or 64-bit:
$ file main
main: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter ./glibc/ld-linux-x86-64.so.2, BuildID[sha1]=da663acb70f9fa157a543a6c4affd05e53fbcb07, for GNU/Linux 3.2.0, not stripped
>> 64-bit
♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠
♠ ♠
♠ Correct ♠
♠ ♠
♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠
Question 2
◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉
◉ ◉
◉ HINT: Run 'gdb ./main' to open the binary in the debugger, then ◉
◉ run 'checksec' to see the protections. ◉
◉ ◉
◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉
[*] Question number 0x2:
Which of these 3 protections are enabled (Canary, NX, PIE)?
We are asked to see the security measures enabled in the binary:
$ checksec main
[*] './main'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
RUNPATH: b'./glibc/'
>> NX
♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠
♠ ♠
♠ Correct ♠
♠ ♠
♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠
Question 3
We must take a look at the code and see what user we need to provide to get a certain message:
◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉
◉ ◉
◉ HINT: Pay attention to the 'void print_msg(char *user)' ◉
◉ and the 'strncmp(arg1, arg2, n_bytes)'. ◉
◉ ◉
◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉
[*] Question number 0x3:
What do you need to enter so the message 'Welcome admin!' is printed?
>> admin
♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠
♠ ♠
♠ Correct ♠
♠ ♠
♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠
Question 4
This one asks for the size reserved for the name buffer:
◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉
◉ ◉
◉ HINT: This is the buffer --> char name[0x20] = {0}; ◉
◉ ◉
◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉
[*] Question number 0x4:
What is the size of the 'name' buffer (in hex or decimal)?
>> 0x20
♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠
♠ ♠
♠ Correct ♠
♠ ♠
♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠
Question 5
Here, we must provide the name of the function that is never executed on the main routine:
◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉
◉ ◉
◉ HINT: Only functions inside 'main()' are called. ◉
◉ Also, the functions these functions call. ◉
◉ ◉
◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉
[*] Question number 0x5:
Which custom function is never called? (e.g. vuln())
>> under_construction
♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠
♠ ♠
♠ Correct ♠
♠ ♠
♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠
Question 6
This time, we must find a function that is used in a wrong way and might cause a Buffer Overflow vulnerability:
◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉
◉ ◉
◉ HINT: Which function reads the string from the stdin? ◉
◉ ◉
◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉
[*] Question number 0x6:
What is the name of the standard function that could trigger a Buffer Overflow? (e.g. fprintf())
This vulnerability appears at scanf("%s", name), because the format string "%s" admits any string length, but name has only 0x20 reserved bytes:
>> scanf
♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠
♠ ♠
♠ Correct ♠
♠ ♠
♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠
Question 7
◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉
◉ ◉
◉ HINT: A Segmentation Fault occurs when the return ◉
◉ address is overwritten with an invalid address. ◉
◉ ◉
◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉
[*] Question number 0x7:
Insert 30, then 39, then 40 'A's in the program and see the output.
After how many bytes a Segmentation Fault occurs (in hex or decimal)?
We must test some payloads to see if a Segmentation Fault occurs:
$ python3 -c 'print("A" * 30)'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
$ ./main
Enter your name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Welcome user!
$ python3 -c 'print("A" * 39)'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
$ ./main
Enter your name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Welcome user!
$ python3 -c 'print("A" * 40)'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
$ ./main
Enter your name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Welcome user!
zsh: segmentation fault (core dumped) ./main
So, we have the answer:
>> 40
♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠
♠ ♠
♠ Correct ♠
♠ ♠
♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠
Question 8
◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉
◉ ◉
◉ HINT: Run 'gdb ./main' to open the binary in the debugger, then ◉
◉ run 'p <function_name>' to see the address of a function. ◉
◉ ◉
◉ e.g. pwndbg> p main ◉
◉ $2 = {<text variable, no debug info>} 0x401294 <main> ◉
◉ ◉
◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉
[*] Question number 0x8:
What is the address of 'under_construction()' in hex? (e.g. 0x401337)
We are asked to see the address of under_construction:
$ objdump -M intel -d main | grep under_construction
00000000004011d6 <under_construction>:
And this is it:
>> 0x4011d6
♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠
♠ ♠
♠ Correct ♠
♠ ♠
♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠
Flag
This is the flag:
Great job! It's high time you solved your first challenge! Here is the flag!
HTB{w4rm35t_w4rmup_3v3r}
