User:Kmcguire: Difference between revisions

From OSDev.wiki
Jump to navigation Jump to search
Content deleted Content added
Kmcguire (talk | contribs)
Kmcguire (talk | contribs)
Line 272: Line 272:
buffer += y;
buffer += y;
}
}

/* give each stream a home at a consistent index */
for(x = 0; x < meta->strmcnt; ++x)
{
if(strcmp(meta->strms[x].name, "#~") == 0)
{
meta->strmbyid[WIN_CLR20_META_TABLES] = meta->strms[x];
}
if(strcmp(meta->strms[x].name, "#US") == 0)
{
meta->strmbyid[WIN_CLR20_META_USTRINGS] = meta->strms[x];
}
if(strcmp(meta->strms[x].name, "#Strings") == 0)
{
meta->strmbyid[WIN_CLR20_META_STRINGS] = meta->strms[x];
}
if(strcmp(meta->strms[x].name, "#Blob") == 0)
{
meta->strmbyid[WIN_CLR20_META_BLOB] = meta->strms[x];
}
if(strcmp(meta->strms[x].name, "#GUID") == 0)
{
meta->strmbyid[WIN_CLR20_META_GUID] = meta->strms[x];
}
}
return 1;
return 1;
}
}
</source>
</source>

==Interpreting Meta-Data Tables From #~ Stream Field Description==
==Interpreting Meta-Data Tables From #~ Stream Field Description==
This allows us to write a function to interpret the table data that follows the
This allows us to write a function to interpret the table data that follows the

Revision as of 20:33, 12 September 2009

Portable Executable 32 File Header And NT Header Structure

typedef struct {
	uint32_t	signature;
	uint16_t	cputype;
	uint16_t	objcnt;
	
	uint32_t	tdstamp;
	uint32_t	reserved1;
	
	uint32_t	reserved2;
	uint16_t	nthdrsize;
	uint16_t	flags;
	
	uint16_t	reserved3;
	uint16_t	lmajor;
	uint16_t	lminor;
	uint16_t	reserved4;
	
	uint32_t	reserved5;
	uint32_t	reserved6;
	
	uint32_t	entrypointrva;
	uint32_t	reserved7;
	
	uint32_t	reserved8;
	uint32_t	imagebase;
	
	uint32_t	objectalign;
	uint32_t	filealign;
	
	uint16_t	osmajor;
	uint16_t	osminor;
	uint16_t	usermajor;
	uint16_t	userminor;
	
	uint16_t	subsysmajor;
	uint16_t	subsysminor;
	uint32_t	reserved9;
	
	uint32_t	imagesize;
	uint32_t	hdrsize;
	
	uint32_t	filechecksum;
	uint16_t	subsystem;
	uint16_t	dllflags;
	
	uint32_t	stackreservesize;
	uint32_t	stackcommitsize;
	
	uint32_t	heapreservesize;
	uint32_t	heapcommitsize;
	
	uint32_t	reserved10;
	uint32_t	_rvasizes;
	
	struct {
		uint32_t	rva;
		uint32_t	size;
	} tables[];
	
} win32_pe32_fhdr;

#define WIN32_PE32_TABLE_EXPORT		0x00
#define WIN32_PE32_TABLE_IMPORT		0x01
#define WIN32_PE32_TABLE_RESOURCE	0x02
#define WIN32_PE32_TABLE_EXCEPTION	0x03
#define WIN32_PE32_TABLE_SECURITY	0x04
#define WIN32_PE32_TABLE_FIXUP		0x05
#define WIN32_PE32_TABLE_DEBUG		0x06
#define WIN32_PE32_TABLE_IMAGEDESC	0x07
#define WIN32_PE32_TABLE_MACHSPEC	0x08
#define WIN32_PE32_TABLE_THREADLOC	0x09
#define WIN32_PE32_TABLE_UNKNOWN1	0x0A
#define WIN32_PE32_TABLE_UNKNOWN2	0x0B
#define WIN32_PE32_TABLE_IMPORTADDR	0x0C
#define WIN32_PE32_TABLE_UNKNOWN3	0x0D
#define WIN32_PE32_TABLE_CLRRTHDR	0x0E

Common Language Runtime Header

typedef struct {
	uint32_t	rva;
	uint32_t	size;
} win32_clr20_datadir;

/* http://ntcore.com/files/dotnetformat.htm */
typedef struct {
	uint32_t			cb;
	uint16_t			rtmajor;
	uint16_t			rtminor;
	win32_clr20_datadir		meta;
	uint32_t			flags;
	uint32_t			entrypointrva;	/* entry point rva */
	win32_clr20_datadir		resources;	/* resources */
	win32_clr20_datadir		strongnamsig;	/* strong name signature */
	win32_clr20_datadir		codemantab;	/* code manager table */
	win32_clr20_datadir		vtabfixups;	/* vtable fixups */
	win32_clr20_datadir		exaddrtabjumps;	/* export address table jumps */
} win32_clr20_hdr;

