Czy ktoś debuguje moją aplikację?
Z różnych powodów, czasem nie chcemy, aby ktoś przyglądał się naszej aplikacji w trakcie jej działania. Pomińmy jednak na chwilę te powody i skupmy się na samym wykrywaniu debuggera…
Najprostszą metodą sprawdzenia w systemie Windows, czy nasza aplikacja jest aktualnie uruchomiona w jego kontekście lub jest on podłączony można wykonać poprzez wywołanie funkcji:
IsDebuggerPresent()
z WinAPI. Jednakże sprytny debugger może ją przesłonić i zawsze zwracać, że nie.
Informację tę zatem wyciągniemy samemu, “ręcznie” z bloku informacji o wątku (Thread Information Block – TIB). Pod indeksem 0x30 znajduje się wskaźnik na strukturę opisującą debugger. Drugi bajt tej struktury opisuje status tego, czego szukamy. Ponadto wartość ta jest dynamicznie uaktualniana, gdy tylko coś dzieje się z naszym procesem. Przykład implementacji funkcji w C, która pobierze dla nas tę wartość przestawiam poniżej.
int IsSuperDebuggerPresent()
{
int result;
__asm
{
/* get the Thread Information Block (TIB) pointer */
mov eax, fs:[18h]
/* 0x30 byte points to the debugger structure: */
mov eax, dword ptr [eax + 0x30]
/* then second word indicates if the process is under debugging: */
movzx eax, byte ptr [eax + 2]
mov result, eax
}
return result;
}
Inną metodą pozwalającą sprawdzić, czy nic nie dzieje się wokół naszej aplikacji jest również sprawdzanie licznika instrukcji RTDSC (Time Stamp Counter). W swoim kodzie możemy oszacować ilość ticków procesora, która mija przy wykonywaniu pewnych, zabezpieczanych bloków instrukcji. Następnie porównywać je ze statystykami prowadzonymi wśród całego kodu. Tutaj jednak pojawiają się pytania – jak zachowywać się i w środowiskach wielowątkowych i wieloprocesorowych, gdzie wielkości te nie dają się łatwo przewidzieć i mogą zmieniać się w czasie…