Dll Injection

Hi,

ich habe folgendes tutorial aus dem Wiki ausprobiert:

Hier

Leider klappt das bei mir nicht so ganz.
Jedes mal wenn ich versuche meine DLL in einen Prozess zu injecten stürtzt der
Zielprozess ab :(

Wenn ich die stelle an der der RemoteThread erzeugt wird weglasse, geht's.
Aber es passiert natürlich auch nichts.

D.h meine frage:

Warum strürtzt der Zielprozess immer ab ?
und vorallem: Wie kann ich das verhindern ?


Btw: Es ist egal in welchen prozes ich injecte. DebugPrivs hab ich, ich bin auch als admin angemeldet :/

OS: WinXP SP2
Compiler: VC++ '05
 
Hier wär ein Code der um einiges einfacher is :

Code:
int InjectDll(HANDLE hProcess,char* dll_to_inject)
{
 LPVOID VirtualMem;
 LPTHREAD_START_ROUTINE ThreadAddr = 0;
 HMODULE KernelModul;
 DWORD rw = 0;
   
 VirtualMem = VirtualAllocEx(hProcess,NULL,strlen(dll_to_inject),MEM_COMMIT,PAGE_READWRITE);
 if(!VirtualMem)      
  return -1;

 KernelModul = GetModuleHandle("Kernel32");
 if(!KernelModul)      
  return -1;

 ThreadAddr = (LPTHREAD_START_ROUTINE) GetProcAddress(KernelModul,"LoadLibraryA");
 if(!ThreadAddr)      
   return -1;
       
 if(!WriteProcessMemory(hProcess,VirtualMem,(LPVOID)dll_to_inject,strlen(dll_to_inject),&rw))
   return -1;

 thread = CreateRemoteThread(hProcess,NULL,0,ThreadAddr,VirtualMem,0,NULL);

 if(!thread)
   return -1;
 
 WaitForSingleObject(thread,INFINITE);  
 VirtualFreeEx(hProcess,VirtualMem,0,MEM_RELEASE);
 CloseHandle(thread);
 CloseHandle(hProcess);

 return 0;
}
Dann nochmal via CreateRemoteThread eine Funktion aus der Dll laden
 
Also der code den du gepostet hast zwingt den "Target Prozess" sozusagen
meine DLL zu laden.

Und dann soll ich einfach einen remote Thread erstellen der also eine funktion aus der bereits geladene DLL "holt" und dann ausführt


Code:
DWORD WINAPI Remote_Thread()
{
MYPROC Proc = GetProcAddress( ???, "MeineDllFunktion");
}

Das ??? ist ja die DLL aus der die addresse des proc's geladen werden soll.
aber woher krieg ich den nach dem Laden der dll im Zielprozess das handle auf die geladene DLL ?

Ich komm da jetzt grade nich ganz mit...
 
moinsen,

also wenn du deinen code direkt nach dem injecten ausführen willst, könntest du auch direkt im konstruktor/einstiegspunkt (DllMain) der dll deine funktionen aufrufen.

MfG
 
Nein das klappt nicht wie ich selbst vor kurzem erfahren musste da die Prozesse sich dann aufhängen.

Sobald der andere Prozess die DLL geladen hast musst du folgendes machen:

Code:
 HINSTANCE my_dll = LoadLibrary("meinedll.dll");
 ThreadAddr = (LPTHREAD_START_ROUTINE)  GetProcAddress(my_dll,"funktion_die_der_andere_prozess_aufrufen_soll");
 thread = CreateRemoteThread(hProcess,NULL,0,ThreadAddr,0,0,NULL);

So in etwa ;)
 
Code:
	HANDLE ProzessHandle;
	int id2;

	printf("PID: ");
	scanf("%d", &id2);

	ProzessHandle = OpenProcess(PROCESS_ALL_ACCESS, false, id2);
	if(ProzessHandle == 0)
		printf("OpenProcess faild !\n");

