1. PEID "Kryptoanalyse" sollte man immer skeptisch betrachten.
CRC32/Adler32 usw. sind z.B sehr kompakt. D.h wenn die Erkennung signaturbasierend abläuft (z.B 0xEDB88320/0xFFFFFFFF Suche bei CRC32), sind Falschmeldungen bei größeren Exen nichts ungewöhnliches.
Ebenso kann die Exe einfach Bibliotheken für alle möglichen CRC/Hashs beinhalten, obwohl nur ein Bruchteil davon genutzt wird (und zudem nicht unbedingt für den Selbstcheck)
2.
Tutorials? Wonach sucht man da?
Vornehmlich suche ich eben Tutorials, die dieses Problem beschreiben/behandeln oder eine .exe/.dll fixen. Natürlich erst einmal ein einfaches Tutorial!
mehr als "selfcheck" fällt mir an Begriffen auch nicht ein. Ein Analyse-Paper von BIW oder ARTeam zu den üblichen "professionellen" Protectoren könnte das Gewünschte beinhalten.
ARTeam eZine / Downloads - Tuts 4 You (ARTeam ezine)
Tutorials / Downloads - ARTeam Website
Wobei Anti-Debug/Anti-Unpack auch in diese Kategorie fallen sollte:
Anti-Debugging / Downloads - Tuts 4 You
Allgemein:
Tutorials, Papers, Dissertations, Essays and Guides / Downloads - Tuts 4 You
------------------------------------
Warum so allgemein:
------------------------------------
Erstmal folgende Überlegungen:
Angenommen, mit einer Magic-Routine (später dazu mehr) können wir als Entwickler die Checksumme der Exe feststellen. Was tun wir dann?
Möglichkeit:
- Wir beenden die Anwendung einfach oder lassen diese gar abstürzen.
Problem: Netzwerkübertragung/Entpack/Lesefehler (Datenträger), fehlerhaftes Update (kommt auch bei größeren Entwicklerteams vor) oder (wenn auch mittlerweile eher exotisch) Vireninfektion.
Und der User behält das Programm als "unstabiles Zeuch, das gar nicht startet" oder "immer abstürzt" in Erinnerung.
-
- Fehlermeldung ausgbeben, beenden.
Problem: sofern wir die üblichen Tipps (Lazarus anti-cracking) mitbekommen haben oder einen professionellen Protector programmieren, wissen wir, dass die Suche nach der Check-Routine dann für den Cracker trivial ist.
-
- Beides kombinieren. Sofern wir z.B eine italienische Softwarefirma sind und KFZ-Flash/Lesesoftware anbieten, lassen wir eine Fehlermeldung anzeigen und starten eine Routine, die die Exe beendet.
Patcht der böse Cracker die Fehlermeldung samt "ExitProcess" weg, darf er ein Backup aufspielen, da gleichzeitig mit/nach ExitProcess ein Thread gestartet wird, der die ersten 20MB der Festplatte mit Zufallsdaten überschreibt
.
Oder in einem Spiel statt Waffen Schweine prodzuieren lassen Schweinisch gut: Die kreativsten Kopierschutz-Mechanismen für PC-Spiele 
Also allgemein:
eine "normale" Meldung ausgeben und unabhängig davon verzögert eine andere Checkroutine starten.
Verzögerung: z.B durch
- SetTimer
- startThread mit einem Sleep
- startThread(suspended) -> irgendwo anders wird der Thread nach einiger Zeit fortgesetzt
- Send/PostMessage mit einem von Programmierer festgelegten Code (WM_USER + X)
- SetWaitableTimer/CreateEvent/CreateTimerQueue usw.
Diese Checkroutine kann dann durchaus wiederum verzögert eine Aktion anstoßen, die keine Meldung ausgibt, sondern in den Programmablauf eingreift.
Oder (gemeinerweise) auch Aktionen mithilfe eines Zufallsgenerators durchführen:
if (random() < 0.1) then verzoegert(Absturz/Funktionsdeaktivierung) else nix.
Denn im Endeffekt ist es egal, ob das "gecrackte" Programm direkt oder erst nach 2-3-10 Minuten abstürzt/nichts mehr speichert
Abgesehen von der eigentlichen Checksummen-Routine (dazu wie gesagt, gleich mehr) ist dieser Eingriff in die Programmlogik relativ einfach durchzuführen (sowohl vom Entwickler wie auch durch Protector) und bei größeren Programmen wird sich der böse Cracker einen Wolf analysieren, um diese "Böse-CRC-Aktionsroutinen" zu finden.
Vor allem wenn er das Programm jedesmal mehrere Minuten laufen lassen muss und die ganzen Funktionen prüfen.
----------------------
D.h - sofern der Programmier selbst Zeit investiert oder einen professionellen Schutz verwendet (diese bieten oft genug auch eine Einbindung auf Quellcodeebene) ist er klar im Vorteil:
- Die Logik dieser Proteciton wird in der "highlevel" Sprache umgesetzt, die in tausenden Asm-Zeilen, ohne Kommentare/Dokumentation, resultieren
-
- Den Schutz auf dieser Ebene zu umgehen erfordert von dem bösen Cracker den zig-fachen Zeitfaufwand
-
- Ihm bleibt also kaum eine andere Wahl, als die eigentliche Checkroutine zu patchen (oder sonstwie zu manipulieren, dass die Patchs nicht erkannt werden)
-------------------------------------------------------------
Magic-Checks
-------------------------------------------------------------
Warum "Magic"? Eine Überlegung aus der Sicht des Programmierers:
Wie setzte ich den Check in einer Hochsprache um?
Man kann nichtmal "if crc(code)!=0xCAFEBABE" schreiben oder Dummywert einsetzen, da sich die Checksumme schon dadurch ändert

