Hot Patching
Je surfais tranquillement sur le net, regardant les news de la journée sans grand intérêt, jusqu’a je tombe sur un post, faisant référence à du hot pachting, Gruuuut kesako ??? Je préfère vous décevoir, cela ne consiste pas à patcher votre OS avec une strip-teaseuse Anyway, si parfois vous trainez sous olly, vous avez sans doute remarqué que certaines fonctions de Windows commençaient avec un mov edi,edi, évidemment l’instruction ne fait pas grand chose d’utile et comme moi vous vous êtes surement dit que ca devait être une facétie de MS. Par exemple, si on prend la fonction RtlEqualString exportée par NTDLL, son prologue est :
lkd> u RtlEqualString nt!RtlEqualString: 8050369a 8bff mov edi,edi 8050369c 55 push ebp 8050369d 8bec mov ebp,esp 8050369f 8b4d08 mov ecx,dword ptr [ebp+8] 805036a2 8b550c mov edx,dword ptr [ebp+0Ch] 805036a5 0fb701 movzx eax,word ptr [ecx]
On peut voir que la première instruction est un mov edi, edi dont on ne voit pas vraiment l’intérêt, du moins pour l’instant :p
Dans le cas ou nous voulons patché cette fonction par un inline hook, c’est à dire en remplaçant les 5 premiers bytes par un long jmp il nous avant de patché, sauvegardé ces bytes pour pourvoir plus tard appeler la fonction de façon normale. Dans le cas présent si on regarde juste avant le prologue de la fonction on peut voir :
lkd> u RtlEqualString-7 nt!CcScheduleReadAhead+0xde: 80503693 ebc4 jmp nt!CcScheduleReadAhead+0x102 (80503659) 80503695 90 nop 80503696 90 nop 80503697 90 nop 80503698 90 nop 80503699 90 nop nt!RtlEqualString: 8050369a 8bff mov edi,edi 8050369c 55 push ebp
Hoho, 5 nop qui s’ennuient dans leurs coins et qui ne seront jamais exécuté. L’astuce consiste donc à savoir qu’un short jmp prend 2 bytes et qu’en patchant le mov edi, edi avec un short jmp on peut sauter à +- 127 bytes de la position courante. Je vous laissez deviner la suite, si on place un long jmp (5 bytes) vers notre fonction de hook au niveau des nop et qu’on fasse sauter notre short jmp sur ce long jmp, SPROUIK on un inline hook super propre qui ne nécessite plus de sauvegardé les instructions du prologue, un hot pachting.
Alors maintenant, étant curieux, je me suis codé un petit tool rapidement qui énumère les fonctions pouvant supporter le hot pachting. J’ai testé mon code sur les fonctions exportées de ntdll, et environ la moitié d’entre elles supportent le hot pachting, voici la liste :
http://ivanlef0u.fr/repo/hot_patching.txt
J’en profite en même pour vous donner le code du petit scanner :
#include <windows.h> #include <stdio.h> #pragma comment(linker, "/nodefaultlib:libc.lib") #pragma comment(linker, "/entry:\"main\"") #pragma comment (lib, "ntdll.lib") #pragma comment (lib, "kernel32.lib") #pragma comment (lib, "msvcrt.lib") int main() { ULONG i,j; HANDLE hLib; PCHAR FctName, FctProlog; PULONG RvaNameTab; PIMAGE_DOS_HEADER pDOS; PIMAGE_NT_HEADERS32 pNT; PIMAGE_EXPORT_DIRECTORY pExp; hLib=GetModuleHandle("ntdll.dll"); pDOS=(PIMAGE_DOS_HEADER)hLib; pNT=(PIMAGE_NT_HEADERS32)((PUCHAR)pDOS->e_lfanew+(ULONG)hLib); pExp=(PIMAGE_EXPORT_DIRECTORY)((PUCHAR)pNT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress+(ULONG)hLib); RvaNameTab=(PULONG)((PUCHAR)pExp->AddressOfNames+(ULONG)hLib); for(i=0; i<pExp->NumberOfNames; i++) { FctName=(PCHAR)(*(RvaNameTab+i)+(ULONG)hLib); FctProlog=(PCHAR)GetProcAddress((HMODULE)hLib, FctName); //scan les 5 premiers bytes avant le prologe de la fct for(j=0; j<5; j++) { if(*(PUCHAR)(FctProlog-5+j)!=(UCHAR)0x90) break; } //si on a pas 5 NOP, on passe à la fct suivante if(j!=5) continue; //si pas de mov edi, edi if(*(PUSHORT)FctProlog!=0xFF8B) //mov edi, edi continue; printf("%s : 0x%x : OKAY for hot patching\n", FctName, FctProlog); } return 0; }
Et voici quelques liens parlant de cette technique :
http://kernelmustard.com/2007/06/13/whence-came-function-hooking/
http://msmvps.com/blogs/kernelmustard/archive/2005/04/25/44413.aspx
http://www.openrce.org/articles/full_view/22
http://www.apihooks.com/EliCZ/export.htm
10 comments juin 14th, 2007