Source file: /~heha/Mikrocontroller/readrsrc.zip/readrsrc.cpp

/* Zu Fuß Ressourcen lesen - für den Treiber */
#include <windows.h>
#include <stdio.h>
#define elemof(x) (sizeof(x)/sizeof(*(x)))

// Bonus, nicht für Treiber
static void LocateResource(PBYTE a) {
 PIMAGE_NT_HEADERS h;
 PIMAGE_RESOURCE_DIRECTORY r;
 PIMAGE_RESOURCE_DIRECTORY_ENTRY e;
 PIMAGE_SECTION_HEADER ish;
 PBYTE r0;
 DWORD i,diff;
 if (*(PWORD)a!=IMAGE_DOS_SIGNATURE) return;
 h=(PIMAGE_NT_HEADERS)(a+*(PDWORD)(a+0x3C));
 if (h->Signature!=IMAGE_NT_SIGNATURE) return;
 ish=(PIMAGE_SECTION_HEADER)((PBYTE)&(h->OptionalHeader)+h->FileHeader.SizeOfOptionalHeader);
 for (i=h->FileHeader.NumberOfSections; i; i--) {
  if (lstrcmpiA((LPCSTR)ish->Name,".rsrc")==0) goto found;
  ish++;
 }
 return;
found:
 r0=a+ish->PointerToRawData;
 diff=ish->VirtualAddress-ish->PointerToRawData;
//   +h->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE/*2 - Offset 112*/].VirtualAddress
//   -h->OptionalHeader.SizeOfHeaders;
 r=(PIMAGE_RESOURCE_DIRECTORY)r0;
 e=(PIMAGE_RESOURCE_DIRECTORY_ENTRY)(r+1);
 for (i=r->NumberOfIdEntries; i; i--) {
  if (e->Id==(WORD)RT_RCDATA) {
   r=(PIMAGE_RESOURCE_DIRECTORY)(r0+e->OffsetToDirectory);
   e=(PIMAGE_RESOURCE_DIRECTORY_ENTRY)(r+1);
   for (i=r->NumberOfIdEntries; i; i--) {
    if (e->Id==100) {
     r=(PIMAGE_RESOURCE_DIRECTORY)(r0+e->OffsetToDirectory);
     e=(PIMAGE_RESOURCE_DIRECTORY_ENTRY)(r+1);
     for (i=r->NumberOfIdEntries; i; i--) {
      if (true) {	// egal welche Sprache
       PIMAGE_RESOURCE_DATA_ENTRY e2=(PIMAGE_RESOURCE_DATA_ENTRY)(r0+e->OffsetToData);
       r0=a+e2->OffsetToData-diff;
       printf("%x %x\n",r0-a, diff);
       printf("%d %d\n",((PWORD)r0)[0],((PWORD)r0)[1]);
       break;
      }
      e++;
     }
     break;
    }
    e++;
   }
   break;
  }
  e++;
 }
}

/************************************
 * Ab hier der Kode für den Treiber *
 ************************************/
static void _stdcall ReadAt(HFILE h, DWORD pos, PVOID w, DWORD l) {
 _llseek(h,pos,0); _lread(h,w,l);	// ZwReadFile()
}

