我如何找到该程序的许可证密钥?

时间:2019-06-30 15:06:54

标签: c linux reverse-engineering ltrace

我正在努力解决大学的这一练习。我们必须“破解”一个程序,该程序缺少启动该程序所需的许可证文件。我们仅使用Linux Shell。

所以我已经做的是创建此丢失的许可证文件。它是一个.ini,其中包括许可证持有人和许可证密钥。我现在唯一要寻找的是正确的许可证密钥。任务说我们应该使用“ strace”和“ ltrace”来解决这个问题。 这是我得到的输出:

fopen("license.ini", "r")                                   =0x55c088307380

fgets("LicenseHolder=annabell.krause@ex"..., 4096, 0x55c088307380)  = 0x7ffe72450860

strncmp("LicenseKey=", "LicenseHolder=annabell.krause@ex"..., 11)   = 3

strncmp("LicenseHolder=", "LicenseHolder=annabell.krause@ex"..., 14)    = 0

sscanf(0x7ffe72450860, 0x55c08753c16b, 0x7ffe72450800, 0xffffc000)  = 1

fgets("LicenseKey=aoeklycf", 4096, 0x55c088307380) = 0x7ffe72450860

strncmp("LicenseKey=", "LicenseKey=aoeklycf", 11)           = 0

sscanf(0x7ffe72450860, 0x55c08753c121, 0x7ffe72450840, 0xfffff800)  = 1

fgets("LicenseKey=aoeklycf", 4096, 0x55c088307380)          = 0

memfrob(0x7ffe72450840, 8, 0, 0xfbad2498)                   = 0x7ffe72450840

strncmp("KEOAFSIL", "aoeklycf", 8)                          = -22

fwrite("ERROR: License key is invalid.\n", 1, 31, 0x7faeabe60680
ERROR: License key is invalid.
)                                   = 31

+++ exited (status 1) +++

所以我想答案就在最后的memfrob和strncmp函数中。但是我不知道下一步是什么。

1 个答案:

答案 0 :(得分:4)

让我们逐个查看库跟踪调用。重要的部分在步骤5中。

分析

  1. 打开文件

    fopen("license.ini", "r")                                   =0x55c088307380
    

    打开许可证文件。

  2. 解析许可证持有人

    fgets("LicenseHolder=annabell.krause@ex"..., 4096, 0x55c088307380)  = 0x7ffe72450860
    

    从文件LicenseHolder=annabell.krause@ex…中读取一行。

    strncmp("LicenseKey=", "LicenseHolder=annabell.krause@ex"..., 11)   = 3
    

    该行是否以LicenseKey=开头? 3的返回值表示否,不是。

    strncmp("LicenseHolder=", "LicenseHolder=annabell.krause@ex"..., 14)    = 0
    

    该行是否以LicenseHolder=开头?是的,确实如此。

    sscanf(0x7ffe72450860, 0x55c08753c16b, 0x7ffe72450800, 0xffffc000)  = 1
    

    不幸的是,ltrace没有取消引用任何地址来显示内容。我们知道0x7ffe72450860是当前行,因此大概是从当前行中提取电子邮件地址。

  3. 解析许可证密钥

    fgets("LicenseKey=aoeklycf", 4096, 0x55c088307380) = 0x7ffe72450860
    

    它读取另一行:LicenseKey=aoeklycf

    strncmp("LicenseKey=", "LicenseKey=aoeklycf", 11)           = 0
    

    该行是否以LicenseKey=开头?是的,确实如此。

    sscanf(0x7ffe72450860, 0x55c08753c121, 0x7ffe72450840, 0xfffff800)  = 1
    

    它正在解析当前行。大概是提取您输入的许可证密钥aoeklycf,并将其保存在变量中,以便以后与预期的许可证密钥进行比较。类似于sscanf(line, "LicenseKey=%s", licenseKey);

  4. 文件结束

    fgets("LicenseKey=aoeklycf", 4096, 0x55c088307380)          = 0
    

    它尝试读取另一行并点击EOF。忽略第一个参数,它只是显示上次调用后缓冲区中剩余的内容。

  5. 许可证密钥比较

    memfrob(0x7ffe72450840, 8, 0, 0xfbad2498)                   = 0x7ffe72450840
    

    通过将每个字节与42异或来“加密”某个存储区的8个字节。这可以通过再次运行memfrob()来反转。我将“加密”放在空中引号中,因为这几乎不能称为加密。只是有点困惑。

    请注意,0x7ffe72450840是来自上方sscanf()的地址。这正在扰乱我在上面称为licenseKey的变量,即从输入文件中提取的LicenseKey=字符串。

    strncmp("KEOAFSIL", "aoeklycf", 8)                          = -22
    

    这是钱线。它会比较实际值和预期值,但会失败。

  6. 错误消息

    fwrite("ERROR: License key is invalid.\n", 1, 31, 0x7faeabe60680)                                   = 31
    

    打印错误。

合成

但是作者不希望您能够运行简单的字符串搜索(如strings ./program)将许可证密钥从可执行文件中拉出。为避免必须在license.ini中输入许可证密钥的 frobbed 版本,而不是原始字符串strings会找到。

代码可能类似于:

char *expected = "aoeklycf";
char actual[BUFSIZE];

sscanf(line, "LicenseKey=%s", actual);
memfrob(actual);
if (strncmp(actual, expected, strlen(expected)) != 0) {
    error("ERROR: License key is invalid.\n");
}

您是否从程序中提取了aoeklycf?如果是这样,则您错过了memfrob()步骤。 license.ini需要列出许可证密钥的“加密”版本:KEOAFSIL