www.xbdev.net xbdev - software development
Friday December 14, 2018
home | about | contact | Donations

     
 

XBOX Programming

More than just a hobby...

 

XBOX - XBE to ASM and Hex using C and NASM

 

We take an xbe...any xbe...from the xbox hard drive...or extract one from a game cd...we'll then go about converting it to a nasm file, which we can use nasm to rebuild into the original xbe.  Of course the nasm file will contain disassembled asm values....header data the works....so we really really get a feel for what makes up an xbe.

 

How does NASM help us?...what is NASM?   where can you get NASM?...hmmm

 

Well NASM stands for the Netwide Assembler, as is an 80x86 open source assembler...but its much much more.  Its open source, so you can download it free and see how it works if you like... its powerful, and can assemble intel pentium 3 and 4 opcodes.  But best of all it allows us to create simple hex/asm files...which we can assemble nice and easily to produce binary output... but for use the binary output will be an xbe.

 

So take an example....open notepad and enter these lines:

 

db 'XBE'

db 0x10

dd 0x59

 

 

Then save it as...hmmm...lets call it test.asm...you can call it anything you want...whacky.txt if you like, nasm will still work with it.  We then go to the command line, and enter:

 

C:> nasm.exe test.asm -o test.txt

 

And that will produce our output file.  The -o is so we can name our output file...if you just put 'nasm.exe test.asm'....it will produce an output file called 'test' with no extension.  Go on now...open your output file test.txt in notepad...see what it looks like..heheh

 

'XBE Y '

 

Well its not much to look at...but if you open it up in a hex editor you'll see that every byte that we've specified in our nasm input file has been put into our output file...we can also mix in 80x86 asm code....comments....so much we can do....and then just assemble it to produce our output.

 

Where is this taking us?  Well we will write some C code which will take our xbe, and convert it to a nasm asm file...which when we assemble it with nasm will reproduce the original xbe.  But while producing the asm file with our C code...we'll be putting information in our output...what each byte means...and possibly disassembling some of the binary code as well :)

 

 

First things first...we'll write a small C code that will take an input xbe file...and give us a nasm asm file....which we can convert back to an xbe using nasm :)

 

Here is our code to start with:

 

code A: main.cpp
 

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

 

// We use this simple function to write data to our file.

void abc(char *str)

{

      FILE *fp;

      fp=fopen("output.txt", "a+");        // a+ -> if file doesn't exist create it,

      fprintf(fp, "%s", str);              //       else 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(..)

 

 

 

//------------------------------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);

      abc(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" );

 

      // Seek to the start of the xbe - as our getfilesize(.) function has left it

      // at the end...so we need this.

      fseek(fp, 0, SEEK_SET);

 

      // Read all the contents into our allocated memory

      fread(pXBE, iFileSize, 1, fp);

 

      // Close our file.

      fclose( fp );

 

      //--------------------------Output XBE Hex to file-----------------------//

 

      abc("db\t");

      for(int icount=0; icount<iFileSize; icount++)

      {

            // Create our output in a format that nasm will like, e.g. "db  0x20"

            sprintf(buf, "0x%02X", pXBE[icount] );

            // Output to file

            abc(buf);

 

            // Every 0x10 bytes, do a new line

            // Added the icount!=0 so that we dont' get a byte db 0x56 etc on its

            // own line at the start.

            if( ((icount % 0x10) == 0) && (icount!=0))

                  abc("\ndb\t");

            else

                  abc(", ");

      }//End for loop

     

      //------------------------End of outputing to file ----------------------//

 

      // Goodbye

 

      // Remember, before exiting the program, release the memory we allcoated for

      // the xbe data we read in

      delete[] pXBE; 

      }// End main(..)

 

It looks like a lot of C code, but there really isn't that much....I've put loads of comments in it, and tried to lay it out in an easy format.  So lets run this baby up with a trial xbe and have a look at some of the output shall we!  Oh yeah...if your using a large xbe...megs...it may take a while to output the text file...as where not really interested in optimisation here..heheh...but be patient.  The nasm build on the other hand only takes a few seconds.

 

; File: default.xbe - xbe filesize: 1633220 bytes

 

db    0x58, 0x42, 0x45, 0x48, 0xFC, 0x55, 0x80, 0xD4, 0xFD, 0x4F, 0x11, 0xF7, 0x2B, 0xCE, 0x74, 0x27, 0xA8

db    0xE7, 0xD4, 0x94, 0x5D, 0x39, 0x20, 0xE7, 0x8E, 0x80, 0x77, 0xC4, 0x3F, 0x45, 0xD0, 0xC2, 0x39

db    0x52, 0x5D, 0x37, 0xD4, 0xDC, 0xE2, 0x8F, 0xF7, 0x08, 0x31, 0x69, 0x36, 0x67, 0x5D, 0xC3, 0x20

db    0x2F, 0x43, 0xEF, 0xFD, 0x3E, 0x3F, 0xA7, 0xC1, 0x85, 0xCB, 0x7F, 0x1F, 0x7B, 0x39, 0x33, 0xE4

db    0xB0, 0x81, 0x3C, 0x71, 0xF8, 0x5B, 0x5E, 0xDC, 0x9A, 0x8A, 0x57, 0x1C, 0xF7, 0x8E, 0xAB, 0x7F

db    0x84, 0x8A, 0x35, 0xE5, 0xA6, 0xB0, 0xF2, 0x45, 0x93, 0x70, 0xAF, 0xBC, 0xD3, 0x95, 0x16, 0xA9

db    0x47, 0xCA, 0x72, 0xEE, 0x68, 0xCC, 0x59, 0xF3, 0xB4, 0x49, 0xB1, 0x75, 0xDF, 0x44, 0x71, 0x5C

db    0x1D, 0x1B, 0x0E, 0xA7, 0xCB, 0x60, 0x9A, 0x17, 0x0B, 0xF1, 0x44, 0x2B, 0x58, 0x2C, 0x18, 0xF2

      db    0x58, 0xDD, 0x7A, 0xC4, 0xDA, 0xD2, 0xA9, 0x59, 0xC3, 0x64, 0x85, 0xBD, 0xDC, 0xA8, 0xD1, 0xF5

 

It may not look like much at the moment...but it will get there...so power up nasm and give it a test.... type in those magic lines "nasm output.txt -o default.xbe"....whoooshh...and there you have it....our original xbe is built from all thos hex values :)

 

