PE Infektion

Hallo liebes Forum!

Um noch mal auf das Thema Bildanalyse zurückzukommen:

Ich habe mich die letzten Stunden mal etwas mit dem Aufbau eines Bildes beschäftigt und ihn mir in einem Hexeditor angeschaut!
Ich finde es ebenfalls höchst interessant zu wissen, wie man Text in Bildern versteckt!!
Was ich schon wusste war, wie man ein Programm in Bildern versteckt, jedoch nicht auf der Ebene, auf der ich mich gerade bewege.

Jeder weiß, dass man mit der Commandozeile copy /B Bild.jpg + Geheim.rar Bild.jpg die Datei Geheim.exe in das Bild kopieren kann, und diese per Entpacken des Bildes dann wieder bekommt.
Mich würde es jedoch interessieren, ob man auch einfach den Hexcode des Programms mit einem Hexeditor an den Hexcode des Bildes anhängen kann, und diesen dann nachher irgendwie wieder voneinander trennen kann...ist denn das prinzipiell möglich??

Viele Grüße
Gapa
 
Jeder weiß, dass man mit der Commandozeile copy /B Bild.jpg + Geheim.rar Bild.jpg die Datei Geheim.exe in das Bild kopieren kann, und diese per Entpacken des Bildes dann wieder bekommt.
Mich würde es jedoch interessieren, ob man auch einfach den Hexcode des Programms mit einem Hexeditor an den Hexcode des Bildes anhängen kann, und diesen dann nachher irgendwie wieder voneinander trennen kann...ist denn das prinzipiell möglich??
mit copy /b wird einfach eine Datei (oder mehrere) an andere gehängt. Ohne irgendwelche "Trennzeichen".

Datei1: (hex dump: )
Code:
450a

Datei2: (hex dump: )
Code:
12b17c

gibt als resultat eines copy /b:
Code:
450a12b17c

Du müstest also irgend eine markante, eindeutige Bytefolge haben, um den beginn der neuen Datei zu bestimmen.

Bei einem Programm ist das nicht mal so schwer. Da im PE Header meist noch alte DOS Header rumschwirren kannst du da leicht eindeutige Bytefolgen feststellen.
 
PE-Header

Ah...jetzt wirds langsam interessant :D

Da habe ich jetzt ein paar Fragen:

1.
Was genau ist der PE-Header??

2.
Wenn so mein Programm im Hexeditor aussieht:
Code:
MZ|.........YY..
,........@.......
..................
..................
..(komisches Zeichen)..I!,.LI!This program cannot be run
in DOS mode.....$.....
SjS..|..(usw)
Wo ist dann hier der PE-Header??

3. Wo erkenne ich, wann der Header beendet ist und wo das Programm anfängt??

4. Wie kann ich Kommentare in das Programm einfügen? Ich weiß, dass es mit jpgs mit den Tags <> geht, aber geht das auch bei exe??

5. Wenn ich die Größe des Programms ändere, muss ich das dann auch im Header angeben, oder warum wird mir ständig eine Fehlermeldung ausgeworfen, sobald ich nur das kleinste Detail dazufüge oder ändere??

6. Wenn ich per copy /b Bild1.jpg + Bild2.jpg Bild.jpg die zwei Bilder in ein Bild kopiere und öffne, so öffnet sich nur Bild1!! Wie stelle ich es an, dass sich beide Bilder öffnen oder dass wenigstens beide Bilder angezeigt werden? Muss ich da irgendwelche Begrenzer löschen??

7. Wenn ich obiges mit 2 exe versuche, und die exe dann öffne, kommt folgende Fehlermeldung: "exe corrupted"...aber wieso? Die ist doch gar nicht beschädigt??

Ich hoffe auf möglichst viele Antworten...wäre echt nett!!

Viele Grüße
Gapa
 
In diesem Thread soll es um das Crackme gehen, nicht um den Aufbau von verschiedenen Dateitypen.
Auf alle von dir gestellten Fragen lässt sich mit ein bisschen Eigeninitiative mithilfe von Google eine Antwort finden.
Solltest du tiefgreifendere Fragen zu dem Thema haben, dann mach doch einfach einen Thread dazu auf.

Bitte nicht alles persönlich nehmen, aber mit Suchbegriffen wie "Portable Executable File Format" kommt man wirklich schnell zu Treffern wie: http://www.csn.ul.ie/~caolan/publink/winresdump/winresdump/doc/pefile.html
Ausserdem würde ich dir empfehlen, dich erstmal mit den verschiedenen Formaten und den Aufbau von Dateien im Allgemeinen zu beschäftigen, bevor du in Themenbereiche wie Steganographie einsteigst.

mfg, loose
 
Dateiformate / Steganographie

Hallo loose,

Tut mir Leid, dass ich diesen Thread benutze, um mir Antworten auf meine Fragen zu verschaffen, aber ein neuer Thread ohne Crackme hätte in diesem Forum wohl auch nichts verloren, oder?

