Я играл с модулями ядра в Linux и, основываясь на примерах на https://sysprog21.github.io/lkmpg/, нашел хороший пример использования kprobes для подключения собственных функций к внутренним функциям ядра, который, кажется, работает хорошо.
Я хотел получить аргументы вызываемой функции. Поскольку моя система представляет собой систему X86_64, соглашение о вызове должно заключаться в том, что аргументы должны находиться в регистрах RDI, RSI и RDX (в именно в этом порядке).
Зарегистрированная функция обратного вызова (pre_handler) имеет аргумент regs, который содержит регистры di, si и dx. Я предполагаю, что это сохраненные регистры rdi, rsi и rdx, поскольку все эти поля в структуре pr_regs 64-битные.
Функция, которую я использовал для перехвата моего предварительного обработчика:
__x64_sys_openat(int dfd, const char *path, struct open_how *how)
Я ожидаю, что первый аргумент будет небольшим положительным целым числом, а второй и третий аргументы будут указателями.
Что я вижу в выводе мой модуль:
[23374.116347] "pre 1st arg dfd :" [di]: 0xFFFFAE19081A3F58 (-90052443357352) valid 0
[23374.116351] "pre 2nd arg *path:" [si]: 0x101 (257) valid 0
[23374.116353] "pre 3th arg *how :" [dx]: 0x0 (0) valid 0
Первый аргумент выглядит как адрес (указатель), второй — как целочисленное значение, а последний может быть нулевым указателем, который может быть допустимым.
Если я попытаюсь напечатать второй аргумент в виде строки (очевидно), произойдет сбой ядра.
Могу ли я получить содержимое аргументов из сохраненных регистров в структуре pt_regs? И можете ли вы объяснить мне, почему это не работает?
Я использую Fedora linux: вывод uname:
Linux 6.11.10-200.fc40.x86_64 #1 SMP PREEMPT_DYNAMIC Sat Nov 23 00:53:13 UTC 2024 x86_64 GNU/Linux
Код, который я использовал:
/*
* syscall-steal.c
*
* System call "stealing" sample.
*
* Disables page protection at a processor level by changing the 16th bit
* in the cr0 register (could be Intel specific).
*/
#include
#include
#include
#include /* which will have params */
#include /* The list of system calls */
#include /* For current_uid() */
#include /* For __kuid_val() */
#include
/* For the current (process) structure, we need this to know who the
* current user is.
*/
#include
#include
/* If you have tried to use the syscall table to intercept syscalls and it
* doesn't work, you can try to use Kprobes to intercept syscalls.
* Set USE_KPROBES_PRE_HANDLER_BEFORE_SYSCALL to 1 to register a pre-handler
* before the syscall.
*/
#include
#define MAX_FILENAME_SIZE 1024
/* UID we want to spy on - will be filled from the command line. */
static uid_t uid = -1;
module_param(uid, int, 0644);
/*
* rdi: 1st argument (saved in regs->di?)
* rsi: 2nd argument (saved in regs->si?)
* rdx: 3th argument (saved in regs->dx?)
*
* __x64_sys_openat(int dfd, const char *path, struct open_how *how)
* dfd => rdi
* path => rsi
* how => rdx
*
*/
#define VALID_ADDRESS(desc, name) pr_info("%s [%s]: 0x%lX (%ld) valid %d\n", #desc, #name, regs->name, regs->name, virt_addr_valid(regs->name));
static int openat_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
char filename[MAX_FILENAME_SIZE];
if (__kuid_val(current_uid()) != uid) {
return 0;
}
strcpy(filename, "No file");
pr_info("openat called by %d\n", uid);
VALID_ADDRESS("pre 1st arg dfd :", di);
VALID_ADDRESS("pre 2nd arg *path:", si);
VALID_ADDRESS("pre 3th arg *how :", dx);
if(copy_from_user(filename, (void*)regs->si, MAX_FILENAME_SIZE-1)) {
pr_info("copy user data failed\n");
}
pr_info("Opening file: %s\n", filename);
//dump_stack();
return 0;
}
static struct kprobe openat_kprobe = {
.symbol_name = "__x64_sys_openat",
.pre_handler = openat_pre_handler,
};
static int __init syscall_steal_start(void)
{
pr_info("Using kprobes\n");
int err;
err = register_kprobe(&openat_kprobe);
if (err) {
pr_err("register_kprobe() on openat failed: %d\n", err);
}
return err;
pr_info("Spying on UID:%d\n", uid);
return err;
}
static void __exit syscall_steal_end(void)
{
unregister_kprobe(&openat_kprobe);
msleep(500);
}
module_init(syscall_steal_start);
module_exit(syscall_steal_end);
MODULE_LICENSE("GPL");
Подробнее здесь: https://stackoverflow.com/questions/793 ... ith-kprobe
Как получить аргументы функций ядра Linux с помощью kprobe ⇐ Linux
-
Anonymous
1735480169
Anonymous
Я играл с модулями ядра в Linux и, основываясь на примерах на https://sysprog21.github.io/lkmpg/, нашел хороший пример использования kprobes для подключения собственных функций к внутренним функциям ядра, который, кажется, работает хорошо.
Я хотел получить аргументы вызываемой функции. Поскольку моя система представляет собой систему X86_64, соглашение о вызове должно заключаться в том, что аргументы должны находиться в регистрах RDI, RSI и RDX (в именно в этом порядке).
Зарегистрированная функция обратного вызова (pre_handler) имеет аргумент regs, который содержит регистры di, si и dx. Я предполагаю, что это сохраненные регистры rdi, rsi и rdx, поскольку все эти поля в структуре pr_regs 64-битные.
Функция, которую я использовал для перехвата моего предварительного обработчика:
__x64_sys_openat(int dfd, const char *path, struct open_how *how)
Я ожидаю, что первый аргумент будет небольшим положительным целым числом, а второй и третий аргументы будут указателями.
Что я вижу в выводе мой модуль:
[23374.116347] "pre 1st arg dfd :" [di]: 0xFFFFAE19081A3F58 (-90052443357352) valid 0
[23374.116351] "pre 2nd arg *path:" [si]: 0x101 (257) valid 0
[23374.116353] "pre 3th arg *how :" [dx]: 0x0 (0) valid 0
Первый аргумент выглядит как адрес (указатель), второй — как целочисленное значение, а последний может быть нулевым указателем, который может быть допустимым.
Если я попытаюсь напечатать второй аргумент в виде строки (очевидно), произойдет сбой ядра.
Могу ли я получить содержимое аргументов из сохраненных регистров в структуре pt_regs? И можете ли вы объяснить мне, почему это не работает?
Я использую Fedora linux: вывод uname:
Linux 6.11.10-200.fc40.x86_64 #1 SMP PREEMPT_DYNAMIC Sat Nov 23 00:53:13 UTC 2024 x86_64 GNU/Linux
Код, который я использовал:
/*
* syscall-steal.c
*
* System call "stealing" sample.
*
* Disables page protection at a processor level by changing the 16th bit
* in the cr0 register (could be Intel specific).
*/
#include
#include
#include
#include /* which will have params */
#include /* The list of system calls */
#include /* For current_uid() */
#include /* For __kuid_val() */
#include
/* For the current (process) structure, we need this to know who the
* current user is.
*/
#include
#include
/* If you have tried to use the syscall table to intercept syscalls and it
* doesn't work, you can try to use Kprobes to intercept syscalls.
* Set USE_KPROBES_PRE_HANDLER_BEFORE_SYSCALL to 1 to register a pre-handler
* before the syscall.
*/
#include
#define MAX_FILENAME_SIZE 1024
/* UID we want to spy on - will be filled from the command line. */
static uid_t uid = -1;
module_param(uid, int, 0644);
/*
* rdi: 1st argument (saved in regs->di?)
* rsi: 2nd argument (saved in regs->si?)
* rdx: 3th argument (saved in regs->dx?)
*
* __x64_sys_openat(int dfd, const char *path, struct open_how *how)
* dfd => rdi
* path => rsi
* how => rdx
*
*/
#define VALID_ADDRESS(desc, name) pr_info("%s [%s]: 0x%lX (%ld) valid %d\n", #desc, #name, regs->name, regs->name, virt_addr_valid(regs->name));
static int openat_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
char filename[MAX_FILENAME_SIZE];
if (__kuid_val(current_uid()) != uid) {
return 0;
}
strcpy(filename, "No file");
pr_info("openat called by %d\n", uid);
VALID_ADDRESS("pre 1st arg dfd :", di);
VALID_ADDRESS("pre 2nd arg *path:", si);
VALID_ADDRESS("pre 3th arg *how :", dx);
if(copy_from_user(filename, (void*)regs->si, MAX_FILENAME_SIZE-1)) {
pr_info("copy user data failed\n");
}
pr_info("Opening file: %s\n", filename);
//dump_stack();
return 0;
}
static struct kprobe openat_kprobe = {
.symbol_name = "__x64_sys_openat",
.pre_handler = openat_pre_handler,
};
static int __init syscall_steal_start(void)
{
pr_info("Using kprobes\n");
int err;
err = register_kprobe(&openat_kprobe);
if (err) {
pr_err("register_kprobe() on openat failed: %d\n", err);
}
return err;
pr_info("Spying on UID:%d\n", uid);
return err;
}
static void __exit syscall_steal_end(void)
{
unregister_kprobe(&openat_kprobe);
msleep(500);
}
module_init(syscall_steal_start);
module_exit(syscall_steal_end);
MODULE_LICENSE("GPL");
Подробнее здесь: [url]https://stackoverflow.com/questions/79315713/how-to-get-arguments-of-linux-kernel-functions-with-kprobe[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия