如何识别这个特定数据文件的结构?

逆向工程 二元分析 文件格式
2021-06-23 09:37:39

这个来自旧电子游戏的数据库文件的结构是什么?https://www.dropbox.com/s/ioe26pi3y1w3320/TMDATA1.S8?dl=0

提前道歉,因为解决特定问题并不是 Stack Exchange 的精神,而是创建一组有用的问答。如果您能指出我正确的方向,我将不胜感激。:-)

2个回答

这当然不是众所周知的格式。使用十六进制查看器快速浏览该文件,会发现它主要由大小和布局相似但不完全相同的记录组成;文件的最后似乎有所不同。

前 2 个字节 - 047E - 似乎是记录数(1150)。

每条记录似乎都以 7 个字符串开头,在大多数情况下,这些字符串表示一个国家、国家的形容词、首都和球队名称 - 我猜保存文件来自足球比赛或类似比赛。

例如,记录的一个开始于1B8507 00 Algeria 07 00 Algeria 07 00 Algeria 07 00 Algeria 08 00 Algerian 07 00 Algiers 0F 00 Stade Olympique显然,这些是表示字符串长度的 2 字节整数;事实上,它们被写成07 00,而不是00 07,告诉你文件有一个小端结构,这可能有助于识别文件中的其他数字。

不幸的是,记录有不同的大小,但如果考虑到不同的字符串长度,它们会很好地工作。这是第一个记录位置、它们的大小以及其中的字符串的组合长度的列表:

pos.  size  strings  size w/o strings
0002  0597  005b     053C
0599  0582  0046     053C
0b1b  0582  0046     053C
109D  056D  0031     053C
160A  057B  003F     053C
1B85  0576  003A     053C
20FB  0569  002D     053C
2664  0570  0034     053C
2BD4  ........

为 7 个 2 字节长度标记减去 0E 导致每个记录在字符串后面有 0x52E 个字节。

接下来,我注意到许多这些字节在许多记录中似乎是相同的。所以我写了一个小的 perl 程序来读取文件,并创建一个直方图来显示记录中哪个位置的哪个字节出现的频率:

#!/usr/bin/perl

open(IN, "<$ARGV[0]") or die "can't open $ARGV[0]: $!";
sysread(IN, $buffer, 2);
$nclubs=unpack("v", $buffer);

for (my $i=0; $i<$nclubs; $i++) {
    printf("%3d  ", $i);
    # read strings
    for (my $j=0; $j<7; $j++) {
        sysread(IN, $buffer, 2);
        my $length=unpack("v", $buffer);
        sysread(IN, $buffer, $length);
        print "|$buffer";
    }
    print "\n";
    sysread(IN, $buffer, 0x52E);

    for (my $j=0; $j<0x52E; $j++) {
        my $byte=ord(substr($buffer, $j, 1));
        $count[$j][$byte]++;
    }
}

for (my $i=0; $i<0x52E; $i++) {
    my $flag=0;
    printf("%03x:", $i) unless $flag;
    for (my $j=0; $j<256; $j++) {
        if ($count[$i][$j]>0) {
            $flag=1;
            printf " 0x%02x(%dx)", $j, $count[$i][$j];
        }
    }
    print "\n";
}

这导致(小提取物):

314: 0x00(1150x)
315: 0x00(1150x)
316: 0x00(1134x) 0x6b(16x)
317: 0x00(1150x)
318: 0x00(1134x) 0x2c(16x)
319: 0x00(1100x) 0x6b(50x)
31a: 0x00(1150x)
31b: 0x00(1150x)
31c: 0x00(1083x) 0x6b(67x)
31d: 0x00(1150x)
31e: 0x00(1150x)
31f: 0x00(1100x) 0x6b(50x)
320: 0x00(1150x)

这意味着字节314315始终为零,而字节在大多数情况下316(107) 16 次,即对于 16 支球队。字节适用于 67 支球队。您现在可以继续将其与将保存文件加载到游戏中时发生的情况进行比较;对于这 1150 支球队中的 16 支或 67 支球队来说,有什么特别之处吗?您还可以查找具有这些值的团队,并检查这些确切团队的特殊之处。00x6b31c0x6b

在这方面投入大量时间可能会让您在不实际反编译应用程序的情况下识别大多数字节。但是,我希望您可以通过这种方式仅识别少数几个值,如果您真的想了解所有内容,则需要按照 Jason 的建议进行操作。另一方面,如果团队/首都/国家名称是您唯一感兴趣的东西,我的程序已经为您输出它们。

该文件没有众所周知的文件头(根据http://www.garykessler.net/library/file_sigs.html)。因此,除非它恰好是SIMUL8 文件(基于文件扩展名),否则您需要对视频游戏的代码进行逆向工程以确定文件格式。