简体   繁体   English

从二进制文件中读取十六进制

[英]reading hexadecimal from binary file

i have been constantly looking for an appropriate answer that would give me the "ahha" moment, but could not find one yet, but i have a binary file in which many other files are in, these files have hexadecimal references to the location to where the file is. 我一直在寻找一个合适的答案,给我“啊哈”的时刻,但还找不到一个,但我有一个二进制文件,其中许多其他文件,这些文件有十六进制引用的位置到哪里文件是。
Say for instance, if i open up a hex editor and look at this binary file at offset 0x500, then from 0x500 to 0x507 would be the postition of that particular file within the binary file. 比方说,如果我打开一个十六进制编辑器并在偏移量0x500处查看此二进制文件,那么从0x500到0x507将是二进制文件中该特定文件的邮件。 then from 0x508 to 0x50F would be the actual file size (or block size, or chunk size or whatever you want to call it) and then the next 32 bytes is the actual file name. 然后从0x508到0x50F将是实际文件大小(或块大小,或块大小或任何你想要调用它)然后接下来的32个字节是实际的文件名。
Here is the C script, i know its wrong and thats why i am here asking for help to get me going :p 这是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//


    }
}

I made a script in perl that does this great, but trying to migrate it to C and it is a little bit confusing to me ;0 我在perl中创建了一个脚本,它做得很好,但是尝试将它迁移到C,这对我来说有点混乱; 0
any help on how i could possibly migrate this to C would be very helpful, thanks for looking here is the script in perl: 任何有关如何将其迁移到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     = '';
};

this will read 8 bytes then 8 more bytes then 32 bytes ad then it will extract the data based of the variables $fileLocation, $fileSize, and $filename over and over until i come to the terminating reference, then will exit 这将读取8个字节,然后8个字节,然后是32个字节,然后它将反复提取基于变量$ fileLocation,$ fileSize和$ filename的数据,直到我来到终止引用,然后将退出

Since the data is stored inside the file in hexadecimal characters , you (1) need to read char s, not int s (thanks @user3121023), (2) convert hex to integer, then (3) use the resulting value. 由于数据以十六进制字符存储在文件中,您(1)需要读取char s,而不是int s(感谢@ user3121023),(2)将hex转换为整数,然后(3)使用结果值。

Also, the return result of fread is not what you think it is! 而且, fread的返回结果并不是你想象的那样! It returns the number of bytes read, and so you can check if the operation was successful. 它返回读取的字节数,因此您可以检查操作是否成功。

read_buffer needs to be your maximum read length (32 bytes) plus 1 for a terminating 0. (Granted: only necessary if you want to printf the read data. But it's sensible to print the data, to make sure you are doing everything right.) 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//
}

I omitted the step of copying read_buffer into name , because for this your name declaration is too small. 我省略了将read_buffer复制到name的步骤,因为这样你的name声明太小了。 Since you want name as a C-string (regardless of how it is saved in the original file), you need to declare it as at least 由于您希望将name作为C字符串(无论它如何保存在原始文件中),您至少需要将其声明为

char name[21];

I think you could declare your variables on a 32 bit system as 我想你可以在32位系统上声明你的变量

unsigned long location;
unsigned long size;
unsigned long entry;
char name[0x20];

on a 64 bit system you would use unsigned int instead of unsigned long 在64位系统上,您将使用unsigned int而不是unsigned long

then read the data 然后读取数据

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//
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM