# [C] Debugger erkennen - eine Funktion tut's, die andere nicht?!



## boss3D (7. Dezember 2013)

Hallo!

Folgende Aufgabenstellung:

Implementieren Sie zumindest folgende Anti-Debugging-Mechanismen:
- IsDebuggerPresent()
- Unhandled Exception
- OutputDebugString()
Testen Sie die Ausführung sowohl im Debugger als auch ohne.

Hier meine Lösung:

```
#include <windows.h>
#include <stdio.h>

LONG WINAPI exHandler(PEXCEPTION_POINTERS pExecpPointers) {
    SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)pExecpPointers->ContextRecord->Eax);
    pExecpPointers->ContextRecord->Eip += 2;
    return EXCEPTION_CONTINUE_EXECUTION;
}

int main(void) {
    
    if (IsDebuggerPresent()) {
        MessageBox(NULL, L"Debugger detected by IsDebuggerPresent!", L"Debugger detected", MB_OK);
        exit(0);
    } else {
        MessageBox(NULL, L"No Debugger detected.", L"No Debugger", MB_OK);
    }
    
    DWORD Val = 666;
    SetLastError(Val);
    OutputDebugString(L"anything");
    if (GetLastError() == Val) {
        MessageBox(NULL, L"Debugger detected by OutputDebugString!", L"Debugger detected", MB_OK);
        exit(0);
    } else {
        MessageBox(NULL, L"No Debugger detected.", L"No Debugger detected", MB_OK);
    }

    int flag = 0;
    SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)exHandler);
    __asm {
        xor eax, eax;
        div eax;
    }
    MessageBox(NULL, L"No Debugger detected.", L"No Debugger", MB_OK);

    printf("Hello, world!\n");

    return 0;
}
```
Das Problem:
Führe ich in Visual Studio 2013 "Start Without Debugging" aus, kriege ich trotzdem "Debugger detected by OutputDebugString!".
Führe ich in Visual Studio 2013 "Start Debugging" aus, kriege ich (korrekterweise) "Debugger detected by IsDebuggerPresent!". Danach beendet sich das Programm (wie's sein soll).
^^ Woran könnte das Problem bei OutputDebugString liegen? Ich sehe den Fehler nicht ... 

Danke für baldige Antworten!


----------



## bingo88 (7. Dezember 2013)

Ich habe irgendwo mal gelesen, dass das nur unter XP funktioniert.


----------



## boss3D (7. Dezember 2013)

Es muss irgendwie möglich sein, weil wir im Studium auf Windows 7 PCs arbeiten. Und es passt ja auch schon alles, außer dass OutputDebugString eben genau das "verkehrte" erkennt ...


----------



## Crysis nerd (7. Dezember 2013)

Moment.. worum gehts dir?
Wollt ihr nur einen "normalen netten" Debugger wie gdb und den von VS erkennen oder 
geht es hier um Sicherheitstechnisches, wo man jegliche Art von überwachter Ausführung unterbinden soll?


----------



## boss3D (7. Dezember 2013)

VS ist nur die IDE meiner Wahl. Ich hätte das auch mit allem möglichen anderen schreiben können ...

Es geht darum, eben einen C Code (und später das ganze auch in Assembler) zu schreiben, der die drei genannten Funktionen zur Erkennung eines Debuggers implementiert. Anschließend soll ich das ganze im OllyDbg (unter Windows 2000) manuell umgehen. Und dann das ganze mit Hilfe von Plugins im Debugger umgehen.


----------



## bingo88 (7. Dezember 2013)

boss3D schrieb:


> Es muss irgendwie möglich sein, weil wir im Studium auf Windows 7 PCs arbeiten. Und es passt ja auch schon alles, außer dass OutputDebugString eben genau das "verkehrte" erkennt ...


In Windows 7 verändert OutputDebugString nicht den letzten Error code, das meinte ich. Daher erkennt dein Programm das auch nicht richtig. Unter Windows XP müsste das funktionieren.


----------



## boss3D (8. Dezember 2013)

^^ Achso, hm ... Ich habe jetzt versucht, den Code unter Windows 2000 in OllyDbg zu starten (die .exe), allerdings kommt da gleich ein Error, dass mein Programm keine gültige Win32 Anwenung sei. Weil ich es unter Windows 7 64 erstellt habe? K. A. ... 
Visual Studio 2013 habe ich ja auch in der 32 bit Version (da gibt's ja gar keine 64 bit, oder?) zum Programmieren des Codes verwendet.


----------



## Crysis nerd (8. Dezember 2013)

Visual Studio ist die Entwicklungsumgebung, die es tatsächlich nur in 32bit gibt. Aber das ist egal. Dein Programm ist für die Architektur, für welche es der Compiler compiliert hat. Und den Compiler kannst du oben in VS umstellen (da is so ein Dropdown Menü wo man zwischen x86 und x64 auswählen kann).


----------



## boss3D (8. Dezember 2013)

^^ Kannst du's bitte auf meinem Screenshot markieren, wo genau ich schauen soll?! So finde ich das nicht ...




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.


----------



## Crysis nerd (8. Dezember 2013)

Auf deinem Screenshot isses nich drauf. Was mich wundert. Eventuell liegt es an einer anderen VS Version, aber eigentlich nicht. Es müsste direkt neben Dropdown menü "Debug" sein. Sonst such mal in den Einstellungen zu deinem Projekt.
ABER: Ich hab nie gesagt, dass das der Fehler ist, der dich gerade stört. ollydbg sollte eigentlich auch x64 Code debuggen können oder ähnliches. 
Was du allerdings mit dem Compiler noch bedenken solltest: Wenn du mit dem Standard Visual C++ Compiler in der neusten Version kompilierst, gibts sicher Probleme in Bezug auf Laufzeitbibliotheken. Selbst WinXp wird nurnoch teilweise unterstützt (oder so). Windows 2000 wird echt verdammt schwer.

Aber ich hab nich wirkliche ne Ahnung. Ich geb dir nur ein paar Hinweise woran es liegen könnte.


----------



## bingo88 (8. Dezember 2013)

Das wird sicherlich an der C++ Runtime liegen. Windows 2000 wurde schon von VS2010 nicht mehr unterstützt.


----------



## boss3D (8. Dezember 2013)

^^ Irgendwie muss sich das ganze lösen lassen, sonst würde ja die ganze Übung nicht gehen. Windows 2000 habe ich in einer VM. Da drinnen muss es auch irgendeinen Compiler geben, aber ich habe noch nichts gefunden. Wenn ich den Code aber einfach unter Windows 2000 kompiliere, dann müsste ihn auch der in der VM enthaltene OllyDbg ausführen können ...


----------



## bingo88 (8. Dezember 2013)

Du könntest es mal mit MinGW probieren. Mit Visual Studio geht das AFAIK nur bis VS2008, danach wird Windows 2000 nicht mehr als Plattform unterstützt.


----------



## boss3D (8. Dezember 2013)

Internetzugriff ist für die VM gesperrt, da kriege ich MinGW nicht rein.
(Das downloadbare File ist ja auch nur ein "Starter", der dann während der Installation die Daten herunterladen will)


----------



## bingo88 (9. Dezember 2013)

Kannst du das denn mit MinGW (oder älterem VS) auf nem anderen Rechner kompilieren und das dann in die VM packen?


----------



## boss3D (9. Dezember 2013)

Ich habe jetzt MinGW auf meinem Windows 7 installiert, aber was fange ich dann damit an? Ich habe folgenden Aufruf im Command Prompt probiert: "mingw -std=99 -pedantic -Wall -o filename.exe", aber da kommt nur "'mingw' ist not recognized as an internal or external command, operable program or batch file" ...


----------



## bingo88 (9. Dezember 2013)

Hast du deine PATH Variable denn für MinGW konfiguriert?


----------



## boss3D (9. Dezember 2013)

^^ Nein, ich blicke da gar nicht durch. Die Doku ist auch nicht die geringste Hilfe ... 

[EDIT]
Hab's jetzt doch geschafft, die PATH Variable zu setzen, kommt aber immer noch der gleiche Fehler.

[EDIT2]
Ich pfeif auf die PATH Variable. Ich habe jetzt einfach mein C file in das Vezeichnis von gcc reinkopiert und das ganze dann so aufgerufen. So arbeitet der Compiler zumindest, allerdings kriege ich (neben unzähligen Warnings) folgende Errors:




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



Hier nochmal der Code (nicht Zeilen-zählen, weil ich oben ein paar Kommentare gelöscht habe. Ich habe den Bereich blau markiert, wo die Fehler her sind [Zeile 36 - 38]):

```
#include <windows.h>
#include <stdio.h>

LONG WINAPI exHandler(PEXCEPTION_POINTERS pExecpPointers) {
    SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)pExecpPointers->ContextRecord->Eax);
    pExecpPointers->ContextRecord->Eip += 2;
    return EXCEPTION_CONTINUE_EXECUTION;
}

int main(void) {
    
    if (IsDebuggerPresent()) {
        MessageBox(NULL, L"Debugger detected by IsDebuggerPresent!", L"Debugger detected", MB_OK);
        exit(0);
    } else {
        MessageBox(NULL, L"No Debugger detected.", L"No Debugger", MB_OK);
    }
    
    DWORD Val = 666;
    SetLastError(Val);
    OutputDebugString(L"anything");
    if (GetLastError() == Val) {
        MessageBox(NULL, L"Debugger detected by OutputDebugString!", L"Debugger detected", MB_OK);
        exit(0);
    } else {
        MessageBox(NULL, L"No Debugger detected.", L"No Debugger detected", MB_OK);
    }

    int flag = 0;
    SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)exHandler);
    [COLOR=royalblue][B]__asm {
        xor eax, eax;
        div eax;[/B]    }
    MessageBox(NULL, L"No Debugger detected.", L"No Debugger", MB_OK);

    printf("Hello, world!\n");

    return 0;
}
```
^^ Kann mir bitte jemand helfen, die Errors weg zu kriegen?!


----------



## bingo88 (9. Dezember 2013)

Der inline Assembler sieht in gcc anders aus als in MS, den müsstest du neu schreiben. Kann auch sein, dass du von der Intel Syntax auf die AT&T Syntax wechseln musst, wobei ich da mal irgendwo nen flag gesehen habe, wie man dem gcc die Verwendung der Intel Syntax klarmacht...


----------



## boss3D (9. Dezember 2013)

Ah, danke. Das Umschreiben habe ich geschafft und damit die Errors weggekriegt, aber leider kommt beim Kompilieren keine exe raus?! 
Folgender Befehl: _gcc -std=c99 -pedantic -Wall mal.c -o mal_

```
#include <windows.h>
#include <stdio.h>

LONG WINAPI exHandler(PEXCEPTION_POINTERS pExecpPointers) {
    SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)pExecpPointers->ContextRecord->Eax);
    pExecpPointers->ContextRecord->Eip += 2;
    return EXCEPTION_CONTINUE_EXECUTION;
}

int main(void) {
    
    if (IsDebuggerPresent()) {
        MessageBox(NULL, "Debugger detected by IsDebuggerPresent!", "Debugger detected", MB_OK);
        exit(0);
    } else {
        MessageBox(NULL, "No Debugger detected.", "No Debugger", MB_OK);
    }
    
    DWORD Val = 666;
    SetLastError(Val);
    OutputDebugString("anything");
    if (GetLastError() == Val) {
        MessageBox(NULL, "Debugger detected by OutputDebugString!", "Debugger detected", MB_OK);
        exit(0);
    } else {
        MessageBox(NULL, "No Debugger detected.", "No Debugger detected", MB_OK);
    }

    SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)exHandler);
    asm("xorl %eax, %eax\n\t");
    asm("divl eax");
    MessageBox(NULL, "No Debugger detected.", "No Debugger", MB_OK);

    printf("Hello, world!\n");

    return 0;
}
```
Hier noch die Warnings. 




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



Beim googeln bin ich auf folgendes gestoßen:


> According to the C standard (appendix J.5.10), asm is a common language extension.  In gcc it is disallowed (together with all gcc extensions), if you use a flag like -std=c90, -std=c99 or -ansi.  If you want C99 with gcc extensions, use -std=gnu99 instead.


^^ Scheint dann einfach an meinen Befehlsparametern zu liegen?! 

Ist jetzt aber auch nicht mehr wirklich schlimm. Viel wichtiger wäre mir, eine mal.exe dabei rauszukriegen, die ich dann in die VM reintun und dort mit OllyDbg testen kann! _*Hilfe*_


----------



## bingo88 (9. Dezember 2013)

Dein Inline ASM scheint immer noch falsch zu sein (linker meckert, weil asm() keine bekannte Funktion ist). Also irgendetwas stimmt da noch nicht, eventuell mit den flags? Es gibt wohl auch ein __asm__, aber mit gcc und inline ASM habe ich jetzt auch nur wenig Erfahrung (ich mag die Syntax nicht!)


----------



## boss3D (9. Dezember 2013)

^^ Ich kenne mich leider auch gar nicht damit aus und habe das nötigste *hier* raus gesucht. Laut der dortigen Beschreibung macht es keinen Unterschied, ob man "asm" oder "__asm__" schreibt ... ?

[EDIT]
Durch "__asm" (*Quelle*) konnte ich es jetzt auf folgendes verringern:




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



Aber weiter weiß ich echt nicht. 

[EDIT2]
Ah, war nur ein Syntax Fehler. 
%eax statt nur eax ...

Jetzt habe ich endlich meine mal.exe. Gleich rein damit in die Windows 2000 VM.

[EDIT3]
Im OllyDbg läuft's jetzt auch und beide Erkennungsmethoden melden das richtige. Nur bei der Exception weiß ich nicht so recht, wie ich deren funktionieren überprüfen soll.


----------



## boss3D (10. Dezember 2013)

2 Fragen noch:

1) Kennt jemand Plugins für OllyDbg, mit deren Hilfe ich OutputDebugString und die Exception umgehen kann?
2) Wie kriege ich meinen C Code jetzt noch in Assembler hin (ohne ernsthaft Assembler-programmieren zu können)? Gibt's die Funktionen schon irgendwie in asm geschrieben, sodass ich mir das irgendwie zusammenbasteln könnte?