Accessing PE32 Headers

	win32_pe32_fhdr		*fhdr;
	win32_pe32_ohdr		*ohdr;	
	uint32_t		pe_off;

	/* get pe32 header offset */
	pe_off = ((uint32_t*)(buffer + 0x3c))[0];
	printf("peoff:%x\n", pe_off);
	
	if(memcmp(buffer + pe_off, "PE\0\0", 4) == 0)
	{
		printf("Yes, this is a PE header.\n");
	}else{
                printf("No, this is not a PE header.\n");
        }
	
	fhdr = (win32_pe32_fhdr*)(buffer + pe_off);
	printf("imagebase: %x\n", fhdr->imagebase);

Accessing CLR Header

	printf("CLRRTHDR_RVA:%x\nCLRRTHDR_SIZE:%x\n", 
			fhdr->tables[WIN32_PE32_TABLE_CLRRTHDR].rva, 
			fhdr->tables[WIN32_PE32_TABLE_CLRRTHDR].size);
	clr_rva = fhdr->tables[WIN32_PE32_TABLE_CLRRTHDR].rva;
	clr_size = fhdr->tables[WIN32_PE32_TABLE_CLRRTHDR].size;
	
	/* 
		The array of objects follow the headers. But, my header does
		not include the size for the data dictionary array. So to
		include that we get the number of entries in the data dictionary
		and multiple this by eight since each one is eight bytes in PE32.
	*/
	ohdr = (win32_pe32_ohdr*)(buffer + pe_off + sizeof(win32_pe32_fhdr) + (fhdr->_rvasizes * 8));

	/* find the object that the CLRRTHDR is in and point header there */
	for(x = 0; x < fhdr->objcnt; ++x)
	{
		printf("object rva %x %s\n", ohdr[x].rva, &ohdr[x].name[0]);
		if(clr_rva >= ohdr[x].rva)
		{
			/* calculating relative to file offset not memory */
			clr_off = ohdr[x].poff + (clr_rva - ohdr[x].rva);
			printf("found object for CLRRTHDR, with rva %x\n", ohdr[x].rva);
			break;
		}
	}
	clr_hdr = (uint8_t*)(buffer + clr_off);

Accessing CLR Meta-Data Header

	printf("clr-metatable:%x [size:%x]\n", clr_hdr->meta.rva, clr_hdr->meta.size);
	meta_rva = clr_hdr->meta.rva;
	meta_size = clr_hdr->meta.size;
	
	/* find the object that the metadata is in and point header there */
	for(x = 0; x < fhdr->objcnt; ++x)
	{
		printf("object rva %x %s\n", ohdr[x].rva, &ohdr[x].name[0]);
		if(meta_rva >= ohdr[x].rva)
		{
			/* calculating relative to file offset not memory */
			meta_off = ohdr[x].poff + (meta_rva - ohdr[x].rva);
			printf("found object for CLR-METADATA, with rva %x\n", ohdr[x].rva);
			break;
		}
	}
	/* offset is relative to our buffer so that (buffer + meta_off) is start and meta_size is size */

CLR Meta-Data Container Structure

#define UINT16_AT(x) (*((uint16_t*)(x)))
#define UINT32_AT(x) (*((uint32_t*)(x)))

typedef struct {
	uint8_t					*name;		/* ASCII name */
	uint8_t					*data;		/* if non-zero is buffer */
} win_clr20_meta_stream;

typedef struct {
	uint16_t		strmcnt;		/* the number of array items below */
	win_clr20_meta_stream	*strms;			/* an array just like they are read in */
	win_clr20_meta_stream	strmbyid[5];		/* copy of strms, but indexed by WIN_CLR20_META_ */
	
	uint8_t			heapoffsetsizes;	/* heap offset sizes */
	uint32_t		valid[2];		/* qword(64bit) tells which tables are present */
	uint32_t		sorted[2];		/* qword(64bit) tells which tables are sorted */

	win_clr20_meta_table	tables[64];		/* all the known tables that are supported */
} win_clr20_meta;

#define WIN_CLR20_META_TABLES	0x00
#define WIN_CLR20_META_USTRINGS	0x01
#define WIN_CLR20_META_STRINGS	0x02
#define WIN_CLR20_META_BLOB		0x03
#define WIN_CLR20_META_GUID		0x04

Read CLR Meta-Data Streams Into Memory

