Autor |
Beitrag |
uall@ogc
Beiträge: 1826
Erhaltene Danke: 11
Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
|
Verfasst: So 28.08.05 16:00
Ich mach mal einen Thread auf in dem es darum geht wie man sein Programm vor dem debuggen/cracken schützen kann.
Ich werde hier im laufe der zeit einige Beispiele posten.
Als erstes einmal etwas, was in 2 Minuten gemacht werden kann und schon den einen oder anderen schlechten Cracker in den Wahnsinn treibt.
hier ein kleines Video wie das geht und ne Erkläung was man wie machen muss
uall.overclock.ch/delphiprotect01.zip
1) Man erstellt ganz normal sein Projekt.
2) Anstatt das Beenden von Delphi übernehmen zu lassen schreibt man bei OnClose (ganz am Schluss) ExitProcess(0) rein,
das wird benötigt damit beim beenden spätr das programm nicht crashed.
3) Im Hauptprogramm (der dpr) fügt man eine Variable ein die dafür sorgt das der Code zum erzeigen des Forms nur einmal ausgeführt wird (das hat interne gründe auf die ich nicht genauer eingehen werde)
4) ausserdem prüft man ob ein Debugger geladen ist (IsDebuggerPresent aus der kernel32.dll importieren bzw meine unit benutzen)
5) Man ändert bei der Sektion Tls +16bytes) mit Hilfe von LORDPE die daten (sollten 4* 00 sein) ab indem man die durch den Entrypoint + ImageBase ersetzt (Entrypoinz ist d wo nacher AFFEAFFE steht)
6) der Entrypoint wird auf irgend eine Adresse gesetzt (würde er ausgeführt werden crashed es, wird er aber nur wenn ein debugger erkannt wurde!)
Code der geändert werden muss:
Delphi-Quelltext 1: 2: 3: 4: 5:
| procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin ExitProcess(0); end; |
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| program Project2;
uses Forms, uallProtect, Unit1 in 'Unit1.pas' ;
{$R *.res}
var first: boolean = true; begin if (not first) or (uallProtect.IsDebuggerPresent) then exit; first := false; Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run; end. |
_________________ wer andern eine grube gräbt hat ein grubengrabgerät
- oder einfach zu viel zeit
Zuletzt bearbeitet von uall@ogc am So 28.08.05 16:17, insgesamt 1-mal bearbeitet
|
|
uall@ogc
Beiträge: 1826
Erhaltene Danke: 11
Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
|
Verfasst: So 28.08.05 16:04
02
Speziel für Ollydbg hab ich bisl code geschrieben der den Debugger zum crashen bringt
Dieser kann einfach bei wichtigen Funktionen (z.b. Keyeingabe testen) vorher (und nachher) aufgerufen werden.
Ist Ollydbg geladen crashed es
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32:
| procedure crash_ollydbg; asm pushad push offset @@handler xor eax, eax push fs:[eax] mov fs:[eax], esp mov ebx, esp push eax push $73257325 push esp push $5 push esp push $2 push eax push $40010006 call RaiseException @@handler: mov eax, [esp+$C] mov esp, [eax+$A4] xor eax, eax pop fs:[eax] pop eax popad end;
procedure TForm1.Button1Click(Sender: TObject); begin crash_ollydbg; form1.caption := 'hallo'; crash_ollydbg; end; |
_________________ wer andern eine grube gräbt hat ein grubengrabgerät
- oder einfach zu viel zeit
|
|
uall@ogc
Beiträge: 1826
Erhaltene Danke: 11
Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
|
Verfasst: So 28.08.05 16:15
03
Ausnutzen der Trägheit der Debugger.
Wenn man sich mit einem Debugger in ein laufendes Programm "einklingt" (Ollydbg -> attach) werden Thread nicht sofort suspended, d.h. sie laufen noch einige Millisekunden weiter. Das kann man ausnutzen um den Debugger zu erkennen und das Programm zu beenden / crashen. Hier mal ein Beispiel:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| function proc(a: integer): integer; begin result := 0; while not uallProtect.IsDebuggerPresent do sleep(10); asm popad end; end;
procedure TForm1.FormCreate(Sender: TObject); var tid: cardinal; begin BeginThread(nil,0,@proc,nil,0,tid); end; |
_________________ wer andern eine grube gräbt hat ein grubengrabgerät
- oder einfach zu viel zeit
|
|
uall@ogc
Beiträge: 1826
Erhaltene Danke: 11
Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
|
Verfasst: So 28.08.05 16:26
von SwissDelphiCenter geklaut aber auch eine Debugger erkennung (für SoftIce)
dazu muss ich aber sagen, jeder der SoftIce bedienen kann, wird das umgehen können
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45:
| function IsSoftIce95Loaded: Boolean; var hFile: THandle; begin Result := False; hFile := CreateFileA('\\.\SICE', GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (hFile <> INVALID_HANDLE_VALUE) then begin CloseHandle(hFile); Result := True; end; end;
function IsSoftIceNTLoaded: Boolean; var hFile: THandle; begin Result := False; hFile := CreateFileA('\\.\NTICE', GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (hFile <> INVALID_HANDLE_VALUE) then begin CloseHandle(hFile); Result := True; end; end;
procedure TForm1.Button1Click(Sender: TObject); begin if IsSoftIce95Loaded or IsSoftIceNTLoaded then begin end; end; |
_________________ wer andern eine grube gräbt hat ein grubengrabgerät
- oder einfach zu viel zeit
Zuletzt bearbeitet von uall@ogc am So 28.08.05 17:09, insgesamt 1-mal bearbeitet
|
|
uall@ogc
Beiträge: 1826
Erhaltene Danke: 11
Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
|
Verfasst: So 28.08.05 16:37
05
Erkennung von Breakpoints (Haltepunkte)
Breakpoints werden oft benutzt um bestimmte stellen zu finden. Kommt z.b. bei der eingabe eines falschen Keys eine Nachricht, dass der Key falsch eingegeben wurde, wird der Cracker versuchen einen Breakpoint auf die API MessageBoxA zu setzen da diese wahrscheinlich aufgerufen wird.
Diesen kann man Abfragen und dann das Programm z.b. crashen lassen:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| procedure TForm1.FormCreate(Sender: TObject); begin if pbyte(GetProcAddress(GetModuleHandle('user32.dll'),'MessageBoxA'))^ = $CC then asm popad jmp eax end; MessageBoxA(0,'der eingegebene Key ist falsch',nil,0); end; |
_________________ wer andern eine grube gräbt hat ein grubengrabgerät
- oder einfach zu viel zeit
|
|
uall@ogc
Beiträge: 1826
Erhaltene Danke: 11
Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
|
Verfasst: Sa 07.01.06 16:50
06
FileCheck
Es gibt ja viele Arten von Filechecks. Ich habe hier mal eine Methode gemacht, die ich sehr schön für Anfänger finde, da man nichts per Hand machen muss. Es reicht die Funktion im OnCreate aufzurufen. Ob sie Programmiertechnisch so toll ist lass ich mal aussen vor. Es funktioniert auch nicht mit irgendwelchen Packern. Beim ersten start der Exe wird eine neue Exe erstellt die den FileCheck beinhaltet. Hier der Code:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78:
| procedure CheckExe; var i, h, h2: integer; read: cardinal; buf: pointer; fsize: Cardinal; addrm : Pinteger; checksum: integer; checkx: integer; begin i := $12345678; checksum := $12345678; h := CreateFileA(PChar(Paramstr(0)),GENERIC_READ,FILE_SHARE_READ or FILE_SHARE_WRITE, nil,OPEN_EXISTING,0,0);
if (h = 0) then begin CloseHandle(h); Exit; end;
if (i = 0) then ;
fsize := GetFileSize(h,nil); if (fsize = 0) then begin CloseHandle(h); Exit; end;
buf := VirtualAlloc(nil,fsize,MEM_COMMIT or MEM_RESERVE,PAGE_EXECUTE_READWRITE); if (buf = nil) then begin CloseHandle(h); Exit; end;
if (not ReadFile(h,buf^,fsize,read,nil)) or (read <> fsize) then begin CloseHandle(h); Exit; end;
addrm := Pinteger(integer(buf)+integer(@CheckExe)-integer(GetModuleHandle(nil))-$BE0); if IsBadReadPtr(addrm,4) then begin CloseHandle(h); Exit; end;
if (addrm^ = $12345678) then begin addrm^ := $00000000; for i := 0 to fsize div 4 -1 do checksum := checksum xor pinteger(integer(buf)+i*4)^; addrm^ := checksum; h2 := CreateFileA(PChar(Paramstr(0)+' new.exe'),GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil,CREATE_ALWAYS,0,0); if (h2 <> 0) then begin WriteFile(h2,buf^,fsize,read,nil); CloseHandle(h2); end; end else begin checkx := addrm^; addrm^ := $00000000; for i := 0 to fsize div 4 -1 do checksum := checksum xor pinteger(integer(buf)+i*4)^; if (checkx <> checksum) then while true do asm pop eax end; end; VirtualFree(buf,fsize,MEM_DECOMMIT); CloseHandle(h); end; |
_________________ wer andern eine grube gräbt hat ein grubengrabgerät
- oder einfach zu viel zeit
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Sa 07.01.06 17:17
Um nicht die API Funktion IsDebuggerPresent nutzen zu müssen, kann man auch seien eigene kleine Routine schreiben:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| asm push eax mov eax, fs:[$30]; mov eax, [eax+2]; mov [BeingDebugged], al pop eax end; |
BeingDebugges ist dabei eine globale Variable. Genaueres gibt es hier: www.michael-puff.de/.../AntiCrackig_1.shtml
@uall@ogc: Motzi, Olli und ich hatten uns schon mal zusammengesetzt, und Methoden erläutert, wie man das Debuggen und somit das Crackenr erschweren könnte. Da beide aber unter chronischen Zeitmangel leiden, ist bisher nur dieser eine Artikel fertig geworden. Im zweiten sollte es um diese nette Routine von Olli gehen:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30:
| asm pushad call @SetupSEHAndRaiseException mov ecx, dword ptr [esp+12] mov eax, fs:[$30] movzx eax, byte ptr [eax+$2] and eax, eax jnz @NoAddOpCodeSize mov dword ptr [ecx+$B8], offset @AfterExceptionCause @NoAddOpCodeSize: mov dword ptr [ecx+$04], eax mov dword ptr [ecx+$08], eax mov dword ptr [ecx+$0C], eax mov dword ptr [ecx+$10], eax mov dword ptr [ecx+$14], eax and dword ptr [ecx+$18], $155 and dword ptr [ecx+$C0], $FFFFFEFF xor eax, eax ret @SetupSEHAndRaiseException: xor eax, eax push dword ptr fs:[eax] mov fs:[eax], esp @KillCode: and dword ptr [eax+$18], $155 @AfterExceptionCause: pop dword ptr fs:[$0] add esp, $4 popad end; |
Leider bin ich da nicht mehr so ganz mit gekommen und das was ich verstanden habe, habe ich leider schon wieder vergessen. Disen teil sollte eigentlich Motzi schreiben, aber nun ja, Zeitmangel. Nun würde ich gerne diese Artikelserie vortsetzen. Eventuell könntest du dich ja daran beteiligen, wenn du Lust hast. Ich würde dann als Herausgeber etc. fungieren.
Zuletzt bearbeitet von Luckie am Sa 07.01.06 17:32, insgesamt 1-mal bearbeitet
|
|
uall@ogc
Beiträge: 1826
Erhaltene Danke: 11
Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
|
Verfasst: Sa 07.01.06 17:26
Das sollte auf 9x ME 2k XP funktionieren.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| function IsDebuggerPresent: boolean; stdcall; asm MOV EAX, FS:[030H] TEST EAX, EAX JS @@W9X @@WNT: MOV EAX, FS:[$18] MOV EAX, [EAX+$30] MOVZX EAX, [EAX+2] RET @@W9X: MOV EAX, [$BFFC9CE4] MOV ECX, [EAX] CMP [ECX+$54], 00000001 SBB EAX, EAX INC EAX RET end; |
_________________ wer andern eine grube gräbt hat ein grubengrabgerät
- oder einfach zu viel zeit
|
|
uall@ogc
Beiträge: 1826
Erhaltene Danke: 11
Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
|
Verfasst: Sa 07.01.06 18:21
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39:
| asm pushad @SetupSEHAndRaiseException: xor eax, eax push offset @ExceptHandler push dword ptr fs:[eax] mov fs:[eax], esp @KillCode: and dword ptr [eax+$18], $155 @AfterExceptionCause: pop dword ptr fs:[$0] add esp, $4 popad jmp @ende
@ExceptHandler: mov ecx, dword ptr [esp+$C] mov eax, fs:[$30] movzx eax, byte ptr [eax+$2] and eax, eax jnz @NoAddOpCodeSize mov dword ptr [ecx+$B8], offset @AfterExceptionCause @NoAddOpCodeSize: mov dword ptr [ecx+$04], eax mov dword ptr [ecx+$08], eax mov dword ptr [ecx+$0C], eax mov dword ptr [ecx+$10], eax mov dword ptr [ecx+$14], eax and dword ptr [ecx+$18], $155 and dword ptr [ecx+$C0], $FFFFFEFF xor eax, eax ret @Ende: end; |
_________________ wer andern eine grube gräbt hat ein grubengrabgerät
- oder einfach zu viel zeit
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Sa 07.01.06 18:26
Was hältst du von Ollis Code? Nur so viel, er wurde schon geknackt, war wohl doch nicht so aufwendig zu umgehen.
|
|
uall@ogc
Beiträge: 1826
Erhaltene Danke: 11
Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
|
Verfasst: Sa 07.01.06 18:30
Ja er wurde von mir "geknackt".
Der macht nicht wirklich viel mehr als IsDebuggerPresent, sondern versucht das nur durch nen Excepion Handler schwierigier debuggbar zu machen.
KillCode einfach auskommentieren (0x90 d.h. noppen) und schon ist das umgangen.
_________________ wer andern eine grube gräbt hat ein grubengrabgerät
- oder einfach zu viel zeit
|
|
|