GNU/Linux >> Tutoriales Linux >  >> Linux

Linux Kernel ROP - ¿Volviendo a la tierra del usuario desde el contexto del kernel?

Terminé escribiendo mi shellcode de una manera diferente. Como no sabía cómo regresar, dejé que el kernel hiciera el trabajo pesado por mí, al regresar a la zona de usuarios. La idea era ejecutar mi bit de escalada de privilegios y volver a donde se suponía que debía regresar la función vulnerable, con los registros y la pila arreglados.

Tan pronto como el núcleo regresó de la función vulnerable (cuando no se desbordó), noté algo a través de gdb . (Las direcciones son imaginarias, pero explican el concepto de todos modos).

(gdb) x/i $eip
0xadd1: ret
(gdb) x/xw $esp
0xadd1: 0xadd2
(gdb) x/6i 0xadd2
0xadd2: add esp,0x40
0xadd3: pop ...
0xadd4: pop ...
0xadd5: pop ...
0xadd6: pop ...
0xadd7: ret

Entonces, inmediatamente después de la devolución, 0x40 bytes de la pila no se usan y simplemente desaparecería con el add esp instrucción. Por lo tanto, aprovechando este hecho, construí una cadena ROP (ya la había construido mientras escribía esta pregunta, su trabajo era deshabilitar SMEP y saltar a mi shellcode de usuario), que tenía 24 bytes de largo. 4 bytes sobrescribirían el EIP en el momento de la devolución, y los 20 restantes (0x14 ) lo seguiría directamente a la pila no utilizada. Esto nos deja con 0x2c bytes de pila sin usar todavía.

Pero si volviéramos a 0xadd2 , nos arriesgaríamos a perder otros 0x14 bytes de valiosa información de registro de la pila y llenando los registros con datos no válidos. Podríamos add 0x2c a esp en nuestro shellcode de usuario, y salta directamente a 0xadd3 , omitiendo el add real instrucción.

También tomando nota de la sesión de depuración, todo excepto eax y ebx estaban siendo restaurados correctamente. Como mi desbordamiento los había destruido a ambos, tuve que restaurarlos con valores similares a los casos en que la función hizo un retorno limpio. (Hacer esto fue simple:establecí un punto de interrupción en 0xadd2 y extrajo los valores de info reg )

Entonces, mi shellcode final de usuario fue este:

Execute privesc payload -> add esp,0x2c -> register fixup -> jump to 0xadd3

Al hacer esto, la ruta del código volvió perfectamente limpia y el kernel hizo la tarea de volver al modo de usuario por mí.


Linux
  1. Mi historia de Linux:de entusiasta de 8 bits a administrador de sistemas de Unix

  2. Controlador de dispositivo del kernel de Linux a DMA desde un dispositivo a la memoria del espacio del usuario

  3. ¿Cómo cargar módulos del kernel de Linux desde el código C?

  4. Falta de referencia del puntero NULL del kernel de Linux en memset de kzalloc

  5. ¿Por qué proteger el kernel de Linux del usuario root?

Cómo compilar el kernel de Linux desde cero {Guía paso a paso}

Núcleo de Linux vs. Núcleo de Mac

De un sueño a la realidad:Cómo Linux cambió mi vida

Trabajar con Microsoft Exchange desde su escritorio Linux

Cómo construir el kernel de Linux desde cero

Cómo compilar el kernel de Linux desde el origen para crear un kernel personalizado