Bitte sage mir, in welches dieser Unterforen ich diesen Thread stellen könnte, und ich werde es sofort tun!
Bitte nicht alles persönlich nehmen, aber mit Suchbegriffen wie "Portable Executable File Format" kommt man wirklich schnell zu Treffern wie: http://www.csn.ul.ie/~caolan/publink/win...doc/pefile.html
Ja siehst du! Ich wusste nicht einmal nach was ich genau suchen sollte...niemals wäre ich auf den Begriff "Portable Executable File Format" gekommen, da ich mich damit (wie du richtig gesagt hast) noch nicht gut genug auskenne.
Ausserdem würde ich dir empfehlen, dich erstmal mit den verschiedenen Formaten und den Aufbau von Dateien im Allgemeinen zu beschäftigen, bevor du in Themenbereiche wie Steganographie einsteigst.
Sehe ich genau so! Aber ich wäre dir hier wirklich SEHR SEHR dankbar, wenn du mir ein paar nützliche Links posten würdest, wo ich wirlklich exakt das lerne!
Normalerweise komme ich mit Google immer zurecht, aber diesmal scheitere ich! Ich finde keine nützlichen Quellen, von denen ich den Aufbau jeglicher Dateiformate lernen kann! Das könnte wohl auch zum Großteil daran liegen, dass ich nicht mal die Stichworte weiß, welche ich in google eingeben müsste^^ - > "PE File Format"... 8)

Ich hoffe auf ein paar nützliche (möglichst deutsche) Links!

Viele Grüße
Gapa
 
Pe

Hallöle!

Wow vielen Dank für diesen sehr nützlichen Link!!
Jetzt ist mir schon mal einiges klarer geworden!!!
Jedoch komme ich nun nicht mehr weiter:

HexBild.JPG


erst an Position 0x03C ist die Adresse des "neuen" Headers (PE) angegeben.
(habe ich ausgelesen! siehe rote Markierung!)
Geht man zu dieser Adresse, sieht man die zwei Buchstaben "PE".
Stimmt auch!
Weitere Angaben sind relativ zu dieser Adresse (als PE+0x geschrieben)
Was meint er damit?? (PE+0x???)Diesen Satz verstehe ich nicht!
In PE + 0x28 befindet sich der Entry Point
Hier gehen die Probleme los!
Meint er mit "PE" die Adresse 0x00100??
Wenn ja, dann müsste ja PE + 0x028 ja die Adresse bzw. Position 0x128 / 128 sein, oder?
Mal hier kurz zum Verständnis: Was ist der Unterschied zwischen Adresse und Position? Im Endeffekt ist doch jede Adresse eine Position und jede Position kann man als Adresse schreiben, oder??
Und haben all diese Adressen links an der Seite nachher eine Bedeutung beim Programmablauf? Sind das denn die Adressen nachher im Stack?? NE, oder? Das sind einfach nur Orientierungspunkte im Programm, oder?

Nun um wieder auf meine Frage zurückzukommen: Ist der EntryPoint das von mir grün markierte??? Wenn ja, was sagt mir das??

Viele Grüße
Gapa
 
Thema gesplittet.

Weitere Angaben sind relativ zu dieser Adresse (als PE+0x geschrieben)

Was meint er damit?? (PE+0x???)Diesen Satz verstehe ich nicht!
Er meint damit folgendes: der Vermerk/Zeiger auf PE-Anfang ist immer an 0x03C. Der PE-Anfang an sich ist aber "dynamisch" - kann also bei unterschiedlichen Executablen unterschiedliche Positionen haben. Damit man damit zurecht kommt, nimmt man nun diesen Punkt (die Adresse von "PE" ) als Ausgang und alle weiteren Angaben sind relativ zu dieser Adresse. Wenn bei der aktuellen Exe der "PE" an Adresse 0x100 liegt, dann ist der EntryPoint an 0x100+0x28. Wenn "PE" an 0x80 liegt - dann liegt der EntryPoint an 0x80+0x28,

Und haben all diese Adressen links an der Seite nachher eine Bedeutung beim Programmablauf?
In dem Post, auf den Du Dich wahrscheinlcih beziehst, sind nur die wesentlichen Sachen aufgezählt - die nicht "optionalen". Diese sind entweder für Programminitialisierung oder den Ablauf wichtig. Die Adressen ganz links sind Positionsangaben für das Auffinden der Informationen in der Exe. Mit diesen Angaben kann man per "Hand" (also mit einem Hexeditor oder eigenem Code) die Infos auslesen/ändern ;).
 
Pe...

Hallöle!

Ah super! Danke für den Splitt!

Also wenn ich dich richtig verstanden habe, dann ist 0x100 + 0x28 0x128, richtig?
Also befindet sich der EntryPoint an Position 128?

Hier mal mein Codeausschnitt als Link, da das Bild nicht richtig angezeigt wird:

http://www.autohotkey.net/~Gapa/HexBild.JPG

Fragen:

1. Schau auf die Markierung in Grün...ist das der EntryPoint??

2.
Die Einträge sind 0x28 Byte groß und so aufgebaut:
Wie viel Byte sind 0x28 Byte???

