Level 01

 Publ .

 Mins 4 (684 words).

 Edit .

Level 01

As usual, you should login using your ssh client. Of course performing a quick inspection of ~ is mandatory. You should find a setuid binary file, owned by leviathan2.

$ file check
check: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=aab009a1eb3940df51c668d1c35dc9cdc1191805, for GNU/Linux 3.2.0, not stripped
$ ./check
password: psswrd
Wrong password, Good Bye ...

Tooling

The next logical step is finding out what tools might be of use, in a typical UNIX system, to infer the operation this setuid binary file is performing. A short research points to:

  1. readelf - a command that will display detailed information about the binary file’s headers, sections, symbols and more.

  2. strace - an utility that can be used to trace the system calls made by the binary and understand how it is interacting within the user and system.

  3. ltrace - traces the library calls made, which can aid in understanding the functions being used within the code.

  4. objdump - this tool can be used to disassemble the binary code, for a very low-level understanding.

After consulting the manual page for each of these programs, I proceed to execute them on the host.

1 - readelf

$ man readelf
$ readelf --all check | less

Using as reference this and this webpages, inspected the output.

In general, the explanations felt somewhat advanced for the writer’s level of understanding. In regards to making sense of the check program, no helpful information derived from the analysis.

2 - strace

After reading the manual page for the utility and then issuing the command plainly on the terminal, it seemed like a good idea rendering the output on a text editor with syntax highlighting capabilities to better parse the output.

$ man strace
$ mkdir /tmp/foobar
$ strace -o /tmp/foobar/out ./check
$ vim /tmp/foobar/out

Once inside vim: :syntax on

Here is a brief description of the calls observed on the strace output:

  • File operations: System calls such as open, read, write, or close, signal that the binary file is reading from or writing to files on the file system.

  • Network operations: socket, connect, send, or recv, making network connections and sending or receiving data over the network.

  • Process operations: fork, exec, or wait, manipulation of processes.

  • System resource usage: getpid, getuid, getgid, or geteuid, querying system information such as process IDs, user IDs, and group IDs.

  • Interaction with the operating system: system calls such as ioctl, mmap, or munmap, interactions with the operating system to manipulate resources such as input/output devices, memory, or file descriptors.

Inspected several man pages of system calls. The final write and read calls might be related to the interactive section of the program. The fact that the arguments of the functions are the strings received and passed to the program suggests this.

3 - ltrace

$ man ltrace
$ ltrace -o /foobar/out ./check

The ltrace utility shows the operations that the binary file performs at the library level.

  • Library usage: functions such as malloc, strcpy, or printf. Tese suggest what the program is doing and how it is handling data.

  • Input and output: fopen, fread, fwrite, or fclose, the binary file is reading from or writing to files on the file system.

  • Network operations: socket, connect, send, or recv, are used for making network connections and sending or receiving data over the network.

  • String operations: strcpy, strcat, or strtok, manipulate and perform string operations.

  • Math operations: pow, sqrt, or sin, perform mathematical operations.

Here is our output:

__libc_start_main(0x80491e6, 1, 0xffffd5f4, 0 <unfinished ...>
printf("password: ")                                         = 10
getchar(0xf7fbe4a0, 0xf7fd6f80, 0x786573, 0x646f67)          = 112
getchar(0xf7fbe4a0, 0xf7fd6f70, 0x786573, 0x646f67)          = 97
getchar(0xf7fbe4a0, 0xf7fd6170, 0x786573, 0x646f67)          = 115
strcmp("pas", "sex")                                         = -1
puts("Wrong password, Good Bye ...")                         = 29
+++ exited (status 0) +++

A detailed analysis of the library calls that the binary uses, led to a solution to the level. You see, the three getchar() calls read each a character from the input buffer while strcmp() tests for equality of two strings received as arguments.

The program checks for the hard-coded string ‘sex’:

$ ./check
password: sex
$ whoami
leviathan2
$