Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Tutorials und Kurse (https://www.delphipraxis.net/36-tutorials-und-kurse/)
-   -   Delphi Simpler PE-Crypter (https://www.delphipraxis.net/129498-simpler-pe-crypter.html)

mr_emre_d 20. Feb 2009 01:58


Simpler PE-Crypter
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hiho liebe Leute.

Ich möchte euch heute erklären, wie man in Delphi einen simplen Crypter schreibt !

In diesem Tutorial wird erklärt wie man die ".text" Section einer Exe Datei verschlüsselt, den Einsprungspunkt auf eine von uns selbst geschrieben (ASM) Procedure/Code umleitet, der die Section wieder entschlüsselt und zum orginalen Einsprungspunkt zurückkehrt !

(Nur so nebenbei: in der .text Section befindet sich der eigentliche Code und deshalb habe ich es in diesem Tutorial (unabsichtlich) abwechslend "text" und "code" verwendet - damit meinte ich aber dasselbe)

Voraussetzungen:
  • Fortgeschrittene Kenntnisse in Delphi
  • Datenstrukturen und Pointer müsstet ihr gut beherrschen
  • Assembler sollte kein Fremdwort sein

Zuerst einmal möchte ich euch warnen:
  • Es ist ziemlich spät und ich bin sehr müde - ich hoffe mal dass ich nicht viele Fehler mache :)
  • Ich achte meistens nicht auf die Richtigkeit meiner Texte sowohl im Sinne von Rechtschreibung als auch in der Grammatik ! (ich werds aber diesmal versuchen :P)
  • Ich versichere nicht auf 100% Richtigkeit meiner Angaben !
  • Dies ist mein allererstes Tutorial !
  • "Hier gibt es die Möglichkeit, dass Benutzer, die sich in einem Gebiet (oder mehreren Gebieten) besonders gut auskennen, ihr Wissen detailliert mit den andern teilen." -- ich würde nicht behaupten, dass ich mich besonders gut darin auskenne aber mein Code funktioniert !

http://www.delphipraxis.net/images/common/divider.jpg

Inhaltsangabe:
  1. Wichtige Details über eine Exe bzw den verschiedenen Headers
  2. Ungefähres Design des Programmes
  3. Das Problem mit den Adressen
  4. Die Implementierung[/b]

http://www.delphipraxis.net/images/common/divider.jpg

1. Wichtige Details über eine Exe bzw den verschiedenen Headers

Ich hatte nicht gewusst, dass die einzelnen Headers in Delphi schon vordefiniert sind und deshalb
machte ich mich auf die Suche nach bestimmten Artikeln, die diese beschrieben ! Da boten sich einige gute an ! Ihr könnt euch die von wotsit.org besorgen ! Sucht dort nach "PE-Header"
bzw Portable Executable..

Eine Exe ist wie folgt aufgebaut:
(wichtige Teile)
  • Dos-Header (Delphi: IMAGE_DOS_SIGNATURE);
  • ...Müll...
  • NT-Header(s) (Delphi: IMAGE_NT_HEADERS)
  • Sections (Delphi: _IMAGE_SECTION_HEADER);
    (unwichtig...)
  • Image Pages
  • import info
  • export info
  • fixup info
  • resource info
  • debug info

Ihr solltet euch diese drei Strukturen einmal genauer anschauen:

Der Dos-Header ist simple aufgebaut und steht am Anfang der Exe:
Delphi-Quellcode:
// alle hier vorgestellten Typen habe ich aus den Dokumentationen extrahiert !
    Signature        : Array[0..1] of Char;  // 4Dh 5Ah (MZ)
    LastPageSize     : Word; // number of bytes in last page
    FilePages        : Word; // number of 512 byte pages
    RelocItems       : Word; // number of entries in table
    HeaderParas      : Word; // size of header in 16 byte paras
    MinAlloc         : Word; // minimum memory required in paras
    MaxAlloc         : Word; // maximum memory wanted in paras
    PreRelocSS       : Word; // offset in paras to stack segment
    InitialSP        : Word; // starting SP value
    NegativeChecksum : Word; // currently ignored
    PreRelocIP       : Word; // execution start address
    PreRelocCS       : Word; // preadjusted start segment
    RelocTableOffset : Word; // is offset from start of file)
    OverlayNumber    : Word; // ignored if not overlay
    Nothing          : Cardinal; // end ...
    Reserved_Unused  : Array[0..6] of Cardinal;
    PEOff            : Cardinal; // offset of the header at off 60
Für uns sind folgende Einträge wichtig:
  • Signature - zum Überprüfen, ob es sich ume eine Exe handelt (bzw Dos Datei)
  • PEOff - hier ist der Offset zum eigentlichen Header - dem NT_Header

Der NT-Header (Delphi: IMAGE_NT_HEADERS) besteht seinerseits wiederum aus drei Teilen:
  • Signature
  • FileHeader]
  • OptionalHeader


Für uns sind unter Umständen folgende Einträge wichtig:
FileHeader:
o NumberOfSections - dazu komme ich später

OptionalHeader:
o AddressOfEntryPoint - Einsprungspunkt
o ImageBase - die Adresse, wo die Exe (Image) hingeladen wird

Dann gibts da noch die Sections ! Im Fileheader steht die Anzahl der Sections nämlich in NumberOfSections !
Delphi Deklaration von einer Section:
_IMAGE_SECTION_HEADER

Da der Eintrag "Misc" euch ein wenig verwirren kann, werde ich euch auch diese Struktur erklären
Delphi-Quellcode:
  TSection_Table = packed record
    Object_Name         : Array[0..7] of Char;  
    Virtual_Size        : Cardinal;            
    RVA                 : Cardinal;            
    Physical_Size       : Cardinal;            
    Physical_Offset     : Cardinal;            
    Reloc_Offset        : Cardinal;            
    Line_Numbers        : Cardinal;            
    Relocation_Number   : Word;
    Line_Numbers_Number : Word;
    Object_Flags        : Cardinal;  
  end;
für uns sind wiedermal folgende Sachen wichtig:
o Object_Name = beinhaltet, so wie der Name schon sagt, den Namen der Section :P
o Virtual_Size = gibt die virtuelle Größe der Section an (die Größe die es nach dem Laden ins Memory hat)
o RVA = Relative Virtual Address = die Adresse im Memory
Ihr fragt euch nun "auf was relativ" ?
Relativ auf die ImageBase-Adresse !!
o Physical_Size = die Größe in der Exe
o Physical_Offset = Adresse in der Exe
o Object_Flags = Nähere Definition, um was für eine Section es sich handelt - ob es beschreibbar/lesbar/ausführbar/... ist

http://www.delphipraxis.net/images/common/divider.jpg

2. Ungefähres Design des Programmes

Der Crypter muss folgende Schritte durcharbeiten:
1. Lese die komplette Exe ein
2. Prüfe ob die DOS.Signature von der Exe "MZ" lautet - wenn ja, dann fahre fort
3. Ermittle den PEOffset
4. Prüfe ob die NTH.Signature von der Exe "PE" lautet - wenn ja, dann fahre fort
Ermittle wichtige Informationen:
5. ImageBase
6. EntryPoint
7. NumberOfSections
8. Offset von ".text" - Section
9. ermitle die einzelnen Parameter dieser Section
10. Prüfe, ob diese Section einen Code-Cave hat UND ob diese >= unserem (ASM) Decrypter ist
11. Crypte diese Section (in unserem Fall mit Xor MagicNumber)
12. Passe unseren ASM-Code an
13. Füge den ASM-Code an das Ende der Section hinzu
14. setze den neuen Einsprungspunkt (Entrypoint) und passe ggf. Werte an

Im Großen und Ganzen wars das auch schon !

http://www.delphipraxis.net/images/common/divider.jpg

3. Das Problem mit den Adressen

Hier gibts eigentlich nicht viel zu sagen. Ich werds trotzdem tun, da
irgendwie viele an diesem Punkt scheitern:

Um die Adresse einer Sections im Speicher ermitteln zu können müsst
ihr die Imagebase von der Exe kennen und ihr braucht noch die VirtualAddress
der Section !

Die Adresse im Speicher = ImageBase + Section.VirtualAddress

http://www.delphipraxis.net/images/common/divider.jpg

4. Die Implementierung

Folgende Codeschnipsel habe ich aus meinem Projekt, welches ich mit angehangen habe, entnommen !

1. Diesen Schritt müsstet ihr schon alleine hinkriegen xD
Ich empfehle euch, die Daten in ein ByteArray (TByteArr = Array of Byte) zu speichern, da folgende Codeschnipsel darauf aufbauen !

2. Einfach schauen, ob die ersten 2 Bytes = MZ sind :
Delphi-Quellcode:
Result := (Chr(FileData[0]) + Chr(FileData[1])) = 'MZ'
3. Ermitteln von PE_Offset
Delphi-Quellcode:
  P.PE_Offset := PCardinal( @FileData[$3C] )^;
Der Offset von PE_Offset im Dos_Header ist $3C = 60 dezimal
Dort lesen wir halt 4 Bytes (PE_Offset = DWord) ein
Ach übrigens - P = TParameters
Delphi-Quellcode:
  TParameters = packed record
    {header:}
    PE_Offset  : Cardinal; // at $3C in the dos_header
    EntryPoint : Cardinal; // offset to org.ep
    ImageBase  : Cardinal;
    SecAlign   : Cardinal;
    {section:}
    Sections   : Word;     // cnt of sections
    CodeOffset : Cardinal; // offset to code (.text) : .. and his values:
    VirtualSize : Cardinal;
    VirtualAddr : Cardinal;
    RawSize    : Cardinal;
    RawAddr    : Cardinal;
    SectionCave : Cardinal;
  end;
