Я могу заменить функцию ядра Linux модулем?

Мой обычный способ сделать это:

my %unique = ();
foreach my $item (@myarray)
{
    $unique{$item} ++;
}
my @myuniquearray = keys %unique;

, Если Вы используете хеш и добавляете объекты к хешу. У Вас также есть премия знания, сколько раз каждый объект появляется в списке.

13
задан Community 23 May 2017 в 12:30
поделиться

4 ответа

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

Вместо этого вы можете изменить код, переименовав существующую функцию, а затем создав глобальный указатель на функцию с исходным именем функции. Инициализируйте указатель функции адресом внутренней функции, чтобы существующий код работал без изменений. Экспортируйте символ глобального указателя на функцию, тогда ваш модуль сможет просто изменить его значение путем присвоения во время загрузки и выгрузки модуля.

7
ответ дан 2 December 2019 в 00:18
поделиться

Вы можете попробовать использовать ksplice - вам даже не нужно делать его нестатическим.

3
ответ дан 2 December 2019 в 00:18
поделиться

Я думаю, что вам нужно Kprobe .

Другой способ, упомянутый caf, - это добавить ловушку к исходной подпрограмме и зарегистрировать / отменить регистрацию модуль.

2
ответ дан 2 December 2019 в 00:18
поделиться

Однажды я доказал концепцию модуля взлома, который вставлял свою собственную функцию вместо функции ядра. Так получилось, что в новой архитектуре привязки ядра используется очень похожая система.

Я внедрил свою собственную функцию в ядро, перезаписав первую пару байтов кода скачком, указывающим на мою пользовательскую функцию. Как только вызывается настоящая функция, она переходит к моей функции, которая после того, как она выполнила свою работу, называлась исходной функцией.


#include <linux/module.h>
#include <linux/kernel.h>

#define CODESIZE 12

static unsigned char original_code[CODESIZE];
static unsigned char jump_code[CODESIZE] =
    "\x48\xb8\x00\x00\x00\x00\x00\x00\x00\x00" /* movq $0, %rax */
    "\xff\xe0"                                          /* jump *%rax */
        ;
/* FILL THIS IN YOURSELF */
int (*real_printk)( char * fmt, ... ) = (int (*)(char *,...) )0xffffffff805e5f6e;

int hijack_start(void);
void hijack_stop(void);
void intercept_init(void);
void intercept_start(void);
void intercept_stop(void);
int fake_printk(char *, ... );


int hijack_start()
{
    real_printk(KERN_INFO "I can haz hijack?\n" );
    intercept_init();
    intercept_start();

    return 0;
}

void hijack_stop()
{
    intercept_stop();
    return;
}

void intercept_init()
{
    *(long *)&jump_code[2] = (long)fake_printk;
    memcpy( original_code, real_printk, CODESIZE );

    return;
}

void intercept_start()
{
    memcpy( real_printk, jump_code, CODESIZE );
}

void intercept_stop()
{
    memcpy( real_printk, original_code, CODESIZE );
}

int fake_printk( char *fmt, ... )
{
    int ret;
    intercept_stop();
    ret = real_printk(KERN_INFO "Someone called printk\n");
    intercept_start();
    return ret;
}

module_init( hijack_start );
module_exit( hijack_stop );

Предупреждаю вас, когда вы собираетесь экспериментировать с подобными вещами, смотрите из-за паники ядра и других катастрофических событий. Я бы посоветовал вам сделать это в виртуализированной среде. Это проверочный код, который я написал некоторое время назад, я не уверен, что он все еще работает.

Это действительно простой принцип, но очень эффективный. Конечно, реальное решение будет использовать блокировки, чтобы никто не вызвал функцию, пока вы ее перезаписываете.

Удачи!

3
ответ дан 2 December 2019 в 00:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: