【问题标题】:reading hexadecimal from binary file从二进制文件中读取十六进制
【发布时间】:2014-05-24 13:57:56
【问题描述】:

我一直在寻找一个合适的答案,让我“啊哈”的时刻,但还没有找到,但我有一个二进制文件,其中有许多其他文件,这些文件有十六进制引用文件所在的位置。
例如,如果我打开一个十六进制编辑器并查看偏移量 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 一遍又一遍地提取数据,直到我到达终止引用,然后将退出

【问题讨论】:

  • 这里具体是什么问题?
  • 我正在尝试将此 perl 脚本迁移到 C,并使用相同的逻辑。我很难使用十六进制偏移量/引用来解析二进制文件
  • 到目前为止你有什么 C 代码?
  • 如果确实“这些文件具有十六进制引用”,那么您忘记了将字符串包含十六进制转换为可在fseek 中使用的数字的步骤。要将十六进制字符串转换为数字,首先需要确保使用fread读取的数据是有效的C字符串:读入更大的缓冲区,并在末尾添加一个0。
  • 等等,这里似乎有一些基本的误解。 “这些文件有十六进制引用”——您是否混淆了十六进制查看器的 hexadecimal 输出与文件中的实际内容——binary 数字?如果是这样,我将删除我的答案。

标签: c hex extract fread seek


【解决方案1】:

由于数据以十六进制字符存储在文件中,因此您(1)需要读取chars,而不是ints(感谢@user3121023),(2)转换十六进制为整数,然后 (3) 使用结果值。

另外,fread 的返回结果不是你想的那样!它返回读取的字节数,因此您可以检查操作是否成功。

read_buffer 需要是您的最大读取长度(32 字节) 1 表示终止 0。(当然:仅当您想 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];

【讨论】:

  • 谢谢你,我会检查一下,是的,我试图打印结果,因为就像你说的那样,这样做对确保我得到正确的数据非常有用,但我的脚本保留了得到不同的 printf 结果,而不是预期的数据。当我忙着取款机时,我会在稍后检查一下。我会回来报告并感谢大家的帮助
  • 根据您的最新评论,我推断您不能使用此代码做您想做的事。
  • 如果我的解释可以更彻底,请告诉我
【解决方案2】:

我认为您可以将 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//
}

【讨论】:

  • 谢谢你的例子,我会坐下来思考大家的例子,再次感谢你的意见
猜你喜欢
  • 2020-10-25
  • 1970-01-01
  • 1970-01-01
  • 2015-05-15
  • 2022-01-17
  • 1970-01-01
  • 2016-11-04
  • 2014-02-25
  • 2012-03-26
相关资源
最近更新 更多