4. Handelt es sich um einen validen PE-Header ?
Delphi-Quellcode:
  Result := chr( FileData[PEOffset] ) + chr( FileData[PEOffset+1] ) = 'PE';
5. Hole ImageBase
Delphi-Quellcode:
  P.ImageBase := PCardinal( @FileData[P.PE_Offset+$34] )^;
6. Der Einsprungspunkt wird hier eingelesen
Delphi-Quellcode:
  P.EntryPoint := PCardinal( @FileData[P.PE_Offset+$28] )^;

7. Ermittle die Anzahl der Sections
Delphi-Quellcode:
  P.Sections := PWord( @FileData[P.PE_Offset+6] )^;
8. Offset von ".text" - Section
Delphi-Quellcode:
// ÜbergabeParameter: FileData: TByteArr; SectionName: TObject_Name; var P: Parameters
// -- nur so nebenbei: TObject_Names = Array[0..7] of Char
var
  Section: TSection_Table;
  x: Word;
begin
  P.CodeOffset := P.PE_Offset + $D0; // 48
  x := 0;
  repeat
    inc( P.CodeOffset, SizeOf( TSection_Table ) );
    Section := PSection_Table( @FileData[P.CodeOffset] )^;
    inc(x);
  until (Section.Object_Name = SectionName) or (x > P.Sections);
  if P.CodeOffset = P.PE_Offset + $D0 then
    P.CodeOffset := 0;
Hier werden die Sections eingelesen und es wird geprüft ob es sich um die
gesuchte Section handelt ! Dies wird solange gemacht, bis man alle Sections durch hat.
Falls nichts gefunden werden konnte, wird 0 zurückgegeben !

9. Ermittle einzelne Werte dieser Section:
Delphi-Quellcode:
// Übergabe Parameter = FileData: TByteArr; var P: TParameters
  with PSection_Table( @FileData[P.CodeOffset] )^ do
    with P do
    begin
      P.VirtualSize := Virtual_Size;
      P.VirtualAddr := RVA;
      P.RawSize    := Physical_Size;
      P.RawAddr    := Physical_Offset;
    end;
10. Cave ermitteln:
Die Größe des Caves kann man wie folgt ermitteln:
RawSize - VirtualSize // RawSize = Physical_Size

11. Crypten der Section
Delphi-Quellcode:
// Übergabe Parameter = var FileData: TByteArr; SectionStart, SectionEnd: Cardinal;
// Magic: Byte
// Magic wird für die Xor-Verschlüsselung verwendet !
var
  i: Integer;
begin
  for i := SecStart to SecEnd do
    FileData[i] := FileData[i] xor Magic;
12. ASM-Code erstellen und anpassen:
Zuerst einmal erstellen wir einen Container.. ja so nenne ich das - "Container"
Diesen Container befüllen wir nachher mit den gewünschten Adressen und zwar:
SectionStart
SectionEnd
OrginalEntryPoint
Delphi-Quellcode:
  mov eax, .codestart // eax := CodeStart ...
  mov edx, .codeend
  mov ecx, orginal entrypoint
  // mainloop start:
  xor ss[eax], magic // Eax^ := Eax^ xor magic
  inc eax             // inc( eax )
  cmp eax, edx       // if not CodeStart = CodeEnd then
  jne mainloop         // repeat ... springe zurück zu mainloop
  // jmp to entrypoint // else
  jmp ecx             // springe zum EntryPoint
Man kann die einzelnen Bytes durch das Debuggen ermitteln:
Code:
     $B8, $00, $00, $00, $00,
     $BA, $00, $00, $00, $00,
     $B9, $00, $00, $00, $00,
     // mainloop start:
     $36, $83, $30, $00,    
     $40,                    
     $39, $D0,                
     $75, $F7,                
     // jmp to entrypoint
     $FF, $E1 );
Ich habe ein Array mit diesen Werten befüllt und ein Paar Index-Konstanten deklariert, damit ich später leichter darauf zugreifen kann !
Wie ihr sehen in den ersten 3 Zeilen unseres Code jede Menge Nullen.
Diese werden wie schon erwähnt mit den Adressen befüllt !

Unserer Container-Ersteller Procedure/whatever übergeben wir folgende Parameter:
CodeStart: ImageBase + (Section)VirtualAddr
CodeEnd: ImageBase + (Section)VirtualAddr + (Section)VirtualAddr
EntryPoint: ImageBase + EntryPoint
Magic: Magic ! Dieser Wert muss = Wert, mit dem ihr die Section gecrypted habt, sein !

