VBox,Virtual PC,VMware i IDT Hooking
Będzie to dość stosunkowo lightowy post o “anomaliach”, które wystąpiły podczas moich testów z hookowaniem tablicy IDT pod wymienionymi w tytule post’a wirtualnymi maszynami. Dlaczego lightowy? Ponieważ żeby ustalić detale związane z sytuacjami, które później zaprezentuje, wymagało by to spooorego research’u odnośnie sposobu działania wewnętrznego mechanizmu poszczególnych wirtualnych maszyn (tak sądzę
).
Także proponuje traktować niniejszy post jako ciekawostkę/(wektor do badań) niż jako rezultat głębszego researchu.
Cała historia zaczyna się od momentu kiedy chciałem przetestować najprostszy w życiu hook na procedure KiSystemService poprzez modyfikacje jej adresu w tablicy IDT. Oto fragment kodu zakładający hook:
void IDTHook()
{
IDTINFO idtInfo;
IDTENTRY *idt_entries;
IDTENTRY *int2e_entry;
DbgPrint("[+] IDTHook");
//pobranie IDTINFO
idtInfo = getIDTInfo();
//pobranie *tablicy IDT
idt_entries = getIDTEntries(&idtInfo);
//zapisanie oryginalnego IDTENTRY_2E
orgIDTEntry_2e = idt_entries[KiSystemService_INDEX];
//zapisanie DWORD'a na potrzeby funkcji hookujacej
orgKiSystemService = MAKELONG(orgIDTEntry_2e.LowOffset,orgIDTEntry_2e.HiOffset);
__asm cli;//wylacz obsluge maskowalnych przerwan
idt_entries[KiSystemService_INDEX].LowOffset = (unsigned short)(&MySystemService);
idt_entries[KiSystemService_INDEX].HiOffset = (unsigned short)(((unsigned long)(&MySystemService))<<16);
__asm lidt idtInfo;
__asm sti;//wlacz obsluge maskowalnych przerwan
}
‘kod MySystemService przepisany w calosci z „Subverting Windows Kernel”‘
__declspec(naked) MySystemService()
{
__asm{
pushad
pushfd
push fs
mov bx,0x30
mov fs,bx
push ds
push es
//do something
//Finish:
pop es
pop ds
pop fs
popfd
popad
jmp orgKiSystemService;
}
}
/* __asm { sysenter VPC } */
Bez większego wachania i namysłow postanowiłem przetestować wynikowy driver pod Virtual PC(ver. 6.0.192.0 + additions)[OS: Windows XP SP3 Eng], z którego zwykłem korzystać. Ku mojemu zaskoczeniu (bo liczyłem co najwyżej na BSOD’a
) przy próbie założenia hook’a wystąpił wewnętrzny błąd vpc:
Hym…dziwna kwestia pomyślałem. Między czasie przypomniałem sobie, że przecież system może w ogóle nie korzystać z IDT jeżeli posiadany przez nas procesor dysponuje obsługą instrukcji sysenter/syscall. Rzut okiem pod vpc na wywolanie jednego z najbardziej popularnych native api:
ZwOpenFile, rozwiało moje wątpliwości:
Sam error „wywalony” przez vpc wskazywał na to, że to nic stricte związanego z samym systemem, a raczej z vm, a teraz dodatkowo wiemy, że sens zakładania hook’a na IDT pod vpc jest raczej nie wielki (przez co POWINIEN być nie szkodliwy)
. Postanowiłem wykonać test jeszcze raz po odinstalowaniu z systemu additions. Tu ponownie zaskoczenie, bo system zachował się tak jak powinien, czyli:
udało się zainstalować hook’a
oraz żaden z breakpoint’ów(po dłuższej chwili), które założyłem na MySystemService nie został wywołany.
Zobaczmy teraz jak się sprawy maja pod VirtualBoxem.
/* __asm { INT VirtualBox } */
Ver. 3.0.8 r53138 + additions
OS pozostaje bez zmian pod każdą maszynką.
Pierwszą kwestią, którą tutaj sprawdziłem jest sposób przejścia procesu z r3 do r0.
Wyśmienicie! Jak widać na załączonym obrazku pod VBoxem możemy śmiało testować hooki na IDT. Tak mi się bynajmniej wydawało…
Ładuje driver,przekazuje odpowiedni IOCL_code do moje driver’a, który wywoła instalacje hook’a i … :
cała akcja kończy się nie oczekiwanem crash’em VBox’a.
Długo nie myśląc odinstalowalem dodatki z systemu i ponowiłem próbę.
Udało się!Instalacja hook’a przebiegła bez problemowo, ale podczas paru kolejnych prób zdarzał mi się BSOD’nąć system z komunikatem, który jedno znacznie wskazywał, że nastąpiła próba dostępu do stronnicowanego obszaru pamięci.Windbg wskazywał następującą linijke kodu jako przyczyne zła:
idt_entries[KiSystemService_INDEX].LowOffset = (unsigned short)(&amp;MySystemService);
Eeee delikatnie dziwne,,,IDT w obszarze stronnicowanej pamięci o_0?
Delikatnie zmodyfikowałem więc kod instalujący hook, po przez zmapowanie tablicy IDT pod NIEstronnicowany obszar pamieci. Kod prezentuje się teraz następująco:
void IDTHook()
{
IDTINFO idtInfo;
IDTENTRY *idt_entries;
IDTENTRY *int2e_entry;
DbgPrint("[+] IDTHook");
//pobranie IDTINFO
idtInfo = getIDTInfo();
//pobranie *tablicy IDT
idt_entries = getIDTEntries(&idtInfo);
//try to map it
idt_entries = mapMemory(idt_entries,idtInfo.IDTLimit);// NOWA LINIA
//update idtinfo struct
idtInfo.HiIDTbase = HIWORD(idt_entries);
idtInfo.LowIDTbase = LOWORD(idt_entries);
//zapisanie oryginalnego IDTENTRY_2E
orgIDTEntry_2e = idt_entries[KiSystemService_INDEX];
//zapisanie DWORD'a na potrzeby funkcji hookujacej
orgKiSystemService = MAKELONG(orgIDTEntry_2e.LowOffset,orgIDTEntry_2e.HiOffset);
__asm cli;//wylacz obsluge maskowalnych przerwan
idt_entries[KiSystemService_INDEX].LowOffset = (unsigned short)(&amp;MySystemService);
idt_entries[KiSystemService_INDEX].HiOffset = (unsigned short)(((unsigned long)(&MySystemService))>>16);
__asm lidt idtInfo;
__asm sti;//wlacz obsluge maskowalnych przerwan
}
Ten prosty zabieg wyeliminował pojawianie się BSOD’ów.
/* __asm { VMware sysenter } */
VMware Workstation
6.5.3 build-185404
Rzut oka na przejście r3 – > r0:

Jak widać użyty jest tu sysenter. Nie będę się rozpisywał przy vmware i od razu powiem, że instalacja hooka przebiega tutaj bez problemowo czy to z zainstalowanymi dodatkami czy bez.
Na podsumowanie sporządziłem następującą tabelkę:
Jak zwykle komentarze i wszelkiego rodzaju sugestie mile widziane
.