io.smashthestack.org / level01

PUBLISHED ON 28/12/2015 — IO.SMASHTHESTACK.ORG, TUTORIALS

Spomnil sem se, da sem pred leti užival v “blowfish” “wargame”-u na smashthestack.org. Nažalost takrat nisem imel dovolj znanja in vztrajnosti, da bi se kam prebil. Prevrtimo čas nekaj let naprej, nekaj stvari sem se vmes naučil in “io” bo idealen test kako daleč sem prišel. Napredek bom vmes popisoval v materinem jeziku :)

Povezava na strežnik je klasična:

$ ssh -l level1 io.smashthestack.org -p2224

Geslo: level1

V domači mapi najdemo navodila za igro. Preberite jih.

Prvi koraki

V kolikor sledimo navodilom, naredimo tole:

level1@io:~$ cd /levels/




level1@io:/levels$ ./level01
Enter the 3 digit passcode to enter: 123

Zagon “level1” programa nas vpraša za geslo, ki je v obliki treh cifer. Kombinacija “123” ni delovala, če smo pogumni lahko na roke preizkusimo še preostalih 999 možnosti. Verjetno pa to ni smisel igre…

Prefinjen pristop bi bil, da preverimo če obstaja izvorna koda programa, katere na našo žalost ni pri roki.

Naslednja stopnja je obratni inženiring.

objdump

V sklopu paketa GNU binutils najdemo med drugim objdump, ki ga lahko izkoristimo za prikaz programa v zbirnem jeziku.

level1@io:/levels$ objdump -d level01

level01:     file format elf32-i386


Disassembly of section .text:

08048080 :
 8048080:   68 28 91 04 08          push   $0x8049128
 8048085:   e8 85 00 00 00          call   804810f 
 804808a:   e8 10 00 00 00          call   804809f 
 804808f:   3d 0f 01 00 00          cmp    $0x10f,%eax
 8048094:   0f 84 42 00 00 00       je     80480dc 
 804809a:   e8 64 00 00 00          call   8048103 

Hiter pregled izpisa nam razjasni delovanje programa. Za nas zanimiva vrstica je ta, ki vsebuje ukaz cmp. cmp (compare) je ukaz za primerjavo v zbirnem jeziku, v primeru ko sta obe podani vrednosti enaki, postavi Z zastavico na 1, sicer pa na 0. Ukaz je (jump if equal), kakor neposredni prevod pove, skoči na določeno mesto v pomnilniku.

eax je en izmed registrov (ang. accumulator register) v katerega lahko shranimo vrednosti, tja shrani naš program vrednost, ki smo jo vpisali, ko je program od nas zahteval geslo. Uporablja se za dostop do vhodno/izhodnih vrat, aritmetiko, prekinitve in podobno. eax poznamo, ugotoviti moramo kaj se skriva pod vrednostjo 0x10f, to lahko izvedemo s pomočjo lupine:

level1@io:/levels$ echo "ibase=16; 10F"| bc
271

Privzeto objdump izpisuje ukaze zbirnika v AT&T sintaksi, ki jo prepoznamo po množici % in $ znakov, omogoča pa tudi izpis v Intel sintaksi, ki je vsaj zame berljivejša kakor AT&T. Naš primer je sicer prekratek, da bi bile razlike res opazne, vendar ga vseeno prilagam.

level1@io:/levels$ objdump -M intel -d level01

level01:     file format elf32-i386


Disassembly of section .text:

08048080 :
 8048080:   68 28 91 04 08          push   0x8049128
 8048085:   e8 85 00 00 00          call   804810f 
 804808a:   e8 10 00 00 00          call   804809f 
 804808f:   3d 0f 01 00 00          cmp    eax,0x10f
 8048094:   0f 84 42 00 00 00       je     80480dc 
 804809a:   e8 64 00 00 00          call   8048103 

gdb

Dodaten način za razbijanje prve stopnje je uporaba GNU razhroščevalnika (gdb, GNU debugger).

level1@io:/levels$ gdb level01
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /levels/level01...(no debugging symbols found)...done.

(gdb) disas main
Dump of assembler code for function main:
   0x08048080 <+0>:    push   $0x8049128
   0x08048085 <+5>:    call   0x804810f 
   0x0804808a <+10>:    call   0x804809f 
   0x0804808f <+15>:    cmp    $0x10f,%eax
   0x08048094 <+20>:    je     0x80480dc 
   0x0804809a <+26>:    call   0x8048103 
End of assembler dump.

(gdb) p 0x10F
$1 = 271

Intel sintakso lahko uporabljamo tudi v GNU razhroščevalniku z ukazom:

(gdb) set dis intel

Navedeni ukaz, nam bo nastavil gdb samo za trenutno sejo, če želimo, da je Intel sintaksa privzeta pri vsakem zagonu razhroščevalnika lahko v .gdbinit dodamo vrstico “set dis intel”:

$ echo "set dis intel" > ~/.gdbinit

Epilog

Ob pridobitvi gesla nam preostane samo še vpis v program in pridobili smo dostop do naslednje stopnje.

level1@io:/levels$ ./level01
Enter the 3 digit passcode to enter: 271
Congrats you found it, now read the password for level2 from /home/level2/.pass
sh-4.2$