Archive for mars 8th, 2007

MyAPITracer

Dernièrement j’ai consacré mon temps à coder un petit tool pour me simplifier la vie, il s’agit d’un traceur d’API ring 3 utilisant les symboles de debug pour récupérer des informations sur les noms des fonctions utilisées par le programme et leurs arguments. L’idée est de mettre sur le prologue de chacunes des fonctions exportées par les DLL un breakpoint (int 3), de lancer le process puis de gérer les exceptions, si on tombe sur une EXCEPTION_DEBUG_EVENT alors on affiche le nom de la fonction qui la généré et on relance le thread. Dans la théorie ca parait simple après c’est un peu plus compliqué, disons que avoir un tool complètement opérationnel va me demander pas mal de taff et que pour l’instant j’arrive à le faire tourner sur des programmes assez basiques.


Le mieux est de montrer ce tool balance pour l’instant. Le code qui sera utilisé est celui-ci :

//systeminfo.c
#include <windows.h>
#include <stdio.h>

int main(int argc, char * argv[])
{
SYSTEM_INFO SystemInfo;

GetSystemInfo(&SystemInfo);

printf("lpMinimumApplicationAddress : 0x%xn", SystemInfo.lpMinimumApplicationAddress);
printf("lpMaximumApplicationAddress : 0x%xn", SystemInfo.lpMaximumApplicationAddress);

return 0;
}

Il permet d’obtenir les adresses hautes et basses du Userland, on obtient comme adresse minumum 0×10000 et comme adresse max 0x7ffeffff. Le binaire à été compilé avec le flag /DEBUG et le linker nous à aussi généré un joli .pdb contenant les informations de debug de notre programme.

Maitenant je lance mon petit tool dessus :

****STARTING DEBUGEE****
EntryPoint : 0x402337
Number of modules: 3
Base : 0x7c800000
NumberOfFunctions : 949
NumberOfNames : 949
****STARTING LOGGING****
Call From : 0x40235d : systeminfo!mainCRTStartup+0x26
0x7c8111da : kernel32!GetVersion

Call From : 0x403938 : systeminfo!_heap_init+0x11
0x7c812bb6 : kernel32!HeapCreate

Call From : 0x403fe2 : systeminfo!_mtinitlocks+0x9
0x7c809ef1 : kernel32!InitializeCriticalSection

Call From : 0x403fea : systeminfo!_mtinitlocks+0x11
0x7c809ef1 : kernel32!InitializeCriticalSection

Call From : 0x403ff2 : systeminfo!_mtinitlocks+0x19
0x7c809ef1 : kernel32!InitializeCriticalSection

Call From : 0x403ffa : systeminfo!_mtinitlocks+0x21
0x7c809ef1 : kernel32!InitializeCriticalSection

Call From : 0x403795 : systeminfo!_mtinit+0x6
0x7c812d9f : kernel32!TlsAlloc

Call From : 0x4054b5 : systeminfo!__sbh_alloc_new_region+0x76
0x7c809a51 : kernel32!VirtualAlloc

Call From : 0x7c809a64 : kernel32!VirtualAlloc+0x13
0x7c809a72 : kernel32!VirtualAllocEx

Call From : 0x405541 : systeminfo!__sbh_alloc_new_group+0x51
0x7c809a51 : kernel32!VirtualAlloc

Call From : 0x7c809a64 : kernel32!VirtualAlloc+0x13
0x7c809a72 : kernel32!VirtualAllocEx

Call From : 0x4037bd : systeminfo!_mtinit+0x2e
0x7c809bc5 : kernel32!TlsSetValue

Call From : 0x4037ce : systeminfo!_mtinit+0x3f
0x7c809728 : kernel32!GetCurrentThreadId

Call From : 0x4035dd : systeminfo!_ioinit+0x5e
0x7c801eee : kernel32!GetStartupInfoA

Call From : 0x4036eb : systeminfo!_ioinit+0x16c
0x7c812f39 : kernel32!GetStdHandle

Call From : 0x4036f9 : systeminfo!_ioinit+0x17a
0x7c810e51 : kernel32!GetFileType

Call From : 0x7c810e8e : kernel32!GetFileType+0x3d
0x7c81aeaa : kernel32!VerifyConsoleIoHandle

Call From : 0x4036eb : systeminfo!_ioinit+0x16c
0x7c812f39 : kernel32!GetStdHandle

Call From : 0x4036f9 : systeminfo!_ioinit+0x17a
0x7c810e51 : kernel32!GetFileType

Call From : 0x7c810e8e : kernel32!GetFileType+0x3d
0x7c81aeaa : kernel32!VerifyConsoleIoHandle

Call From : 0x4036eb : systeminfo!_ioinit+0x16c
0x7c812f39 : kernel32!GetStdHandle

Call From : 0x4036f9 : systeminfo!_ioinit+0x17a
0x7c810e51 : kernel32!GetFileType

Call From : 0x7c810e8e : kernel32!GetFileType+0x3d
0x7c81aeaa : kernel32!VerifyConsoleIoHandle

Call From : 0x403730 : systeminfo!_ioinit+0x1b1
0x7c80cc97 : kernel32!SetHandleCount

Call From : 0x4023bc : systeminfo!mainCRTStartup+0x85
0x7c812f1d : kernel32!GetCommandLineA

Call From : 0x403464 : systeminfo!__crtGetEnvironmentStringsA+0x17
0x7c812f08 : kernel32!GetEnvironmentStringsW

Call From : 0x4034dc : systeminfo!__crtGetEnvironmentStringsA+0x8f
0x7c80a0d4 : kernel32!WideCharToMultiByte

Call From : 0x4034fe : systeminfo!__crtGetEnvironmentStringsA+0xb1
0x7c80a0d4 : kernel32!WideCharToMultiByte

Call From : 0x40351b : systeminfo!__crtGetEnvironmentStringsA+0xce
0x7c814ae7 : kernel32!FreeEnvironmentStringsW

Call From : 0x4040ab : systeminfo!_lock+0x3d
0x7c809ef1 : kernel32!InitializeCriticalSection

Call From : 0x404653 : systeminfo!_setmbcp+0x13
0x7c809915 : kernel32!GetACP

Call From : 0x404691 : systeminfo!_setmbcp+0x51
0x7c812e76 : kernel32!GetCPInfo

Call From : 0x4048a7 : systeminfo!_setmbcp+0x267
0x7c812e76 : kernel32!GetCPInfo

Call From : 0x406cbe : systeminfo!__crtGetStringTypeA+0x3f
0x7c80a490 : kernel32!GetStringTypeW

Call From : 0x406d44 : systeminfo!__crtGetStringTypeA+0xc5
0x7c809bf8 : kernel32!MultiByteToWideChar

Call From : 0x406d9a : systeminfo!__crtGetStringTypeA+0x11b
0x7c809bf8 : kernel32!MultiByteToWideChar

Call From : 0x406dac : systeminfo!__crtGetStringTypeA+0x12d
0x7c80a490 : kernel32!GetStringTypeW

Call From : 0x406a72 : systeminfo!__crtLCMapStringA+0x42
0x7c80cca8 : kernel32!LCMapStringW

Call From : 0x406b0f : systeminfo!__crtLCMapStringA+0xdf
0x7c809bf8 : kernel32!MultiByteToWideChar

Call From : 0x406b67 : systeminfo!__crtLCMapStringA+0x137
0x7c809bf8 : kernel32!MultiByteToWideChar

Call From : 0x406b7d : systeminfo!__crtLCMapStringA+0x14d
0x7c80cca8 : kernel32!LCMapStringW

Call From : 0x406c18 : systeminfo!__crtLCMapStringA+0x1e8
0x7c80cca8 : kernel32!LCMapStringW

Call From : 0x406c3d : systeminfo!__crtLCMapStringA+0x20d
0x7c80a0d4 : kernel32!WideCharToMultiByte

Call From : 0x406b0f : systeminfo!__crtLCMapStringA+0xdf
0x7c809bf8 : kernel32!MultiByteToWideChar

Call From : 0x406b67 : systeminfo!__crtLCMapStringA+0x137
0x7c809bf8 : kernel32!MultiByteToWideChar

Call From : 0x406b7d : systeminfo!__crtLCMapStringA+0x14d
0x7c80cca8 : kernel32!LCMapStringW