InjectDll(ProzessHandle, "C:\\dll.dll")


	LPTHREAD_START_ROUTINE ThreadAddr = (LPTHREAD_START_ROUTINE) GetProcAddress(dll, "hSay");
	HANDLE RemoteThread = CreateRemoteThread(ProzessHandle, 0, 0, ThreadAddr, 0, 0, 0);

	if(RemoteThread == 0)
		printf("Creating Func-Thread faild !\n");

	printf("\nGetLastError() == %d\n", GetLastError());

Die Dll hab ich vor diesem Code schon geladen.
(in der variabelen "dll" ^^)

Bei CreateRemoteThread liefert die funktion immer NULL zurück
und das letzte GetlastError liefet den Fehlercode nummer 6 (Invalid Handle)

Jemand ne idee ?
Hat die DLL injection überhaupt schon mal bei jemandem hier funktioniert ?
 
@Felheart
LPTHREAD_START_ROUTINE ThreadAddr = (LPTHREAD_START_ROUTINE) GetProcAddress(dll, "hSay");
sehe ich es richtig (bin des C nicht wirklich mächtig): Du versuchst den RemoteThread an einer Adresse zu starten, die Du aus der "aktuellen" Anwendung holst ? Das kann nicht klappen, da die DLL in der anderen Anwendung an eine andere Basisadresse geladen werden kann - und somit die Funktionsadressen nicht mehr stimmen.

Das "InvalidHandle" könnte wegen mangelnder Rechte stammen - muss ich mal genauer in meiner Sammlung nachschauen (manchmal muss man sich expliziert im Programm selbst noch Rechte beschaffen, um einen Prozess per OpenProcess vollständig manipulieren zu können)

@Xalon
Nein das klappt nicht wie ich selbst vor kurzem erfahren musste da die Prozesse sich dann aufhängen.
Doch, klappt eigentlich wunderbar. Natürlich sollte return(TRUE) am Ende korrekt sein und insgesamt eine "normale" DLL (nicht dieses ActiveX usw Zeug) benutzt werden.

Bei Deinem Code sehe ich allerdings ein Problem: LoadLibraryA des Zielprozesses wird per CreateRemoteThread aufgerufen - soweit so gut. Allerdings wird dabei nur ein Parameter übergeben - und LoadLibrary nimmt 2 entgegen.
Weiterhin: was passiert, wenn LoadLibrary Funktion returnt? Ich nehme an, Du verlässt Dich auf die von Windows automatisch auf dem Stack abgelegte Return Adresse zum ExitThread.
Allerdings kommt mir das ganze wegen den Parametern etwas suspekt vor: von CreateRemoteThread wird nur 1 Parameter gepusht, beim Return in der LoadLibraryA werden aber 2 Parameter gepoppt (und damit auch die Rückkehradresse). Bin jetzt aber zu faul in Olly das Ganze nachzuvollziehn.

@Felheart
Hat die DLL injection überhaupt schon mal bei jemandem hier funktioniert ?

siehe (unter win2k,XP SP1,SP2 getestet):
[3H] CrackMe lvl1 - solved
Crackme#3 - Solved by CDW

auch wenn jetzt das Laden der DLL eher abenteuer
lich anmutet (es wird Code injiziert, der die DLL lädt - das geht auch eleganter) - danach wird alles wesentliche in der DLL Main aufgerufen - z.B der zusätzliche Dialog läuft in der DLL.

andere Methoden:
Dll injection
http://y0da.cjb.net/ (unter Artikeln)
 
@Felheart
Zitat:
LPTHREAD_START_ROUTINE ThreadAddr = (LPTHREAD_START_ROUTINE) GetProcAddress(dll, "hSay");

sehe ich es richtig (bin des C nicht wirklich mächtig): Du versuchst den RemoteThread an einer Adresse zu starten, die Du aus der "aktuellen" Anwendung holst ? Das kann nicht klappen, da die DLL in der anderen Anwendung an eine andere Basisadresse geladen werden kann - und somit die Funktionsadressen nicht mehr stimmen.

Das "InvalidHandle" könnte wegen mangelnder Rechte stammen - muss ich mal genauer in meiner Sammlung nachschauen (manchmal muss man sich expliziert im Programm selbst noch Rechte beschaffen, um einen Prozess per OpenProcess vollständig manipulieren zu können)

- Der Code is ned von mir, ich hab ihn einfach von Xalon's Post Kopiert :)
aber das hab ich mir auch gedacht.

Was ich meine ist das ich bei GetProcAddress( XXX, "hSay");

anstatt der selbstgeladenen DLL (im eigenen prozerss) doch das handle der dll die durch den Zielprozess geladen wurde eintragen muss.


- Invalid Handle: hmm, ich hab keine ahnung warum das so ist.
Weil Open Process ja keinen NULL wert zurückliefert.
d.h. -> injecten lässt sich die DLL aber der REmote thread geht irgenwie kein 2. mal.

Btw: ich glaub ned das das an mangelnden rechten liegt.
bin unter WinXP Sp2 als admin angemeldet, und hab Notepad selbst gestartet :)
Debug Privs hab ich auch für mein Programm via Funktion bereitgestellt.

LoadLibraryA des Zielprozesses wird per CreateRemoteThread aufgerufen - soweit so gut. Allerdings wird dabei nur ein Parameter übergeben - und LoadLibrary nimmt 2 entgegen.

Ich hab in der MSDN geschaut.
Was sind den die 2 Parameter ?
Also ich seh da blos einen: LPSTR lpFileName
und mehr braucht die funktion doch auch garned zu wissen um die DLL zu laden oder ?
Verwechselt du das gerade mit GetProcAddress ?


die Links schau ich mir gleich mal an, sieht interessant aus ^^


//edit:

Verdammt, sobald ein prozess die DLL geladen hat muss ich hin neustarten das er sie nicht mehr geladen hat.

Solange kann ich auch die DLL nicht ersetzen.

giebt es einen weg DLL's auch wieder zu ENT-laden.
Kennt jemand ein programm mit dem ich DLL's aus prozessen entladen kann ?

Oder noch viel besser ist es möglich eine funktion in eine DLL einzubauen die beim aufruf sich selbst entläd ? -.-

// edit 2:

FreeLibary()

aber geht das auch aus der DLL selbst ?
 
Was ich meine ist das ich bei GetProcAddress( XXX, "hSay");

anstatt der selbstgeladenen DLL (im eigenen prozerss) doch das handle der dll die durch den Zielprozess geladen wurde eintragen muss.
Naja, das "Handle" zu der DLL ist eigentlich die aktuelle Basisadresse dieser DLL im (virtuellen)Speicher der Anwendung. Also nicht prozessübergreifend.


Debug Privs hab ich auch für mein Programm via Funktion bereitgestellt.
dann sollte es "Rechtemäßig" schon alles sein.

Ich hab in der MSDN geschaut.
Ich auch :). Allerdings war ich wohl wirklich irgendwie auf die GetProcAddress "fixiert".
Also LoadLibraryA aufruf sollte schon so klappen. Du schreibst ja auch, dass die DLL geladen wird.


FreeLibary()

aber geht das auch aus der DLL selbst ?
Du kannst es ja probieren ;)
 
Also CDW bei mir funktioniert das Injecten mit obigem Code super.
Und man sollte deshalb nicht alles in der Main machen da ein Prozess keine DLLs laden kann solange noch eine
DLL in ihrer Main ist.

Der IE , FF und ICQ z.B hängen sich dabei auf.

@Threadsteller: Du musst den Pfad deiner DLL absolut angeben.
Sobald ich meinen PC wieder hab werde ich hier mal Funktionierenden Bsp Code posten

Xalon
 
Also CDW bei mir funktioniert das Injecten mit obigem Code super.
Sorry, ich war zu sehr auf GetProcessAddress fixiert.

Und man sollte deshalb nicht alles in der Main machen da ein Prozess keine DLLs laden kann solange noch eine
starte in der Main einen Thread, returne - und die Sache ist gegessen ;)
Allemal einfacher, als zu versuchen, die Adressen der DLL Funktionen in einem fremden Prozess herauszubekommen ;)
 
Ok, leute nach viel rumgebastele und gegeoogele hab ich endlich eine funktion hingekrigt
die 3 argumante übernimmt:

InjectDll(DWORD PID, char* "abslouter dll pfad", char* FTSAL);

FTSAL == Function to start after Load.

