EMO Style ForumPro - Hos Geldiniz
Giriş yap

Şifremi unuttum

Istatistikler
Toplam 202 kayıtlı kullanıcımız var
Son kaydolan kullanıcımız: AnthonyFurey3

Kullanıcılarımız toplam 1186 mesaj attılar bunda 862 konu
Tarıyıcı
 Kapı
 Indeks
 Üye Listesi
 Profil
 SSS
 Arama
Arama
 
 

Sonuç :
 


Rechercher çıkıntı araştırma

RSS akısı


Yahoo! 
MSN 
AOL 
Netvibes 
Bloglines 


Kimler hatta?
Toplam 4 kullanıcı online :: 0 Kayıtlı, 0 Gizli ve 4 Misafir :: 1 Arama motorları

Yok

[ Bütün listeye bak ]


Sitede bugüne kadar en çok 92 kişi Paz Ağus. 28, 2016 6:58 am tarihinde online oldu.
En son konular
» İnternetten Para Kazandıran Oyun ! Ödeme Alt Limiti Yok ! DEV KONU
Cuma Ağus. 29, 2014 8:33 am tarafından Hello EMO

» goldenchase.net maden yaparak para kazanma
Cuma Ağus. 29, 2014 8:18 am tarafından Hello EMO

» etichal hacker görsel egitim seti
Çarş. Ağus. 06, 2014 4:57 am tarafından Hello EMO

» KO TBL Source C#
Ptsi Ara. 09, 2013 6:36 am tarafından Hello EMO

» x86 Registers
C.tesi Ağus. 24, 2013 5:02 am tarafından Hello EMO

» [Tutorial] Pegando Address, Pointers de WYD
Çarş. Tem. 10, 2013 7:25 am tarafından Hello EMO

» [Tutorial] Pegando Address, Pointers de CS Metodo²
Çarş. Tem. 10, 2013 7:23 am tarafından Hello EMO

» [Tutorial] Aprendendo basico deASM OLLYDBG
Çarş. Tem. 10, 2013 7:22 am tarafından Hello EMO

» Basic C# DLL injector
Ptsi Tem. 08, 2013 7:48 am tarafından Hello EMO

Reklam

Find Pattern Tutorial C++

Önceki başlık Sonraki başlık Aşağa gitmek

Find Pattern Tutorial C++

Mesaj tarafından EMO Bir Cuma Nis. 13, 2012 2:28 pm

[QUOTE=.ErpeL;12599791]Find Pattern Tutorial

Find Pattern wird dafür genutzt, bestimmte Funktionsadressen aus einem Prozess auszulesen.
Dazu wird der Byte-OpCode einer EXE, DLL, BIN oder dergleichen durchlaufen und nach einem vordefiniertem Byte-Muster durchsucht.

Am Anfang etwas Theorie:
Spoiler:

Da die Find Pattern Funktion einen bestimmten Suchbereich erwartet muss dieser zuvor ausgelesen werden. Normalerweise wird immer von der Modulbase bis zum Code-Ende alles durchsucht. Dazu braucht man den Anfangswert (Base) und den Endwert (SizeOfCode) , beides ist ganz einfach auslesbar. Der Anfang einer Windows Executable ist immer wie folgt aufgebaut (Tabelle unten).

DOS headerNT header......
An der Modulbasis der DOS-Header, dieser ist Standardisiert und sieht im Debugger so aus (Bild Unten).



Gleich darauf folgt der NT-Header (auch PE-Header). Im DOS-Header steht der Offset an dem letzterer zu finden ist (oben rot markiert). In diesem Fall das Offset 148 (Hexadezimal) also Beginnt dieser bei 400148, wenn mal die Modulbase draufrechnet (Im Bild unten nochmal durch die grüne Markierung verdeutlicht).



Interessant sind hierbei wie zuvor geschrieben der Start und Endwert. Der Basiswert wird durch die GetModuleHandle Funktion ermittelt, der Endwert wird aus dem PE-Header ausgelesen (Oben rot markiert). Der Codeabschnitt unten zeigt eine mögliche Umsetzung in C++.

[php]DWORD Base = (DWORD)GetModuleHandleA("metin2client.bin");
DWORD PEOffset = *(DWORD*)(Base + 0x3C); //Anfang des PE-Headers auslesen
DWORD SizeOfCode = *(DWORD*)(Base + PEOffset + 0x1C) + Base; //SizeOfCode auslesen[/php]

Problemstellung:
Spoiler:

Ziel ist es ein bestimmtes Muster zu finden, in diesem Beispiel muss der Metin2 Client herhalten. Es sollen die Funktionsadressen automatisch gesucht werden, im Beispiel die „DropItem“ Funktion. Diese sieht im Debugger folgendermaßen aus (im Bild unten grau unterlegt).



