Warning: Use of undefined constant ipaddress - assumed 'ipaddress' (this will throw an Error in a future version of PHP) in /home/www/acp/lib/session.php on line 98

Warning: Use of undefined constant useragent - assumed 'useragent' (this will throw an Error in a future version of PHP) in /home/www/acp/lib/session.php on line 98

Warning: Use of undefined constant request_uri - assumed 'request_uri' (this will throw an Error in a future version of PHP) in /home/www/acp/lib/session.php on line 98

Warning: Cannot modify header information - headers already sent by (output started at /home/www/acp/lib/session.php:98) in /home/www/acp/lib/functions.php on line 82

Warning: Cannot modify header information - headers already sent by (output started at /home/www/acp/lib/session.php:98) in /home/www/acp/lib/functions.php on line 82

Warning: Use of undefined constant postid - assumed 'postid' (this will throw an Error in a future version of PHP) in /home/www/print.php on line 27

Warning: Use of undefined constant postid - assumed 'postid' (this will throw an Error in a future version of PHP) in /home/www/print.php on line 27

Warning: Use of undefined constant postid - assumed 'postid' (this will throw an Error in a future version of PHP) in /home/www/print.php on line 27

Warning: Use of undefined constant postid - assumed 'postid' (this will throw an Error in a future version of PHP) in /home/www/print.php on line 27

Warning: Use of undefined constant postid - assumed 'postid' (this will throw an Error in a future version of PHP) in /home/www/print.php on line 27

Warning: Use of undefined constant postid - assumed 'postid' (this will throw an Error in a future version of PHP) in /home/www/print.php on line 27

Warning: Use of undefined constant postid - assumed 'postid' (this will throw an Error in a future version of PHP) in /home/www/print.php on line 27

Warning: Use of undefined constant postid - assumed 'postid' (this will throw an Error in a future version of PHP) in /home/www/print.php on line 27

Warning: Use of undefined constant postid - assumed 'postid' (this will throw an Error in a future version of PHP) in /home/www/print.php on line 27
Forum www.Kopierschutzsysteme.de - Hier findet Ihr Informationen rund um das Thema Kopierschutz - Druckvorschau: Codeverschleierung - Seite 1

