

#include <stdio.h>                     // Need this for fopen(..) fwrite(..) etc
#include <string.h>                    // memcpy(..)

// We use this simple function to write data to our file.
void fileout(char *str)
{
      FILE *fp;
      fp=fopen("output.txt", "a+");   // a+ -> if file doesn't exist create it, else
      fprintf(fp, "%s", str);         //       append to the end of the file
      fclose(fp); 
}// End fileout(..)

long FileSize( char * szFileName )
{
	FILE *file = fopen(szFileName, "rb"); // Open the file
	fseek(file, 0, SEEK_END);             // Seek to the end
	long file_size = ftell(file);         // Get the current position
	fclose(file);
	
	return file_size;                     // We have the file size, so return it
}// End FileSize(..)


//-----------------------------stImageHeader Structure------------------------------//
// Remember that we use 'pragma pack(1)' so our data in the stucture is packed nice
// and tight using a 1 byte alignment.
#pragma pack(1)
struct stImageHeader
{
	char          sig[4];
	unsigned char auth_sig[0x100];
	unsigned int  base_address;
	unsigned int  size_header;
	unsigned int  size_image;
	unsigned int  size_image_header;
	unsigned int  time_date;
	unsigned int  cert_addr;
	unsigned int  num_sections;
	unsigned int  sect_addr;
	unsigned int  init_flags;
#define MountUtilityDrive    0x00000001
#define FormatUtilityDrive   0x00000002
#define Limit64Megabytes     0x00000004 
#define DontSetupHarddisk    0x00000008
	unsigned int  entry_point;
#define XOR_ENTRY_DEBUG      0x94859D4B
#define XOR_ENTRY_RETAIL     0xA8FC57AB
	unsigned int  tls_addr;
	unsigned int  pls_stack_commit;
	unsigned int  pe_heap_reserv;
	unsigned int  pe_heap_commit;
	unsigned int  pe_base_addr;
	unsigned int  pe_size_image;
	unsigned int  pe_checksum;
	unsigned int  pe_timedata;
	unsigned int  pathname_addr;
	unsigned int  filename_addr;
	unsigned int  unicode_filename_addr;
	unsigned int  kernel_thunk_addr;
#define XOR_KERNEL_DEBUG     0xEFB1F152
#define XOR_KERNEL_RETAIL    0x5B6D40B6
	unsigned int  non_kernel_dir_addr;
	unsigned int  num_lib_versions;
	unsigned int  lib_vers_addr;
	unsigned int  kernel_lib_vers_addr;
	unsigned int  xapi_lib_vers_addr;
	unsigned int  logo_bitmap_addr;
	unsigned int  logo_bitmap_size;
};
#pragma pack()

//-----------------------------stCertificate Structure------------------------------//
#pragma pack(1)
struct stCertificate
{
	unsigned int  sizeCertStruc;
	unsigned int  timedate;
	unsigned int  titleID;
	wchar_t       title[0x28];         // or 0x50 bytes - unicode title
	unsigned int  alt_titleIDs[0x16];  // 0x40 bytes
	unsigned int  media_flags;
#define XBEIMAGE_MEDIA_TYPE_HARD_DISK           0x00000001 
#define XBEIMAGE_MEDIA_TYPE_DVD_X2              0x00000002 
#define XBEIMAGE_MEDIA_TYPE_DVD_CD              0x00000004 
#define XBEIMAGE_MEDIA_TYPE_CD                  0x00000008 
#define XBEIMAGE_MEDIA_TYPE_DVD_5_RO            0x00000010 
#define XBEIMAGE_MEDIA_TYPE_DVD_9_RO            0x00000020 
#define XBEIMAGE_MEDIA_TYPE_DVD_5_RW            0x00000040 
#define XBEIMAGE_MEDIA_TYPE_DVD_9_RW            0x00000080 
#define XBEIMAGE_MEDIA_TYPE_DONGLE              0x00000100 
#define XBEIMAGE_MEDIA_TYPE_MEDIA_BOARD         0x00000200 
#define XBEIMAGE_MEDIA_TYPE_NONSECURE_HARD_DISK 0x40000000 
#define XBEIMAGE_MEDIA_TYPE_NONSECURE_MODE      0x80000000 
#define XBEIMAGE_MEDIA_TYPE_MEDIA_MASK          0x00FFFFFF 
	unsigned int  game_region;
#define XBEIMAGE_GAME_REGION_NA                 0x00000001 
#define XBEIMAGE_GAME_REGION_JAPAN              0x00000002 
#define XBEIMAGE_GAME_REGION_RESTOFWORLD        0x00000004 
#define XBEIMAGE_GAME_REGION_MANUFACTURING      0x80000000 
	unsigned int  game_ratings;
	unsigned int  disk_number;
	unsigned int  cert_version;
	unsigned char lan_key[0x10];
	unsigned char signature_key[0x10];
	unsigned char alt_signature_key[0x10 * 0x10];
};
#pragma pack()

