著录项信息
专利名称 | 一种用于Linux系统测试代码注入的方法 |
申请号 | CN201010538375.5 | 申请日期 | 2010-11-10 |
法律状态 | 权利终止 | 申报国家 | 中国 |
公开/公告日 | 2011-03-09 | 公开/公告号 | CN101984409A |
优先权 | 暂无 | 优先权号 | 暂无 |
主分类号 | G06F9/445 | IPC分类号 | G;0;6;F;9;/;4;4;5查看分类表>
|
申请人 | 南京南瑞继保电气有限公司;南京南瑞继保工程技术有限公司 | 申请人地址 | 江苏省南京市江宁区苏源大道69号
变更
专利地址、主体等相关变化,请及时变更,防止失效 |
权利人 | 南京南瑞继保电气有限公司,南京南瑞继保工程技术有限公司 | 当前权利人 | 南京南瑞继保电气有限公司,南京南瑞继保工程技术有限公司 |
发明人 | 李忠安;李兴建 |
代理机构 | 南京天翼专利代理有限责任公司 | 代理人 | 陈建和 |
摘要
一种用于Linux系统测试代码注入的方法,步骤1,编写编译引导程序及测试代码;引导程序目的是在目标进程里申请地址空间,装载测试代码,及使申请的内存空间属性变为可执行;步骤2,关联待测进程,复制引导程序到进程地址空间;步骤3:执行引导程序并装载测试代码;在目标进程里申请地址空间,装载测试代码,并将其与原进程符号进行链接;步骤4:执行测试代码;在目标进程中创建线程,同时在目标进程里申请地址空间,装载测试代码,并将其与原进程符号链接、函数重定向工作;步骤5:脱离待测进程,恢复原进程空间指令,恢复原进程执行。本发明提供的方法能够在不中断目标进程运行,实时对目标程序进行测试代码的动态注入。
1.一种用于Linux系统测试代码注入的方法,其特征是:
步骤1,编写编译引导程序及测试代码;引导程序目的是在目标进程里申请地址空间,装载测试代码,及使申请的内存空间属性变为可执行;
步骤2,关联待测进程,复制引导程序到进程地址空间;
步骤3:执行引导程序并装载测试代码;在目标进程里申请地址空间,装载测试代码,并将其与原进程符号进行链接;
步骤4:执行测试代码;在目标进程中创建线程,同时在目标进程里申请地址空间,装载测试代码,并将其与原进程符号链接、函数重定向工作;
步骤5:脱离待测进程,恢复原进程空间指令,恢复原进程执行:
其中步骤1中,测试代码根据目标进程类型编译为共享库文件.so或简单.o文件;若目标进程为动态共享链接而成,则测试代码也编译为.so文件,若目标进程为静态链接,则编译为.o中间文件;
所述静态链接的测试代码对应的引导程序:首先利用mmap系统调用程序申请一定大小数据空间;将测试代码即elf文件的.text与.data段数据映射到此段空间,然后执行符号链接、函数重定向操作,最后利用mprotect系统调用程序将上述内存区域设置成可执行属性;由于测试代码为中间.o目标文件,无法直接执行,而目标进程空间中存在符号表,因此必须人工分析目标进程的二进制文件,查找测试代码.o文件所需外部符号对应位置;
所述动态链接的测试代码对应的引导程序:加载测试代码对应的.so文件,调用Linux系统动态函数库ld.so;动态链接、目标进程必须加载的第一个.so文件的函数dlopen打开.so文件,不需要另外编写加载器;需要查找函数dlopen及dlsym地址;
引导程序查找保存测试代码的入口地址,为执行测试代码做准备:动态链接的测试代码仅仅使用ld.so的函数dlsym即可找到特定测试代码入口在内存中的地址;静态链接的测试代码,在mmap系统调用程序映射测试代码到内存空间时,知道代码段加载的内存地址,再加上测试代码入口在文件中的偏移量,即可算出测试代码的入口在内存中的实际地址。
2.如权利要求1所述的用于Linux系统测试代码注入的方法,其特征是:在步骤2中,通过ptrace系统调用调试监控目标进程,备份目标进程某内存地址步骤代码;同时将引导程序复制到此内存地址。
3.由权利要求1所述用于Linux系统测试代码注入的方法,其特征是:在步骤3过程中,引导程序包含一简单程序加载器,用于测试代码的动态加载,包括符号解析、链接、函数重定向。
4.如权利要求1所述的用于Linux系统测试代码注入的方法,其特征是:步骤3中执行引导程序并装载测试代码;引导程序在目标进程空间执行,使用ptrace系统调用改变原进程的指令寄存器值,从而达到执行引导程序的目的。
5.如权利要求4所述的用于Linux系统测试代码注入的方法,其特征是:步骤3中prace系统调用有四个参数,第一个参数决定了ptrace的行为与其它参数的使用方法;通过ptrace系统调用、调用参数PTRACE_ATTACH与目标进程建立起关联调试关系,同时备份目标进程的上下文;然后通过ptrace系统调用、调用参数PTRACE_PEEKTEXT读取用户的进程指令区中指令并备份;备份结束后,通过ptrace系统调用参数PTRACE_POKETEXT将引导程序写入上述引导程序复制的内存中。
6.根据权利要求1所述的用于Linux系统测试代码注入的方法,其特征是,步骤3中在引导程序最后一条指令替换为TRAP指令;这样在引导程序执行完后,可继续操作目标进程。
7.如权利要求1所述的用于Linux系统测试代码注入的方法,其特征是:步骤4中再次通过ptrace系统调用设置指令寄存器的值为测试代码起始地址,参数为PTRACE_POKEUSR,并通过ptrace系统调用执行测试程序,参数为PTRACE_CONT;测试代码执行时在目标进程中创建一测试线程,当最后进程恢复时,测试线程仍驻留在目标进程中,可继续进行测试任务。
8.如权利要求1所述的用于Linux系统测试代码注入的方法,其特征是:步骤5中在脱离待测进程前,先用步骤2备份的指令恢复被引导程序覆盖的代码指令;其次,恢复目标进程的上下文,也采用步骤2备份的上下文恢复;恢复完后ptrace系统调用调用参数PTRACE_CONT继续执行原进程,这样就脱离了目标进程,原进程也恢复了执行。
一种用于Linux系统测试代码注入的方法\n技术领域\n[0001] 本发明涉及用于Linux操作系统的测试代码注入的方法和使用该方法的软件工具。\n背景技术\n[0002] 代码注入是指向目标程序对应的本地进程(目标进程)的地址空间注入一段可执行代码,并使进程执行这段代码,用来实现某些特殊的功能。\n[0003] 在Linux开发过程中,为对目标程序进行测试,经常需要在目标进程的地址空间内注入某些测试代码,用于搜集信息或其他测试目的。\n[0004] 在Linux系统中,每个进程都有自己的私有内存空间,互相隔离,彼此不能越界操作。把代码注入不同的进程地址空间,然后在该进程的上下文中执行注入的代码,就必须跨越进程间访问内存执行代码。代码注入技术作为病毒、木马已经存在多年,特别是在Windows系统中:为躲避系统的监控,一些木马病毒在攻击系统时往往将自身作为一个线程运行于其他应用程序的地址空间内,并监视、窃取甚至修改用户进程内的数据。这些技术也可用于软件测试领域,因为测试工具也往往需要对待测程序进行监控、获取进程数据。\n[0005] 目前测试代码注入方法一般有两类。第一类为直接修改目标程序的源代码即源代码插桩,由于必须拥有源代码,其局限性显而易见。例如《舰船电子工程》24卷6期《基于源代码插桩的C程序内存使用错误动态检测》、《计算机工程》36卷4期《飞行控制软件测试中插桩技术的优化方法》、专利号CN200710123818.2的《一种嵌入式系统测试方法》 及专利号CN200910054325.7的《使用监控线程对二进制翻译程序执行流程动态监控的方法》等均采用了源代码插桩方法。另一类为在目标程序运行前对目标程序二进制代码进行修改。这对于某些运行时间超长,且无法中断的程序就无能为力了。病毒传播大部分采用此方法。\n[0006] 下面就此文用到的一些名词进行解释。\n[0007] 系统调用程序是Unix/Linux操作系统向用户程序提供支持的接口,通过这些接口应用程序向操作系统请求服务,控制转向操作系统,而操作系统在完成服务后,将控制和结果返回给用户程序。Linux 包括200多个系统调用,主要分为进程控制、文件系统控制、系统控制、内存管理、网络管理、用户管理、进程通信等几类。本方法用到了一下ptrace、mmap、 mprotect等3个系统调用程序。\n[0008] ptrace系统调用:提供父进程观察和控制另一个进程执行的机制,同时提供查询和修改另一进程的核心影像与寄存器的能力。主要用于执行断点调试和系统调用跟踪。\n[0009] mmap系统调用:Linux中的程序执行时,需要将对应的进程映象调入进程的虚拟内存空间,就需要通过mmap系统调用向系统申请一段合适的虚拟内存空间。\n[0010] mprotect系统调用:可以更改一个已经存在的内存映射区的访问权限。\n[0011] 函数库:函数库是用于程序的子程序(函数)的集合。其和可执行文件的区别是,库不是独立程序,他们是向其他程序提供服务的代码。库链接是指把一个或多个库包括到程序中。有两种不同的库链接形式:静态链接和动态链接,相应的,前者链接的库叫做静态库,后者的叫做共享库或动态库。\n[0012] 静态链接:指将函数库的内容直接加入到可执行程序中,即程序本身拥有一份共享函数库中函数的副本,加载时只加载程序本身的文件即可。\n[0013] 动态链接:它提供了一种方法,使可执行程序可以调用外部函数,此函数的代码位于一个独立 SO (或DLL)文件中。该 SO(或DLL)文件包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。SO(或DLL) 有助于共享数据和资源。\n[0014] 装载器:程序文件的解析器,它负责解释程序文件,准备好执行环境(包括场地等资源),形成进程。对于动态链接或静态链接的程序,其装载过程不太相同。静态连接程序,装载过程简单为将程序文件映射到内存。对于动态连接的程序,工作还包括库加载和符号解析重定位。\n[0015] PPC Linux 2.4.25系统:嵌入式PowerPC架构Linux系统,内核版本2.4.25。\n发明内容\n[0016] 本发明的目的是:提供一种用于Linux系统测试代码注入的方法。\n[0017] 本发明的技术方案由五个步骤组成,用于Linux系统下运行进程测试代码注入的方法:\n[0018] 第一步骤,编写编译引导程序及测试代码;引导程序(装载器)在目标进程里申请地址空间,装载测试代码,及使申请的内存空间属性变为可执行;\n[0019] 若目标进程为动态共享链接而成,则测试代码编译为.so文件;若目标进程为静态链接,则编译为.o中间文件;引导程序为加载器,加载测试代码对应的.so或.o文件;\n[0020] 静态链接的测试代码对应的引导程序:首先利用mmap系统调用程序申请一定大小数据空间;将测试代码、即elf文件的.text .data等段数据映射到此段空间,然后执行符号链接、函数重定向操作,最后利用mprotect系统调用程序将上述内存区域设置成可执行属性;由于测试代码为中间.o目标文件,无法直接执行,而目标进程空间中存在符号表等,因此必须人工分析目标进程的二进制文件,查找测试代码.o文件所需外部符号对应位置;\n[0021] 动态链接的测试代码对应的引导程序:加载测试代码对应的so文件,调用Linux系统动态函数库ld.so的函数dlopen打开so文件,不需要另外编写加载器(ld.so是进程加载的第一个so文件,所有其他so文件是通过ld.so间接加载的);需要查找函数dlopen及dlsym地址。由于目标进程地址空间存在符号表、PLT及GOT表,容易获得此地址。\n[0022] 引导程序查找保存测试代码的入口地址,为执行测试代码做准备:动态链接的测试代码仅仅使用ld.so 的函数dlsym即可找到特定测试代码入口在内存中的地址;静态链接的测试代码,在mmap系统调用程序映射测试代码到内存空间时,知道代码段加载的内存地址,再加上测试代码入口在文件中的偏移量,即可算出测试代码的入口在内存中的实际地址;\n[0023] 第二步骤,关联待测进程,复制引导程序到进程地址空间;\n[0024] 通过ptrace系统调用调试监控目标进程,备份目标进程某内存地址步骤代码;同时将引导程序复制到此内存地址;\n[0025] prace系统调用有四个参数,第一个参数决定了ptrace的行为与其它参数的使用方法;通过ptrace系统调用、调用参数PTRACE_ATTACH与目标进程建立起关联调试关系。\n同时备份待测进程的上下文;然后通过ptrace系统调用、调用参数PTRACE_PEEKTEXT读取用户的进程指令区中指令并备份。备份结束后,通过ptrace系统调用、调用参数PTRACE_POKETEXT将引导程序写入上述引导程序复制的内存中;\n[0026] 第三步骤:执行引导程序并装载测试代码;在目标进程里申请地址空间,装载测试代码,并将其与原进程符号链接;\n[0027] 执行引导程序并装载测试代码;引导程序在目标进程空间执行,使用ptrace系统调用改变原进程的指令寄存器值,从而达到执行引导程序的目的;对于PPC Linux 2.4.25系统,一般通过ptrace系统调用、调用参数PTRACE_POKEUSR设置指令寄存器值为引导程起始地址,并通过ptrace系统调用参数PTRACE_CONT 执行引导程序;\n[0028] 尤其是在引导程序最后一条指令替换为TRAP指令;这样在引导程序执行完后,可继续操作目标进程;\n[0029] 第四步骤:执行测试代码;在目标进程中创建线程,同时在目标进程里申请地址空间,装载测试代码,并将其与原进程符号链接、函数重定向工作;\n[0030] 再次通过ptrace系统调用调用参数PTRACE_POKEUSR设置指令寄存器值为测试代码起始地址,并通过ptrace系统调用参数PTRACE_CONT 执行测试程序;测试代码执行时在目标进程中创建一测试线程,当最后进程恢复时,测试线程仍驻留在进程中; [0031] 第五步骤:脱离待测进程,恢复原进程空间指令,恢复原进程执行;\n[0032] 在脱离目标进程前,先用备份的指令恢复被引导程序覆盖的代码段;其次,还需要恢复目标进程上下文,也采用备份上下文恢复;恢复完后ptrace系统调用调用(参数PTRACE_CONT)继续执行原进程,这样就脱离了目标进程,原进程也恢复了执行。\n[0033] 本发明的有益效果:本发明提供的方法能够在不中断被检测目标程序运行,不需要更改目标代码的情况下,实时对目标程序注入测试代码用于测试。\n附图说明\n[0034] 下面结合附图对本发明的具体实施方式作进一步详细的说明。\n[0035] 图1是一个静态链接的引导程序流程图。\n[0036] 图2是一个动态链接的引导程序流程图。\n[0037] 图3是系统流程图。\n具体实施方式\n[0038] 分五步骤内容,下面以PPC Linux 2.4.25为例说明这一过程。\n[0039] 第一步骤为编写、编译引导程序及测试代码。测试代码根据目标进程类型编译为共享库文件.so或简单.o文件。若目标进程为动态共享链接而成,则测试代码也编译为.so文件。若目标进程为静态链接,则编译为.o中间文件。引导程序实际为一加载器,主要功能为加载测试代码对应的.so或.o文件。具体流程如图1和图2所示\n[0040] 静态链接的测试代码对应的引导程序主要功能为:首先利用mmap系统调用申请一定大小数据空间,将测试代码(elf文件的.text .data等段数据)映射到此段空间,然后执行符号链接、函数重定向操作,最后利用mprotect系统调用将上述内存区域设置成可执行属性。由于测试代码为中间.o目标文件,无法直接执行,而目标进程空间中符号表等,因此必须人工分析目标进程的二进制文件,查找测试代码.o文件所需外部符号对应位置,手工进行链接操作。为减少手工链接工作量,测试代码尽可能少引用库函数(或自己编写库函数),尽可能直接使用系统调用。\n[0041] 动态链接的测试代码对应的引导程序主要功能为:由于Linux系统唯一的动态库引导程序ld.so在目标代码开始执行时已经加载到了其进程空间,因此加载测试代码对应的so文件,可简单的调用ld.so 的函数dlopen打开so文件,不需要另外编写加载器。唯一的工作为查找函数dlopen及dlsym地址。由于目标进程地址空间存在符号表、PLT及GOT表,因此此地址也较容易获得。\n[0042] 引导程序最后的功能为查找保存测试代码的入口地址,为执行测试代码做准备。\n动态链接的测试代码仅仅使用ld.so 的函数dlsym即可找到特定测试代码入口在内存中的地址。静态链接的测试代码,在mmap映射测试代码到内存空间时,已经知道代码段加载的内存地址,再加上测试代码入口在文件中的偏移量,即可算出测试代码的入口在内存中的实际地址\n[0043] 第二步骤:调试关联待测进程,复制引导程序到进程地址空间,用于最后的指令恢复与执行。在Linux系统中,为方便软件的开发和调试,提供了一种对运行中的进程进行跟踪和控制的手段,那就是系统调用ptrace。ptrace提供了一种使父进程监视和控制其它进程的方式,它还能够改变子进程中的寄存器和内核映像,实现断点调试和系统调用的跟踪。\nprace调用有四个参数,它的第一个参数决定了ptrace的行为与其它参数的使用方法。通过ptrace调用参数PTRACE_ATTACH与目标进程建立起关联调试关系,同时备份进程上下文环境,然后通过ptrace调用参数PTRACE_PEEKTEXT读取用户的进程指令区中指令并备份。\n备份结束后,通过ptrace调用参数PTRACE_POKETEXT将引导程序写入上述内存中。\n[0044] 第三步骤:执行引导程序,装载测试代码。引导程序必须在目标进程空间执行。这里使用ptrace调用方法改变原进程的指令寄存器值,从而达到执行引导程序的目的。对于PPC Linux 2.4.25系统,一般通过ptrace调用参数PTRACE_POKEUSR设置指令寄存器值为引导程起始地址,并通过ptrace调用参数PTRACE_CONT 执行引导程序。为了让引导程序执行完后,目标程序能继续接受控制,这里在引导程序最后一条指令替换为TRAP指令。这样引导程序执行完后,我们可以继续操作目标进程。\n[0045] 第四步骤:执行测试代码;在目标进程中创建线程,同时在目标进程里申请地址空间,装载测试代码,并将其与原进程符号链接、函数重定向工作。这里再次通过ptrace调用(参数PTRACE_POKEUSR)设置指令寄存器值为测试代码起始地址,并通过ptrace调用(参数PTRACE_CONT) 执行测试程序。测试代码执行时可在目标进程中创建一测试线程,这样等到最后进程恢复时,测试线程仍驻留在目标进程中继续运行。\n[0046] 第五步骤:恢复原进程空间指令,脱离待测进程,恢复原进程执行。在脱离目标进程前,我们首先用备份的指令恢复被引导程序覆盖的代码段。其次,再恢复目标进程上下文环境,也采用备份上下文恢复。恢复完后ptrace调用参数PTRACE_CONT继续执行原进程,这样我们就脱离了目标进程,原进程也恢复了执行。\n[0047] 整个系统流程如图3所示。\n[0048] 实验结果表明,利用上述方法开发的测试工具能实时将测试代码注入到运行中的进程中去,不受测试代码大小限制,提高了测试工具的应用能力。
法律信息
- 2021-10-26
未缴年费专利权终止
IPC(主分类): G06F 9/445
专利号: ZL 201010538375.5
申请日: 2010.11.10
授权公告日: 2013.03.13
- 2013-03-13
- 2011-04-20
实质审查的生效
IPC(主分类): G06F 9/445
专利申请号: 201010538375.5
申请日: 2010.11.10
- 2011-03-09
引用专利(该专利引用了哪些专利)
序号 | 公开(公告)号 | 公开(公告)日 | 申请日 | 专利名称 | 申请人 |
1
| |
2010-06-30
|
2008-12-26
| | |
2
| |
2009-07-01
|
2008-01-15
| | |
3
| |
2010-03-10
|
2008-09-01
| | |
被引用专利(该专利被哪些专利引用)
序号 | 公开(公告)号 | 公开(公告)日 | 申请日 | 专利名称 | 申请人 | 该专利没有被任何外部专利所引用! |