#include #include #include #include #include #include #include #include #include #include "config.h" #include "hd24fs.h" #include "convertlib.h" #define VERSION "1.3 beta" #define _LARGE_FILES #define _FILE_OFFSET_BITS 64 #define FILE_OFFSET_BITS 64 #define LARGE_FILES #define LARGEFILE64_SOURCE #define SECTORSIZE 512 #define ARGHEADER "--header=" #ifdef DARWIN # define open64 open # define lseek64 lseek # define pread64 pread # define creat64 creat # define pwrite64 pwrite #endif #ifndef WINDOWS # include #endif string device; string headerfilename; __uint64 writeoffset; int force; int expertmode; int graphmode; int enable_graphmode; int disable_graphmode; // Check if a file exists bool fileexists (string* fname) { struct stat fi; if ((stat(fname->c_str(), &fi) != -1) && ((fi.st_mode & S_IFDIR) == 0)) { return true; } return false; } // Check if file handle is invalid bool isinvalidhandle(FSHANDLE handle) { #ifdef WINDOWS if (handle == FSHANDLE_INVALID) { return true; } #else if (handle == 0 || handle == FSHANDLE_INVALID) { return true; } #endif return false; } // Output a message for expert only features void expertmodemessage(string feature) { cout << feature <<" is only allowed in expert mode." << endl; } // Seek to a position in the drive void hd24seek(FSHANDLE devhd24, __uint64 seekpos) { #ifdef WINDOWS LARGE_INTEGER li; li.HighPart = seekpos >> 32; li.LowPart = seekpos % ((__uint64) 1 << 32); SetFilePointerEx(devhd24, li, NULL, FILE_BEGIN); #else lseek64(devhd24, seekpos, 0); #endif return; } // Calculate a 32-bit checksum for a block long unsigned int calcblockchecksum(hd24raw* rawdevice, unsigned long firstsector, unsigned long endsector) { long unsigned int checksum32 = 0; unsigned char origblock[5120]; for (unsigned long k = firstsector; k < endsector; k++) { rawdevice->readsectors(k, origblock, 1); for (unsigned long i = 0; i < SECTORSIZE; i += 4) { unsigned long num = Convert::getint32(origblock, i); int byte1 = num % 256; int byte2 = (num >> 8) % 256; int byte3 = (num >> 16) % 256; int byte4 = (num >> 24) % 256; num = byte4 + (byte3 << 8) + (byte2 << 16) + (byte1 << 24); checksum32 += num; } } return checksum32; } // Write to a sector long writesectors(FSHANDLE devhd24, unsigned long sectornum, unsigned char * buffer, int sectors) { int WRITESIZE = SECTORSIZE * sectors; // allows searching across sector boundaries hd24seek(devhd24, (__uint64) sectornum * 512); #ifdef WINDOWS DWORD dummy; long bytes = 0; if (WriteFile(devhd24, buffer, WRITESIZE, &dummy, NULL)) { bytes = WRITESIZE; }; #else long bytes = pwrite64(devhd24, buffer, WRITESIZE, (__uint64) sectornum * 512); #endif return bytes; } void writetofile(hd24raw* rawdevice,string filename, long firstsector,long endsector) { int i; unsigned char bootblock[5120]; #if defined(LINUX) || defined(DARWIN) FSHANDLE handle=creat64(filename.c_str(),O_WRONLY); #endif #ifdef WINDOWS FSHANDLE handle=CreateFile(filename.c_str(),GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); if (isinvalidhandle(handle)) { handle=CreateFile(filename.c_str(),GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); } #endif if (isinvalidhandle(handle)) { cout << "Cannot open file "<readsectors(i,bootblock,1); #if defined(LINUX) || defined(DARWIN) __uint64 targetoff=i; targetoff-=firstsector; targetoff+=writeoffset; targetoff*=512; ssize_t byteswritten=pwrite64(handle,bootblock,512,targetoff); #endif #ifdef WINDOWS //DWORD dummy; //long bytes=0; __uint64 targetoff=i; targetoff-=firstsector; targetoff+=writeoffset; __uint64 byteswritten=writesectors(handle,targetoff,bootblock,1); #endif if (byteswritten==0) { cout << "Wrote 0 bytes to file. Access denied?" << endl; #if defined(LINUX) || defined(DARWIN) close (handle); #endif #ifdef WNDOWS CloseHandle(handle); #endif return; } if ((i%1000)==0) { string* x=Convert::int64tohex((__uint64)i*0x200); cout << "Write offset " << *x << "\r"; if (x!=NULL) { delete x; x=NULL; } } } #if defined(LINUX) || defined(DARWIN) close (handle); #endif #ifdef WINDOWS CloseHandle(handle); #endif return; } string getbinstr(string tofind) { if (tofind.substr(0,1)=="'") { // find literal string tofind=tofind.substr(1,tofind.length()-2); cout << "Find string " << tofind << endl; } else { string binstr=""; string tmp=""; tofind+=" "; unsigned int i; for (i=0;iL " << endl; return 0; } if ( (editstr.substr(0,1)==" ") ) { editstr=editstr.substr(1,editstr.length()-1); while ( (editstr.substr(0,1)!=" ") &&(editstr!="")) { strtopos+=editstr.substr(0,1); editstr=editstr.substr(1,editstr.length()-1); } } else { cout << "Syntax: mL " << endl; return 0; } cout << " strfrompos=" << strfrompos << endl; cout << " strmovelen=" << strmovelen << endl; cout << " strtopos=" << strtopos << endl; long frompos=(Convert::hex2long(strfrompos)%SECTORSIZE); long movelen=(Convert::hex2long(strmovelen)%SECTORSIZE); long topos=(Convert::hex2long(strtopos)%SECTORSIZE); cout << " pos=" << frompos << endl; cout << " movelen=" << movelen << endl; cout << " movepos=" << topos << endl; void* x=malloc(movelen); memcpy(x,bootblock+frompos,movelen); memcpy(bootblock+topos,x,movelen); free (x); return 0; } long editbytes(unsigned char* bootblock,string editstr) { string strpos=""; while ((editstr.substr(0,1)!=" ") &&(editstr!="")) { strpos+=editstr.substr(0,1); editstr=editstr.substr(1,editstr.length()-1); } if (editstr!="") { editstr=editstr.substr(1,editstr.length()-1); } string binstr=getbinstr(editstr); long pos=(Convert::hex2long(strpos)%SECTORSIZE); cout << "binstr=" << binstr << " " << pos << endl; memcpy(bootblock+pos,binstr.c_str(),binstr.length()); return 0; } void compareblock(hd24raw* rawdevice,unsigned long firstsector,unsigned long endsector,long current) { unsigned int i; unsigned int j; unsigned int k; unsigned char origblock[5120]; unsigned char destblock[5120]; string* startoff=Convert::int64tohex((__uint64)firstsector*512); string* endoff=Convert::int64tohex((__uint64)endsector*512-1); cout << "Compare range from offset "<< *startoff << " to offset " << *endoff <readsectors(k,origblock,1); rawdevice->readsectors(k-firstsector+current,destblock,1); for (i=0;ireadsectors(i,bootblock,2); if ((i%0x1000)==0) { string* curroff=Convert::int64tohex((__uint64)i*0x200); cout << "Scan offset " << *curroff << "\r"; delete curroff; curroff=NULL; } /* check if string found. */ int j=0; for (j=0;j<512;j++) { if (memcmp((const void *)&bootblock[j],(const void *)tofind.c_str(),(size_t)tofind.length())==0) { string* foundoff=Convert::int64tohex((__uint64)i*512+j); cout << endl << "Found on offset " << *foundoff << endl; delete foundoff; foundoff=NULL; return i; } } } cout << endl << "Not found." << endl; return current; } void fstfix(unsigned char * bootblock,int fixsize) { for (int i=0;i no translate if (!fsys->isOpen()) { cout << "Cannot open hd24 device." << endl; delete fsys; fsys=NULL; if (rawdevice!=NULL) { delete rawdevice; rawdevice=NULL; } return 1; } if (headerfilename!="") { if (!(fsys->useheaderfile(headerfilename))) { cout << "Couldn't load header file "<getdevicename() << endl; /* Initialization */ unsigned char bootblock[5120]; unsigned long sectornum=0; int nodump=0; int noread=0; int writesec=0; unsigned long blockstart=0; unsigned long blockend=0; writeoffset=0; unsigned long checksum=0; string userinput; string lastsearch=""; if (expertmode==1) { cout << "Expert mode enabled. " << endl; cout << "Warning! Disk writes are enabled." << endl; cout << "You now have the capability to destroy." << endl; cout << "Proceed with extreme caution!" << endl; } try{ /* try block is intended to make sure hd24 device is closed on exit*/ string filename="outfile.dmp"; do { int i; int j; if (enable_graphmode==1) { cout << "Enabling graph mode." << endl; graphmode=1; enable_graphmode=0; } if (disable_graphmode==1) { cout << "Disabling graph mode." << endl; graphmode=0; disable_graphmode=0; } if (writesec==1) { rawdevice->writesectors(sectornum,bootblock,1); writesec=0; } if (noread==0) { rawdevice->readsectors(sectornum,bootblock,1); } noread=0; long offset=sectornum*512; if (nodump==0) { cout << "Sector " << *Convert::int32tohex((long)sectornum) << endl; for (i=0;i0) { sectornum--; } else { sectornum=0; } continue; } if (userinput.substr(0,1)=="-") { long sectoadd=Convert::hex2long(userinput.substr(1,userinput.length()-1)); if ((__uint32)sectoadd>(__uint32)sectornum) { sectornum=0; } else { sectornum-=sectoadd; } continue; } if (userinput==".") { noread=1; continue; } if ((userinput.substr(0,1)=="?")||(userinput=="help")) { cout << "Help for hd24hexview " << VERSION << endl; cout << "==============================" << endl; cout << "General:" < increment n sectors, then dump sector"< decrement n sectors, then dump sector"< dump sector " << endl; cout << " d- dump sector totalnumberofsectors-" << endl; cout << " d re-read current sector from disk" << endl; cout << " ml " << endl; cout << " move bytes from offset to " << endl; cout << " o dump sector that contains offset " << endl; cout << " s x y.. scan marked block for byte sequence x y ..." << endl; cout << " s'...' scan marked block for exact string" << endl; cout << " e

xx edit byte sequence at pos p to xxxx " << endl; cout << " e

'x' edit pos p to string 'x'" << endl; cout << endl; cout << "Block commands:" << endl; cout << " bb mark start of sector as block beginning" << endl; cout << " be mark end of sector as block end" << endl; cout << " bc block clear" << endl; cout << " diff compare marked block with current" << endl; cout << " p paste first sector of marked block to current sector" << endl; cout << endl; cout << "File commands:" << endl; cout << " n set filename to xx" << endl; cout << " n clear filename" << endl; cout << " w write marked block to named file/device" << endl; cout << " wo clear sector write offset for file/device write" << endl; cout << " wo set write offset to xx sectors" << endl; cout << " ws write back current edited sector to disk" << endl; cout << "HD24 specific features:" << endl; cout << " fix reverse byte ordering of 32 bit words" << endl; cout << " for better human readability" << endl; cout << " cs Calc checksum of selected block" << endl; cout << " scs Set zero checksum of selected block" << endl; nodump=1; // inhibit viewing the sector after this command. continue; } if (userinput.substr(0,2)=="bc") { blockstart=0; blockend=0; cout << "Block selection cleared." << endl; nodump=1; // inhibit viewing the sector after this command. continue; } if (userinput.substr(0,2)=="bb") { cout << "Block start set." << endl; nodump=1; // inhibit viewing the sector after this command. blockstart=sectornum; continue; } if (userinput.substr(0,2)=="be") { cout << "Block end set." << endl; /* dump is startsector..endsector, * excl. end sector. number of bytes to dump= * (blockend-blockstart)*512 */ nodump=1; // inhibit viewing the sector after this command. blockend=sectornum+1; continue; } if (userinput.substr(0,2)=="cs") { checksum=calcblockchecksum(rawdevice,blockstart,blockend); cout << "Block checksum is " << checksum << endl; nodump=1; noread=1; continue; } if (userinput.substr(0,3)=="scs") { if (blockend-1!=sectornum) { cout << "Current sector must be block end." << endl; nodump=1; noread=1; continue; } unsigned long checksum=calcblockchecksum(rawdevice,blockstart,blockend); unsigned long oldchecksum=0; oldchecksum+=((unsigned char)(bootblock[511])); oldchecksum=oldchecksum <<8; oldchecksum+=((unsigned char)(bootblock[510])); oldchecksum=oldchecksum <<8; oldchecksum+=((unsigned char)(bootblock[509])); oldchecksum=oldchecksum <<8; oldchecksum+=((unsigned char)(bootblock[508])); oldchecksum-=checksum; bootblock[508]=oldchecksum%256; oldchecksum=oldchecksum >> 8; bootblock[509]=oldchecksum%256; oldchecksum=oldchecksum >> 8; bootblock[510]=oldchecksum%256; oldchecksum=oldchecksum >> 8; bootblock[511]=oldchecksum%256; oldchecksum=oldchecksum >> 8; noread=1; continue; } if (userinput.substr(0,4)=="diff") { nodump=1; // inhibit viewing the sector after this command. if (blockend==blockstart) { cout << "Please set block start/end first." << endl; continue; } compareblock(rawdevice,blockstart,blockend,sectornum); continue; } if (userinput.substr(0,1)=="s") { if (userinput=="s") { userinput+=lastsearch; } else { lastsearch=userinput.substr(1,userinput.length()-1); } if (blockend==blockstart) { sectornum=scanforblock(rawdevice,lastsearch,0,0xffffffff,sectornum); } else { sectornum=scanforblock(rawdevice,lastsearch,blockstart,blockend,sectornum); } continue; } if (userinput=="version") { cout << VERSION << endl; nodump=1; // inhibit viewing the sector after this command. noread=1; continue; } if (userinput.substr(0,1)=="p") { //paste if (blockend==blockstart) { nodump=1; cout << "Mark a block first." << endl; continue; } rawdevice->readsectors(blockstart,bootblock,1); noread=1; continue; } if (userinput.substr(0,1)=="e") { string editstr=userinput.substr(1,userinput.length()-1); editbytes(bootblock,editstr); noread=1; continue; } if (userinput.substr(0,1)=="m") { string editstr=userinput.substr(1,userinput.length()-1); movebytes(bootblock,editstr); noread=1; continue; } if (userinput=="d") { continue; } if (userinput.substr(0,2)=="d-") { // if we have 10 sectors (0..9), last one is d-1=sector 9 // so sector num is total number of secs - negnum sectornum=rawdevice->getlastsectornum()-Convert::hex2long(userinput.substr(2,userinput.length()-2))+1; continue; } if (userinput.substr(0,1)=="d") { sectornum=Convert::hex2long(userinput.substr(1,userinput.length()-1)); continue; } if (userinput.substr(0,1)=="o") { long offset=Convert::hex2long(userinput.substr(1,userinput.length()-1)); offset-=(offset%512); sectornum=offset/512; } if (userinput=="fix") { fstfix(bootblock,512); noread=1; continue; } if (userinput.substr(0,1)=="n") { int dangerousname=0; if (userinput.substr(1,4)=="\\\\.\\") { dangerousname=1; } if (userinput.substr(1,5)=="/dev/") { dangerousname=1; } if (userinput.substr(1,4)=="//./") { dangerousname=1; } if (dangerousname==1) { if (expertmode==0) { expertmodemessage("Writing to devices"); } else { filename=userinput.substr(1,userinput.length()-1); cout << "OK, setting output file to device " << filename << endl; cout << "Please take your time to make sure this is really the correct drive."<getnextfreesector(0xFFFFFFFF)) << endl; cout << rawdevice->getnextfreesector(0xFFFFFFFF) << endl; } if (userinput=="commit") { if (expertmode==1) { cout << "Commit FS to disk." << endl; fsys->commit(); } } } while (userinput!="q"); } catch (string e) { cout << "Exiting because of an unexpected error." << endl; delete rawdevice; rawdevice=NULL; delete fsys; fsys=NULL; return 1; } delete rawdevice; rawdevice=NULL; delete fsys; fsys=NULL; return 0; }