3.
in PE+6 befindet sich die Anzahl der Sections (als WORD)
Das wäre ja dann Position 106...da steht bei mir 03! Heißt das, dass das Programm aus 3 Sections besteht?? Oder was genau meinst du mit WORD?

4.
in PE+0xF8 findet man ein Section-Array vor.
Wie genau lese ich dieses Array aus? Schließlich sehe ich da nur eine Combi aus Zahlen^^


Ich hoffe du könntest mir eine Antwort auf diese vier Fragen geben (vor allem wie ich aus diesen ganzen Hexzahlen etwas auslesen kann wie ein Array...)

Viele Grüße
Gapa
 
Hi!

Ich hab da auch mal so ne Frage...

Code:
#include <cstdlib>
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char *argv[])
{
    ifstream file1;
    file1.open("C:\\irgendne\\exe.exe", ios::binary);
    char b1,b2;
    int PE = 0;
    int EP = 0;
    int OEP = 0;
    int EPV = 0;
    int imagebase = 0;
    int pos = 0;
    while(!file1.eof() && file1 && PE == 0) {
                b1 = file1.get();
                b2 = file1.get();
                if(b1=='P' && b2=='E') {
                           PE = pos;
                           }
                pos+=2;
                }
    printf("PE Found at %X\n",PE);
    EP = PE + 0x28;
    file1.seekg(PE+0x28);
    EPV = file1.get();
    printf("EP Should be at %X with value %X\n",EP,EPV);
    file1.seekg(PE+0x34);
    imagebase = file1.get();
    printf("Imagebase-Value should be %X\n",imagebase);
    OEP = imagebase + EPV;
    printf("OEP : %X",OEP);
    file1.close();
    system("PAUSE");
    return EXIT_SUCCESS;
}
Mein Programm wirft mir folgendes raus:

PE Found at 108
EP Should be at 130 with value 23
Imagebase-Value should be 0
OEP : 23Drücken Sie eine beliebige Taste . . .

Was hab ich nicht/falsch beachtet?

PE stimmt, EP mit Value und Imagebase-Value stimmt auch.

Aber wie berechne ich daraus den OEP? nur imagebase + EPV (ergibt 0x23) kann doch nicht sein, oder?
 
RE: Pe...

Original von Gapa

Hier mal mein Codeausschnitt als Link, da das Bild nicht richtig angezeigt wird:

http://www.autohotkey.net/~Gapa/HexBild.JPG
gibt einen 403 "Forbidden". Also nicht für andere User/mich sichtbar ;)
Fragen:


2.
Die Einträge sind 0x28 Byte groß und so aufgebaut:
Wie viel Byte sind 0x28 Byte???
Es gibt mehrere übliche Schreibweisen für hexadezimale Zahlen:
einmal mit einem h am Ende (also 20h) oder mit einem 0x am Anfang:
also z.B 0xFF

0x28 Bytes sind 0x28 Bytes im Hexsystem oder 101000 Binär ;)

3.
in PE+6 befindet sich die Anzahl der Sections (als WORD)
Das wäre ja dann Position 106...da steht bei mir 03! Heißt das, dass das Programm aus 3 Sections besteht?? Oder was genau meinst du mit WORD?
WORD heißt, dass der Wert mittels 2 Bytes (16-Bits = WORD) kodiert wird.
Anders gesagt: man liest die 2 Bytes (1 Word) an dieser Position aus - das, was in diesen 2 Bytes steht, ist die Sectionanzahl. Der Wert 3 sollte eigentlich passen. Üblicheweise sind es meistens nicht mehr als 5-7 Sections.

4.
in PE+0xF8 findet man ein Section-Array vor.
Wie genau lese ich dieses Array aus? Schließlich sehe ich da nur eine Combi aus Zahlen^^
Ein Array muss ja nicht nur primitive Datentypen (also nur einen Int,Char usw) enthalten - es können auch komplexe Strukturen sein. In diesem Fall besteht ein einzelner Arrayeintrag aus
Code:
+0 8byte ANSI name 
+8 dword misc (actual size)
+C dword virtual address (an rva to where it should bee mapped)
10 dword sizeofrawdata 
14 dword pointerToRawData (file based offset)
18 dword pointerToRelocations
1C dword PointerToLinenumbers
20 word NumberOfRelocations
22 word NumberOfLineNumbers
24 dword Characteristics
also 0x28 Bytes an Informationsangaben.
Also: an PE+0xF8 fängt das Array an: die ersten 8 Bytes sind der Sectionname,
dann 4Bytes, die die aktuelle größe (im Speicher) angeben, dann 4 Bytes mit der Adressangabe (wo die Section im Speicher liegen soll), dann die größe "Raw" (also in der Datei) usw. Diese Angaben werden vom Windows-PE-Loader ausgelesen und ausgewertet, damit die Sectionen aus der Executable-Datei an die richtige Stelle in den Speicher geladen werden.
Möchte man die Informationen aus der nächsten Section auslesen, geht man zum nächsten Array-Eingtrag: also PE+0xF8 (Arrayanfang) +0x28 (nächster Eintrag bzw die größe eines Eintrags).

