
Ein Toolkit zum Schreiben von Shellcode
Das Schreiben von Shellcodes hat immer super Spaß gemacht, aber einige Teile sind extrem langweilig und fehleranfällig. Konzentriere dich nur auf den lustigen Teil und benutze ShellNoob!
Für einen schnellen Überblick, schau dir die Folien des Black Hat Arsenal Vortrags an: Link
Möchtest du beitragen? Funktionswunsch? Fehlermeldung? Flüche? Jegliches Feedback ist willkommen!! (Aber manche Art von Feedback ist willkommener als andere :-)).
Du kannst mich gerne auf Twitter @reyammer anpingen oder mir eine E-Mail an yanick[AT]cs.ucsb.edu schreiben, falls du Fragen hast!
21.01.2014 - ShellNoob 2.1 ist draußen! Es kommt mit vollständiger Unterstützung für Python 3 und zahlreichen Fehlerbehebungen. Die volle Anerkennung gebührt Levente Polyak!
29.07.2013 - ShellNoob 2.0 ist draußen!
08.06.2013 - ShellNoob wurde bei Black Hat Arsenal angenommen! Siehe Ankündigung hier: Link.
--intel.--64.-c.--to-strace und --to-gdb!--file-patch, --vm-patch, --fork-nopper! (alle Details unten)$ ./shellnoob.py -h
shellnoob.py [--from-EINGABE] (eingabe_dateipfad | - ) [--to-AUSGABE] [ausgabe_dateipfad | - ]
shellnoob.py -c (einen Breakpoint voranstellen (Warnung: nur wenige Plattformen/OS werden unterstützt!)
shellnoob.py --64 (64-Bit-Modus, Standard: 32 Bit)
shellnoob.py --intel (Intel-Syntax-Modus, Standard: att)
shellnoob.py -q (leiser Modus)
shellnoob.py -v (oder -vv, -vvv)
shellnoob.py --to-strace (kompiliert & führt strace aus)
shellnoob.py --to-gdb (kompiliert & führt gdb aus & setzt Breakpoint am Einstiegspunkt)
Eigenständige "Plugins"
shellnoob.py -i [--to-asm | --to-opcode ] (für interaktiven Modus)
shellnoob.py --get-const <const>
shellnoob.py --get-sysnum <sysnum>
shellnoob.py --get-errno <errno>
shellnoob.py --file-patch <exe_fp> <datei_offset> <daten> (in hex). (Warnung: nur auf x86/x86_64 getestet)
shellnoob.py --vm-patch <exe_fp> <vm_adresse> <daten> (in hex). (Warnung: nur auf x86/x86_64 getestet)
shellnoob.py --fork-nopper <exe_fp> (dies entfernt die Aufrufe von fork(). Warnung: nur auf x86/x86_64 getestet)
"Installation"
shellnoob.py --install [--force] (dies kopiert das Skript einfach an eine geeignete Stelle)
shellnoob.py --uninstall [--force]
Unterstütztes EINGABE-Format: asm, obj, bin, hex, c, shellstorm
Unterstütztes AUSGABE-Format: asm, obj, exe, bin, hex, c, completec, python, bash, ruby, pretty, safeasm
Alle Kombinationen von EINGABE zu AUSGABE werden unterstützt!
$ ./shellnoob.py --install
Dies kopiert das Skript einfach nach /usr/local/bin/snoob. Das war's. (Führe ./shellnoob.py --uninstall aus, um es rückgängig zu machen).
$ snoob --from-asm shell.asm --to-bin shell.bin
Einige gleichwertige Alternativen (das Tool wird versuchen zu erraten, was du möchtest, basierend auf der Dateierweiterung..)
$ snoob --from-asm shell.asm --to-bin
$ snoob shell.asm --to-bin
$ snoob shell.asm --to-bin - > shell.bin
$ cat shell.asm | snoob --from-asm - --to-bin - > shell.bin
--intel für Intel-Syntax. (Siehe Abschnitt "asm als Ausgabeformat" für weitere Details)--from-shellstorm akzeptiert als Argument eine <shellcode_id>. ShellNoob holt den ausgewählten Shellcode aus der shell-storm Shellcode-Datenbank und konvertiert ihn in das gewünschte Format.$ snoob -c shell.asm --to-exe shell
$ gdb -q shell
$ run
Reading symbols from ./shell...(no debugging symbols found)...done.
(gdb) run
Starting program: ./shell
Program received signal SIGTRAP, Trace/breakpoint trap.
0x08048055 in ?? ()
(gdb)
Oder du kannst die neuen Schalter --to-strace und --to-gdb verwenden!
$ snoob open-read-write.asm --to-strace
Converting open-read-write.asm (asm) into /tmp/tmpBaQbzP (exe)
execve("/tmp/tmpBaQbzP", ["/tmp/tmpBaQbzP"], [/* 97 vars */]) = 0
[ Process PID=12237 runs in 32 bit mode. ]
open("/tmp/secret", O_RDONLY) = 3
read(3, "thesecretisthedolphin\n", 255) = 22
write(1, "thesecretisthedolphin\n", 22thesecretisthedolphin
) = 22
_exit(0)
$ snoob open-read-write.asm --to-gdb
Converting open-read-write.asm (asm) into /tmp/tmpZdImWw (exe)
Reading symbols from /tmp/tmpZdImWw...(no debugging symbols found)...done.
(gdb) Breakpoint 1 at 0x8048054
(gdb)
Beachte, wie ShellNoob automatisch einen Breakpoint am Einstiegspunkt setzt!
$ snoob --get-sysnum read
i386 ~> 3
x86_64 ~> 0
$ snoob --get-sysnum fork
i386 ~> 2
x86_64 ~> 57
$ snoob --get-const O_RDONLY
O_RDONLY ~> 0
$ snoob --get-const O_CREAT
O_CREAT ~> 64
$ snoob --get-const EINVAL
EINVAL ~> 22
$ snoob --get-errno EINVAL
EINVAL ~> Invalid argument
$ snoob --get-errno 22
22 ~> Invalid argument
$ snoob --get-errno EACCES
EACCES ~> Permission denied
$ snoob --get-errno 13
13 ~> Permission denied
$ ./shellnoob.py -i --to-opcode
asm_to_opcode selected
>> mov %eax, %ebx
mov %eax, %ebx ~> 89c3
>>
./shellnoob.py -i --to-asm
opcode_to_asm selected
>> 89c3
89c3 ~> mov %eax,%ebx
>>
$ python
>>> from shellnoob import ShellNoob
>>> sn = ShellNoob(flag_intel=True)
>>> sn.asm_to_hex('nop; mov ebx,eax; xor edx,edx')
'9089c331d2'
>>> sn.hex_to_inss('9089c331d2')
['nop', 'mov ebx,eax', 'xor edx,edx']
>>> sn.do_resolve_syscall('fork')
i386 ~> 2
x86_64 ~> 57
Wenn "asm" das Ausgabeformat ist, gibt ShellNoob sein Bestes. Objdump wird als Disassembler verwendet, aber seine Ausgabe ist nicht absolut zuverlässig. ShellNoob versucht, die Disassemblierung zu erweitern, indem es die Bytes (.byte-Notation) hinzufügt und, wo angemessen, die Entsprechung in ASCII (.ascii-Notation) anzeigt. Dies ist nützlich, wenn du die Ausgabe von objdump ändern/assemblieren möchtest, aber eine schnelle Korrektur benötigst.
Beispiel mit der .byte-Notation:
jmp 0x37 # .byte 0xeb,0x35
pop %ebx # .byte 0x5b
mov %ebx,%eax # .byte 0x89,0xd8
add $0xb,%eax # .byte 0x83,0xc0,0x0b
xor %ecx,%ecx # .byte 0x31,0xc9
Beispiel mit der .ascii-Notation:
das # .ascii "/"
je 0xac # .ascii "tm"
jo 0x70 # .ascii "p/"
jae 0xa8 # .ascii "se"
arpl %si,0x65(%edx) # .ascii "cre"
je 0xa0 # .ascii "tX
ShellNoob wird unter der MIT-Lizenz veröffentlicht. Siehe die COPYRIGHT-Datei.