CN111857681A - 一种c++系统的软件定义化关键函数定位与提取方法 - Google Patents
一种c++系统的软件定义化关键函数定位与提取方法 Download PDFInfo
- Publication number
- CN111857681A CN111857681A CN202010520447.7A CN202010520447A CN111857681A CN 111857681 A CN111857681 A CN 111857681A CN 202010520447 A CN202010520447 A CN 202010520447A CN 111857681 A CN111857681 A CN 111857681A
- Authority
- CN
- China
- Prior art keywords
- function
- information
- calling
- key function
- key
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Granted
Links
Images
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F8/00—Arrangements for software engineering
- G06F8/30—Creation or generation of source code
- G06F8/31—Programming languages or programming paradigms
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F11/00—Error detection; Error correction; Monitoring
- G06F11/30—Monitoring
- G06F11/34—Recording or statistical evaluation of computer activity, e.g. of down time, of input/output operation ; Recording or statistical evaluation of user activity, e.g. usability assessment
- G06F11/3466—Performance evaluation by tracing or monitoring
- G06F11/3476—Data logging
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F8/00—Arrangements for software engineering
- G06F8/30—Creation or generation of source code
- G06F8/31—Programming languages or programming paradigms
- G06F8/315—Object-oriented languages
Landscapes
- Engineering & Computer Science (AREA)
- General Engineering & Computer Science (AREA)
- Theoretical Computer Science (AREA)
- Software Systems (AREA)
- Physics & Mathematics (AREA)
- General Physics & Mathematics (AREA)
- Computing Systems (AREA)
- Computer Hardware Design (AREA)
- Quality & Reliability (AREA)
- Debugging And Monitoring (AREA)
Abstract
本发明提供了一种C++系统的软件定义化关键函数定位与提取方法,涉及软件分析领域,本发明在基于C++开发的用户系统的可执行文件中进行插桩,以对汇编语言中的函数的运行信息进行记录,获得函数运行日志,然后将该函数运行日志提供给用户,使用户可以在该函数运行日志中搜索、定位包含了业务数据的生成和展示的关键函数,接着对所述关键函数的调用约定和参数类型进行确定,以生成所述关键函数的调用代码,并将所述调用代码注入所述用户系统,以提取所述关键函数,从而有助于软件分析。
Description
技术领域
本发明涉及软件分析领域,特别是涉及一种C++系统的软件定义化关键函数定位与提取方法。
背景技术
关键函数是指应用软件在某个运行阶段发挥着关键作用的核心功能函数。对软件中的关键函数进行快速定位与提取有助于分析理解该软件。然而,软件系统发展到今天,平台众多,不同的平台上软件的运行环境不同,其编程语言、编程框架也千差万别,导致进行关键函数定位与分析的方法也各有不同。其中,C++开发的Windows客户端软件系统占据了很大的比例,在工控等领域很常见。因此,如何辅助开发人员解决没有源码,缺少维护的C++开发的Windows客户端软件系统的关键函数定位和提取问题是非常重要的。
发明内容
本发明公开了一种C++系统的软件定义化关键函数定位与提取方法,包括:
在基于C++开发的用户系统的可执行文件中进行插桩,以对汇编语言中的函数的运行信息进行记录,获得函数运行日志;
显示所述函数运行日志,当接收到用户查询业务数据的触发操作时,在所述函数运行日志中定位所述业务数据关联的关键函数;
根据所述关键函数的运行信息,确定所述关键函数的调用约定和参数类型;
生成所述关键函数的调用代码,将所述调用代码进行封装并注入所述用户系统,以提取所述关键函数。
可选的,所述运行信息包括函数的调用信息、返回信息以及地址信息;在基于C++开发的用户系统的可执行文件中进行插桩,以对汇编语言中的函数的运行信息进行记录,获得函数运行日志,包括:
利用C语言指针在基于C++开发的用户系统的可执行文件中写入插桩代码;
通过所述插桩代码对汇编语言中的函数的调用信息、返回信息以及地址信息进行记录,获得函数运行日志。
可选的,通过所述插桩代码对汇编语言中的函数的调用信息、返回信息以及地址信息进行记录,获得函数运行日志,包括:
在接收到运行所述插桩代码的触发操作时,通过所述插桩代码对汇编语言中的函数的调用信息、返回信息以及地址信息写入所述用户系统的内存;
当所述内存中的数据量达到预设存储阈值时,将所述内存中的所述函数的调用信息、返回信息以及地址信息写入所述函数运行日志。
可选的,所述方法还包括:
确定所述函数中的非逻辑函数;
判断所述非逻辑函数的调用次数;
当所述非逻辑函数的调用次数大于等于预设记录阈值时,停止将所述非逻辑函数的调用信息、返回信息以及地址信息写入所述函数运行日志。
可选的,所述方法还包括:
删除所述函数运行日志中没有对应调用信息的返回信息;
删除所述函数运行日志中没有对应返回信息的调用信息。
可选的,所述函数运行日志包括多个日志文件,所述日志文件与线程一一对应;显示所述函数运行日志,包括:
针对每个线程,在相应的日志文件中,以函数为显示条目,在所述显示条目内显示所述函数的调用信息、返回信息以及地址信息;其中:
针对所述函数的调用信息内部不同层次的调用结构,用缩进表示栈的深度;
所述函数的调用信息、返回信息与所述函数的地址信息具有匹配关系。
可选的,所述方法还包括:
收集所述业务数据对应的字符串;
当接收到用户查询业务数据的触发操作时,在所述函数运行日志中定位所述业务数据关联的关键函数,包括:
当接收到用户查询业务数据的触发操作时,确定所述业务数据对应的字符串;
将所述字符串的富有特征的子串转换为相应的内存编码;
依据所述子串的内存编码在所述函数运行日志中定位所述业务数据关联的关键函数。
可选的,根据所述关键函数的运行信息,确定所述关键函数的调用约定,包括:
根据所述关键函数的运行信息,反汇编获得所述关键函数的地址和调用所述关键函数的返回指令;
根据所述关键函数的地址和调用所述关键函数的返回指令,判断所述关键函数的执行逻辑中是否存在未初始化使用的ecx寄存器和edx寄存器;
当所述关键函数的执行逻辑中存在未初始化使用的ecx寄存器和edx寄存器时,确定所述关键函数采用了_fastcall调用约定;
当所述关键函数的执行逻辑中不存在未初始化使用的ecx寄存器和edx寄存器时,判断所述关键函数的返回指令是否为ret N指令,N为所述关键函数的参数所占的字节总数;
当所述关键函数的返回指令为ret N指令且执行逻辑中不存在未初始化使用的ecx寄存器和edx寄存器时,确定所述关键函数采用了_stdcall调用约定;
当所述关键函数的返回指令不为ret N指令且执行逻辑中不存在未初始化就使用的ecx寄存器和edx寄存器时,判断所述关键函数在调用并且返回后,是否负责了被调用函数参数的清除工作;如果是,确定用户采用了_cdecl调用约定;
根据所述关键函数的运行信息,确定所述关键函数的参数类型,包括:
将所述关键函数的运行信息在各种参数类型下的内容进行显示;
当接收到用户选择目标参数类型的触发操作时,将所述目标参数类型确定为所述关键函数的参数类型。
可选的,判断所述关键函数的执行逻辑中是否存在未初始化就使用的ecx寄存器和edx寄存器,包括:
判断在所述ecx寄存器和所述edx寄存器被作为源操作数使用之前,是否有指令对所述ecx寄存器和所述edx寄存器的内容进行了写操作;
如果有,确定所述ecx寄存器和所述edx寄存器为先经过赋值操作再使用的。
可选的,生成所述关键函数的调用代码,将所述调用代码进行封装并注入所述用户系统,以提取所述关键函数,包括:
将所述关键函数的地址、调用约定和参数类型编写为所述关键函数的调用代码;
通过网络请求方式在所述调用代码中输入参数和控制逻辑,以控制对所述关键函数的调用;
使用进程注入工具在所述用户系统中开辟线程,将所述调用代码注入所述用户系统,以提取所述关键函数。
与现有技术相比,本发明包括以下优点:
本发明实施例在基于C++开发的用户系统的可执行文件中进行插桩,以对汇编语言中的函数的运行信息进行记录,获得函数运行日志,然后将该函数运行日志提供给用户,使用户可以所述函数运行日志中搜索、定位包含了业务数据的生成和展示的关键函数,接着对所述关键函数的调用约定和参数类型进行确定,以生成所述关键函数的调用代码,并将所述调用代码注入所述用户系统,以提取所述关键函数,从而可以辅助开发者实现软件功能的理解。
附图说明
图1是本发明实施例一种C++系统的软件定义化关键函数定位与提取方法的整体思路示意图;
图2是本发明实施例一种C++系统的软件定义化关键函数定位与提取方法的步骤流程图;
图3是本发明实施例通过内存缓冲提高插桩效率的流程示意图;
图4是本发明实施例减少非业务数据部分的插桩数量的流程示意图;
图5是本发明实施例的函数调用约定判断流程;
图6是本发明实施例一个关键函数的调用代码示例图;
图7是本发明实施例一种关键函数的提取工具的框架示意图;
图8.1是本实例的插桩时间开销示意图;
图8.2是本实例的插桩空间开销示意图;
图8.3是本实例的S省化学仪器控制系统和表格A的示意图;
图8.4是本实例获得的函数运行日志的示意图;
图8.5是本实例加载最大的日志文件的示意图;
图8.6是本实例在最大的日志文件中定位关键函数的示意图;
图8.7是本实例分析关键函数的示意图。
具体实施方式
为使本发明的上述目的、特征和优点能够更加明显易懂,下面结合附图和具体实施方式对本发明作进一步详细的说明。
针对本发明所提出的技术问题,本发明提出了一种从C++开发的Windows客户端软件系统的业务逻辑层,即自身的代码入手,找到汇编代码中的函数,对其中包含了业务数据的生成和展示的关键函数进行快速定位与提取的方法,可以有助于开发者分析、理解该软件。
参照图1,示出了本发明实施例一种C++系统的软件定义化关键函数定位与提取方法的整体思路示意图。本发明实施例的关键函数指包含了业务数据的生成和展示的函数,通过将用户使用的用户系统中的关键函数提取出来,独立运行,那么就能够实现对用户系统中的业务数据的提取。因此,本发明问题的输入是用户系统(即C++开发的Windows客户端软件系统),输出则是包含关键函数逻辑的API接口,执行这些接口,就执行了原用户系统中的关键函数代码,从而辅助开发者实现软件的理解。
参照图2,示出了本发明实施例一种C++系统的软件定义化关键函数定位与提取方法的步骤流程图,可以包括以下步骤:
步骤S201,在基于C++开发的用户系统的可执行文件中进行插桩,以对汇编语言中的函数的运行信息进行记录,获得函数运行日志;
就步骤S201而言,记录过程可以如下:
开发者建立trace文件夹,生成并修改配置文件,设置要记录的文件列表,这个配置限制了插桩的文件数量,一般先对主程序进行。之后,通过drrun程序打开原用户系统,跳转至业务数据展示之前的页面。接下来设置记录工具为开始记录,进行业务数据展示相关的操作,停止记录,关闭原用户系统。这样,记录工具会在trace文件夹留下多个文件,每个文件记录了一个线程中的所有函数调用相关信息。该trace文件夹即为本发明实施例的函数运行日志。
在本发明实施例中,插桩,是在保证被测程序原有逻辑完整性的基础上在程序中插入一些探针代码,通过探针的执行来收集程序运行时信息,以达到软件测试目的的技术。本发明实施例可选用代码插桩中的目标代码插桩方法在用户系统的可执行文件中进行插桩,具体可通过目标代码插桩方法中的动态二进制插桩框架直接在用户系统的可执行文件中运行,这样就不需要程序的源代码,也不需要重新编译或重新链接程序,可实现对许多无源码的用户系统进行分析。需要强调的是,本发明实施例的可执行文件也可用二进制文件表示。
函数的运行信息指用户系统运行时的函数调用栈信息,这些信息将作为关键函数信息定位和分析的基础。但在汇编代码中,函数的数量很多,例如一个最简单10行左右的求斐波那契数列值的C++代码,编译之后的汇编代码中就有501个函数。记录线程中函数的运行信息带来的额外开销会成倍的增长,过多的额外时间、空间开销会导致程序插桩后运行崩溃,用户难以进行操作,而在这些函数中准确、没有遗漏的找到业务数据关联的关键函数又是一个难点。因此,如何解决函数数量规模大带来的时间效率问题,就是本发明实施例的一大挑战。
针对上述挑战,本发明实施例从两方面入手,考虑两个思路,第一是对于每个插桩的位置插入的代码,运行的开销要尽量小;第二是要减少插桩的数量。
对于第一方面,单次插桩运行开销优化:
首先,本发明实施例在基于C++开发的用户系统的可执行文件中进行插桩。
其次,本发明实施例提出了一种优选记录方法,所述运行信息可以包括函数的调用信息、返回信息以及地址信息;步骤S201具体可以包括以下子步骤:
子步骤S201-1,利用C语言指针在基于C++开发的用户系统的可执行文件中写入插桩代码;
子步骤S201-2,通过所述插桩代码对汇编语言中的函数的调用信息、返回信息以及地址信息进行记录,获得函数运行日志。
发明人通过对业务数据进行分析,发现业务数据可能是函数的返回值,也可能是作为参数传递指针到函数中,再在函数中进行赋值和引用。因此,本发明实施例设定插桩代码对函数的调用信息、返回信息以及地址信息进行记录,可从繁多的函数中找到和业务数据关联的关键函数,既能保证业务数据记录的全面性,还能同时兼顾记录的效率。本发明实施例利用C语言指针撰写插桩代码,写入速度较快,可提高插桩代码的执行效率。
另外,由于写文件的操作十分频繁,效率很低,本发明实施例进一步对子步骤S201-2进行优化,包括以下步骤:
第一步,在接收到运行所述插桩代码的触发操作时,通过所述插桩代码对汇编语言中的函数的调用信息、返回信息以及地址信息写入所述用户系统的内存;
第二步,当所述内存中的数据量达到预设存储阈值时,将所述内存中的所述函数的调用信息、返回信息以及地址信息写入所述函数运行日志。
本发明实施例使用了缓存的方式,就是在每次插桩代码运行时,先不输出信息,而是把信息先缓存到内存中,当缓存满后再一次性输出,可进一步提高插桩程序的效率。参照图3,示出了本发明实施例通过内存缓冲提高插桩效率的流程示意图。
对于第二方面,减少插桩的数量:
首先,本发明实施例减少非业务数据部分的插桩数量,即在接收到插桩工具的开始操作和结束操作时,对业务数据关联的函数的运行信息进行记录。假设需要的业务数据是点击Event按钮后窗口处的信息,本发明实施例设置在点击Event按钮前,不记录任何信息,点击之后开始记录,直到信息显示完全。以此可以节省大量的时间开销,特别是程序启动时,往往逻辑非常复杂,如果从程序一启动开始记录,时间的开销会非常大,实际情况下甚至几分钟程序都不能启动。参照图4,示出了本发明实施例减少非业务数据部分的插桩数量的流程示意图。
其次,本发明实施例对汇编代码中与原用户系统业务不相关但会被反复调用的函数进行优化,优化方法可以包括以下步骤:
确定所述函数中的非逻辑函数;
判断所述非逻辑函数的调用次数;
当所述非逻辑函数的调用次数大于等于预设记录阈值时,停止将所述非逻辑函数的调用信息、返回信息以及地址信息写入所述函数运行日志。
针对上述优化方法,本发明实施例采用了以下例子进行说明:栈溢出是编程中常出现的错误之一,Windows的cl编译器如果开启了/GS编译选项,就会用一种机制来避免栈溢出的发生。具体来说,对每个可能出现的栈溢出的函数,都会插入一个名为___security_cookie的函数,这个函数会通过检查栈上的一个不变量来确定是否出现栈溢出。那么在这个例子中,___security_cookie这个函数就和原系统中开发者编写的业务数据的逻辑函数无关,就是指本发明实施例中的非逻辑函数。对于这个函数就没有必要一次次的输出其信息,值输出预设记录阈值之前次数的运行时信息即可。预设记录阈值是一个可变参数,可以在插桩程序运行之前自行调整,值越大,记录越详细,运行效率越低,反之亦然。优选设置为10,这样可以有效的降低程序运行的时间。
另外,由于函数运行日志中会记录程序运行的一个片段内的函数调用和返回,然而,这样的记录存在很多误记信息。因此,发明人提出了对函数运行日志的误记信息的清洗和筛选方法,所述方法包括:
删除所述函数运行日志中没有对应调用信息的返回信息;
删除所述函数运行日志中没有对应返回信息的调用信息。
经发明人研究发现,误记信息主要有两部分,一部分是没有对应调用信息的返回信息,这类信息主要是由于开启日志记录的时间点是在程序运行的过程中,而这个时间节点下,可能有很多的函数已经调用但没有返回,这会导致存在一些找不到调用信息的返回信息。另外,有时汇编代码中,call和ret可能不是一一对应的,这是因为实际上汇编代码的call和ret指令只是一个特殊的跳转指令,一个ret可能对应的是之前的一次跳转,这样也会导致出现没有对应调用信息的返回信息。再者,可能由于插桩工具本身的局限性,存在一定可能性缺少调用信息的记录。另一部分是没有对应返回信息的调用信息,产生原因与没有对应调用信息的返回信息类似,即函数运行日志中断时,有很多调用的返回信息没有被工具记录,或是由于插桩工具的误记录。
对于上述两种误记信息,本发明实施例将其删除,以使得到的函数运行日志中的调用和返回都可以一一对应,可以还原为一个完整的栈结构,从而提供给关键函数的定位和分析工具来进行展示和分析。
步骤S202,向用户显示所述函数运行日志,当接收到用户查询业务数据的触发操作时,在所述函数运行日志中定位所述业务数据关联的关键函数;
在此步骤中,开发者首先通过可视化界面,打开步骤S201中记录的信息。这样可以查看原用户系统的函数调用栈和每个函数的运行信息。之后通过对原用户系统界面中业务数据的搜索和筛选,找到所述业务数据关联的函数,即关键函数。
为便于用户查找定位关键函数,本发明实施例提出了以下显示原则:第一,对于每个函数,在其开始和结束时,都记录了八个寄存器的值和栈上的值,又记录了这些值作为指针时,指针内存处的信息。这导致每个条目的信息实际上会达到几百个字符左右的量,需要将这些混乱的信息条理清晰的展示。第二,插桩记录的日志是顺序的,但是函数之间的调用和返回是层次的,需要对各个函数之间的调用层次进行直观清晰的展示。第三,程序运行时会产生很多线程,每个线程的函数调用顺序结构是相对独立的,需要对这些不同的线程进行分别显示。
综合上述显示原则,本发明在步骤S201中进行记录时,首先对不同的线程分文件记录,以此获得的函数运行日志可以包括多个日志文件,所述日志文件与线程一一对应;之后,步骤S202中向用户显示所述函数运行日志,具体可以包括下述显示方式:
针对每个线程,在相应的日志文件中,以函数为显示条目,在所述显示条目内显示所述函数的调用信息、返回信息以及地址信息;其中:
针对所述函数的调用信息内部不同层次的调用结构,用缩进表示栈的深度;
所述函数的调用信息、返回信息与所述函数的地址信息具有匹配关系。本发明实施例对于每个线程的信息,以函数为单位显示各个条目,将混乱的调用信息、返回信息以及地址信息以函数为单位条理清晰的展示,可便于用户快速确定每个函数的调用信息、返回信息、地址信息以及栈的深度和匹配关系。
将函数运行日志提供给用户后,接下来,需要根据用户针对业务数据的查询操作,在函数运行日志中从繁多的函数中定位该业务数据关联的关键函数,本发明实施例可用业务数据当做锚点,通过锚点检索定位到关键函数。但为了避免检索过程中误报,以提高定位的准确性,本发明实施例提出了一种通过字符串进行关键函数定位的方法:首先,收集所述业务数据对应的字符串;其次,将字符串作为锚点进行关键函数的检索定位。在本发明一可选实施例中,步骤S202中的当接收到用户查询业务数据的触发操作时,在所述函数运行日志中定位所述业务数据关联的关键函数,可以包括以下子步骤:
子步骤S202-1,当接收到用户查询业务数据的触发操作时,确定所述业务数据对应的字符串;
子步骤S202-2,将所述字符串的富有特征的子串转换为相应的内存编码;
子步骤S202-3,依据所述子串的内存编码在所述函数运行日志中定位所述业务数据关联的关键函数。
为实现上述过程,在业务数据的收集的过程中,需要更加关注的是业务数据的字符串。在C++程序的内存中,字符串可能存储在栈空间或是堆空间中,可能是C++内建string类型或者char类型数组。但是字符串存放的位置还是信息的变量类型,在参数传递时,都是通过传入一个字符串的首指针来传递。因此,对于内存信息,如果只输出函数调用前后的栈信息、寄存器信息等,得到的只有指针的首地址,而不能了解字符串具体的值。综上所述,对于栈中和寄存器中的值,除了输出值本身,还需要将其当作指针,输出指针指向的一系列值,即本发明实施例的字符串可指指针指向的一系列值。并且,对于多重嵌套的数据结构,还需要输出其多次指向最后的结果。指针的嵌套可能层数不确定,但是大多集中在3层以内,本发明实施例取最多三层作为信息提取的上限。因此,本发明实施例在函数插桩过程中需要统计的信息,即在函数的调用、返回时统计所有寄存器中的值以及栈上指定长度的值,对于上述值中可看做指针的,需要继续统计其指针所指向的内存处的信息。
本发明实施例采用所述业务数据对应的字符串作为锚点进行检索定位,对于一个用户系统,显示的字符串在内存中存在的形式可能是多种不同的编码格式。常见的格式就有ASCII、GBK、UTF-8和UNICODE等。因此,在实际对字符串进行搜索时,本发明实施例将所述字符串的富有特征的子串转换为相应的内存编码,再在系统中对内存编码进行搜索,以依据所述子串的内存编码在所述函数运行日志中定位所述业务数据关联的关键函数。
步骤S203,根据所述关键函数的运行信息,确定所述关键函数的调用约定和参数类型;
开发者通过对业务数据所在的位置对函数进行分析,主要是确认函数的调用约定,参数类型信息,并确认如何通过调用函数得到业务数据。由于业务数据可能在函数的返回值或是函数的参数中存在,需要确定该函数是真正对业务数据进行生成的逻辑块,有时甚至需要查看原系统的汇编代码来进一步分析。因此,在本发明一可选实施例中,步骤S203中的根据所述关键函数的运行信息,确定所述关键函数的调用约定,可以包括以下步骤:
根据所述关键函数的运行信息,反汇编获得所述关键函数的地址和调用所述关键函数的返回指令;
根据所述关键函数的地址和调用所述关键函数的返回指令,判断所述关键函数的执行逻辑中是否存在未初始化使用的ecx寄存器和edx寄存器;
当所述关键函数的执行逻辑中存在未初始化使用的ecx寄存器和edx寄存器时,确定所述关键函数采用了_fastcall调用约定;
当所述关键函数的执行逻辑中不存在未初始化使用的ecx寄存器和edx寄存器时,判断所述关键函数的返回指令是否为ret N指令,N为所述关键函数的参数所占的字节总数;
当所述关键函数的返回指令为ret N指令且执行逻辑中不存在未初始化使用的ecx寄存器和edx寄存器时,确定所述关键函数采用了_stdcall调用约定;
当所述关键函数的返回指令不为ret N指令且执行逻辑中不存在未初始化就使用的ecx寄存器和edx寄存器时,判断所述关键函数在调用并且返回后,是否负责了被调用函数参数的清除工作;如果是,确定用户采用了_cdecl调用约定;
其中,判断所述关键函数的执行逻辑中是否存在未初始化就使用的ecx寄存器和edx寄存器,包括:
判断在所述ecx寄存器和所述edx寄存器被作为源操作数使用之前,是否有指令对所述ecx寄存器和所述edx寄存器的内容进行了写操作;
如果有,确定所述ecx寄存器和所述edx寄存器为先经过赋值操作再使用的。
上述所提及的反汇编可以通过各种各样的反汇编程序来完成,本发明实施例以IDA pro为例子,通过IDA pro生成的.map文件和.asm文件,可以知道某个内存地址处的函数的汇编代码,在有了函数汇编代码后,本发明实施例通过一系列步骤来判断函数的调用约定。上述函数的汇编代码的即指所述关键函数的地址和调用所述关键函数的返回指令,所述关键函数的地址可包括起始地址和结束地址,调用所述关键函数的返回指令可指结束地址处的指令。参照图5,示出了本发明实施例的函数调用约定判断流程。
在本发明一可选实施例中,步骤S203中的根据所述关键函数的运行信息,确定所述关键函数的参数类型,可以包括以下步骤:
将所述关键函数的运行信息在各种参数类型下的内容进行显示;
当接收到用户选择目标参数类型的触发操作时,将所述目标参数类型确定为所述关键函数的参数类型。
对于函数参数类型的判断,本发明实施例的主要方法是,对关键函数的运行信息进行分析,显示信息在各种参数类型条件下的内容,用户可以根据参数的实际意义来给出具体判断,筛选相对更合理、更有实际意义的类型。如表1展示了一个栈内的元素,在不同参数类型,不同编码形式下的值。
表1:不同参数类型下参数的意义
从表1可以看出,可以看出,不同的参数类型下,数据会有不同的含义。这些不确定的含义需要开发者人工确认,主要方法是确认数据在各个参数类型下的含义有没有意义。例如,上表中的参数作为string(gbk)类型时,有明显的实际含义,用户可以据此判断,该参数的类型是string,编码类型是gbk。MessyCode代表无法解析的乱码。
步骤S204,生成所述关键函数的调用代码,将所述调用代码进行封装并注入所述用户系统,以提取所述关键函数。
在本发明一可选实施例中,步骤S204可以通过以下子步骤实现:
子步骤S204-1,将所述关键函数的地址、调用约定和参数类型编写为所述关键函数的调用代码;
子步骤S204-2,通过网络请求方式在所述调用代码中输入参数和控制逻辑,以控制对所述关键函数的调用;
子步骤S204-3,使用进程注入工具在所述用户系统中开辟线程,将所述调用代码注入所述用户系统,以提取所述关键函数。
在本发明实施例中,子步骤S204-1可以参照图6所示方法编写所述关键函数的调用代码。编写完代码后,本发明实施例通过网络请求方式在所述调用代码中输入参数和控制逻辑,完成对所述调用代码的封装。接着,使用进程注入工具将所述调用代码注入所述用户系统,以通过所述调用代码调用原用户系统中的关键函数,以此完成了对关键函数的提取。本发明实施例的进程注入工具采用的是进程注入技术。具体的,可以CreateRemoteThread和LoadLibrary两个系统API为基础,将上面编写的调用代码编译为dll,插入原程序的进程中。此外,在编译的dll中,也可以插入一系列触发器,例如网络请求,键盘监听器等。这样可以通过触发器的触发,反复地对编写的关键函数提取器进行调用,达到测试的目的。
综合步骤S201~步骤S204,参照图7,示出了本发明实施例一种关键函数的提取工具的框架示意图,工具主要包含两大块,函数日志记录模块和函数定位分析模块,记录模块将生成好的日志信息交给定位分析模块。其中,函数日志记录模块中,控制模块主要负责控制在原用户系统运行时,在不干扰原用户系统的情况下,控制日志记录的开始和结束。函数信息输出模块是主要的插桩逻辑,它在程序运行时一同运行,负责输出函数信息。日志清洗模块负责在日志输出之后,再进行一次数据清洗,删除误记录的数据。函数定位分析模块中,关键函数定位模块具有展示日志和搜索日志两大功能,实现在Web端。关键函数分析模块基于定位模块,在Web端的后端进行调用约定和参数的分析,并将结果展示到前端供开发者查看。
接下来,本发明实施例以S省科学院化学仪器控制系统为实例,对本发明实施例的一种关键函数提取方法进行验证。
第一,对函数日志记录模块性能评估:
本实例选取S省科学院化学仪器控制系统中的两个窗口,与H省工业控制系统中的一个窗口进行分析,在后文中分别用窗口1、2、3来表示。
表2:窗口信息统计
表2统计了各个窗口的控件数量和控件类型,可以看到,窗口1、窗口3的控件类型较为复杂,数据都在表格中,窗口2的控件数量多,但控件类型多为String,数据较为分散。此外,窗口1、窗口3的表格数据无法通过Windows句柄的方式直接获得,这侧面验证了本方法的通用性。
本实例对三个窗口进行插桩后的时间效率进行统计,分别统计了未插桩时,完全插桩时和优化后插桩时的窗口开启时间,如图8.1所示。此外,还对完全插桩和优化后插桩生成的日志大小进行了统计,如图8.2所示。从图8.2可看出,本实例的优化方法带来了时间和空间方面的开销减少,其中,时间开销最多减少了81.8%,平均减少了75.3%,空间开销最多减少了80.2%,平均减少了79.9%。可以发现,本实例的方法可以大大减少插桩带来的时间和空间开销。
第二,对关键函数定位分析模块性能评估:
由于日志的量很大,对这样量级的日志进行展示、搜索、分析需要消耗一定的时间。本实例将给出具体的函数定位分析模块的时间消耗,更直观的展示模块的性能,以证明模块的可用性。
表3:函数定位分析模块的时间开销
由表3中数据可以看到,定位分析模块的时间消耗基本和日志大小相关。这是由于本实例中的展示、搜索、分析都是线性扫描日志得出结果的。据此可以看到,函数日志分析模块的时间消耗是在可用范围内的。
第三、C++应用关键函数提取的可用性的实例验证:
图8.3示出了S省化学仪器控制系统和表格A的示意图,S省化学仪器控制系统是一个化学分析仪器的PC端控制系统,用户可以设定好仪器的分析模式、分析流程,控制仪器的工作序列。如果需要提取表格A中间部分圈红的数据,那么尝试去搜索一个字母L,可能的结果有很多,因为L的内存编码0x6C可能在内存的各个位置出现,但是它代表的意义并不是字母L,这会导致很高的误报率。如果搜索后面的字符串“CB Cd/2ng/TR”,内存中重复出现的概率就会小很多。因此,本实例可将字符串“CB Cd/2ng/TR”作为锚点。
首先,本实例对系统进行插桩,在这里,只关心显示表格A的窗口,因此在开启窗口之前开始插桩,等待窗口完全显示结束,最后在关闭窗口之后关闭插桩。如图8.4所示,根据每个线程一个得到一个日志文件,共17个。可以看到,日志中有些线程为空,这是由于本实例限制了日志记录的范围,有些附加库中的日志没有记录,导致涉及该附加库的线程中没有记录。此外,可以看到有几个日志文件尤其大(如图中的0,10,11,15号日志),这是因为化学仪器控制系统中有很多子窗口,这每一个子窗口会分配独立的线程,每个窗口对应的主线程函数调用比较多。
之后,使用函数定位分析模块加载最大的11号线程的日志,如图8.5所示。将锚点“CB Cd/2ng/TR”转换为ASCII编码并搜索,可以看到,搜索到的结果很多,这里以一条为例,如图8.6所示。可以看到,该函数的ecx寄存器存储有关键信息。之后,通过右键点击函数的显示条目,在该显示条目内列出函数的调用约定和可能的调用参数。图8.7中,左侧高亮部分是日志内的信息,右侧的是对该信息的分析结果。分析结果中显示,调用约定为fastcall类型,其中,ecx寄存器,即函数的第一个参数处存储了所需的业务数据。因此,该函数的作用是将函数的第一个参数赋值为我们想要的业务数据,根据这个函数的信息,结合汇编源码中的信息,可以编写信息提取的程序片段。将该函数注入原程序中,可以正确的得到表格A中的第一行数据“Cd L W-A 2014-11-14 15:17CB Cd/2ng/TR”。
可见,经过上述提取过程表明,本实例可以正确的记录函数信息,并通过函数信息找到关键函数并进行提取。
本说明书中的各个实施例均采用递进的方式描述,每个实施例重点说明的都是与其他实施例的不同之处,各个实施例之间相同相似的部分互相参见即可。
以上对本发明所提供的一种C++系统的软件定义化关键函数定位与提取方法进行了详细介绍,本文中应用了具体个例对本发明的原理及实施方式进行了阐述,以上实施例的说明只是用于帮助理解本发明的方法及其核心思想;同时,对于本领域的一般技术人员,依据本发明的思想,在具体实施方式及应用范围上均会有改变之处,综上所述,本说明书内容不应理解为对本发明的限制。
Claims (10)
1.一种C++系统的软件定义化关键函数定位与提取方法,其特征在于,包括:
在基于C++开发的用户系统的可执行文件中进行插桩,以对汇编语言中的函数的运行信息进行记录,获得函数运行日志;
显示所述函数运行日志,当接收到用户查询业务数据的触发操作时,在所述函数运行日志中定位所述业务数据关联的关键函数;
根据所述关键函数的运行信息,确定所述关键函数的调用约定和参数类型;
生成所述关键函数的调用代码,将所述调用代码进行封装并注入所述用户系统,以提取所述关键函数。
2.根据权利要求1所述的方法,其特征在于,所述运行信息包括函数的调用信息、返回信息以及地址信息;在基于C++开发的用户系统的可执行文件中进行插桩,以对汇编语言中的函数的运行信息进行记录,获得函数运行日志,包括:
利用C语言指针在基于C++开发的用户系统的可执行文件中写入插桩代码;
通过所述插桩代码对汇编语言中的函数的调用信息、返回信息以及地址信息进行记录,获得函数运行日志。
3.根据权利要求2所述的方法,其特征在于,通过所述插桩代码对汇编语言中的函数的调用信息、返回信息以及地址信息进行记录,获得函数运行日志,包括:
在接收到运行所述插桩代码的触发操作时,通过所述插桩代码对汇编语言中的函数的调用信息、返回信息以及地址信息写入所述用户系统的内存;
当所述内存中的数据量达到预设存储阈值时,将所述内存中的所述函数的调用信息、返回信息以及地址信息写入所述函数运行日志。
4.根据权利要求3所述的方法,其特征在于,所述方法还包括:
确定所述函数中的非逻辑函数;
判断所述非逻辑函数的调用次数;
当所述非逻辑函数的调用次数大于等于预设记录阈值时,停止将所述非逻辑函数的调用信息、返回信息以及地址信息写入所述函数运行日志。
5.根据权利要求1~4任一项所述的方法,其特征在于,所述方法还包括:
删除所述函数运行日志中没有对应调用信息的返回信息;
删除所述函数运行日志中没有对应返回信息的调用信息。
6.根据权利要求2所述的方法,其特征在于,所述函数运行日志包括多个日志文件,所述日志文件与线程一一对应;显示所述函数运行日志,包括:
针对每个线程,在相应的日志文件中,以函数为显示条目,在所述显示条目内显示所述函数的调用信息、返回信息以及地址信息;其中:
针对所述函数的调用信息内部不同层次的调用结构,用缩进表示栈的深度;
所述函数的调用信息、返回信息与所述函数的地址信息具有匹配关系。
7.根据权利要求1或6所述的方法,其特征在于,所述方法还包括:
收集所述业务数据对应的字符串;
当接收到用户查询业务数据的触发操作时,在所述函数运行日志中定位所述业务数据关联的关键函数,包括:
当接收到用户查询业务数据的触发操作时,确定所述业务数据对应的字符串;
将所述字符串的富有特征的子串转换为相应的内存编码;
依据所述子串的内存编码在所述函数运行日志中定位所述业务数据关联的关键函数。
8.根据权利要求1所述的方法,其特征在于,根据所述关键函数的运行信息,确定所述关键函数的调用约定,包括:
根据所述关键函数的运行信息,反汇编获得所述关键函数的地址和调用所述关键函数的返回指令;
根据所述关键函数的地址和调用所述关键函数的返回指令,判断所述关键函数的执行逻辑中是否存在未初始化使用的ecx寄存器和edx寄存器;
当所述关键函数的执行逻辑中存在未初始化使用的ecx寄存器和edx寄存器时,确定所述关键函数采用了_fastcall调用约定;
当所述关键函数的执行逻辑中不存在未初始化使用的ecx寄存器和edx寄存器时,判断所述关键函数的返回指令是否为ret N指令,N为所述关键函数的参数所占的字节总数;
当所述关键函数的返回指令为ret N指令且执行逻辑中不存在未初始化使用的ecx寄存器和edx寄存器时,确定所述关键函数采用了_stdcall调用约定;
当所述关键函数的返回指令不为ret N指令且执行逻辑中不存在未初始化就使用的ecx寄存器和edx寄存器时,判断所述关键函数在调用并且返回后,是否负责了被调用函数参数的清除工作;如果是,确定用户采用了_cdecl调用约定;
根据所述关键函数的运行信息,确定所述关键函数的参数类型,包括:
将所述关键函数的运行信息在各种参数类型下的内容进行显示;
当接收到用户选择目标参数类型的触发操作时,将所述目标参数类型确定为所述关键函数的参数类型。
9.根据权利要求8所述的方法,其特征在于,判断所述关键函数的执行逻辑中是否存在未初始化就使用的ecx寄存器和edx寄存器,包括:
判断在所述ecx寄存器和所述edx寄存器被作为源操作数使用之前,是否有指令对所述ecx寄存器和所述edx寄存器的内容进行了写操作;
如果有,确定所述ecx寄存器和所述edx寄存器为先经过赋值操作再使用的。
10.根据权利要求8所述的方法,其特征在于,生成所述关键函数的调用代码,将所述调用代码进行封装并注入所述用户系统,以提取所述关键函数,包括:
将所述关键函数的地址、调用约定和参数类型编写为所述关键函数的调用代码;
通过网络请求方式在所述调用代码中输入参数和控制逻辑,以控制对所述关键函数的调用;
使用进程注入工具在所述用户系统中开辟线程,将所述调用代码注入所述用户系统,以提取所述关键函数。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202010520447.7A CN111857681B (zh) | 2020-06-08 | 2020-06-08 | 一种c++系统的软件定义化关键函数定位与提取方法 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202010520447.7A CN111857681B (zh) | 2020-06-08 | 2020-06-08 | 一种c++系统的软件定义化关键函数定位与提取方法 |
Publications (2)
Publication Number | Publication Date |
---|---|
CN111857681A true CN111857681A (zh) | 2020-10-30 |
CN111857681B CN111857681B (zh) | 2021-04-30 |
Family
ID=72987325
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN202010520447.7A Active CN111857681B (zh) | 2020-06-08 | 2020-06-08 | 一种c++系统的软件定义化关键函数定位与提取方法 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN111857681B (zh) |
Cited By (3)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN113032254A (zh) * | 2021-03-19 | 2021-06-25 | 中国工商银行股份有限公司 | 测试覆盖情况的评估方法和装置 |
CN113238801A (zh) * | 2021-05-17 | 2021-08-10 | 上海中通吉网络技术有限公司 | 快递扫描信息采集方法、装置和系统 |
CN114968417A (zh) * | 2021-02-25 | 2022-08-30 | 中移物联网有限公司 | 一种函数调用方法、装置及设备 |
Citations (13)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN102314358A (zh) * | 2011-05-30 | 2012-01-11 | 兰雨晴 | 一种在云平台上以soa的方式部署常规应用的方法 |
CN102460408A (zh) * | 2009-06-01 | 2012-05-16 | 惠普开发有限公司 | 用于收集应用性能数据的系统和方法 |
US20130232133A1 (en) * | 2010-12-03 | 2013-09-05 | Awny K. Al-omari | Systems and methods for performing a nested join operation |
CN103631712A (zh) * | 2013-10-23 | 2014-03-12 | 北京信息控制研究所 | 一种基于内存管理的模式化软件关键行为跟踪方法 |
CN103714288A (zh) * | 2013-12-26 | 2014-04-09 | 华中科技大学 | 一种数据流跟踪方法 |
CN106502907A (zh) * | 2016-10-28 | 2017-03-15 | 中国科学院软件研究所 | 一种基于执行轨迹追踪的分布式软件异常诊断方法 |
CN107168881A (zh) * | 2017-06-07 | 2017-09-15 | 成都四象联创科技有限公司 | 代码异常定位与处理方法 |
CN109240700A (zh) * | 2018-07-06 | 2019-01-18 | 北京大学 | 关键代码定位方法与系统 |
CN109992968A (zh) * | 2019-03-25 | 2019-07-09 | 北京理工大学 | 基于二进制动态插桩的Android恶意行为动态检测方法 |
US20190260770A1 (en) * | 2018-02-20 | 2019-08-22 | Darktrace Limited | Appliance extension for remote communication with a cyber security appliance |
CN110213243A (zh) * | 2019-05-15 | 2019-09-06 | 浙江大学 | 一种基于动态污点分析的工业通信协议逆向分析方法 |
CN110489130A (zh) * | 2018-05-31 | 2019-11-22 | 北京数聚鑫云信息技术有限公司 | 一种基于客户端的业务数据提取方法及装置 |
CN111046396A (zh) * | 2020-03-13 | 2020-04-21 | 深圳开源互联网安全技术有限公司 | web应用测试数据流跟踪方法及系统 |
-
2020
- 2020-06-08 CN CN202010520447.7A patent/CN111857681B/zh active Active
Patent Citations (14)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN102460408A (zh) * | 2009-06-01 | 2012-05-16 | 惠普开发有限公司 | 用于收集应用性能数据的系统和方法 |
US20130232133A1 (en) * | 2010-12-03 | 2013-09-05 | Awny K. Al-omari | Systems and methods for performing a nested join operation |
CN102314358A (zh) * | 2011-05-30 | 2012-01-11 | 兰雨晴 | 一种在云平台上以soa的方式部署常规应用的方法 |
CN103631712A (zh) * | 2013-10-23 | 2014-03-12 | 北京信息控制研究所 | 一种基于内存管理的模式化软件关键行为跟踪方法 |
CN103714288A (zh) * | 2013-12-26 | 2014-04-09 | 华中科技大学 | 一种数据流跟踪方法 |
CN106502907A (zh) * | 2016-10-28 | 2017-03-15 | 中国科学院软件研究所 | 一种基于执行轨迹追踪的分布式软件异常诊断方法 |
CN107168881A (zh) * | 2017-06-07 | 2017-09-15 | 成都四象联创科技有限公司 | 代码异常定位与处理方法 |
US20190260770A1 (en) * | 2018-02-20 | 2019-08-22 | Darktrace Limited | Appliance extension for remote communication with a cyber security appliance |
US20190260785A1 (en) * | 2018-02-20 | 2019-08-22 | Darktrace Limited | Endpoint agent and system |
CN110489130A (zh) * | 2018-05-31 | 2019-11-22 | 北京数聚鑫云信息技术有限公司 | 一种基于客户端的业务数据提取方法及装置 |
CN109240700A (zh) * | 2018-07-06 | 2019-01-18 | 北京大学 | 关键代码定位方法与系统 |
CN109992968A (zh) * | 2019-03-25 | 2019-07-09 | 北京理工大学 | 基于二进制动态插桩的Android恶意行为动态检测方法 |
CN110213243A (zh) * | 2019-05-15 | 2019-09-06 | 浙江大学 | 一种基于动态污点分析的工业通信协议逆向分析方法 |
CN111046396A (zh) * | 2020-03-13 | 2020-04-21 | 深圳开源互联网安全技术有限公司 | web应用测试数据流跟踪方法及系统 |
Non-Patent Citations (1)
Title |
---|
黄双玲: "面向C/C++程序函数调用关系的静态分析方法研究", 《中国优秀硕士学位论文全文数据库 信息科技辑》 * |
Cited By (5)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN114968417A (zh) * | 2021-02-25 | 2022-08-30 | 中移物联网有限公司 | 一种函数调用方法、装置及设备 |
CN114968417B (zh) * | 2021-02-25 | 2024-05-24 | 中移物联网有限公司 | 一种函数调用方法、装置及设备 |
CN113032254A (zh) * | 2021-03-19 | 2021-06-25 | 中国工商银行股份有限公司 | 测试覆盖情况的评估方法和装置 |
CN113032254B (zh) * | 2021-03-19 | 2024-05-31 | 中国工商银行股份有限公司 | 测试覆盖情况的评估方法和装置 |
CN113238801A (zh) * | 2021-05-17 | 2021-08-10 | 上海中通吉网络技术有限公司 | 快递扫描信息采集方法、装置和系统 |
Also Published As
Publication number | Publication date |
---|---|
CN111857681B (zh) | 2021-04-30 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
CN111857681B (zh) | 一种c++系统的软件定义化关键函数定位与提取方法 | |
David et al. | BINSEC/SE: A dynamic symbolic execution toolkit for binary-level analysis | |
US20230094191A1 (en) | Scalable execution tracing for large program codebases | |
US7398469B2 (en) | Automated test system for testing an application running in a windows-based environment and related methods | |
US6305008B1 (en) | Automatic statement completion | |
US7975256B2 (en) | Optimizing application performance through data mining | |
US7493596B2 (en) | Method, system and program product for determining java software code plagiarism and infringement | |
US20110271258A1 (en) | Software Development Tool | |
US20110271250A1 (en) | Software Development Tool | |
CN115543294B (zh) | 一种Linux系统上动态链接库可视化依赖树的生成方法 | |
CN111859380A (zh) | Android App漏洞的零误报检测方法 | |
CN113051514A (zh) | 元素的定位方法、装置、电子设备及存储介质 | |
US7647581B2 (en) | Evaluating java objects across different virtual machine vendors | |
US10642714B2 (en) | Mapping dynamic analysis data to source code | |
US20060004810A1 (en) | Method, system and product for determining standard java objects | |
Barton et al. | Dynamic and graphical web page breakpoints | |
CN113835952B (zh) | 基于编译器代码注入的Linux系统调用监控方法 | |
Oliveira | pytest Quick Start Guide: Write better Python code with simple and maintainable tests | |
CN110674033A (zh) | 处理代码的方法、装置、设备及存储介质 | |
Gabrijelčič | Mastering Delphi Programming: A Complete Reference Guide: Learn all about building fast, scalable, and high performing applications with Delphi | |
CN113419960B (zh) | 用于可信操作系统内核模糊测试的种子生成方法及系统 | |
Sharma et al. | Finding substitutable binary code for reverse engineering by synthesizing adapters | |
CN114443418A (zh) | 一种基于硬件虚拟化的riscv内存溢出漏洞检测方法及装置 | |
CN113687880A (zh) | 一种调用组件的方法、装置、设备和介质 | |
WO2021104027A1 (zh) | 代码性能检测方法、装置、设备及存储介质 |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
PB01 | Publication | ||
PB01 | Publication | ||
SE01 | Entry into force of request for substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
GR01 | Patent grant | ||
GR01 | Patent grant |