Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: Skali en 3 Julio 2018, 02:37 am



Título: Linea de código dificil de entender
Publicado por: Skali en 3 Julio 2018, 02:37 am
Buenas, estaba analizando el código fuente de un kernel rootkit, y leyendo la documentación de las apis que se utilizan más o menos me estoy dando mania, aunque hay lineas que tal vez me cuestan bastante comprender, como ésta:

Código
  1. *(void **)&((char *)h->original_function)[ASM_HOOK_CODE_OFFSET] = h->modified_function;

Aquí les dejo un fragmento del rootkit para que les sea más facil entender:

Código
  1. // ========== ASM HOOK LIST ==========
  2.  
  3. #if defined __i386__
  4.    // push 0x00000000, ret
  5.    #define ASM_HOOK_CODE "\x68\x00\x00\x00\x00\xc3"
  6.    #define ASM_HOOK_CODE_OFFSET 1
  7.    // alternativly we could do `mov eax 0x00000000, jmp eax`, but it's a byte longer
  8.    //#define ASM_HOOK_CODE "\xb8\x00\x00\x00\x00\xff\xe0"
  9. #elif defined __x86_64__
  10.    // there is no push that pushes a 64-bit immidiate in x86_64,
  11.    // so we do things a bit differently:
  12.    // mov rax 0x0000000000000000, jmp rax
  13.    #define ASM_HOOK_CODE "\x48\xb8\x00\x00\x00\x00\x00\x00\x00\x00\xff\xe0"
  14.    #define ASM_HOOK_CODE_OFFSET 2
  15. #else
  16.    #error ARCH_ERROR_MESSAGE
  17. #endif
  18.  
  19. struct asm_hook {
  20.    void *original_function;
  21.    void *modified_function;
  22.    char original_asm[sizeof(ASM_HOOK_CODE)-1];
  23.    struct list_head list;
  24. };
  25.  
  26. LIST_HEAD(asm_hook_list);
  27.  
  28. /**
  29.  * Patches machine code of the original function to call another function.
  30.  * This function should not be called directly.
  31.  */
  32. void _asm_hook_patch(struct asm_hook *h)
  33. {
  34.    DISABLE_W_PROTECTED_MEMORY
  35.    memcpy(h->original_function, ASM_HOOK_CODE, sizeof(ASM_HOOK_CODE)-1);
  36.    *(void **)&((char *)h->original_function)[ASM_HOOK_CODE_OFFSET] = h->modified_function;
  37.    ENABLE_W_PROTECTED_MEMORY
  38. }

Link del rootkit: https://github.com/nurupo/rootkit/blob/master/rootkit.c (https://github.com/nurupo/rootkit/blob/master/rootkit.c)

no quiero que me expliquen todo el código, solo quiero saber como interpretar la línea que marqué más arriba (sería la línea 36 en éste fragmento).

Muchas gracias desde ya. Saludos



Título: Re: Linea de código dificil de entender
Publicado por: srWhiteSkull en 3 Julio 2018, 14:01 pm
Pues es lo que ves, un array que se le asigna a una de sus celdas una función  ;D


Título: Re: Linea de código dificil de entender
Publicado por: Skali en 3 Julio 2018, 15:11 pm
Buenas! Gracias srWhiteSkull por leer y responder, pero todavía no termino de entender... Si el código fuera asi:

Código
  1. h->original_function[ASM_HOOK_CODE_OFFSET] = h->modified_function;

Podría decir que al campo original_function del registro h en la posición ASM_HOOK_CODE_OFFSET se le asigna el campo modified_function del mismo registro h, pero lo que me hace marear mucho es lo que está antes, es como una conversión de tipos muy extraña, por eso me gustaría si pudieramos dividir la linea parte por parte y analizarla para entenderla bien. Gracias desde ya.

Saludos!


