RuCTF 2012 Quals –
Discern utility

RuCTF 2012 - Discern utility - task description

Die Aufgabenstellung (Discern utility) spricht von einer aufgefundenen Datei und verlangt von uns festzustellen, was der deren Inhalt beschreibt. Bei dem Dokument selbst handelt es sich nur um eine Textdatei, deren Inhalt mit 73 Zeilen recht überschaubar ist. Ein erster Blick in die Daten zeigt uns:

brk(0)                                  = 0x2335000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9bfad31000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=117316, ...}) = 0

Hierbei handelt es sich um “System Calls” (Syscalls), das heißt, rudimentäre Systemfunktionen, die im Kernel verankert sind und aus denen die Funktionalität aller komplexen Programme aufgebaut wird. Welche Syscalls ein Programm verwendet, lässt sich mit dem Werkeug “strace” herausfinden. Und genau dieses Werkzeug wurde auch hier verwendet um die Aufgabe dieser Challenge zu stellen.

Um die Aufgabe zu lösen müssen wir also herausfinden, welches Werkzeug die uns zur Verfügung gestellte strace-Ausgabe liefert. Sehen wir uns dazu die gesamte Textdatei an und versuchen, Merkmale des aufgerufenen Programmes zu identifizieren. Folgende Syscalls sollten hierbei auffallen:

uname({sys="Linux", node="ros-laptop", ...}) = 0
access("/proc/net", R_OK)               = 0
access("/proc/net/unix", R_OK)          = 0
socket(PF_FILE, SOCK_DGRAM, 0)          = 3
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 4
access("/proc/net/if_inet6", R_OK)      = 0
socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP) = 5
access("/proc/net/ax25", R_OK)          = -1 ENOENT (No such file or directory)
access("/proc/net/nr", R_OK)            = -1 ENOENT (No such file or directory)
access("/proc/net/rose", R_OK)          = -1 ENOENT (No such file or directory)
access("/proc/net/ipx", R_OK)           = -1 ENOENT (No such file or directory)
access("/proc/net/appletalk", R_OK)     = -1 ENOENT (No such file or directory)
access("/proc/sys/net/econet", R_OK)    = -1 ENOENT (No such file or directory)
access("/proc/sys/net/ash", R_OK)       = -1 ENOENT (No such file or directory)
access("/proc/net/x25", R_OK)           = -1 ENOENT (No such file or directory)

Das Programm liest zunächst per “uname” die Systeminformationen des Kernels aus und greift anschließend auf viele Netzwerkinformationen des Systems über proc-Dateisystem zu.  Es scheint sich also um irgendein Werkzeug zu handeln, das mit Netzwerkinformationen oder Netzwerkkonfigurationen zu tun hat.

Auf einem Linux-System kommt uns hier als erstes das Tool “ifconfig” in den Sinn. Um einen Vergleichswert zu erhalten, führen wir “ifconfig” selbst einmal aus und sehen uns die Ausgabe von “strace” an. Um, wie in unserer Challenge-Datei, die Bildschirmausgabe auszublenben, filtern wir diesen Dateideskriptor heraus.

lambda:~/discern_utility# strace ifconfig 1>/dev/null
[...]
uname({sys="Linux", node="lambda", ...}) = 0
access("/proc/net", R_OK)               = 0
access("/proc/net/unix", R_OK)          = 0
socket(PF_FILE, SOCK_DGRAM, 0)          = 3
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 4
access("/proc/net/if_inet6", R_OK)      = 0
socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP) = 5
access("/proc/net/ax25", R_OK)          = -1 ENOENT (No such file or directory)
access("/proc/net/nr", R_OK)            = -1 ENOENT (No such file or directory)
access("/proc/net/rose", R_OK)          = -1 ENOENT (No such file or directory)
access("/proc/net/ipx", R_OK)           = -1 ENOENT (No such file or directory)
access("/proc/net/appletalk", R_OK)     = -1 ENOENT (No such file or directory)
access("/proc/sys/net/econet", R_OK)    = -1 ENOENT (No such file or directory)
access("/proc/sys/net/ash", R_OK)       = -1 ENOENT (No such file or directory)
access("/proc/net/x25", R_OK)           = -1 ENOENT (No such file or directory)
open("/proc/net/dev", O_RDONLY)         = 6
[...]

Die beiden Ausgaben sind erstaunlich ähnlich – selbst die Reihenfolge der /proc-Elemente ist gleich. Es liegt also mehr als Nahe, dass für die Challenge ebenfalls das Werkzeug “ifconfig” verwendet wurde.

Im weiteren Verlauf unterscheiden sich die Ausgaben jedoch. Unser Aufruf von “ifconfig” lies die Konfiguration der Netzwerkschnittstellen aus und greift mit folgenden Syscalls auf das System zu:

ioctl(4, SIOCGIFCONF, {64, {{"lo", {AF_INET, inet_addr("127.0.0.1")}}, {"eth0", {AF_INET, inet_addr("192.168.0.1")}}}}) = 0
ioctl(5, SIOCGIFFLAGS, {ifr_name="eth0", ifr_flags=IFF_UP|IFF_BROADCAST|IFF_RUNNING|IFF_MULTICAST}) = 0
ioctl(5, SIOCGIFHWADDR, {ifr_name="eth0", ifr_hwaddr=00:12:34:56:78:90}) = 0
ioctl(5, SIOCGIFMETRIC, {ifr_name="eth0", ifr_metric=0}) = 0
ioctl(5, SIOCGIFMTU, {ifr_name="eth0", ifr_mtu=1500}) = 0

Währenddessen unternimmt der zur Challenge-Aufgabe gehörende Aufruf von “ifconfig” nichts dergleichen, sondern führt nur einen einzigen Syscall dieser Art aus, nämlich:

ioctl(4, SIOCSIFHWADDR, {ifr_name="eth0", ifr_hwaddr=ee:ee:ee:ee:ee:ee}) = 0

ioctl” (Input/Output Control) ist ein Syscall um gerätespezische Ein- und Ausgabeoperationen durchzuführen. In unserem Aufruf von “ioctl” wird dabei das Kommando “SIOCGIFHWADDR” verwendet, während der Challenge-Aufruf “SIOCSIFHWADDR” benutzt.

“SIOCGIFHWADDR” steht für “Set I/O Control: Get Interface Hardware Address” und “SIOCSIFHWADDR” steht für “Set I/O Control: Set Interface Hardware Address”.

Der einzige Unterschied ist also, dass unser Aufruf nur die Hardware-Adresse des Gerätes ausliest, während das Werkzeug der Challenge-Aufgabe die Hardware-Adresse zuweist, nämlich auf “ee:ee:ee:ee:ee:ee”, was wir aus dem “ioctl”-Syscall ebenfalls erkennen.

Gesucht ist also nur noch der Aufruf von “ifconfig” um die Hardware-Adresse auf “ee:ee:ee:ee:ee:ee” abzuändern. Dieser sieht wie folgt aus:

lambda:~/discern_utility# ifconfig eth0 hw ether ee:ee:ee:ee:ee:ee

Auch die abschließende Probe dieses Aufrufes mit “strace” zeigt, dass die Aufgabe mit der der Challenge-Aufgabe annähernd identisch ist.

Zur Lösung der Challenge musste die Hardware-Adresse jedoch ohne Doppelpunkte angegeben werden. Diese Darstellung wird von “ifconfig” genauso akzeptiert, wie die Angabe mit Trennzeichen.

Die Lösung lautet also “ifconfig eth0 hw ether eeeeeeeeeeee“.

Leave a Reply

Your email address will not be published. Required fields are marked *