From: <mi...@us...> - 2003-10-12 19:28:06
|
Update of /cvsroot/xbox-linux/eds_i2c_staff/xbox_vdbtool In directory sc8-pr-cvs1:/tmp/cvs-serv4213/xbox_vdbtool Added Files: BootEEPROM.c BootEEPROM.h BootFlash.c BootFlash.h BootHddKey.c BootHddKey.h Makefile boot.h consts.h main.c rc4.c rc4.h sha1.c sha1.h xbox_vdbtool xboxlib.c xboxlib.h Log Message: Bits and pieces from xbox_tool and raincoat, provides information for the xbox versions database. Plan to make it ask for data it can't determine and submit it to the site via wget. --- NEW FILE: BootEEPROM.c --- #include <string.h> #include <stdio.h> #include <stdlib.h> #include "boot.h" #include "BootHddKey.h" #include "rc4.h" #include "sha1.h" int BootDecyptEEPROM(EEPROMDATA *eeprom) { int retVal = 0; unsigned char key_hash[20]; unsigned char data_hash_confirm[20]; //20 bytes unsigned char XBOX_Version = V1_0; rc4_key RC4_key; unsigned char eepData[0x30]; int nEncryptedState = 1; memset(eepData,0,0x30); memset(&RC4_key,0,sizeof(rc4_key)); memcpy(eepData,eeprom,0x30); while (((XBOX_Version <= 11) && (!retVal)) && nEncryptedState) { memset(key_hash,0,20); memset(data_hash_confirm,0,20); HMAC_SHA1_calculation(XBOX_Version, key_hash, eeprom->HMAC_SHA1_Hash, 20, NULL); rc4_prepare_key(key_hash, 20, &RC4_key); rc4_crypt(eeprom->Confounder, 8, &RC4_key); rc4_crypt(eeprom->HDDKkey, 20, &RC4_key); HMAC_SHA1_calculation(XBOX_Version, data_hash_confirm, eeprom->Confounder, 8, eeprom->HDDKkey, 20, NULL); if (_strncmp(eeprom->HMAC_SHA1_Hash,data_hash_confirm,0x14)) { memcpy(eeprom,eepData,0x30); XBOX_Version++; retVal = 0; } else { nEncryptedState = 0; retVal = 1; } } return retVal; } --- NEW FILE: BootEEPROM.h --- #ifndef _BootEEPROM_H_ #define _BootEEPROM_H_ //Defines for Data structure sizes.. #define EEPROM_SIZE 0x100 #define CONFOUNDER_SIZE 0x008 #define HDDKEY_SIZE 0x010 #define XBEREGION_SIZE 0x001 #define SERIALNUMBER_SIZE 0x00C #define MACADDRESS_SIZE 0x006 #define ONLINEKEY_SIZE 0x010 #define DVDREGION_SIZE 0x001 #define VIDEOSTANDARD_SIZE 0x004 //EEPROM Data structe value enums typedef enum { V_NONE = 0x00, V1_0 = 0x0A, V1_1 = 0x0B } XBOX_VERSION; typedef enum { ZONE_NONE = 0x00, ZONE1 = 0x01, ZONE2 = 0x02, ZONE3 = 0x03, ZONE4 = 0x04, ZONE5 = 0x05, ZONE6 = 0x06 } DVD_ZONE; typedef enum { VID_INVALID = 0x00000000, NTSC_M = 0x00400100, PAL_I = 0x00800300 } VIDEO_STANDARD; typedef enum { XBE_INVALID = 0x00, NORTH_AMERICA = 0x01, JAPAN = 0x02, EURO_AUSTRALIA = 0x04 } XBE_REGION; //Structure that holds contents of 256 byte EEPROM image.. typedef struct _EEPROMDATA { BYTE HMAC_SHA1_Hash[20]; // 0x00 - 0x13 HMAC_SHA1 Hash BYTE Confounder[8]; // 0x14 - 0x1B RC4 Encrypted Confounder ?? BYTE HDDKkey[16]; // 0x1C - 0x2B RC4 Encrypted HDD key BYTE XBERegion[4]; // 0x2C - 0x2F RC4 Encrypted Region code (0x01 North America, 0x02 Japan, 0x04 Europe) BYTE Checksum2[4]; // 0x30 - 0x33 Checksum of next 44 bytes unsigned char SerialNumber[12]; // 0x34 - 0x3F Xbox serial number BYTE MACAddress[6]; // 0x40 - 0x45 Ethernet MAC address BYTE UNKNOWN2[2]; // 0x46 - 0x47 Unknown Padding ? BYTE OnlineKey[16]; // 0x48 - 0x57 Online Key ? BYTE VideoStandard[4]; // 0x58 - 0x5B ** 0x00014000 = NTSC, 0x00038000 = PAL BYTE UNKNOWN3[4]; // 0x5C - 0x5F Unknown Padding ? //Comes configured up to here from factory.. everything after this can be zero'd out... //To reset XBOX to Factory settings, Make checksum3 0xFFFFFFFF and zero all data below (0x64-0xFF) //Doing this will Reset XBOX and upon startup will get Language & Setup screen... BYTE Checksum3[4]; // 0x60 - 0x63 other Checksum of next BYTE TimeZoneBias[4]; // 0x64 - 0x67 Zone Bias? unsigned char TimeZoneStdName[4]; // 0x68 - 0x6B Standard timezone unsigned char TimeZoneDltName[4]; // 0x5C - 0x6F Daylight timezone BYTE UNKNOWN4[8]; // 0x70 - 0x77 Unknown Padding ? BYTE TimeZoneStdDate[4]; // 0x78 - 0x7B 10-05-00-02 (Month-Day-DayOfWeek-Hour) BYTE TimeZoneDltDate[4]; // 0x7C - 0x7F 04-01-00-02 (Month-Day-DayOfWeek-Hour) BYTE UNKNOWN5[8]; // 0x80 - 0x87 Unknown Padding ? BYTE TimeZoneStdBias[4]; // 0x88 - 0x8B Standard Bias? BYTE TimeZoneDltBias[4]; // 0x8C - 0x8F Daylight Bias? BYTE LanguageID[4]; // 0x90 - 0x93 Language ID BYTE VideoFlags[4]; // 0x94 - 0x97 Video Settings BYTE AudioFlags[4]; // 0x98 - 0x9B Audio Settings BYTE ParentalControlGames[4]; // 0x9C - 0x9F 0=MAX rating BYTE ParentalControlPwd[4]; // 0xA0 - 0xA3 7=X, 8=Y, B=LTrigger, C=RTrigger BYTE ParentalControlMovies[4]; // 0xA4 - 0xA7 0=Max rating BYTE XBOXLiveIPAddress[4]; // 0xA8 - 0xAB XBOX Live IP Address.. BYTE XBOXLiveDNS[4]; // 0xAC - 0xAF XBOX Live DNS Server.. BYTE XBOXLiveGateWay[4]; // 0xB0 - 0xB3 XBOX Live Gateway Address.. BYTE XBOXLiveSubNetMask[4]; // 0xB4 - 0xB7 XBOX Live Subnet Mask.. BYTE OtherSettings[4]; // 0xA8 - 0xBB Other XBLive settings ? BYTE DVDPlaybackKitZone[4]; // 0xBC - 0xBF DVD Playback Kit Zone BYTE UNKNOWN6[64]; // 0xC0 - 0xFF Unknown Codes / History ? } EEPROMDATA, *LPEEPROMDATA; EEPROMDATA eeprom; typedef struct _XBOXDATA { int YResolution; int XResolution; int nReadFromFile; char szFileName[MAXFILENAME]; } XBOXDATA, *LPXBOXDATA; void BootEepromReadEntireEEPROM(void); void BootEepromPrintInfo(void); int BootDecyptEEPROM(EEPROMDATA *eeprom); #endif // _BootEEPROM_H_ --- NEW FILE: BootFlash.c --- /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /* 2003-11-12 mi...@ya... Truncated to minimum necessary for use in xbox_vdb (ie just id chip) 2003-04-14 an...@wa... Fixed W49F020 erase, confirmed working 2003-01-27 an...@wa... Fixed and verified ST29F080A programming Different block erase command from SST part Also seemed to require explicit chip reset action 2003-01-06 an...@wa... Created */ #include "boot.h" #include "BootFlash.h" #include <stdio.h> #include <string.h> // gets device ID, sets pof up accordingly // returns true if device okay or false for unrecognized device bool BootFlashGetDescriptor( OBJECT_FLASH *pof, KNOWN_FLASH_TYPE * pkft ) { bool fSeen=false; BYTE baNormalModeFirstTwoBytes[2]; int nTries=0; int nPos=0; pof->m_fIsBelievedCapableOfWriteAndErase=true; pof->m_szAdditionalErrorInfo[0]='\0'; baNormalModeFirstTwoBytes[0]=pof->m_pbMemoryMappedStartAddress[0]; baNormalModeFirstTwoBytes[1]=pof->m_pbMemoryMappedStartAddress[1]; while(nTries++ <2) { // first we try 29xxx method, then 28xxx if that failed // no ISRs should touch flash while we do the stuff __asm__ __volatile__ ( "pushf ; cli "); if(nTries!=1) { // 29xxx protocol // make sure the flash state machine is reset pof->m_pbMemoryMappedStartAddress[0x5555]=0xf0; pof->m_pbMemoryMappedStartAddress[0x5555]=0xaa; pof->m_pbMemoryMappedStartAddress[0x2aaa]=0x55; pof->m_pbMemoryMappedStartAddress[0x5555]=0xf0; // read flash ID pof->m_pbMemoryMappedStartAddress[0x5555]=0xaa; pof->m_pbMemoryMappedStartAddress[0x2aaa]=0x55; pof->m_pbMemoryMappedStartAddress[0x5555]=0x90; pof->m_bManufacturerId=pof->m_pbMemoryMappedStartAddress[0]; pof->m_bDeviceId=pof->m_pbMemoryMappedStartAddress[1]; pof->m_pbMemoryMappedStartAddress[0x5555]=0xf0; pof->m_fDetectedUsing28xxxConventions=false; // mark the flash object as representing a 28xxx job } else { // 28xxx protocol, seen on Sharp // make sure the flash state machine is reset pof->m_pbMemoryMappedStartAddress[0x5555]=0xff; // read flash ID pof->m_pbMemoryMappedStartAddress[0x5555]=0x90; pof->m_bManufacturerId=pof->m_pbMemoryMappedStartAddress[0]; pof->m_pbMemoryMappedStartAddress[0x5555]=0x90; pof->m_bDeviceId=pof->m_pbMemoryMappedStartAddress[1]; pof->m_pbMemoryMappedStartAddress[0x5555]=0xff; pof->m_fDetectedUsing28xxxConventions=true; // mark the flash object as representing a 28xxx job } __asm__ __volatile__ ( "popf "); if( (baNormalModeFirstTwoBytes[0]!=pof->m_bManufacturerId) || (baNormalModeFirstTwoBytes[1]!=pof->m_pbMemoryMappedStartAddress[1]) ) nTries=2; // don't try any more if we got some result the first time } // while // interpret device ID info { bool fMore=true; while(fMore) { if(!pkft->m_bManufacturerId) { fMore=false; continue; } if((pkft->m_bManufacturerId == pof->m_bManufacturerId) && (pkft->m_bDeviceId == pof->m_bDeviceId) ) { fSeen=true; fMore=false; nPos+=sprintf(&pof->m_szFlashDescription[nPos], "%s (%ldK)", pkft->m_szFlashDescription, pkft->m_dwLengthInBytes/1024); pof->m_dwLengthInBytes = pkft->m_dwLengthInBytes; if(pof->m_fDetectedUsing28xxxConventions) { int n=0; // detect master lock situation pof->m_pbMemoryMappedStartAddress[0x5555]=0x90; if(pof->m_pbMemoryMappedStartAddress[3]!=0) { // master lock bit is set, no erases or writes are going to happen pof->m_fIsBelievedCapableOfWriteAndErase=false; nPos+=sprintf(&pof->m_szFlashDescription[nPos], "Master Lock SET "); } // detect block lock situation nPos+=sprintf(&pof->m_szFlashDescription[nPos], "Block Locks: "); while(n<pof->m_dwLengthInBytes) { pof->m_pbMemoryMappedStartAddress[0x5555]=0x90; nPos+=sprintf(&pof->m_szFlashDescription[nPos], "%u", pof->m_pbMemoryMappedStartAddress[n|0x0002]&1); n+=0x10000; } nPos+=sprintf(&pof->m_szFlashDescription[nPos], " "); pof->m_pbMemoryMappedStartAddress[0x5555]=0x50; pof->m_pbMemoryMappedStartAddress[0x5555]=0xff; } } pkft++; } } if(!fSeen) { if( (baNormalModeFirstTwoBytes[0]==pof->m_bManufacturerId) && (baNormalModeFirstTwoBytes[1]==pof->m_pbMemoryMappedStartAddress[1]) ) { // we didn't get anything worth reporting sprintf(pof->m_szFlashDescription, "Read Only??? manf=0x%02X, dev=0x%02X", pof->m_bManufacturerId, pof->m_bDeviceId); } else { // we got what is probably an unknown flash type sprintf(pof->m_szFlashDescription, "manf=0x%02X, dev=0x%02X", pof->m_bManufacturerId, pof->m_bDeviceId); } } return fSeen; } --- NEW FILE: BootFlash.h --- /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /* 2003-01-06 an...@wa... Created */ // header for BootFlash.c #include "consts.h" typedef struct { volatile BYTE * volatile m_pbMemoryMappedStartAddress; // fill on entry BYTE m_bManufacturerId; BYTE m_bDeviceId; char m_szFlashDescription[256]; char m_szAdditionalErrorInfo[256]; DWORD m_dwLengthInBytes; DWORD m_dwStartOffset; DWORD m_dwLengthUsedArea; bool m_fDetectedUsing28xxxConventions; bool m_fIsBelievedCapableOfWriteAndErase; } OBJECT_FLASH; typedef struct { BYTE m_bManufacturerId; BYTE m_bDeviceId; char m_szFlashDescription[32]; DWORD m_dwLengthInBytes; } KNOWN_FLASH_TYPE; // requires pof->m_pbMemoryMappedStartAddress set to start address of flash in memory on entry bool BootFlashGetDescriptor( OBJECT_FLASH *pof, KNOWN_FLASH_TYPE * pkft ); --- NEW FILE: BootHddKey.c --- #include "boot.h" #include <stdarg.h> #include <string.h> #include "sha1.h" #include "rc4.h" /* This is basically originally all speedbump's work 2002-10-13 fr...@ca... Changes to work with v1.0 and v1.1 boxes 2002-09-18 fr...@ca... Changes to use a single SMAC_SHA1_calculation() routine 2002-09-13 an...@wa... Stitched in Franz's excellent key removal work: his modest statement follows Updated now, with no use for MS$ RC4 key now. Please do not send emails to me and ask: how does it work ? / What happended ? / Where ist the key ? (the key has gone) I only would say: It's a structural problem of the combination of the HMAC and the SHA-1. This only happened, as the programmer only take "standard" algorithm, and not thinking, what happens there. Ok, Studying Numerical Mathematical Analysis also helps a little. Maybe, i will document how this happend one day (would take me about 4 days to type this) on the http://sha1.caos.at website Beside, it's about 30% faster, as using the "standard" programm. (hehehe, it's a optimazion) Sorry, for the "brutal" programming, i know, it could have done better, yes. This was the working ,testing and probing programm, and usually if something is working, you are not touching it anyway. I hope, it is working good, as i have no XBOX to test this. 2002-06-27 an...@wa... Stitched it into crom, simplified out code that was for test, added munged key */ int HMAC1Reset(int, SHA1Context *context); int HMAC2Reset(int, SHA1Context *context); void SHA1ProcessMessageBlock(SHA1Context *context); void HMAC_SHA1_calculation(int, unsigned char *HMAC_result, ... ); extern size_t strlen(const char * s); void quick_SHA1( unsigned char *SHA1_result, ... ) { va_list args; struct SHA1Context context; va_start(args,SHA1_result); SHA1Reset(&context); while(1) { unsigned char *buffer = va_arg(args,unsigned char *); int length; if (buffer == NULL) break; length = va_arg(args,int); SHA1Input(&context,buffer,length); } SHA1Result(&context,SHA1_result); va_end(args); } void HMAC_SHA1( unsigned char *result, unsigned char *key, int key_length, unsigned char *text1, int text1_length, unsigned char *text2, int text2_length ) { unsigned char state1[0x40]; unsigned char state2[0x40+0x14]; int i; struct SHA1Context context; for(i=0x40-1; i>=key_length;--i) state1[i] = 0x36; for(;i>=0;--i) state1[i] = key[i] ^ 0x36; SHA1Reset(&context); SHA1Input(&context,state1,0x40); SHA1Input(&context,text1,text1_length); SHA1Input(&context,text2,text2_length); SHA1Result(&context,&state2[0x40]); for(i=0x40-1; i>=key_length;--i) state2[i] = 0x5C; for(;i>=0;--i) state2[i] = key[i] ^ 0x5C; SHA1Reset(&context); SHA1Input(&context,state2,0x40+0x14); SHA1Result(&context,result); } void HMAC_SHA1_calculation(int version,unsigned char *HMAC_result, ... ) { va_list args; struct SHA1Context context; va_start(args,HMAC_result); HMAC1Reset(version, &context); while(1) { unsigned char *buffer = va_arg(args,unsigned char *); int length; if (buffer == NULL) break; length = va_arg(args,int); SHA1Input(&context,buffer,length); } va_end(args); SHA1Result(&context,&context.Message_Block[0]); HMAC2Reset(version, &context); SHA1Input(&context,&context.Message_Block[0],0x14); SHA1Result(&context,HMAC_result); } int copy_swap_trim(unsigned char *dst, unsigned char *src, int len) { unsigned char tmp; int i; for (i=0; i < len; i+=2) { tmp = src[i]; //allow swap in place dst[i] = src[i+1]; dst[i+1] = tmp; } --dst; for (i=len; i>0; --i) { if (dst[i] != ' ') { dst[i+1] = 0; break; } } return i; } --- NEW FILE: BootHddKey.h --- #ifndef _BOOTHDDKEY_H_ #define _BOOTHDDKEY_H_ #include "consts.h" #include "boot.h" #include "BootEEPROM.h" void quick_SHA1( unsigned char *SHA1_result, ... ); void HMAC_SHA1( unsigned char *result, unsigned char *key, int key_length, unsigned char *text1, int text1_length, unsigned char *text2, int text2_length ); void HMAC_SHA1_calculation(int version,unsigned char *HMAC_result, ... ); int copy_swap_trim(unsigned char *dst, unsigned char *src, int len); #endif // _BOOTHDDKEY_H_ --- NEW FILE: Makefile --- CC = gcc CFLAGS = -g -O2 -Wall -Werror -D_GNU_SOURCE -I. LD = ld LBFLAGS = -lgcc -lc GCC295 = cpp0-2.95 ### objects OBJECTS = main.o EEPROM.o sha1.o rc4.o # target: all : xbox_vdbtool clean : rm -rf *.o *~ core *.core xbox_vdbtool xbox_vdbtool : gcc --static -g -O2 -Wall -Werror -D_GNU_SOURCE -o xbox_vdbtool main.c sha1.c rc4.c BootHddKey.c BootEEPROM.c BootFlash.c xboxlib.c ### rules: %.o : %.c boot.h consts.h BootFilesystemIso9660.h ${CC} ${CFLAGS} -o $@ -c $< %.o : %.S consts.h ${CC} -DASSEMBLER ${CFLAGSBR} -o $@ -c $< --- NEW FILE: boot.h --- #include "xboxlib.h" #define false 0 #define true 1 --- NEW FILE: consts.h --- #ifndef _CONSTS_H_ #define _CONSTS_H_ typedef unsigned char BYTE; #define MAXFILENAME 1024 #ifndef bool_already_defined_ typedef int bool; #endif #define true 1 #define false 0 #ifndef NULL #define NULL ((void *)0) #endif typedef unsigned long DWORD; typedef unsigned short WORD; #define GEN_CONFIG 0 /* general configuration */ #define INTEGRITY 255 /* integrity word */ #define SECU_STATUS 128 /* security status */ /* time to complete security erase */ #define ERASE_TIME 89 /* - ordinary */ #define ENH_ERASE_TIME 90 /* - enhanced */ /* words 89, 90, SECU ERASE TIME */ #define ERASE_BITS 0x00ff #define PSWD_CODE 92 /* master password revision code */ /* word 128: security */ #define SECU_ENABLED 0x0002 #define SECU_LEVEL 0x0010 #define NUM_SECU_STR 6 #define NOVAL_0 0x0000 #define NOVAL_1 0xffff //Important ATA IDENTIFY Data Structure values ////As per ATA Spec #define IDE_SECURITY_SUPPORTED 0x0001 #define IDE_SECURITY_ENABLED 0x0002 #define IDE_SECURITY_PASSWORD_SET 0x0004 #define IDE_SECURITY_FROZEN 0x0008 #define IDE_SECURITY_COUNT_EXPIRED 0x0010 #define IDE_SECURITY_LEVEL_MAX 0x0100 #define HDD_SERIAL_OFFSET 0x014 #define HDD_MODEL_OFFSET 0x036 #define HDD_SECURITY_STATUS_OFFSET 0x100 #endif //_CONSTS_H_ --- NEW FILE: main.c --- /*************************************************************************** * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /* 2003-10-12 mi...@ya... Grabbed useful bits from xbox_tool */ #include <errno.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <sys/io.h> #include <linux/hdreg.h> #include <linux/i2c-dev.h> #include <getopt.h> #include "rc4.h" #include "BootHddKey.h" #include "BootFlash.h" #include "consts.h" #ifdef I2C_FUNC_SMBUS_READ_I2C_BLOCK_2 #define USE_I2C_BLOCK 1 #else #define USE_I2C_BLOCK 0 #endif #ifdef I2C_FUNC_SMBUS_BLOCK_DATA_PEC #define HAVE_PEC 1 #endif #define HDAINTERFACE "/dev/ide/host0/bus0/target0/lun0/disc" #define HDAPROCINTERFACE "/proc/ide/hda/identify" unsigned char m_XBOX_Version = V_NONE; OBJECT_FLASH objectflash; KNOWN_FLASH_TYPE aknownflashtype[32] = { // max 31 flash types known // default flash types used if /etc/raincoat.conf not available { 0xbf, 0x61, "SST49LF020", 0x40000 }, { 0x01, 0xd5, "Am29F080B", 0x100000 }, { 0x04, 0xd5, "Fujitsu MBM29F080A", 0x100000 }, { 0xad, 0xd5, "Hynix HY29F080", 0x100000 }, { 0x20, 0xf1, "ST M29F080A", 0x100000 }, { 0x89, 0xa6, "Sharp LHF08CH1",0x100000 }, { 0xda, 0x8c, "Winbond W49F020",0x40000 }, { 0x01, 0xa4, "AMD - Am29F040B",0x80000 }, { 0xda, 0x0b, "Winbond - W49F002U",0x40000 }, { 0xc2, 0x36, "MACRONIX - MX29F022NTPC",0x40000 }, { 0x20, 0xb0, "ST M29f002BT",0x40000 }, { 0, 0, "", 0 } // terminator }; void print_hex(unsigned char *szString,long len) { int i; for(i=0;i<len;i++) { printf("%02x",szString[i]); } } void flash_ident () { bool fReadback=false; int fileMem; // construct the flash object objectflash.m_bManufacturerId=0; objectflash.m_bDeviceId=0; objectflash.m_dwLengthInBytes=0; objectflash.m_dwStartOffset=0; objectflash.m_dwLengthUsedArea=0; objectflash.m_fDetectedUsing28xxxConventions=false; strcpy(&objectflash.m_szFlashDescription[0], "Unknown"); fileMem = open("/dev/mem", O_RDWR); if(!fileMem) { printf("Must be run as root\n"); return; } objectflash.m_pbMemoryMappedStartAddress = (BYTE *)mmap(0, 0x1000000, PROT_READ | PROT_WRITE, MAP_SHARED, fileMem , 0xff000000); if(objectflash.m_pbMemoryMappedStartAddress==NULL) { printf("Unable to map register memory\n"); return; } if (iopl(3)) {perror("iopl"); return;} if(BootFlashGetDescriptor(&objectflash, &aknownflashtype[0])) { printf("Flash Chip : %s\n", objectflash.m_szFlashDescription); } else { if(!fReadback) { printf("Flash Chip : Unknown - %s\n", objectflash.m_szFlashDescription); } } } int hdd_ident(char *device,unsigned char *buffer) { unsigned char args[4+512] = { WIN_IDENTIFY, 0, 0, 1, }; unsigned char *data = &args[4]; int rc; int dev = open(device,O_RDONLY); if (dev < 0) { printf("\n\nfailed to open device %s\n",device); exit(-1); } memset(data,0,512); rc = ioctl(dev,HDIO_DRIVE_CMD,args); if(rc != 0) { printf("HDIO_DRIVE_CMD(identify) failed"); } close(dev); memcpy(buffer,data,512); return rc; } void get_hdpasswd(EEPROMDATA *eeprom) { unsigned char model[0x28]; unsigned char m_length = 0x28; unsigned char ide_device_identity[512]; //response from DEVICE_IDENTIFY unsigned char *HDModel = &ide_device_identity[HDD_MODEL_OFFSET]; if((hdd_ident(HDAINTERFACE,ide_device_identity) != 0)) exit(0); memset(model,0,0x28); m_length = copy_swap_trim(model,HDModel,m_length); printf("HDD Model : %d %.*s\n",m_length,m_length,model); } int read_eeprom(EEPROMDATA *eeprom,XBOXDATA *xbdata) { FILE *fp; int i2cbus,address,file; int i; int e1, e2, e3; char filename1[20]; char filename2[20]; char filename3[20]; char *filename; int reg94,reg96; int reg86,reg78; BYTE *pb=(BYTE *)eeprom; if(xbdata->nReadFromFile) { fp = fopen(xbdata->szFileName,"r"); fread(eeprom,sizeof(EEPROMDATA),1,fp); fclose(fp); return 1; } else { i2cbus = 0; address = 0x54; sprintf(filename1,"/dev/i2c-%d",i2cbus); sprintf(filename2,"/dev/i2c%d",i2cbus); sprintf(filename3,"/dev/i2c/%d",i2cbus); if ((file = open(filename1,O_RDWR)) < 0) { e1 = errno; if ((file = open(filename2,O_RDWR)) < 0) { e2 = errno; if ((file = open(filename3,O_RDWR)) < 0) { e3 = errno; if(e1 == ENOENT && e2 == ENOENT && e3 == ENOENT) { fprintf(stderr,"Error: Could not open file `%s', `%s', or `%s': %s\n", filename1,filename2,filename3,strerror(ENOENT)); } if (e1 != ENOENT) { fprintf(stderr,"Error: Could not open file `%s' : %s\n", filename1,strerror(e1)); if(e1 == EACCES) fprintf(stderr,"Run as root?\n"); } if (e2 != ENOENT) { fprintf(stderr,"Error: Could not open file `%s' : %s\n", filename2,strerror(e2)); if(e2 == EACCES) fprintf(stderr,"Run as root?\n"); } if (e3 != ENOENT) { fprintf(stderr,"Error: Could not open file `%s' : %s\n", filename3,strerror(e3)); if(e3 == EACCES) fprintf(stderr,"Run as root?\n"); } exit(1); } else { filename = filename3; } } else { filename = filename2; } } else { filename = filename1; } /* use FORCE so that we can look at registers even when a driver is also running */ if (ioctl(file,I2C_SLAVE_FORCE,address) < 0) { fprintf(stderr,"Error: Could not set address to %d: %s\n",address, strerror(errno)); return 0; } for( i = 0; i < 256; i++ ) { *pb++ = i2c_smbus_read_byte_data(file,i); } address = 0x45; if (ioctl(file,I2C_SLAVE_FORCE,address) < 0) { fprintf(stderr,"Error: Could not set address to %d: %s\n",address, strerror(errno)); return 0; } reg94 = i2c_smbus_read_byte_data(file, 0x94); reg96 = i2c_smbus_read_byte_data(file, 0x96); reg86 = i2c_smbus_read_byte_data(file, 0x86); reg78 = i2c_smbus_read_byte_data(file, 0x78); xbdata->YResolution = (((DWORD)(reg96&0x0c))<<6)|reg94; xbdata->XResolution = (((DWORD)(reg86&0x70))<<4)|reg78; if(xbdata->XResolution > 500 && xbdata->XResolution < 700) xbdata->XResolution = 640; if(xbdata->XResolution > 750 && xbdata->XResolution < 850) xbdata->XResolution = 800; return 1; } return 0; } void print_video(EEPROMDATA *eepromdata) { switch(*((VIDEO_STANDARD *)eepromdata->VideoStandard)) { case VID_INVALID: printf("0 "); break; case NTSC_M: printf("NTSC"); break; case PAL_I: printf("PAL"); break; default: printf("%X ", (int)*((VIDEO_STANDARD *)eepromdata->VideoStandard)); break; } printf("\n"); } void print_serial(EEPROMDATA *eepromdata) { char sz[13]; memcpy(sz, eepromdata->SerialNumber, 12); sz[12]='\0'; printf("%s", sz); printf("\n"); } int main(int argc, char *argv[]) { EEPROMDATA eeprom; XBOXDATA xbdata; int nAll = 0; memset(&eeprom,0,sizeof(EEPROMDATA)); memset(&xbdata,0,sizeof(XBOXDATA)); nAll = 1; if(read_eeprom(&eeprom,&xbdata)) { if(!BootDecyptEEPROM(&eeprom)) { printf("Error in BootDecyptEEPROM\n"); exit(1); } printf("Video : "); print_video(&eeprom); printf("Serial : "); print_serial(&eeprom); get_hdpasswd(&eeprom); flash_ident(); } else { exit(1); } exit(0); } --- NEW FILE: rc4.c --- /*rc4.c */ #include "rc4.h" static void swap_byte(unsigned char *a, unsigned char *b) { unsigned char swapByte; swapByte = *a; *a = *b; *b = swapByte; } void rc4_prepare_key(unsigned char *key_data_ptr, int key_data_len, rc4_key *key) { unsigned char index1; unsigned char index2; unsigned char* state; short counter; state = &key->state[0]; for(counter = 0; counter < 256; counter++) state[counter] = counter; key->x = 0; key->y = 0; index1 = 0; index2 = 0; for(counter = 0; counter < 256; counter++) { index2 = (key_data_ptr[index1] + state[counter] + index2) % 256; swap_byte(&state[counter], &state[index2]); index1 = (index1 + 1) % key_data_len; } } void rc4_crypt(unsigned char *buffer_ptr, int buffer_len, rc4_key *key) { unsigned char x; unsigned char y; unsigned char* state; unsigned char xorIndex; short counter; x = key->x; y = key->y; state = &key->state[0]; for(counter = 0; counter < buffer_len; counter ++) { x = (x + 1) % 256; y = (state[x] + y) % 256; swap_byte(&state[x], &state[y]); xorIndex = (state[x] + state[y]) % 256; buffer_ptr[counter] ^= state[xorIndex]; } key->x = x; key->y = y; } --- NEW FILE: rc4.h --- /* rc4.h */ #ifndef RC4_HEADER_INCLUDED #define RC4_HEADER_INCLUDED typedef struct rc4_key { unsigned char state[256]; unsigned char x; unsigned char y; } rc4_key; void rc4_prepare_key(unsigned char *key_data_ptr,int key_data_len,rc4_key *key); void rc4_crypt(unsigned char *buffer_ptr,int buffer_len,rc4_key * key); #endif /* RC4_HEADER_INCLUDED */ --- NEW FILE: sha1.c --- /* * sha1.c * * Description: * This file implements the Secure Hashing Algorithm 1 as * defined in FIPS PUB 180-1 published April 17, 1995. * * The SHA-1, produces a 160-bit message digest for a given * data stream. It should take about 2**n steps to find a * message with the same digest as a given message and * 2**(n/2) to find any two messages with the same digest, * when n is the digest size in bits. Therefore, this * algorithm can serve as a means of providing a * "fingerprint" for a message. * * Portability Issues: * SHA-1 is defined in terms of 32-bit "words". This code * uses <stdint.h> (included via "sha1.h" to define 32 and 8 * bit unsigned integer types. If your C compiler does not * support 32 bit unsigned integers, this code is not * appropriate. * * Caveats: * SHA-1 is designed to work with messages less than 2^64 bits * long. Although SHA-1 allows a message digest to be generated * for messages of any number of bits less than 2^64, this * implementation only works with messages with a length that is * a multiple of the size of an 8-bit character. * * * 2002-09-13 fr...@ca... Mods to Reset functions to use fixed states for avoiding keys * 2002-09-18 fr...@ca... Some minor cleanup and creating a single SMAC_SHA1_calculation() routine */ #include "sha1.h" /* * Define the SHA1 circular left shift macro */ #define SHA1CircularShift(bits,word) \ (((word) << (bits)) | ((word) >> (32-(bits)))) /* Local Function Prototyptes */ void SHA1PadMessage(SHA1Context *); void SHA1ProcessMessageBlock(SHA1Context *); /* * SHA1Reset * * Description: * This function will initialize the SHA1Context in preparation * for computing a new SHA1 message digest. * * Parameters: * context: [in/out] * The context to reset. * * Returns: * sha Error Code. * */ int HMAC1Reset(int version,SHA1Context *context) { SHA1Reset(context); if (version==10) { context->Intermediate_Hash[0] = 0x72127625; context->Intermediate_Hash[1] = 0x336472B9; context->Intermediate_Hash[2] = 0xBE609BEA; context->Intermediate_Hash[3] = 0xF55E226B; context->Intermediate_Hash[4] = 0x99958DAC; } if (version==11) { context->Intermediate_Hash[0] = 0x39B06E79; context->Intermediate_Hash[1] = 0xC9BD25E8; context->Intermediate_Hash[2] = 0xDBC6B498; context->Intermediate_Hash[3] = 0x40B4389D; context->Intermediate_Hash[4] = 0x86BBD7ED; } context->Length_Low = 512; return shaSuccess; } int HMAC2Reset(int version,SHA1Context *context) { SHA1Reset(context); if (version==10) { context->Intermediate_Hash[0] = 0x76441D41; context->Intermediate_Hash[1] = 0x4DE82659; context->Intermediate_Hash[2] = 0x2E8EF85E; context->Intermediate_Hash[3] = 0xB256FACA; context->Intermediate_Hash[4] = 0xC4FE2DE8; } if (version==11) { context->Intermediate_Hash[0] = 0x9B49BED3; context->Intermediate_Hash[1] = 0x84B430FC; context->Intermediate_Hash[2] = 0x6B8749CD; context->Intermediate_Hash[3] = 0xEBFE5FE5; context->Intermediate_Hash[4] = 0xD96E7393; } context->Length_Low = 512; return shaSuccess; } int SHA1Reset(SHA1Context *context) { if (!context) { return shaNull; } context->Length_Low = 0; context->Length_High = 0; context->Message_Block_Index = 0; context->Intermediate_Hash[0] = 0x67452301; context->Intermediate_Hash[1] = 0xEFCDAB89; context->Intermediate_Hash[2] = 0x98BADCFE; context->Intermediate_Hash[3] = 0x10325476; context->Intermediate_Hash[4] = 0xC3D2E1F0; context->Computed = 0; context->Corrupted = 0; return shaSuccess; } /* * SHA1Result * * Description: * This function will return the 160-bit message digest into the * Message_Digest array provided by the caller. * NOTE: The first octet of hash is stored in the 0th element, * the last octet of hash in the 19th element. * * Parameters: * context: [in/out] * The context to use to calculate the SHA-1 hash. * Message_Digest: [out] * Where the digest is returned. * * Returns: * sha Error Code. * */ int SHA1Result( SHA1Context *context, uint8_t Message_Digest[SHA1HashSize]) { int i; if (!context || !Message_Digest) { return shaNull; } if (context->Corrupted) { return context->Corrupted; } if (!context->Computed) { SHA1PadMessage(context); for(i=0; i<64; ++i) { /* message may be sensitive, clear it out */ context->Message_Block[i] = 0; } context->Length_Low = 0; /* and clear length */ context->Length_High = 0; context->Computed = 1; } for(i = 0; i < SHA1HashSize; ++i) { Message_Digest[i] = context->Intermediate_Hash[i>>2] >> 8 * ( 3 - ( i & 0x03 ) ); } return shaSuccess; } /* * SHA1Input * * Description: * This function accepts an array of octets as the next portion * of the message. * * Parameters: * context: [in/out] * The SHA context to update * message_array: [in] * An array of characters representing the next portion of * the message. * length: [in] * The length of the message in message_array * * Returns: * sha Error Code. * */ int SHA1Input( SHA1Context *context, const uint8_t *message_array, unsigned length) { if (!length) { return shaSuccess; } if (!context || !message_array) { return shaNull; } if (context->Computed) { context->Corrupted = shaStateError; return shaStateError; } if (context->Corrupted) { return context->Corrupted; } while(length-- && !context->Corrupted) { context->Message_Block[context->Message_Block_Index++] = (*message_array & 0xFF); context->Length_Low += 8; if (context->Length_Low == 0) { context->Length_High++; if (context->Length_High == 0) { /* Message is too long */ context->Corrupted = 1; } } if (context->Message_Block_Index == 64) { SHA1ProcessMessageBlock(context); } message_array++; } return shaSuccess; } /* * SHA1ProcessMessageBlock * * Description: * This function will process the next 512 bits of the message * stored in the Message_Block array. * * Parameters: * None. * * Returns: * Nothing. * * Comments: * Many of the variable names in this code, especially the * single character names, were used because those were the * names used in the publication. * * */ void SHA1ProcessMessageBlock(SHA1Context *context) { const uint32_t K[] = { /* Constants defined in SHA-1 */ 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 }; int t; /* Loop counter */ uint32_t temp; /* Temporary word value */ uint32_t W[80]; /* Word sequence */ uint32_t A, B, C, D, E; /* Word buffers */ /* * Initialize the first 16 words in the array W */ for(t = 0; t < 16; t++) { W[t] = context->Message_Block[t * 4] << 24; W[t] |= context->Message_Block[t * 4 + 1] << 16; W[t] |= context->Message_Block[t * 4 + 2] << 8; W[t] |= context->Message_Block[t * 4 + 3]; } for(t = 16; t < 80; t++) { W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); } A = context->Intermediate_Hash[0]; B = context->Intermediate_Hash[1]; C = context->Intermediate_Hash[2]; D = context->Intermediate_Hash[3]; E = context->Intermediate_Hash[4]; for(t = 0; t < 20; t++) { temp = SHA1CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0]; E = D; D = C; C = SHA1CircularShift(30,B); B = A; A = temp; } for(t = 20; t < 40; t++) { temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; E = D; D = C; C = SHA1CircularShift(30,B); B = A; A = temp; } for(t = 40; t < 60; t++) { temp = SHA1CircularShift(5,A) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; E = D; D = C; C = SHA1CircularShift(30,B); B = A; A = temp; } for(t = 60; t < 80; t++) { temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; E = D; D = C; C = SHA1CircularShift(30,B); B = A; A = temp; } context->Intermediate_Hash[0] += A; context->Intermediate_Hash[1] += B; context->Intermediate_Hash[2] += C; context->Intermediate_Hash[3] += D; context->Intermediate_Hash[4] += E; context->Message_Block_Index = 0; } /* * SHA1PadMessage * * Description: * According to the standard, the message must be padded to an even * 512 bits. The first padding bit must be a '1'. The last 64 * bits represent the length of the original message. All bits in * between should be 0. This function will pad the message * according to those rules by filling the Message_Block array * accordingly. It will also call the ProcessMessageBlock function * provided appropriately. When it returns, it can be assumed that * the message digest has been computed. * * Parameters: * context: [in/out] * The context to pad * ProcessMessageBlock: [in] * The appropriate SHA*ProcessMessageBlock function * Returns: * Nothing. * */ void SHA1PadMessage(SHA1Context *context) { /* * Check to see if the current message block is too small to hold * the initial padding bits and length. If so, we will pad the * block, process it, and then continue padding into a second * block. */ if (context->Message_Block_Index > 55) { context->Message_Block[context->Message_Block_Index++] = 0x80; while(context->Message_Block_Index < 64) { context->Message_Block[context->Message_Block_Index++] = 0; } SHA1ProcessMessageBlock(context); while(context->Message_Block_Index < 56) { context->Message_Block[context->Message_Block_Index++] = 0; } } else { context->Message_Block[context->Message_Block_Index++] = 0x80; while(context->Message_Block_Index < 56) { context->Message_Block[context->Message_Block_Index++] = 0; } } /* * Store the message length as the last 8 octets */ context->Message_Block[56] = context->Length_High >> 24; context->Message_Block[57] = context->Length_High >> 16; context->Message_Block[58] = context->Length_High >> 8; context->Message_Block[59] = context->Length_High; context->Message_Block[60] = context->Length_Low >> 24; context->Message_Block[61] = context->Length_Low >> 16; context->Message_Block[62] = context->Length_Low >> 8; context->Message_Block[63] = context->Length_Low; SHA1ProcessMessageBlock(context); } --- NEW FILE: sha1.h --- /* * sha1.h * * Description: * This is the header file for code which implements the Secure * Hashing Algorithm 1 as defined in FIPS PUB 180-1 published * April 17, 1995. * * Many of the variable names in this code, especially the * single character names, were used because those were the names * used in the publication. * * Please read the file sha1.c for more information. * */ #ifndef _SHA1_H_ #define _SHA1_H_ #include <stdint.h> /* * If you do not have the ISO standard stdint.h header file, then you * must typdef the following: * name meaning * uint32_t unsigned 32 bit integer * uint8_t unsigned 8 bit integer (i.e., unsigned char) * int_least16_t integer of >= 16 bits * */ #ifndef _SHA_enum_ #define _SHA_enum_ enum { shaSuccess = 0, shaNull, /* Null pointer parameter */ shaInputTooLong, /* input data too long */ shaStateError /* called Input after Result */ }; #endif #define SHA1HashSize 20 /* * This structure will hold context information for the SHA-1 * hashing operation */ typedef struct SHA1Context { uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */ uint32_t Length_Low; /* Message length in bits */ uint32_t Length_High; /* Message length in bits */ /* Index into message block array */ int_least16_t Message_Block_Index; uint8_t Message_Block[64]; /* 512-bit message blocks */ int Computed; /* Is the digest computed? */ int Corrupted; /* Is the message digest corrupted? */ } SHA1Context; /* * Function Prototypes */ int SHA1Reset(SHA1Context *); int SHA1Input( SHA1Context *, const uint8_t *, unsigned int); int SHA1Result( SHA1Context *, uint8_t Message_Digest[SHA1HashSize]); #endif /* _SHA1_H_ */ --- NEW FILE: xbox_vdbtool --- (This appears to be a binary file; contents omitted.) --- NEW FILE: xboxlib.c --- #include "xboxlib.h" int _strncmp(const char *sz1, const char *sz2, int nMax) { while((*sz1) && (*sz2) && nMax--) { if(*sz1 != *sz2) return (*sz1 - *sz2); sz1++; sz2++; } if(nMax==0) return 0; if((*sz1) || (*sz2)) return 0; return 0; // used up nMax } --- NEW FILE: xboxlib.h --- #ifndef _XBOXLIB_H_ #define _XBOXLIB_H_ int _strncmp(const char *sz1, const char *sz2, int nMax); #endif // _XBOXLIB_H_ |