如何查找程序中的非法指令?
How to find illegal instructions in a program?
我有一个旨在 运行 在特定模拟器上的基准测试,一些指令添加到基准测试中以与模拟器通信(不执行 CPU 操作),例如转储统计信息或重置统计数据等等。
现在我需要 运行 在另一个模拟器上进行相同的基准测试,而且确实没有其他解决方法,我必须使用相同的二进制文件,当然它不起作用,因为它会生成 SIGILL
或 Illegal Instruction
错误。
我现在想要的是能够直接从可执行二进制文件中删除错误指令(没有源代码,无法重新编译,无法从其他地方设置) 并将它们替换为 NOP
s。所以我 运行 gdb
中的基准测试并使用 layout asm
命令来查找错误指令的地址。这是输出:
我的问题可能看起来有点愚蠢,但现在我在文本编辑器中打开二进制文件,并尝试使用我从 gdb
获得的地址来查找二进制文件中的非法指令,但没有成功。二进制文件的大小大约为 1MB,而地址从大约 4MB 开始。如何使用从 gdb
获得的地址找到二进制文件中的非法指令?这是二进制文件的一个片段,显示了它的格式:
616c 6967 6e00 5f5f 7265 6769 7374 6572
5f66 7261 6d65 5f69 6e66 6f00 5f49 4f5f
7664 7072 696e 7466 005f 5f70 7468 7265
6164 5f73 6574 7370 6563 6966 6963 5f69
6e74 6572 6e61 6c00 7763 7274 6f6d 6200
5f64 6c5f 636f 7272 6563 745f 6361 6368
655f 6964 005f 646c 5f73 6f72 745f 6669
6e69 005f 5f6e 6577 5f66 6f70 656e 0063
6c6f 7365 005f 5f73 7472 6e63 7079 5f73
7365 3200 5f5f 6c69 6263 5f63 6f6e 6e65
6374 005f 5f77 6d65 6d63 7079 005f 494f
5f69 7465 725f 6e65 7874 006d 355f 7061
6e69 6300 5f64 6c5f 636c 6f73 655f 776f
726b 6572 005f 646c 5f70 6167 6573 697a
6500 5f5f 7661 6c6c 6f63 005f 5f6d 656d
616c 6967 6e5f 686f 6f6b 005f 5f70 7468
7265 6164 5f69 6e69 745f 7374 6174 6963
5f74 6c
您的十六进制转储只是一堆函数名称,所以它告诉我们的不多。你也没有提到操作系统...
我假设如果你可以 运行 gdb
,你也可以使用 GNU binutils。
首先,您可以尝试 objdump -h myprog
。它将给出一个包含大小、加载地址和文件偏移量的部分列表。如果它告诉您有一个部分从 401000
开始,文件偏移量 400
并且大小至少 af4
,那么 运行 时间位置 401af4
在文件中偏移 401af4-401000+400
.
如果有问题的地址在共享库中,或者如果程序对其地址进行了任何重新映射space,任务将会更加困难。
您没有指定处理器或操作系统。看起来像 x86,因为它是一个可变长度的指令集,这使得这变得更加困难,在第一个问题指令上,反汇编器如果你使用它可能会感到困惑,这取决于反汇编器。
尝试找出模拟器响应的具体非法指令是什么,在二进制文件中找到那些位模式,围绕反汇编进行交互,如果发现这些模式,则将它们替换为 nop 并重复,不是万无一失的,并且取决于关于这个二进制文件是如何制作的,可能有一些尝试来防止这种黑客攻击。
当然是一项不平凡的任务...
我有一个旨在 运行 在特定模拟器上的基准测试,一些指令添加到基准测试中以与模拟器通信(不执行 CPU 操作),例如转储统计信息或重置统计数据等等。
现在我需要 运行 在另一个模拟器上进行相同的基准测试,而且确实没有其他解决方法,我必须使用相同的二进制文件,当然它不起作用,因为它会生成 SIGILL
或 Illegal Instruction
错误。
我现在想要的是能够直接从可执行二进制文件中删除错误指令(没有源代码,无法重新编译,无法从其他地方设置) 并将它们替换为 NOP
s。所以我 运行 gdb
中的基准测试并使用 layout asm
命令来查找错误指令的地址。这是输出:
我的问题可能看起来有点愚蠢,但现在我在文本编辑器中打开二进制文件,并尝试使用我从 gdb
获得的地址来查找二进制文件中的非法指令,但没有成功。二进制文件的大小大约为 1MB,而地址从大约 4MB 开始。如何使用从 gdb
获得的地址找到二进制文件中的非法指令?这是二进制文件的一个片段,显示了它的格式:
616c 6967 6e00 5f5f 7265 6769 7374 6572
5f66 7261 6d65 5f69 6e66 6f00 5f49 4f5f
7664 7072 696e 7466 005f 5f70 7468 7265
6164 5f73 6574 7370 6563 6966 6963 5f69
6e74 6572 6e61 6c00 7763 7274 6f6d 6200
5f64 6c5f 636f 7272 6563 745f 6361 6368
655f 6964 005f 646c 5f73 6f72 745f 6669
6e69 005f 5f6e 6577 5f66 6f70 656e 0063
6c6f 7365 005f 5f73 7472 6e63 7079 5f73
7365 3200 5f5f 6c69 6263 5f63 6f6e 6e65
6374 005f 5f77 6d65 6d63 7079 005f 494f
5f69 7465 725f 6e65 7874 006d 355f 7061
6e69 6300 5f64 6c5f 636c 6f73 655f 776f
726b 6572 005f 646c 5f70 6167 6573 697a
6500 5f5f 7661 6c6c 6f63 005f 5f6d 656d
616c 6967 6e5f 686f 6f6b 005f 5f70 7468
7265 6164 5f69 6e69 745f 7374 6174 6963
5f74 6c
您的十六进制转储只是一堆函数名称,所以它告诉我们的不多。你也没有提到操作系统...
我假设如果你可以 运行 gdb
,你也可以使用 GNU binutils。
首先,您可以尝试 objdump -h myprog
。它将给出一个包含大小、加载地址和文件偏移量的部分列表。如果它告诉您有一个部分从 401000
开始,文件偏移量 400
并且大小至少 af4
,那么 运行 时间位置 401af4
在文件中偏移 401af4-401000+400
.
如果有问题的地址在共享库中,或者如果程序对其地址进行了任何重新映射space,任务将会更加困难。
您没有指定处理器或操作系统。看起来像 x86,因为它是一个可变长度的指令集,这使得这变得更加困难,在第一个问题指令上,反汇编器如果你使用它可能会感到困惑,这取决于反汇编器。
尝试找出模拟器响应的具体非法指令是什么,在二进制文件中找到那些位模式,围绕反汇编进行交互,如果发现这些模式,则将它们替换为 nop 并重复,不是万无一失的,并且取决于关于这个二进制文件是如何制作的,可能有一些尝试来防止这种黑客攻击。
当然是一项不平凡的任务...