We'll go about making our C code a bit smarter now, and make it output additional information for us...like the first 4 byte values are the char values 'X','B','E','H'....so we can have our C code do " db 'XBEH' on the first line.   And bit by bit disassemble the xbe into understandable information.

 

Also the great thing about learning this way is...that once you understand how an xbe is put together...what each byte is for...and which bytes are important...you can build xbox executables that are totally custom....just put in the asm code that you want and assemble it...then run it on the xbox and thats it.  Or progress further and create an exe to xbe converter program :)

 

A good idea at this point is to look over the xbe specification a few times, and try and understand it.  You don't have to worry to much, as I'll be taking you through it bit by bit....but its still worth having it close by so that you can look things up from time to time....and who knows...might might make a mistake :-/

 

Just so we can expand our code more and more and keep it tidy...I've split up the code we had above into some sub functions....so its easier to work with....small little pieces are better than big clumsy ones :)

 

code B: main.cpp

 

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

 

// We use this simple function to write data to our file.

void abc(char *str)

{

      ...

}// End fileout(..)

 

long FileSize( char * szFileName )

{

      ...

}// End FileSize(..)

 

void ReadInXBE( unsigned char ** pXBE, char * szFileName )

{

      long iFileSize = FileSize(szFileName);

 

      // Lets allocate enough memory for the whole xbe and read it all in

      *pXBE = new unsigned char[iFileSize];

 

      // Open our xbe file

      FILE* fp = fopen( szFileName, "r" );

 

      // Seek to the start of the xbe - as our getfilesize(.) function has left it

      // at the end...so we need this.

      fseek(fp, 0, SEEK_SET);

 

      // Read all the contents into our allocated memory

      fread(*pXBE, iFileSize, 1, fp);

 

      // Close our file.

      fclose( fp );

 

}// End ReadInXBE(..)

 

 

// We can use this function to either output all the file in hex, or if there

// are parts of the file that we are unsure about, then we can output that section

// in hex keeping the file integrity...or possibly output code sections in hex.

void OutRawHex( unsigned char * pXBE, int iFrom, int iTo )

{

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

      //--------------------------Output XBE Hex to file-----------------------//

     

      abc("db\t");

      for(int icount=iFrom; icount< iTo-1; icount++)

      {

            // Create our output in a format that nasm will like, e.g. "db  0x20"

            sprintf(buf, "0x%02X", pXBE[icount] );

            // Output to file

            abc(buf);

 

            // Every 0x10 bytes, do a new line

            if( (icount % 0x10) == 0 )

                  abc("\ndb\t");

            else

                  abc(", ");

      }//End for loop

 

      // Added this line, and made the above loop finish at iTo-1 instead of

      // iTo, so that our hex output doesn't finish with a comman (i.e. ,)

      sprintf(buf, " 0x%02X", pXBE[iTo-1] );

      abc(buf);

     

      //------------------------End of outputing to file ----------------------//

 

}// End OutRawHex(..)

 

 

/***************************************************************************************/

/*                                                                                     */

//------------------------------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);

      abc(buf);

 

      unsigned char * pXBE = NULL;

      ReadInXBE( &pXBE, szFileName );

 

 

      abc("db 'XBEH'\n");

 

      // Start at 4, as XBEH is 4 bytes..but arrays and all computers start at 0...so in

      // effect we have 0,1,2,3 then we start

      OutRawHex(pXBE, 4, iFileSize );

 

 

      // Goodbye

 

      // Remember, before exiting the program, release the memory we allcoated for

      // the xbe data we read in

      delete[] pXBE;

 

}// End main(..)

 

And the output isn't much different from the previous one...except I've not output the first 4 bytes as char as they should be :)

 

; File: default.xbe - xbe filesize: 1633220 bytes

 

db    'XBEH'

db    0x48, 0xFC, 0x55, 0x80, 0xD4, 0xFD, 0x4F, 0x11, 0xF7, 0x2B, 0xCE, 0x74, 0x27, 0xA8

db    0xE7, 0xD4, 0x94, 0x5D, 0x39, 0x20, 0xE7, 0x8E, 0x80, 0x77, 0xC4, 0x3F, 0x45, 0xD0, 0xC2, 0x39

db    0x52, 0x5D, 0x37, 0xD4, 0xDC, 0xE2, 0x8F, 0xF7, 0x08, 0x31, 0x69, 0x36, 0x67, 0x5D, 0xC3, 0x20

db    0x2F, 0x43, 0xEF, 0xFD, 0x3E, 0x3F, 0xA7, 0xC1, 0x85, 0xCB, 0x7F, 0x1F, 0x7B, 0x39, 0x33, 0xE4

db    0xB0, 0x81, 0x3C, 0x71, 0xF8, 0x5B, 0x5E, 0xDC, 0x9A, 0x8A, 0x57, 0x1C, 0xF7, 0x8E, 0xAB, 0x7F

 etc etc.....

 

Hmmmm...so what next....just sitting here, thinking of the best way to go about this....could get messy if we do it the wrong way :)  

 

 

IDEAS*

Well at various stages in my code development, I'm tempted to add all sorts of sweet improvements which will make the code much cooler and much more useful - but at a cost, which includes more complexity, and the possibility that it will be more inflexible to some unknowns.

Let me give you some ideas of where you could add some add-ons...which I won't implement, as I want to keep the code as simple as I can. 

\ Hidden File Offsets - There is nothing stopping you putting file offsets all the way through your file...e.g ";<0x0010020>" on the far right of your text output file.  This offset as long as you have the ; in front of it will be ignored by nasm.  But also, if you do a GUI interface later on, you could have the GUI loader look for this offset and use it in some way to get some further information from the xbe.

\ Progress Feedback.  Now I'm working with quite a big xbe, so it takes a few minutes to process the data...so it might be better off to possibly use printf(..) to output some data to the dos console to show whats happening...and when we go into one of those big loops....do a possible %10, %20...feedback of how far along we are.

 

What do we have now... I've wrote a nice piece of code...which a few helper functions which makes it possible now for us to hopefully output and analyse all the header data.... the code seemed to grow quiet fast, but I kept thinking ahead...as we have quick a few different headers after the main ImageHeader at the start...so putting together some nice output functions which we can call over and over again makes the code easier to the eyes I think.  At this point, all I've done is processed the first 0x178 bytes...which is the first Header data at the start of the xbe.

 

This tells us all the other offsets to all our other juicy data that we'll be extracting soon.  I've not put many comments into the header outputs yet....things like where it has the address of the file location...we could put a comment line and write what is written at that address - just so the asm file looks more understandable.  We'll have a few cups of coffee later on and try and add those lines in :)

 

 

code C: main.cpp

 

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

 

/***************************************************************************************/

//-------------------------------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()

 

/***************************************************************************************/

 

 

// We use this simple function to write data to our file.

void abc(char *str)

{

      ...

}// End fileout(..)

 

long FileSize( char * szFileName )

{

      ...

}// End FileSize(..)

 

void ReadInXBE( unsigned char ** pXBE, char * szFileName )

{

      ...

}// End ReadInXBE(..)

 

 

// We can use this function to either output all the file in hex, or if there

// are parts of the file that we are unsure about, then we can output that section

// in hex keeping the file integrity...or possibly output code sections in hex.

void OutRawHex( unsigned char * pXBE, int iFrom, int iTo )

{

      ...

}// End OutRawHex(..)

 

// iNum      -> How many char to output...e.g. db 'XBE' is 3 char

// pData     -> Pointer to the character data

// szComment -> Should speak for itself, if we want a comment on the end

void OutCharData(int iNum, char* pData, char* szComment=0  )

{

      ...

}// End OutCharData(..)

 

void OutWordData(int iNum, unsigned short* pData, char* szComment=0  )

{

      ...

}// End OutCharData(..)

 

void OutDwordData(int iNum, unsigned int* pData, char* szComment=0  )

{

      ...

}// End OutCharData(..)

 

// I added this function, so I could put comments into the output file, with

// the same indentation spaces...instead of using sprintf(..) and output etc

// over and over agian :)

void OutComment(char * szComment)

{

      ...

}// End OutComment(..)

 

 

#define DATA_TYPE_CHAR  0

#define DATA_TYPE_WORD  1

#define DATA_TYPE_DWORD 2

void OutData( unsigned int iType, void * pData, char* szComment=0, int iNum=1 )

{

      char buf[500];

 

      switch( iType )

      {

      case 0:

            OutCharData(iNum, (char*)pData, szComment);

            break;

      case 1:

            OutWordData(iNum, (unsigned short*)pData, szComment);

            break;

      case 2:

            OutDwordData(iNum, (unsigned int*)pData, szComment);

            break;

      // possible implement a default - just incase

      }// End switch(..)

 

}// End OutData(..)

 

// Output the image header information

void OutImageHeader(unsigned char * pXBE, stImageHeader * pImageHeader)

{

      char buf[500];

 

      abc(";---------------------------ImageHeader-----------------------------;\n\n");

      abc("StartImageHeader:\n");

      OutData( DATA_TYPE_CHAR,  (void*)pImageHeader->sig, "Signature", 4);

 

      // The authentication signature can just be replaced by a load of zero's

      sprintf(buf, "db\tresb  0x100\n"); abc(buf);

 

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->base_address,   "BaseAddress");

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->size_header,    "SizeHeader");

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->size_image,     "SizeImage");

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->size_image_header, "SizeImageHeader");

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->time_date,      "Time&Date");

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->cert_addr,      "Cert Header Addr");

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->num_sections,   "Num Sections");

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->sect_addr,      "Section Header Addr");

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->init_flags,     "Initialisation Flags");

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->entry_point,    "*Program Entry Point*");

 

      sprintf(buf, "XOR with our Release Key");

      OutComment(buf);

      sprintf(buf, "0x%08X ^ 0x%08X = 0x%08X", XOR_ENTRY_RETAIL,

                                                 pImageHeader->entry_point,

                                                                   pImageHeader->entry_point ^ XOR_ENTRY_RETAIL );

      OutComment(buf);

      OutComment("****Important**** - this is our entry point for our code\n");

 

 

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->tls_addr,       "TLS Header Addr");

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->pls_stack_commit, "PLS Stack Commit");

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->pe_heap_reserv, "PE Heap Reserve");

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->pe_heap_commit, "Pe Heap Commit");

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->pe_base_addr,   "PE Base Addr");

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->pe_size_image,  "PE Size Image");

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->pe_checksum,    "PE CheckSum");

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->pe_timedata,    "PE Time&Data");

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->pathname_addr,  "PathName Addr");

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->filename_addr,  "FileName Addr");

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->unicode_filename_addr, "Unicode FileName Addr");

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->kernel_thunk_addr, "Kernel Thunk Addr");

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->non_kernel_dir_addr, "Non Kernel Dir Addr");

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->num_lib_versions, "Num Library Headers");

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->lib_vers_addr, "Library Headers Addr");

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->kernel_lib_vers_addr, "Kernel Lib Addr");

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->xapi_lib_vers_addr, "XAPI Lib Addr");

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->logo_bitmap_addr, "Logo Bitmap Addr");

      OutData( DATA_TYPE_DWORD, (void*)&pImageHeader->logo_bitmap_size, "Logo Bitmap Size");

 

}// End OutImageHeader(..)

 

 

// Now all the xbe checking and outputting goes in here, as its bad to have all your

// code in the main function

void ProcessXBE( unsigned char * pXBE , long iFileSize)

{

      // Output the first part of the file - which is ImageHeader

      stImageHeader * pImageHeader = (stImageHeader*)pXBE;

      OutImageHeader( pXBE,  pImageHeader);

 

      // Display the rest of the file as hex

      OutRawHex(pXBE, sizeof(stImageHeader), iFileSize );

}// End ProcessXBE(..)

/***************************************************************************************/

/*                                                                                     */

//------------------------------Program Entry Point------------------------------------//

/*                                                                                     */

/***************************************************************************************/

void main(int argc, char* argv[])

{

      ...

}// End main(..)

 

And our output file:

 

; File: default.xbe - xbe filesize: 1633220 bytes

 

;---------------------------ImageHeader-----------------------------;

 

StartImageHeader:

db    'XBEH'           ;Signature

      resb  0x100

dd    0x00010000       ;BaseAddress

dd    0x00002000       ;SizeHeader

dd    0x0019E240       ;SizeImage

dd    0x00000178       ;SizeImageHeader

dd    0x3D5CE207       ;Time&Date

dd    0x00010178       ;Cert Header Addr

dd    0x00000018       ;Num Sections

dd    0x00010364       ;Section Header Addr

dd    0x0000000C       ;Initialisation Flags

dd    0xA8F93C11       ;*Program Entry Point*

                       ;XOR with our Release Key'

                       ;0xA8FC57AB ^ 0xA8F93C11 = 0x00056BBA

                       ;****Important**** - this is our entry point for our code

 

dd    0x0001D8EC       ;TLS Header Addr

dd    0x00010000       ;PLS Stack Commit

dd    0x00100000       ;PE Heap Reserve

dd    0x00001000       ;Pe Heap Commit

dd    0x00011B40       ;PE Base Addr

dd    0x0015A960       ;PE Size Image

dd    0x0016A024       ;PE CheckSum

dd    0x3D5CE202       ;PE Time&Data

dd    0x00010A7C       ;PathName Addr

dd    0x00010AA0       ;FileName Addr

dd    0x00010A58       ;Unicode FileName Addr

dd    0x5B6C60B6       ;Kernel Thunk Addr

dd    0x00000000       ;Non Kernel Dir Addr

dd    0x0000000B       ;Num Library Headers

dd    0x000109A8       ;Library Headers Addr

dd    0x000109E8       ;Kernel Lib Addr

dd    0x000109A8       ;XAPI Lib Addr

dd    0x00010AB4       ;Logo Bitmap Addr

dd    0x000002B2       ;Logo Bitmap Size

db    0xEC, 0x01, 0x00, 0x00, 0x0A, 0x3C, 0x5D, 0x3D, 0x00

db    0x00, 0xFE, 0xFF, 0x58, 0x00, 0x62, 0x00, 0x6F, 0x00, 0x78, 0x00, 0x20, 0x00, 0x44, 0x00, 0x61

db    0x00, 0x73, 0x00, 0x68, 0x00, 0x62, 0x00, 0x6F, 0x00, 0x61, 0x00, 0x72, 0x00, 0x64, 0x00, 0x00

db    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00

db    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00

 etc etc....all the other hex values to the end of the file

 

Yikes....its looking long now....but most of our main output functions are there...we can just dump the various header sections...like TLS Header and the Certifcate Header one after the other now...giving us a more or less complete header output...and leaving us with hex that should be padding and code.

 

So the ImageHeader part, has told us a lot of information...it tells us the locations of the various other sub headers....and it also tells us the base address, which we use a lot to calculate the offset of address into the xbe file where the data actually is.

 

 

This is one monster of a piece of code.  I guess its not that complex, as it just uses simple text out.... but its long...and has loads of small functions.  I've tried to do it so that output asm/txt file looks as nice as possible.  Slowness is also a big problem...but you won't be running it that often.  Usually you get the asm/txt output...fiddle with it and keep it safe...then rebuild it to an xbe when your ready.  Some of the padding between the headers is for text strings...names of sections etc.

A possible later improvement is to print the text values to the right of the hex in comments....so we can see if they are text values, then what are they.  Trying to make them out in hex is crazy..hehe.

 

What we really need to do as well, is in our main hex dump routine, is look for important offsets...such as the entry point...and sections....then mark them with markers..so we can see them :)  And every say 0x100 bytes...do an offset update as a comment...so we can see where we are all the time in the hex.

 

IDEAS

\ Many Zeros - Now at times when you scroll through the hex, you'll notice there are times when it repeats...for example...you get a million zeros...these are usually padding bytes.  And an improvement is to check for say more than 30 byte of zero, then replace them with 'resb 30' for example.  Makes our output file a lot smaller and more managable.

\ Help - On the console window, if we enter \? after our program name, it would be nice if it showed us some information on how our little program works....maybe add some additional options which can determine the type of output...and comments etc.

 

 

code D: main.cpp

 

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

#include <string.h>                         // strcpy(..)

 

/***************************************************************************************/

//-----------------------------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   // size 16 bytes

{

      char            library_name[8];

      unsigned short  majour_version;

      unsigned short  minor_version;

      unsigned short  build_version;

      unsigned short  pad;

      //unsigned char   gap_unknown[118];

      //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()

 

/***************************************************************************************/

 

 

// We use this simple function to write data to our file.

void abc(char *str)...

 

long FileSize( char * szFileName )...

 

void ReadInXBE( unsigned char ** pXBE, char * szFileName )...

 

 

// We can use this function to either output all the file in hex, or if there

// are parts of the file that we are unsure about, then we can output that section

// in hex keeping the file integrity...or possibly output code sections in hex.

int OutRawHex( unsigned char * pXBE, int iFrom, int iTo, int iNumPerLine = 0x10 )...

 

// iNum      -> How many char to output...e.g. db 'XBE' is 3 char

// pData     -> Pointer to the character data

// szComment -> Should speak for itself, if we want a comment on the end

void OutCharData(int iNum, char* pData, char* szComment=0  )...

 

void OutUnicodeData(int iNum, unsigned short* pData, char * szComment=0  )...

void OutWordData(int iNum, unsigned short* pData, char* szComment=0  )...

void OutDwordData(int iNum, unsigned int* pData, char* szComment=0  )...

 

// I added this function, so I could put comments into the output file, with

// the same indentation spaces...instead of using sprintf(..) and output etc

// over and over agian :)

void OutComment(char * szComment)...

 

 

#define DATA_TYPE_CHAR    0

#define DATA_TYPE_WORD    1

#define DATA_TYPE_DWORD   2

#define DATA_TYPE_UNICODE 3

void OutData( unsigned int iType, void * pData, char* szComment=0, int iNum=1 )...

 

// Output the image header information

unsigned int OutImageHeader(unsigned char * pXBE, stImageHeader * pImageHeader)...

int OutCertHeader(unsigned char * pXBE, stCertificate * pCertHeader)...

 

 

int OutSingleSectionHeader(unsigned char *pXBE, stSection * pSectHeader, unsigned int iBaseAddr )...

int OutSectionHeader(unsigned char *pXBE, stSection * pSectHeader, unsigned int iBaseAddr, int iNum )...

 

int OutSingleLibraryHeader(unsigned char *pXBE, stLibrary * pLibHeader )...

int OutLibraryHeader(unsigned char *pXBE, stLibrary * pLibHeader, int iNum )...

int OutTLSHeader(unsigned char *pXBE, stTLS * pTLSHeader )...

 

 

// Now all the xbe checking and outputting goes in here, as its bad to have all your

// code in the main function

void ProcessXBE( unsigned char * pXBE , long iFileSize)

{

      char buf[500];

      unsigned int iOffset = 0;

 

      // Output the first part of the file - which is ImageHeader

      stImageHeader * pImageHeader = (stImageHeader*)pXBE;

      iOffset += OutImageHeader( pXBE,  pImageHeader);

 

      unsigned int iBaseAddr      = pImageHeader->base_address;

      unsigned int iCertOffset    = pImageHeader->cert_addr     - iBaseAddr;

      stCertificate * pCertHeader = (stCertificate*)&pXBE[iCertOffset];

 

      unsigned int iSectOffset    = pImageHeader->sect_addr     - iBaseAddr;

      stSection     * pSectHeader = (stSection*)&pXBE[iSectOffset];

 

      unsigned int iLibOffset     = pImageHeader->lib_vers_addr - iBaseAddr;

      stLibrary     * pLibHeader  = (stLibrary*)&pXBE[iLibOffset];

 

      unsigned int iTLSOffset     = pImageHeader->tls_addr      - iBaseAddr;

      stTLS         * pTLSHeader  = (stTLS*)&pXBE[iTLSOffset];

 

      // Possible check here? - we could check the order of the various sub structures

      // incase they change, but we'll assume a fixed order for now.

 

      // Skip any padding between end of previous header and this one

      iOffset += OutRawHex(pXBE, iOffset, iCertOffset );

      // Output the certificate header data

      iOffset += OutCertHeader( pXBE, pCertHeader );

 

      // Skip any padding between end of previous header and this one

      iOffset += OutRawHex(pXBE, iOffset, iSectOffset );

      // Output the first section header data

      iOffset += OutSectionHeader(pXBE, pSectHeader, iBaseAddr, pImageHeader->num_sections );

 

      //Debug

      sprintf(buf, "\n;{0x%08X} -> 0x%02X\n", iOffset, pXBE[iOffset]);

      abc(buf);

 

      // Skip any padding between end of previous header and this one

      iOffset += OutRawHex(pXBE, iOffset, iLibOffset );

      // Output the first library header

      iOffset += OutLibraryHeader(pXBE, pLibHeader, pImageHeader->num_lib_versions);

 

     

      // Skip any padding between end of previous header and this one

      iOffset += OutRawHex(pXBE, iOffset, iTLSOffset );

      // Output TLS Header

      iOffset += OutTLSHeader(pXBE, pTLSHeader);

     

 

      //Debug

      sprintf(buf, "\n;{0x%08X} -> 0x%02X\n", iOffset, pXBE[iOffset]);

      abc(buf);

     

 

 

      // Display the rest of the file as hex

      OutRawHex(pXBE, iOffset, iFileSize );

}// End ProcessXBE(..)

 

 

/***************************************************************************************/

/*                                                                                     */

//------------------------------Program Entry Point------------------------------------//

/*                                                                                     */

/***************************************************************************************/

void main(int argc, char* argv[])

{

      ...

}// End main(..)

 

 

I've just commented the contents of a lot of the functions out with "..." as it really fills the web page up otherwise.... you can still look at the code and test it out, by clicking on main.cpp.  The output as you can imagine is long, but I've put a lot of comments in our output txt file as well.

 

Remember to rebuild the xbe from the output.txt, you type "nasm.exe output.txt -o output.xbe"

 

Usually only takes 20-30 seconds to build the xbe.  If you change the output.txt file, remember that you have to think of things like alignment......might want to look up how you can keep data aligned to certain positions...filling it with padding :)

 

Here is how you would align a point to exactly 0x1000 in nasm:

 

TIMES 0x1000-($-$$) DB 0 ; I've aligned this point in the code to exactly

                               ; 0x1000

 

Everything up to that point is then padded with zero's.

 

Anyhow...lets take a look at the output...not take a deep breath, as its big!...

 

Output:

 

; File: default.xbe - xbe filesize: 1633220 bytes

 

;---------------------------ImageHeader-----------------------------;

 

StartImageHeader:

db    'XBEH'           ;Signature

resb  0x100

dd    0x00010000       ;BaseAddress

dd    0x00002000       ;SizeHeader

dd    0x0019E240       ;SizeImage

dd    0x00000178       ;SizeImageHeader

dd    0x3D5CE207       ;Time&Date

dd    0x00010178       ;Cert Header Addr

dd    0x00000018       ;Num Sections

dd    0x00010364       ;Section Header Addr

dd    0x0000000C       ;Initialisation Flags

dd    0xA8F93C11       ;*Program Entry Point*

                       ;XOR with our Release Key

                       ;0xA8FC57AB ^ 0xA8F93C11 = 0x00056BBA

                       ;****Important**** - this is our entry point for our code

 

dd    0x0001D8EC       ;TLS Header Addr

dd    0x00010000       ;PLS Stack Commit

dd    0x00100000       ;PE Heap Reserve

dd    0x00001000       ;Pe Heap Commit

dd    0x00011B40       ;PE Base Addr

dd    0x0015A960       ;PE Size Image

dd    0x0016A024       ;PE CheckSum

dd    0x3D5CE202       ;PE Time&Data

dd    0x00010A7C       ;PathName Addr

dd    0x00010AA0       ;FileName Addr

dd    0x00010A58       ;Unicode FileName Addr

dd    0x5B6C60B6       ;Kernel Thunk Addr

dd    0x00000000       ;Non Kernel Dir Addr

dd    0x0000000B       ;Num Library Headers

dd    0x000109A8       ;Library Headers Addr

dd    0x000109E8       ;Kernel Lib Addr

dd    0x000109A8       ;XAPI Lib Addr

dd    0x00010AB4       ;Logo Bitmap Addr

dd    0x000002B2       ;Logo Bitmap Size

;-----------------------End ImageHeader-----------------------------;

 

;-------------------------CertificateHeader-------------------------;

 

StartCertHeader:

dd    0x000001EC       ;SizeCertificateHeader

dd    0x3D5D3C0A       ;Time&Data

dd    0xFFFE0000       ;TitleID

;UniCode Title

dw    0x0058, 0x0062, 0x006F, 0x0078, 0x0020, 0x0044, 0x0061, 0x0073

dw    0x0068, 0x0062, 0x006F, 0x0061, 0x0072, 0x0064, 0x0000, 0x0000

dw    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000

dw    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000

dw    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000

;db   'X b o x   D a s h b o a r d '

;Alt TitleIDs

dd    0x00000000

dd    0x00000000

dd    0x00000000

dd    0x00000000

dd    0x00000000

dd    0x00000000

dd    0x00000000

dd    0x00000000

dd    0x00000000

dd    0x00000000

dd    0x00000000

dd    0x00000000

dd    0x00000000

dd    0x00000000

dd    0x00000000

dd    0x00000000

dd    0x80000001

dd    0x7FFFFFFF

dd    0xFFFFFFFF

dd    0x00000000

dd    0x10027100

dd    0xEFD23B6E

dd    0x3D9A798B       ;Media Flags

dd    0x77F215B3       ;Game Region

dd    0x91AF7A86       ;Game Rating

dd    0x0E94B612       ;Disk Number

dd    0xEC59BE4D       ;Certificate Version

;LAN Key

db    0xE0, 0xC7, 0xF8, 0x06, 0x33, 0x20, 0xB1, 0xB8, 0x0F, 0x21, 0x4F, 0xC8, 0x8C, 0x77, 0xAF, 0x90

;Signature Key

db    0xCF, 0x95, 0x60, 0xDA, 0x99, 0x68, 0xDF, 0x5C, 0x76, 0xEA, 0x9F, 0x3C, 0xB5, 0x7E, 0x70, 0xF4

;Alt Signature Key

db    0x5A, 0x24, 0x63, 0x98, 0xD8, 0xE7, 0xF2, 0x07, 0xCF, 0xC6, 0x4B, 0x3B, 0x37, 0xBB, 0x17, 0x54

db    0xF7, 0xB8, 0x2E, 0x28, 0x8B, 0x2B, 0xF6, 0x3E, 0x47, 0xC9, 0x8D, 0xE1, 0xEF, 0x33, 0xBE, 0x77

db    0x2B, 0x77, 0xE2, 0x0D, 0xBD, 0xE4, 0x9B, 0xCF, 0xEA, 0x7B, 0x1E, 0x40, 0x4A, 0x08, 0xD0, 0x8D

db    0x0C, 0x39, 0x0D, 0xE8, 0xAC, 0x63, 0x06, 0xE0, 0x19, 0x57, 0xA7, 0x40, 0x45, 0x06, 0x92, 0x52

db    0x2A, 0xB2, 0xA0, 0x22, 0x99, 0x65, 0x2D, 0xC8, 0xE6, 0x39, 0x2F, 0xCE, 0x16, 0x40, 0x92, 0x07

db    0xFD, 0x2E, 0x9F, 0x48, 0x82, 0x57, 0x48, 0x9D, 0x20, 0x61, 0x8B, 0xDD, 0x92, 0xA8, 0xB6, 0x08

db    0x20, 0x1E, 0xBC, 0xA6, 0x79, 0x42, 0x41, 0x74, 0xF1, 0x52, 0x94, 0x38, 0xE2, 0xD7, 0x62, 0x37

db    0xAF, 0x4A, 0x78, 0x03, 0xC8, 0x17, 0x91, 0xFB, 0x54, 0x1E, 0x53, 0x0A, 0x30, 0x67, 0x4B, 0x37

db    0x4D, 0x65, 0xB6, 0x44, 0x98, 0x8F, 0x39, 0xC6, 0x4A, 0x76, 0x3D, 0xA5, 0x2C, 0x49, 0xE8, 0xAA

db    0x47, 0x2C, 0xA2, 0x0F, 0x76, 0xBF, 0x34, 0x4E, 0x24, 0xB6, 0x49, 0x71, 0x4A, 0x37, 0x62, 0xAC

db    0xF4, 0x65, 0x8B, 0x20, 0x67, 0x62, 0x2E, 0x04, 0xDA, 0x34, 0xC4, 0x8F, 0xA9, 0xFB, 0x8A, 0x82

db    0xC1, 0x14, 0x8B, 0x7D, 0x06, 0x3D, 0xEA, 0x2F, 0x18, 0x60, 0x74, 0xDD, 0xDE, 0x48, 0x6C, 0xCD

db    0xB3, 0x27, 0x66, 0x65, 0xF4, 0x89, 0x9F, 0xC7, 0xC4, 0xAE, 0x66, 0x2E, 0x27, 0x84, 0xB7, 0x82

db    0xF6, 0x7C, 0x23, 0xB3, 0xC6, 0x56, 0x6C, 0x1A, 0x36, 0xE7, 0x5B, 0x39, 0xA4, 0xAB, 0x16, 0x33

db    0x0C, 0xCC, 0x37, 0xA2, 0xE1, 0x0C, 0x75, 0xD8, 0xEC, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00

db    0x00, 0x00, 0x00, 0x00, 0x2B, 0x74, 0x07, 0x35, 0xEF, 0x37, 0x9A, 0x4E, 0x37, 0xF8, 0xE7, 0xA9

;---------------------End CertificateHeader-------------------------;

 

db    0x3B, 0x31, 0xBC, 0xB4

;---------------------------SectionHeaders--------------------------;

 

StartSectHeader:

 

;----------------;

;**.text**

dd    0x00000016       ;Flags

dd    0x00012000       ;Virtual Address

dd    0x000A1850       ;Virtual Size

dd    0x00002000       ;Raw Address

dd    0x000A1850       ;Raw Size

dd    0x000108D4       ;Section Name Addr

dd    0x00000000       ;Section Name Ref Count

dd    0x000108A4       ;Head Share Page Ref Count Addr

dd    0x000108A6       ;Tail Share Page Ref Count Addr

;Section Digest

db    0x48, 0x48, 0x2D, 0x5C, 0x89

db    0x07, 0x6B, 0xB5, 0x09, 0x95

db    0xA5, 0xD1, 0xE5, 0xCB, 0x0D

db    0x26, 0x3B, 0x19, 0xF8, 0x18

 

;----------------;

 

....skip as so not so big on the eyes....

 

;----------------;

;**PortugueseXlate**

dd    0x00000009       ;Flags

dd    0x001A5660       ;Virtual Address

dd    0x00008BC4       ;Virtual Size

dd    0x00186000       ;Raw Address

dd    0x00008BC4       ;Raw Size

dd    0x00010997       ;Section Name Addr

dd    0x00000000       ;Section Name Ref Count

dd    0x000108D0       ;Head Share Page Ref Count Addr

dd    0x000108D2       ;Tail Share Page Ref Count Addr

;Section Digest

db    0x3D, 0x53, 0xDE, 0xA5, 0xF2

db    0x5D, 0x94, 0x62, 0x9B, 0x49

db    0x13, 0x94, 0x3D, 0x43, 0x8B

db    0x00, 0xC1, 0xDE, 0x38, 0xED

 

;-----------------------End SectionHeaders--------------------------;

;....these values are the actual text that is used in the section names address

;....so things like 'PortugueseXlate' and '.text'....this is where the text is

;{0x000008A4} -> 0x00

db    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00

db    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00

db    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00

db    0x00, 0x00, 0x00, 0x00, 0x2E, 0x74, 0x65, 0x78, 0x74, 0x00, 0x44, 0x33, 0x44, 0x00, 0x44, 0x33

db    0x44, 0x58, 0x00, 0x58, 0x47, 0x52, 0x50, 0x48, 0x00, 0x44, 0x53, 0x4F, 0x55, 0x4E, 0x44, 0x00

db    0x57, 0x4D, 0x41, 0x44, 0x45, 0x43, 0x00, 0x58, 0x4F, 0x4E, 0x4C, 0x49, 0x4E, 0x45, 0x00, 0x58

db    0x4E, 0x45, 0x54, 0x00, 0x58, 0x50, 0x50, 0x00, 0x2E, 0x64, 0x61, 0x74, 0x61, 0x00, 0x44, 0x4F

db    0x4C, 0x42, 0x59, 0x00, 0x58, 0x4F, 0x4E, 0x5F, 0x52, 0x44, 0x00, 0x44, 0x56, 0x44, 0x54, 0x48

db    0x55, 0x4E, 0x4B, 0x00, 0x2E, 0x64, 0x61, 0x74, 0x61, 0x31, 0x00, 0x58, 0x49, 0x50, 0x53, 0x00

db    0x45, 0x6E, 0x67, 0x6C, 0x69, 0x73, 0x68, 0x58, 0x6C, 0x61, 0x74, 0x65, 0x00, 0x4A, 0x61, 0x70

db    0x61, 0x6E, 0x65, 0x73, 0x65, 0x58, 0x6C, 0x61, 0x74, 0x65, 0x00, 0x47, 0x65, 0x72, 0x6D, 0x61

db    0x6E, 0x58, 0x6C, 0x61, 0x74, 0x65, 0x00, 0x46, 0x72, 0x65, 0x6E, 0x63, 0x68, 0x58, 0x6C, 0x61

db    0x74, 0x65, 0x00, 0x53, 0x70, 0x61, 0x6E, 0x69, 0x73, 0x68, 0x58, 0x6C, 0x61, 0x74, 0x65, 0x00

db    0x49, 0x74, 0x61, 0x6C, 0x69, 0x61, 0x6E, 0x58, 0x6C, 0x61, 0x74, 0x65, 0x00, 0x4B, 0x6F, 0x72

db    0x65, 0x61, 0x6E, 0x58, 0x6C, 0x61, 0x74, 0x65, 0x00, 0x54, 0x43, 0x68, 0x69, 0x6E, 0x65, 0x73

db    0x65, 0x58, 0x6C, 0x61, 0x74, 0x65, 0x00, 0x50, 0x6F, 0x72, 0x74, 0x75, 0x67, 0x75, 0x65, 0x73

db    0x65, 0x58, 0x6C, 0x61, 0x74, 0x65, 0x00, 0x00

;---------------------------LibraryHeaders--------------------------;

 

StartLibHeader:

 

;----------------;

 

;db   'XAPILIB'        ;Library Name

db    0x58, 0x41, 0x50, 0x49, 0x4C, 0x49, 0x42, 0x00

dw    0x0001           ;Majour Version

dw    0x0000           ;Minor Version

dw    0x12DF           ;BuildVersion

dw    0x4001           ;16 bytes alignment

 

;----------------;

 

....skip as so not so big on the eyes....

 

;----------------;

 

;db   'LIBCPMT'        ;Library Name

db    0x4C, 0x49, 0x42, 0x43, 0x50, 0x4D, 0x54, 0x00

dw    0x0001           ;Majour Version

dw    0x0000           ;Minor Version

dw    0x12DF           ;BuildVersion

dw    0x4001           ;16 bytes alignment

 

;-----------------------End LibraryHeaders--------------------------;

 

db    0x78, 0x00, 0x62, 0x00, 0x6F, 0x00, 0x78, 0x00

db    0x64, 0x00, 0x61, 0x00, 0x73, 0x00, 0x68, 0x00, 0x5F, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00

db    0x32, 0x00, 0x2E, 0x00, 0x65, 0x00, 0x78, 0x00, 0x65, 0x00, 0x00, 0x00, 0x64, 0x3A, 0x5C, 0x78

db    0x62, 0x6F, 0x78, 0x72, 0x65, 0x74, 0x5C, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5C, 0x75

db    0x69, 0x5C, 0x78, 0x61, 0x70, 0x70, 0x5C, 0x6F, 0x62, 0x6A, 0x5C, 0x69, 0x33, 0x38, 0x36, 0x5C

db    0x78, 0x62, 0x6F, 0x78, 0x64, 0x61, 0x73, 0x68, 0x5F, 0x32, 0x30, 0x30, 0x32, 0x2E, 0x65, 0x78

db    0x65, 0x00, 0x00, 0x00, 0x07, 0x33, 0xAD, 0x03, 0x07, 0x53, 0xAD, 0x03, 0xA9, 0x03, 0xEA, 0x00

           etc etc...rest of hex values...

 

ACCCkkkkkk...its a lot!...I mean a loooOOOOooootttTTTTTTTtt.  Yup... but most of it we don't really worry about.  Its just there, as I like to say ..hehe...also I'm working with a monster of an xbe :)   Use a big complex xbe, so I know our code won't let us down :)

 

 

 

Well in an effort to produce a more or less useable version...I added a few fix me ups to the code.  So now in our main hex dump, every 5 lines it will give us the offset into the file.  As it can be a monster to edit in wordpad if we dont' know where we are in the hex values.

 

****

Download Code E : main.cpp

****

 

 

IDEAS*

There is always so much more you can do to code...

\ The main hex dump loop - we could speed that baby up by using a temp string buffer....a dynamic one for example <string.h>...then keep putting the text there, and only at exiting the function write it to file.  As writing to disk is a considerable slow down.  Its okay for small files, but we can really notice it here.

\ Definitely need feedback - Its okay for us programmers, as we know its working...but sometimes we need to put some text out to tell people what its doing our program..possibly using printf(...)

\ Section Names - I think a definete must, would be to do a check function in our hex dump loop.  Which will check for certain locations...like the program entry point, and the start of each section, then add a label...e.g. "Entry_Point:" ...makes things even easier to edit.

\ Dissembler - Now it sounds harder than it is....but a small dissembler function.....nothing to advanced...but something we can use to disassemble a few of the useful lines in our code so we can see what they are - for example the entry point...starting points of sections etc.   One thing to be careful of here, is that sometimes the asm doesn't always compile back to the same size bytes which it came from!  Which means code that doesn't work!  So be careful of that...especially when disassembling jmp mnemonics.

\ More alignment points....so if we modify or delete sections...the rest of the code is still aligned to certain points.

 

 

Remember now, to rebuild the original xbe from your output.txt file....it just requies the lines "nasm.exe output.txt -o default.xbe"

 

So many things can be done with this!  We could take it right back to the ASM and have a complete looksy at the xbe!  Just takes time and effort.  Hopefully this small tutorial has helped.  If you find any problems or add some additional fixes, I'm grateful for any feedback on this.

 

bkenwright@xbdev.net

 

 

 

_______________________________________________________________________

 

References:

 

NASM Homepage

XBE-Specification (xbox-linux Ref)

 

 

 

 

 

 

 

 

 
 Visitor: 9534626  { 209.237.238.175 } Copyright (c) 2002-2017 xbdev.net - All rights reserved.
Designated tutorial and software are the property of their respective owners.