Адрес таблицы системных вызовов (Как узнать адресс таблицы системных вызовов)

Взгляд изнутри

Модератор: Модераторы разделов

Ответить
Аватара пользователя
netelis
Сообщения: 95
ОС: Debian Wheezy i686
Контактная информация:

Адрес таблицы системных вызовов

Сообщение netelis »

Как узнать адресс таблицы системных вызовов в ядре linux-2.6.32 или в самом новом известном вам ядре? Только не говорите что через /boot/System.map. Вобщем эта функция основана на нахождении таблицы системных вызовов по поиску экспортируемой функции sys_close в секции сегмента данных выдаёт что адресс 0. Раньше ядром экспортировалась структура init_mm типа struct_mm сейчас она не экспортируется и старая процедура не подходит.

Код: Выделить всё

void find_sys_call_table(void)
{
  unsigned long *ptr;
unsigned long arr[4];
int i;
ptr=(unsigned long *)((current->mm->end_code + 4) & 0xfffffffc);

        while((unsigned long)ptr < (unsigned long)current->mm->end_data)
        {
                if (*ptr == (unsigned long *)sys_close)
                {
                       for(i=0;i<4;i++)
                        {
                                arr[i]=*(ptr+i);
                                arr[i]=(arr[i] >> 16) & 0x0000ffff;
                        }
                        if(arr[0] != arr[2] || arr[1] != arr[3])
                        {
                                sys_call_table=(ptr - __NR_close);
                                break;
                        }
                }
                ptr++;
        }
        printk(KERN_INFO"sys_call_table base found at: %x\n",sys_call_table);
};

Пробую перехватить sys_close. Так как вызов sys_close экспортируется то его легко перехватить, то почему не работает мой код перехвата close на ядре linux-2.6.32

Код: Выделить всё

char old_commands[COMMANDS_COUNT];
int sys_close(int fd);
int my_close(int fd){
return 0;
};
int old_close(int fd);
static int mod2_init(void){
unsigned long *Addr=sys_close;
memcpy(old_commands, (void *)sys_close, COMMANDS_COUNT);
printk(KERN_INFO"sys_close address: %x
",(unsigned long*) Addr);
Addr=my_close;
sys_close=Addr;
return -1;
};

Пишет /root/mod2/mod2.c:65: error: lvalue required as left operand of assignment.
У меня есть ещё одна процедура нахождения адресса этой таблицы, но он тоже не работает основан на поиске опкода команды перехода к таблице

Код: Выделить всё

phys_addr_t search_sct_address( void )
{
    u_char *p;
    uint push1,push2;
    void  *start_addr;
    struct idtr   idtr;          //таблица дескрипторов прерываний
    struct gate *igd;          //дескриптор прерывания
    char    sc_asm[128];
    asm("sidt %0" : "=m" (idtr));    //получили таблицу дескрипторов прерываний
    igd=(void*)idtr.base+(8*0x80);  //берем дескриптор для system_call
    //start_addr = gate_offset(igd);  //адресс обработчика system_call
    start_addr = (igd->off2 << 16) | igd->off1;    //адресс обработчика system_call
    //теперь тупо ищем опкод call
        printk(KERN_INFO"idt80: flags=%X sel=%X off=%X\n",
                (unsigned)igd->flags,(unsigned)igd->sel,sys_call_table);
p=(u_char* )memmem( sc_asm, 100,"\xff\x14\x85", 3 );
    if (p) { //если нашли
        p+=3;
        return *(phys_addr_t *)p;
    } else { //если не нашли
        return 0;
    }
};

И ещё один через MSR и тоже не работает

Код: Выделить всё

phys_addr_t search_sct_address2( void )
{
    u_char *p=NULL;
    void *start_addr=NULL;
#ifdef CONFIG_X86_64
    start_addr=(void*)native_read_msr(MSR_IA32_SYSENTER_EIP);
#else
    {
    u32 rh,rl;
    rh=rl=0;
    rdmsr( MSR_IA32_SYSENTER_EIP , rl, rh );
    start_addr=(void*)rl;
    }
#endif
    if(start_addr)//начиная с адреса обработчика sysenter
    {
        p =(u_char*)memmem(start_addr, 150, "\xff\x14\x85",3);
        if (p) { //если нашли
            p+=3;
            return *(phys_addr_t *)p;
        }
    }

    return 0;
}

Оба последних используют функцию поиска опкода в памяти memmem описана тут Опкоды.
Спасибо сказали:
чудо
Сообщения: 11

Re: Адрес таблицы системных вызовов

Сообщение чудо »

Чтобы понять, что ты делаешь, надо б поразбираться.
1. если есть в ОС( в OpenSuse лежит прямо в /boot) vmlinux. Если нету, то надо ручками пересобрать ядро.
2. дебажим с помощью gdb наш vmlinux.
Ищешь функцию syscall_call ( посмотри что там делается то =)) ) понял , что искать то надо ;)
с помощью того же gdb сам поймешь, какой у тебя опкод ( а он именно как я и писал). У тебя какова разрядность ? эмуляция 32, 64 битный режим или вообще 32 бита? от этого зависит то, что ты там будешь искать. Плюс диапазоны, в которых ищется опкод могут меняться. тюнингуй. сверяйся по /proc/kallsyms и т.д. и т.п.
Есть еще lookup_symbol_name()....
Все что угодно. У меня все замечательно работает, тренируйся, разбирайся
Спасибо сказали:
Аватара пользователя
netelis
Сообщения: 95
ОС: Debian Wheezy i686
Контактная информация:

Re: Адрес таблицы системных вызовов

Сообщение netelis »

Не может найти опкоды
dmesg
[ 1579.254623] get_syscall: Hi, you fucking linux!
[ 1579.254629] get_syscall: function:get_syscall_table_ia32-L248: idtr base at c079c000
[ 1579.254634] get_syscall: function:get_syscall_table_ia32-L264: sys_call_off at c0850068
[ 1579.254638] opcode not found, meats that we cannot find sys_call_table.
Спасибо сказали:
Аватара пользователя
Stauffenberg
Сообщения: 2042
Статус: ☮ PEACE ☮
ОС: открытая и свободная

Re: Адрес таблицы системных вызовов

Сообщение Stauffenberg »

чудо писал(а):
12.01.2010 23:49
Чтобы понять, что ты делаешь, надо б поразбираться.
1. если есть в ОС( в OpenSuse лежит прямо в /boot) vmlinux. Если нету, то надо ручками пересобрать ядро.
2. дебажим с помощью gdb наш vmlinux.

Я так понял, что netelis хочет, чтобы это работало на автомате.

чудо писал(а):
12.01.2010 23:49
с помощью того же gdb сам поймешь, какой у тебя опкод ( а он именно как я и писал). У тебя какова разрядность ? эмуляция 32, 64 битный режим или вообще 32 бита? от этого зависит то, что ты там будешь искать.

Разве опкод звисит от разрядности?
К примеру ffffffff8020c5bb и 8020c5bb.
Хотя да, конечно же зависит (:

чудо писал(а):
12.01.2010 23:49
У меня все замечательно работает, тренируйся, разбирайся

Дык... расскажи поподробней.
Labor omnia vincit

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.” (Brian Kernighan)
Спасибо сказали:
Ответить