Título: Re: Linea de código dificil de entender
Publicado por: srWhiteSkull en 3 Julio 2018, 15:29 pm
Me imagino que será un array char, que a su vez contiene el puntero de una función que toma de argumento un void ** ... creo  :rolleyes:


Título: Re: Linea de código dificil de entender
Publicado por: MAFUS en 3 Julio 2018, 17:40 pm
Código:
*(void **)&((char *)h->original_function)[ASM_HOOK_CODE_OFFSET] = h->modified_function;

h->original_function : objeto, un puntero.

(char *)h->original_function : un puntero casteado a puntero a char.

((char *)h->original_function)[ASM_HOOK_CODE_OFFSET] : dado que h->original_function ha sido casteado a char * moverse a través de él será byte a byte, por tanto esto devolverá lo que hay en el byte ASM_HOOK_CODE_OFFSET de h->original_function.

&((char *)h->original_function)[ASM_HOOK_CODE_OFFSET] : devuelve la dirección del byte ASM_HOOK_CODE_OFFSET del objeto h->original_function.

(void **)&((char *)h->original_function)[ASM_HOOK_CODE_OFFSET] : castea a void ** la dirección del byte ASM_HOOK_CODE_OFFSET del objeto h->original_function. Se reconvierte la dirección devuelta al puntero de un puntero a void.

*(void**)&((char *)h->original_function)[ASM_HOOK_CODE_OFFSET] : se obtiene la dirección del byte ASM_HOOK_CODE_OFFSET del objeto h->original_function como puntero a void.


Título: Re: Linea de código dificil de entender
Publicado por: Skali en 3 Julio 2018, 19:07 pm
Excelente MAFUS! Muchas gracias por desmenuzar la línea parte por parte y analizarla, me ayudaste a entender con éste ejemplo práctico cómo leer una línea compleja teniendo en cuenta la precedencia de operadores. Ahora todo queda bastante más claro. Gracias nuevamente! Saludos.


Título: Re: Linea de código dificil de entender
Publicado por: MAFUS en 3 Julio 2018, 19:14 pm
En el siguiente link https://medium.com/@bartobri/untangling-complex-c-declarations-9b6a0cf88c96 te enseñarán a desmenuzar todas estas declaraciones complicadas. Hay muchos otros ejemplos en la red. Son un puzzle bastante bonito a resolver.


Título: Re: Linea de código dificil de entender
Publicado por: srWhiteSkull en 4 Julio 2018, 13:54 pm
Citar
Hace un casting a char* para poder avanzar byte a byte ya que sino avanzaria el tamaño de un puntero 4bytes, etc.. supongo que es o codigo viejo o de un programa en C, ya que hoy en dia en C++ no hay que hacer estas barbaridades tan poco legibles.


Título: Re: Linea de código dificil de entender
Publicado por: MAFUS en 4 Julio 2018, 14:20 pm
Seguramente es C, aunque en realidad C++ por debajo termina haciendo lo mismo. Son cosas de la expresividad del lenguaje.

Por otra parte: no se movería 4 bytes, eso en caso de que fuera un puntero a int, pero el objeto es un puntero a void. ¿Qué ocupa un dato de tipo void? Ni siquiera existe. Algunos compiladores, como GCC consideran que sumar 1 a un void* ha de apuntar al siguiente byte, pero claro puede haber otros desarrolladores de compiladores que no consideren así.


Título: Re: Linea de código dificil de entender
Publicado por: srWhiteSkull en 4 Julio 2018, 14:30 pm
La cita la extraí de una conversación con mi master al que le pregunté sobre la explicación de ese casting tan raro. Este hombre, mi master, es un señor que lleva muchísimos años programando, sobre todo en C++. Con él me inicié en el C y luego en el C++. Incluso sólo viendo la línea dedujo que se trataría de algún hook (la línea se la mostré sin la constante ASM_HOOK_CODE_OFFSET).

Yo no soy experto en C, puntualmente hago alguna cosilla en C (no es algo que se demande).