Forum www.Kopierschutzsysteme.de - Hier findet Ihr Informationen rund um das Thema Kopierschutz (http://www.Kopierschutzsysteme.de/index.php)
- Programmierung (http://www.Kopierschutzsysteme.de/board.php?boardid=12)
-- C / C++ (http://www.Kopierschutzsysteme.de/board.php?boardid=19)
--- Codeverschleierung (http://www.Kopierschutzsysteme.de/threadid.php?threadid=94)


Geschrieben von rob am 22.03.2008 um 17:40:

Codeverschleierung

Hallo,

steh vor folgendem Problem:

Ich möchte mein Programm (Visual C++ V6.0) gegen Tracing schützen. Hierfür habe ich schon ein paar Debugger Erkennungen eingebaut. Abgeprüft werden die bekannten Debugger wie SICE, OllyDbg und WinDbg. Nun möchte ich gern ein paar Codeverschleierungs-Routinen integrieren, hab nur keinen Plan wie ich das machen kann.

Wäre für jeden Hinweis dankbar.

Gruß
Robert


Geschrieben von Michael Bauer am 22.03.2008 um 19:26:

Hallo Robert,

willkommen im Forum.

Zuerst mal eine Anmerkung zu Deiner Debugger Erkennung. Da es von OllyDbg auch einige Klons gibt (z.B. Shadow, flyODBG und OllyICE), solltest Du diese auch abfragen. Zusätzlich würde ich vorschlagen, prüf auch noch auf den Syser-Debugger, der wird unter Hackern als Wiederaufstehung der Ring0 Debugger gefeiert, da Softice nicht mehr weiterentwickelt wird.

Nun aber zum eigentlichen Thema.

Du könntest die Codeverschleierung z.B. mittels Anti-Disassembling Makros realisieren. In Visual C++ lässt sich das leicht durch Inline-Assembling machen. Nachfolgend ein Beispiel dazu:

Code ohne Verschleierung:
code:

void Beispiel_Codeverschleierung ()
{
    If (  Check_RegCode() )
    {
         /* RegCode ungültig */
         Goto Exit
     }      
}


Code mit Verschleierung:
code:

#define ANTI_DISASSEMBLING_MACRO() \
    __asm \
    { \
    __asm __emit 0x60 /* pushad */\
    __asm __emit 0xE8 /* call JUMP1 */\
    __asm __emit 0x03 \
    __asm __emit 0x00 \
    __asm __emit 0x00 \
    __asm __emit 0x00 \
    __asm __emit 0xD2 \
    __asm __emit 0xEB /* JUMP4: jmp JUMP5 */\
    __asm __emit 0x0B \
    __asm __emit 0x58 /* JUMP1: pop eax */\
    __asm __emit 0xEB /* jmp JUMP2 */\
    __asm __emit 0x01 \
    __asm __emit 0x48 \
    __asm __emit 0x40 /* JUMP2: inc eax */\
    __asm __emit 0xEB /* jmp JUMP3 */\
    __asm __emit 0x01 \
    __asm __emit 0x35 \
    __asm __emit 0xFF /* JUMP3: jmp eax -> JUMP4 */\
    __asm __emit 0xE0 \
    __asm __emit 0xE7 \
    __asm __emit 0x61 /* JUMP5: popad */\
    }


void Beispiel_Codeverschleierung ()
{
    ANTI_DISASSEMBLING_MACRO(); 
    If (  Check_RegCode() )
    {
         /* RegCode ungültig */
         Goto Exit
     }      
}


Das ANTI_DISASSEMBLING_MACRO fügt folgenden Assemblercode hinzu:
code:

                                  ;..... eigentlicher Code
00000000          60                                           pushad
00000001          e8 03 00 00 00                         call 00000009
00000006          d2 eb                                       shr bl,cl
00000008          0b 58 eb                                   or ebx, [eax-15h]
0000000b          01 48 40                                 add [eax+40h], ecx
0000000e          eb 01                                      jmp 00000011
00000010          35 ff e0 e7 61                          xor eax, 61e7e0ffh
                                  ;..... eigentlicher Code


Aufgrund der Sprunganweisungen mitten in Instruktionen wird der Code sehr unleserlich. Ausgeführt ergibt sich folgender Code:

                                  ;..... eigentlicher Code
00000000          60                                           pushad                        ; Sichert alle Register
00000001          e8 03 00 00 00                         call 00000009               ; Sprung zu der Adresse
00000009          58                                           pop eax                       ; call return Wert in EAX Register = 00000006
0000000A         eb 01                                       jmp 0000000D
0000000D         40                                            inc eax                         ; return Wert um 1 erhöhen
0000000E         eb 01                                       jmp 00000011              ; Sprung
00000011          ff e0                                        jmp eax                       ; Sprung 00000007
00000007          eb 0b                                      jmp 00000014              ; Sprung
00000014          61                                           popad                         ; Register wieder herstellen
                                  ;..... eigentlicher Code



Durch wiederholtes platzieren verschiedenster Anti-Disasembling Makros erhält man eine gute Codeverschleierung.

Natürlich gibt es noch andere Methoden um Code zu verschleiern z.B. Virtuelle Maschine, polymorpher Code oder metamorpher Code, die sind aber wesentlich aufwendiger zu programmieren.

Gruss
Michael


Geschrieben von rob am 24.03.2008 um 12:54:

Wow cool, die Idee mit dem Makros ist genial. Hätte nicht gedacht, dass es so einfach geht.

Die Klons von OllyDbg sind mir bekannt. Den Syser-Debugger kenn ich noch nicht, danke für den Tip. Hast Du eine Idee wie man den erkennen kann?


Geschrieben von Onyx am 25.03.2008 um 11:35:

Hi,

@rob: es geht auch noch viel leichter und ohne inline assembler.schreibe dir einfach vier bis fünf functions die sich gegenseitig aufrufen und die nach einem speziellen abbruchkriterium enden. wenn du das so programmierst, das sich die functions gegenseitig prüfen und jede funciton ca. 1000 mal aufrufst dann ist das später im debugger ziemlich eklig zu debuggen.
diese functionsaufrufe führst du einfach immer an stellen aus die dir wichtig erscheinen (serial abfrage, hidden checks, speichern, etc.). in dem fall brauchst du dich nicht mit assembler rumärgern und es ist auch relativ schön wartbar, da alles in deiner programmiersprache geschrieben ist.

was das aufspüren von debuggern angeht, gibt es unzählige methoden. bei ring-0 debugger wie softice und syser z.B. kannst du immer die existenz verschiedener treiber prüfen. jeder ring-0 treiber unter windows ist auf einen treiber angewiesen. in der regel haben diese treiber immer den selben namen und man kann diesen überprüfen. existiert der treiber, ist der debugger installiert und du kannst reagieren.

bei ring-3 debugger wie, ollydbg oder der ida-debugger kann man es ähnlich handhaben. überprüfe einfach ob ein prozess mit einem speziellen namen existiert. z.b. "ollydbg.exe", ida.exe und so weiter.
fensternamen eignen sich auch. prüfe aber nicht auf das titelfenster sondern versuche fenstertitel von optionsdialogen und ähnlichem zu finden. das wird seltener gepatched.

noch ein letzter tipp bezüglich obfuscation. wenn du deinen code obfuscierst, sei die darüber im klaren, das du dir sicherheit in diesem fall mit performanceverlust erkaufst. je mehr obfuscation umso mehr performance verliert deine application.

Was antidebugging angeht, so rate ich dir damit nicht zu viel zeit zu verschwenden. antidebugging wird immer umgangen, es ist lediglich eine frage der zeit. jeden debugger und jeden mod davon ins antidebugging aufzunehmen macht keine sinn. könzentriere dich auf generische methoden.

gruß,

onyx.

__________________
Benjamin Gnahm
Reverse Engineer & Software Entwickler
Aladdin Europe GmbH


Geschrieben von rob am 26.03.2008 um 22:19:

Hi Onyx,

danke für Deine Tipps.

Bzgl. Anti-Debuging hätte ich noch die Frage, was genau meinst du mit generischen Methoden? Wäre eine generische Methode z.B. die API-Funktion IsDebuggerPresent()? Hiermit können alle Ring3 Debugger erkannt werden.

Gruß
Rob


Geschrieben von Michael Bauer am 27.03.2008 um 22:24:

Richtig, die API-Funktion IsDebuggerPresent() wäre eine generische Methode.

Mit generischen Methoden ist gemeint, dass allgemeingültige Debugger-Merkmale überprüft werden sollen wie z.B.:
- mittels IsDebuggerPresent() Funktion
- Erkennung von Breakpoints
- Auswerten des Timingverhaltens z.B. mittels GetTickCount() oder RDTSC


Geschrieben von notme am 17.04.2008 um 13:55:

Bau Dir ne Random_Obfuscation.. Wenn Du Angst hast das die Performance in den Keller geht, mach ne Messung (wenn es ein aufwendiges Program ist nimm zb. Fraps um DirectX FPS oder ähnliches zu messen).. Bei einer standard Windowsapp wirst Du nichts merken. Von mir geschriebene Engines generieren teilweise für 1 Instruktion 300+~Instruktionen-Junk+die Real und bei einer normalen App merkst Du nichts davon.

Zum Thema Antidebugging...
Das Thema ist wirklich abgegrast. Die wirklich guten Tools sind alle *private* bei den Crackergruppen und die detectest Du mit den herkömmlichen Routinen garantiert nicht. Darauf würde ich garnicht soviel Zeit setzen...


Geschrieben von rob am 17.04.2008 um 23:44:

Hi,

hättest Du auch ein Beispiel zu Deiner Random_Obfuscation?

Gruss
rob


Geschrieben von notme am 18.04.2008 um 17:55:

Bei der Random_Obfuscation ändert sich halt einiges, damit der Code nicht mehr statisch analysiert werden kann...

Beispiel an einer realen Instruktion:

mov eax,12345678h

wird zu

pushfd
push ebx
sub eax,eax
mov ebx,12340000h
add eax,ebx
add ebx,987654
pop ebx
add eax,00005678h
popfd

Wobei sich die genutzten Register / Instruktionen natürlich alle verändern...

Das wäre also ein OpcodeExpander, da er aus einer Instruktion ein vielfaches macht. Dann könntest Du nen OpcodePermutator schreiben der die Reihenfolge ändert in der bestimmte Opcodes aufgerufen werden, oder einen OpcodeShrinker... Um komplex dargestellte Instruktionen durch einfache zu ersetzen...

Bei dem ganzen kommst Du um viel Asm nicht herum, aber wenn Du z.B Asm & C++ kannst kannst Du dir da ganz leicht was schreiben.

Gruß

Powered by: Burning Board Lite 1.0.2 © 2001-2004 WoltLab GmbH