Hallo Elite PvPer!
Auf folgende Fragen wirst du in diesem Tutorial Antworten finden:
Was ist eine "Code/Dll injection" und was bringt mir das - kann man das essen?
Was sind Dll-Dateien (dynamische/statische Bibliotheken) - kann man die ebenfalls essen?
Wie erstelle ich etwas, was "injected" werden soll?
und das wichtigste,
Wie mache ich so eine "Code injection" (/erstelle einen Injector)?
Falls Fragen auftreten, die in diesem Tutorial unbeantwortet bleiben, habt ihr natürlich die Erlaubnis sie zu stellen! (doch nur, wenn ihr zuvor eine online Suchmaschine zu Rate gezogen habt.
)Was ist eine "Code/Dll injection"?
Abgesehen davon, dass die meisten, die dieses Tutorial lesen, es wahrscheinlich schon wissen, erkläre ich es hier nocheinmal:
Eine Code Injection ist das Zwischenfügen von einem Programmcode in einem Fremden Prozess. Stellen wir uns also folgendes vor:
Wir sind mal wieder am Programmieren
und haben uns soeben eine Pizza in den Ofen geschoben - da wir gerade an einem äußerst kniffligem Algorithmus arbeiten vergessen wir darüber die Zeit. Eine volle Stunde später holen wir dann unsere verbrannte Pizza aus dem Ofen und ärgern uns, dass unser Programmier Editor keinen Wecker hat, der dieses hätte verhindern können. Dank Code Injection könn man jedoch in den Editor genau so eine Funktion hinzufügen. Neben den Menüellementen "New", "Open" und "Save" könnte dann im Editor zusätzlich noch "Wecker" stehen und ein Fenster mit einstellbarer Alarmzeit würde sich bei einem Draufklicken öffnen.
Funktionieren tut dies folgendermaßen:
1. Wir schreiben eine Dll (siehe unten), die einige Weckerfunktionen beinhaltet.
2. Wir schreiben einen "Injector" (Spritzer
) , der die Dll zu einem Teil des Editors macht - sprich: Einen von uns selbst erstellten Wecker Code (in form einer Dll) in den Editor schleust.(Für wen Bibliotheken & Dll's bereits reine Routine sind, kann diesen Teil überspringen)
Was sind Dll-Dateien (dynamische/statische Bibliotheken)
"Dll" ist eine abkürzung für "Dynamic Link Library" -> also eine Dynamisch verbindbare Bibliothek.
Es gibt 2 gängige Arten von Bibliotheken (Bibliotheken = Dateien welche für andere Programme nutzbare Funktionen endhalten):
Die statischen (Static; meist die Dateiendungen ".o" und ".lib") und die dynamischen (Dynamic; ".dll") Librarys (Bibliotheken)
.Static library:
Eine Static library ist eine Datei, in der sich von andern Endwicklern vorgefertigte (compilite) Funktionen befinden. Diese Datein haben unter Windows meist die Datei-Endungen .o oder .lib und werden beim Erstellen einer .exe (ausführbaren Datei) die dessen Funktionen benutzt in das Programm (per Linker[=siehe Google oder einfach weiterlesen]) eingebunden
. Man hat also nun eine ausführbare Datei. Warum Leute soetwas machen -> genügt der source code denn nicht?
Wenn ein Entwickler anderen Leuten viele Funktionen zur Verfügung stellen will, dauert es lange, bis der Computer diese in Maschinencode übersetzt hat. Darum werden sie schon vorübersetzt mitgeliefert und man kann sie wesentlich schneller in sein neues Programm integrieren.
.Vorteil einer Static library
:->Immer erreichbar und bloß 1 File, statt vieler. Außerdem bei erster Benutzung geringfügig schneller als eine dynamische Bibliothek, da die funktionen sich im Programm selbst befinden. und nicht erst eingefügt werden müssen.
->Schnelleres einbinden des Maschinen Codes in das Programm, als bei reinem Sourcecode - Somit ein schnelleres Erstellen
Nachteile
:->Die Static Library muss von jeder Datei, die dessen Funktionen nutzen will beim erstellen mit dem Linker eingebunden werden und erhöht so unnötig die Programmgröße, falls sie von mehr als nur einer .exe benutzt wird.
Und jetzt habt ihr die Erlaubnis laut aufzustöhnen, denn die static library ist für eine Dll injection nicht von Relevanz
. Jedoch Solltet ihr über ein Gegenstück zu Dll-Datein informiert sein und die Dll lässt sich wesentlich leichter verstehen
, wenn man auch die static library kennt. Lieber zu viel wissen, als zu wenig :P Dynamic Link Library (.dll):
Eine Dll enthält wie die Static library ebenfalls schon fertige (compilite) Funktionen, doch kann die Dll nicht (durch einen Linker) in die exe integriert werden, sondern muss vom laufendem Programm geladen werden werden.
Vorteile
:->Keine überflüssige Filegröße, wenn die funktionen von mehreren datein genutzt werden sollen.
->Leichter wartbar, da man wenn neue funktionen bei einem Update kommen man nicht das ganze programm neu ersetzen muss, sondern nur einige kleine Dll's.
->Die funktionen können zur Laufzeit geladen werden und müssen nicht beim erstellen der Datei eingebunden sein. Dies hat zum einen einen Resourcen Vorteil und zum anderen ist es für eine Code Injection ideal.
->Durch die Funktion DllMain kann die Dll beim eingebunden werden noch Vorkehrungen zum Initialisieren der Funktionen treffen.
Nachteile:
->Man hat mehrere Datein und es wird unter Umständen unübersichtlich
->Eine EXTRA Datei verbraucht geringfügig mehr Speicher als eine eingebundene und lohnt sich so gesehen also nur bei Benutzung von verschiedenen Prozessen.
Sie müssen extra in den Prozess geladen werden, bevor man dessen Funktionen nutzen kann -> was Zeit kostet.
Fazit:
Bei einer Dll injection macht man sich zum Vorteil, dass Dll-Dateien während der Laufzeit eingebunden werden können und spart somit beim Abändern eines fremden Prozesses eine menge Arbeit:
Statt, dass man seine "neuen" Funktionen komplett in Assembler (siehe Google) in den Prozess einfügen muss, muss man einfach nur den fremden Prozess die Dll laden lassen und dann in der DllMain funktion einen neuen Thread (Unterprozess des fremden Programmes, der parallele zum Hauptprozess ausgeführt wird) erstellen, der die gwünschten Funktionen aus der Dll aufruft. In unserem Hack beispiel, wäre das eine Funktion, die ein Menü Ellement hinzufügt und beim anklicken von diesem einen Wecker erstellt.
Praktisch ist hierbei, dass nahezu jeder Windows Prozess die kernel32.dll (näheres wie immer
) benutzen muss, in der die Funktionen zum Dll laden vordefiniert sind.Man muss also nur einen Aufruf dieser Kernel Funktionen mit der zu ladenen Dll als Parametern in das fremde Programm einfügen und schwups hat man seine Dll (bzw. Code) Injection!
.Wie erstelle ich etwas, was "injected" werden soll?
So viel zur Theorie... die Praxis ist da leider etwas komplizierter
Wir brauchen also einen Injector (ein Programm, dass den fremden Prozess so verändert, dass die gewünschte Dll geladen wird) und eine Dll, die wir injecten können.
Als erstes erstellen wir die Dll. Ich benutze hier die Programmiersprache C++, doch kann auch eine beliebig andere Sprache zum erstellen von Dll-Datein verwendet werden
Ich habe die Dll übrigens auch angehängt.
Wer bereits einen Injector wie z.B. winject17b besitzt kann einmal probieren die Dll in NotePad zu injitieren und wird sehen, dass Notepad plötzlich fähig ist, eine Message Box auszugeben
Wie mache ich so eine "Code injection" (/erstelle einen Injector)?
Unser zweites Ziel ist es jetzt aber, selbst einen Injector zu basteln, der unsere Dll in einen fremden Prozess (ich nehme Notepad
) läd.Dabei gehen wir nach folgendem Konzepte:
1. Wir schreiben den Pfad unserer Dll in das fremde Programm
2. Wir rufen die "LoadLibraryA" Funktion der Kernel Dll auf und übergeben ihr den Dll-Pfad als Parameter
3. Wir warten, bis alles geklappt hat und löschen dann den nicht mehr länger benötigten Dll Pfad aus dem fremden Prozess
Wir beginnen also mit einer schlichten Konsolen Anwendung - dem Grundgerüst eines solchen Programmes:
Code:
#include "windows.h"//Für spätere Funktionen nötig
#include <iostream>//Für spätere Funktionen nötig
using namespace std;//Für spätere Funktionen nötig
int main(int argc, char* argv)//Programm Einstieg
{
}
Code:
#include "windows.h"
#include <iostream>
using namespace std;
char const Path[]="C:\\Message Box.dll";//deklariert den Pfad zu unserer dll
int main(int argc, char* argv)
{
HANDLE hWnd;
DWORD PID;
hWnd = FindWindow(0, "Unbenannt - Editor");//sucht nach dem angegebenen Fenster und gibt das Hwnd zurück
//Parameter 1: evtl. Klasse des Fensters; Parameter 2: Titel des Fensters
GetWindowThreadProcessId((HWND)hWnd, &PID);//legt die PID in der Variable PID ab
//Parameter 1: hWnd eines Fensters des Prozesses; Parameter 2: Variable, in die die PID abgelegt werden soll
}
Wir müssen also zu unseren Variablen noch eine weitere Variable vom Typ "HANDLE" hinzufügen.
Code:
HANDLE hWnd, hProcess;
DWORD PID;
hWnd = FindWindow(0, "Unbenannt - Editor");
GetWindowThreadProcessId((HWND)hWnd, &PID);
hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, PID);//öffnet den Prozess mit den Berechtigungen, zum schreiben, lesen, ausführen, etc. (PROCESS_ALL_ACCESS)
//Parameter 1: Zugriffs Berechtigungen; Parameter 2: unwichtig, aber auf google nachlesbar; Parameter 3: Die PID des Prozesses, der geöffnet werden soll
Diesen freien Platz kann man mit der Funktion "VirtualAllocEx" anfordern (alternativ kann man aber auch Code Caves benutzen), die uns die Adresse des Speichers übergibt und die wir wieder in einem HANDLE speichern.Code:
HANDLE hWnd, hProcess, AllocAdresse;
DWORD PID;
hWnd = FindWindow(0,"Unbenannt - Editor");
GetWindowThreadProcessId((HWND)hWnd, &PID);
hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, PID);
AllocAdresse = VirtualAllocEx(hProcess, 0, sizeof(Path), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
//Parameter 1: Handle zum Prozess; Parameter 2: Adresse ab der nach freiem Speicher gesucht werden soll
//Parameter 3: Größe des anzuvordernen Speichers; Parameter 4: siehe [url=http://msdn.microsoft.com/en-us/library/aa366890%28VS.85%29.aspx]VirtualAllocEx Function (Windows)[/url]
//Parameter 5: Wofür der Speicher verwendet werden soll (siehe [url=http://msdn.microsoft.com/en-us/library/aa366786%28VS.85%29.aspx]Memory Protection Constants (Windows)[/url])
Code:
WriteProcessMemory(hProcess, (void*)AllocAdresse, (void*)Path, sizeof(Path), 0); //Parameter 1: Handle zum Prozess; Parameter 2: StartAdresse, des zu beschreibenen Speichers //Parameter 3: der Wert, der in den Speicher geschrieben werden soll; Parameter 4: Speichergröße des Wertes //Parameter 5: unwichtig - siehe [url=http://msdn.microsoft.com/en-us/library/ms681674%28VS.85%29.aspx]WriteProcessMemory Function (Windows)[/url]
Code:
HANDLE hWnd, hProcess, AllocAdresse, hRemoteThread;
DWORD PID;
hWnd = FindWindow(0,"Unbenannt - Editor Editor");
GetWindowThreadProcessId((HWND)hWnd, &PID);
hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, PID);
AllocAdresse = VirtualAllocEx(hProcess, 0, sizeof(Path), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(hProcess, (void*)AllocAdresse, (void*)Path, sizeof(Path), 0);
hRemoteThread=CreateRemoteThread(hProcess, 0, 0, (LPTHREAD_START_ROUTINE) GetProcAddress(GetModuleHandle("kernel32.dll"),"LoadLibraryA"), AllocAdresse, 0, 0);
//Parameter 1: Prozess Handle; Parameter 2: unwichtig - siehe [url=http://msdn.microsoft.com/en-us/library/ms682437%28VS.85%29.aspx]CreateRemoteThread Function (Windows)[/url]
//Parameter 3: Thread Stack Größe (siehe [url=http://msdn.microsoft.com/en-us/library/ms686774(VS.85).aspx]Thread Stack Size (Windows)[/url])
//Parameter 4: Die Adresse der Funktion, die aufgerufen werden soll; Parameter 5: übergebene Parameter
//Parameter 5&6: unwichtig -> siehe [url=http://msdn.microsoft.com/en-us/library/ms682437%28VS.85%29.aspx]CreateRemoteThread Function (Windows)[/url]
! Der wichtigste Teil ist geschafft. Jetzt müssen wir nur noch warten bis die "LoadLibraryA" Funktion beendet und unsere Dll geladen ist und wir können die benutzen Resourcen weder freigeben. Zum warten eignet sich die Funktion "WaitForSingleObject", zum Speicherplatz freigeben die "VirtualFreeEx" Funktion und zum beenden der Prozessbearbeitung die "CloseHandle" Funktion.
Code:
WaitForSingleObject(hRemoteThread, INFINITE);
//Parameter 1: Handle zum Object; Parameter 2: Wartezeit in Millisekunden (INFINITE steht für unendlich lang, ist aber einfach nur eine sehr hohe Zahl)
VirtualFreeEx(hProcess, AllocAdresse, sizeof(Path), MEM_DECOMMIT);
//Parameter 1: Handle zum Prozess; Parameter 2: freizugebende Startadresse; Parameter 3: größe des freizugebenden Speichers
//Parameter 4: Typ des freizugebenden Speichers (siehe [url=http://msdn.microsoft.com/en-us/library/aa366894%28VS.85%29.aspx]VirtualFreeEx Function (Windows)[/url])
CloseHandle(hProcess);
//Parameter 1: Handle zum Prozess
zusammengefügt sollte der Code etwa folgendermaßen aussehen:
Debug Rechte setzen:
Wenn wir unseren Injector an mehreren Programmen testen, merken wir jedoch, dass es Prozesse gibt, in die wir nicht injecten können
Doch keine Sorge, denn es ist nur unser Betriebssystem, das der meinung ist, unser Programm sei noch viel zu klein um über andere Programme bestimmen zu können :werderw:
Wir müssen uns also einfach nur das besondere Pivileg verleihen, fremde Prozesse bearbeiten zu dürfen.
Dieses Privileg wird auch "Debug Privilege" genannt, da es in erster Linie von Debuggern (Wartungsprogramme; Eines der bekanntesten Debugger ist OllyDbg) benutzt wird.Da wir also ein Debug Recht setzen müssen, heißt unsere Funktion:
Code:
void SetDebugPrivilege() {}
)Wir brauchen also eine Variable für das Handle unsere Prozesses und eine für das Handle des Tokens.
Code:
void SetDebugPrivilege()
{
HANDLE hProcess=GetCurrentProcess(), hToken;
}
Code:
void SetDebugPrivilege()
{
HANDLE hProcess=GetCurrentProcess(), hToken;
TOKEN_PRIVILEGES priv;
}
Code:
void SetDebugPrivilege()
{
HANDLE hProcess=GetCurrentProcess(), hToken;
TOKEN_PRIVILEGES priv;
LUID luid;
OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken);//öffnet unser Prozess token zum "anpassen"(adjust) und speichert ein handle zum verwalten in hToken ab.
LookupPrivilegeValue(0, "seDebugPrivilege", &luid)/*speichert den LUID wert von "seDebugPrivilege" in die LUID-Variable. 0 heißt,
dass es die LUID von unserem System und nicht etwa die eines remote-systems sein soll*/
}
" in ein Privilegien array und ein integer mit der anzahl der Privilegien, die man hinzufügen will, eingeteilt. wir müssen also die Anzahl der zusetzenden Privilegen angeben (in unserem Fall nur eins) und dann noch schnell das Privileg beschreiben, bevor wir es dann setzen.
zum Schluss müssen wir nurnoch unsere beiden Handle wieder schließen und wir haben unsere funktion fertig! :burns:
Diese Funktion rufen wir dann am Anfang der "Main"-Funktion des injectors auf und können neue erfolgreichere Testversuche machen.
ACHTUNG: Der Injector muss mit Administratorrechten ausgeführt werden!
Ich hoffe sehr, dass euch das Tutorial gefallen hat und epvp&AutoitBot (Das Original Tutorial habe ich heir veröffentlicht:
) freuen sich selbstverständlich über Ergebnisse!
MFG,
Deathly Assassin
Anmerkung: Im Anhang Befindet sich die im Tutorial benutzte Dll und eine Autoit UDF, die es ermöglicht in der Scriptsprache Autoit einen Injector zu erstellen (enthaltene Funktionen: _InjectAttachDll; _InjectDetachDllEx; _InjectDetachDll; _InjectModulInfo)