PBYTE _stdcall LoadRCData(HFILE h, WORD id, DWORD*len) {
// Datei-I/O im Kernel-Mode - NUR RCDATA - NUR numerische IDs
// Der Aufrufer muss den gelieferten Speicher-Zeiger freigeben.
 WORD w,w1,w2;
 DWORD l,p,p0,i;
 PBYTE ret;
 ReadAt(h,0,&w,2); if (w!=/*IMAGE_DOS_SIGNATURE*/'ZM') return NULL;
 ReadAt(h,0x3C,&p,4);
 ReadAt(h,p,&l,4); if (l!=/*IMAGE_NT_SIGNATURE*/'EP') return NULL;
 ReadAt(h,p+6,&w1,2);		// NumberOfSections
 ReadAt(h,p+0x14,&w2,2);	// SizeOfOptionalHeader
 p+=0x18+w2;
 for (i=w1; i; i--) {
  char buf[6];
  ReadAt(h,p,buf,6);
//  if (lstrcmpiA(buf,".rsrc")==0) goto f0;	// RtlCompare...
  if (*(PDWORD)buf=='rsr.' && ((PWORD)buf)[2]=='c') goto f0;	// schneller
//  if (*(__int64*)buf&0xFFFFFFFFFFFF=='crsr.' goto f0	// für x64-Architektur
  p+=0x28;			// sizeof(IMAGE_SECTION_HEADER)
 }
 return NULL;
f0:
 ReadAt(h,p+0x0C,&l,4);		// VirtualAddress
 ReadAt(h,p+0x14,&p,4);		// PointerToRawData
 l-=p0=p;			// Differenz (wichtig!!)
 ReadAt(h,p+0x0C,&i,4);		// NumberOfEntries
 w1=LOWORD(i); w2=HIWORD(i);
 p+=0x10+8*w1;			// NumberOfNamedEntries übergehen
 for (i=w2; i; i--) {		// Suche RCDATA-Ressourcen
  ReadAt(h,p,&w,2);
  if (w==(WORD)RT_RCDATA/*10*/) goto f1;
  p+=8;				// sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY)
 }
 return NULL;
f1:
 ReadAt(h,p+4,&i,4);
 p=p0+(i&0x7FFFFFFF);
 ReadAt(h,p+0x0C,&i,4);		// nochmal dasselbe
 w1=LOWORD(i); w2=HIWORD(i);
 p+=0x10+8*w1;
 for (i=w2; i; i--) {		// Suche Ressource mit passender ID
  ReadAt(h,p,&w,2);
  if (w==id) goto f2;
  p+=8;
 }
 return NULL;
f2:
 ReadAt(h,p+4,&i,4);
 p=p0+(i&0x7FFFFFFF);
 ReadAt(h,p+0x14,&i,4);		// erster (einziger) Eintrag
 p=p0+i;
 ReadAt(h,p,&p0,4);
 p0-=l;
 ReadAt(h,p+4,&l,4);
 ret = new BYTE[l];		// ExAllocatePoolWithTag()
 if (!ret) return NULL;
 ReadAt(h,p0,ret,l);
 if (len) *len=l;
 return ret;
}

/************************************
 * Ende Treiberkode. User-Mode-Demo *
 ************************************/

// Einfaches Hex/ASCII-Dump
static void hdump(PBYTE a, DWORD l) {
 for (DWORD j=0; j<l; j+=16) {
  printf("%04X",j);
  DWORD i;
  for (i=0; i<16; i++) {
   if (j+i>=l) break;
   printf(" %02X",a[j+i]);
  }
  for (; i<17; i++) printf("   ");
  for (i=0; i<16; i++) {
   if (j+i>=l) break;
   printf("%c",isprint(a[j+i])||(char)a[j+i]<0?a[j+i]:'.');
  }
  printf("\n");
 }
}

void mainCRTStartup(void) {
 HANDLE hFile,hMapped;
 HFILE f;
 PBYTE lpBaseAddress;
 TCHAR ExeFileName[MAX_PATH];

 GetModuleFileName(0,ExeFileName,elemof(ExeFileName));

// Erste Methode: Datei laden (perfekt für Treiber)
 f=_lopen(ExeFileName,0);	// ZwCreateFile()
 if (f) {
  PWORD x;
  DWORD len;
  x=(PWORD)LoadRCData(f,100,&len);
  if (x) {
   hdump((PBYTE)x,len);
   delete[] x;			// ExFreePool()
  }
  _lclose(f);			// ZwClose()
 }

// Zweite Methode: Datei einblenden (weiß nicht wie das für Treiber geht)
 hFile=CreateFile(ExeFileName, GENERIC_READ,0,
   NULL,OPEN_EXISTING,0,NULL);
 if (hFile!=INVALID_HANDLE_VALUE) {
  hMapped=CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);
  if (hMapped) {
   lpBaseAddress=(PBYTE)MapViewOfFile(hMapped,FILE_MAP_READ,0,0,0);
   if (lpBaseAddress) {
    LocateResource(lpBaseAddress);
    UnmapViewOfFile(lpBaseAddress);
   }
   CloseHandle(hMapped);
  }
  CloseHandle(hFile);
 }
}
Detected encoding: ANSI (CP1252)4
Wrong umlauts? - Assume file is ANSI (CP1252) encoded