13. Den "Container" in die Datei einfügen
Delphi-Quellcode:
// Übergabe Parameter: Offset zur Ende der Section
  Move( Stub[0], FileData[Offset], Length(Stub) );
Offset = RawAddr+VirtualSize !!

14. Den neuen Einsprungspunkt setzen und Werte anpassen:
Dazu habe ich mir eine Hilfsfunction Namens "Parameters" geschrieben,
die mir eine TParameters-Struktur mit den übergegebenen Werten
zurück liefert;
Diese Procedure SetSectionParams setzt die Parameter und
was noch wichtig ist:
Es setzt die Flags auf writeable / executable !
Object_Flags := SECTION_WRITEABLE_EXECUTEABLE;
Delphi-Quellcode:
  SetSectionParams( FileData, Params,
    Parameters(PE_Offset, EntryPoint, ImageBase,
    SecAlign, Sections, CodeOffset,
    VirtualSize + Length(Stub), VirtualAddr, RawSize,
    RawAddr, SectionCave) );
den neuen EntryPoint setzen:
Delphi-Quellcode:
// Übergabe Parameter: var FileData: TByteArr; P: Parameters; NexEntryP: Cardinal
  PCardinal( @FileData[P.PE_Offset+$28] )^ := NewEntryP;
NewEntryP = VirtualAddr+VirtualSize

http://www.delphipraxis.net/images/common/divider.jpg

So puh ... War n ganzes Stück Arbeit.

Ich bin erschöpft; Ich hätte nie gedacht, dass Tutorials schreiben so
anstrengend sein können :pale:

Ich hoffe auf konstruktive Kritik ! Wie schon ganz am Anfang erwähnt ist dies mein
erstes Tutorial !

Achja: Ich weiß gerade gar nicht wie die ganze Formatierung schlussendlich aussehen wird -> deshalb
werde ich öfters editieren müssen :) Also wundert euch nicht, wenn ihr eine zweistellige Zahl
unten bei "X - Mal bearbeitet" seht !

Falls es euch gefällt, könnte ich euch noch das Decrypten erklären!

EDIT: Achja bevor ich es vergesse - es gibt keine Fehlerbehandlungen !

MfG und gute Nacht
Emre

mleyen 20. Feb 2009 07:41

Re: Simpler PE-Crypter
 
Guten Morgen,

ich sag schonmal im vorraus, dass bei diesem Tutorial mein momentaner Kentnissstand überschritten wird.
Bevor ihr jetzt aber anfangt um die wette zu (de)crypten, habe ich noch eine kurze Frage, die ich dabei nie so ganz verstanden habe.
Zitat:

Zitat von mr_emre_d
In diesem Tutorial wird erklärt wie man die ".Code" Section einer Exe Datei verschlüsselt, den Einsprungspunkt auf eine von uns selbst geschrieben (ASM) Procedure/Code umleitet, der die Section wieder entschlüsselt und zum orginalen Einsprungspunkt zurückkehrt!

Die Frage: Wozu macht man diesen Aufwand?
Irgendwie verstehe ich den Sinn dieser ganzen Angelegenheit nicht. :duck:
Das einzige, was ich mir vorstellen könnte wäre es, Programme wie "DeDe" auszutricksen, damit man seine Codeinhalte "versteckt". Stimmt das?

Zum Tutorial:
Sehr gut geschrieben. Imho habe ich soweit alles Oberflächlich verstanden.
(Sobald ich Zeit habe, werde ich mich auch mal intensiv damit beschäftigen, dann kann ich auch mitreden.) :pale:

MfG
Marcel

brechi 20. Feb 2009 08:17

Re: Simpler PE-Crypter
 
Du solltest schon mit den beigelieferten Records in der windows.pas arbeiten. Inbesondere so sachen wie +$24 für den EP gibt da direkt als "....EntryPoint" und 'MZ' als IMAGE_DOS_SIGNATURE wenn ich mich nicht ganz irre. Außerdem schreibst du einmal von der ".Code" und einmal von der ".Text" Sektion.

Tut is also noch ausbaubar, inbesondere wenns darum geht eigene APIs im Loadcode zu benutzen muss schon mehr gemacht werden -> Anpassung Import tbaelle etc.
Find gerade meinen Crypter nicht sonst würd ich den Sourcedavon anhängen.

mleyen 20. Feb 2009 08:38

Re: Simpler PE-Crypter
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich hab da mal was im DF gefunden.
uall@ogc/brechi hat seinen execrypt_v13 mit source veröffentlicht. (siehe Anhang)
(Da steht bestimmt so einiges interressantes drin)
Damals hat Antivir mich jedoch nach jedem testcrypt mit Virenmeldungen nur so überhäuft. (also vorsicht) :?

