Entwickler-Ecke
Sonstiges (Delphi) - ESCrackMe v.0.1 [SOLVED by BenBE & Martok]
SAiBOT - Mo 22.06.09 15:10
Titel: ESCrackMe v.0.1 [SOLVED by BenBE & Martok]
hi @ll,
Ich habe mich auch einmal rangemacht und ein Crackme geschrieben, ich würde mich freuen wenn sich ein paar von euch daran versuchen!
Alles ist erlaubt, ich will nur den Text haben, der bei einer erfolgreichen Passworteingabe zu sehen ist, oder das Passwort natürlich!
Der erste der es löst wird in einem neuen Beitrag in meinem
Blog [
http://www.EvilSoft.de] erwähnt ;) (welche Ehre :lol:).
Der Lösungsweg würde mich auch interessieren :).
Edit: ganz vergessen zu erwähnen: das Crackme benötigt Adminrechte zumindest in Vista!
Viel Spass.
Crosspoint [
http://www.hackerboard.de/thread.php?threadid=41208]
DerNetteNachbar - Mo 22.06.09 16:26
Es kommt ne leere Message Box raus. War doch nicht so schwer :-)
SAiBOT - Mo 22.06.09 16:27
DerNetteNachbar hat folgendes geschrieben : |
| Es kommt ne leere Message Box raus. War doch nicht so schwer :-) |
ne leider nicht ;)
BenBE - Mo 22.06.09 18:16
Netter Versuch, die Debugging-API zu hooken mit nem virtuellen Treiber :P
Auch schöne Idee über den Treiber die Nachricht in die Exe zu schreiben ;-) Da aber mangels funktionierendem Dissambler ich grad nicht sinnvoll in die ss.sys schauen kann, komm ich an der Stelle nicht weiter.
Ich geb aber mal nen Pointer [
http://xkcd.com/138/]: 0x00411DA8 ;-)
Martok - Mo 22.06.09 18:29
Ja gut... so weit waren wir auch.
Netterweise kann man auch mit gepatchtem Header OllyDbg nicht zur Kooperation bringen. Der Decompiler vom PE Explorer macht zwar etwas, aber das sieht sehr nach "nicht verstanden" aus ;) Da wirkt Spaghetticode wenigstens ;)
BenBE - Mo 29.06.09 01:45
Martok und ich haben die Lösung gefunden.
Das Passwort ist:
9166d42ae989fc85531902e0b8fb5eaa
Lösung schreibt Martok dann gleich.
Aber was aufgefallen ist:
Der Treiber hat einen Buffer-Overflow, den man für eine Priviledge Escalation missbrauchen kann. Dieser Bug kann ausgenutzt werden, indem man ein zu langes Passwort in den Treiber schreibt. Wenn man dabei das Stack-Layout beachtet, kann man den Canary dazu missbrauchen, um die Return-Adresse auf den Datenpuffer umzubiegen. Exploit bin ich grad zu faul, das als Proof-of-Concept zu schreiben. Der Exploit wäre zudem extrem vom System abhängig, aber ist nicht ganz unmöglich.
Arbeitszeit zum Reversen des Treibers etwa 6 Stunden.
Martok - Mo 29.06.09 01:57
BenBE und ich habens geschafft ;)
Einen Treiber zu decompilieren ist mit den richtigen Tools sehr einfach. Und da das die
richtigen waren, kann man dann auch alles zerlegen ;)
Also, die Nachricht ist extrem 1337:
| Zitat: |
| dIEs iST Nun eiNe vOLlverSiOn |
Passwort ist auch bekannt: 9166d42ae989fc85531902e0b8fb5eaa
Wie haben wir das gemacht? Im Grunde hab ich jetzt den Treiber vollständig vor mir, es ist also auch die "Verschlüsselung" bekannt.
Wo du das dann benutzt, ist auch klar, denn das muss ja bei den Ks(Un)Stack(De/A)ttachProcess-Aufrufen sein. Die Daten, die da verwendet werden, stammen aus Spaghetticode der sich zwischen den CreateDriver-Geschichten verbirgt.
Da du das alles so schön aus dem Datensegment lädst, kann man das auch mit einem kleinen Delphi-Programm selber machen (Achtung, hässlich):
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:
| var s:string; i:integer; c,b:char; t:integer; begin s:= Edit1.text; for i:= 1 to length(s) do begin if s[i] in ['0'..'9'] then begin b:= '0'; t:= 10; end else if s[i] in ['a'..'z'] then begin b:= 'a'; t:= 26; end else if s[i] in ['A'..'Z'] then begin b:= 'A'; t:= 26; end else continue; s[i]:= chr(ord(b) + (t-(ord(s[i]) - ord(b))) - 1) end; Edit1.Text:= s; |
Damit war das Passwort klar, und die Aufgabe erfüllt.
Es zeigt sich aber auch wieder, dass jeder Kopierschutz auf ein JMP zusammenfällt:
Quelltext
1: 2: 3: 4: 5:
| .text:00011303 cmp_res: .text:00011303 mov ecx, [ebp+compare_res] .text:00011309 mov [ebp+tmp], ecx .text:0001130F cmp [ebp+tmp], 0 .text:00011316 jnz ende |
Hier ein paar NOPs verteilt, sollte gehen. Tuts aber nicht, daran arbeiten wir noch ;)
Wäre schön, wenn du den Source offen legen könntest. ASM haben wir zwar, aber etwas higher-level wäre cool, gerade in Bezug auf den Treiber-Patch und wie du das absicherst.
Schöne Grüße,
Martok
for the record: das endergebnis stammt von mir, BenBE war zwischendurch GeSHi-basteln gegangen ;)
BenBE - Mo 29.06.09 08:47
Martok hat folgendes geschrieben : |
| for the record: das endergebnis stammt von mir, BenBE war zwischendurch GeSHi-basteln gegangen ;) |
for the record: den dissamblierten Source hatte Martok von mir, genauso wie ein wenig Unterstützung bei der Interpretation ;)
Was ich oben aber noch vergessen hab:
Der Treiber hat ein Mem-Leak, was man nutzen kann, um das System zum Absturz zu bringen. Dazu einfach wiederholt einzelne Blöcke an Daten zum Treiber schreiben. Bei jedem Aufruf wird eine weitere Prozess-Struktur referenziert. Diese wird anschließend nicht korrekt wieder dereferenziert, was man zum Erzeugen eines Double Free nutzen kann, wenn man in der Referenzzählung einen Overflow provoziert.
elundril - Mo 29.06.09 09:42
Könnten die nicht-code-Knacker vl. eine ausführliche Beschreibung in für einen Laien verständliche Worten haben?
lg elundril
BenBE - Mo 29.06.09 10:01
Das könnte etwas umfangreicher werden, da wir auf unserem Weg zur Lösung nahezu den gesamten Treiber reversed haben ...
Ansatz ist aber:
In nem Debugger schauen, was das Crackme macht. Dabei erstmal schauen, wo die Meldung Passwort ist ungültig herkommt. Von da aus Rückwärts schauen, wo die Entscheidung für die anzuzeigende Meldung steht.
Dabei stellt man fest, dass mit CreateFile auf den Treiber \\.\CRACKME zugegriffen wird. Dieser wird aus der Datei ss.sys geladen.
Nun geht es darum, was dieser Treiber tut: Als erstes findet eine Initialisierung des Treibers statt, in die das Aufbauen zweier Puffer (Passwd und Message) eingeflochten sind (scheußlicher Spaghetti-Code BTW). Die Puffer werden bei der Initialisierung noch nicht "entschlüsselt".
Beim Anmelden des Treibers werden 2 Routinen in die Dispatch-Struktur des Treibers eingetragen: Die Unload-Funktion und die Funktion für den WriteFile-Handler.
Nun geht es drum, herauszufinden, was diese Macht:
Neben einer Reihe von Prüfungen, ob diverse Puffer zugewiesen und verfügbar sind, wird im Datenpuffer der String lokal umkopiert (Buffer Overflow möglich ;-)) und dann über die Dekodier-Funktion gejagt (siehe oben Pascal-Source von Martok). Dies wird auch für den PW-Puffer innerhalb des Treibers gemacht, der vorher initialisiert wurde. Stimmen beide Puffer überein, so wird auch die Nachricht dekodiert und mit keStackAttachProcess\KeStackDetachProcess eine Art "WriteProcessMemory" ausgeführt. (vgl. MSDN zu diesen Funktionen). Daher auch von MArtok der Hinweis, dass man von diesen Funktionen rückwärts vorgehen kann.
Wie gesagt war die aufwändigste Arbeit daran, den ASM-Source aus dem Dissambly wieder in eine Algo-ähnliche Form zu übersetzen und die zahlreichen Variablen zuzuordnen. Optimierter Code sieht vollständig anders aus, was durchaus ein Hauptgrund dafür war, dass es um einiges mehr Aufwand gemacht hat, die korrekte Stelle zum Patchen zu finden.
Wie gesagt: Ich bin schon auf den Quelltext in Originalform gespannt!
Martok - Mo 29.06.09 14:18
BenBE hat folgendes geschrieben : |
for the record: den dissamblierten Source hatte Martok von mir, genauso wie ein wenig Unterstützung bei der Interpretation ;) |
for the record: später hab ich mir den nochmal selber im Debugger geladen, da kann man dann wenigstens Label benennen und sowas alles.
So, zum Vorgehen noch was:
Erstmal gucken wir in die ESCrackMe.exe, also den UserMode-Teil.
BenBE hat folgendes geschrieben : |
| In nem Debugger schauen, was das Crackme macht. Dabei erstmal schauen, wo die Meldung Passwort ist ungültig herkommt. Von da aus Rückwärts schauen, wo die Entscheidung für die anzuzeigende Meldung steht. |
Ergänzung: die Entscheidung besteht darin, dass man eine Adresse anguckt. Steht da "nichts" (also null) drin, gibts ne Fehlermeldung, sonst wird das als Nachricht ausgegeben. Irgendwer muss also den Speicher setzen... macht aber niemand.
Also:
BenBE hat folgendes geschrieben : |
| Dabei stellt man fest, dass mit CreateFile auf den Treiber \\.\CRACKME zugegriffen wird. Dieser wird aus der Datei ss.sys geladen. |
Die Daten, die in dieses File geschrieben werden, kriegt man auch raus. Ist alles ein Buffer, der mit folgendem gefüllt wird:
32-bit ProcessID des UserMode-Prozesses
32-bit Pointer auf die eben erwähnte Nachrichten-Speicherstelle
Zero-Terminated String User-Eingabe
Nun hat man einen Decompiler, der Kernel-Treiber versteht. Oder man muss wen kennen, der einen hat ;)
BenBE hat folgendes geschrieben : |
| Beim Anmelden des Treibers werden 2 Routinen in die Dispatch-Struktur des Treibers eingetragen: Die Unload-Funktion und die Funktion für den WriteFile-Handler. |
Was übrigens im Code relativ blöd zu lesen ist, weil man aus den Offsets erstmal auf die Struktur-Member schließen muss. Nur mal am Rande^^
BenBE hat folgendes geschrieben : |
| Nun geht es drum, herauszufinden, was diese Macht: |
Hier wird die oben erwähnte Struktur auseinandergenommen. Erstmal holen wir uns aus der ProcessID, also den ersten 4 Byte, ein EPROCESS-Objekt.
Ansonsten so weiter wie bei BenBE beschrieben: Daten vergleichen und ggf den dekodierten String dahin schreiben, wo uns die 2. 4 Byte hinpointen.
BenBE hat folgendes geschrieben : |
| Wie gesagt war die aufwändigste Arbeit daran, den ASM-Source aus dem Dissambly wieder in eine Algo-ähnliche Form zu übersetzen und die zahlreichen Variablen zuzuordnen. |
Man merkt schon den Unterschied zwischen full-blown Debugger-IDE und ASM-im-Editor-angucken. Aber wie gesagt, Tools sind alles ;)
BenBE hat folgendes geschrieben : |
| Optimierter Code sieht vollständig anders aus, was durchaus ein Hauptgrund dafür war, dass es um einiges mehr Aufwand gemacht hat, die korrekte Stelle zum Patchen zu finden. |
Stimmt, zumal unmengen Code redundant drin war. Das Teil ließe sich auf die halbe Größe optimieren, wenn nicht noch kleiner ;)
BenBE hat folgendes geschrieben : |
| Wie gesagt: Ich bin schon auf den Quelltext in Originalform gespannt! |
Dito!
Und jetzt sollten wir vielleicht den OP auch mal was sagen lassen. Immerhin muss er ja noch unsere Goldmedaillen verteilen :lol:
SAiBOT - Mo 29.06.09 18:34
:dance: :dance2: :dance: Also zuerst einmal: gute Arbeit! Ich hoffe ihr hattet Spass :P
TreiberSrc:
C#-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: 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: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134:
| #include "ntifs.h" #include "ntddk.h"
UNICODE_STRING usDosDeviceName; CHAR Text[250];CHAR rKey[33]; void atbash(char *Buffer, int BufferLen) { int basis,sl,li;
for (li = 0; li <= BufferLen; li = li +1) {
if ((Buffer[li] >= 48) && (Buffer[li] <= 57)) { basis = 48; sl = 10; } else if ((Buffer[li] >= 65) && (Buffer[li] <= 90)) { basis = 65; sl = 26; } else if ((Buffer[li] >= 97) && (Buffer[li] <= 122)) { basis = 97; sl = 26; } else { continue; } Buffer[li] = basis+(sl-(Buffer[li]-basis))-1; } }
VOID OnUnload( IN PDRIVER_OBJECT DriverObject ) { IoDeleteSymbolicLink(&usDosDeviceName); IoDeleteDevice(DriverObject->DeviceObject); }
typedef struct _MYPACK { ULONG Pid; ULONG String; CHAR Key[33]; } MYPACK, *PMYPACK;
NTSTATUS MyWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PIO_STACK_LOCATION pIoStackIrp = NULL; PMYPACK MyPack; ULONG pe = 0; CHAR retText[250]; CHAR retKey[33]; KAPC_STATE ks;
pIoStackIrp = IoGetCurrentIrpStackLocation(Irp); if(pIoStackIrp) { MyPack = (PMYPACK)Irp->AssociatedIrp.SystemBuffer; if(MyPack) { if (PsLookupProcessByProcessId(MyPack->Pid, &pe) == STATUS_SUCCESS) { strcpy(retText,Text); strcpy(retKey,rKey); atbash(retText,29); atbash(retKey,32);
if (strcmp(MyPack->Key,retKey) == 0) { KeStackAttachProcess(pe, &ks); strcpy(MyPack->String,retText); KeUnstackDetachProcess(&ks); } }
} } return STATUS_SUCCESS; }
NTSTATUS UnSupportedFunction(PDEVICE_OBJECT DeviceObject, PIRP Irp) { return STATUS_NOT_SUPPORTED; }
NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath ) { UNICODE_STRING usDriverName; PDEVICE_OBJECT pDeviceObject = NULL; ULONG uiIndex = 0;
strcat(Text, "wRVh "); strcat(rKey, "0833w5");
RtlInitUnicodeString(&usDriverName, L"\\Device\\CRACKME");
strcat(Text, "rHG "); strcat(rKey, "7zv010");
RtlInitUnicodeString(&usDosDeviceName, L"\\DosDevices\\CRACKME");
strcat(Text, "Mfm "); strcat(rKey, "ux1446"); if (IoCreateDevice(theDriverObject, 0, &usDriverName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDeviceObject) == STATUS_SUCCESS) { for(uiIndex = 0; uiIndex < IRP_MJ_MAXIMUM_FUNCTION; uiIndex++) theDriverObject->MajorFunction[uiIndex] = UnSupportedFunction;
theDriverObject->MajorFunction[IRP_MJ_WRITE] = MyWrite; pDeviceObject->Flags |= DO_BUFFERED_IO; pDeviceObject->Flags &= (~DO_DEVICE_INITIALIZING); IoCreateSymbolicLink(&usDosDeviceName, &usDriverName);
}
strcat(Text, "vrMv "); strcat(rKey, "8097v9");
theDriverObject->DriverUnload = OnUnload;
strcat(Text, "eLOoeviHrLm\00"); strcat(rKey, "y1uy4vzz");
return STATUS_SUCCESS; } |
SenderSrc:
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: 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: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96:
| program ESCrackMe;
{$APPTYPE CONSOLE}
uses SysUtils, WinSvc, Windows;
type MYPACK = packed record Pid: DWORD; pString: Pointer; key: Array[1..33] of AnsiChar; end; PMYPACK = ^MYPACK;
const DriverName = 'ss'; Nachricht = 'Nachricht:';
var scm,svc: Cardinal; PathAndSys:AnsiString; status: _SERVICE_STATUS; pfool:PAnsiChar = nil;
f: THandle; p: MYPACK; rString: Array[1..250] of AnsiChar; cfool: Cardinal;
eingabe: AnsiString; begin WriteLN('**************************'#13#10+ '* ESCrackMe v0.1 *'#13#10+ '* http://www.EvilSoft.de *'#13#10+ '**************************'#13#10);
p.Pid := GetCurrentProcessId; p.pString := @rString[1];
scm := OpenSCManager(nil,nil,SC_MANAGER_CREATE_SERVICE); if (scm <> 0) then begin PathAndSys := AnsiString(ExtractFilePath(ParamStr(0))+'ss.sys');
svc := CreateServiceA(scm,DriverName,DriverName,SERVICE_START or _DELETE or SERVICE_STOP,SERVICE_KERNEL_DRIVER,SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE,@PathAndSys[1],nil,nil,nil,nil,nil);
if (svc = 0) then svc := OpenServiceA(scm,DriverName,SERVICE_START or _DELETE or SERVICE_STOP);
if (svc <> 0) then begin StartServiceA(svc,0,pfool); WriteLN('Bitte geben Sie das Passwort ein und bestaetigen Sie mit Enter!'#13#10); ZeroMemory(@rString[1],250); ZeroMemory(@p.key[1],250);
ReadLn(eingabe); Copymemory(@p.key[1], @eingabe[1], 32);
f := CreateFile('\\.\CRACKME', GENERIC_WRITE, 0, nil, OPEN_EXISTING, 0, 0); if (f <> 0) then begin WriteFile(f, p, SizeOf(MYPACK), cfool, nil); CloseHandle(f); Sleep(10); if rString[1] = #00 then MessageBoxA(0, 'Das Passwort ist ungültig!'#13#10,Nachricht,0) else MessageBoxA(0, @rString[1],Nachricht,0); end else WriteLn('Fehler: Es konnte keine Verbindung zum Sicherheitssystem hergestellt werden!'#13#10); ControlService(svc,SERVICE_CONTROL_STOP,status); DeleteService(svc); CloseServiceHandle(svc); end else WriteLn('Fehler: Sicherheitssystem konnte nicht gestartet werden!'#13#10);
CloseServiceHandle(scm); end else WriteLn('Fehler: Sicherheitssystem konnte nicht installiert werden!'#13#10);
WriteLn('Druecken Sie Enter zum beenden!'); readln; end. |
BenBE hat folgendes geschrieben : |
Der Treiber hat ein Mem-Leak, was man nutzen kann, um das System zum Absturz zu bringen. Dazu einfach wiederholt einzelne Blöcke an Daten zum Treiber schreiben. Bei jedem Aufruf wird eine weitere Prozess-Struktur referenziert. Diese wird anschließend nicht korrekt wieder dereferenziert, was man zum Erzeugen eines Double Free nutzen kann, wenn man in der Referenzzählung einen Overflow provoziert. |
ok... da werde ich mich mal schlau machen!
BenBE hat folgendes geschrieben : |
| (scheußlicher Spaghetti-Code BTW) |
Durch den "Spaghetti-Code" habe ich das auslesen der "goodboy message" und des Passwortes etwas erschwert =).
Die CrackMe habt ihr zu 100% verstanden... da sieht man mal wieder, wie die Delphi-Community sogenannte "Hackerboards"(Crosslink) mit eigens eingerichteten Foren-Sparten dominiert. :lol:
Ja... sehr gut, darf ich fragen welchen Disassembler ihr für den Treiber verwendet habt ? IDA ?
PS: Die "Verschlüsselung" ist AKA atbash :wink:
turboPASCAL - Mo 29.06.09 19:11
Mal 'ne Frage,
Was ist denn das für eine Intro.exe ?
Nett gemacht ist sie ja aber 3MB ?
Viele Nullers und 'n paar PNGs die sich wiederholen ...:gruebel:
SAiBOT - Mo 29.06.09 20:23
turboPASCAL hat folgendes geschrieben : |
Mal 'ne Frage,
Was ist denn das für eine Intro.exe ?
Nett gemacht ist sie ja aber 3MB ?
Viele Nullers und 'n paar PNGs die sich wiederholen ...:gruebel: |
Da steckt glaube ich eine ganze Physik-Engine drin ->
http://www.testaware.de.tp/
Flamefire - Mo 29.06.09 20:33
mal ein Frage:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| strcpy(retText,Text); strcpy(retKey,rKey); atbash(retText,29); atbash(retKey,32); if (strcmp(MyPack->Key,retKey) == 0) |
Hab ich was falsch verstanden, oder ist das mal wieder ne zemliche Schwachstelle?
BZW genügt es im asm den buffer des schlüssels den man eingeben hat mit dem zu vergleichenden zu ersetzen um das pw zu erhalten da atbash sysmetrisch ist
turboPASCAL - Mo 29.06.09 20:37
Aha, guck ich mir mal an...
Anbei, könne man auch so machen. :wink: *angeb*
//Edit:
Neue Version hochgeladen wegen Virenverdacht. 6.12.2009
Die Application ist nun "nur" mit UPX gepackt.
SAiBOT - Mo 29.06.09 21:08
Flamefire hat folgendes geschrieben : |
Hab ich was falsch verstanden, oder ist das mal wieder ne zemliche Schwachstelle?
BZW genügt es im asm den buffer des schlüssels den man eingeben hat mit dem zu vergleichenden zu ersetzen um das pw zu erhalten da atbash sysmetrisch ist |
In einem Treiber sind die simpelsten Dinge viel schwieriger zu bewerkstelligen als in einem Debugger freundlichen userland Programm, natürlich hätte ich alles noch ein wenig salzen können ;)
turboPASCAL hat folgendes geschrieben : |
Aha, guck ich mir mal an...
Anbei, könne man auch so machen. :wink: *angeb* |
Selbst gemacht schmeckt halt doch am besten :).
BenBE - Mo 29.06.09 21:37
SAiBOT hat folgendes geschrieben : |
| :dance: :dance2: :dance: Also zuerst einmal: gute Arbeit! Ich hoffe ihr hattet Spass :P |
Jap. War wieder mal eine gute Arbeit damit man nicht einrostet ;-)
SAiBOT hat folgendes geschrieben : |
BenBE hat folgendes geschrieben : |
Der Treiber hat ein Mem-Leak, was man nutzen kann, um das System zum Absturz zu bringen. Dazu einfach wiederholt einzelne Blöcke an Daten zum Treiber schreiben. Bei jedem Aufruf wird eine weitere Prozess-Struktur referenziert. Diese wird anschließend nicht korrekt wieder dereferenziert, was man zum Erzeugen eines Double Free nutzen kann, wenn man in der Referenzzählung einen Overflow provoziert. |
ok... da werde ich mich mal schlau machen! |
Siehe die Notiz zu psProcessByProcessId im MSDN ...
SAiBOT hat folgendes geschrieben : |
BenBE hat folgendes geschrieben : | | (scheußlicher Spaghetti-Code BTW) |
Durch den "Spaghetti-Code" habe ich das auslesen der "goodboy message" und des Passwortes etwas erschwert =). |
Unwesentlich ... Wir hatten die Dekodierungsroutine nämlich zuerst und brauchten uns dadurch nur Straight Forward im Source die Puffer zusammensuchen. Da hätte es wirklich bösere Möglichkeiten für gegeben ;-)
SAiBOT hat folgendes geschrieben : |
| Die CrackMe habt ihr zu 100% verstanden... da sieht man mal wieder, wie die Delphi-Community sogenannte "Hackerboards"(Crosslink) mit eigens eingerichteten Foren-Sparten dominiert. :lol: |
Die Algo&Opti-Sparte wurde von mir einmal beantragt, da es oftmals sinnvoll ist, Algorithmen losgelöst von deren Implementierung zu betrachten, bzw. für spezielle Implementierungen Optimierungsfälle vorzuschlagen, die nichts mit Delphi zu tun haben.
SAiBOT hat folgendes geschrieben : |
| Ja... sehr gut, darf ich fragen welchen Disassembler ihr für den Treiber verwendet habt ? IDA ? |
Jap. Wobei ich das Dissambly bekommen hatte und dann an Martok weitergereicht hatte. Aber der Dump, den wir zur Verfügung hatten, stammte von IDA.
SAiBOT hat folgendes geschrieben : |
| PS: Die "Verschlüsselung" ist AKA atbash :wink: |
Ich geh jetzt mal nicht näher drauf ein, dass ich einfache, monoalphabethische Substitutionen nichtals Verschlüsslung betrachte ...
Bin dann mal auf den Blog-Post gespannt ;-)
P.S.: In dem Hacker-Board haben die sich ja richtig oberflächlich angestellt ... Einen Treiber CRACKME zu übersehen, von dem man regelrecht angebrüllt wird "\\.\CRACKME", ist wirklich eine reife Leistung :P
Flamefire - Mo 29.06.09 22:13
turboPASCAL hat folgendes geschrieben : |
Aha, guck ich mir mal an...
Anbei, könne man auch so machen. :wink: *angeb* |
nice. wie geht das? da es ne substitution ist hätte ich gedaacht die zuordnung sei eineindeutig
BenBE - Mo 29.06.09 22:31
Flamefire hat folgendes geschrieben : |
mal ein Frage:
Delphi-Quelltext 1: 2:
| strcpy(retText,Text); strcpy(retKey,rKey); | |
In einem Treiber strcpy und strcat zu verwenden ist SEHR gewagt ... Bitte lieber strncpy und derivate nutzen. Genauso, wie man den Puffern, die von einem Benutzer kommen, nicht trauen sollte: Wenn ich 33 Non-Zero-Bytes schreibe, erhalte ich bei deiner Variante einen Read-Zugriff hinter dem Puffer-Ende, was im Zweifelsfall und bei schlechtem Alignment zu einem Bluescreen führt. dann lieber strnlen verwenden, was die Längen- und Lesebegrenzung auf den übergebenen Puffer sichert.
Womit wieder einmal bestätigt wäre, dass die meisten C nur bis zum nächsten Buffer Overflow beherrschen ...
@TP: Schade, dass ich beim Starten einen Runtime-Fehler 201 bekomme:
Quelltext
1: 2: 3: 4: 5: 6: 7:
| --------------------------- Error --------------------------- Runtime error 201 at 0040A278 --------------------------- OK --------------------------- |
SAiBOT - Di 30.06.09 17:03
Von beherschen kann bei mir garnicht die Rede sein =), macht Sinn was du sagst! Sollte ich mal etwas machen, was Stabil laufen muß, werde ich es mir zu Herzen nehmen, gerade weil derartige Fehler in einem Treiber oftmals das ganze System in den Abgrund reissen!
Wenn ich etwas mehr Zeit habe gibts natürlich noch den versprochenen Blogpost und die Sense fürs Hackerboard . :wink:
BenBE - Sa 11.07.09 23:55
Dein Blogpost hätte ruhig etwas umfangreicher ausfallen dürfen ;-)
SAiBOT - So 12.07.09 11:48
Ja, meine Zeit ist momentan leider sehr rar, aber jeder der sich für die Materie etwas interessiert weiss was ihr vollbracht habt :D.
Der DF-Link ist ja auch angegeben, wo es etwas mehr ins Detail geht!
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!