(vor allem wie ich aus diesen ganzen Hexzahlen etwas auslesen kann wie ein Array...)
Dir ist schon klar, dass es nur eine andere Räpresentation der Zahlen ist ;) ?


@AlterHacker:
OEP wird üblicherweise im Zusammenhang mit Protectoren/Packern verwendet.
Die Exe hat dann z.B einen EP - allerdings ist diese ja gepackt/geschützt und der EP ist nur der Programmanfang des Protectors/Packers - nicht der eigentlichen Anwendung. OEP = original Entry Point heißt dann in diesem Zusammenhang: Programmanfang(Adresse) des "echten" Codes - also den, der zu der orignal Executable gehört. EP und OEP Begriffe für eine "saubere" Executable zu verwenden ist afaik irgendwie nicht gängig ;)

Zum Fehler:
Code:
file1.seekg(PE+0x28);
    EPV = file1.get();
in EPV müsste jetzt EntryPoint als RVA (also ohne Imagebase) stehen.
Allerdings: EntryPoint Angabe ist 4 Bytes groß - so wie ich das sehe, ließt Du nur 1 Byte aus (das sagen sowohl die Dokumentation zu get wie auch der Debugger ;) )

ich hab das ein bisschen geändert (kann sein, dass es eleganter geht - aber ich kann/mag kein C++ ;)) - jetzt sollten die richtigen Werte rauskommen:
Code:
file1.seekg(PE+0x28);
    file1.get((char*)&EPV,4);
    printf("EP Should be at %X with value %X\n",EP,EPV);
    file1.seekg(PE+0x34);
    file1.get((char*)&imagebase,4);
Es werden jetzt durch "get" 4 Bytes statt nur einem ausgelesen und zumindest bei der Testanwendung richtige Werte angezeigt (g++ compiliert den obigen Code ohne zu meckern). Der Code ist allerdings in der Hinsicht nicht sauber - da die Größe des Int afaik schwanken kann (16,32,64 Bit (bin ehrlich gesagt zu faul, die ISO zu suchen und nachzuschlagen - aber afaik sind das nur die Mindestgrößen)).
 
HexBild

Hallo!

Ok sorry das mit dem Bildlink ist mir ja ganz peinlich :rolleyes:

Hier der neue Link:

Kopie%20von%20HexBild.GIF


Fragen:
0x28 Bytes sind 0x28 Bytes im Hexsystem oder 101000 Binär
8 bit sind doch ein byte...also 11111111 in binär ist ein byte, richtig?? Oder ist 10101010 auch ein byte? Jetzt verstehe ich langsam gar nichts mehr^^
Wie rechnest du 0x28 hexa auf 101000 binär um und wie viele bytes sind das denn jetzt genau?

0x28 ist doch keine Größe wie z.B bytes...ich dachte es wäre eine Adresse?!?
An der Stelle 0x28 sowie an der stelle 0x34 kann ich im Hexeditor eine zweistellige Zahl auslesen (siehe Bild)...und diese sind doch stehts 1 Byte groß, oder? Aber wieso?

Viele Grüße
Gapa
 
RE: HexBild

Original von Gapa
Wie rechnest du 0x28 hexa auf 101000 binär um und wie viele bytes sind das denn jetzt genau?

0x28 ist doch keine Größe wie z.B bytes...ich dachte es wäre eine Adresse?!?
An der Stelle 0x28 sowie an der stelle 0x34 kann ich im Hexeditor eine zweistellige Zahl auslesen (siehe Bild)...und diese sind doch stehts 1 Byte groß, oder? Aber wieso?

0x28 ist einfach eine Zahl = dezimal 40. Man kann auch so schreiben:
PE Position+40Bytes. Da die Angaben in den Dokus aber alle im Hexsystem sind, nutzt man eben dieses Zahlensystem ;) .Wenn Du Dich auf die Größe der Einträge beziehst - die einzelnen Einträge sind 0x28 (dezimal: 40) Bytes groß. Der Wert der Zahl ändert sich ja nicht - nur die Darstellung.
An der Stelle 0x28 sowie an der stelle 0x34 kann ich im Hexeditor eine zweistellige Zahl auslesen (siehe Bild)...und diese sind doch stehts 1 Byte groß, oder? Aber wieso?
Also, die Ziffern links in der Dokumentation geben die Position an:
NEW EXE
+0 PE
4 WORD Machine;
6 WORD NumberOfSections;
8 DWORD TimeDateStamp;
C DWORD PointerToSymbolTable;
10 DWORD NumberOfSymbols;
14 WORD SizeOfOptionalHeader;
16 WORD Characteristics;
die Einträge in der Mitte (WORD,DWORD) geben die Größe des Eintrags an - wieviele Bytes man auslesen muss. Bei WORD sind es 2 Bytes, bei DWORD (Double WORD) sind es 4. Ganz rechts sind die Erklärungen, was der Eintrag darstellen soll ;).
Beispiel2:
+0 8byte ANSI name
+8 dword misc (actual size)
+C dword virtual address (an rva to where it should bee mapped)
10 dword sizeofrawdata
14 dword pointerToRawData (file based offset)
18 dword pointerToRelocations
1C dword PointerToLinenumbers
20 word NumberOfRelocations
22 word NumberOfLineNumbers
24 dword Characteristics
das ist die Struktur des SectionArray Eintrags.
Wenn man nun den Anfang des Arrays kennt, kann man die Werte für eine Section auslesen: Anfang_des_Arrays+0xC (oder 12 dezimal) => da steht die virtuelle Adresse der Section drin (also wo die Section sich im Speicher befinden soll). DWORD sagt - die Angabe is 4 Bytes groß.
Der letzte Eintrag ist an Position 0x24 : Anfang_des_Arrays+0x24 -> hier kann man die Eigenschaften der Section auslesen. Da der Eintrag 1 DWORD=4Bytes groß ist, endet die Struktur mit dem 0x24+0x4=0x28 (dezimal=40) gsten Byte. Die Struktur ist damit 0x28 (dezimal 40) Bytes groß. Möchte man nun Eigenschaften der nächsten Section auslesen: Anfang_des_Arrays+groesse_des_Eintrags(0x28 )+0x24=>Eigenschaften der zweiten Section.

Im Bild ist der EntryPoint (grün) richtig markiert - es ist allerdings ein DWORD Wert (deshalb sollte der Kreis eigentlich 4 Bytes umschließen).
 
PE-File

Hallöle!

Man super CDW für deine ausführlichen Beiträge!!! Ich verstehe jedesmal ein ganzes Stück mehr! =)

Bevor ich dich nun wieder zufrage, möchte ich mich nochmal sehr für deinen Support hier bedanken! Ist echt top wie viel Mühe du dir gibst! Und ich hoffe ich gehe dir mit meinen Fragen nicht auf die Nerven, aber du musst mich verstehen! Ich will das hinbekommen. Ich hoffe dass ich es so bald wie möglich noch erreiche, meinen C++-Code in eines meiner PE-Files zu injizieren!

Nunja, hier mein aktueller Standpunkt:

HexBild.GIF


PE-Adresse: 0x00100
EP-Adresse: 0x00128
EP-Wert: C0 F1 06 00
ImageBase-Adresse: 0x00134
ImageBase-Wert: 00 00 40 00 O
EP-Adresse: ???
OEP-Wert: ???
<--------Wie genau errechne ich denn den Wert? Muss ich da die einzelnen Bytes die ich auslese addieren??
Um die Codeadresse im laufenden Programm anzuspringen, müssen wir allerdings die VA kennen - und diese berechnet sich aus Imagebase + RVA Angabe. Imagebase können wir an: PE+0x34 auslesen.also OEP (original entry point)=Wert an [PE+0x34]+Wert an[PE+28]
Ja...ImageBase ist 00 00 40 00
Aber was mache ich damit? Diese 4 Bytes addieren?? Ich kann ja nicht einfach so ne Rechnung durchführen: 00 00 40 00 + C0 F1 06 00

SectionAnzahl-Adresse: 0x00106
Anzahl Sections: 03 00 <----- sind das nun 3 Sections?? Muss ich da also doch addieren???
SectionArray-Adresse: 0x001F8
SectionArray:
- ANSI name: 55 50 58 30 00 00 00 00
- virtual size: 00 F0 03 00
- virtual address: 00 10 00 00
- sizeofrawdata: 00 00 00 00
- pointertorawdata: 00 04 00 00
- pointertorelocations: 00 00 00 00
- NumberofRelocations: 00 00
- NumberofLinenumbers: 00 00
- Characteristics: 00 00 00 00


Ich wäre dir sehr dankbar, wenn du die Angaben anhand des Bildes nochmal prüfen würdest...
und mir natürlich wieder weiterhilfst auf meine Fragen und überhaupt wie ich nun weiterkomme. =)

Also schonmal vielen VIELEN DANK im Voraus!!

Viele Grüße
Gapa
 
RE: PE-File

Original von Gapa

Nunja, hier mein aktueller Standpunkt:

http://www.autohotkey.net/~Gapa/HexBild.GIF

PE-Adresse: 0x00100
EP-Adresse: 0x00128
EP-Wert: C0 F1 06 00
ImageBase-Adresse: 0x00134
ImageBase-Wert: 00 00 40 00 O
EP-Adresse: ???
OEP-Wert: ???
<--------Wie genau errechne ich denn den Wert? Muss ich da die einzelnen Bytes die ich auslese addieren??
Als erstes: die üblichen CPUs arbeiten mit Little-Endian:
http://de.wikipedia.org/wiki/Byte-Reihenfolge
d.h die Bytes werden von der CPU in "umgekehrter" Folge abgelegt und genauso umgekehrt ausgelesen.
Bsp: ein DWORD 12 34 56 78
wird so abgelegt:
78 56 34 12
Ein Mensch muss es also nach dem direkten Auslesen für sich "umkeheren" (ließt man es mit einem Programm aus, muss man nichts weiter machen ;) ).
Mensch-verträgliche Werte:
EP-Wert: 00 06 F1 C0
ImageBase-Wert: 00 40 00 00
EP-Wert liegt also als relative Angabe vor (RVA).
Wert im Speicher errechnet sich aus ImageBase + RVA Wert:
00 40 00 00 + 06 F1 C0 = 00 46 F1 C0
SectionAnzahl-Adresse: 0x00106
Anzahl Sections: 03 00 <----- sind das nun 3 Sections?? Muss ich da also doch addieren???
Nochmal ein Verweis auf Little-Endian: als Mensch sollte man es so lesen:
00 03 <- ist eine WORD Angabe (also nur 2 Bytes) , und ja, es sind tatsächlich 3 Sections.
Ob man die Addieren muss, kommt jetzt darauf an, was Du machen willst. Ich nehm' an, Du willst die letze Section manipulieren:
SectionArray-Adresse: 0x001F8 <- hier fängt auch der erste Eintrag im Array an
0x001F8+0x28+0x28 <- hier sollte der Eintrag zu der letzten Section stehen.

