|
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
|
|
22.03.2008 18:26 |
|
Onyx
Grünschnabel
Dabei seit: 20.03.2008
Beiträge: 2
|
|
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
|
|
25.03.2008 10:35 |
|
notme
Grünschnabel
Dabei seit: 17.04.2008
Beiträge: 9
|
|
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ß
|
|
18.04.2008 16:55 |
|
|