📄 dump.c
字号:
/* * dump.c * Output functions for the ntfs tools * * Copyright (C) 1995 Martin von L鰓is */#include <stdio.h>#include <unistd.h>#include <ctype.h>#include <stdlib.h>#include "config.h"#include "ntfs.h"void dump_runs(unsigned char*,int,int,int);void list_attr_mem(char*);void print_name(char*);void uniprint(char*,int);void dump_attribute_list(char *start,char *stop);/* Dump a block of memory starting at buf. Display length bytes. The displayed index of the first byte is start */void dump_mem(unsigned char *buf,int start,int length){ int offs,i; for(offs=0;offs<length;offs+=16) { printf("%8.8X ",start+offs); for(i=0;i<16;i++)printf("%2X ",buf[offs+i]); for(i=0;i<16;i++) if(buf[offs+i]>31 && buf[offs+i]<128)putchar(buf[offs+i]); else putchar('.'); putchar('\n'); }} /* dump from the raw volume, starting at position */void dump(int position,int start,int length){ int offset; lseek(NTFS_FD(the_vol),position,SEEK_SET); for(offset=0;length==-1 || offset<length;offset+=16) { int i; unsigned char buf[16]; if(read(NTFS_FD(the_vol),buf,16)!=16) {perror("read");return;} printf("%8.8X ",start+offset); for(i=0;i<16;i++) printf("%2X ",buf[i]); for(i=0;i<16;i++) if(buf[i]>31 && buf[i]<128)putchar(buf[i]); else putchar('.'); putchar('\n'); }}/* Find a string on the volume, starting at position. If searching for Unicode strings, the string argument should already be Unicode */#define BSIZE 32768int grep(int position,int length, unsigned char *string,int stringlen,int ignore_case){ int offset; int b_offs; int i; unsigned char buf[2*BSIZE]; if(ignore_case) for(i=0;string[i];i++)string[i]=tolower(string[i]); lseek(NTFS_FD(the_vol),position,SEEK_SET); read(NTFS_FD(the_vol),buf,BSIZE); if(ignore_case) for(i=0;i<BSIZE;i++)buf[i]=tolower(buf[i]); for(offset=b_offs=0;length==-1 || offset<length;offset+=BSIZE) { if(read(NTFS_FD(the_vol),buf+BSIZE,BSIZE)!=BSIZE) {perror("read");return -1;} if(ignore_case) for(i=BSIZE;i<2*BSIZE;i++)buf[i]=tolower(buf[i]); for(;b_offs<BSIZE;b_offs++) if(buf[b_offs]==string[0]) { for(i=0;i<stringlen;i++) if(buf[b_offs+i]!=string[i]) break; if(i==stringlen)return position+offset+b_offs; } memcpy(buf,buf+BSIZE,BSIZE); b_offs-=BSIZE; } return -1;} /* print the attribute list for the MFT record at offset on the volume */void list_attributes(int offset){ char rec[4096]; lseek(NTFS_FD(the_vol),offset,SEEK_SET); if(read(NTFS_FD(the_vol),rec,sizeof(rec))!=sizeof(rec)){ perror("read"); return; } if(!ntfs_check_mft_record(the_vol,rec)){ fprintf(stderr,"Not a mft record\n"); return; } list_attr_mem(rec);}/* print the attribute list at rec */void list_attr_mem(char *rec){ int offs; int type,length,resident,namelen,compressed; char *start; /* first attribute should start at *0x14 */ offs= NTFS_GETU16(rec + 0x14); while(offs<the_vol->mft_recordsize) { printf("%4.4X:",offs); printf("Type %X ",type=NTFS_GETU32(rec+offs)); if(type==-1)break; /* offset to the next attribute */ printf("Length %X ",length=NTFS_GETU32(rec+offs+4)); resident=*(rec+offs+8)=='\0'; compressed=*(rec+offs+0xC); if(resident){ printf("resident "); if(*(rec+offs+0x16)) printf("indexed "); } if(compressed) printf("compressed "); printf("Slot #%X ",NTFS_GETU16(rec+offs+14)); /* position of attribute data if resident */ start=rec+offs+NTFS_GETU8(rec+offs+10); if(NTFS_GETU8(rec+offs+10)==0)start+=NTFS_GETU16(rec+offs+0x20); /* length attribute name, name starts at start */ namelen=NTFS_GETU8(rec+offs+9); if(namelen!=0) { printf("named("); uniprint(start,namelen); start+=namelen*2; printf(") "); } if(NTFS_GETU8(rec+offs+11)) fprintf(stderr,"Found [B] at offset %X\n",offs); if(NTFS_GETU8(rec+offs+13)) fprintf(stderr,"Found [D] at offset %X\n",offs); switch(type) { case 0x10: printf("Standard attributes\n"); printf("\tCreation time "); print_time(NTFS_GETU64(rec+offs+0x18)); printf("\n\tModification time "); print_time(NTFS_GETU64(rec+offs+0x20)); printf("\n\tMFT Modification time "); print_time(NTFS_GETU64(rec+offs+0x28)); printf("\n\tAccess time "); print_time(NTFS_GETU64(rec+offs+0x30)); puts(""); break; case 0x20: printf("Attribute list\n"); dump_attribute_list(rec+offs+0x18,rec+offs+length); break; case 0x30: printf("File name\n"); printf("\t");print_name(rec+offs+0x58); printf("\tIndexed in 0x%X\n",NTFS_GETU32(rec+offs+0x18)); break; case 0x40: printf("Volume version, please report\n");break; case 0x50: printf("Security descriptor\n");break; case 0x60: printf("Volume name\n");break; case 0x70: printf("Volume information\n");break; case 0x80: printf("Data\n");break; case 0x90: printf("Index root\n");break; case 0xa0: printf("Index allocation\n");break; case 0xb0: printf("Bitmap\n");break; case 0xc0: printf("Symlink, please report\n");break; /* HPFS extended attributes */ case 0xd0: printf("EA info\n");break; case 0xf0: printf("EA\n");break; default: printf("Unknown, please report\n");break; } { ntfs_inode ino; int length; ino.attr=rec; if(resident) printf("\tSize %x \n",NTFS_GETU32(rec+offs+0x10)); else{ printf("\tSize %x, allocated %x, initialized %ux", length=NTFS_GETU32(rec+offs+0x28),NTFS_GETU32(rec+offs+0x30), NTFS_GETU32(rec+offs+0x38)); if(compressed) printf(", compressed %x\n",NTFS_GETU32(rec+offs+0x40)); else putchar('\n'); if(NTFS_GETU16(rec+offs+0x22)) fprintf(stderr,"Found [22]=%x at offset %X\n",NTFS_GETU16(rec+offs+0x22),offs); if(NTFS_GETU32(rec+offs+0x24)) fprintf(stderr,"Found [24] at offset %X\n",offs); dump_runs(start,NTFS_GETU32(rec+offs+0x10), NTFS_GETU32(rec+offs+0x18),compressed); } } offs+=length; } puts("");} void print_name(char *first){ int length=*(unsigned char*)first++; switch(*first++) { case 0: printf("Posix-Name:");break; case 1: printf("Unicode-Name:");break; case 2: printf("DOS-Name:");break; case 3: printf("Unicode+DOS:");break; default: printf("Don't know how to read the name\n"); return; } uniprint(first,length); puts("");}void uniprintz(char *first){ while(*first){ putchar(*first++); if(*first++){ printf("!!!!Error printing string\n"); return; } }}/* display all subentries, then display this entry */void dumpdir_entry(ntfs_inode* ino,char *entry){ int length=NTFS_GETU16(entry+8); int used=(NTFS_GETU8(entry+12)&2)==0; if(used)printf("\tinode %x\t",NTFS_GETU32(entry)); if(NTFS_GETU8(entry+13)) fprintf(stderr,"Found [D] at %x\n",ino->i_number); if(NTFS_GETU16(entry+14)) fprintf(stderr,"Found [E] at %x\n", ino->i_number); if((int)NTFS_GETU8(entry+12)&1){ int nextblock=NTFS_GETU64(entry+length-8); printf("Going down to block %x\n",nextblock); dumpdir_record(ino,nextblock); printf("back to\tinode %x\t",NTFS_GETU32(entry)); } if(used)print_name(entry+0x50);}/* display a directory record */void dumpdir_record(ntfs_inode* ino,int nextblock){ int length; char record[8192]; char *offset; ntfs_io io; io.fn_put=ntfs_put; io.fn_get=0; io.param=record; if(ntfs_read_attr(ino,AT_INDEX_ALLOCATION,"$I30", nextblock*the_vol->clustersize,&io,ino->u.index.recordsize)!= ino->u.index.recordsize){ printf("read failed\n"); return; } if(!ntfs_check_index_record(ino,record)){ printf("Not a index record\n"); return; } offset=record+NTFS_GETU16(record+0x18)+0x18; do{ dumpdir_entry(ino,offset); if(*(offset+0xC)&2)break; length=NTFS_GETU16(offset+8); if(!length)break; offset+=length; }while(1);}/* display an inode as directory */void dumpdir(ntfs_inode* ino){ int length=ino->vol->mft_recordsize; char *buf=(char*)malloc(length); char *data; ntfs_io io; io.fn_put=ntfs_put; io.fn_get=0; io.param=buf; if(ntfs_read_attr(ino,AT_INDEX_ROOT,"$I30", 0,&io,length)<=0) { printf("Not a directory\n"); free(buf); return; } ino->u.index.recordsize=NTFS_GETU32(buf+0x8); ino->u.index.clusters_per_record=NTFS_GETU32(buf+0xC); /* FIXME: consistency check */ data=buf+0x20; while(1) { length=NTFS_GETU16(data+8); dumpdir_entry(ino,data); if(NTFS_GETU8(data+12)&2)break; data+=length; if(!length){ printf("length==0!!\n"); break; } } free(buf);}/* display the list of runs of an attribute */void dump_runs(unsigned char *start,int vcnstart,int vcnend,int compressed){ int length=0; int cluster=0; int l=vcnend-vcnstart; int vcn=vcnstart; int ctype; while(l>0 && decompress_run(&start,&length,&cluster,&ctype)!=-1) { l-=length; if(!ctype) printf("\tRun from %x to %x (VCN=%x)\n",cluster,cluster+length,vcn); else printf("\tCompression unit size %x\n",length); vcn+=length; }}/* dump the attribute list attribute */void dump_attribute_list(char *start,char *stop){ while(start!=stop){ printf("\tType %X,MFT# %X,Start VCN %X ",NTFS_GETU32(start), NTFS_GETU32(start+0x10),NTFS_GETU32(start+0x8)); uniprint(start+0x1A,NTFS_GETU8(start+0x6)); start+=NTFS_GETU16(start+4); putchar('\n'); }}static void putchar1(unsigned char c){ if(c>=32 && c<=127) putchar(c); else switch(c) { case 10: printf("\\n");break; case 13: printf("\\r");break; default: printf("\\%o",c); }}void dump_decompress(ntfs_inode *ino,int run,int verbose){ int block,len,clear_pos; unsigned char *compressed; char clear[16384]; int tag=0,bits,charmode; int ctype; unsigned char *data; int offset=0; unsigned char *attr=ntfs_get_attr(ino,AT_DATA,0); ntfs_io io; io.fn_put=ntfs_put; io.fn_get=0; if(!attr) { fprintf(stderr,"No data attribute in this inode\n"); return; } if(RESIDENT(attr)) { fprintf(stderr,"Attribute is resident\n"); return; } if(!COMPRESSED(attr)) { fprintf(stderr,"Data attribute is not compressed\n"); return; } /*Skip name and valueoffset*/ attr+=NTFS_GETU16(attr+0x20)+NTFS_GETU8(attr+9); block=0; do{ decompress_run(&attr,&len,&block,&ctype); }while(run--); compressed=(char*)malloc(len*the_vol->clustersize); io.param=compressed; io.do_read=1; ntfs_getput_clusters(the_vol,block,0,len*the_vol->clustersize,&io); data=compressed; while(*(data+1) & 0xF0) { int block_size; unsigned char *stop; block_size = *(unsigned short*)data; if(verbose)printf("Head %x",block_size); block_size &= 0xFFF; data+=2; offset+=2; stop = data + block_size; bits=0; charmode=0; clear_pos=0; while(data<=stop) { if(!bits){ if(verbose)printf("\nOffset %x",offset); charmode=0; tag=*data; bits=8; data++; offset++; if(data>stop) break; } if(tag&1){ int i,len,delta,delta1=0; delta = *(unsigned short*)(data); len=*data; len&=0x1f; if(clear_pos<=0x10) { delta1=delta>>12; len = delta & 0xFFF; } else if(clear_pos<=0x20) { delta1=delta>>11; len = delta & 0x7FF; } else if(clear_pos<=0x40) { delta1=delta>>10; len = delta & 0x3FF; } else if(clear_pos<=0x80) { delta1=delta>>9; len = delta & 0x1FF; } else if(clear_pos<=0x100) { delta1=delta>>8; len = delta & 0xFF; } else if(clear_pos<=0x200) { delta1=delta>>7; len = delta & 0x7F; } else if(clear_pos<=0x400) { delta1=delta>>6; len = delta & 0x3F; } else if(clear_pos<=0x800) { delta1=delta>>5; len = delta & 0x1F; } else if(clear_pos<=0x1000) { delta1=delta>>4; len = delta & 0xF; }else fprintf(stderr,"NOW WHAT?\n"); len+=3; if(verbose)printf("\n%8.8X:len %x(%x) delta %x(%x) ", clear_pos,len,*data,delta,delta1); charmode=0; for(i=0;i<len;i++) { if(verbose) putchar1(clear[clear_pos-delta1-1]); else putchar(clear[clear_pos-delta1-1]); clear[clear_pos]=clear[clear_pos-delta1-1]; clear_pos++; } data+=2; offset+=2; }else{ if(verbose)if(!charmode) printf("\n%8.8X:",clear_pos); if(verbose) putchar1(*data); else putchar(*data); clear[clear_pos++]=*data; data++; offset++; charmode=1; } tag>>=1; bits--; } if(verbose)putchar('\n'); }/*while*/}void dump_inode(ntfs_inode *ino){ int i,j,vcn; printf("Inode %d, %d attributes, %d mft clusters\n", ino->i_number, ino->attr_count, ino->record_count); for(i=0;i<ino->attr_count;i++) { printf("attribute %X",ino->attrs[i].type); if(ino->attrs[i].name) { printf(" named("); uniprint((char*)ino->attrs[i].name,ino->attrs[i].namelen); printf(")\n"); }else printf("\n"); if(RESIDENT(&ino->attrs[i].header)) printf(" resident\n"); else for(j=0,vcn=0;j<ino->attrs[i].d.r.len;j++) { printf(" Run %d from %x len %x (VCN=%x)\n", j, ino->attrs[i].d.r.runlist[j].cluster, ino->attrs[i].d.r.runlist[j].len,vcn); vcn+=ino->attrs[i].d.r.runlist[j].len; } }}/* * Local variables: * c-file-style: "linux" * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -