Pufferüberlaufproblemen



  • Es geht mir um fTextout, nicht um Textout, diese muss anders aussehen, denn sonst würde

    g_pLogfile->fTextout ("%s\n", (*iL));
    

    nicht kompilieren (*iL ist vom Typ string, nicht char const *).

    FindFileswithoutSubFolder sieht größtenteils in Ordnung aus, obwohl ich mir gerade nicht sicher bin, wie FindClose(INVALID_HANDLE_VALUE) reagiert. Du solltest den FindClose-Aufruf fünf Zeilen nach oben verlegen.



  • Ok werde FindClose nach oben setzten.

    Hier fTextout:

    // fTextout
    //
    // Aufgabe: formatierten Text ins Logfile schreiben (schwarz)
    //
    void CLogfile::fTextout (const char *Text, ...)
    {
    	TCHAR buffer[MAX_BUFFER];  // char-Buffer
    	va_list pArgList;          // Liste der übergebenen Argumente
    
    	// String aus den Argumenten erstellen
    	va_start (pArgList, Text);
    	vsprintf (buffer, Text, pArgList);
    	va_end (pArgList);
    
    	// Erzeugten String schreiben
    	Textout (buffer);
    
    } // fTextout (schwarz)
    
    // fTextout
    //
    // Aufgabe: formatierten Text ins Logfile schreiben (farbig)
    //
    void CLogfile::fTextout (int Color, const char *Text, ...)
    {
    	TCHAR buffer[MAX_BUFFER];  // char-Buffer
    	va_list pArgList;          // Liste der übergebenen Argumente
    
    	// String aus den Argumenten erstellen
    	va_start (pArgList, Text);
    	vsprintf (buffer, Text, pArgList);
    	va_end (pArgList);
    
    	// Erzeugten String schreiben
    	Textout (Color, buffer);
    
    } // fTextout (farbig)
    
    // fTextout
    //
    // Aufgabe: formatierten Text ins Logfile schreiben (farbig, Liste)
    //
    void CLogfile::fTextout (int Color, bool List,const char *Text, ...)
    {
    	TCHAR buffer[MAX_BUFFER];  // char-Buffer
    	va_list pArgList;          // Liste der übergebenen Argumente
    
    	// String aus den Argumenten erstellen
    	va_start (pArgList, Text);
    	vsprintf (buffer, Text, pArgList);
    	va_end (pArgList);
    
    	// Erzeugten String schreiben
    	Textout (Color, List, buffer);
    
    } // fTextout (farbig, Liste)
    


  • Ja, da sieht man's. fTextOut ist dein Problem (bzw. der Aufruf). So müsste es gehen:

    g_pLogfile->fTextout ("%s\n", iL->c_str());
    

    ...wobei das ganze Konzept nicht besonders hübsch ist. Spricht etwas dagegen, ganz normal auf std::ostream aufzusetzen?



  • ..wobei das ganze Konzept nicht besonders hübsch ist.

    Was meinst du mit Konzept?

    Spricht etwas dagegen, ganz normal auf std::ostream aufzusetzen?

    Nein spricht nichts dagegen. Würde nur gerne die Vorteile von ostream wissen.



  • Ich meine das Konzept, Variablen per Ellipse an C-I/O-Funktionen durchzureichen. Komplexe Datentypen kriegst du so überhaupt nicht behandelt, und Typsicherheit ist nicht gegeben - beides hast du ja gerade am eigenen Leib erfahren.

    Das wären auch die Vorteile von C++-Streams.



  • Vielen Danke für die Info. Werde das dann mal ausprobieren und mich dann wieder melden.



  • So habe jetzt umgeschrieben und fTextout raus genommen. Benutze nur noch Textout und die sieht jetzt wie folgt aus:

    aus Sicherheitsgründen entfernt
    

    Bekomme ich immer noch die Fehlermeldung mit Pufferüberlauf



  • Mit

    Textout ("PCFix " + Version + " - http://www.christian.duefel.de\nScan ");
    

    kann das aber nicht die Textout-Funktion sein, die du hier beschrieben hast - der Ausdruck ist vom Typ std::string, nicht char const *.



  • Doch ist sie und funktioniert auch. Da char in string einfach umgewandelt wird.



  • Ah, ich hab die Definition weiter unten übersehen; dachte, du nimmst noch die alte.

    Folgendes:

    ostream os(&m_fb);
    

    wird vermutlich danebengehen; std::ostreams Konstruktor nimmt als Parameter nur einen Streambuffer. Aber da m_fb schon ein std::ostream ist, kannst du einfach

    m_fb << Text << "\n";
    

    schreiben. Kompiliert der Konstruktoraufruf oben überhaupt?



  • m_fb ist ein filebuf. Deshalb kann folgendes:

    m_fb << Text << "\n";
    

    nicht gehen



  • va_list sind nicht typsicher und sind eigentlich C Code.

    Wie wäre es mit etwas C++0x:

    namespace variadic {
    	void print() {
    		std::cout << std::endl;	
    	}
    	template<typename Arg, typename ... Remains>
    	void print(const Arg& arg, const Remains&... remains) {
    		std::cout << arg;
    		print(remains...);
    	}	
    }
    

    Sollte so passen. Erfordert aber ein --std=c++0x beim Kompilieren.

    Und so tust du's anwenden:

    variadic::print("Test ", 1, 2, 3, " okay es funktioniert!");
    


  • Ja das ist zum anzeigen in der Konsole sehr schön, aber ich möchte den Kram in eine Datei schreiben.



  • ok..



  • Das war jetzt nicht böse gemeint.
    Habe die Funktion mit den Argument entfernt. Habe jetzt nur noch eine ganz einfach Funktion die einen String über ostream in eine Datei schreibt. Nur kommt es irgendwo, zu einem Pufferüberlauf, den ich mir nicht erklären kann.



  • Keiner mehr eine Idee?



  • Und der Überlauf kommt beim Schreiben in die Datei ?



  • Der Pufferüberlauf kommt am Ende des Programms, wenn alles erledigt ist. Erst kommt 10sec Sleep und wenn ich den 10sec Sleep das Programm per Alt + F4 oder einfach mit X beende kommt kein Pufferüberlauf, aber wenn es sich selbst beendet entsteht ein Pufferüberlauf.



  • Update: Problem hat sich verschoben
    ausschnitt aus main.cpp

    // Überschrift erzeugen
    	g_pLogfile->WriteTopic ("Test");
    
    	// Allocate array for getting ImageBase addresses of
        // all drivers present in system.
        DWORD dwBufferLen = GetImageBaseAddrArrayLen();
        LPVOID* pImageBaseAddrArray = (LPVOID*)new BYTE[ dwBufferLen ];
    
        DWORD dwBytesReturned = 0;
        // Get the ImageBaseAddresses of all drivers.
        EnumDeviceDrivers( pImageBaseAddrArray,  // array of load addresses
                           dwBufferLen,  // size of array as 0.
                           &dwBytesReturned );
    
        // Get the total number of drivers. calculate it by
        // total size in bytes/sizeof(void*)
        DWORD nDrivers = dwBufferLen / sizeof(LPVOID);
    
    	PVOID OldValue = NULL;
    
    	for( DWORD Index = 0; Index < nDrivers; ++Index )
        {
            // Get Device Driver informations.
            string sDriverBaseName;
            string sDriverFileName;
            GetDriverInfo( pImageBaseAddrArray[ Index], sDriverBaseName, sDriverFileName );
    
    		// \??\ /
    		int iFindIdxMD5Question = sDriverFileName.find( "\\??\\" );
    		int iExistQuestion = 0;
    		if ( iFindIdxMD5Question != -1 )
    		{
    			sDriverFileName.erase( 0, 4 );
    			iExistQuestion = 1;
    		}
    		// \Windows\System32
    		int iFindIdxMD5Win = sDriverFileName.find( "\\Windows\\System32" );
    		if ( iFindIdxMD5Win != -1 )
    			sDriverFileName.replace( iFindIdxMD5Win, 17, sSysDir );
    		// \WINDOWS\System32
    		int iFindIdxMD5Win2 = sDriverFileName.find( "\\WINDOWS\\System32" );
    		if ( iFindIdxMD5Win2 != -1 )
    			sDriverFileName.replace( iFindIdxMD5Win, 17, sSysDir );
    		// \SystemRoot\System32
    		int iFindIdxMD5SysRoot = sDriverFileName.find( "\\SystemRoot\\System32" );
    		if ( iFindIdxMD5SysRoot != -1 )
    			sDriverFileName.replace( iFindIdxMD5SysRoot, 20, sSysDir );
    		// \SystemRoot\system32
    		int iFindIdxMD5SysRoot2 = sDriverFileName.find( "\\SystemRoot\\system32" );
    		if ( iFindIdxMD5SysRoot2 != -1 )
    			sDriverFileName.replace( iFindIdxMD5SysRoot2, 20, sSysDir );
    		// \SystemRoot\SysWOW64
    		int iFindIdxMD5SysWOW64 = sDriverFileName.find( "\\SystemRoot" );
    		if ( iFindIdxMD5SysWOW64 != -1 )
    			sDriverFileName.replace( iFindIdxMD5SysWOW64, 11, sWinDir );
    		// C:\Windows\SysWOW64
    		int iFindIdxMD5C = sDriverFileName.find( "C:\\" );
    		if ( iFindIdxMD5C == -1 )
    			sDriverFileName.insert( 0, "C:\\" );
    
    		// calculating MD5
    		HANDLE hFile;
    		DWORD dwNumRead = -1;
    
    		if(IsWow64())
    			if (!WOW64DisableFsRedirection(&OldValue))
    				printf("WOW64DisableFsRedirection doesn´t work\n");
    
    		hFile = CreateFile(sDriverFileName.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
    
    		if (!WOW64RevertFsRedirection(OldValue))
    			printf("WOW64RevertFsRedirection doesn´t work\n");
    
    		if(hFile == INVALID_HANDLE_VALUE)
    		{
    			g_pLogfile->Textout ("ERROR: INVALID_HANDLE_VALUE" + sDriverFileName);
    		}
    		else
    		{
    			//GetFileSize to determine size of buffer for ReadFile
    			DWORD BufferSize = GetFileSize(hFile,NULL);
    
    			cout << "Buffer: " << BufferSize <<endl;
    
    			char* ReadBuffer = new char [BufferSize];// create a new char * to hold the buffer using the filesize
    
    			//Read from the file:
    			if(!ReadFile(hFile, ReadBuffer,BufferSize+1,&dwNumRead,NULL))
    			{
    				printf ("ReadFile Fail");
    				return 1;
    			}
    
    			//To close the file:
    			CloseHandle(hFile);
    
    			char hash[32];
    			MD5Hash((BYTE*)ReadBuffer,BufferSize,hash);
    			free(ReadBuffer);
    			if ( iExistQuestion == 1)
    			sDriverFileName.insert( 0, "\\??\\");
    
    			g_pLogfile->Textout (sDriverBaseName + " : " + sDriverFileName + " : " + hash);
    
    		}
        }
    

    MD5.cpp

    #include <iostream>
    #include <windows.h>
    #include <wincrypt.h>
    #include <fstream>
    
    using namespace std;
    
    #define MD5LEN  16
    
    void MD5Hash(BYTE hash[],int sz,char sec[])
    {
        HCRYPTPROV hProv = 0,hHash = 0;
        BYTE rgbHash[MD5LEN];
        DWORD cbHash = 0;
        char finalhash[32], dig[] = "0123456789abcdef";
        unsigned int l = 0;
    
        CryptAcquireContext(&hProv, NULL,NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
        CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
        CryptHashData(hHash, hash, sz, 0);
        cbHash = MD5LEN;
        CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash, 0);
    
        for(DWORD i = 0; i < cbHash; i++){
            finalhash[l] = dig[rgbHash[i] >> 4];
            l++;
            finalhash[l] = dig[rgbHash[i] & 0xf];
            l++;
        }
    
        for(l = 32; l < strlen(finalhash); l++) finalhash[l] = 0;
        strcpy_s(sec, 33, finalhash);
        CryptDestroyHash(hHash);
        CryptReleaseContext(hProv, 0);
    }
    

    DLL_LoadFunction.h

    #include <windows.h>
    
    typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
    typedef BOOL (WINAPI *LPFN_WOW64DISABLEWOW64FSREDIRECTION) (PVOID*);
    typedef BOOL (WINAPI *LPFN_WOW64REVERTWOW64FSREDIRECTION) (PVOID);
    
    BOOL IsWow64();
    BOOL WOW64DisableFsRedirection(PVOID *OldValue);
    BOOL WOW64RevertFsRedirection(PVOID OldValue);
    

    DLL_LoadFunction.cpp

    #include "DLL_LoadFunction.h"
    
    LPFN_ISWOW64PROCESS fnMyIsWow64Process;
    LPFN_WOW64DISABLEWOW64FSREDIRECTION fnMyWow64DisableWow64FsRedirection;
    LPFN_WOW64REVERTWOW64FSREDIRECTION fnMyWow64RevertWow64FsRedirection;
    
    BOOL IsWow64()
    {
        BOOL bIsWow64 = FALSE;
    
        //IsWow64Process is not available on all supported versions of Windows.
        //Use GetModuleHandle to get a handle to the DLL that contains the function
        //and GetProcAddress to get a pointer to the function if available.
    
        fnMyIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(
            GetModuleHandle(TEXT("kernel32")),"IsWow64Process");
    
        if(NULL != fnMyIsWow64Process)
        {
            if (!fnMyIsWow64Process(GetCurrentProcess(),&bIsWow64))
            {
                //handle error
            }
        }
        return bIsWow64;
    }
    
    BOOL WOW64DisableFsRedirection(PVOID *OldValue)
    {
    	fnMyWow64DisableWow64FsRedirection = (LPFN_WOW64DISABLEWOW64FSREDIRECTION) GetProcAddress(
    		GetModuleHandle(TEXT("kernel32")),"Wow64DisableWow64FsRedirection");
    
    	if(NULL != fnMyWow64DisableWow64FsRedirection)
    	{
    		if (!fnMyWow64DisableWow64FsRedirection(OldValue))
    		{
    			// handel error
    			return false;
    		}
    		else
    		{
    			return true;
    		}
    	}
    	return false;
    }
    
    BOOL WOW64RevertFsRedirection(PVOID OldValue)
    {
    	fnMyWow64RevertWow64FsRedirection = (LPFN_WOW64REVERTWOW64FSREDIRECTION) GetProcAddress(
    		GetModuleHandle(TEXT("kernel32")),"Wow64RevertWow64FsRedirection");
    
    	if(NULL != fnMyWow64RevertWow64FsRedirection)
    	{
    		if (!fnMyWow64RevertWow64FsRedirection(OldValue))
    		{
    			// handel error
    			return false;
    		}
    		else
    		{
    			return true;
    		}
    	}
    	return false;
    }
    

    Wenn wer Fehler oder Optimierungsbedarf sieht immer her damit 🙂



  • Der ganze Code ist mir zu gross, aber ein paar Dinge:

    LPVOID* pImageBaseAddrArray = (LPVOID*)new BYTE[ dwBufferLen ];
    

    Wo gibst du den Speicher frei? Vergiss nicht, ihn vor dem delete[] in BYTE* zu casten.

    int iFindIdxMD5Win = sDriverFileName.find( "\\Windows\\System32" );
    if ( iFindIdxMD5Win != -1 ) 
                sDriverFileName.replace( iFindIdxMD5Win, 17, sSysDir ); 
    // [Noch 5 Mal Codeduplikation]
    

    Auslagern in Funktionen wäre angebracht.

    char* ReadBuffer = new char [BufferSize];
    // [...]
    free(ReadBuffer);
    

    Das resultiert in undefiniertem Verhalten. Niemals new / delete mit malloc() / free() mischen**!** ⚠

    In C++ solltest du primär new / delete bzw. new[] / delete[] verwenden. Noch besser wäre natürlich automatische Speicherverwaltung mittels RAII. Gut möglich, dass hier auch dein Fehler liegt.

    #define MD5LEN  16
    

    Ziehe für Konstanten const typ einem #define vor.


Anmelden zum Antworten