/* read clr metadata */
int xxxx_clr_meta_read(uint8_t *buffer, uint32_t len, win_clr20_meta *meta)
{
	uint16_t	ver_major;
	uint16_t	ver_minor;
	uint16_t	ver_strlen;
	uint16_t	strmcnt;
	uint32_t	x;
	uint32_t	y;
	uint16_t	strm_off;
	uint16_t	strm_size;
	uint8_t		*_buffer;
	
	_buffer = buffer;

	if(UINT32_AT(buffer) != 0x424A5342)
	{
		printf("invalid clr metadata signature\n");
		return 0;
	}
	
	ver_major = UINT16_AT(buffer + 4 + 0);
	ver_minor = UINT16_AT(buffer + 4 + 2);
	
	printf("meta data ver:%x.%x\n", ver_major, ver_minor);
	
	ASSERT((ver_major == 1) && (ver_minor == 1));
		
	/* jump over signature, version, and reserved */
	buffer += 4 + 4 + 4;
	
	/* display and jump over version string */
	ver_strlen = UINT32_AT(buffer);
	ASSERT((ver_strlen & 0x3) == 0x0);			/* has to be multiple of 4 */
	printf("ver_strlen:%u\n", ver_strlen);
	printf("ver:%s\n", buffer + 4);
	buffer += 4 + ver_strlen;
		
	/* jump over flags; 16 bit field; supposed to always be zero;
	   but apparently it is not always zero oddly enough..
	ASSERT(UINT16_AT(buffer) != 0x0); */
	buffer += 2;
	
	strmcnt = UINT16_AT(buffer);
	buffer += 2;
	
	printf("MetaDataStreamCount:%u\n", strmcnt);
	
	/* read each metadata stream header */
	meta->strmcnt = strmcnt;
	meta->strms = (win_clr20_meta_stream*)malloc(sizeof(win_clr20_meta_stream) * strmcnt);
	for(x = 0; x < strmcnt; ++x)
	{
		/* read offset and size then copy into newly allocated buffer */
		printf("off:%x,size:%x,name:%s\n", UINT32_AT(buffer), UINT32_AT(buffer + 4), buffer + 8);
		meta->strms[x].data = (uint8_t*)malloc(UINT32_AT(buffer + 4));
		memcpy(meta->strms[x].data, _buffer + UINT32_AT(buffer), UINT32_AT(buffer + 4));
		buffer += 4 + 4;
		/* read stream name (stop at zero byte) */
		y = 0;
		while(buffer[y] != 0x00)
		{
			++y;
		}
		++y;
		y = ((y & 3) > 0 ? (y & (~3)) + 4 : y);
		meta->strms[x].name = (uint8_t*)malloc(y + 1);
		memcpy(meta->strms[x].name, buffer, y + 1);
		/* advance to next offset and size pair */
		buffer += y;
	}

	/* give each stream a home at a consistent index */
	for(x = 0; x < meta->strmcnt; ++x)
	{
		if(strcmp(meta->strms[x].name, "#~") == 0)
		{
			meta->strmbyid[WIN_CLR20_META_TABLES] = meta->strms[x];
		}
		if(strcmp(meta->strms[x].name, "#US") == 0)
		{
			meta->strmbyid[WIN_CLR20_META_USTRINGS] = meta->strms[x];
		}
		if(strcmp(meta->strms[x].name, "#Strings") == 0)
		{
			meta->strmbyid[WIN_CLR20_META_STRINGS] = meta->strms[x];
		}
		if(strcmp(meta->strms[x].name, "#Blob") == 0)
		{
			meta->strmbyid[WIN_CLR20_META_BLOB] = meta->strms[x];
		}
		if(strcmp(meta->strms[x].name, "#GUID") == 0)
		{
			meta->strmbyid[WIN_CLR20_META_GUID] = meta->strms[x];
		}
	}
	return 1;
}

Interpreting Meta-Data Tables From #~ Stream Field Description

This allows us to write a function to interpret the table data that follows the header in the #~ meta-data stream. The indexes can vary in size by what tables they reference so we have to create a letter for each specific index which refers to specific tables so that during run-time we can calculate the index size needed.

In my opinion this was done to conserve space, but I am not sure.

