我一直在寻找一个合适的答案,这些答案会给我带来很好的帮助。那一刻,但还找不到一个,但我有一个二进制文件,其中有许多其他文件,这些文件有十六进制引用文件所在的位置。
例如,如果我打开一个十六进制编辑器并在偏移量0x500处查看此二进制文件,则从0x500到0x507将是二进制文件中该特定文件的邮件。然后从0x508到0x50F将是实际的文件大小(或块大小,或块大小或任何你想要调用的大小)然后接下来的32个字节是实际的文件名。
这是C脚本,我知道它的错误,这就是为什么我在这里寻求帮助让我去:p
int main (){
FILE* in = fopen("file", "rb");
int location[0x08];
int size[0x08];
int name[0x20];
int fileLocation;
int fileSize;
int fileName;
int buffer[0x08];
int entryCount;
fseek(in, 0x08, SEEK_SET);
entryCount = fread(buffer, sizeof(buffer), 1, in);
for ( int x = 0; x < 25; ++x) {
fileLocation = fread(location, sizeof(location), 1, in);
fileSize = fread(size, sizeof(size), 1, in);
fileName = fread(name, sizeof(name), 1, in);
// extract data based on references//
}
}
我在perl中创建了一个很好的脚本,但尝试将其迁移到C并且对我来说有点混乱; 0
任何有关我如何将其迁移到C的帮助将非常有帮助,谢谢你的期待
这是perl中的脚本:
my $fileLocation = '';
my $fileSize = '';
my $fileName = '';
my $file = '';
my $chunk = '';
my $exit = '';
seek( $infile, 0x10, 0 ) or die "cannot seek $infile: $!";
until ($exit) {
read( $infile, $fileLocation, 0x08 );
read( $infile, $fileSize, 0x08 );
read( $infile, $fileName, 0x20 );
if ( $fileLocation =~ 'terminating reference' ) {
last;
}
$fileLocation =~ s/(.)/sprintf("%02x",ord($1))/egs;
$fileSize =~ s/(.)/sprintf("%02x",ord($1))/egs;
$fileName =~ s/\0+$//;
if ( $fileLocation =~ 'terminating reference' ) {
last;
}
open( $file, '>', "extracted/$fileName" ) or die "Cannot open $fileName $!";
binmode($file);
sysseek( $infile, hex($fileLocation), 0 );
sysread( $infile, $chunk, hex($fileSize) );
syswrite( $file, $chunk );
$fileLocation = '';
$fileSize = '';
};
这将读取8个字节,然后是8个字节,然后是32个字节,然后它将根据变量$ fileLocation,$ fileSize和$ filename一遍又一遍地提取数据,直到我来到终止引用,然后将退出< / p>
答案 0 :(得分:2)
由于数据以十六进制字符存储在文件中,您(1)需要阅读char
s,而不是int
s(感谢@ user3121023),( 2)将十六进制转换为整数,然后(3)使用结果值。
此外,fread
的返回结果不您认为它是什么!它返回读取的字节数,因此您可以检查操作是否成功。
read_buffer
需要是您的最大读取长度(32字节)加上 1.(当然:只有在您想要printf
读取数据时才需要但是打印数据是明智的,以确保你做的一切正确。)
char read_buffer[0x21];
for ( int x = 0; x < 25; ++x)
{
if (fread (read_buffer, 1,8, in) < 8) break;
read_buffer[8] = 0;
fileLocation = strtol(read_buffer, NULL, 16);
printf ("location: %s -> %08Xh\n", read_buffer, fileLocation);
if (fread (read_buffer, 1,8, in) < 8) break;
read_buffer[8] = 0;
fileSize = strtol(read_buffer, NULL, 16);
printf ("size: %s -> %08Xh\n", read_buffer, fileSize);
if (fread (read_buffer, 1,0x20, in) < 0x20) break;
read_buffer[0x20] = 0;
printf ("name: %s\n", read_buffer);
// extract data based on references//
}
我省略了将read_buffer
复制到name
的步骤,因为为此你的name
声明太小了。由于您希望name
作为C字符串(无论它如何保存在原始文件中),您需要将其声明为至少
char name[21];
答案 1 :(得分:1)
我认为你可以在32位系统上声明你的变量
unsigned long location;
unsigned long size;
unsigned long entry;
char name[0x20];
在64位系统上,您可以使用unsigned int
代替unsigned long
然后读取数据
fseek(in, 0x08, SEEK_SET);
entryCount = fread(entry, sizeof(entry), 1, in);
printf ( "entry %lu\n", entry);
for ( int x = 0; x < 25; ++x) {
fileLocation = fread(&location, sizeof(location), 1, in);
printf ( "location %lu\n", location);
fileSize = fread(&size, sizeof(size), 1, in);
printf ( "size %lu\n", size);
fileName = fread(name, sizeof(name), 1, in);
printf ( "name %s\n", name);
// extract data based on references//
}