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
}
&#91;/sourcecode&#93;
‘kod MySystemService przepisany w calosci z „Subverting Windows Kernel”‘
&#91;sourcecode language="cpp"&#93;
__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;
}
}
&#91;/sourcecode&#93;
&#91;sourcecode language="cpp"&#93;
/* __asm { sysenter VPC } */
&#91;/sourcecode&#93;
Bez większego wachania i namysłow postanowiłem przetestować wynikowy driver pod <strong>Virtual PC(ver. 6.0.192.0 + additions)[OS: Windows XP SP3 Eng]</strong>, z którego zwykłem korzystać. Ku mojemu zaskoczeniu (bo liczyłem co najwyżej na <strong>BSOD’a</strong> :P) przy próbie założenia hook’a wystąpił wewnętrzny błąd vpc:
<img src="http://www.icewall.pl/wp-content/uploads/2009/10/vpc_crash_error1.JPG" alt="vpc_crash_error" title="vpc_crash_error" width="827" height="452" class="alignnone size-full wp-image-297" />
Hym...dziwna kwestia pomyślałem. Między czasie przypomniałem sobie, że przecież system może w ogóle nie korzystać z <strong>IDT</strong> jeżeli posiadany przez nas procesor dysponuje obsługą instrukcji <strong>sysenter/syscall</strong>. Rzut okiem pod vpc na wywolanie jednego z najbardziej popularnych <strong>native api:
ZwOpenFile</strong>, rozwiało moje wątpliwości:
<img src="http://www.icewall.pl/wp-content/uploads/2009/10/vpc_syscalls_handler.JPG" alt="vpc_syscalls_handler" title="vpc_syscalls_handler" width="779" height="144" class="alignnone size-full wp-image-287" />
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 <strong>(przez co POWINIEN być nie szkodliwy)</strong> ;). 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.
vbox_syscalls_handler
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 … :
vbox_crash
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(&amp;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)(&amp;MySystemService))&gt;&gt;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:
vmware_syscalls_handler
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ę:
table
Jak zwykle komentarze i wszelkiego rodzaju sugestie mile widziane ;).It’s gonna be quite light version of post about “anomaly” which I had pleasure to notice during tests of IDT hooking under virtual machines mentioned in this post title. Why light? Because in order to present all details related with cases that I’m going to show in letter part of post, it would required a deeply research regarding to internal manner of work each virtual machine
( I guess so :P). My suggestion is to treat this post like a curiosity/(vector to research) and not like a result of deeply research.
Entire story begins from the moment when I decided to test the simplest hook on KiSystemService procedure through modification its address in IDT table. It’s a piece of code responsible of hook installation:

void IDTHook()
{
IDTINFO idtInfo;
IDTENTRY *idt_entries;
IDTENTRY *int2e_entry;
DbgPrint([+] IDTHook);
//pobranie IDTINFO
idtInfo = getIDTInfo();
//pobranie *tablicy IDT
idt_entries = getIDTEntries(&amp;amp;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)(&amp;MySystemService);
idt_entries[KiSystemService_INDEX].HiOffset  = (unsigned short)(((unsigned long)(&amp;amp;MySystemService))&lt;&lt;16);
__asm lidt idtInfo;
__asm sti;//wlacz obsluge maskowalnych przerwan
}

‘code MySystemService has been rewritten from „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 } */

Without bigger doubts and not necessary thinking I decided to test obtained driver under
Virtual PC(ver. 6.0.192.0 + additions)[OS: Windows XP SP3 Eng], which I mostly used to use. To my great surprise (because I counted on BSOD:P) during attempt to hook installation, occurred internal VPC error:
vpc_crash_error
Hymm…strange issue I thought. Meanwhile I remind to myself that operation system doesn’t need to use IDT table if our processor supports sysenter/syscall instruction. Eye throw under vpc on call to one of mostly used native api: ZwOpenFile, dispelled my doubts:
vpc_syscalls_handler
Error “triggered” by VPC pointed that it’s not strict related problem with OS, rather with vm, and now additionally we know that sense of hook installation on IDT under VPC isn’t too big(by what should be harmless) ;). I decided to perform test again after uninstallation additions from system. Another surprise here, system acted like it should act, that is:
– hook have been installed successfully
and neither of breakpoints (after quite long time), which I had set on MySystemService wasn’t triggered. We will see now how to cases look under VirtualBox.

/* __asm { INT VirtualBox } */

Ver. 3.0.8 r53138 + additions
OS stays without changes under each vm.

First issue which I have checked under this vm is manner on what process steps from r3 to r0.
vbox_syscalls_handler
Delicious! Like you can see on attached screenshot without any doubts we can test hooks on IDT. It seemed as such to me …
I’m loading driver ,I’m passing proper IOCTL code to my driver which is going to trigger hook installation and … :
vbox_crash
entire action is ending with unexpected VBox crash.
Don’t wondering too much I have uninstalled additions from system and I repeated test. Success! Hook installation have been made without any problems, but after couple another attempts I’ve had situations where system crashed with BSOD unambiguously saying, that occurred access attempt to paged memory region. Windbg was pointing following line of code as source of all evil:

idt_entries[KiSystemService_INDEX].LowOffset = (unsigned short)(&amp;amp;MySystemService);

Hymm…a little strange. IDT in paged memory region o_0 ?
I have modified a little source code to eliminate this problem by mapping IDT table under NON-PAGED memory area. Code presents now in the following way :

void IDTHook()
{
IDTINFO idtInfo;
IDTENTRY *idt_entries;
IDTENTRY *int2e_entry;
DbgPrint("[+] IDTHook");
//pobranie IDTINFO
idtInfo = getIDTInfo();
//pobranie *tablicy IDT
idt_entries = getIDTEntries(&amp;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;amp;MySystemService);
idt_entries[KiSystemService_INDEX].HiOffset  = (unsigned short)(((unsigned long)(&amp;MySystemService))&gt;&gt;16);
__asm lidt idtInfo;
__asm sti;//wlacz obsluge maskowalnych przerwan
}

This simple “patch” eliminated occurrence of BSOD’s.

/* __asm { VMware sysenter } */

VMware Workstation
6.5.3 build-185404

Quick look on transition r3 – > r0:
vmware_syscalls_handler
As we can see sysenter has been used here. I won’t dwell on vmware and at the beginning I’m going to say that there is no problems with hook installation, with or without installed additions in system.
As summary I prepared the following table:
table
Like always comments and any kind of suggestions are welcome ;).

This entry was posted in Analiza and tagged , , , , , , , . Bookmark the permalink.

4 Responses to VBox,Virtual PC,VMware i IDT Hooking

  1. pi3 says:

    Moze jakis 0day? :>

  2. Icewall says:

    @pi3
    Stosując powściągliwość emocjonalną nazwę to poprostu usterką 😛

  3. Gynvael says:

    Thx za tabelkę, przyda się ;>
    Jestem ciekaw na czym bug polega głębiej, i czy można go ztriggerować z user mode (np wysyłając jakieś przerwanie).

  4. Icewall says:

    @Gynvael
    n/p ; )
    Mhmm trzeba będzie przysiąść i zbadać ;).

Comments are closed.