.
Also nur Teile der Exe prüfen. Da bringt das CRC-Plugin für PEID nicht viel, da die Bytes am Ende angefügt werden.
Oder man nutzt extra eine DLL/zweite Exe.
Grobe Ansätze:
- Zur Laufzeit die eigene Exe einlesen, Checksummen (zumindest von Teilen) berechnen. Ohne Inline-Asm bzw. professionelen Protector/entsprechende Entwickler ist damit auch für 95% aller Softwareprojekte Schluss (denn einen Kopierschutz kann man ja nicht nur durch Anti-Patching umsetzen, da gibt es noch Public-Keys + Verschlüsselung, Online-Gedöns mit "remote Codeausführung", Dongle usw).
Nachteil: lässt sich durch "Loader" aka "memory patcher" relativ einfach umgehen. Allerdings kann auch hier der eine oder andere Anti-Loder Trick angewendet werden.
Erkennung:
Ja, es muss die Exe selbst geöffnet werden. Also kann man alle CreateFileA/W Aufrufe (am besten in den SystemDLLs) beobachten. Natürlich steht hier auch der Entwicklerkreativität nichts im Weg: native API Aufrufe wie ZwOpenFile oder die Suchen entsprechender Imports in Kernel32/NTDLL über eine eigene Routine.
Bei größeren Anwendungen wird zudem die Beobachtung ohne Zusatzscripte/Tools ziemlich aufwändig, da bei einem Programmstart Dateien en Masse geöffnet werden.
Allgemein bleibt auch die Frage:
Wie erkennt man kurze Check-Algos wie CRC32 oder Adler32?
Zusatz: auch diese Routinen können wie oben beschrieben, verzögert gestartet werden. Zudem muss der Zugriff auf die Exe selbst keineswegs vom Entwickler veranlasst sein (z.B Lesen von Ressourcen/Manifest durch Bibliotheken/System-DLLs)
-
- Zur Laufzeit den Speicher prüfen. Natürlich nur CODE-Sections.
Imho nur bei einem Protector anzutreffen, da die Eigenentwicklung zu zeitaufwändig/fehleranfällig wäre.
Vorteil: einfache Loader/Memory patcher ziehen nicht mehr
Nachteil: allzu oft angwendet, zieht es Rechenleistung. Wie erwähnt, kompliziert umzusetzen (also nur Protector).
Lässt sich durch API-Hooks + Codeinjection umgehen (so kam ich zumindest zu meinem ersten Hook-Mempatcher
)
Erkennung:
Memory BPs auf die Codestellen. Dabei sollte zwischen Ausführung (EIP = Codestelle) und Check (read) unterschieden werden. Entsprechende Befehlssequenzen direkt zu erkennen halte ich für kaum machbar, da es
ein "rep movs bla; block_check bla" oder "mov eax, [esi]; Block_check; add esi,4; loop" oder "mov ebx, [ecx+ebx]; blub; sub ecx, FFFFFFFC" usw. sein kann. Wie der Compiler gerade drauf ist, es zu übersetzen.
-----------------------------------
Also eigentlich immer eine nachträgliche Erkennung der Checks (das, was Du vermeiden wolltest). Vor allem den zweiten Ansatz im Vorfeld (bei größeren Anwendungen) zu erkennen halte ich für nicht machbar.
Ausnahme wäre z.B die Erkennung eines Protectors und das Wissen, dass dieser solche Checks einsetzt
Grundsätzlich würde ich gar nicht versuchen, diese Checks direkt zu "bekämpfen", da man hier wieder mit "30-Zeilen-HLL == 300 bis 30000 Zeilen Asm" zu tun bekommt (geinlinten/stat. Bibliothekroutinen mitgerechnet).
Wie gesagt, die Fehlermeldung kann nur die Spitze des Eisbergs sein.
Stattdessen würde ich den Patch so gestalten, dass dieser nicht bemerkt wird.
Also Loader/Memorypatcher, die beliebig kompliziert werden können (z.B bei einer großen, geschützten NET Anwendung die Win-CryptoAPI hooken um einen falschen MD5 Wert zurückzuliefern. Oder bei Themida zwei WinAPIs hooken - der erste Aufruf patcht den Code, der zweite stellt den Originalzustand wieder her und ähnliche Spässe

).
Die Fehlermeldung kann hier ganz hilfreich sein (wenn diese nicht kommt, dann ist die Chance groß, dass auch die "versteckten" Checks nicht angesprungen sind).
-------------------------------------------------------
-------------------------------------------------------
Und zum anderen benötige ich wieder einmal eine kleine Hilfestellung und einen Rat. Ich habe mir einfach einmal das Programm...
OT:
Da wir in D. hosten und ich k.A habe, ob schon der Name, geschweige denn die Links ausreichen, um eine nette Abmahnung/Zivilklage anzustoßen, möchte ich bitten, keine Links/Programmnamen zu posten. Die kann man ggf. ganz privat über Email&Co austauschen.
So, nun stehe ich wieder einmal am Schlauch.
Denn nach einer Änderung (HexWorkshop oder Olly) und Speicherung der .exe erscheint diese Meldung:
Diese Meldung kennt man ja auch von anderen Programmen/Beispielen!
Selbst nach dem FIX (PeID, CRC) erscheint diese Meldung.
Also wird offensichtlich geprüft. Aber wo, durch was und wie?
Umgebung:
- WinXP in VirtualBox
- OllyDbg 1.10 ohne Plugins (allerdings gepatch, so dass "Odbg"/"OllyDbg" nirgendwo als String vorkommt)
Schritte:
- Start der Anwendung ohne Debugger: Lizenzfehler.
- Start der Anwendung in Olly: Lizenzfehler.
-
- Irgendwo in Olly im 0x005Exxxx Bereich ein Byte gepatcht und gespeichert -> Fehlermeldung wie im Screenshot.
-
- Überlegung:
Memory oder Dateicheck?
- Patchen der original Exe vor der Ausführung in Memory => keine Meldung
- Laden der gepatchen Exe in Ollydbg und Wiederherstellung der gepatchen Stelle vor der Ausführung => trotzdem Meldung.
Also muss zumindest eine Prüfroutine die Exe von dem Datenträger lesen.
-
- Überlegung 2: Lesen vom Datenträger => Breakpoint auf CreateFileW (in der Kernel32 DLL, sicher ist sicher)
-
- Treffer:
Code:
0012FB30 00461DBB /CALL to CreateFileW from mAirList.00461DB6
0012FB34 0012FB7E |FileName = "C:\crackme\mAirList-4.2.1\mAirList2.exe"
0012FB38 80000000 |Access = GENERIC_READ
Am Aufrufort sieht man sowas:
Code:
00461E1A E8 396FFAFF CALL <JMP.&kernel32.MapViewOfFile>
...
00461E34 66:8178 18 0B02 CMP WORD PTR DS:[EAX+18],20B
00461E3A 75 0B JNZ SHORT mAirList.00461E47
Hier wird also die Exe selbst gemappt und direkt losgelegt:
-
- EAX zeigt auf PE Header.
PE + 18 = "Magic" = (normalerweise) 10B für 32-Bit Exen und 20B für 64
Code:
00461E47 83C0 58 ADD EAX,58
00461E4A 8945 F4 MOV DWORD PTR SS:[EBP-C],EAX
00461E4D 8B45 F4 MOV EAX,DWORD PTR SS:[EBP-C]
PE + 0x58 = CheckSum;
Die, die vom Linker eingefügt wird. Danach sieht man einen CRC Aufruf und:
-
Code:
CMP
00461E93 /74 02 JE SHORT mAirList.00461E97
00461E95 |B3 01 MOV BL,1
Es wird also ermittelt, ob die Checksumme im PE-Header gültig ist. Bei "normalen" Patchs mittels Hexeditor/Olly stimmt's natürlich nicht.
Jedoch lässt sich dieser Wert mit einem guten PE-Editor (CFF Explorer/LordPE) korrigieren oder selber berechnen (z.B CheckSumMappedFile function (Windows) ). Dann gibt es auch keine Meldung mehr.