Dll Injection - Passiert was?



  • Ich versuche eine dll injektion durchzuführen, aber irgendwie klappt das (keine Fehler) aber irgendwie auch nicht (das gewünschte passiert nicht).
    Irgendwelche Ideen / Möglichkeiten festzustellen, ob und was eigentlich im Programm passiert?

    Aber evt. ist mein Code auch fehlerhaft, wobei ich den eigentlich mit mehreren tuts abgeglichen habe:

    // lil.dll
    #if defined(_MSC_VER)
    #include <windows.h>
    #define DLL extern "C" __declspec(dllexport)
    #else
    #define DLL
    #endif
    
    DLL void SayHi ( void ) 
    {
    	::MessageBox( 0, "Injection succeed!", "T", 1 );
    }
    
    BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved )
    {
    	if( reason == DLL_PROCESS_ATTACH )
    		 CreateThread( 0, 0, ( LPTHREAD_START_ROUTINE )SayHi, 0, 0, 0 );
        return TRUE;
    }
    
    // inection.cpp
    #include "windows.h"
    #include <iostream>
    
    using namespace std;
    
    string dllPath = "lil.dll";
    
    void SetDebugPrivilege( ) 
    {
    	HANDLE hProcess = GetCurrentProcess( );
    	HANDLE hToken;
    	TOKEN_PRIVILEGES tokpriv;
    	LUID luid;
    
    	OpenProcessToken( hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken );
    	LookupPrivilegeValue( 0, "seDebugPrivilege", &luid );
    
        tokpriv.PrivilegeCount = 1;
    	tokpriv.Privileges[0].Luid = luid;
    	tokpriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        AdjustTokenPrivileges( hToken, false, &tokpriv, 0, 0, 0 );
    
    	CloseHandle(hToken);
    }
    
    int main( int argc, char* argv )
    {
        HANDLE hWnd;
    	HANDLE hProcess;
    	HANDLE hRemoteThread;
    	HANDLE AllocAdress;
        DWORD PID;
    
    	SetDebugPrivilege( );
    
        hWnd = FindWindow( 0,"Unbenannt - Editor" );
    	if( hWnd == 0 )
    		::MessageBox( 0, "FindWindow failed.", "E", 0 );
    
    	GetWindowThreadProcessId( ( HWND )hWnd, &PID );
    
        hProcess = OpenProcess( PROCESS_ALL_ACCESS, false, PID );
    
        AllocAdress = VirtualAllocEx( hProcess, 0, sizeof( dllPath ), MEM_COMMIT, PAGE_EXECUTE_READWRITE );
        WriteProcessMemory( hProcess, ( void* )AllocAdress, ( void* )dllPath.c_str( ), sizeof( dllPath ), 0 );
        hRemoteThread=CreateRemoteThread( hProcess, 0, 0, ( LPTHREAD_START_ROUTINE )GetProcAddress( GetModuleHandle( "kernel32.dll" ),"LoadLibraryA" ), AllocAdress, 0, 0 );
    
        WaitForSingleObject( hRemoteThread, INFINITE );
    
        VirtualFreeEx( hProcess, AllocAdress, sizeof( dllPath ), MEM_DECOMMIT );
        CloseHandle( hProcess );
    }
    


  • OS?
    Win 7 / Vista?

    Siehe: Address Randomization
    http://msdn.microsoft.com/en-us/library/bb384887.aspx

    Das ist für alle Windows-DLLs aktiviert und somit liefert das "GetprocAddress" die "falsche" Adresse (nämlich die, welche in *Deinem* Prozess gültig ist, nicht aber im anderen 😉 ).



  • Windows XP noch

    also d.h. dass die dll gar nicht erst injeziert wird ?



  • Jo, aber weil du das machst:

    string dllPath = "lil.dll";
    // ...
    sizeof( dllPath )
    

    Gucken:
    http://en.wikipedia.org/wiki/Sizeof
    http://www.cplusplus.com/reference/string/string/size/



  • Hä??
    Durch was muss ich das dann ersetzen?


  • Mod

    Danyka schrieb:

    Hä??
    Durch was muss ich das dann ersetzen?

    Du hast doch die Links. Warum liest Du nicht?
    sizeof liefert die die Größe des string Objektes und icht die Länge des Strings.

    string ist kein char[]!



  • naja, ich kann ja einfach sizeof( dllPath ) durch dllPath.size( ) ersetzen (darauf wollt ihr doch hinaus, oder?), jedoch ohne Erfolg



  • Dann liegt es tatsächlich an der blöden "Address Randomization".
    Die ist aber nur bei Dateien aktiv, die mit eben dieser Linkeroption erstellt wurden.
    Notepad könnte da halt dazugehören, bei eigenen Programmen ohne der Option sollte es hinhauen.

    Ich glaub, da bleibt dir nur, die Module eines fremden Prozesses mit CreateToolhelp32Snapshot + Module32First/Module32Next zu enumerieren und so die Base zu holen.

    Übrigens, nein kannst du nicht. std::string::size() gibt die Länge ohne Terminierungszeichen zurück. Das solltest du aber auch in den Prozess schreiben, sonst ist es nur Glück, dass nach deinem String eine Null kommt.
    Also .size() + 1 schreiben. In Verbindung mit .c_str() ist das ok.



  • Hi

    Rate mal was dir createtoolhelp32snapshot liefert !?

    Lowbyte



  • Credits an Cypher von MMOWNED bzw , von seinem Code habe ich die Funktion für meine Library "geklaut" 😉 http://blog.cypherjb.com/ :

    //Written by Cypher, credit him
    	FARPROC Process::customGetProcAddress(HMODULE module, const std::string& functionName) const
    	{
    		PIMAGE_DOS_HEADER pDosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(module);
    		if(!pDosHeader || pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
    			throw std::runtime_error("Process::customGetProcAddress Error : DOS PE header is invalid.");
    
    		PIMAGE_NT_HEADERS pNtHeader = reinterpret_cast<PIMAGE_NT_HEADERS>(reinterpret_cast<PCHAR>(module) + pDosHeader->e_lfanew);
    		if(pNtHeader->Signature != IMAGE_NT_SIGNATURE)
    			throw std::runtime_error("Process::customGetProcAddress Error :  NT PE header is invalid.");
    
    		PVOID pExportDirTemp				= reinterpret_cast<PBYTE>(module) + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
    		PIMAGE_EXPORT_DIRECTORY pExportDir	= reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(pExportDirTemp);
    		if(pExportDir->AddressOfNames == NULL)
    			throw std::runtime_error("Process::customGetProcAddress Error : Symbol names missing entirely.");
    
    		PDWORD pNamesRvas			= reinterpret_cast<PDWORD>(reinterpret_cast<PBYTE>(module) + pExportDir->AddressOfNames);
    		PWORD pNameOrdinals			= reinterpret_cast<PWORD>(reinterpret_cast<PBYTE>(module) + pExportDir->AddressOfNameOrdinals);
    		PDWORD pFunctionAddresses	= reinterpret_cast<PDWORD>( reinterpret_cast<PBYTE>(module) + pExportDir->AddressOfFunctions);
    
    		for (DWORD n = 0; n < pExportDir->NumberOfNames; n++) 
    		{
    			PSTR CurrentName = reinterpret_cast<PSTR>(reinterpret_cast<PBYTE>(module) + pNamesRvas[n]);	  
    			if(functionName == CurrentName)
    			{
    				WORD Ordinal = pNameOrdinals[n];
    				return reinterpret_cast<FARPROC>(reinterpret_cast<PBYTE>(module) + pFunctionAddresses[Ordinal]);
    			}
    		}
    
    		return 0;
    	}
    


  • lowbyte_ schrieb:

    Hi
    Rate mal was dir createtoolhelp32snapshot liefert !?
    Lowbyte

    MSDN schrieb:

    it returns an open handle to the specified snapshot

    Auf was willst du hinaus?

    😕



  • Hi

    Meine wen du die Base addr. holen willst !Des von dir gewünschten Proc. !
    Überleg dir mal was dan Microsoft random addr. bringen würde? nichts ! darum kannst du die Variante vergessen bei Vista,Win7 und zum teil WinXp.

    Lowbyte



  • Und zwar so: (Ich liebe Spoonfeeding 😃 )

    DWORD_PTR Process::getModuleBaseByName(std::wstring moduleName, bool isPath) const
    	{
    		//Convert given name to lowercase
    		std::transform(moduleName.begin(), moduleName.end(), moduleName.begin(), towlower);
    
    		//Get a snapshot of all modules
    		SafeHandle modSnapshot(CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, processId_));
    		if(modSnapshot == INVALID_HANDLE_VALUE)
    			throw WinException("Process::getModuleBaseByName()", "CreateToolhelp32Snapshot()", GetLastError());
    
    		//Iterate the complete module-list and break if module is found
    		MODULEENTRY32W modEntry = { sizeof(modEntry) };
    		for(BOOL moreModuleEntries = Module32FirstW(modSnapshot, &modEntry); moreModuleEntries; moreModuleEntries = Module32NextW(modSnapshot, &modEntry)) 
    		{
    			//Convert current modulename to lowercase
    			std::wstring currentModulePath(modEntry.szExePath);
    			std::transform(currentModulePath.begin(), currentModulePath.end(), currentModulePath.begin(), towlower);
    
    			//Cut off all text before the module name if the user didn't supply a path
    			if(!isPath)
    			{
    				std::wstring currentModuleName(currentModulePath.substr(currentModulePath.find_last_of(L"\\") + 1));
    				if(currentModuleName == moduleName)
    					return reinterpret_cast<DWORD_PTR>(modEntry.modBaseAddr);
    			}
    			else
    			{
    				//Else just compare
    				if(currentModulePath == moduleName)
    					return reinterpret_cast<DWORD_PTR>(modEntry.modBaseAddr);
    			}
    		}
    
    		//Nothing found
    		return 0;
    	}
    


  • Welche Variante? An wen war die erste Frage eigentlich gerichtet?

    Meinst du, MODULEENTRY32::modBaseAddr hat nicht den gewünschten Wert?

    MSDN schrieb:

    modBaseAddr

    The base address of the module in the context of the owning process.



  • Hi

    das funtioniert bei xp, aber nicht bei vista-win7.

    Lowbyte



  • Und was steht ab Vista in MODULEENTRY32::modBaseAddr ?



  • durch ASLR sind die DLL-Adressen nur von Start zu Start verschieden - während der Laufzeit sind sie in allen Prozessen gleich.



  • Wie bekommt man denn nun die Adresse einer Funktion in einem anderen Prozess ab Vista? Dabei soll der eigene Prozess aber nicht zwingend das Modul geladen haben müssen. Das ist nämlich bei "Cypher"s Code der Fall, da sonst gleich bei der ersten Zeile ein Crash auftritt:

    PIMAGE_DOS_HEADER pDosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(module);

    (Weil die Adresse "module" im eigenen Prozess nicht existiert, weil das Modul hier nicht geladen ist, sondern nur im Fremdprozess)



  • LoadLibrary()+GetProcAddress()



  • Was? Nein, du verstehst wohl nicht.

    Nochmal: Wie bekommt man denn nun die Adresse einer Funktion in einem anderen Prozess ab Vista?

    (Damit diese für CreateRemoteThread verwendet werden kann)



  • !!!: LoadLibrary()+GetProcAddress()


Anmelden zum Antworten