
A shellcode writing toolkit
Écrire des shellcodes a toujours été super amusant, mais certaines parties sont extrêmement ennuyeuses et sujettes à erreurs. Concentrez-vous uniquement sur la partie amusante et utilisez ShellNoob !
Pour un aperçu rapide, consultez les diapositives de la présentation Black Hat Arsenal : lien
Vous voulez contribuer ? Demande de fonctionnalité ? Rapport de bug ? Insultes ? Tous les retours sont les bienvenus !! (Mais certains types de retours sont plus les bienvenus que d'autres :-)).
N'hésitez pas à me mentionner sur Twitter @reyammer ou à m'envoyer un email à yanick[AT]cs.ucsb.edu pour toute question !
21/01/2014 - ShellNoob 2.1 est sorti ! Il est livré avec le support complet de Python 3 et des tonnes de corrections de bugs. Tout le crédit revient à Levente Polyak !
29/07/2013 - ShellNoob 2.0 est sorti !
08/06/2013 - ShellNoob a été accepté à Black Hat Arsenal ! Voir l'annonce ici : lien.
--intel.--64.-c.--to-strace et --to-gdb !--file-patch, --vm-patch, ! (tous les détails ci-dessous)$ ./shellnoob.py -h
shellnoob.py [--from-INPUT] (input_file_path | - ) [--to-OUTPUT] [output_file_path | - ]
shellnoob.py -c (prepend a breakpoint (Warning: only few platforms/OS are supported!)
shellnoob.py --64 (64 bits mode, default: 32 bits)
shellnoob.py --intel (intel syntax mode, default: att)
shellnoob.py -q (quite mode)
shellnoob.py -v (or -vv, -vvv)
shellnoob.py --to-strace (compiles it & run strace)
shellnoob.py --to-gdb (compiles it & run gdb & set breakpoint on entrypoint)
Standalone "plugins"
shellnoob.py -i [--to-asm | --to-opcode ] (for interactive mode)
shellnoob.py --get-const <const>
shellnoob.py --get-sysnum <sysnum>
shellnoob.py --get-errno <errno>
shellnoob.py --file-patch <exe_fp> <file_offset> <data> (in hex). (Warning: tested only on x86/x86_64)
shellnoob.py --vm-patch <exe_fp> <vm_address> <data> (in hex). (Warning: tested only on x86/x86_64)
shellnoob.py --fork-nopper <exe_fp> (this nops out the calls to fork(). Warning: tested only on x86/x86_64)
"Installation"
shellnoob.py --install [--force] (this just copies the script in a convinient position)
shellnoob.py --uninstall [--force]
Supported INPUT format: asm, obj, bin, hex, c, shellstorm
Supported OUTPUT format: asm, obj, exe, bin, hex, c, completec, python, bash, ruby, pretty, safeasm
All combinations from INPUT to OUTPUT are supported!
$ ./shellnoob.py --install
Cela va simplement copier le script dans /usr/local/bin/snoob. C'est tout. (Exécutez ./shellnoob.py --uninstall pour annuler).
$ snoob --from-asm shell.asm --to-bin shell.bin
Quelques alternatives équivalentes (l'outil essaiera de deviner ce que vous voulez en fonction de l'extension du fichier..)
$ 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 pour utiliser la syntaxe Intel. (voir la section « asm en sortie » pour plus de détails)--from-shellstorm prend en argument un <shellcode_id>. ShellNoob récupérera le shellcode sélectionné depuis la base de shellcodes de shell-storm et le convertira au format choisi.$ 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)
Ou vous pouvez utiliser les nouvelles options --to-strace et --to-gdb !
$ 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)
Remarquez comment ShellNoob définit automatiquement un point d'arrêt sur le point d'entrée !
$ 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
Lorsque le format de sortie est « asm », ShellNoob fait de son mieux. Objdump est utilisé comme désassembleur, mais sa sortie n'est pas infaillible. ShellNoob essaie d'enrichir le désassemblage en ajoutant les octets (notation .byte), et, le cas échéant, affiche l'équivalent en ASCII (notation .ascii). Cela est utile lorsque vous voulez modifier/assembler la sortie de objdump mais que vous avez besoin d'une correction rapide.
Exemple avec la notation .byte :
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
Exemple avec la notation .ascii :
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 est distribué sous la licence MIT. Consultez le fichier COPYRIGHT.
--fork-nopper