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