如何在程序中查找非法指令?

时间:2015-06-10 11:58:22

标签: c++ c assembly gdb benchmarking

我有一个基准,它可以在特定的模拟器上运行,一些指令添加到基准测试中以与模拟器通信(不执行CPU操作),如转储统计信息或重置统计信息等。

现在我需要在另一个模拟器上运行相同的基准测试,并且实际上没有其他工作,我必须使用相同的二进制文件,当然它不起作用,因为它生成#include <stdio.h> #include <stdlib.h> #include <string.h> #define IS_DIGIT(x) \ ( x == '0' || x == '1' || x == '2' || \ x == '3' || x == '4' || x == '5' || x == '6' || \ x == '7' || x == '8' || x == '9' ) /* the function will return 0 in success and -1 in error */ /* on success num will contain the pointer to the number */ int check_last_num(char * str , int * num) { int len = strlen(str); int index = len - 1; /* make sure the last char is ')' */ if (str[index] != ')') return -1; while ( --index >= 0 && (str[index] != '(') ) { char c = str[index]; if ( ! IS_DIGIT(c) ) return -1; } /* loop exit check */ if (index < 0) return -1; *num = atoi((const char *) &str[index + 1]); return 0; } int main(int argc , char *argv[] ) { int rc ; if ( 0 == check_last_num("MyName(890790)" , & rc)) printf ("%d \n" , rc); else printf ("error \n"); return 0; } 或者SIGILL错误。

我现在想要的是能够直接从可执行二进制文件中删除错误指令(无源代码,无法重新编译,无法从其他地方进行设置)并将其替换为Illegal Instruction秒。所以我在NOP中运行了基准测试,并使用gdb命令查找错误指令的地址。这是输出: enter image description here

我的问题可能看起来有点愚蠢,但现在我在文本编辑器中打开了二进制文件,并尝试使用我从layout asm获取的地址来查找二进制文件中的非法指令,但没有运气。二进制文件的大小约为1MB,而地址从大约4MB开始。如何使用gdb中的地址在二进制文件中找到非法指令?以下是二进制文件的片段,显示其格式:

gdb

2 个答案:

答案 0 :(得分:2)

你的十六进制转储只是一堆函数名,所以它并没有告诉我们多少。你没有提到操作系统......

我假设您可以在其上运行gdb,您也可以使用GNU binutils。

首先,您可以尝试objdump -h myprog。它将给出一个包含其大小,加载地址和文件偏移的部分列表。如果它告诉您那里的部分从401000开始,文件偏移量为400且大小至少为af4,则运行时位置401af4位于文件偏移量{ {1}}。

如果违规地址在共享库中,或者程序已经重新映射其地址空间,则任务将更难。

答案 1 :(得分:1)

您没有指定处理器或操作系统。看起来像x86这使得它变得更加困难,因为它是一个可变长度的指令集,在第一个问题指令时反汇编程序如果你使用它可能会混淆,取决于反汇编程序。

尝试找出模拟器响应的具体非法指令,找到二进制中的那些位模式,围绕拆解进行交互,如果发现这些模式用nops替换它们并重复,而不是万无一失,并且取决于如何这个二进制文件可能会有一些尝试来阻止这种黑客行为。

当然是一项非平凡的任务......