一种定位动态运行库加载异常的方法与流程

专利2024-02-20  107



1.本发明涉及数据处理领域,尤其涉及一种定位动态运行库加载异常的方法。


背景技术:

2.目前软件行业的方式,普遍使用微软提供的dumpbin、depdenys工具,来补充dll到程序目录中,这种方案的原理是分析每个dll导入表,根据导入表信息分析出,dll依赖的其他库。dumpbin、depends能够查看依赖的dll文件依赖关系,将依赖的dll文件全部放在程序同目录下,但当我们处于多人开发,或者使用了不同的第三方库时,是无法控制每个dll加载时机,就无法分析出复杂环境下加载失败的原因。
3.另外动态库加载过程,受到用户电脑环境变量目录和系统目录下文件影响,这种静态的分析是无法确定真实场景下的加载失败的问题。这种情况一般是在加载a.dll时,a.dll依赖了b.dll,b.dll又依赖了c.dll,c.dll依赖d.dll存在这种多层依赖关系,但由于windows加载dll方式依赖到其他dll时,会到环境变量path的多个目录寻找,当多个目录中存在了同样的文件名dll文件时,会先加载到搜索路径靠前的目录,当这个目录dll版本和预期版本不一致就会导致加载失败。而对于开发者来说,只收到的错误只有来源于加载首个a.dll返回的错误,提示未能加载有a.dll导入的整个过程。这样的错误信息,无法确定具体问题,以及环境路径的情况,以及库冲突的问题。
4.另外搜索目录还会受到开发者当前环境变量目录影响,而当前工作目录和环境变量目录不是固定的,是可以跟随程序改变的,这样在真实用户的环境下,会变得更为复杂,错误日志无法准确定位问题。
5.因此,如何帮助开发者分析用户环境下的异常问题成为了一个亟待解决的技术问题。
6.上述内容仅用于辅助理解本发明的技术方案,并不代表承认上述内容是现有技术。


技术实现要素:

7.本发明的主要目的在于提供一种定位动态运行库加载异常的方法,旨在解决帮助开发者分析用户环境下的异常问题。
8.为实现上述目的,本发明提供一种定位动态运行库加载异常的方法,所述方法包括以下步骤:
9.执行在程序中初始化监控加载库的操作;
10.创建监控搜索动态运行库dll路径的过程函数和监控正在加载动态运行库dll路径的过程函数;
11.获取监控搜索动态运行库dll路径的过程函数和监控正在加载动态运行库dll路径的过程函数中压入全局运行库文件绝对路径的信息栈数据;
12.遍历上述全局运行库文件绝对路径的信息栈中数据,按照顺序读取dll绝对路径;
13.获取动态运行库dll文件版本信息,根据文件版本信息函数读取动态运行库dll文件版本信息对应的版本号;
14.比较预设的加载库版本和路径,确定运行库加载异常状况。
15.优选的,所述执行在程序中初始化监控加载库的操作包括:
16.获取ntdll.dll的模块句柄地址,其中,所述ntdll.dll的模块句柄地址是在初始化监控中使用加载动态库的过程函数得到的;
17.通过ntdll.dll模块句柄,导出指定函数地址的过程函数,其中,导出指定函数地址的过程函数包括查询文件属性的过程函数和打开文件的过程函数;
18.读取原有nt内核的过程函数地址,将导出的函数地址的过程函数保存到nt内核的过程函数地址的全局地址变量中;
19.通过读取进程内存函数,读取nt内核过程函数地址的全局地址变量所在头部8个字节,将8个字节保存到原有nt内核过程函数的全局字节数组变量。
20.优选的,所述创建监控搜索动态运行库dll路径的过程函数包括:
21.创建捕获搜索动态运行库dll路径的信息函数流程,其中,该信息函数包括对象属性和文件基础信息的结构体;
22.将创建的监控搜索动态运行库dll路径的过程函数替换为进程空间中的查询指定文件对象的属性的过程函数;
23.判断是否触发获取到文件对象属性的信号,在获取到所述文件对象属性信号触发的情况下,对搜索的动态运行库dll文件的完整路径信息进行捕获提取。
24.优选的,所述创建监控搜索动态运行库dll路径的过程函数还包括:
25.获取对象属性信息长度,判断是否为空,如果不为空,则进行完整路径提取;
26.从对象属性获取句柄对象名称的字符串数据指针;
27.从符字符串的缓冲区读取内容,其中,该内容为程序当前正在搜索动态运行库dll的路径;
28.拼接当前搜索的动态运行库dll名称的完整路径;
29.将获取内容压栈,写入到全局运行库文件绝对路径的信息栈中。
30.优选的,所述创建监控搜索动态运行库dll路径的过程函数还包括:
31.读取在程序中初始化监控加载库的操作中已经保存在nt内核查询文件属性的过程函数地址的全局地址变量中函数地址、和原有nt内核查询文件属性的过程函数的全局字节数组变量的8个字节数组;
32.将保存在全局字节数组变量备份的8个字节数组写入到全局地址变量函数地址中进行恢复;
33.调用nt内核查询文件属性的过程函数;
34.继续执行监控搜索动态运行库dll路径的信息函数流程。
35.优选的,开始执行监控搜索动态运行库dll过程包括:将创建好的监控搜索动态运行库dll路径的过程函数,赋值替换到原有检nt内核检索查询文件属性的过程函数地址中,其中,赋值替换过程包括:
36.设置8个字节的跳转指令缓冲区数组;
37.将创建的监控搜索动态运行库dll路径的过程函数地址,填充到跳转指令缓冲区
第一个字节之后;
38.将监控搜索动态运行库dll路径的过程函数地址赋值给寄存器;
39.通过跳转指令跳转到寄存器的监控搜索动态运行库dll路径的过程函数地址上;
40.执行监控遍历搜索动态运行库dll路径的信息记录流程。
41.优选的,所述创建监控正在加载动态运行库dll的过程函数包括:
42.创建捕获监控正在加载动态运行库dll完整路径的信息函数流程,其中,该信息函数包括文件操作句柄、文件访问类型、对象属性、文件操作和完成状态的信息的结构体指针、文件的共享访问类型以及打开文件时操作选项;
43.将创建的监控正在加载动态运行库dll路径的过程函数替换为进程空间中的原有nt内核打开文件的过程函数地址;
44.判断是否触发打开动态运行库dll文件对象句柄操作时的信号,在打开动态运行库dll文件对象句柄操作信号触发的情况下,对正在加载的动态运行库dll完整路径信息进行捕获提取。
45.优选的,所述创建监控正在加载动态运行库dll的过程函数还包括:
46.获取对象信息长度,判断是否为空,如果不为空,则进行完整路径提取;
47.从对象信息中获取句柄对象名称的字符串数据指针;
48.从符字符串的缓冲区读取内容,其中,该符字符串的缓冲区中的内容包括程序目录或系统目录或系统目录system32下或环境变量path下路径;
49.拼接当前正在加载的动态运行库dll名称的完整路径;
50.将获取内容压栈,写入全局运行库文件绝对路径的信息栈中。
51.优选的,所述创建监控正在加载动态运行库dll的过程函数还包括:
52.读取在程序中初始化监控加载库的操作中已经保存在nt内核打开文件的过程函数的全局地址变量中函数地址、和原有nt内核打开文件的过程函数的全局字节数组变量的8个字节数组;
53.将保存在全局地址变量备份的8个字节写入到全局地址变量中进行恢复;
54.调用nt内核打开文件的过程函数;
55.继续执行监控正在加载运行库dll完整路径的信息函数流程。
56.优选的,还包括:
57.读取在程序中初始化监控加载库的操作中已经保存在nt内核查询文件属性和打开文件的过程函数地址的全局地址变量中函数地址、和原有nt内核打开文件的过程函数的全局字节数组变量的8个字节数组;
58.使用写入进程的内存区域的函数,将保存在全局地址变量备份的8个字节写入到全局字节数组变量函数地址中;
59.还原原有nt内核查询文件和打开文件属性的过程函数流程。
60.此外,为实现上述目的,本发明还提出一种存储介质,所述存储介质上存储有动态检测、快速定位运行库加载异常的程序,所述动态检测、快速定位运行库加载异常的程序被处理器执行时实现如上文所述的动态检测、快速定位动态运行库加载异常的方法的步骤。
61.与现有技术相比,本发明提供的一种定位动态运行库加载异常的方法,通过设置监控搜索动态运行库dll过程以及设置监控正在加载动态运行库dll库的过程,能够动态获
取实时加载过程情况,不受环境影响,通过数据分析,能够准确看到,动态库搜索过程和加载过程,对比找出没有加载的dll的信息、以及受到环境变量影响找不到dll位置问题、以及dll版本不一致复杂情况,进行打印提示或者上报,能够准确反映出错误原因和用户环境情况。
62.该方案不需要遍历所有环境变量路径下所有文件,性能更高,而且兼容动态变化的环境变量,不会受程序或者系统环境变化影响,能够分析出复杂的动态库关联调用关系,兼容性更强,稳定性高。同时不需要单独分析用户环境、不需要远程,更利于开发者分析用户环境下的异常问题。
63.显然,上述有关本发明优点的描述是概况性的,更多的优点描述将体现在后续的实施例揭示中,以及,本领域技术人员也可以本发明所揭示的内容合理地发明本发明的其他诸多优点。
64.本发明附加的方面和优点将在下面的描述中给出,并且本发明的优点将在下面的描述中变得明显或通过本发明的实践了解到。
附图说明
65.图1是本发明一种定位动态运行库加载异常的方法第一实施例的流程示意图。
具体实施方式
66.现将详细参考本公开的当前实施例,其实例在附图中得以说明。只要有可能,相同元件符号在图式及描述中用来表示相同或相似部分。
67.参照图1,图1为本发明动态检测、快速定位动态运行库加载异常的方法第一实施例的流程示意图。本实施例中,所述动态检测、快速定位动态运行库加载异常的方法包括以下步骤:
68.s100:执行在程序中初始化监控加载库的操作。
69.需要说明的是,在本实施例中该初始化监控加载库的具体操作包括;使用加载动态库的过程函数获取ntdll.dll的模块句柄地址;通过ntdll.dll模块句柄,使用检索导出指定函数地址的过程函数读取原有nt内核查询文件属性的过程函数地址,将检索导出的函数地址保存到nt内核查询文件属性的过程函数地址的全局地址变量中,通过读取进程内存函数,读取nt内核查询文件属性的过程函数地址的全局地址变量所在头部8个字节,将8个字节保存到原有nt内核查询文件属性的过程函数的全局字节数组变量中,用于停止监控搜索路径时,恢复原有nt内核查询文件属性的过程函数的流程状态。
70.通过ntdll.dll模块句柄,使用检索导出指定函数地址的过程函数读取原有nt内核打开文件的过程函数地址,将检索导出的函数地址保存到nt内核打开文件的过程函数的全局地址变量中,通过读取进程内存函数,读取出nt内核打开文件的过程全局地址变量所在头部8个字节,将8个字节保存到原有nt内核打开文件的过程的全局字节数组变量中,用于停止监控正在加载的动态库路径时,恢复原有nt内核打开文件的过程函数的流程状态。
71.s200:设置监控搜索动态运行库dll路径的过程函数和设置监控正在加载动态运行库dll的过程。
72.需要说明的是,设置监控搜索动态运行库(dll)过程包括:创建监控搜索动态运行
库dll路径的过程函数和开始执行监控搜索动态运行库dll过程。
73.在具体实施中,创建监控搜索动态运行库dll路径的过程函数包括如下步骤:
74.创建捕获搜索动态运行库dll路径的信息函数流程,该函数有两个参数,第一个是对象属性,该对象属性描述了文件对象属性的信息内容,第二个参数是文件基础信息的结构体,该结构体中包含了文件相关的时间戳信息,以及文件属性,属性描述了文件是否是加密、是否是只读、是否是压缩等信息。
75.当开始设置监控搜索动态运行库dll时,使用创建的监控搜索动态运行库dll路径的函数替换进程空间中的查询指定文件对象的属性的函数,即替换原有nt内核查询文件属性的过程函数,当执行加载运行库依赖其他动态运行库dll文件时,会到不同环境变量或者系统目录进行搜索,当搜索指定动态运行库dll时会获取文件对象属性,这时候会触发到所创建的捕获搜索动态运行库dll路径的信息函数流程中,该函数过程中会对搜索的动态运行库dll文件的完整路径信息进行捕获提取。
76.具体数据存在于对象属性变量的结构中,该结构是获取指定可以通过创建对象和/或返回对象句柄的例程应用于对象或对象句柄的属性。
77.首先获取对象属性信息长度,判断是否为空,如果不为空,进行完整路径提取。
78.从对象属性获取句柄对象名称的字符串数据指针,该值为宽字符字符串的指针,从符字符串的缓冲区读取内容,该内容为程序当前正在搜索动态运行库dll的路径。
79.该符字符串的缓冲区中的内容是程序目录或系统目录或系统目录system32下或环境变量path下路径,拼接当前搜索的动态运行库dll名称的完整路径。将获取内容压栈,写入到全局运行库文件绝对路径的信息栈中,用于后续数据分析和打印。
80.读取s100在程序中初始化开始监控加载库过程中已经保存在nt内核查询文件属性的过程函数地址的全局地址变量中函数地址和原有nt内核查询文件属性的过程函数的全局字节数组变量的8个字节数组,将保存在全局字节数组变量备份的8个字节写入到全局地址变量函数地址中进行恢复。用于之后还原原有nt内核查询文件属性的过程函数流程。
81.执行调用nt内核查询文件属性的过程函数,设置的两个参数为当前传入的捕获搜索动态运行库dll路径信息函数流程的两个参数。即第一个是对象属性和第二个参数是文件基础信息的结构体,来保证程序原有逻辑顺序和完整的调用过程,不影响流程。
82.调用完原有nt内核查询文件属性的过程函数,继续执行监控搜索动态运行库dll路径信息函数流程,保证持续监控每一个正在搜索动态库的过程,直到执行s40停止监控的流程。
83.在具体实施中,创建开始执行监控搜索动态运行库dll路径的过程函数包括将创建好的监控搜索动态运行库dll路径的过程函数,赋值替换到原有检nt内核检索查询文件属性的过程函数地址中,具体过程包括如下步骤:
84.设置8个字节的跳转指令缓冲区数组,具体内容为{0xb8,0x00,0x00,0x00,0x00,0xff,0xe0,0x00},将创建的监控搜索动态运行库dll路径的过程函数地址,填充到跳转指令缓冲区第一个字节之后,该跳转指令在执行时会转化为机器指令,通过将监控搜索动态运行库dll路径的过程函数地址赋值给寄存器(eax),再通过跳转指令(jmp)跳转到寄存器eax的监控搜索动态运行库dll路径的过程函数地址上,执行监控遍历搜索动态运行库dll路径的信息记录流程。
85.当程序加载库的搜索过程中,每搜索遍历一个路径,都会进入监控搜索动态运行库dll路径的信息函数流程中一次,被记录当前搜索的路径到全局运行库文件绝对路径的信息栈中。
86.另外,设置监控正在加载动态运行库dll路径的过程函数包括:
87.创建监控正在加载动态运行库dll的过程函数和开始执行监控正在加载动态运行库dll完整路径的信息函数流程过程。
88.具体的是,创建监控正在加载动态运行库dll的过程函数包括以下步骤:
89.步骤1:创建捕获控正在加载动态运行库dll完整路径的信息函数流程,该函数有6个参数,分别为第一个是文件操作句柄,第二个是文件访问类型,第三位对象属性,第四为文件操作和完成状态的信息的结构体指针,第五个为文件的共享访问类型,第六个为打开文件时操作选项。
90.需要说明的是,创建的函数过程中会捕获正在加载动态运行库dll完整路径信息。
91.步骤2:当开始设置监控动态运行库dll时,使用所创建的监控正在加载动态运行库dll的过程函数替换进程空间中的原有nt内核打开文件的过程函数地址,当执行加载运行库中已经搜索找到依赖的其他dll库时,会对该dll动态库文件执行加载过程,当执行加载过程中打开该动态运行库dll文件对象句柄的操作时会触发进入到所创建的监控正在加载动态运行库dll的过程函数中,该函数过程中会对正在加载的动态运行库dll完整路径信息进行捕获提取。
92.在一种实施例中,具体数据同样存在于变量结构中,该结构是获取指定可以通过创建对象和/或返回对象句柄的例程应用于对象或对象句柄的属性。
93.首先获取对象信息长度,判断是否为空,如果不为空,进行完整路径提取。
94.从对象信息长度获取句柄对象名称的字符串数据指针,该值为字符串的指针,从符字符串的缓冲区读取内容,该内容为程序当前正在加载的动态运行库dll的路径。
95.该符字符串的缓冲区中的内容是程序目录或系统目录或系统目录system32下或环境变量path下路径,拼接当前正在加载的动态运行库dll名称的完整路径;将获取内容压栈,写入全局运行库文件绝对路径的信息栈中,用于后续数据分析和打印。
96.读取s100在程序中初始化开始监控加载库过程中已经保存在nt内核打开文件的过程函数的全局地址变量中函数地址和原有nt内核打开文件的过程的全局字节数组变量的8个字节数组,将保存在变量备份的8个字节写入到函数地址中进行恢复;用于之后还原原有nt内核打开文件的过程函数流程。
97.执行调用nt内核打开文件的过程函数,设置的6个参数为当前传入的监控正在加载动态运行库dll的过程函数流程的6个参数。即第一个是文件操作句柄,第二个是文件访问类型,第三位对象属性,第四为文件操作和完成状态的信息的结构体指针,第五个为文件的共享访问类型,第六个为打开文件时操作选项。来保证程序原有逻辑顺序和完整的调用过程。
98.在调用完原有nt内核打开文件的过程函数后,继续再执行开始执行监控正在加载动态运行库dll完整路径的信息函数流程过程,保证持续监控每一个正在加载动态库的过程,直到执行后续停止监控的流程。
99.具体的是,开始执行监控正在加载动态运行库dll完整路径的信息函数流程过程
包括将上一步创建好的监控正在加载动态运行库dll的过程函数,赋值替换到原有nt内核打开文件的过程函数地址中。具体过程包括:
100.设置8个字节的跳转指令缓冲区数组,具体内容为{0xb8,0x00,0x00,0x00,0x00,0xff,0xe0,0x00},将创建监控正在加载动态运行库dll的过程函数地址,填充到跳转指令缓冲区第一个字节之后。使用写入进程的内存区域的函数,将跳转指令缓冲区数组的8个字节写入到函数地址中进行替换,替换后该跳转指令在执行时会转化为机器指令,通过将监控正在加载动态运行库dll的过程函数地址赋值给寄存器(eax),再通过跳转指令(jmp)跳转到寄存器eax的监控正在加载动态运行库dll的过程函数地址上,执行监控正在加载动态运行库dll完整路径的信息记录流程。
101.当程序加载库搜索过程中,每搜索找到一个动态运行库dll,都会对其进行加载,每次加载过程中都会进入监控当前正在加载动态运行库dll路径的信息函数流程中,被记录当前正在加载动态运行库的路径到全局运行库文件绝对路径的信息栈中。
102.在监控完成后,还包括停止关闭监控搜索动态库和加载动态库流程的步骤,
103.其中,停止监控搜索动态运行库dll库过程的步骤具体包括:
104.读取步骤s100在程序中初始化开始监控加载库过程中已经保存在nt内核查询文件属性的过程函数地址的全局地址变量中函数地址和原有nt内核查询文件属性的过程函数的全局字节数组变量的8个字节数组。
105.使用写入进程的内存区域的函数,将保存在全局字节数组变量备份的8个字节写入到全局地址变量函数中进行恢复。用于之后还原原有nt内核查询文件属性的过程函数流程,不在执行后续监控搜索动态库的过程,保证程序后面的逻辑调用过程。
106.其中,停止监控正在加载动态运行库dll库的过程的步骤具体包括:
107.读取步骤s100在程序中初始化开始监控加载库过程中已经保存在nt内核打开文件的过程函数的全局地址变量中函数地址和原有nt内核打开文件的过程的全局字节数组变量的8个字节数组。
108.使用写入进程的内存区域的函数,将保存在全局字节数组变量备份的8个字节写入到全局地址变量函数地址中进行恢复。用于之后还原原有nt内核打开文件的过程函数流程。不在执行监控后续正在加载动态库的过程,保证程序后面的逻辑调用过程。
109.s300:获取监控搜索动态运行库dll路径的过程函数和监控正在加载动态运行库dll路径的过程函数中压入全局运行库文件绝对路径的信息栈数据。
110.由于栈结构保留了搜索和加载库的顺序和完整路径,本实例通过将监控搜索动态运行库dll过程函数和监控正在加载动态运行库dll过程函数中压入全局运行库文件绝对路径的信息栈中数据读取出来,按照顺序查询并写入日志记录。
111.s400:遍历上述全局运行库文件绝对路径的信息栈中数据,按照顺序读取dll绝对路径。
112.s500:获取动态运行库dll文件版本信息,根据文件版本信息函数读取动态运行库dll文件版本信息对应的版本号。
113.在本实施例中,获取动态运行库dll文件版本信息,通过获取动态运行库版本信息大小函数来创建对应存储空间,并通过获取文件版本信息函数读取动态运行库dll文件版本信息对应的4位完整版本号。
114.s600:比较预设的加载库版本和路径,确定运行库加载异常状况。
115.通过判断对比预设置的加载库版本和路径,对比找出没有加载的动态运行库dll的信息,进行打印提示或者上报;对比动态运行库dll版本不一致情况,进行打印提示或者上报;对比动态运行库dll路径不一致的情况,进行打印提示或者上报。
116.在步骤s400前,本实施例还包括通过获取当前进程模块名称函数得到程序所在路径的目录,通过拼接设置日志写入路径,为当前程序目录下的logs文件,创建读写、共享读写删除权限,保证文件不被锁定;设置文件指针到文件尾部,用来顺序记录打印日志。
117.本发明通过在程序中初始化开始监控加载库过程,并设置监控搜索动态运行库(dll)过程以及设置监控正在加载动态运行库dll库的过程,在监控加载过程中,根据不同用户环境情况,实时反馈记录出搜索动态库的过程以及动态库实时加载过程情况,因为是动态监控,所以完全兼容不同用户环境下的复杂情况,不需要遍历所有环境变量路径,而且兼容动态变化的环境变量,不会受程序或者系统环境变化影响,能够分析出无限层次的调用关系,兼容性更强,稳定性高,同时不需要单独分析用户环境。不需要远程,更利于开发者分析用户环境下的异常问题。
118.示例性的,本发明定位动态运行库加载异常的方法的完整流程如下:
119.(1):在程序中初始化开始监控加载库过程
120.初始化监控,使用加载动态库的过程函数(loadlibrary)获取ntdll.dll的模块句柄地址;通过ntdll.dll模块句柄,使用检索导出指定函数地址的过程函数(getprocaddress)读取原有nt内核查询文件属性的过程函数(ntqueryattributesfile)地址,将检索导出的函数地址保存到nt内核查询文件属性的过程函数地址的全局地址变量(g_lpfnaddrntqueryattributesfile)中,通过读取进程内存(readprocessmemory)函数,读取nt内核查询文件属性的过程函数地址的全局地址变量(g_lpfnaddrntqueryattributesfile)所在头部8个字节,将8个字节保存到原有nt内核查询文件属性的过程函数的全局字节数组变量(g_szntqueryattributesfileoldbytes)中,用于停止监控搜索路径时,恢复原有nt内核查询文件属性的过程函数ntqueryattributesfile的流程状态;
121.通过ntdll.dll模块句柄,使用检索导出指定函数地址的过程函数(getprocaddress)读取原有nt内核打开文件的过程函数(ntopenfile)地址,将检索导出的函数地址保存到nt内核打开文件的过程函数的全局地址变量(g_lpfnaddrntopenfile)中,通过读取进程内存(readprocessmemory)函数,读取出nt内核打开文件的过程全局地址变量(g_lpfnaddrntopenfile)所在头部8个字节,将8个字节保存到原有nt内核打开文件的过程的全局字节数组变量(g_szntopenfileoldbytes)中,用于停止监控正在加载的动态库路径时,恢复原有nt内核打开文件的过程函数ntopenfile的流程状态;
122.设置全局动态运行库dll文件绝对路径的信息栈,该栈会顺序存放搜索过程中搜索dll的完整路径信息以及正在加载的dll动态库的完整路径信息,并将其按照顺序存储起来。
123.(2):设置监控搜索动态运行库(dll)过程
124.1、创建监控搜索动态运行库dll路径的过程函数
125.创建捕获搜索动态运行库dll路径的信息函数流程,该函数有两个参数,第一个是
对象属性(object_attributes),该属性描述了文件对象属性的信息内容,第二个参数是文件基础信息的结构体(pfile_basic_information),该结构中包含了文件相关的时间戳信息,以及文件属性,属性描述了文件是否是加密、是否是只读、是否是压缩等信息;
126.当开始设置监控搜索动态运行库dll时,使用我们创建的监控搜索动态运行库dll路径的函数替换进程空间中的查询指定文件对象的属性的函数ntqueryattributesfile,也就是替换原有nt内核查询文件属性的过程函数,当执行加载运行库依赖其他动态运行库dll文件时,会到不同环境变量或者系统目录进行搜索,当搜索指定动态运行库dll时会获取文件对象属性,这时候会触发到我们创建的捕获搜索动态运行库dll路径的信息函数流程中,该函数过程中会对搜索的动态运行库dll文件的完整路径信息进行捕获提取。
127.具体数据存在于对象属性变量object_attributes的结构中,该结构是获取指定可以通过创建对象和/或返回对象句柄的例程应用于对象或对象句柄的属性。
128.首先获取objectattributes对象属性信息长度,判断是否为空,如果不为空,进行完整路径提取;
129.从对象属性objectattributes获取句柄对象名称的字符串数据指针objectname,该值为宽字符(unicode)字符串的指针,从符字符串的缓冲区读取内容,该内容为,程序当前正在搜索动态运行库dll的路径,该符字符串的缓冲区中的内容是程序目录或系统目录或系统目录system32下或环境变量path下路径,拼接当前搜索的动态运行库dll名称的完整路径;将获取内容压栈,写入到全局运行库文件绝对路径的信息栈中,用于s50后续数据分析和打印;
130.读取在程序中初始化开始监控加载库过程中已经保存在nt内核查询文件属性的过程函数地址的全局地址变量(g_lpfnaddrntqueryattributesfile)中函数地址和原有nt内核查询文件属性的过程函数的全局字节数组变量(g_szntqueryattributesfileoldbytes)的8个字节数组提取出来,将保存在g_szntqueryattributesfileoldbytes备份的8个字节写入到g_lpfnaddrntqueryattributesfile函数地址中进行恢复。用于之后还原原有nt内核查询文件属性的过程函数流程,执行调用nt内核查询文件属性的过程函数,设置的两个参数为当前传入的捕获搜索动态运行库dll路径信息函数流程的两个参数。即第一个是对象属性(object_attributes)和第二个参数是文件基础信息的结构体(pfile_basic_information),来保证程序原有逻辑顺序和完整的调用过程,不影响流程;
131.调用完原有原有nt内核查询文件属性的过程函数,继续再执行下面的开始执行监控搜索动态运行库dll路径信息函数流程,保证持续监控每一个正在搜索动态库的过程,直到执行s40停止监控的流程。
132.2、开始执行监控搜索动态运行库dll过程
133.将上一步创建好的监控搜索动态运行库dll路径的过程函数,赋值替换到原有检nt内核检索查询文件属性的过程函数(ntqueryattributesfile)地址中,具体过程,设置8个字节的跳转指令缓冲区数组(byteg_szntqueryattributesfilenewbytes[8]),具体内容为{0xb8,0x00,0x00,0x00,0x00,0xff,0xe0,0x00},将创建的监控搜索动态运行库dll路径的过程函数地址,填充到跳转指令缓冲区第一个字节之后,该跳转指令在执行时会转化为机器指令,通过将监控搜索动态运行库dll路径的过程函数地址赋值给寄存器(eax),在通
过跳转指令(jmp)跳转到寄存器eax的监控搜索动态运行库dll路径的过程函数地址上,执行监控遍历搜索动态运行库dll路径的信息记录流程;
[0134]
当程序加载库的搜索过程中,每搜索遍历一个路径,都会进入监控搜索动态运行库dll路径的信息函数流程中一次,被记录当前搜索的路径到全局运行库文件绝对路径的信息栈中。
[0135]
(3):设置监控正在加载动态运行库dll的过程
[0136]
1、创建监控正在加载动态运行库dll的过程函数
[0137]
创建捕获控正在加载动态运行库dll完整路径的信息函数流程,该函数有6个参数,分别为第一个是文件操作句柄(filehandle),第二个是文件访问类型(desiredaccess),第三位对象属性(object_attributes),第四为文件操作和完成状态的信息的结构体指针(pio_status_block),第五个为文件的共享访问类型(shareaccess),第六个为打开文件时操作选项(openoptions);
[0138]
创建的函数过程中会捕获正在加载动态运行库dll完整路径信息,当开始设置监控动态运行库dll时,使用我们创建的监控正在加载动态运行库dll的过程函数替换进程空间中的原有nt内核打开文件的过程函数(ntopenfile)地址,当执行加载运行库中已经搜索找到依赖的其他dll库时,会对该dll动态库文件执行加载过程,当执行加载过程中打开该动态运行库dll文件对象句柄的操作时会触发进入到我们创建的监控正在加载动态运行库dll的过程函数中,该函数过程中会对正在加载的动态运行库dll完整路径信息进行捕获提取。
[0139]
具体数据同样存在于变量object_attributes结构中,该结构是获取指定可以通过创建对象和/或返回对象句柄的例程应用于对象或对象句柄的属性。
[0140]
首先获取objectattributes对象信息长度,判断是否为空,如果不为空,进行完整路径提取;
[0141]
从objectattributes获取句柄对象名称的字符串数据指针objectname,该值为unicode字符串的指针,从符字符串的缓冲区读取内容,该内容为,程序当前正在加载的动态运行库dll的路径,该符字符串的缓冲区中的内容是程序目录或系统目录或系统目录system32下或环境变量path下路径,拼接当前正在加载的动态运行库dll名称的完整路径,将获取内容压栈,写入全局运行库文件绝对路径的信息栈中,用于s50后续数据分析和打印;
[0142]
读取s10在程序中初始化开始监控加载库过程,中已经保存在nt内核打开文件的过程函数的全局地址变量(g_lpfnaddrntopenfile)中函数地址和原有nt内核打开文件的过程的全局字节数组变量(g_szntopenfileoldbytes)的8个字节数组提取出来,将保存在变量g_szntopenfileoldbytes备份的8个字节写入到g_lpfnaddrntopenfile函数地址中进行恢复。用于之后还原原有nt内核打开文件的过程函数流程;
[0143]
执行调用nt内核打开文件的过程函数,设置的6个参数为当前传入的监控正在加载动态运行库dll的过程函数流程的6个参数。即第一个是文件操作句柄(filehandle),第二个是文件访问类型(desiredaccess),第三位对象属性(object_attributes),第四为文件操作和完成状态的信息的结构体指针(pio_status_block),第五个为文件的共享访问类型(shareaccess),第六个为打开文件时操作选项(openoptions),来保证程序原有逻辑顺
序和完整的调用过程;
[0144]
调用完原有nt内核打开文件的过程函数,继续再执行下面的开始执行监控正在加载动态运行库dll完整路径的信息函数流程过程,保证持续监控每一个正在加载动态库的过程,直到执行s40停止监控的流程
[0145]
2、开始执行监控正在加载动态运行库dll完整路径的信息函数流程过程
[0146]
将上一步创建好的监控正在加载动态运行库dll的过程函数,赋值替换到原有nt内核打开文件的过程函数(ntopenfile)地址中,具体过程,设置8个字节的跳转指令缓冲区数组(byte g_szntopenfilenewbytes[8]),具体内容为{0xb8,0x00,0x00,0x00,0x00,0xff,0xe0,0x00},将创建监控正在加载动态运行库dll的过程函数地址,填充到跳转指令缓冲区第一个字节之后。使用写入进程的内存区域的函数(writeprocessmemory),将跳转指令缓冲区数组(byte g_szntopenfilenewbytes[8])的8个字节写入到g_lpfnaddrntopenfile函数地址中进行替换,替换后该跳转指令在执行时会转化为机器指令,通过将监控正在加载动态运行库dll的过程函数地址赋值给寄存器(eax),在通过跳转指令(jmp)跳转到寄存器eax的监控正在加载动态运行库dll的过程函数地址上,执行监控正在加载动态运行库dll完整路径的信息记录流程;
[0147]
当程序加载库搜索过程中,每搜索找到一个动态运行库dll,都会对其进行加载,每次加载过程中都会进入监控当前正在加载动态运行库dll路径的信息函数流程中,被记录当前正在加载动态运行库的路径到全局运行库文件绝对路径的信息栈中。
[0148]
(4):监控完成,停止关闭监控搜索动态库和加载动态库流程
[0149]
1、停止监控搜索动态运行库dll库过程
[0150]
读取s10在程序中初始化开始监控加载库过程,中已经保存在nt内核查询文件属性的过程函数地址的全局地址变量(g_lpfnaddrntqueryattributesfile)中函数地址和原有nt内核查询文件属性的过程函数的全局字节数组变量(g_szntqueryattributesfileoldbytes)的8个字节数组提取出来;
[0151]
使用写入进程的内存区域的函数(writeprocessmemory),将保存在数组变量g_szntqueryattributesfileoldbytes备份的8个字节写入到g_lpfnaddrntqueryattributesfile函数地址中进行恢复。用于之后还原原有nt内核查询文件属性的过程函数流程,不在执行后续监控搜索动态库的过程,保证程序后面的逻辑调用过程。
[0152]
2、停止监控正在加载动态运行库dll库的过程
[0153]
读取s10在程序中初始化开始监控加载库过程,中已经保存在nt内核打开文件的过程函数的全局地址变量(g_lpfnaddrntopenfile)中函数地址和原有nt内核打开文件的过程的全局字节数组变量(g_szntopenfileoldbytes)的8个字节数组提取出来;
[0154]
使用写入进程的内存区域的函数(writeprocessmemory),将保存在变量g_szntopenfileoldbytes备份的8个字节写入到g_lpfnaddrntopenfile函数地址中进行恢复。用于之后还原原有nt内核打开文件的过程函数流程。不在执行监控后续正在加载动态库的过程,保证程序后面的逻辑调用过程。
[0155]
(5):自动分析全局运行库文件绝对路径的信息栈内容,分析对比,定位问题,打印提示或错误上报
[0156]
将监控搜索动态运行库dll过程函数和监控正在加载动态运行库dll过程函数中压入全局运行库文件绝对路径的信息栈中数据读取出来,因为栈结构保留了搜索和加载库的顺序和完整路径,我们按照顺序查询并写入日志记录下来;
[0157]
通过获取当前进程模块名称函数(getmodulefilename)得到程序所在路径的目录,通过拼接设置日志写入路径,为当前程序目录下的logs文件,创建读写、共享读写删除权限,保证文件不被锁定;
[0158]
设置文件指针到文件尾部,用来顺序记录打印日志;
[0159]
遍历全局运行库文件绝对路径的信息栈中数据,按照顺序读取dll绝对路径;
[0160]
获取动态运行库dll文件版本信息,通过获取动态运行库版本信息大小函数(getfileversioninfosize)来创建对应存储空间,并通过获取文件版本信息函数(getfileversioninfo)读取出读取动态运行库dll文件版本信息对应的4位完整版本号;
[0161]
判断对比预设置的加载库版本和路径;
[0162]
对比找出没有加载的动态运行库dll的信息,进行打印提示或者上报
[0163]
对比动态运行库dll版本不一致情况,进行打印提示或者上报;
[0164]
对比动态运行库dll路径不一致的情况,进行打印提示或者上报。
[0165]
本发明的目的就是提出一种动态检测、快速动态检测、快速定位动态运行库加载异常的方法,本发明可以处理复杂用户电脑环境变量,不受变化的环境变量限制,动态监控跟踪动态运行库搜索和加载过程,通过搜索顺序以及记载对应版本的信息,推导出具体冲突的问题,不需要远程分析用户电脑环境,不需要遍历所有的环境文件夹目录以及所有的文件。对于开发人员分析加载问题更加简单和方便。而且不需要改变原有运行代码逻辑,不影响程序稳定性。
[0166]
采用本发明所述直接本发明方案在通过在程序中初始化开始监控加载库过程,并设置监控搜索动态运行库(dll)过程以及设置监控正在加载动态运行库dll库的过程,在监控加载过程中,根据不同用户环境情况,实时反馈记录出搜索动态库的过程以及动态库实时加载过程情况,因为是动态监控,所以完全兼容不同用户环境下的复杂情况,不需要遍历所有环境变量路径,而且兼容动态变化的环境变量,不会受程序或者系统环境变化影响,能够分析出无限层次的调用关系,兼容性更强,稳定性高,同时不需要单独分析用户环境。不需要远程,更利于开发者分析用户环境下的异常问题。
[0167]
以上所述仅为本发明的较佳实施例而已,并不用以限制本发明,凡在本发明的精神和原则之内所作的任何修改、等同替换和改进等,均应包括在本发明的保护范围之内。

技术特征:
1.一种定位动态运行库加载异常的方法,其特征在于,所述动态检测、快速定位运行库加载异常包括:执行在程序中初始化监控加载库的操作;创建监控搜索动态运行库dll路径的过程函数和监控正在加载动态运行库dll路径的过程函数;获取监控搜索动态运行库dll路径的过程函数和监控正在加载动态运行库dll路径的过程函数中压入全局运行库文件绝对路径的信息栈数据;遍历上述全局运行库文件绝对路径的信息栈中数据,按照顺序读取dll绝对路径;获取动态运行库dll文件版本信息,根据文件版本信息函数读取动态运行库dll文件版本信息对应的版本号;比较预设的加载库版本和路径,确定运行库加载异常状况。2.根据权利要求1所述的定位动态运行库加载异常的方法,其特征在于,所述执行在程序中初始化监控加载库的操作包括:获取ntdll.dll的模块句柄地址,其中,所述ntdll.dll的模块句柄地址是在初始化监控中使用加载动态库的过程函数得到的;通过ntdll.dll模块句柄,导出指定函数地址的过程函数,其中,导出指定函数地址的过程函数包括查询文件属性的过程函数和打开文件的过程函数;读取原有nt内核的过程函数地址,将导出的函数地址的过程函数保存到nt内核的过程函数地址的全局地址变量中;通过读取进程内存函数,读取nt内核过程函数地址的全局地址变量所在头部8个字节,将8个字节保存到原有nt内核过程函数的全局字节数组变量。3.根据权利要求2所述的一种定位动态运行库加载异常的方法,其特征在于,所述创建监控搜索动态运行库dll路径的过程函数包括:创建捕获搜索动态运行库dll路径的信息函数流程,其中,该信息函数包括对象属性和文件基础信息的结构体;将创建的监控搜索动态运行库dll路径的过程函数替换为进程空间中的查询指定文件对象的属性的过程函数;判断是否触发获取到文件对象属性的信号,在获取到所述文件对象属性信号触发的情况下,对搜索的动态运行库dll文件的完整路径信息进行捕获提取。4.根据权利要求3所述的定位动态运行库加载异常的方法,其特征在于,所述创建监控搜索动态运行库dll路径的过程函数还包括:获取对象属性信息长度,判断是否为空,如果不为空,则进行完整路径提取;从对象属性获取句柄对象名称的字符串数据指针;从符字符串的缓冲区读取内容,其中,该内容为程序当前正在搜索动态运行库dll的路径;拼接当前搜索的动态运行库dll名称的完整路径;将获取内容压栈,写入到全局运行库文件绝对路径的信息栈中。5.根据权利要求3所述的定位动态运行库加载异常的方法,其特征在于,所述创建监控搜索动态运行库dll路径的过程函数还包括:
读取在程序中初始化监控加载库的操作中已经保存在nt内核查询文件属性的过程函数地址的全局地址变量中函数地址、和原有nt内核查询文件属性的过程函数的全局字节数组变量的8个字节数组;将保存在全局字节数组变量备份的8个字节数组写入到全局地址变量函数地址中进行恢复;调用nt内核查询文件属性的过程函数;继续执行监控搜索动态运行库dll路径的信息函数流程。6.根据权利要求2所述的定位动态运行库加载异常的方法,其特征在于,开始执行监控搜索动态运行库dll过程包括:将创建好的监控搜索动态运行库dll路径的过程函数,赋值替换到原有检nt内核检索查询文件属性的过程函数地址中,其中,赋值替换过程包括:设置8个字节的跳转指令缓冲区数组;将创建的监控搜索动态运行库dll路径的过程函数地址,填充到跳转指令缓冲区第一个字节之后;将监控搜索动态运行库dll路径的过程函数地址赋值给寄存器;通过跳转指令跳转到寄存器的监控搜索动态运行库dll路径的过程函数地址上;执行监控遍历搜索动态运行库dll路径的信息记录流程。7.根据权利要求2所述的定位动态运行库加载异常的方法,其特征在于,所述创建监控正在加载动态运行库dll的过程函数包括:创建捕获监控正在加载动态运行库dll完整路径的信息函数流程,其中,该信息函数包括文件操作句柄、文件访问类型、对象属性、文件操作和完成状态的信息的结构体指针、文件的共享访问类型以及打开文件时操作选项;将创建的监控正在加载动态运行库dll路径的过程函数替换为进程空间中的原有nt内核打开文件的过程函数地址;判断是否触发打开动态运行库dll文件对象句柄操作时的信号,在打开动态运行库dll文件对象句柄操作信号触发的情况下,对正在加载的动态运行库dll完整路径信息进行捕获提取。8.根据权利要求7所述的定位动态运行库加载异常的方法,其特征在于,所述创建监控正在加载动态运行库dll的过程函数还包括:获取对象信息长度,判断是否为空,如果不为空,则进行完整路径提取;从对象信息中获取句柄对象名称的字符串数据指针;从符字符串的缓冲区读取内容,其中,该符字符串的缓冲区中的内容包括程序目录或系统目录或系统目录system32下或环境变量path下路径;拼接当前正在加载的动态运行库dll名称的完整路径;将获取内容压栈,写入全局运行库文件绝对路径的信息栈中。9.根据权利要求7所述的定位动态运行库加载异常的方法,其特征在于,所述创建监控正在加载动态运行库dll的过程函数还包括:读取在程序中初始化监控加载库的操作中已经保存在nt内核打开文件的过程函数的全局地址变量中函数地址、和原有nt内核打开文件的过程函数的全局字节数组变量的8个字节数组;
将保存在全局地址变量备份的8个字节写入到全局地址变量中进行恢复;调用nt内核打开文件的过程函数;继续执行监控正在加载运行库dll完整路径的信息函数流程。10.根据权利要求2所述的定位动态运行库加载异常的方法,其特征在于,还包括:读取在程序中初始化监控加载库的操作中已经保存在nt内核查询文件属性和打开文件的过程函数地址的全局地址变量中函数地址、和原有nt内核打开文件的过程函数的全局字节数组变量的8个字节数组;使用写入进程的内存区域的函数,将保存在全局地址变量备份的8个字节写入到全局字节数组变量函数地址中;还原原有nt内核查询文件和打开文件属性的过程函数流程。

技术总结
本发明公布了一种定位动态运行库加载异常的方法,通过在程序中初始化开始监控加载库过程,并设置监控搜索动态运行库DLL过程以及设置监控正在加载动态运行库DLL库的过程,在监控加载过程中,根据不同用户环境情况,实时反馈记录出搜索动态库的过程以及动态库实时加载过程情况,因为是动态监控,所以完全兼容不同用户环境下的复杂情况,不需要遍历所有环境变量路径,而且兼容动态变化的环境变量,不会受程序或者系统环境变化影响,能够分析出无限层次的调用关系,兼容性更强,稳定性高,同时不需要单独分析用户环境。不需要远程,更利于开发者分析用户环境下的异常问题。开发者分析用户环境下的异常问题。开发者分析用户环境下的异常问题。


技术研发人员:朱志强 江泽龙
受保护的技术使用者:深圳软牛科技有限公司
技术研发日:2022.07.11
技术公布日:2022/11/1
转载请注明原文地址: https://tieba.8miu.com/read-6903.html

最新回复(0)