----------



## bingo88 (10. Dezember 2013)

boss3D schrieb:


> 2 Fragen noch:
> 
> 1) Kennt jemand Plugins für OllyDbg, mit deren Hilfe ich OutputDebugString und die Exception umgehen kann?
> 2) Wie kriege ich meinen C Code jetzt noch in Assembler hin (ohne ernsthaft Assembler-programmieren zu können)? Gibt's die Funktionen schon irgendwie in asm geschrieben, sodass ich mir das irgendwie zusammenbasteln könnte?


 1) Ist mir nicht bekannt
2) Meinst du komplett in Assembler? Welchen Code meinst du genau?


----------



## boss3D (10. Dezember 2013)

Ich soll die Anwendung in C und Assembler schreiben, so die Aufgabenstellung. Den Sinn verstehe ich auch nicht... 

Irgendwie mit "invoke isDebuggerPresent" muss ich anfangen, aber ich habe keine Ahnung, wie das dann mit den ganzen Registern geht.


----------



## bingo88 (10. Dezember 2013)

Na das wird ja ein Spaß 

Du musst dir die Calling Conventions für die Funktionen besorgen. Damit wird festgelegt, wie eine Funktion aufgerufen wird, also wie zum Beispiel die Funktionsparameter übergeben werden und ob der Aufrufer hinterher aufräumen muss. Wenn die Anwendung komplett in Assembler geschrieben werden soll, dann musst du natürlich auch deine Main passend zusammenbauen (Funktionsprolog und -epilog).


----------