#define CLR20_META_TMODULE			0x0
#define CLR20_META_TTYPEREF			0x01
#define CLR20_META_TTYPEDEF			0x02
#define CLR20_META_TFIELD			0x03
#define CLR20_META_TMETHODDEF			0x04
#define CLR20_META_TPARAM			0x05
#define CLR20_META_TIFACEIMPL			0x06	/* interface implementation table */
#define CLR20_META_TMEMBERREF			0x07
#define CLR20_META_TCONSTANT			0x08
#define CLR20_META_TCUSTOMATTRI                 0x09
#define CLR20_META_TFIELDMARSHAL		0x0A
#define CLR20_META_TDECLSECURITY		0x0B
#define CLR20_META_TCLASSLAYOUT                 0x0C
#define CLR20_META_TFIELDLAYOUT                 0x0D
#define CLR20_META_TSTANDALONGSIG		0x0E
#define CLR20_META_TEVENTMAP			0x0F
#define CLR20_META_TEVENT			0x10
#define CLR20_META_TPROPERTY			0x11
#define CLR20_META_TMETHODSEMAN                 0x12
#define CLR20_META_TMETHODIMPL			0x13
#define CLR20_META_TMODULEREF			0x14
#define CLR20_META_TIMPLMAP			0x15
#define CLR20_META_TFIELDRVA			0x16
#define CLR20_META_TASSEMBLY			0x17
#define CLR20_META_TASSEMBLYPROC		0x18
#define CLR20_META_TASSEMBLYOS			0x19
#define CLR20_META_TASSEMBLYREF                 0x1A
#define CLR20_META_TASSEMBLYREFPROC		0x1B
#define CLR20_META_TASSEMBLYREFOS		0x1C
#define CLR20_META_TFILE			0x1D
#define CLR20_META_TEXPORTEDTYPE		0x1E
#define CLR20_META_TMANIFESTRES                 0x1F
#define CLR20_META_TNESTEDCLASS                 0x20
#define CLR20_META_TGENERICPARAM		0x21
#define CLR20_META_TGENERICPARAMCONST	        0x22
#define CLR20_META_TPROPERTYMAP			0x23
#define CLR20_META_TTYPESPEC			0x24
uint8_t *WIN_CLR20_META_TFIELDS[64] = 
{
	[CLR20_META_TMODULE] = 		"2SGGG",
	[CLR20_META_TTYPEREF] = 	"RSS",			/* META_TTYPEREF */
	[CLR20_META_TTYPEDEF] = 	"4SSTFM",		/* META_TTYPEDEF */
	[CLR20_META_TFIELD] = 		"2SB",			/* META_TFIELD */
	[CLR20_META_TMETHODDEF] = 	"422SBP",		/* META_TMETHODDEF */
	[CLR20_META_TPARAM] = 		"22S",			/* META_TPARAM */
	[CLR20_META_TIFACEIMPL] = 	"DT",			/* META_TIFACEIMPL */
	[CLR20_META_TMEMBERREF] = 	"ESB",			/* META_TMEMBERREF */
	[CLR20_META_TCONSTANT] = 	"11HB",			/* META_TCONSTANT */
	[CLR20_META_TCUSTOMATTRI] = 	"CIB",			/* META_TCUSTOMATTRI */
	[CLR20_META_TFIELDMARSHAL] = 	"OB",			/* META_TFIELDMARSHAL */
	[CLR20_META_TDECLSECURITY] = 	"2AB",			/* META_TDECLSECURITY */
	[CLR20_META_TCLASSLAYOUT] = 	"24D", 			/* META_TCLASSLAYOUT */
	[CLR20_META_TFIELDLAYOUT] = 	"4F",
	[CLR20_META_TSTANDALONGSIG] =	"B",
	[CLR20_META_TEVENTMAP] = 	"DV",
	[CLR20_META_TEVENT] = 		"2ST",
	[CLR20_META_TPROPERTYMAP] =	"DY",
	[CLR20_META_TPROPERTY] =	"2SB",
	[CLR20_META_TMETHODSEMAN] =	"2MS",
	[CLR20_META_TMETHODIMPL] = 	"DII",
	[CLR20_META_TMODULEREF] =	"S",
	[CLR20_META_TTYPESPEC] =	"B",
	[CLR20_META_TIMPLMAP] =		"2USN",
	[CLR20_META_TFIELDRVA] =	"4F",
	[CLR20_META_TASSEMBLY] = 	"422224BSS",
	[CLR20_META_TASSEMBLYPROC] =	"4",
	[CLR20_META_TASSEMBLYOS] = 	"444",
	[CLR20_META_TASSEMBLYREF] = 	"22224BSSB",
	[CLR20_META_TASSEMBLYREFPROC] = "4J",
	[CLR20_META_TASSEMBLYREFOS] = 	"444J",
	[CLR20_META_TFILE] = 		"4SB",
	[CLR20_META_TEXPORTEDTYPE] = 	"44SSB",
	[CLR20_META_TMANIFESTRES] = 	"44SB",
	[CLR20_META_TNESTEDCLASS] = 	"DD",
	[CLR20_META_TGENERICPARAM] =	"22KS",
	[CLR20_META_TGENERICPARAMCONST]= "LT"
};