Call From : 0x406c18 : systeminfo!__crtLCMapStringA+0x1e8
0x7c80cca8 : kernel32!LCMapStringW

Call From : 0x406c3d : systeminfo!__crtLCMapStringA+0x20d
0x7c80a0d4 : kernel32!WideCharToMultiByte

Call From : 0x403223 : systeminfo!_setargv+0x23
0x7c80b4cf : kernel32!GetModuleFileNameA

Call From : 0x7c80b508 : kernel32!GetModuleFileNameA+0x39
0x7c80b3d5 : kernel32!GetModuleFileNameW

Call From : 0x4022ba : systeminfo!main+0xa
0x7c812d56 : kernel32!GetSystemInfo

Call From : 0x7c812d3b : kernel32!GetProcessVersion+0x118
0x7c812c23 : kernel32!GetProcessVersion

Call From : 0x4040ab : systeminfo!_lock+0x3d
0x7c809ef1 : kernel32!InitializeCriticalSection

Call From : 0x407554 : systeminfo!_lock_fhandle+0x3d
0x7c809ef1 : kernel32!InitializeCriticalSection

Call From : 0x406149 : systeminfo!_write_lk+0xc7
0x7c810d87 : kernel32!WriteFile

Call From : 0x7c81cf4c : kernel32!WriteConsoleA+0x27
0x7c81cf25 : kernel32!WriteConsoleA

Call From : 0x406149 : systeminfo!_write_lk+0xc7
0x7c810d87 : kernel32!WriteFile

Call From : 0x7c81cf4c : kernel32!WriteConsoleA+0x27
0x7c81cf25 : kernel32!WriteConsoleA

Call From : 0x4040ab : systeminfo!_lock+0x3d
0x7c809ef1 : kernel32!InitializeCriticalSection

Call From : 0x4040ab : systeminfo!_lock+0x3d
0x7c809ef1 : kernel32!InitializeCriticalSection

Call From : 0x4040ab : systeminfo!_lock+0x3d
0x7c809ef1 : kernel32!InitializeCriticalSection

Call From : 0x402f9b : systeminfo!_c_exit+0xac
0x7c81cdda : kernel32!ExitProcess

Process Exited

Remarquez que je ne loggue pas les appels aux fonctions de ntdll. On voit que la CRT (C RunTime) bouffe la majorité du log pour pas dire grand chose d’utile et qu’au final le code se résume en fait à :
Pour la fonction GetSystemInfo:
Call From : 0x4022ba : systeminfo!main+0xa
0x7c812d56 : kernel32!GetSystemInfo
et pour printf:
Call From : 0×406149 : systeminfo!_write_lk+0xc7
0x7c810d87 : kernel32!WriteFile

Call From : 0x7c81cf4c : kernel32!WriteConsoleA+0×27
0x7c81cf25 : kernel32!WriteConsoleA

En fait ce tool se raproche un peu d’un strace sous nux, sauf qu’ici on loggue tous les appels aux API et pas uniquement les appels système.

Alors je sais, vous allez me dire que ce genre d’outils existe déjà, certes c’est vrai, mais combien utilisent les symboles de débuggage pour obtenir les noms des fonctions ? La plupart de ceux que j’ai vu comme le logger.exe des Debugging Tools for Windows utilisent une database à coté pour parser leurs informations. Avec les symboles on est sur d’avoir des infos à la fois sur notre programme (si celui-ci est compilé en debug) et sur les fonctions des DLL.

Développe ce tool commence à me prendre un peu la tête, je releaserais le binaire quand je l’aurais amélioré, par contre je garde les sources pour moi, le code étant tellement crade que même un moine tibétain défoncé au beurre de yack ne pourrait le comprendre.

En attendant voiçi un lien sur un topic d’OpenRCE causant des outils de monitoring pour Win, si jamais vous cherchez un tool du même genre vous y trouverez votre bonheur :
http://www.openrce.org/forums/posts/274

2 comments mars 8th, 2007


Calendar

mars 2007
L Ma Me J V S D
« fév   avr »
 1234
567891011
12131415161718
19202122232425
262728293031  

Posts by Month

Posts by Category