帮助破译创建 3 个密码的二进制文件

逆向工程 加密 米普 嵌入式
2021-06-26 09:51:55

我在我一直在使用的设备上找到了一个二进制文件,它被调用genrandpass,唯一的用户输入是一个存储在设备本地的公钥(它是一个 .bin 文件)。它还收集一些其他信息,可能来自环境以生成三个密码(使用 引用 Box ID strings)。查看与 相关的 shell 脚本genrandpass,它需要三个生成的密码和:

  • 使用第一个密码作为 root 密码
  • 使用第二个密码被调用$epass,第三个被调用$spass(我只记下名字,以防它对比我更聪明的人有任何意义。)
  • 然后它复制$epass复制$spass到 dropbear 横幅文件中,只要有人连接到 dropbear(甚至在登录之前)就会显示这些文件。

这让我认为开发人员打算能够使用$epass$spass变量来生成实际的 root 密码。盒子本身有一些证书和一个私钥 (decryption.pem)。不确定这是否是破译密码的正确密钥,但我想尝试一下,因为我还有一些其他型号的这些盒子,但我还无法破解。我只是不确定要尝试哪些正确的命令。有任何想法吗?

genrandpass 文件位于https://dl.dropboxusercontent.com/u/23091/genrandpass

生成的最后 2 个密码的示例:

$ EPASS:SxTV2Z7TFvU0​​XKP / lYYTDlKAhlRR2jwkDGbWPF68go / oOx6x4Pr5DeyNRlx9oQGF05sHld / vyXXchmxlbzsVzPIwocWIq3OIr3J + ZFJrJYPss9VE7YWrwpyRlGwTVHDvZGIzCKXcaipJd85ldLiWUrNxMl4g + 5kzwVA2a3I8LuiuixRFVmc8ji / W2W5ZeU5FTcbaiNjlpoRHjPFUkvHKJ4nHSfXpZuLDRS53hxcSnb8ZmvTmFP4ITAdyj9Yw + C2pvD + gSEWRB / H + 1cFPQOTi7wr / FY8266QEWqGZw30ZEsMCUNCC0DgiIX + H68QKcU8QFYUJC5 + vui3BtcOfFXKHZl ==

$ SPASS:RtcTy7fJ11XAQi1P2HiZM4MAxMZMA2NlD6wZL8jNYdrSL5i8qtkGztKDccmGqRWgjiVKI7TcVNcX3PhUSB3UfQCAF6KpBvH7NNezkExdwdM3W2mSnXJvyRLpDSJEgALs0wurUrqIYClZOjTc + xiJzOIUP0Gxb4d2ADOaKXHQ6n6H2Ss / 1smITjrbXJ1K8RentZu26sAy3DW + zRIxtxnktSAGUscdG1oytlOL15aAROSL27NUcPSoA3 + 4o76zggq5TspIBTSmidVRUccEdXPyAzZggR0yqGNrm99uJXHlhw4zCW + GzKJFsJSTwDHZvCoeLERCLuyXFVrgmIISKf6E2V ==

1个回答

您的代码在 0x400960 处有一个函数,它看起来像一个主函数,并且省略了所有初始化(一切都被初始化为 0)和错误检查,如下所示:

char input_file_buffer[256];

int finder_id_size=16;
char finder_id[16];

int temp_256=256;
char finder_public_key[256];

char password[31];

int temp_32=32;
char sha_buffer[256];
char rsa_buffer[256];
char base64_input[256];
char base64_output[345];

FILE *fp=fopen(argv[1], "rb");
fread(input_file_buffer, 256, 1, fp);
fclose(fp);

get_finder_public_key(finder_id, &finder_id_size,
                    finder_public_key, &finder_public_key_size);

make_password(password, 30);

printf("%s\n", password);

memmove(sha_buffer+32, password, 30);
memmove(sha_buffer+63, finder_id, 16);
run_sha256(sha_buffer, 256, rsa_buffer+36, &temp_32);
run_rsa_public_decrypt(sha_buffer, 256, base64_input, &temp_256,
                            input_file_buffer, 256);
    // base64_encode is a loop calling encodeblock, not a function,
    // in the original binary. Encodeblock encodes 3 bytes binary
    // input 4 bytes base64 output.
base64_encode(base64_input, 256, base64_output, 345);
printf("%s\n", base64_output);

rsa_buffer[32]=htonl(1);
run_rsa_ks(rsa_buffer, 256, base64_input, &temp_256);
base64_encode(base64_input, 256, base64_output, 345);
puts(base64_output);

因此,(因为某些函数在共享库中,其中一部分是假设)您的代码:

  • 生成一个随机密码(make_password 没有任何输入)
  • 输出那个随机密码
  • 运行 sha256 在该密码和您的 finder 的 id 的组合上
  • 在 sha 输出上运行 RSA“解密”,公钥来自您的输入文件(?)
  • 输出 base64 编码的 RSA 数据
  • 在 sha 输出的不同部分运行 rsa_ks(某个东西的 32 字节缓冲区,前面是 1,在 256 字节缓冲区中间的某个地方?)
  • 输出 rsa_ks 的结果。

在 RSA 中,您使用某人的公钥加密消息,以便此人可以使用他们的私钥对其进行解密,或者您使用您的私钥对某些内容进行加密以证明您的身份(因为可以使用公钥对其进行解密)。因此,我不会过分强调 rsa 函数被称为“解密”这一事实。

我假设 run_sha 函数生成一个随机的 32 位密钥,使用它来进行加密,并将其保存到我所说的rsa_buffer. 稍后,run_rsa_ks(ks 表示密钥保存)对该 sha 密钥进行 rsa 加密。因此,如果您丢失了设备的 root 密码,并向供应商寻求帮助,他们

  • 用私钥解密第二个密码,得到sha key
  • 使用私钥解密第一个密码,得到sha输出
  • 使用 sha 密钥和 sha 输出获取包含您的 root 密码和查找程序 ID 的缓冲区
  • 验证查找器 ID 是否与您告诉他们的 ID 匹配
  • 告诉你root密码。

不幸的是,正如我在评论中已经说过的那样,这意味着除非您可以破解 rsa,并且没有任何其他方法来获取私钥,否则您的任务就到此为止了。除非供应商使用非常弱的 RSA 密钥,但当他们使用他们为保护 root 密码所做的努力时,这不太可能。

更新:我浏览了 libjsonsigner.so 中的一些函数,并且get_finder_id_public_keyrsa 函数使用了一个名为 的设备/dev/vixs/xcodedrv,它暗示了一个视频硬件芯片还有一个get_certificate函数,它使用一个get_device_certx使用相同设备函数。因此,至少一部分证书内容以及 rsa 加密似乎是硬件辅助的。这意味着如果没有对实际硬件的动态分析、良好的芯片文档和大量时间,您将不会走得更远(并且可能仍然会因为 RSA 而在某个时候撞墙)。