Coding with Titans

so breaking things happens constantly, but never on purpose

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…