Aus den OpCode muss jetzt eine Suchmaske erstellt werden, dazu sucht man sich ein Codefragment aus welches die gewünschte Funktion beinhaltet, es kann ruhig etwas weiter nach oben bzw. unten gehen (wie im Bild oben rot markiert), damit es später besser gefunden werden kann. Anschließend wird dieser Code in ein BYTE-Array kopiert und die Bytes, die sich von Version zu Version oder durch Relozierung des Moduls ändern könnten (also z.B. Adressen oder Offsets) und daher durch die noch folgende String Maske ignoriert werden, zur besseren Lesbarkeit durch 0-Bytes ersetzt.
Das Byte Array speziell für diese Funktion sieht so aus wie im Bild unten, alle Unbekannten wurden durch 0-Bytes ersetzt.

[php]BYTE Mask[] = {0xC3,
0x8B, 0x54, 0x24, 0x04,
0x8B, 0x44, 0x24, 0x08,
0x8B, 0x0D, 0x00, 0x00, 0x00, 0x00,
0x52,
0x6A, 0x00,
0x50,
0xE8, 0x00, 0x00, 0x00, 0x00,
0xE8, 0x00, 0x00, 0x00, 0x00,
0x5E};[/php]Jetzt muss noch eine Prüfmaske erstellt werden, in dieser werden alle bekannten Bytes durch ein „x“ gekennzeichnet, alle Unbekannten durch ein „-„. Das Beispiel unten zeigt eine solche Maske (zur besseren Veranschaulichung mit Zeilenumbrüchen).

[php]char mask[] = "x
xxxx
xxxx
xx---x
x
xx
x
x---x
x---x
x";[/php]Nun ist alles Wichtige vorhanden um die Funktion aufzurufen.

Die Find Pattern Funktion:
Spoiler:

Diese Funktion besteht aus zwei Bestandteilen, einmal die Funktion als solches und eine Unterfunktion DataCompare welche dafür zuständig ist die Bytes aus der Suchmaske mit dem OpCode aus dem Prozess zu vergleichen. Die Originalfunktion stammt von dom1n1k (gamedeception.net), ich habe noch den Ignore Parameter hinzugefügt.


[php]bool DataCompare(const BYTE* OpCodes, const BYTE* Mask, const char* StrMask)
{
//solange bis String zuende
while (*StrMask)
{
//wenn Byte ungleich --> false
if(*StrMask == 'x' && *OpCodes != *Mask )
return false;

++StrMask;
++OpCodes;
++Mask;
}

return true; //wenn alle Bytes gleich
}

DWORD FindPattern(DWORD StartAddress, DWORD CodeLen, BYTE* Mask, char* StrMask, unsigned short ignore)
{
unsigned short Ign = 0;
DWORD i = 0;

while (Ign <= ignore)
{
if(DataCompare((BYTE*)(StartAddress + i++), Mask,StrMask))
++Ign;

else if (i>=CodeLen)
return 0;
}

return StartAddress + i - 1;
}[/php]Parameter:

Typ | Name | BeschreibungDWORD | StartAddress | Offset von welchem begonnen wird zu durchsuchenDWORD | CodeLen | Offset an dem die Suche gestoppt wirdBYTE* | Mask | Byte-OpCode Maskechar* | StrMask | String Maske, definiert welche Bytes bei der Suche beachtet werden(x) und welche ausgeschlossen werden(-).unsigned short | ignore | Anzahl der Funde die ignoriert werden, 0 = erster Fund wird zurückgegeben
Rückgabe:
Zurückgegeben wird das Offset an dem die Funktion (die Suchmaske) gefunden wurde als DWORD Wert, in diesem Beispiel wäre das 0x41484E (auch auf dem Debugger-Codefragment im Bild oben ersichtlich, blau markiert).

Ein Aufruf könnte so aussehen

[php]DWORD Offset = FindPattern( Base + 0x1000, //BaseOfCode = Base + 1000(Hex)
SizeOfCode,
Mask,
"xxxxxxxxxxx---xxxxxx---xx---xx",
0);[/php]

Als StartAddress wurde nicht direkt Base sondern Base + 1000(Hex) übergeben, dass ist weil der eigentliche Code erst ab Offset 1000(Hex) beginnt (und zwar immer). Der Bereich davor ist für die Headers reserviert.
Wie bereits geschrieben sollte die Funktion im Beispiel das Offset 0x41484E liefern. Mit diesem Offset lassen sich die benötigten Funktionsadressen ermitteln, wie das funktioniert wird nun erklärt.

Funktionsadressen berechnen:
Spoiler:

Damit nicht ständig hochgescrollt werden muss hier nochmal das Codefragment der DropItem Funktion von vorhin.



Um eine Adresse im Stil von DWORD PTR DS:[??????] auszulesen muss man folgendes tun. Man zählt die Bytes ab Beginn der Suchmaske bis zu der Stelle an dem die benötigte Adresse steht. Im Beispiel soll die Adresse 61C028 (Bild oben grün markiert) ausgelesen werden, also beginnt man ab Start der Suchmaske, in unserem Beispiel war das C3 die Bytes (1 Byte = Zahlenpaar aus 2 Zahlen) bis zu der Adresse zu Zählen. So kommt man auf 11 Bytes. Die gezählten Bytes wurden im Bild zur Veranschaulichung gelb hinterlegt. Der Blau hinterlegte Abschnitt ist die gewünschte Adresse. Das Codebeispiel unten zeigt nun wie diese ausgelesen werden kann.

[php]DWORD Address1 = *(DWORD*)( Offset + 11);[/php]Um Andere Adressen wie z.B. 0041E1B0 auslesen zu können geht man ähnlich vor wie vorhin. Nur die Berechnung ändert sich da diese Adresse anders auf dem Speicher liegt. Man zählt wieder die Bytes vom Beginn unserer Maske (in diesem Fall C3) bis zur Adresse. Dieses Mal sind das 20 Bytes. Ausgelesen wird nun mit hilfe der Funktion unten.

[php]DWORD RelativeToAbsolute(DWORD Offset)
{
return *(DWORD*)(Offset) + Offset + 0x4;
}[/php]Aufgerufen wird sie so:

[php]DWORD Address2 = RelativeToAbsolute(Offset + 20);[/php]Dies ist nötig weil die Adresse relativ zu dem Offset codiert ist. Man muss also erst den Wert auslesen der auf dem Offset liegt. In unserem Beispiel wäre das 994A, auf diesen Wert muss jetzt das Offset draufaddiert werden und dann noch die Länge der Adresse in Bytes also 4. Also 0x41E1B0 = 0x994A + (Offset +20) + 0x4.

Alles in allem:
Spoiler:
[php]//DataCompare--------------------------------------------------------
bool DataCompare(const BYTE* OpCodes, const BYTE* Mask, const char* StrMask)
{
//solange bis String zuende
while (*StrMask)
{
//wenn Byte ungleich --> false
if(*StrMask == 'x' && *OpCodes != *Mask )
return false;

++StrMask;
++OpCodes;
++Mask;
}

return true; //wenn alle Bytes gleich
}

//FindPattern------------------------------------------------------------------
DWORD FindPattern(DWORD StartAddress, DWORD CodeLen, BYTE* Mask, char* StrMask, unsigned short ignore)
{
unsigned short Ign = 0;
DWORD i = 0;

while (Ign <= ignore)
{
if(DataCompare((BYTE*)(StartAddress + i++), Mask, StrMask))
++Ign;

else if (i>=CodeLen)
return 0;
}

return StartAddress + i - 1;
}

//RelativeToAbsolute -------------------------------------------------------------
DWORD RelativeToAbsolute (DWORD Offset)
{
return *(DWORD*)(Offset) + Offset + 0x4;
}

// FindAddresses----------------------------------------------------------------
bool FindAddresses()
{
DWORD Base = (DWORD)GetModuleHandleA("metin2client.bin");
DWORD PEOffset = *(DWORD*)(Base + 0x3C); //Anfang des PE-Headers auslesen
DWORD SizeOfCode = *(DWORD*)(Base + PEOffset + 0x1C) + Base; //SizeOfCode auslesen

BYTE Mask[] = {0xC3,
0x8B, 0x54, 0x24, 0x04,
0x8B, 0x44, 0x24, 0x08,
0x8B, 0x0D, 0x00, 0x00, 0x00, 0x00,
0x52,
0x6A, 0x00,
0x50,
0xE8, 0x00, 0x00, 0x00, 0x00,
0xE8, 0x00, 0x00, 0x00, 0x00,
0x5E};

DWORD Offset = FindPattern( Base + 0x1000, //BaseOfCode = Base + 1000(Hex)
SizeOfCode,
Mask,
"xxxxxxxxxxx---xxxxxx---xx---xx",
0);

//Wenn Funktion nicht gefunden
if (!Offset)
return false;

DWORD Address1 = *(DWORD*)( Offset + 11);
DWORD Address2 = RelativeToAbsolute(Offset + 20);

return true;
}[/php]

Download als PDF:[/QUOTE]
avatar
EMO
EMO Team
EMO Team

Cinsiyet : Erkek
Burçlar : Yay
Yılan
Mesaj Sayısı : 184
Puan : 107693
Rep Puanı : 5
Doğum tarihi : 28/11/89
Kayıt tarihi : 18/05/11
Yaş : 27
Nerden : EMO world
İş/Hobiler : RCE Student / Game Hacking / Learn Beginner C#,C++,Delphi
Lakap : EMO

Kullanıcı profilini gör

Sayfa başına dön Aşağa gitmek

Önceki başlık Sonraki başlık Sayfa başına dön

- Similar topics

 
Bu forumun müsaadesi var:
Bu forumdaki mesajlara cevap veremezsiniz