Bitwise OR



  • Ich steh auf dem Schlauch...

    Ich lese in einem Consolenprogramm den Sectiontable von PE-files (executables) aus. In jedem dieser Sectiontables befindet sich ein Feld names 'Characteristics'.
    Dieses Feld möchte ich auf Ausführungs-, Lese- und Schreibrechte überprüfen. Ist das jeweilige Recht vorhanden sollen dazu die Buchstaben...
    x für execute
    r für read
    w für write
    ...ausgegeben werden.

    Nun ist dieses Feld über ein bitweises ODER (bitwise OR) abgespeichert. "|" entspricht bitwise OR in C++. z.B.:

    long characteristic = IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ; // Diese Sektion hätte Ausführungs- und Leserechte.
    

    kleiner Auszug aus (Es sind eigentlich viel mehr Werte):
    "Microsoft Portable Executable and Common Object File Format Specification"

    IMAGE_SCN_MEM_EXECUTE 0x20000000 The section can be executed as code.
    IMAGE_SCN_MEM_READ 0x40000000 The section can be read.
    IMAGE_SCN_MEM_WRITE 0x80000000 The section can be written to.

    Was ich bräuchte ist ca. so eine Funktion. Was müsste in die 'If's rein?:

    void GetSectionCharacteristic(long characteristic)
    {
    	std::string tmp;
    
    	if ( /*characteristic has execute rights*/ )
    		tmp.append("x");
    	std::cout << std::hex << "0x" << characteristic << std::endl;
    
    	if ( /*characteristic has read rights*/ )
    		tmp.append("r");
    	std::cout << std::hex << "0x" << characteristic << std::endl;
    
    	if ( /*characteristic has write rights*/ )
    		tmp.append("w");
    	std::cout << std::hex << "0x" << characteristic << std::endl;
    
    	std::cout << tmp.c_str() << std::endl;
    }
    

    Mir ist aufgefallen das Microsoft in PE-files sehr oft 'bitwiso OR' verwendet, scheint ja auch eine sehr effektive Methode zu sein Möglichst viele Informationen auf kleinem Raum zu speichern. Nur wie man das wieder auswertet ist mir unklar.



  • if(characteristic & IMAGE_SCN_MEM_EXECUTE == IMAGE_SCN_MEM_EXECUTE) {
    	cout<<"ausführbar"<<endl;
    }
    

    Die beiden anderen Rechte können analog dazu geprüft werden.


  • Administrator

    Spekulatius schrieb:

    Nun ist dieses Feld über ein bitweises ODER (bitwise OR) abgespeichert. "|" entspricht bitwise OR in C++. z.B.:

    Danke, das weiss ich auch ... *SCNR*

    Ehm zu deinem Problem. Einfach das bitwise AND anwenden:

    if(characteristic & IMAGE_SCN_MEM_EXECUTE) // Ergibt 0 oder eine Zahl
    {
      // Dann ist IMAGE_SCN_MEM_EXECUTE gesetzt.
    }
    

    Sowas nennt man übrigens Flags, falls du mal danach suchen möchtest 😉

    Grüssli



  • Etwas flexibler geht es z.B. auch so:

    std::string GetSectionCharacteristic(long characteristic)
    {
        //alle moeglichen flags
        const long characteristics_map[] =
        {
            IMAGE_SCN_MEM_EXECUTE,
            IMAGE_SCN_MEM_READ,
            IMAGE_SCN_MEM_WRITE
            //mehr faelle
        };
    
        std::string tmp;
        //alle flags durchgehen...
        for(int n = 0; n != (sizeof(characteristics_map) / sizeof(*characteristics_map)); ++n)
        {
            long masked = characteristic & characteristics_map[n];
            switch(masked)
            {
            case IMAGE_SCN_MEM_EXECUTE:
                tmp.append("x");
                break;
            case IMAGE_SCN_MEM_READ:
                tmp.append("r");
                break;
            case IMAGE_SCN_MEM_WRITE:
                tmp.append("w");
                break;
            //case...
            default:
                //irgenwas passt nicht
                break;
            }
        }
        return tmp;
    }
    

    Oder noch einfacher mit std::map .



  • moagnus schrieb:

    if(characteristic & IMAGE_SCN_MEM_EXECUTE == IMAGE_SCN_MEM_EXECUTE) {
    	cout<<"ausführbar"<<endl;
    }
    

    Die beiden anderen Rechte können analog dazu geprüft werden.

    Das dürfte nicht funktionieren, denn die Precedence von == liegt höher als von & Also:

    if(characteristic & (IMAGE_SCN_MEM_EXECUTE == IMAGE_SCN_MEM_EXECUTE)) {
    	cout<<"ausführbar"<<endl;
    }
    

    Dann liefert Dein Ausdruck nur true, wenn in characteristic das niedrigste Bit gesetzt hat!

    Korrekt wäre

    if((characteristic & IMAGE_SCN_MEM_EXECUTE) == IMAGE_SCN_MEM_EXECUTE) {
    	cout<<"ausführbar"<<endl;
    }
    


  • Der STL-Container std::bitset kann auch zur konfortablen, speicherschonenden Verwaltung von Bitmasken verwendet werden.



  • @Martin Richter: Sorry, die Operatorenpräzedenz hab ich nicht bedacht. Bin nur selten im bitweisen Bereich unterwegs... 😉


Anmelden zum Antworten