对 base64 编码的数字进行逆向工程

逆向工程 编码
2021-06-16 07:49:45

我正在对编码进行逆向工程。

-12 到 12 之间的数字,有 2 个小数,使用未知方法编码,结果是一对字符串,如下所示:

value   string1     string2
  0     AAAAAAAAAA  AAAAAAAA
  0.01  AAAAB7FK5H  4XqEPwAA
  0.02  AAAAB7FK5H  4XqUPwAA
  0.03  AAAAC4HoXr  UbiePwAA
  1     EAAAAAAAAA  AADwPwAA
  2     IAAAAAAAAA  AAAAQAAA
  3     MAAAAAAAAA  AAAIQAAA
  4     QAAAAAAAAA  AAAQQAAA
  5     UAAAAAAAAA  AAAUQAAA
  6     YAAAAAAAAA  AAAYQAAA
  7     cAAAAAAAAA  AAAcQAAA
  8     gAAAAAAAAA  AAAgQAAA
  9     kAAAAAAAAA  AAAiQAAA
 10     oAAAAAAAAA  AAAkQAAA
 11     sAAAAAAAAA  AAAmQAAA
 12     wAAAAAAAAA  AAAoQAAA
-12     T///8AAAAA  AAAowAAA
- 1     ////8AAAAA  AADwvwAA
- 0.64  ////97FK5H  4XrkvwAA
  2.01  IAAAAUrkfh  ehQAQAAA

(可根据要求提供任何其他样品)

显然,我想确定用于进行此转换的算法。

我的研究表明它可能与 base64 编码有关,使用的字母表是 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

A=0 B=1 ... /=63

例如,第一列转换为十进制,然后除以 4(丢弃余数),当值为正时,给出值的“整数”部分,当值为负时,给出 16 值。

我的小数部分运气不好,我只是不知道。

如果有人能给我一个提示或解决方案,将不胜感激。

我是一名具有基本数学和编程知识的摄影师,这将是完成脚本所需的核心部分,该脚本将优化我的工作流程,现在需要我手动读取、计算(excel)并将这些值写回(十进制) )。

谢谢你。

2个回答

这些是用 base64 编码的双数的二进制表示。要了解编码,让我们看一个示例(我曾经使用此页面将数字转换为二进制双精度表示):

0.03 = 0x3F9EB851EB851EB8 (binary representation of the double number)

使用小端编码,它以以下形式存储在内存中:

B8 1E 85 EB  51 B8 9E 3F

您必须用 2 个零扩展第一个和第二个 4 个字节,并使用 base64 对其进行编码:

base64(0000B81E85EB) = AAC4HoXr
base64(51B89E3F0000) = UbiePwAA

在您的示例中,0.03 被编码为:

0.03 = AAAAC4HoXr  UbiePwAA

因此,区别仅在于第一个字符串中的前 2 个字母,但我不明白为什么第一个字符串以这些字母开头。

基于@ebux 的回答:

前 4 个字节是数字的组成部分,以一种稍微奇怪的方式编码......第一个字节的 UPPER 半字节是数字本身。其他 5 个半字节是 0 表示正数,f 表示负数以“通常”的方式。

其余的字符串,就像@ebux 所说的那样,是值的浮点部分,采用 IEEE 格式,但是在编码/解码它们时,您必须向二进制字符串添加/删除两个 \0 字节。

这个 perl 程序将解码一个包含您的示例的文件:

#!/usr/bin/perl

use MIME::Base64 qw(decode_base64 encode_base64);
while (<>) {
    chomp;
    y/\r//d;
    s/- /-/;
    s/^\s+//;
    ($a, $b, $c)=split();
    $a2=decode_base64(substr($b, 0, 4));
    $b2=substr(decode_base64(substr($b, 2)), 2);
    $c2=substr(decode_base64($c), 0, 4);
    printf("%10s", $a);
    print "\t"; printhex($a2); 
    print "\t"; printhex($b2); 
    print "\t"; printhex($c2);
    print "\t"; printint($a2);
    print "\t"; printdbl($b2.$c2);
    print "\n";
}

sub printhex {
    my $str=shift;
    for ($i=0; $i<length($str); $i++) {
        printf("%02x.", ord(substr($str, $i, 1)));
    }
}