Edit:
Oh, achso, brechi=ogc.
Hmm auf den FTP liegen noch einige sachen, die nichts hiermit zu tun haben, ich lad es mal lieber mal als Anhang hoch.

toms 20. Feb 2009 08:42

Re: Simpler PE-Crypter
 
FYI, uall@ogc = brechi

brechi 20. Feb 2009 10:28

Re: Simpler PE-Crypter
 
Die Version liegt auch hier:
http://uall.cheat-project.com/execrypt/execrypt1.3.txt

Verschlüsselt mir RC4, da der Key aber in der Exe ist -> Sinnlos. Man könnte eine Abfrage einbauen, dann würds sogar (ein wenig) sicher sein ;)

Es gab aber noch ne 1.5er Version, die die Daten noch gepackt hat. Muss ich mal schaun ob ich se finde wenn ich zu Hause bin.
Ich glaube nicht nur AntiVir meckert. Solche Crypter werden halt viel für Viren etc. benutzt :/. Teilwese ist es möglich mit wenig Änderugnen einen
Crypter zu erstellen der dann bekannte Viren so modifiziert, dass Sie nicht mehr erkannt werden. Und AV-herstellen wollen dann nicht die einzelnen
Viren wieder erkennen, sondern setzen den Crypter auf ihre Blacklist.

Und ja me=brechi=uall@ogc. Wenn es gehen würde hätte ich mich schon hier im Forum mal umbenannt, weil das echt ab manchmal zur Verwirrung führt :)

mr_emre_d 21. Feb 2009 11:55

Re: Simpler PE-Crypter
 
Zitat:

Zitat von spawn89
Guten Morgen,
Irgendwie verstehe ich den Sinn dieser ganzen Angelegenheit nicht. :duck:
Das einzige, was ich mir vorstellen könnte wäre es, Programme wie "DeDe" auszutricksen, damit man seine Codeinhalte "versteckt". Stimmt das?

Ja so ca :) Der Codeinhalt wird nicht versteckt, sondern verschlüsselt.

Zitat:

Zitat von spawn89
Sehr gut geschrieben. Imho habe ich soweit alles Oberflächlich verstanden.

Danke. Tut gut soetwas zu lesen :P

Zitat:

Zitat von brechi
Du solltest schon mit den beigelieferten Records in der windows.pas arbeiten.

Ja wie schon gesagt, wusste ich das am Anfang nicht :stupid:

Zitat:

Zitat von brechi
Inbesondere so Sachen wie +$24 für den EP gibt da direkt als "....EntryPoint" und 'MZ' als IMAGE_DOS_SIGNATURE wenn ich mich nicht ganz irre

Ähm ich versteh das irgendwie nicht.. sorry. Falls du damit meinst, dass ich das "leserlicher" programmieren soll:
Das ist mir relativ egal gewesen, da bei diesem kleinen Projekt eh fast alles Spaghetticodemäßig ist und mir gings hauptsächlich um die Technik!
Andererseits ist es ein Tutorial.. Hmm. Ich werde evt. noch Änderungen vornehmen :)


Zitat:

Zitat von brechi
Tut is also noch ausbaubar, inbesondere wenns darum geht eigene APIs im Loadcode zu benutzen muss schon mehr gemacht werden -> Anpassung Import tbaelle etc.
Find gerade meinen Crypter nicht sonst würd ich den Sourcedavon anhängen.

Naja es ist ja ein "simpler" Crypter von daher denke ich nicht, dass ich das jetzt unbedingt ergänzen sollte.

MfG

ErazerZ 21. Feb 2009 13:08

Re: Simpler PE-Crypter
 
Ich hab mal eine PE Unit geschrieben in Delphi die einem ermöglichen eine PE datei zu verändern, bei den Beispielen hab ich auch einen Execrypter rein falls es jemanden interessiert.
Link: http://www.delphipraxis.net/internal...384&highlight=

mr_emre_d 21. Feb 2009 16:26

Re: Simpler PE-Crypter
 
Schön sauber programmiert. Klasse gemacht :thumb:

Apollonius 22. Feb 2009 10:26

Re: Simpler PE-Crypter
 
Wozu greifst du in der Entschlüsselungsroutine auf ss[eax] zu? Die Daten liegen ja nicht auf dem Stack. Lass das Segment-Präfix doch einfach weg.
Eine ganz kurze Anmerkung zur Form: Vor Ausrufezeichen steht kein Leerzeichen. Überhaupt stört deren große Anzahl den Lesefluss.

mr_emre_d 22. Feb 2009 10:35

Re: Simpler PE-Crypter
 
Ach ja? Ich dachte mir immer, dass beide im Ram liegen (Programm und Stack).
Wenn das so ist wie du es sagst, ist es wunderlich, dass es überhaupt funktioniert.

MfG

Apollonius 22. Feb 2009 10:39