Ich wäre dir sehr dankbar, wenn du die Angaben anhand des Bildes nochmal prüfen würdest...
und mir natürlich wieder weiterhilfst auf meine Fragen und überhaupt wie ich nun weiterkomme. =)
Es gibt PE-Editoren wie LordPE oder PETools. Damit kann man die Werte auch alleine Kontrollieren ;)
Im Screenshot wird eine Beispielexe geöffnet, die Sections aufgelstet sowie deren Eigenschaften angezeigt (durch Rechtsklick auf Section ->"Edit Section Header" Auswahl. Zudem wird der letze Wert ("Characteristics" - auch "Flags" genannt) lesbar dargestellt.
 
PE-File

Hallöle!

Ah super für die Info! Das mit dem little-Endian hatte ich sogar schon mal gelernt, habe es aber völlig vergessen in dieser Situation zu berücksichtigen :rolleyes:

00 40 00 00 + 06 F1 C0 = 00 46 F1 C0
Ist das das selbe wie: 0x00400000 + 0x0006F1C0 ??

Ob man die Addieren muss, kommt jetzt darauf an, was Du machen willst. Ich nehm' an, Du willst die letze Section manipulieren:
Ich weiß ja nicht, was einfacher ist...vielleicht ist es ja auch einfacher ne Section anzuhängen (also ne vierte Section).
Aber ich habe kein Plan wie ich nun meinen Code ins Progamm bekomme...
Bis jetzt habe ich ja nur Werte ausgelesen, welche mir absolut nichts sagen (sind ja schließlich nur Zahlen).

SectionArray-Adresse: 0x001F8 <- hier fängt auch der erste Eintrag im Array an 0x001F8+0x28+0x28 <- hier sollte der Eintrag zu der letzten Section stehen.
Wieso 2 mal 0x28??
Ich dachte, das ganze Array ist 28 Bytes lang...was steht in den 28 Bytes nach dem Array??

Laut deiner Aussage ist das hier der Eintrag zur letzten Section an der Adresse 0x00248 zu finden ( 0x001F8+0x28+0x28 ). Da ich nicht weiß, wie viele Bytes ich nun auslesen muss, lese ich einfach mal 10 Bytes aus (bereits umgekehrt): 20 00 00 00 00 6372 73 72 2E

Und was genau kann ich jetzt mit diesem Eintrag anfangen?? Und gleich dazu: Was kann ich mit dem oben errechneten OEP anfangen?

Ich hoffe du kannst mir wieder weiterhelfen!
Viele Grüße
Gapa
 
Ist das das selbe wie: 0x00400000 + 0x0006F1C0 ??
Jep.

Ich weiß ja nicht, was einfacher ist...vielleicht ist es ja auch einfacher ne Section anzuhängen (also ne vierte Section).
Aber ich habe kein Plan wie ich nun meinen Code ins Progamm bekomme...
Einfacher ist imho, die letze Section zu vergrößern. Dann muss man nur die Größe der Section anpassen (sowohl RAW wie Virtuelle)+ImageSize.Einfach die Größe des hinzugefügten Codes hinzuaddiert.
Wenn man eine Section hinzufügt, muss man einen neuen Eintrag in den SectionArray schreiben (wenn noch Platz da ist - sonst kommen Verschiebungen in der Datei und Korrekturen der RAW-Werte einzelner Section hinzu).

Wieso 2 mal 0x28??
Ich dachte, das ganze Array ist 28 Bytes lang...was steht in den 28 Bytes nach dem Array??
Ein einzelner Array-Eintrag ist 28 Bytes lang. Die Anzahl der Einträge im Array==Anzahl der Sections. Daher - wenn man bei 3 vorhandenen Sections den dritten auslesen möchte:
info=array[2]. Da man hier alles "per Hand macht" muss man eben:
virtualAdress_3=array[2*28+0xC].

Laut deiner Aussage ist das hier der Eintrag zur letzten Section an der Adresse 0x00248 zu finden ( 0x001F8+0x28+0x28 ). Da ich nicht weiß, wie viele Bytes ich nun auslesen muss, lese ich einfach mal 10 Bytes aus (bereits umgekehrt): 20 00 00 00 00 6372 73 72 2E
also: die Bytes sollte man shcon so umkehren, wie sie zusammengehören. Nicht einfach 10 Bytes andersrum schreiben, denn:
+0 8byte ANSI name
+8 dword misc (actual size)
+C dword virtual address (an rva to where it should bee mapped)
10 dword sizeofrawdata
14 dword pointerToRawData (file based offset)
die ersten 8 Bytes stellen den Namen dar. Kann man sich wie einen Chararray in C vorstellen. Da man diese sowieso byte per Byte liest, ist es nicht notwendig, den Namen verkehrt herum zu schreiben.
2E 72 73 72 63 00 00 00 <- Name
20 00 (fehlen noch 2 Bytes) <- virtual size

Und was genau kann ich jetzt mit diesem Eintrag anfangen??
wenn man diese Werte hat, kann man die Section vergrößern, dazu:

+0 8byte ANSI name
+8 dword misc (actual size) <--- gewünschten Wert dazuaddieren
+C dword virtual address (an rva to where it should bee mapped)
10 dword sizeofrawdata < -- gewünschten Wert hinzuaddieren
...
24 dword Characteristics <--- gewünschten Flag setzen
- some of the flags in this are ;-
0x00000020 contains code
0x00000040 contains initialized data
0x00000080 contains uninitialized data
0x00000200 contains comments
0x02000000 can be discarded
0x10000000 This section is shareable.
0x20000000 This section is executable.
0x40000000 This section is readable.
0x80000000 The section is writeable.
sofern man code dazuaddiert, sollte man bei Characteristics den Flag 0x20000000 setzen (executable) - damit der Code auch ausgeführt werden kann. Bitweise Operatoren (AND zum Abfragen und OR zum setzen)
http://www.galileocomputing.de/openbook/c_von_a_bis_z/c_008_004.htm


Was kann ich mit dem oben errechneten OEP anfangen?
Wenn Du Code injezieren willst, dann brauchst Du den OEP, damit das Programm nach der Ausführung des injezierten Codes normal startet. Die letze Anweisung des injezierten Codes sollte daher irgendetwas sein, was den zum OEP springt (JMP OEP,Call OEP usw).
 
PE-File

Hallöle!

Ok also fassen wir zusammen:

Schritte:

1. Hauptprogramm in Hexeditor laden^^
2. PE suchen
3. Anzahl Sections auslesen
4. Letztes Sectionarray auslesen
5. virtual size ändern
6. virtual adress ändern
7. sizeofrawdata ändern
8. Characteristics auf 0x2000000 setzen
9. Injectionscode mit OEP einbetten

Fragen:

1. Angenommen, mein Code, welchen ich ins Hauptprogramm einfügen möchte, ist in C++ geproggt und gibt nur eine Messagebox aus - > Welche Funktionen muss ich dann vom Hauptprogramm mitbenutzen bzw. brauche ich aus der Winapi?

2. Welchen Teil meines Programms füge ich ins Hauptprogramm ein? Alles, oder nur die Sections?Wäre ja unlogisch, sonst stünde in der letzten Section des Hauptprogramms ja ein neuer MZ-Header bzw. PE-Header...

3. Habe ich irgendeinen Schritt vergessen bzw. muss ich noch etwas beachten?

Viele Grüße
Gapa
 
RE: PE-File

Original von Gapa
Hallöle!

Ok also fassen wir zusammen:

Schritte:

1. Hauptprogramm in Hexeditor laden^^
2. PE suchen
3. Anzahl Sections auslesen
4. Letztes Sectionarray auslesen
5. virtual size ändern
6. virtual adress ändern <--- schön beim alten lassen (es ändert sich ja nur die größe
7. sizeofrawdata ändern
8. Characteristics auf 0x2000000 setzen <--- Das Bit (falls nicht gesetzt) setzen.
9. Injectionscode mit OEP einbetten
denn: 0x2000000 ist binär 10000000000000000000000000.b
durch bitweises OR kann man das Bit setzen (falls es nicht gesetzt wurde)
http://de.wikipedia.org/wiki/Bitmaske
denn: wie man aus der Doku entnimmt, handelt es sich nur um eine DWORD Zahl, die aber mehrere Informationen kodiert
- some of the flags in this are ;-
0x00000020 contains code
0x00000040 contains initialized data
0x00000080 contains uninitialized data
0x00000200 contains comments
0x02000000 can be discarded
0x10000000 This section is shareable.
0x20000000 This section is executable.
0x40000000 This section is readable.
0x80000000 The section is writeable.
es wäre ungünstig, diese Informationen zu "vernichten" in dem man das Ganze mit 0x20000000 überschreibt (dann ist die Section nicht mehr beschreibbar/lesbar).

Fragen
1. Angenommen, mein Code, welchen ich ins Hauptprogramm einfügen möchte, ist in C++ geproggt und gibt nur eine Messagebox aus - > Welche Funktionen muss ich dann vom Hauptprogramm mitbenutzen bzw. brauche ich aus der Winapi?
das kommt darauf an, was der C++ Kompiler so ausspuckt und automatisch einbindet.
außerdem hast Du das Problem, dass der Code nicht adressgebunden sein darf.
d.h entweder eine gute Kontrolle über den Kompiler haben oder den Injectionscode in Assembly schreiben. Ich weiß, dass es sehr enttäuschend ist und das auch schnell in ein Flamewar ausarten kann - aber C++ ist bei weitem nicht allmächtig (oder zumindest in manchen Bereichen schwer zu hanhaben) :D.

API Nutzung: entweder muss die MessageBox schon vorhanden sein oder Du musst die Adresse der API herausbekommen.
a)Um die in der Anwendung vorhandene API zu nutzen muss man 1) die Imports auslesen - man scannt zuerst die Imports nach einem Eintrag mit dem Namen User32.dll. 2) dann die zu diesem Import zugehörige ImportTable (FirstThunk) nach "MessageBoxA" / "MessageBoxW" /"MessageBoxExA" oder "MessageBoxExW" absuchen. Hat man diese gefunden, merkt man sich die Adresse des Eintrags - hier wird nach dem Start der Executable die Adresse der MessageBox stehen.
Jetzt muss man nur diese Adresse in den zu injezierenden Code einfügen.
b) man kann stattdessen nach "LoadLibraryA" und "GetProcAddress" scannen - diese sind imho häufiger anzutreffen (besonders wenn man statt MessageBox andere APIs braucht).
c) man kann direkt die Kernel32.dll nach "LoadLibraryA" und "GetProcAddress" scannen
den Code gibts hier:
Masm32 Code patchen
(der HookInlinPatching Anhang - und ja, solche Methoden werden inzwischen eher von Crackern benutzt und ausgearbeitet, denn viele der heutigen "Vierenschreiben" (oder zumindest viele, die sich zu unrecht so schimpfen) haben nie etwas anders als ihre VB IDE oder Batcheditor gesehen ;) ).

