UpdateResource ()



  • guten tag allerseits .
    folgendes :
    ich moechte die resourcen einer exe datei durch andere austauschen.
    nachdem ich mich in der msdn naeher informiert habe funktioniert das unter windows 2000 wunderbar.
    sinn und zweck war allerdings die ntoskrnl.exe von win2k anpassen zu koennen (bootlogo aendern).
    merkwuerdiger weise bekomm ich nach aendern der ntoskrnl.exe mit meinem prg ein fehler beim booten, der darauf hinweist, das diese beschaedigt waere.
    ich habe zum test eine ntoskrnl.exe mit der software reshacker modifiziert, welche einwandfrei arbeitet.
    die mit meinemn prg erstellte ntoskrnl.exe weisst nun trotz gleicher bmp einige unterschiede in einem hex editor auf.
    die groesse der datei ist absolut gleich, auch die groesse der bmp datei (laut reshacker) sind gleich.
    mit normalen win32 anwendungen funktioniert es auch einwand frei, nur halt nicht mit der datei ntoskrnl.exe.

    hier ein ausschnitt aus dem code :

    CFile booti;
    	CString tmp,ntdatei=m_windir+m_bootein.Mid(8);
    	HANDLE hfile,hResource;
    	DWORD dwFileSize,dwBytesRead;
    	BYTE *lpBuffer;
    
    	hfile = CreateFile(m_bitmap, GENERIC_READ, 
                       0,
                       NULL,
                       OPEN_EXISTING,
                       FILE_ATTRIBUTE_NORMAL,
                       NULL);
    	if (hfile == INVALID_HANDLE_VALUE )
    	{
    		MessageBox(_T("load error"));
    		return;
    	}
    	dwFileSize = GetFileSize(hfile, NULL);
    
        lpBuffer = new BYTE[dwFileSize];
    
        if (ReadFile(hfile, lpBuffer, dwFileSize, &dwBytesRead, NULL) == FALSE)
        {
    		delete [] lpBuffer;
    		CloseHandle(hfile);
    		MessageBox(_T("lese fehler"));
    		return;
        }
    	CloseHandle(hfile);
    
    	if (CopyFile(m_windir+"ntoskrnl.exe",ntdatei,true)==NULL)
    	{
    		delete [] lpBuffer;
    		MessageBox(_T("copy fehler"));
    		return;
    	}
    
    	hResource = BeginUpdateResource(ntdatei, FALSE);
    	if (NULL != hResource)
    	{
    		if (UpdateResource(hResource, 
    			RT_BITMAP,
    			MAKEINTRESOURCE(1),
    			MAKELANGID(LANG_GERMAN, SUBLANG_DEFAULT),
    			(BYTE*)lpBuffer+14,
    			dwFileSize-14) == FALSE)
    		{
    			MessageBox(_T("update fehler"));
    		}
    		if (EndUpdateResource(hResource, FALSE)==FALSE) MessageBox(_T("updateclose fehler"));
    	}
    
    	delete [] lpBuffer;
    

    der code ist noch etwas "durcheinander" da ich ihn zigmal geaendert habe um tests durchfuehren zu koennen also nicht "meckern":)

    mfg donny 😉



  • nach laengeren tests scheint es wohl eindeutig an der api zu liegen.
    scheint so als muesst ich eine eigene routine dazu schreiben ^^
    sobald ich die zeit dazu habe werd ich mich daran ( nicht dranne ^^) setzen und den code dazu hier posten 😉

    mfg donny



  • du kannst ja mal XN Resource Editor ausprobieren. Falls der das auch schafft kannst du im Source nachgucken ob es UpdateResource oder was eigenes benutzt.



  • hab ich , hab ich 🙂
    beide einstellungen in xn resource editor funktionieren nicht (windows api oder eigener).
    aber auf der hp vom reshacker steht, das der reshacker auch unter win95 laeuft, wobei ja updateresource erst ab nt5 vorhanden ist.
    damit ergibt sich logischerweise das der reshacker eine sehr ausgefeilte und vor allen dingen eigene routine dafuer nutzt.
    wie gesagt ich arbeite mich gerade durch die msdn von wegen mzexe,neexe und den eintraegen von wegen .rscs.
    wird wohl noch etwas daueren bis ich das alles zusammen hab. ( dummer hauptschueler ^^)

    mfg donny 😉



  • so wie es scheint , habe ich den fehler gefunden.
    UpdateResource passt die checksum im nt optional header nicht an ...
    was soll man dazu noch sagen 😕
    die loesung heisst CheckSumMappedFile .
    damit laesst sich die checksum berechnen ,welche dann nur noch an entprechender stelle gschrieben werden muss.
    dazu brauch man nur die lib ImageHlp.lib und die header datei Imagehlp.h einzubinden.
    bei interesse poste ich gerne noch den code bei, sobald ich fertig bin .

    mfg donny 😉



  • donbubu schrieb:

    bei interesse poste ich gerne noch den code bei, sobald ich fertig bin.

    Ja, doch, bei sowas speziellem findet man sonst immer nur sehr spärlich was 🙂



  • Hallo,

    für einen Hauptschüler bist du aber ganz schön gut. Weiter so. 👍



  • vielen dank 🙂

    freut mich wenn ich doch mal etwas brauchbares produziere ^^

    HANDLE hfile=INVALID_HANDLE_VALUE,hResource=NULL,hfilemap=NULL;;
    	DWORD dwFileSize=0,dwBytesRead=0,filechsum=0,clacsum=0;;
    	BYTE *lpBuffer;
    	IMAGE_NT_HEADERS *tmpntheader=NULL;
    	PVOID startaddmap=NULL;
    
    	hfile = CreateFile(L"c:\\boot.bmp", //bmp im format : 640 x 480 4bpp (16 farben)
    				   GENERIC_READ,
                       0,
                       NULL,
                       OPEN_EXISTING,
                       FILE_ATTRIBUTE_NORMAL,
                       NULL);
    	if (hfile == INVALID_HANDLE_VALUE )
    	{
    		MessageBox(_T("load error"));
    		return;
    	}
    	dwFileSize = GetFileSize(hfile, NULL);
    
        lpBuffer = new BYTE[dwFileSize];
    
        if (ReadFile(hfile, lpBuffer, dwFileSize, &dwBytesRead, NULL) == FALSE)
        {
    		delete [] lpBuffer;
    		CloseHandle(hfile);
    		MessageBox(_T("lese fehler"));
    		return;
        }
    	CloseHandle(hfile);
    
    	hResource = BeginUpdateResource(L"c:\\ntoskrnl.exe", FALSE);
    	if (NULL != hResource)
    	{
    		if (UpdateResource(hResource, 
    			RT_BITMAP,
    			MAKEINTRESOURCE(1),
    			MAKELANGID(LANG_GERMAN, SUBLANG_DEFAULT),
    			(BYTE*)lpBuffer+14,			//datei header einer bitmap hat 14 bytes
    			dwFileSize-14) == FALSE)    // (datei header eines icon hat 22 bytes)
    		{
    			MessageBox(_T("update fehler"));
    		}
    		else if (EndUpdateResource(hResource, FALSE)==FALSE) MessageBox(_T("updateclose fehler"));
    	}
    
    	delete [] lpBuffer;
    
    	// die checksum anpassen ...
    	hfile=INVALID_HANDLE_VALUE;
    	hfile = CreateFile(L"c:\\ntoskrnl.exe", GENERIC_READ|GENERIC_WRITE, 
                       0,
                       NULL,
                       OPEN_EXISTING,
                       FILE_ATTRIBUTE_NORMAL,
                       NULL);
    	if (hfile == INVALID_HANDLE_VALUE )
    	{
    		return ;
    	}
    	hfilemap=CreateFileMapping(hfile,NULL,PAGE_READONLY, 0, 0, NULL);
    	if(hfilemap==NULL)
    	{
    		CloseHandle(hfile);
    		return ;
    	}
    	startaddmap=MapViewOfFile(hfilemap,FILE_MAP_READ,0,0,0);
    	if (startaddmap==NULL)
    	{
    		CloseHandle(hfilemap);
    		CloseHandle(hfile);
    		return ;
    	}
    	dwFileSize = GetFileSize(hfile, NULL);
    	tmpntheader=CheckSumMappedFile(startaddmap,dwFileSize,&filechsum,&clacsum);
        if(tmpntheader==NULL) // bei fehler , pointer zu ntheaders des files = NULL
    	{
    		CloseHandle(hfilemap);
    		CloseHandle(hfile);
    		UnmapViewOfFile(startaddmap);
    		return;
    	}
    	UnmapViewOfFile(startaddmap);
    	CloseHandle(hfilemap);
    	//die start position des ntheaders in der datei lesen (datei position 60)
    	if (SetFilePointer(hfile,60,NULL,FILE_BEGIN)==NULL) MessageBox(L"setfilepointer 1 error checksum");
    	if (!ReadFile(hfile,&filechsum,4,&dwSize,NULL)) MessageBox(L"read ntheader error checksum");
    	filechsum+=88;// die position der ntheaderchecksum (88 bytes vom nt header start)
    	if (SetFilePointer(hfile,
    		filechsum,		//an dieser adresse steht die checksum im optional header 
    		NULL,
    		FILE_BEGIN)==NULL) MessageBox(L"setfilepointer2 error checksum");
    	if(WriteFile(hfile,&clacsum,4,&dwFileSize,NULL)==000) MessageBox(L"write error checksum");
    	CloseHandle(hfile);
    

    EDIT : nach einigen tests auf verschiedenen pc habe ich einige unterschiede in der groesse gefunden, weswegen ich dann doch lieber die position des nt headers ermittle

    in diesem beispiel wird die ntoskrnl.exe, die von system32 in das root verzeichniss kopiert wurde mit einem neuem bootlogo ausgestattet.
    wichtig dabei ist das format der bitmap : 640 x 480 4 bpp (16 farben und nicht wie faelschlicherweise auf manchen inet seiten angegeben 16 bpp !!!).

    da eine resource wenig mit dem fileheader der bitmap anfangen kann, muss dieser entfernt werden (bei einem bitmap sind das 14 bytes, bei einem icon 22).

    nach dem aufruf von BeginUpdateResource und UpdateResource wird an der eigentlichen datei noch nichts veraendert, erst durch den befehl EndUpdateResource werden die neuen daten in dem file gespeichert.
    in den meisten faellen wuerde das reichen, doch fuer die ntoskrnl.exe braucht es noch eine gueltige checksum.

    nach dem oeffnen der ntoskrnl.exe und dem mappen im speicher wird mit CheckSumMappedFile die neue checksum ermittelt.
    CheckSumMappedFile gibt einen pointer auf die struktur IMAGE_NT_HEADERS zurueck, welcher aber den original header ohne geaenderter checksum enthaelt.
    bei einem fehler wird NULL zurueck gegeben.
    die neue checksum steht als DWORD im letzten parameter, die originale im vorletzten.
    die position der nt-optional-header-checksum in einem file :
    im dos-header steht an position 60 die adresse (dword) vom nt header, in diesem an position 88 die checksumme.

    microsoft gibt wenig bis keine infos zur checksum raus.
    Jeffrey Walton hat sich damit etwas naeher beschaeftigt und auf der codeproject site mehr informationen dazu gegeben http://www.codeproject.com/KB/cpp/PEChecksum.aspx

    das berechnen der checksum ueberlasse ich hier der Imagehlp bibliothek.
    dazu muss die headerdatei

    #include "Imagehlp.h"
    

    eingebunden,
    und die Imagehlp.lib unter projekteinstellungen > linker > bibliothek-module eingesetzt werden.

    diese sind bestandteil des sdk (bei mir die version 2003 sp1).

    infos zu den headers :
    http://msdn2.microsoft.com/en-us/magazine/cc301808.aspx
    http://support.microsoft.com/kb/90493
    http://msdn2.microsoft.com/en-us/library/ms680195.aspx

    der letzte link ist besonders interessant.

    mfg donny 😉



  • ich habe das PRG fertig.
    wenn noch jemand win2k hat und gerne sein bootlogo einfach aendern und verwalten will einfach eine PM an mich.
    ist nur 84 kb gross 😉

    mfg donny 😉


Anmelden zum Antworten