Code:
#include <iostream>
using namespace std;
#include <windows.h>
#include <stdio.h>
#include "GetProcessID.h"
#define CREATE_THREAD_ACCESS (PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ)


void EDP()
{
	TOKEN_PRIVILEGES priv;
	HANDLE hThis, hToken;
	LUID luid;
	hThis = GetCurrentProcess();

	OpenProcessToken(hThis, TOKEN_ADJUST_PRIVILEGES, &hToken);
	LookupPrivilegeValue(0, "seDebugPrivilege", &luid);
	priv.PrivilegeCount = 1;
	priv.Privileges[0].Luid = luid;
	priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
	AdjustTokenPrivileges(hToken, false, &priv, 0, 0, 0);

	CloseHandle(hToken);
	CloseHandle(hThis);
}

int Inject(DWORD PID, char *dllname, char* DLL_FUNC_TO_START)
{
	EDP();

	HANDLE process;
	char buf[50]={0};
	LPVOID stringaddr, loadlibaddr;

	process = OpenProcess(CREATE_THREAD_ACCESS, 0, PID);

	if(process == 0)
	{
		printf("FEHLER:\tDerProzess konnte nicht geöffnet werden. (Fehlende Rechte ?)");
		return -1;
	}

	loadlibaddr = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");

	stringaddr = (LPVOID)VirtualAllocEx(process, NULL, strlen(dllname), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
	WriteProcessMemory(process, (LPVOID)stringaddr, dllname, strlen(dllname), NULL);
	
	HANDLE thread=CreateRemoteThread(process, NULL, NULL, (LPTHREAD_START_ROUTINE)loadlibaddr, (LPVOID)stringaddr, NULL, NULL);//load the function into targets memory
	
	if(thread == 0)
	{
		printf("Fehler beim erstellen Loader-Threads");
		return -2;
	}
	WaitForSingleObject(thread,INFINITE);

	DWORD exitcode;
	GetExitCodeThread(thread,&exitcode);
	DWORD offset;
	HMODULE findoff=LoadLibrary(dllname);
	DWORD modfunc=(DWORD)GetProcAddress(findoff, DLL_FUNC_TO_START);
	offset=modfunc-(DWORD)findoff;
	exitcode=exitcode+offset;

	HANDLE thread2=CreateRemoteThread(process,NULL,NULL,(LPTHREAD_START_ROUTINE)exitcode,NULL,NULL,NULL);//execute the function
	if(thread2 == 0)
	{
		// DLL-Func-Einsprungspunkt nicht gefunden oO
		return -3;
	}
	CloseHandle(process);
	return 1;
}

void main()
{
	DWORD PID;
	do
	{
		PID = GetProcessID("notepad.exe");
		Sleep(1);
	}while(!PID);

	printf("Notepad found, injecting.....\n\n");

	int ret = Inject(PID, "C:\\loldll.dll", "test_f1");

	if(ret == 1)
		printf("DLL Successfully injected !!!");

	Sleep(INFINITE);
}


Btw: ich finde die Process id mit einer selber gemachen Header datei,
die ich wuch jetzt auch nicht vorenthalten will xD

Code:
#include "TLHELP32.H"
#include <windows.h>

DWORD GetProcessID (char* ProcName)
{
	HANDLE h;
	h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

	PROCESSENTRY32 st;
	st.dwSize=sizeof(PROCESSENTRY32);

	bool resp=Process32First(h,&st);
	
	while(resp)
	{
		//printf("Name: %s\nProcess ID : %u\n\n", st.szExeFile, st.th32ProcessID);
		if(!strcmp(st.szExeFile, ProcName))
		{
			CloseHandle(h);
			return (st.th32ProcessID);
		}
		st.dwSize = sizeof(PROCESSENTRY32);
		resp = Process32Next(h,&st);
	}

	CloseHandle(h);
	return 0;
}

@CDW

Und man sollte deshalb nicht alles in der Main machen da ein Prozess keine DLLs laden kann solange noch eine
starte in der Main einen Thread, returne - und die Sache ist gegessen ;)
Allemal einfacher, als zu versuchen, die Adressen der DLL Funktionen in einem fremden Prozess herauszubekommen ;)

das ist ne gute idee

@Xalon:

