Комплексное литье - PullRequest
       13

Комплексное литье

0 голосов
/ 03 июля 2018

После изучения C и теоретических материалов операционных систем я решил проанализировать один руткит ядра для linux, но я не могу понять одну строку кода, я не знаю, как читать эту строку:

*(void **)&((char *)h->original_function)[ASM_HOOK_CODE_OFFSET] = h->modified_function;

Полный контекст:

#if defined __i386__
    // push 0x00000000, ret
    #define ASM_HOOK_CODE "\x68\x00\x00\x00\x00\xc3"
    #define ASM_HOOK_CODE_OFFSET 1
    // alternativly we could do `mov eax 0x00000000, jmp eax`, but it's a byte longer
    //#define ASM_HOOK_CODE "\xb8\x00\x00\x00\x00\xff\xe0"
#elif defined __x86_64__
    // there is no push that pushes a 64-bit immidiate in x86_64,
    // so we do things a bit differently:
    // mov rax 0x0000000000000000, jmp rax
    #define ASM_HOOK_CODE "\x48\xb8\x00\x00\x00\x00\x00\x00\x00\x00\xff\xe0"
    #define ASM_HOOK_CODE_OFFSET 2
#else
    #error ARCH_ERROR_MESSAGE
#endif

struct asm_hook {
    void *original_function;
    void *modified_function;
    char original_asm[sizeof(ASM_HOOK_CODE)-1];
    struct list_head list;
};


/**
 * Patches machine code of the original function to call another function.
 * This function should not be called directly.
 */
void _asm_hook_patch(struct asm_hook *h)
{
    DISABLE_W_PROTECTED_MEMORY
    memcpy(h->original_function, ASM_HOOK_CODE, sizeof(ASM_HOOK_CODE)-1);
    *(void **)&((char *)h->original_function)[ASM_HOOK_CODE_OFFSET] = h->modified_function;
    ENABLE_W_PROTECTED_MEMORY
}

Руткит-ссылка: https://github.com/nurupo/rootkit/blob/master/rootkit.c (строка 314 rootkit.c)

Я не хочу объяснять, как руткит, только хочу понять, как читать эту строку кода, первая часть строки вызывает у меня головокружение.

1 Ответ

0 голосов
/ 03 июля 2018

Если я не ошибаюсь: вы начинаете с самой внутренней части, которая является

h->original_function

Затем мы видим фигурную скобку справа, поэтому теперь мы сканируем влево поисковую фигурную скобку. Но подождите секунду, мы видим приведение к (char *), так что это указатель на символ, и теперь скобка закрывается.

Справа теперь мы видим индексирование массива для элемента [ASM_HOOK_CODE_OFFSET], а слева мы видим & для его адреса. Итак, теперь у нас есть адрес символа.

Теперь мы можем перейти только влево и увидеть *(void **), который преобразует этот адрес в указатель на указатель на пустоту, а затем разыменовывает его и присваивает правую часть адресу.

...