【发布时间】:2019-02-15 20:04:28
【问题描述】:
首先,万一有人想知道,这个问题仅用于教育目的。
假设我得到了一个二进制可执行文件(由 C 代码编译而成)。这个二进制可执行文件接受一个参数,一个密码,如果密码正确,它会写出一条秘密消息。在实践中$./jeff-binary jeffspassword 会产生Secret: Jeff's Secret Message
我想知道这个秘密,同时绕过知道密码的必要性 (jeffspassword)。我知道在创建这些二进制文件的 C 代码中,包含密码的路径是硬编码的。代码中有一部分内容为:fp = fopen("/etc/secret-password-dir/jeff/password", "r"); 显然,因为我不是 Jeff,所以我不知道有权读取或写入jeff。
由于我可以访问此二进制文件,因此我目前所做的工作是在二进制文件中作为单个长十六进制字符串读取,然后在其中搜索匹配的十六进制字符串(根据示例)/etc/secret-password-dir/jeff/password 并替换它使用/home/fred/Documents/blank_password,然后创建了一个具有此单一更改的新二进制文件。目的是文件指针最终会假设密码是我输入blank_password(我知道)的任何内容,因此我可以使用非密码运行这个修改后的二进制文件,以便打印出 Jeff 的秘密。
具体来说,我目前正在运行的进程是这样的:
我有一个 C 程序,它读取
jeff-binary的内容并将其作为十六进制字符串写入hex_of_jeff_binary.txt。-
然后我有一个读取
hex_of_jeff_binary.txt的 Python 脚本通过将/etc/secret-password-dir/jeff/password的十六进制表示替换为/home/fred/Documents/blank_password来执行一些字符串理解,然后将此修改后的二进制写入jeff-binary-mod。 chmod +x jeff-binary-mod使其可执行。结果为:
Segmentation fault (core dumped)。嗯。
我的问题是:我正在尝试做的事情可能吗?如果是这样,我哪里出错了?
【问题讨论】:
-
代码在哪里崩溃了?还是您没有访问 C 代码的权限?
-
(1) 逐字节比较
jeff-binary和jeff-binary-mode,看看除了对字符串的预期更改之外是否有任何差异。您可能会发现od -xa命令对于使用十六进制和 ASCII 字符显示文件很有用——您可以使用od -xa显示每个文件,然后比较od的两个输出。 (2) 如果你没有打开 etc/secret-password-dir/jeff/password 的权限,你为什么期望你写的一个可执行文件有这样的权限?如果原始可执行文件标记为 setuid 并且归 Jeff 所有,则它可能具有该权限。但你的副本不会。 -
你有没有把原来的字符串换成相同长度的字符串?如果不是,您更改了二进制文件的大小,更重要的是,您在更改后使所有偏移量无效。
-
一般来说,“修补”可执行二进制文件是极其困难的,因此对于大多数用途来说它可能是不可能的。但字符串常量是个例外,例如您要更改的路径名。 如果你不改变它们的长度,改变它们是非常简单的。如果新字符串的长度与旧字符串的长度相同或短,那就没问题了。如果新字符串比旧字符串长,你就不能这样做,除非你很幸运,而且超出字符串的数据并不重要。 (还记得保留空终止。)
-
为什么要绕道成“十六进制字符串”?