//-------------------------------stSection Structure--------------------------------//
#pragma pack(1)
struct stSection
{
	unsigned int  flags;
#define SECTION_WRITABLE						0x00000001 
#define SECTION_PRELOAD							0x00000002 
#define SECTION_EXECUTABLE						0x00000004 
#define SECTION_INSERTED_FILE					0x00000008 
#define SECTION_HEAD_PAGE_READ_ONLY				0x00000010 
#define SECTION_TAIL_PAGE_READ_ONLY				0x00000020 
	unsigned int  virt_addr;
	unsigned int  virt_size;
	unsigned int  raw_addr;
	unsigned int  raw_size;
	unsigned int  section_name_addr;
	unsigned int  section_name_ref_count;
	unsigned int  head_shared_page_ref_count_addr;
	unsigned int  tail_shared_page_ref_count_addr;
	unsigned char section_digest[0x14];
};
#pragma pack()


//-------------------------------stLibrary Structure--------------------------------//
#pragma pack(1)
struct stLibrary
{
	char		    library_name[8];
	unsigned short  majour_version;
	unsigned short  minor_version;
	unsigned short  build_version;
	unsigned int    flags;
#define LIB_QFEVERSION						0x1FFF  // 13-Bit Mask 
#define LIB_APPROVED						0x6000  // 02-Bit Mask
#define LIB_DEBUG_BUILD						0x8000  // 01-Bit Mask
};
#pragma pack()

//---------------------------------stTLS Structure----------------------------------//
#pragma pack(1)
struct stTLS
{
	unsigned int  data_start_addr;
	unsigned int  data_end_addr;
	unsigned int  tls_index_addr;
	unsigned int  tls_callback_addr;
	unsigned int  size_zero_fill;
	unsigned int  characteristics;
};
#pragma pack()


//-------------------------------ProcessXBE Function--------------------------------//

void ProcessXBE( unsigned char *pXBE, long iSizeXBE )
{

	stImageHeader IH;
	memcpy( &IH, pXBE, sizeof(stImageHeader) );

	// Large temp char buffer
	char buf[500];           

	int iOffset = 0;
	unsigned int * ptr = (unsigned int*)pXBE;

	// Write out the first 3 char's of the xbe to see what they are
	sprintf(buf, "Sig (0x4) (XBEH) = %c%c%c%c\n", 
		    IH.sig[0], IH.sig[1], IH.sig[2], IH.sig[3] );
	fileout(buf);

	sprintf(buf, "Base Address: 0x%08X\n", IH.base_address );
	fileout(buf);

	sprintf(buf, "Number Sections: 0x%08X\n", IH.num_sections );
	fileout(buf);

	sprintf(buf, "Section Address: 0x%08X\n", IH.sect_addr );
	fileout(buf);

	sprintf(buf, "Entry Point: 0x%08X (Decodes to: 0x%08X)\n", 
		                   IH.entry_point,  
						   IH.entry_point^XOR_ENTRY_RETAIL);
	fileout(buf);

	sprintf(buf, "Kernel Thunk Address: 0x%08X (Decodes to: 0x%08X)\n", 
		                  IH.kernel_thunk_addr, 
						  IH.kernel_thunk_addr^XOR_KERNEL_RETAIL );
	fileout(buf);

}// End ProcessXBE(..)


//------------------------------Program Entry Point---------------------------------//
//----------------------------------------------------------------------------------//
void main(int argc, char* argv[])
{
	char szFileName[] = "default.xbe";    // Our input xbe
	char buf[500];                        // Large temp char buffer

	long iFileSize = FileSize(szFileName);

	sprintf(buf, "File: %s - xbe filesize: %d bytes\n\n", szFileName, iFileSize);
	fileout(buf);

	// Lets allocate enough memory for the whole xbe and read it all in
	unsigned char * pXBE = new unsigned char[iFileSize];

	// Open our xbe file
	FILE* fp = fopen( szFileName, "r" );
	fseek(fp, 0, SEEK_SET);

	// Read all the contents into our allocated memory 
	fread(pXBE, iFileSize, 1, fp);

	// Close our file.
	fclose( fp );

	//------------------------Our XBE Analysis Code-------------------------//

	ProcessXBE( pXBE, iFileSize );
	
	//------------------------End of XBE Analysis---------------------------//

	// Goodbye

	// Remember, before exiting the program, release the memory we allcoated for 
	// the xbe data we read in
	delete[] pXBE;

}// End main(..)