Re: Simpler PE-Crypter
 
Es ist nicht verwunderlich, dass es funktioniert. Windows verwendet Segmentation praktisch nicht, beispielsweise zeigen alle Segmente auf die gleiche Startadresse. ss[eax] ist in diesem Sinne aber erstens irreführend und zweitens kostet es ein Byte im Code. Wenn du nur [eax] schreibst, wird implizit das ds-Segment verwendet und das Segment Override Prefix fällt weg.

himitsu 22. Feb 2009 10:40

Re: Simpler PE-Crypter
 
Zitat:

Zitat von mr_emre_d
Zitat:

Zitat von spawn89
Guten Morgen,
Irgendwie verstehe ich den Sinn dieser ganzen Angelegenheit nicht. :duck:
Das einzige, was ich mir vorstellen könnte wäre es, Programme wie "DeDe" auszutricksen, damit man seine Codeinhalte "versteckt". Stimmt das?

Ja so ca :) Der Codeinhalt wird nicht versteckt, sondern verschlüsselt.

die "besseren" Decompiler und Co. lesen eh den "Code" aus'm RAM des laufenden Programms aus.
und um die "einfachen" Decompiler zu ärgern, reicht es schon z.B. einige unwichtige Delphitypische Teile zu löschen/verändern.

Und was z.B. das Speichermanagement und die Virenscanner betrifft ... hier gab's schon öfters mal Theman zu Exe-Packern und so.

Xen 27. Jun 2011 19:52

AW: Simpler PE-Crypter
 
Nennt mich ThreadLeichen-Schänder, aber ich hab da mal ne Frage bzw. ein Problem.

