Previous Level: Level 6
Login
SSH: ssh leviathan6@leviathan.labs.overthewire.org -p 2223
Password: UgaoFee4li
- new YZ55XPVk2l
A little bit of Theory
This level includes a lot of new things, that will be too much, so I will stick to explaining the very basics needed. And you should look more into Assembly and gdb if you are interested - I will link some resources that were helpful for me.
Assembly language is a low-level programming language, it is between machine code (hard to read for humans) and high-level programming languages (’easy’ to read for humans). There are different types of assembly, namely Intel and AT&T Syntax. In this walkthrough, you will see the AT&T Syntax. Check out TryHackMe Win64 Assembly for the basics of reverse engineering and assembly.
Let’s quickly look over the structure of a line of assembly code:
instr source,dest
. A line starts with an instruction. Followed by a source and destination (for the AT&T syntax). There is a certain set of instructions (based on the machine code), that can be chosen from. Very common ones are for example jumps (‘je’=‘jump if equal’) or the compare (‘cmp’) instruction. The source and destination can - depending on the instruction - be a hard-coded value, a register or an address.
Examples:
add $0x4,%eax
: here the instruction is ‘add’, the source is the value ‘0x4’ and the destination is the ’eax’ register.
mov (%eax),%eax
: here the instruction is ‘mov’ (move), the source is the value saved at the ‘address’ saved in eax and the destination is again the ’eax’ register.
I highly recommend that you understand and do research on concepts like memory, address and the different types of registers etc. to understand this walkthrough. Maybe check out Tutorialspoint Assembly Programming Tutorial or other resources.
GDB (GNU Debugger) is a debugger for Linux. It can be used for reverse engineering. There are however also programs, like Ghidra, which are designed specifically for reverse engineering. There are also plugins for GDB, which make debugging and/or reverse engineering easier like PWNDBG.
GDB has a lot of commands, let’s take a look at the most important ones:
- To run GDB with a program to debug and parameter input use:
gdb --args program_name params
. - Use
disassemble func_name
, to get the assembly code of a specific function. break *hex_address
to set a breakpoint at a specific part of the code- Use
c
to continue after a breakpoint run
starts the programinfo registers
prints the current values of all registersx hex_address
allows you to print the value saved at the address If you google ‘gdb cheat sheet’ you will find even more helpful commands.
Solution
The home folder contains a file called ’leviathan6’, which takes a 4-digit code as input.
|
|
Using the strings
or ltrace
command from previous levels does not show us the solution. One way to solve this is to try brute-force to get the correct 4-digit code - this could be done manually or with a simple script. However, that would be rather boring (it could look something like this: for i in {0000..9999}; do ./leviathan6 $i; done
).
Instead, we can get a little more into reverse engineering and look into the code with gdb.
First, we start it:
|
|
Then we look at the assembly code of the main function. We need to find the line where the digits are compared:
|
|
Looking at the code, we can see line ‘+106’ calls ‘setreuid@plt’ and line ‘122’ calls ‘system@plt’. The names sound, like the user id, is changed and a shell command is executed. We can check this assumption, by looking into the Linux Manual Page. We find this is exactly, what is happening. So now we just need to follow the program flow, to see, how we get to this part of the code. We will find that the jump in line ‘+87’ would lead to skipping that part because it jumps to line ‘+132’. This must be, where the code is checked and if it is not equal, it skips the for us important part. another way to see this is the line ‘+76’, where the ‘atoi’ function is called (converts string to integer - assume it’s our input). So we need to check what is compared (line ‘+84’).
|
|
So looking at the line 0x0804922a <+84>: cmp %eax,-0xc(%ebp)
, we compare the value in the register ’eax’, which is 0
, so our initial input, with what is stored on the address in register ’ebp’ minus 0xc
.
First, we calculate the address, and then we look at what is saved at that address in decimal:
|
|
And we got a 4-digit number, now we just need to test, if it is the correct one.
|
|
We got the right code and a shell, as leviathan7. So we can read the password file.
Addition
Since this is the last level (as of this writing), we should test the last password:
|
|