sub printint {
    my $str=shift;
    my $val=ord(substr($str, 0, 1))>>4;
    $val-=16 if (substr($str, 1, 1) eq "\xff");
    printf("%5d", $val);
}

sub printdbl {
    my $str=shift;
    my $val=unpack("d", $str);
    printf("%10.4f", $val);
}

输出(列顺序是您的列,从 base64 字符串派生的 3 列十六进制字节,从 col1 派生的整数值,从 col2/3 派生的浮点值):

  2.01  20.00.00.   14.ae.47.e1.    7a.14.00.40.        2       2.0100
     0  00.00.00.   00.00.00.00.    00.00.00.00.        0       0.0000
  0.01  00.00.00.   7b.14.ae.47.    e1.7a.84.3f.        0       0.0100
  0.02  00.00.00.   7b.14.ae.47.    e1.7a.94.3f.        0       0.0200
  0.03  00.00.00.   b8.1e.85.eb.    51.b8.9e.3f.        0       0.0300
     1  10.00.00.   00.00.00.00.    00.00.f0.3f.        1       1.0000
     2  20.00.00.   00.00.00.00.    00.00.00.40.        2       2.0000
     3  30.00.00.   00.00.00.00.    00.00.08.40.        3       3.0000
     4  40.00.00.   00.00.00.00.    00.00.10.40.        4       4.0000
     5  50.00.00.   00.00.00.00.    00.00.14.40.        5       5.0000
     6  60.00.00.   00.00.00.00.    00.00.18.40.        6       6.0000
     7  70.00.00.   00.00.00.00.    00.00.1c.40.        7       7.0000
     8  80.00.00.   00.00.00.00.    00.00.20.40.        8       8.0000
     9  90.00.00.   00.00.00.00.    00.00.22.40.        9       9.0000
    10  a0.00.00.   00.00.00.00.    00.00.24.40.       10      10.0000
    11  b0.00.00.   00.00.00.00.    00.00.26.40.       11      11.0000
    12  c0.00.00.   00.00.00.00.    00.00.28.40.       12      12.0000
   -12  4f.ff.ff.   00.00.00.00.    00.00.28.c0.      -12     -12.0000
    -1  ff.ff.ff.   00.00.00.00.    00.00.f0.bf.       -1      -1.0000
 -0.64  ff.ff.ff.   7b.14.ae.47.    e1.7a.e4.bf.       -1      -0.6400
  2.01  20.00.00.   14.ae.47.e1.    7a.14.00.40.        2       2.0100

该程序将一个或多个数字转换为您的格式:

#!/usr/bin/perl

use MIME::Base64 qw(decode_base64 encode_base64);

foreach $a (@ARGV) {
    print $a;
    my $intpart=($a & 0x0f) << 4;
    if ($a<0) {
        $intpart|=0xffffff0f;
    }
    my $part1=encode_base64(pack("l", $intpart)); chomp $part1;
    # print "\t", $part1;

    my $temp=encode_base64("\x00\x00".pack("d", $a)); chomp $temp;
    # print "\t", $temp;

    my $part2=substr($part1, 0, 4).substr($temp, 2, 6);
    print "\t", $part2;

    my $part3=substr($temp, 8, 6)."AA";
    print "\t", $part3;

    print "\n";
}

例子:

$ perl encode.pl 0.01 0.02 0.03  2.01 0 11 12 -12 -1 
0.01    AAAAB7FK5H  4XqEPwAA
0.02    AAAAB7FK5H  4XqUPwAA
0.03    AAAAC4HoXr  UbiePwAA
2.01    IAAAAUrkfh  ehQAQAAA
0       AAAAAAAAAA  AAAAAAAA
11      sAAAAAAAAA  AAAmQAAA
12      wAAAAAAAAA  AAAoQAAA
-12     T///AAAAAA  AAAowAAA
-1      ////AAAAAA  AADwvwAA

这是从 -12 到 12 的所有数字的链接:

https://mega.nz/#!BVpWgBiI!aPbtMmMYnLgUUn011Cl5qjA5OO6TpKG8CSTIhR7Re0E