Also CDW bei mir funktioniert das Injecten mit obigem Code super.
Und man sollte deshalb nicht alles in der Main machen da ein Prozess keine DLLs laden kann solange noch eine
DLL in ihrer Main ist.

Der IE , FF und ICQ z.B hängen sich dabei auf.

Also wenn ich wie CDW sage in der Main nen Thread erstelle und dann returne,
geht das dann mit FF und Co. ?
Ich werd das später mal selbst testen ^^

@Threadsteller: Du musst den Pfad deiner DLL absolut angeben.
Sobald ich meinen PC wieder hab werde ich hier mal Funktionierenden Bsp Code posten
Auch wenn ich die Lösung schon hab', poste trozdem dann bitte deine Version des
codes :)
 
das ist ne gute idee
in den oben verlinken Threads nutze ich das, um einen zusätzlichen Dialog anzuzeigen, der dann aus dem Programmspeicher ausgelesene Informationen enthält. Das Programm läuft ganz normal weiter. Ich gehe stark davon aus, dass es sich auch bei größeren Progarmmen so verhält ;)
Code:
LibMain proc hInstDLL:DWORD, arg:DWORD, reserviert:DWORD
      
        .if arg == DLL_PROCESS_ATTACH
            invoke CreateThread,0,0,addr Thread,addr BytesWritten,NULL,addr ThreadID
            ;patchen           
            mov eax,1
            ret 
       .elseif arg==DLL_PROCESS_DETACH       	
           mov eax,1        
        .endif
        ret
LibMain Endp

Thread proc
           invoke GetModuleHandle,NULL
            mov hInstance,eax

           ..gekürzt, da nur Patchcode..
	
	invoke DialogBoxIndirectParam,hInstance,addr template,NULL,addr DialogProc,NULL
	invoke ExitThread,0	
	ret

Thread endp


DialogProc proc hWin:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
LOCAL buffer [MAX_BUFFER]:byte

    .if uMsg == WM_INITDIALOG
... usw...
auch wenn es jetzt MASM ist - die APIs kann man denke ich gut entziffern.
 
von Assambler hab ich leider keine ahnung, aber
du hast recht; man kann schon so ungefähr lesen um was es geht ^^

Btw: kennstdu ein gutes tutorial mit dem man so wenigestensie grundelagen von
Asm oder MASM oder was auch immer lernen kann ?
(was ist überhaupt der unterschied zwischen MASM und normalem ASM und NASM usw. ?)
 
Original von Felheart
Btw: kennstdu ein gutes tutorial mit dem man so wenigestensie grundelagen von
Asm oder MASM oder was auch immer lernen kann ?
(was ist überhaupt der unterschied zwischen MASM und normalem ASM und NASM usw. ?)
http://wiki.hackerboard.de/index.php/Programmieren_links#Assembler
The Art of Assembly Language Programmin:
http://webster.cs.ucr.edu/

Unterschiede zwischen MASM/NASM/FASM/TASM:
naja, im Prinzip ist das Grundgerüst gleich, allerdings gibt es deutliche Unterschiede in den "Erweiterungen" - also Variablendefintionen, Macros usw.
Unter MASM kann man z.B statt:
push a
push b
push c
call function

auch
invoke function,c,b,a schreiben (was kürzer und übersichtlicher ist). Mit Hilfe der Macros lässt sich das Ganze sogar so erweitern, dass man fast "Basic-like" programmieren kann:
Code:
mov str3, cat$(str2,"Windows directory is ",lcase$(WinDir$()),SADD(13,10))

Welchen Assembler man nutzt, ist Geschmackssache - unter Windows wird man wohl eher MASM nehmen, unter Linux NASM.
 
Meinst du jetzt das eine DLL keine Threads starten kann ?
oder meinst du das eine DLL keine Threads im Prozess der sie geladen hat starten kann ?

also ersteres geht oO
 
Hmm leider ist das in assembler.

Kann das viell jmd in C übersetzen?

Pseudocode wäre auch schon hilfreich (ich meine einen Thread starten, sodass der Prozess normal weiterläuft und der Code in der dll parallel dazu läuft)

Wär ur toll,

thx, mfg
 
Zurück
Oben