diff options
Diffstat (limited to 'src/magic_block_scan.c')
-rw-r--r-- | src/magic_block_scan.c | 877 |
1 files changed, 748 insertions, 129 deletions
diff --git a/src/magic_block_scan.c b/src/magic_block_scan.c index 5b72a31..3eef1ac 100644 --- a/src/magic_block_scan.c +++ b/src/magic_block_scan.c @@ -30,12 +30,12 @@ #include "inode.h" #include "magic.h" - +#include "extent_db.h" //#define DEBUG_MAGIC_SCAN -extern ext2_filsys current_fs ; -ext2fs_block_bitmap d_bmap = NULL ; +extern ext2_filsys current_fs ; +ext2fs_block_bitmap d_bmap = NULL ; static __u32 get_block_len(unsigned char *buf){ @@ -49,17 +49,61 @@ static __u32 get_block_len(unsigned char *buf){ static struct found_data_t* free_file_data(struct found_data_t* old){ + int tmp; + if(old->inode) free(old->inode); if(old->scan_result) free(old->scan_result); if(old->name) free(old->name); + if(old->priv){ + old->func(NULL,&tmp,0,4,old); + old->priv = NULL; + } free(old); - old = NULL; - return old; + return NULL; +} + + + + +static struct found_data_t* copy_file_data(struct found_data_t* old){ + static struct found_data_t* new = NULL; + int str_len = strlen(old->scan_result)+1; + int name_len = strlen(old->name)+1; + +//FIXME private + new = malloc(sizeof(struct found_data_t)); + if (!new) return NULL; + memcpy(new,old,sizeof(struct found_data_t)); + new->scan_result = malloc(str_len); + new->name = malloc(name_len); + new->inode = new_inode(); + if(old->priv){ + new->priv = malloc(old->priv_len); + if (new->priv) + memcpy(new->priv,old->priv,old->priv_len); + else + new->priv_len = 0; + } + if((!new->scan_result) || (!new->name) || (!new->inode)){ + if (new->priv){ + free (new->priv); + new->priv = NULL; + } + new = free_file_data(new); + fprintf(stderr,"ERROR; while allocate memory for found copy file struct\n"); + } + else{ + memcpy(new->scan_result,old->scan_result,str_len); + memcpy(new->name,old->name,name_len); + memcpy(new->inode,old->inode,128); + } + return new; } -static struct found_data_t* new_file_data(blk_t blk,__u32 scan,char *magic_buf, unsigned char* buf, __u32 *f){ + +static struct found_data_t* new_file_data(blk_t blk,__u32 scan,char *magic_buf, unsigned char* buf, __u32 *f, __u32 buf_length){ struct found_data_t *new; int str_len; __u32 name_len; @@ -72,11 +116,16 @@ static struct found_data_t* new_file_data(blk_t blk,__u32 scan,char *magic_buf, new->first = blk; new->last = blk; - new->leng = 0; + new->buf_length = buf_length; + new->next_offset = 0; + new->last_match_blk = 0; + new->scantype = H_F_Carving; new->scan = scan; new->size = 0; new->h_size = 0; + new->priv_len = 0; new->func = NULL; + new->priv = NULL; if ( ident_file(new,&scan,magic_buf,buf)){ new->type = scan; str_len = strlen(magic_buf) + 1; @@ -103,8 +152,12 @@ static struct found_data_t* new_file_data(blk_t blk,__u32 scan,char *magic_buf, get_file_property(new); new->func(buf,&name_len,scan,2,new); } + if ((!new->func) || (!new->first)) { + *f = 0; + return free_file_data(new); + } } - *f++; +*f++; return new; } @@ -113,9 +166,8 @@ return new; static struct found_data_t* recover_file_data(char *des_dir, struct found_data_t* this, __u32 *follow){ recover_file(des_dir,"MAGIC-3",this->name,(struct ext2_inode*)this->inode, 0 , 1); - free_file_data(this); *follow = 0; - return NULL; + return free_file_data(this); } @@ -135,10 +187,7 @@ static struct found_data_t* forget_file_data(struct found_data_t* this, __u32 *p static __u32 add_file_data(struct found_data_t* this, blk_t blk, __u32 scan ,__u32 *f){ - __u32 retval = 0; - - if (inode_add_block(this->inode , blk , current_fs->blocksize)){ - this->leng++; + if (inode_add_block(this->inode , blk )){ this->last = blk; (*f)++ ; } @@ -159,6 +208,7 @@ static int file_data_correct_size(struct found_data_t* this, int size){ this->inode->i_size = i_size & 0xffffffff ; this->inode->i_size_high = i_size >> 32 ; if ((i_size <= (12 * current_fs->blocksize))&&(!(this->inode->i_flags & EXT4_EXTENTS_FL))) { + //correcting small ext3 inodes if(this->inode->i_block[EXT2_IND_BLOCK]){ this->inode->i_block[EXT2_IND_BLOCK] = 0; this->inode->i_block[EXT2_DIND_BLOCK] = 0; @@ -168,9 +218,7 @@ static int file_data_correct_size(struct found_data_t* this, int size){ while (ref < EXT2_IND_BLOCK){ this->inode->i_block[ref] = 0; ref++; - } - - + } } } return flag; @@ -187,29 +235,16 @@ static int check_file_data_end(struct found_data_t* this,unsigned char *buf, __u if (ret) ret = file_data_correct_size(this,size); - return ret; + return (mask & FORCE_RECOVER) ? 1 : ret ; } -//????? -static int check_data_passage(char *a_buf, unsigned char *b_buf){ - int i, blocksize; - int sum[4][2]; - - - -} - - - static int check_file_data_possible(struct found_data_t* this, __u32 scan ,unsigned char *buf){ - int ret = 0; int size ; size = (scan & M_SIZE ); - ret = this->func(buf, &size ,scan ,1 , this); - return ret; + return this->func(buf, &size ,scan ,1 , this); } @@ -230,7 +265,6 @@ static int check_meta3_block(unsigned char *block_buf, blk_t blk, __u32 size, in (((flag == 1) && (i == (size -4)) && (i>4))||(!ext2fs_test_block_bitmap(bmap,block))) || (flag == 2) ) ){ - if (i) { //work not by sparse file for (j = i - 4 ; j >= 0 ;j -= 4){ if (block == ext2fs_le32_to_cpu(*((blk_t*)(block_buf+j)))) @@ -241,7 +275,6 @@ static int check_meta3_block(unsigned char *block_buf, blk_t blk, __u32 size, in if (block == blk+1) return 1; } - } else return 0; @@ -321,6 +354,8 @@ return ret; static int check_meta4_block(unsigned char *block_buf, blk_t blk, __u32 size){ +return (ext2fs_extent_header_verify((void*)block_buf, current_fs->blocksize)) ? 0 : 1; +/* __u16 *p_h16; __u16 h16; @@ -333,16 +368,18 @@ static int check_meta4_block(unsigned char *block_buf, blk_t blk, __u32 size){ return 0; if ((!h16) || (h16 > ext2fs_le16_to_cpu(*p_h16))) return 0; - return 1 ; + return 1 ;*/ } static int check_dir_block(unsigned char *block_buf, blk_t blk, __u32 size){ - struct ext2_dir_entry_2 *dir_entry; - ext2_ino_t inode_nr; - __u16 len; + struct ext2_dir_entry_2 *dir_entry; + ext2_ino_t inode_nr; + __u16 len; + __u16 p_len; + int i; dir_entry = (struct ext2_dir_entry_2*)block_buf; @@ -350,18 +387,27 @@ static int check_dir_block(unsigned char *block_buf, blk_t blk, __u32 size){ if ((inode_nr && (inode_nr < EXT2_GOOD_OLD_FIRST_INO)) || (inode_nr > current_fs->super->s_inodes_count)) return 0; len = ext2fs_le16_to_cpu(dir_entry->rec_len); - if ((len < 8) || (len % 4) || (len > current_fs->blocksize) ||(len < (((unsigned)dir_entry->name_len + 11) & ~3 ))) + if ((len < 8) || (len % 4) || (len> current_fs->blocksize) ||(len < (((unsigned)dir_entry->name_len + 11) & ~3 ))||(!dir_entry->name_len) || (! dir_entry->file_type) || (dir_entry->file_type & 0xf8)) return 0; - if ((dir_entry->name_len & 0x01) && dir_entry->name[(unsigned)dir_entry->name_len]) + + for (i=0; i<dir_entry->name_len;i++) + if(!dir_entry->name[i]) + return 0; + if((dir_entry->name_len == 1) && ((dir_entry->name[0] < 33) || (dir_entry->name[0] > 126))) return 0; +loop: + p_len =len; if (len < current_fs->blocksize - 12){ - dir_entry = (struct ext2_dir_entry_2*) (block_buf + len); + dir_entry = (struct ext2_dir_entry_2*) (((void*)dir_entry) + len); len = ext2fs_le16_to_cpu(dir_entry->rec_len); - if ((len < 8) || (len % 4) || (len > current_fs->blocksize) ||(len < (((unsigned)dir_entry->name_len + 11) & ~3 ))) + if ((len < 8) || (len % 4) || ((len+p_len) > current_fs->blocksize) ||(len < (((unsigned)dir_entry->name_len + 11) & ~3 ))||(!dir_entry->name_len) || (! dir_entry->file_type) || (dir_entry->file_type & 0xf8) ) return 0; if ((dir_entry->name_len & 0x01) && dir_entry->name[(unsigned)dir_entry->name_len]) - return 0; - } + goto loop; + + }else + if (block_buf[current_fs->blocksize -1]) + return 0; return 1; } @@ -391,11 +437,14 @@ static int check_acl_block(unsigned char *block_buf, blk_t blk, __u32 size){ -static int add_ext4_extent_idx_data(struct found_data_t* this, void *buf, blk_t blk){ - int ret; - ret = inode_add_extent(this->inode ,blk, buf, 1); - this->last = get_last_block_ext4(this->inode); - return ret; +static int add_ext4_extent_idx_data(struct found_data_t* this, struct extent_area* ea){ + return inode_add_extent(this->inode ,ea, &(this->last), 1); +} + + + +static int add_ext4_extent_data(struct found_data_t* this, struct extent_area* ea){ + return inode_add_extent(this->inode ,ea, &(this->last), 0); } @@ -410,6 +459,7 @@ static int add_ext3_file_meta_data(struct found_data_t* this, unsigned char *buf if (check_indirect_meta3(buf)){ ret = inode_add_meta_block(this->inode , blk, &last_data, &next_meta, buf ); this->last = last_data; + this->scantype |= DATA_METABLOCK; } if (ret && (next_meta > 10 && (ext2fs_test_block_bitmap ( d_bmap, next_meta) && (! ext2fs_test_block_bitmap( bmap, next_meta))))){ @@ -430,22 +480,19 @@ static int add_ext3_file_meta_data(struct found_data_t* this, unsigned char *buf ret = inode_add_meta_block(this->inode , meta, &last_data, &next_meta, buf ); this->last = last_data; } - } - } - } return ret ; } - // skip not of interest blocks : return 1 if skiped static int skip_block(blk_t *p_blk ,struct ext2fs_struct_loc_generic_bitmap *ds_bmap ){ struct ext2fs_struct_loc_generic_bitmap *p_bmap; blk_t o_blk; int flag = 0; + int diff = (current_fs->blocksize == 1024)?1:0; o_blk = (*p_blk) >> 3; p_bmap = (struct ext2fs_struct_loc_generic_bitmap *) bmap; @@ -454,13 +501,14 @@ static int skip_block(blk_t *p_blk ,struct ext2fs_struct_loc_generic_bitmap *ds_ o_blk ++; flag = 1; } - *p_blk = o_blk << 3 ; + *p_blk = (o_blk << 3) + diff ; return flag; } //magic scanner +//FIXME static int magic_check_block(unsigned char* buf,magic_t cookie , magic_t cookie_f, char *magic_buf, __u32 size, blk_t blk, int deep){ int count = current_fs->blocksize -1 ; int *i , len; @@ -468,7 +516,9 @@ static int magic_check_block(unsigned char* buf,magic_t cookie , magic_t cookie_ char *p_search; __u32 retval = 0; char token[20]; - + + memset(magic_buf,0,100); //FIXME + memset(text,0,100); while ((count >= 0) && (*(buf+count) == 0)) count-- ; if (ext2fs_le32_to_cpu(*(blk_t*)buf) == blk +1){ if (check_meta3_block(buf, blk, count+1, 0)){ @@ -477,12 +527,20 @@ static int magic_check_block(unsigned char* buf,magic_t cookie , magic_t cookie_ } } - strncpy(text,magic_buffer(cookie_f,buf , size),60); - strncpy(magic_buf, magic_buffer(cookie , buf , size),60); -/*#ifdef DEBUG_MAGIC_SCAN - printf("Scan Result : %s %d\n", magic_buf , count+1) ; - printf("RESULT : %s \n",text); -#endif */ + if (size > current_fs->blocksize){ + strncpy(text,magic_buffer(cookie_f, buf, 512),60); + if ((!strncmp(text,"data",4))|| (!strncmp(buf,"ID3",3))){ + strncpy(text,magic_buffer(cookie_f,buf , size),60); + strncpy(magic_buf, magic_buffer(cookie , buf , size),60); + } + else{ + strncpy(magic_buf, magic_buffer(cookie , buf , 512),60); + } + } + else{ + strncpy(text,magic_buffer(cookie_f,buf , size),60); + strncpy(magic_buf, magic_buffer(cookie , buf , size),60); + } if (!strncmp(text,"data",4)){ if (count == -1) { @@ -490,24 +548,59 @@ static int magic_check_block(unsigned char* buf,magic_t cookie , magic_t cookie_ goto out; } } + + if((strstr(magic_buf,"text/")) || (strstr(magic_buf,"application/") && (strstr(text,"text")))){ + retval |= M_TXT ; + if (deep && count && (count > 60))// current_fs->blocksize)) + strncpy(magic_buf, magic_buffer(cookie , buf , count-1),60); + } + + if ((strstr(magic_buf,"text/plain"))||(strstr(magic_buf,"text/html"))){ + if (deep && (count > 250) && (!strncmp(buf,"From ",5))){ + p_search = buf + 6; + for (len = 0; (len < (count -7)) ; len++){ + if( *(p_search++) == 0x40) + break; + } + for (;len<(count -7); len++){ + if( *(p_search++) == 0x0a) + break; + } + if ((len < (count - 180)) && ((!strncmp(p_search,"From:",5))||(!strncmp(p_search,"Return-Path:",12)))){ + strncpy(magic_buf,"message/rfc822",15); + retval = M_TXT | M_MESSAGE | M_CLASS_1 ; + goto out; + } + } + if(!(strstr(magic_buf,"text/html"))){ + if(deep && (count < (current_fs->blocksize -2))) { + p_search = buf + 6; + for (len = 0; len < 15 ; len++) + if( *(p_search++) == 0x20) + break; + if (len < 15){ + retval = M_TXT | M_CLASS_2 ; + goto out; + } + } +//FIXME + retval |= (M_DATA | M_TXT) ; + goto out; + } + } + if (strstr(magic_buf,"application/vnd.oasis.opendocument")){ retval |= (M_APPLI | M_BINARY | M_CLASS_1); goto out; } - if((strstr(magic_buf,"text/")) || (strstr(magic_buf,"application/") && (strstr(text,"text")))){ - retval |= M_TXT ; - if (deep && count && (count < current_fs->blocksize)) - strncpy(magic_buf, magic_buffer(cookie , buf , count+1),60); - } - if (strstr(magic_buf,"charset=binary")){ retval |= M_BINARY ; } //FIXME test: catch of properties from file-5.04 if ((retval & M_TXT) && - ((retval & M_BINARY) || (strstr(magic_buf,"charset=unknown-8bit") && (count > 8)) || + ((retval & M_BINARY) ||// (strstr(magic_buf,"charset=unknown-8bit") && (count > 8)) || (strstr(text,"very long lines, with no")))){ retval |= M_DATA; @@ -518,12 +611,6 @@ static int magic_check_block(unsigned char* buf,magic_t cookie , magic_t cookie_ } } -/* -//FIXME only for test -if ((strstr(magic_buf,"application/octet-stream")) && (!(strncmp(text,"text",4)))) - printf("application/octet-stream + text in BlockNR; %ul\n",blk); -*/ - if ((retval & M_DATA) || (*(buf+7) < EXT2_FT_MAX) || (count < 32) ) { if (check_meta4_block(buf, blk, count+1)){ retval = M_EXT4_META ; @@ -566,12 +653,12 @@ if ((strstr(magic_buf,"application/octet-stream")) && (!(strncmp(text,"text",4)) } if (strstr(magic_buf,"application/octet-stream")){ - char searchstr[] = "7-zip cpio CD-ROM MPEG 9660 Targa Kernel boot SQLite OpenOffice.org VMWare3 VMware4 JPEG ART PCX IFF DIF RIFF ATSC ScreamTracker "; + char searchstr[] = "7-zip cpio CD-ROM MPEG 9660 Targa Kernel boot SQLite OpenOffice.org VMWare3 VMware4 JPEG ART PCX IFF DIF RIFF ATSC ScreamTracker matroska LZMA Audio=Visual Sample=Vision ISO=Media ext2 ext3 ext4 LUKS "; p_search = searchstr; while (*p_search){ len=0; while((*p_search) != 0x20){ - token[len] = *p_search; + token[len] = ((*p_search)==0x3d)? 0x20 : (*p_search); p_search++; len++; } @@ -592,10 +679,12 @@ if ((strstr(magic_buf,"application/octet-stream")) && (!(strncmp(text,"text",4)) if (strstr(magic_buf,"x-tar")) retval |= ( M_APPLI | M_TAR | M_CLASS_1) ; else{ - if(strstr(magic_buf,"x-elc") || strstr(magic_buf,"keyring") || strstr(magic_buf,"x-arc")) + if((!strstr(magic_buf,"x-archive")) &&((strstr(magic_buf,"x-elc") || strstr(magic_buf,"keyring") || strstr(magic_buf,"x-arc")||strstr(magic_buf,"keystore")||strstr(magic_buf,"x-123")|| + strstr(magic_buf,"fontobject")))){ //FIXME fontobject retval = M_DATA; + } else { - if (strstr(magic_buf,"encrypted") || strstr(magic_buf,"x-tex-tfm")) + if (strstr(magic_buf,"encrypted") || strstr(magic_buf,"x-tex-tfm") || strstr(magic_buf,"x-compress")) retval |= ( M_APPLI | M_CLASS_2 ); else retval |= ( M_APPLI | M_CLASS_1 ); @@ -662,7 +751,6 @@ out: #endif retval |= (count+1); - return retval; } @@ -681,12 +769,28 @@ return file_data; } -static int get_range(blk_t* p_blk ,struct ext2fs_struct_loc_generic_bitmap *ds_bmap, unsigned char* buf){ + +static __u32 check_next_border(struct ext2fs_struct_loc_generic_bitmap *ds_bmap, blk_t blk, __u32 count){ + __u32 ret = 0; + __u32 i = 0; + + while ((i < count) && (! ret) && ((blk + i) < ds_bmap->end)){ + ret = (ext2fs_test_block_bitmap(d_bmap, blk + i) && (! ext2fs_test_block_bitmap(bmap, blk +i)))? 0 :1 ; + i++; + } + return (ret) ? i-1 : 0 ; +} + + + +static int get_range(blk_t* p_blk ,struct ext2fs_struct_loc_generic_bitmap *ds_bmap, unsigned char* buf, int *flag){ blk_t begin; blk_t end; int count=1; + int diff = (current_fs->blocksize == 1024)?1:0; + for (begin = *p_blk; begin <= ds_bmap->end ; begin++){ - if((!(begin & 0x7)) && skip_block(&begin, ds_bmap)){ + if((!((begin-diff) & 0x7)) && skip_block(&begin, ds_bmap)){ #ifdef DEBUG_MAGIC_SCAN printf("jump to %lu \n",begin); #endif @@ -719,7 +823,9 @@ static int get_range(blk_t* p_blk ,struct ext2fs_struct_loc_generic_bitmap *ds_b } if (count && count < MAX_RANGE){ memset(buf+(count * current_fs->blocksize), 255, current_fs->blocksize); - } + *flag = 1; + }else + *flag = (ext2fs_test_block_bitmap(d_bmap, end+1) && (! ext2fs_test_block_bitmap( bmap, end+1)))? 0 :1 ; return count; } @@ -731,9 +837,10 @@ static int get_full_range(blk_t* p_blk ,struct ext2fs_struct_loc_generic_bitmap int count=0; int i; errcode_t x; + int diff = (current_fs->blocksize == 1024)?1:0; for (begin = *p_blk; begin <= ds_bmap->end ; begin++){ - if((!(begin & 0x7)) && skip_block(&begin, ds_bmap)){ + if((!((begin - diff) & 0x7)) && skip_block(&begin, ds_bmap)){ #ifdef DEBUG_MAGIC_SCAN printf("jump to %lu \n",begin); #endif @@ -786,6 +893,59 @@ return count-1; } +//FIXME +//Attention : Changes have a very strong effect of the magic-fuction result +static int check_plain_passing(unsigned char * buf){ + int ret = 0; + unsigned char *last = buf-1; + unsigned char *next = buf; + int i,j, count1,count2; + if ((!(*last)) || (!(buf[current_fs->blocksize-1]))) + return 0; //NULL at end + last = buf -32; + count1 = count2 = 0; + for (i = 0; i< 32; i++){ + for (j = 0; j<32; j++){ + if (last[i] == next[j]){ + count1++; + break; + } + } + for (j = 0; j<32; j++){ + if (next[i] == last[j]){ + count2++; + break; + } + + } + } + if ((count1 > 7 ) && (count2 > 7 )) + ret = 1; //many duplicate + + + count1 = count2 = 0; + for (i = 0; i< 31; i++){ + if( last[i] == last[i+1]) count1++; + if( next[i] == next[i+1]) count2++; + } + if ((count1 > 10) && (count2 > 10)) + ret += 2; //many repetitions + + + count1 = count2 = 0; + for (i = 0; i< 31; i++){ + for (j = i+1; j<32; j++){ + if (last[i] == last[j]) count1++; + if (next[i] == next[j]) count2++; + } + } + if ((count1 < 5) && (count2 < 5)) + ret += 4; //very different + + return ret; +} + + static blk_t block_backward(blk_t blk , int count){ int i=count; @@ -799,8 +959,8 @@ static blk_t block_backward(blk_t blk , int count){ - //main of the magic_scan_engine for ext3 +//FIXME Disabled (not tested and can't work by version) int magic_block_scan3(char* des_dir, __u32 t_after){ magic_t cookie = 0; magic_t cookie_f = 0; @@ -815,7 +975,7 @@ unsigned char *v_buf = NULL; unsigned char *buf ; char *magic_buf = NULL; unsigned char *tmp_buf = NULL; -int blocksize, ds_retval,count,i,ret; +int blocksize, ds_retval,count,i,ret,dummy; __u32 scan,follow, size; @@ -837,7 +997,7 @@ if ((! v_buf) || (! magic_buf) || (! tmp_buf)){ fprintf(stderr,"ERROR: can't allocate memory\n"); goto errout; } - +memset(magic_buf,0,100); ds_retval = init_block_bitmap_list(&d_bmap, t_after); while (ds_retval){ ds_retval = next_block_bitmap(d_bmap); @@ -848,8 +1008,8 @@ while (ds_retval){ ds_bmap = (struct ext2fs_struct_loc_generic_bitmap *) d_bmap; count = 0; - blk[0] = 0; - count = get_range(blk ,ds_bmap, buf); + blk[0] = 1; + count = get_range(blk ,ds_bmap, buf, &dummy); while (count){ #ifdef DEBUG_MAGIC_SCAN @@ -867,7 +1027,7 @@ while (ds_retval){ #endif if (((count -i) > 12) && (ext2fs_le32_to_cpu(*(__u32*)(buf +((i+12)*blocksize))) == blk[0] + i +1 + 12)){ follow = 0; - file_data = new_file_data(blk[0]+i,scan,magic_buf,buf+(i*blocksize),&follow); + file_data = new_file_data(blk[0]+i,scan,magic_buf,buf+(i*blocksize),&follow, count - i); for(j=blk[0]+i; j<(blk[0]+i+12);j++) add_file_data(file_data, j, scan ,&follow); scan = magic_check_block(buf+((i+12)*blocksize), cookie, cookie_f , magic_buf , blocksize ,blk[0]+i+12, 0); @@ -890,10 +1050,10 @@ while (ds_retval){ } } blk[0] += (i)?i:1; - count = get_range(blk ,ds_bmap,buf); + count = get_range(blk ,ds_bmap,buf, &dummy); } count = 0; - blk[0] = 0; + blk[0] = 1; last_rec = 0; fragment_flag = 0; count = get_full_range(blk ,ds_bmap, buf,flag); @@ -924,7 +1084,7 @@ while (ds_retval){ printf("SCAN %lu : %09x : %s\n",flag[i],scan,magic_buf); #endif if (((count -i) > 12) && (ext2fs_le32_to_cpu(*(__u32*)(buf +((i+12)*blocksize))) == flag[12+i]+1)){ - file_data = new_file_data(flag[i],scan,magic_buf,buf+(i*blocksize),&follow); + file_data = new_file_data(flag[i],scan,magic_buf,buf+(i*blocksize),&follow,count - i); for(j=i; j<(12+i);j++) add_file_data(file_data, flag[j], scan ,&follow); scan = magic_check_block(buf+((i+12)*blocksize), cookie, cookie_f , magic_buf , blocksize ,flag[i+12],0); @@ -946,7 +1106,7 @@ while (ds_retval){ for (j=i; j< 12+i; j++){ if (!follow){ - file_data = new_file_data(flag[i],scan,magic_buf,buf+(i*blocksize),&follow); + file_data = new_file_data(flag[i],scan,magic_buf,buf+(i*blocksize),&follow,count - i); add_file_data(file_data, flag[i], scan ,&follow); } else{ @@ -1025,16 +1185,100 @@ if (cookie_f) magic_close(cookie_f); +static int check_extent_len(struct ext3_extent_header *header, struct extent_area* ea, blk_t blocknr ){ + void *buf = NULL; + int ret = 0; + struct ext3_extent_idx *idx; + struct ext3_extent *extent; + int entry,i; + + ret = ext2fs_extent_header_verify((void*) header, current_fs->blocksize); + if(!ret){ + ea->b_count++; + for (entry =1; ((!ret) && (entry <= ext2fs_le16_to_cpu(header->eh_entries))) ; entry++){ + if (ext2fs_le16_to_cpu(header->eh_depth)){ + idx = (struct ext3_extent_idx*) (header + entry); + buf=malloc(current_fs->blocksize); + if (!buf) + return 1; + if(io_channel_read_blk ( current_fs->io,ext2fs_le32_to_cpu(idx->ei_leaf), 1, buf )){ + fprintf(stderr,"Error read block %lu\n",ext2fs_le32_to_cpu(idx->ei_leaf)); + ret = 2; + } + else{ + //Recursion + ret = check_extent_len((struct ext3_extent_header*)buf, ea , 0); + } + if (buf){ free(buf); buf = NULL ;} + } + else{ + extent = (struct ext3_extent*)(header + entry); + if ((ext2fs_le16_to_cpu(extent->ee_len)) & 0x8000){ + continue; + } + for (i = 0; ((! ret) && (i< ext2fs_le16_to_cpu(extent->ee_len))); i++){ + if (ext2fs_test_block_bitmap( bmap,ext2fs_le32_to_cpu(extent->ee_start) + i )) + ret = 4; + } + if (!ret){ + if ((entry == 1) && (!ea->start_b)){ + ea->start_b = ext2fs_le32_to_cpu(extent->ee_start); + ea->l_start = ext2fs_le32_to_cpu(extent->ee_block); + } +// if (entry == ext2fs_le16_to_cpu(header->eh_entries)){ + ea->end_b = ext2fs_le32_to_cpu(extent->ee_start) + ext2fs_le16_to_cpu(extent->ee_len)-1; + ea->l_end = ext2fs_le32_to_cpu(extent->ee_block) + ext2fs_le16_to_cpu(extent->ee_len)-1; +// } + ea->b_count += ext2fs_le16_to_cpu(extent->ee_len); + ea->size = ((unsigned long long) ((ext2fs_le32_to_cpu(extent->ee_block)) + + (ext2fs_le16_to_cpu(extent->ee_len)))) * current_fs->blocksize; + } + } + } + if ((blocknr) && (!ret)){ + ea->blocknr = blocknr; + ea->depth = ext2fs_le16_to_cpu(header->eh_depth); + } + } +return ret; +} + + + +int recover_db(struct extent_db_t *db , struct extent_area *ea_group){ + int flag = 0; + int count = 0; + __u32 start; + struct extent_area *ea = ea_group ; + memset (ea_group, 0 ,sizeof(struct extent_area) *4); + + start = 0; + while ((!flag) && (count < 4)) { + start = extentd_db_find(db, (start) ? start+1 : start , ea); + if (start){ + count++; +// printf(" --> %d ; start: %lu end: %lu depth: %lu \n",count, ea->l_start, ea->l_end, ea->depth); + ea++; + } + else flag++; + } + +return count; +} + + //FIXME NEW --------------------------------------------------------------------------------------------------------- //main of the magic_scan_engine for ext4 int magic_block_scan4(char* des_dir, __u32 t_after){ magic_t cookie = 0; magic_t cookie_f = 0; -struct ext3_extent_header *p_extent_header; -struct ext3_extent *p_extent; -struct ext3_extent_idx *p_extent_idx; -struct ext2fs_struct_loc_generic_bitmap *ds_bmap; +struct ext2fs_struct_loc_generic_bitmap *ds_bmap = NULL; +ext2fs_block_bitmap c_bmap = NULL; +struct extent_db_t *db = NULL; struct found_data_t *file_data = NULL; +struct found_data_t *tmp_file_data = NULL; +struct extent_area *ea = NULL; +struct extent_area ea_group[4]; blk_t blk[2] ; blk_t first_b; blk_t last_rec; @@ -1042,25 +1286,39 @@ unsigned char *v_buf = NULL; unsigned char *buf ; char *magic_buf = NULL; unsigned char *tmp_buf = NULL; -int blocksize, ds_retval,count,i,ret; -__u32 scan,follow;//, size; +int blocksize, size, ds_retval,count,i,j,ret,dummy, border; +__u32 scan,follow; +int tes ; //typical extent size + + +//only for test +//int zahler = 0; +//int zahler1 =0; printf("MAGIC-3 : start ext4-magic-scan search. Experimental in develop \n"); blocksize = current_fs->blocksize ; +tes = 1048576 / blocksize; +if (ext2fs_copy_bitmap(current_fs->block_map, &c_bmap)){ + fprintf(stderr,"Error: while duplicate bitmap\n"); + return 0; +} +ext2fs_clear_block_bitmap(c_bmap); + count = 0; -blk[0] = 0; -cookie = magic_open(MAGIC_MIME | MAGIC_NO_CHECK_COMPRESS | MAGIC_NO_CHECK_ELF ); +blk[0] = 1; +cookie = magic_open(MAGIC_MIME | MAGIC_NO_CHECK_COMPRESS | MAGIC_NO_CHECK_ELF | MAGIC_CONTINUE); cookie_f = magic_open(MAGIC_NO_CHECK_COMPRESS | MAGIC_NO_CHECK_ELF | MAGIC_RAW ); + if ((! cookie) || magic_load(cookie, NULL) || (! cookie_f) || magic_load(cookie_f, NULL)){ fprintf(stderr,"ERROR: can't find libmagic\n"); goto errout; } v_buf = malloc(blocksize * (MAX_RANGE+1)); buf = v_buf + blocksize ; -tmp_buf = malloc(blocksize); +tmp_buf = malloc(blocksize * 9); magic_buf = malloc(100); -if ((! v_buf) || (! magic_buf) || (! tmp_buf)){ +if ((! v_buf) || (! magic_buf) || (! tmp_buf)){ fprintf(stderr,"ERROR: can't allocate memory\n"); goto errout; } @@ -1070,13 +1328,15 @@ while (ds_retval){ ds_retval = next_block_bitmap(d_bmap); if (ds_retval == 2 ) continue; - if (d_bmap && ds_retval ){ + db = extent_db_init(d_bmap); + if (d_bmap && ds_retval && db ){ ds_bmap = (struct ext2fs_struct_loc_generic_bitmap *) d_bmap; + last_rec = 0; count = 0; - blk[0] = 0; + blk[0] = 1; follow = 0; - count = get_range(blk ,ds_bmap, buf); + count = get_range(blk ,ds_bmap, buf, &dummy); while (count){ #ifdef DEBUG_MAGIC_SCAN @@ -1088,47 +1348,406 @@ while (ds_retval){ if ((check_dir_block(buf +(i*blocksize), blk[0]+i,1)) || (check_acl_block(buf+(i*blocksize), blk[0]+i,1))){ ext2fs_mark_generic_bitmap(bmap, blk[0]+i); -// printf ("<<> %lu DIR-BLOCK \n",blk[0]+i); +// printf ("<<> %lu DIR-BLOCK \n",blk[0]+i); continue; } + if (check_plain_passing((buf +(i*blocksize))) && ((blk[0]+i-((blocksize==1024)?1:0)) % tes ) ) + ext2fs_mark_generic_bitmap(c_bmap, blk[0]+i); +//zahler++; if (check_meta4_block(buf+(i*blocksize), blk[0]+i,1)){ -// printf ("<<> %lu IDX \n",blk[0]+i); - p_extent_header=(struct ext3_extent_header*)(buf+(i*blocksize)); - if (! ext2fs_le16_to_cpu(p_extent_header->eh_depth)){ //FIXME Indextiefe - p_extent=(struct ext3_extent*)(p_extent_header +1) ; - if (! ext2fs_le32_to_cpu(p_extent->ee_block)) { //FIXME Fileanfang - first_b = ext2fs_le32_to_cpu(p_extent->ee_start); - if(( ext2fs_test_block_bitmap( bmap,first_b)) || - (io_channel_read_blk (current_fs->io,first_b,1,tmp_buf ))){ - fprintf(stderr,"ERROR: while read block %10lu\n",first_b); +// printf ("<<> %lu IDX \n",blk[0]+i); + ea = new_extent_area(); + if ( ea ){ + if (check_extent_len((struct ext3_extent_header*) (buf+(i*blocksize)) , ea, blk[0]+i)){ + printf("extent %lu range allocated or damage\n",blk[0]+i); + } + else{ +// printf(" --> start: %lu end: %lu depth: %lu \n",ea->l_start, ea->l_end, ea->depth); + if (!ea->l_start){ + first_b = ea->start_b; + if(( ext2fs_test_block_bitmap( bmap,first_b)) || + (io_channel_read_blk (current_fs->io,first_b - 1,9,tmp_buf ))){ + fprintf(stderr,"!ERROR: while read block %10lu\n",first_b); +//FIXME ERROR goto ? + } + else{ + scan = magic_check_block(tmp_buf+blocksize, cookie, cookie_f , magic_buf , blocksize*8 ,first_b, 1); + file_data = new_file_data(first_b,scan,magic_buf,tmp_buf+blocksize,&follow, 8); + if ((file_data) && + (add_ext4_extent_idx_data(file_data, ea))){ + file_data->scantype |= DATA_METABLOCK; + io_channel_read_blk (current_fs->io, file_data->last, 1, tmp_buf); + file_data = soft_border(des_dir, tmp_buf, file_data, &follow, ea->blocknr ,&last_rec, 0x7); + + if(last_rec == blk[0]+i){ + extent_db_add (db, ea,1); + extent_db_del(db,blk[0]+i); + ea=NULL; + } + else{ + extent_db_add (db, ea,1); + ea = NULL; + } + } + } } else{ - scan = magic_check_block(tmp_buf, cookie, cookie_f , magic_buf , blocksize ,first_b, 1); - file_data = new_file_data(first_b,scan,magic_buf,tmp_buf,&follow); - if ((file_data) && - (add_ext4_extent_idx_data(file_data, (void*) p_extent_header, blk[0]+i))){ - io_channel_read_blk (current_fs->io, file_data->last, 1, tmp_buf); - file_data = soft_border(des_dir, tmp_buf, file_data, &follow, 0 ,&last_rec, 0x7); - } + extent_db_add (db, ea,1); + ea = NULL; } } - } - blk[0] = blk[0] - count + i; - i = count; + blk[0] = blk[0] - count + i; + i = count; + if(ea) {free(ea); ea=NULL;} + } } //ext4meta - } //for i blk[0] += (i)?i:1; - count = get_range(blk ,ds_bmap,buf); + count = get_range(blk ,ds_bmap,buf, &dummy); } //count - } //ds_bmap +// } //ds_bmap + + while(1){ + count = recover_db(db, ea_group); + if(count){ + ea = ea_group; + if (( ea->blocknr) &&(! ea->l_start)){ + first_b = ea->start_b; + if(( ext2fs_test_block_bitmap( bmap,first_b)) || + (io_channel_read_blk (current_fs->io,first_b-1 ,9,tmp_buf ))){ + fprintf(stderr,"!ERROR: while read block %10lu\n",first_b); +//FIXME ERROR goto ? + } + else{ + scan = magic_check_block(tmp_buf+blocksize, cookie, cookie_f , magic_buf , blocksize*8,first_b, 1); + file_data = new_file_data(first_b,scan,magic_buf,tmp_buf+blocksize,&follow,8); + if ((file_data) && (add_ext4_extent_idx_data(file_data, ea))){ + for (i = 1; i<count; i++){ + ea++; + add_ext4_extent_idx_data(file_data, ea); + } + io_channel_read_blk (current_fs->io, file_data->last, 1, tmp_buf); + file_data = soft_border(des_dir, tmp_buf, file_data, &follow, ea_group[0].blocknr, + &last_rec, 0x7 | FORCE_RECOVER); + + if(last_rec != ea_group[0].blocknr) + printf("error: block %lu -> file not written\n",ea_group[0].blocknr); + for (i=0; i<count; i++){ + extent_db_del(db,ea_group[i].blocknr); + } + } + else{ + printf("error : while create new file_data\n"); +// goto errout; + } + } + } + else{ + printf("error : no first blocknumber or not begin of a file\n"); +// goto errout; + } + ea = NULL; + } + else{ +// printf("ExtentDB ready for now\n"); + break; + } + } //while +//-------------------------- + last_rec = 0; + count = 0; + blk[0] = 1; + follow = 0; + count = get_range(blk ,ds_bmap, buf, &border); + ea = NULL; + + while (count){ +newloop: + for (i = 0; i< count ;i++){ + if ((follow % tes) && (ext2fs_test_block_bitmap(c_bmap,blk[0]+i))){ + if (ea) + (ea->len)++; + if (file_data) + add_file_data(file_data, blk[0]+i, scan ,&follow); + else + follow++; + continue; + } + + if (!follow){ + scan = magic_check_block(buf+(i*blocksize), cookie, cookie_f , magic_buf , (count-i)*blocksize ,blk[0]+i, 1); +//printf("SCAN %lu : %09x : %s\n",blk[0]+i,scan,magic_buf); + ea = new_extent_area(); + if ( ea ){ + ea->start_b = blk[0]+i; + (ea->len)++; + if ((scan & M_IS_FILE) && (!(scan & M_DATA))){ + file_data = new_file_data(blk[0]+i,scan,magic_buf,buf+(i*blocksize),&follow,count - i); + if (file_data){ +//----------------------<<< +//File can recover by follow the datastream + if (file_data->scantype & DATA_CARVING){ + (ea->len)--; + for (j=0;j<file_data->buf_length;j++){ + add_file_data(file_data, blk[0]+i+j, scan ,&follow); + (ea->len)++; + } + blk[0] += i+j; + count = get_range(blk ,ds_bmap,buf, &border); + ret = 1; + while (ret && (!(file_data->scantype & (DATA_READY | DATA_BREAK)))){ + file_data->buf_length = count; + ret = file_data->func(buf, &size ,scan ,3 , file_data); + if (ret){ + if (((!file_data->buf_length)&& (!(file_data->scantype & (DATA_READY))))|| ((ret == 3) && (file_data->scantype & H_F_Carving))){ + // break follow > scan now + goto newloop; + } + + if (file_data->buf_length > count){ + i = check_next_border(ds_bmap, blk[0],file_data->buf_length); + if (i){ + ea->len = file_data->last_match_blk; +// printf("%lu : BREAK-1 : %s after %ld blocks\n",blk[0]+i,file_data->name, ea->len); + blk[0] = ea->start_b + ((ea->len)?ea->len:1); + extent_db_add (db, ea, 0); + ea = NULL; + file_data = forget_file_data(file_data, &follow); + count = get_range(blk ,ds_bmap,buf, &border); + goto newloop; + } + } + + for (j=0;j<file_data->buf_length;j++){ + add_file_data(file_data, blk[0]+j, scan ,&follow); + (ea->len)++; + } + + if ((border && (file_data->last == blk[1]))&& (!(file_data->scantype & (DATA_READY)))){ + if ((!file_data->next_offset)&&(file_data->scantype & DATA_NO_FOOT)){ + file_data->scantype |= DATA_READY; +// printf("possible EOF, recover this\n"); + } + else { +// printf("%lu : BREAK-2 : %s after %ld blocks\n",blk[0]+i,file_data->name, file_data->last - file_data->first); + extent_db_add (db, ea, 0); + ea = NULL; + blk[0] = file_data->last + 1; + file_data = forget_file_data(file_data, &follow); + count = get_range(blk ,ds_bmap,buf, &border); + goto newloop; + } + } + blk[0] += j; + count = get_range(blk ,ds_bmap,buf, &border); + } + else{ +// printf("%lu : BREAK-3 : %s after %ld blocks\n",blk[0]+file_data->buf_length,file_data->name, file_data->last - file_data->first); + if (!file_data->last_match_blk) + (file_data->last_match_blk)++; + ea->len = file_data->last_match_blk; + extent_db_add (db, ea, 0); + ea = NULL; + blk[0] = file_data->first + file_data->last_match_blk ; + file_data = forget_file_data(file_data, &follow); + count = get_range(blk ,ds_bmap,buf, &border); + goto newloop; + } + } + if (file_data->scantype & (DATA_READY)){ + io_channel_read_blk (current_fs->io, file_data->last, 1, tmp_buf); + file_data = soft_border(des_dir, tmp_buf, file_data, &follow, ea->start_b ,&last_rec, 0x7); + if (ea->start_b != last_rec){ +// printf("%lu force recover, but not written\n",ea->blocknr); + extent_db_add (db, ea, 0); + ea = NULL; + } + } + else{ +// printf("%lu : BREAK put into extent-cache\n", blk[0]); + if (!file_data->last_match_blk) + (file_data->last_match_blk)++; + ea->len = file_data->last_match_blk; + extent_db_add (db, ea, 0); + ea = NULL; + blk[0] = file_data->first + file_data->last_match_blk; + file_data = forget_file_data(file_data, &follow); + count = get_range(blk ,ds_bmap,buf, &border); + } + if (ea){free(ea);ea = NULL;} + follow = 0; + goto newloop; + } +//End follow datastream + else{ + add_file_data(file_data, blk[0]+i, scan ,&follow); //add the first block + } + if (file_data->scantype & DATA_LENGTH){ +//Start of size carving + j = check_next_border(ds_bmap, blk[0]+i,((file_data->size-1)/blocksize)+1); + if ((!j) && (! io_channel_read_blk (current_fs->io, blk[0]+ i + ((file_data->size-1)/blocksize), 1, tmp_buf))){ + size = get_block_len(tmp_buf); + if ((!(file_data->scantype & DATA_MINIMUM)) && (size <= ((file_data->size % blocksize)?(file_data->size % blocksize):blocksize))){ + tmp_file_data = copy_file_data(file_data); + if (tmp_file_data){ + for (j = 1; j< (((file_data->size-1)/blocksize)+1); j++){ + add_file_data(tmp_file_data, blk[0]+i+j, scan ,&follow); + } + tmp_file_data = soft_border(des_dir, tmp_buf, tmp_file_data, &follow, blk[0]+i ,&last_rec, 0x3); + if (blk[0]+i == last_rec){ + file_data = forget_file_data(file_data, &follow); + if (ea){free(ea);ea = NULL;} + blk[0]+= j + i; + count = get_range(blk ,ds_bmap,buf, &border); + goto newloop; + } + } + } + + } +//and only MIN_SIZE + if ((!j) && (file_data->scantype & DATA_MINIMUM)){ + for (j = 1; j< (((file_data->size-1)/blocksize)+1); j++){ + add_file_data(file_data, blk[0]+i+j, scan ,&follow); + (ea->len)++; + } + file_data->scantype = H_F_Carving; + blk[0]+=(i+j-2); + count = get_range(blk ,ds_bmap,buf, &border); + i = 1; +// size = get_block_len(buf+(i*blocksize)); + goto followloop; + } + else{ + file_data->scantype = H_F_Carving; + follow = ea->len; + } + } +//End size carving +//------------------------------>>> + + }else { // no file_data +// printf("%lu : no file_data\n",blk[0]+i); + if(ea){ + (ea->l_start)--; + if(!ea->len) + (ea->len)++; + extent_db_add (db, ea, 0); + ea = NULL; + } + } + }else { +// printf("%lu : no file begin\n",blk[0]+i); + (ea->l_start)--; + follow++; + } + }else + printf("fail malloc ea\n"); + } + else{ + scan = magic_check_block(buf+(i*blocksize), cookie, cookie_f , magic_buf , blocksize ,blk[0]+i, 0); +// zahler1++; +// printf("SCAN %lu : %09x : %s\n",blk[0]+i,scan,magic_buf); + if (file_data){ + if ( check_file_data_possible(file_data, scan ,buf+(i*blocksize))){ + add_file_data(file_data, blk[0]+i, scan ,&follow); + (ea->len)++; + } + else{ + file_data = soft_border(des_dir,buf+((i-1)*blocksize), file_data, &follow, blk[0]+i-1, &last_rec,0x3); + if (last_rec != blk[0]+i-1){ +// printf("%lu : clear, put into extent-cache\n", blk[0]+i-1 ); + extent_db_add (db, ea, 0); + ea = NULL; + } + if (ea){free(ea);ea = NULL;} + i--; + } + } + else{ + if ((scan & M_IS_FILE) && (!(scan & M_DATA))){ +// printf("%lu : end of fragment, put into extent-cache\n",blk[0]+i); + extent_db_add (db, ea, 0); + ea = NULL; + follow = 0; + i--; + } + else { + (ea->len)++; + follow++; + if ((scan & M_SIZE) < (blocksize - 32)){ +// printf("%lu : possible end of fragment, add extent-cache\n",blk[0]+i); + extent_db_add (db, ea, 0); + ea = NULL; + follow = 0; + } + } + } + } + size = (scan & M_SIZE ); //get_block_len(buf+(i*blocksize)); +followloop: + if (follow && file_data){ + ret = file_data->func(buf+(i*blocksize), &size ,scan ,0 , file_data); + if (ret == 1){ + if (file_data_correct_size(file_data,size)){ + file_data = recover_file_data(des_dir, file_data, &follow); + last_rec = blk[0]+i; + } + else{ + file_data = forget_file_data(file_data, &follow); + extent_db_add (db, ea, 0); + ea = NULL; + +// printf("%lu : Don't recover this file\n",blk[0]+i); + } + if (ea){free(ea);ea = NULL;} + } + else + if(ea && (file_data->func == file_none)) + (ea->l_start)--; + } + } + if(border){ +// printf("%lu : border warning\n", blk[0]+i); + if (file_data) { + file_data = soft_border(des_dir,buf+((i-1)*blocksize), file_data, &follow, blk[0]+i-1, &last_rec,0x3); + if (last_rec != blk[0]+i-1){ +// printf("%lu : clear and put into extent-cache\n", blk[0]+i-1 ); + extent_db_add (db, ea, 0); + ea = NULL; + } + else { + free(ea);ea = NULL; + } + } + if (follow){ +// printf("%lu : end of fragment\n", blk[0]+i); + follow = 0; + } + if (ea){ + extent_db_add (db, ea, 0); + ea = NULL; + } + } + blk[0] += (i)?i:1; + count = get_range(blk ,ds_bmap,buf, &border); + } + + } +// printf("ExtentDB : %lu entries\n",db->count); + if (db){ extent_db_clear(db) ; db=NULL;} }//ds_retval errout: +clear_block_bitmap_list(d_bmap); +ext2fs_free_block_bitmap(c_bmap); +if (ea) free (ea); +if (db) extent_db_clear(db); if (v_buf) free(v_buf); if (tmp_buf) free(tmp_buf); if (magic_buf) free(magic_buf); if (cookie) magic_close(cookie); if (cookie_f) magic_close(cookie_f); +//printf("Count-1 = %lu Count-2 = %lu \n",zahler, zahler1); }//funcion //--------END---------- |