d) eine andere Methode wäre, die vorhandenenen Imports zu erweitern. Dazu müssten allerdings mindestens 20 Bytes nach dem letzen Import Eintrag frei sein. Und das ist nicht immer der Fall (Verschieben und Platzmachen ist etwas aufwendig).

Paar Sachen zu Imports:
http://win32assembly.online.fr/pe-tut6.html
mein Favorit
http://sandsprite.com/CodeStuff/Understanding_imports.html (hier wird FirstThunk als rvaImportAddressTable bezeichnet).


Code:
2. Welchen Teil meines Programms füge ich ins Hauptprogramm ein? Alles, oder nur die Sections?Wäre ja unlogisch, sonst stünde in der letzten Section des Hauptprogramms ja ein neuer MZ-Header bzw. PE-Header...
nur den adressunabhängigen Code. Mit dem Rest wird nämlich der PE-Loader nichts anfangen können. Er wird die ImportTabelle nicht ausfüllen und Deine Sections nicht initialisieren oder gar an richtige Adressen laden.
D.h Du kannst in Deinem Code erstmal keine API bzw. Fremd-DLL Aufrufe nutzen (siehe oben - zuerst LoadLibrary/GetProcess herausbekommen oder alternativ direkt die APIs der Anwendung mitbenutzen). Zudem darf der Code nicht adressabhängig sein - fügt man blind den vom Compiler generierten Code ein, hat man garantiert mehrere Probleme - z.B werden globale Variablen oder Konstanten aus der Data Section geladen, die natürlich eine vom Compiler zugewiesene virtuelle Adresse hat - die aber bei einer Injection gar nicht stimmt (es verschiebt sich alles). Außerdem gibt es "automatisch generierten" Code, z.B um die an die Main übergebene Argumente abzufragen, Abhängigkeiten von Runtimedlls und andere Späße.

3. Habe ich irgendeinen Schritt vergessen bzw. muss ich noch etwas beachten?
da kann ich nur hierauf verweisen:
code von exe an code von anderen exe hängen? (c++)
(da war ich noch halbwegs in Form bezüglich PE Format ;) ).
 
Im Endeffekt bringt das alles nicht viel. Egal aus welchen Gründen man Code injected.

Viel simpler ist das verschieben/umbenennen der Ursprungs-EXE, und dafür einen eigenen "Loader" hinzustellen. Der Loader startet dann einfach die Original-exe und führt dann seinen Code aus.

Dies hat keine Nachteile - Icons und Assembly Infos kann der Loader auch einfach aus der Original-Exe klauen/kopieren.

Viel weniger Komplex, aber genauso effektiv. Es kommt selten vor, wo man Code wirklich in eine andere Exe Injecten muss.

Muss aber trotzdem zugeben, dass ich höchst interessiert diese Postings hier lese ;)
 
Zurück
Oben