Die Sache mit dieser Assembler Stub finde ich unglaublich spannend!
Wegen dem Tutorial hab ich mich gleich auf Assembler gestürtzt :D
Deswegen wollte ich nicht den selben Code nehmen wie im Tutorial.
Damit ein wenig spannender wird, wollte ich das ganze etwas komplizierter gestalten, nur geht es jetzt nicht mehr :(:

Nach dem Tut wird jedes Byte der Section mit dem Key geXORed.
(Funktioniert ja auch wunderbar)

Ich wollte das folgendermaßen machen:

Ich Xore das ERSTE Byte der Section mit dem Key (Magic)
Das 2. Byte Xore ich mit dem Ersten (was ja schon mit Magic Xored ist)
Danach Xore ich das 3. Byte mit dem 2.
Danach das 4. mit dem 3.
usw.
bis ich am Ende ankomme.

Funktioniert soweit.

Zum Entschlüsseln gehe ich der Einfachheit halber von hinten nach vorne durch die Section:

Ich nehme das vorletzte Byte und Xore es mit dem Letzten ( = Letztes Byte jetzt im Klartext)
Ich nehme das vorvorletzte Byte und Xore es mit dem vorletzten ( = Vorletztes Byte jetzt im Klartext)
Ich nehme das vorvorvorletzte Byte und Xore es mit vorvorletzten ( = Vorvorletztes Byte im Klartext)
...
Bis ich beim ERSTEN Byte angekommen bin. Das wiederum Xore ich mit dem Key ( = Ganze Section entschlüsselt)

Das ganze habe ich in Assembler geschrieben:

(Alle $1100.. und $00 Adressen werden nacher durch echte Adressen ersetzt)
Delphi-Quellcode:
asm

                MOV eax, $11000000 // ENDE der Section ImageBase + V.Addr + V.Size
                MOV edx, $11000000 // Echter EntryPoint
                DEC eax   // Einen Runter

         @loop: CMP eax, $11000000 // Wenn gößer als der START Imagebase + V.Addr
                JE @lastbyte // Wenn gleich dann Springen

                  DEC eax      //Zum Byte davor gehen
                  MOV ecx, [eax] //Byte Davor speichern
                  INC eax      //Wieder zu dem noch verschlüsselten zurück
                  XOR [eax], ecx //Mit ECX entschlüsseln

                  DEC eax      // Wieder aufs vorige Byte zurück
                  JMP @loop

     @lastbyte: XOR [eax], $00  // Letztes byte mit Key entschlüsseln
                JMP edx      // Zum Echten Entry Point springen
end;
Das Funktioniert aber leider nicht. Die Exe ist nacher beschädigt :(

Hat Irgendjemand ein wenig Ahnung von Assembler und kann mir sagen was ich dort falsch mache?

Die Idee dahinter funktioniert. Ich habe die verschlüsselte Datei mal nacher mit einem "Zeile für Zeile von ASM nach Delphi"-Code entschlüsselt.
Ergebnis: Exe funktioniert. (Ich benutze ein in Delphi geschriebenen Pizza-Timer :D )

Hier ist der "Zeile für Zeile von ASM nach Delphi"-Code:
Delphi-Quellcode:
                eax := SecEnd; // ENDE der Section ImageBase + V.Addr + V.Size
                Dec(eax);

          loop: if eax = SecStart then // Wenn gößer als der START Imagebase + V.Addr
                  goto lastbyte; // Wenn gleich dann Springen

                  Dec(eax);      //Zum Byte davor gehen
                  ecx := FileData[eax]; //Byte Davor speichern
                  Inc(eax);      //Wieder zu dem noch verschlüsselten zurück
                  FileData[eax] := FileData[eax] XOR ecx; //Mit ECX entschlüsseln

                  Dec(eax);     // Wieder aufs vorige Byte zurück
                  goto loop;

    lastbyte:   FileData[eax] := FileData[eax] XOR Magic; // Letztes byte mit Key entschlüsseln
Wie gesagt hier gings nur darum die Funktion des ASM exakt nachzubilden.
Aber es funktioniert.

Jetzt meine Frage:

Was macht mein "Wannabe"-ASM Code richtig, was mein echter ASM Code falsch macht?

himitsu 27. Jun 2011 22:03

AW: Simpler PE-Crypter
 
Wenn du deine beiden Ver-/Entschlüsselungscodes in Funktionen verpackst, dann kannst du sie ganz einfach mal nacheinander im Delphi-Debugger über einen Speicherblock jagen und schauen was wann warum schief läuft.

PS:
Delphi-Quellcode:
DEC eax //Zum Byte davor gehen
MOV ecx, [eax] //Byte Davor speichern
INC eax //Wieder zu dem noch verschlüsselten zurück
XOR [eax], ecx //Mit ECX entschlüsseln
Delphi-Quellcode:
MOV ecx, [eax-1] //Byte Davor speichern
XOR [eax], ecx //Mit ECX entschlüsseln

Wobei du auch von vorne nach hinten gehn kannst.

Delphi-Quellcode:
eax := Startposition
temp := Startwert
loop:
temp2 := [eax]
[eax] := [eax] xor temp
temp := temp2
inc eax
goto loop


PPS: dein Vorgehen ist sogar noch unsicherer
denn alles, bis auf das erste Byte kann ohne Kenntnis des Startwertes (der Verschlüsselung) entschlüsselt werden, da man den Startwert der Entschlüsselung kennt.

OK, bei einer so einfachen Verschlüsselung mit einem 1 Byte-Schlüssel braucht man eh nur durchschnittlich 128 Versuche und man hat es auch so entschlüsselt.

Aphton 28. Jun 2011 10:26

AW: Simpler PE-Crypter
 
"Das Funktioniert aber leider nicht. Die Exe ist nacher beschädigt"

Das kann zunächst einmal an folgendem liegen:

1. du packst in EDX die absolute Adresse rein - du solltest aber mit Relativen arbeiten -> ImageBase + relative Adresse
Da die ImageBase von Windows PE Loader geändert werden kann und somit die Image an einem ganz anderen Ort liegt

2. fügst du deinen Stub wirklich in ein Cave und überschreibst keine wichtigen Daten bzw. hat es so funktioniert, wie du es von meinem Tutorial übernommen hast?!

Luckie 28. Jun 2011 10:45

AW: Simpler PE-Crypter
 
Zitat:

Zitat von Aphton (Beitrag 1108619)
Da die ImageBase von Windows PE Loader geändert werden kann und somit die Image an einem ganz anderen Ort liegt

Was aber bei einer Exe sehr unwahrscheinlich ist.

Aphton 28. Jun 2011 11:03

AW: Simpler PE-Crypter
 
Ja aber halt für alle Fälle...

Xen 28. Jun 2011 23:35

AW: Simpler PE-Crypter
 
@himitsu
Wow, der Code fürs vorwärts entschlüsseln ist ja nochmal deutlich kürzer!

Zum Rückwärtscode:
Kann man das denn überhaupt so schreiben???
Code:
MOV ecx, [eax-1] //Byte Davor speichern
XOR [eax], ecx //Mit ECX entschlüsseln
[eax-1] Sieht irgendwie so "Delphisch" aus. Ich hab gedacht jede Arithmetik Operation muss man extra angeben (w.z.B. DEC oder INC)



@Aphton:
1. Ja ich verwende die relative Andressen. Also immer ImgBase + VAddr für den Start, und ImgBase + VAddr + VSize fürs Ende.
Also exakt wie im Tutorial beschrieben.

2. Zum Cave. Ja ... der wird mit 100% Sicherheit hinter das letzte beschriebene SectionByte gesetzt. Also wirklich da wo vie V.Size endet.
Das ganze habe ich mehrmals im Hex-Editor überprüft.


Um zu überprüfen das es am ASM Code liegen muss, habe ich das Ganze (also En/Decrypter) in die Unit aus dem Tutorial verfrachtet.
Mit selben Ergebnis: Exe Kaput bei meinem ASM Code. Exe heil bei mr_emre_d's Original ASM Code.

:cry:

Ist denn der ASM Code wie ich ihn gepostet habe von der Logic u. Syntaktik korrekt?
Da der hier angebotene ASM Crashkurs nicht allzuumfangreich ist habe ich mir vieles einfach zusammen gereimt.
War ich denn richtig der Annahme das "[eax]" auf den Inhalt der Adresse die in eax selbst gespeichet ist zugreift?


Was mir Wahrscheinlich extrem helfen würde wäre den decrypting Prozess in der "Ziel-Exe" direkt im Ram verfolgen zu können.
Wie kann ich das bewerkstelligen? Kann ich für sowas den Delphi Debugger nehmen oder lieber einen externen wie OllyDBG?


Schonmal vielen lieben Dank für die Hilfe!

Aphton 28. Jun 2011 23:53

AW: Simpler PE-Crypter
 
Zitat:

Ist denn der ASM Code wie ich ihn gepostet habe von der Logic u. Syntaktik korrekt?
Da der hier angebotene ASM Crashkurs nicht allzuumfangreich ist habe ich mir vieles einfach zusammen gereimt.
Falls ich morgen Lust habe, helfe ich dir. Bin momentan zu Müde dafür.

Zitat:

War ich denn richtig der Annahme das "[eax]" auf den Inhalt der Adresse die in eax selbst gespeichet ist zugreift?
Ja

Zitat:

Was mir Wahrscheinlich extrem helfen würde wäre den decrypting Prozess in der "Ziel-Exe" direkt im Ram verfolgen zu können.
Wie kann ich das bewerkstelligen? Kann ich für sowas den Delphi Debugger nehmen oder lieber einen externen wie OllyDBG?
Codestelle markieren (Breakpoint setzen) und dann in den CPU - Modus/Ansicht wechseln (STRG+SHIFT+C) und per F7 Stück für Stück durchsteppen!
Ollydbg. wäre natürlich noch angenehmer, aber da muss man zuerst einmal die Stelle finden, was für Anfänger nicht so einfach ist.

himitsu 29. Jun 2011 00:20

AW: Simpler PE-Crypter
 
Zitat:

Zitat von Xen (Beitrag 1108746)
Zum Rückwärtscode:
Kann man das denn überhaupt so schreiben???

Aber sicher doch. :angle:

Schau dir einfach mal den erzeugten Maschienencode an :zwinker:

Die ASM-Befehle verstehen hierbei einige verschiedene Offsets, aber meistens nur in kleineren Bereichen und in Schritten von Zweierpotenzen
und ist auch nicht bei allen Registern gleich. (wenn was nicht geht, dann wird es der Debugger schon bemängeln)

PS: Der Delphi-InlineASM-Code muß ja auch irgendwie in ein Format gebracht werden, welches Intel, AMD und Co. verstehen. Da kann Delphi auch nicht sein eigenes Süppchen kochen, sondern muß sich an die Regeln halten. (ein ASM-Befehl im Code wird in einen ASM-Befehl für die CPU umgewandelt ... da wird nix zusammengeschustert)


Zitat:

Codestelle markieren (Breakpoint setzen) und dann in den CPU - Modus/Ansicht wechseln (STRG+SHIFT+C) und per F7 Stück für Stück durchsteppen!
Ollydbg. wäre natürlich noch angenehmer, aber da muss man zuerst einmal die Stelle finden, was für Anfänger nicht so einfach ist.
Wobei es in Delphi garnicht so einfach ist, einen Bootloader zu debuggen. (sowas war ja auch nie vorgesehn)
Drum ja der Tipp das erstmal als Funktion zu testen, wo man den Haltepunkt direkt im Quellcode setzen kann.
Dort könnte man sogar in Quellcode debuggen und muß nicht unbedingt in die CPU-Ansicht.
Überwachte Ausdrücke lassen sich auch auf Register setzen oder zum Anzeigen von Speicherbereichen nutzen. :freak:

:snowball:

Aphton 29. Jun 2011 12:34

AW: Simpler PE-Crypter
 
Du hast vollkommen Recht, Himitsu.

@Xen: Mach zuerst mal das, was er vorgeschlagen hat!
Packe deine Ver- und Entschlüsselungsroutine in Proceduren und wende sie an einen Datenblock an. Wenn gilt:
Entschlüsseln(Verschlüsseln(Datenblock)) = Datenblock
dann ist alles in Ordnung!

Edit: Anschließend, falls es nicht daran lag und die Exe immernoch nicht funktioniert, könntest du mal die Exe hier hochladen und ich schaus mir genauer an...
Ansonsten müsstest du halt noch an deinem "Stub" rumpfeilen!


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:21 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz