第三方模块远程注入到软件中引发软件异常的若干实战案例分享

news2024/9/25 3:29:00

目录

1、概述

2、老版本的输入法导致软件CPU频繁跳高(导致软件出现卡顿)的问题

3、QQ拼音输入法注入到安装包进程中,导致安装包主线程卡死问题

3.1、多线程死锁分析

3.2、进一步研究

4、安全软件注入到软件中,注入模块发生了崩溃,直接导致软件发生崩溃

5、安全软件注入到软件中,注入模块发生了内存泄露,直接导致软件内存耗尽后发生闪退

6、最后


VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931C++软件分析工具从入门到精通案例集锦(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131405795C/C++基础与进阶(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.html开源组件及数据库技术(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_12458859.html网络编程与网络问题分享(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_2276111.html       有些软件为了实现某些功能需要远程注入到其他软件进程中的,比如输入法和安全软件等,注入到其他进程后,注入模块就运行在被注入的进程空间中了,一旦注入模块发生内存泄漏、崩溃等问题,会直接影响到被注入的进程,引发被注入进程发生异常。本文结合项目中遇到的若干问题,给大家详细介绍一下因为远程注入引发软件异常的几个典型项目实例,以供大家借鉴或参考。

1、概述

       在日常工作中接触比较多的需要注入到其他软件进程的软件主要有输入法和安全软件:

1)输入法:输入法在注入到其他软件进程之后,其他软件进程才能使用输入法输入文字。

2)安全软件:安全软件为了实时监控其他软件的操作与行为,为了实时监控其他软件网络数据的收发,也需要远程注入到其他软件进程中。

用于远程注入的模块,注入到目标进程中后,就驻留在目标进程中了,即运行在目标进程的进程空间中了。一旦注入模块发生异常,会直接影响到被注入的进程,会直接引发被注入的进程发生异常。

      根据之前项目中遇到的多个问题,注入模块对被注入进程的影响,主要有以下几类:

1)输入法注入到软件进程后,可能会导致软件发生明显的卡顿,特别是在输入文字时,这个问题在客户使用低版本的搜狗输入法时遇到过。
2)输入法注入到软件进程后,可能会引发软件发生死锁,这个问题在运行软件安装包程序时遇到过。
3)注入模块在运行过程中遇到异常,发生崩溃,直接导致被注入的软件发生崩溃。因为注入模块就运行在被注入的软件进程中的。
4)注入模块发生内存泄漏,内存泄漏发生在被注入的软件进程中,导致被注入软件发生Out of memory内存耗尽发生闪退。

      下面讲几个在项目中遇到的问题实例,来看看注入模块是怎样影响到我们软件的。

2、老版本的输入法导致软件CPU频繁跳高(导致软件出现卡顿)的问题

       有客户反馈,在其使用我们软件的过程中会时不时出现卡顿问题。让客户打开Windows任务管理器,让其帮忙观察一下软件使用过程中该软件进程的CPU占用情况。

       经观察发现,软件在使用过程中CPU占用比例会时不时地跳高,跳高之后又自动回落。特别是在聊天框中输入时,CPU会跳高。CPU占用变高,一般可能是因为软件中在持续地执行代码导致的,比如程序中发生死循环,一直在不停歇地执行代码。但本例中,CPU会很快自动回落,好像不是死循环导致的,如果是死循环,CPU占用会一直比较高。难道代码中会出现短时间内的死循环?

       于是使用Process Explorer工具查看CPU占用高的线程,然后查看该线程的函数调用堆栈,多次刷新多次查看函数调用堆栈,发现线程中一直有搜狗输入法(IME - Input Method Editor,输入法)相关函数的调用(函数所在模块名中有Ime和Sougou字样,所以判断是搜狗输入法相关模块),所以怀疑这个问题可能和搜索输入法有关。

       软件界面卡顿,应该是软件UI界面卡顿,所以应该是UI主线程有问题。Process Explorer中看到的CPU占用高的线程,应该就是UI主线程。可以用Windbg确认一下,将Windbg附加到软件进程上,使用~命令将进程中的所有线程信息都打印出来,如下所示:

在Windbg中,UI主线层是0号线程,将该0号线程的线程id(进程id为16进制数)与Process Explorer中显示的线程id(进程id为十进制数)比较一下就知道了。至于怎么比较,也可以参看我之前写的文章:

使用Process Explorer/Process Hacker和Windbg高效排查软件高CPU占用问题icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/134180480       后来让客户查看了一下其安装的搜狗输入法的版本,是一个较老的版本,让他安装最新版本的搜狗输入法,安装后好像就没问题了。所以该问题应该是和输入法有关的

3、QQ拼音输入法注入到安装包进程中,导致安装包主线程卡死问题

       在某客户的电脑上,会时不时出现启动我们的软件安装包后没反应,启动起来后应该显示安装包界面的,但一直看不到安装包界面,到任务管理器中可以看到软件安装包进程,说明程序已经启动了。

       估计是安装包UI界面所在的UI主线程发生卡死了,查看安装包进程的CPU占用很低,所以能排除程序发生死循环的可能。很可能是UI线程与其他线程发生死锁了。

3.1、多线程死锁分析

       导致线程发生卡死,一般有两种原因:

1)代码中发生死循环,导致函数一直没返回,线程卡死;
2)代码一直卡在WaitForSingleObject等待锁的状态,导致函数一直没返回,线程卡死。这是多个线程之间使用锁,发生死锁引发的。

        于是将Windbg启动起来,附加到出问题的安装包进程上,然后使用~0s命令切换到UI主线程(UI主线程是0号线程),然后输入kn命令查看函数调用堆栈,如下所示:

从堆栈中可以看出,当前线程卡在等待锁的WaitForSingleObject函数上,一直没返回。可以多次go,多次查看0号线程的函数调用堆栈,每次都卡在WaitForSingleObject函数上。

       此外,沿着函数调用堆栈向上看,是调用EnterCriticalSection接口去获取临界区对象,触发了WaitForSingleObject函数的调用。说明当前发生死锁的是临界区锁。

       当前确定是UI主线程发生死锁了,那与之关联的死锁线程是哪个呢?安装包程序比较简单,进程中没几个线程,使用~*kn命令将所有线程的函数调用堆栈都打印出来,看到1号线程也卡在获取临界区锁的函数调用上:

那基本可以确定是0号线程和1号线程发生死锁了:

至于是不是这两个线程形成了死锁,需要分析锁的信息,具体分析方法,我在此就不赘述了,可以查看我之前写的文章:

使用Process Explorer/Process Hacker和Windbg高效排查软件高CPU占用问题icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/134180480       此处也可以用《Windows核心编程》第9章源码中提供了一个叫LockCop的死锁检测工具,当时使用该工具监测结果如下:

该死锁检测工具是调用Windows API函数去检测的,只能检测到部分对象的死锁,无法监测到所有类型的死锁,关于这个工具的详细说明,可以查看《Windows核心编程》第9章(使用等待链遍历API来检测死锁)的内容

       关于多线程及多线程死锁相关内容,可以参考我的文章:

从C++软件调试实战的角度去看多线程编程中的若干细节问题icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/134358655       从发生死锁的1号线程的调用堆栈来看,看到了QQPinYin的模块名,那说明这个线程是与QQ拼音输入法相关的。这就是说,这个死锁是与QQ拼音相关的,当时建议尝试两个办法,一个是升级QQ拼音输入法的版本,另一个是将QQ拼音输入法换成搜狗输入法。客户采用了后面这个方法,将输入法换成搜狗输入法后就不再出现了。

3.2、进一步研究

        对于0号线程,是调用了API函数SHGetSpecialFolderLocation触发的死锁;对于1号线程,是调用API函数SHGetSpecialFolderPathW触发的死锁。这说明死锁发生在底层的Windows系统库中,不在上层库中。这种情况很少遇到,一般死锁都发生在上层的业务代码中。

       这两个函数在两个线程中调用会发生死锁?于是尝试到微软MSDN上查看这两个函数的说明。看到这两个函数都已经被微软废弃了,如下所示:

建议不要使用这两个函数了,应该使用对应的替代函数。

       为了保证代码的健壮性,我们应该遵从微软官方的说明,不再使用已经废弃的API函数。如果继续使用,可能会产生一些无法预料、未知的结果。

4、安全软件注入到软件中,注入模块发生了崩溃,直接导致软件发生崩溃

      几年前遇到的一个客户问题,他们的Windows系统中安装了VPN软件,注入到我们的进程中,hook了网络通信的相关接口,以监控软件的网络数据包的收发,其中hook的recvfrom接口实现有bug,我们代码中有处调用recvfrom接口的地方传入了两个NULL参数(对于系统API函数recvfrom,传入NULL值是允许的),结果直接导致该注入模块产生了崩溃,进而导致了我们软件的崩溃。

       到MSDN上查看套接字API函数recvfrom的说明,函数的最后两个参数是可选的,可以不传入,直接设置NULL就可以了,如下所示:

       但客户VPN软件注入模块,将系统的recvfrom函数hook成了他们实现的recvfrom函数,在实现他们自己的recvfrom函数时,直接访问了recvfrom最后的两个参数,而我们的代码直接传入了NULL值:


这样在他们的recvfrom内部访问了NULL指针,触发了内存访问违例,导致VPN软件的注入模块发生崩溃,从而导致了我们整个程序的崩溃。

事实上,这个问题的排查难度远比此处文字描述的复杂,崩溃时的函数调用堆栈不完整(看不到套接字函数recvfrom的调用):

崩溃的注入库MinLSP.dll是第三方安全厂商的,我们拿不到该库的pdb文件,可能厂商也没有保存!

当时是使用IDA反汇编工具查看汇编代码,以及使用Windbg的dds命令,找出recvfrom函数调用的!限于篇幅,这个地方就没有完全展开了!

       像这类出在第三方安全软件中的问题,必须要拿出足够的证据,证明问题是出在安全软件上,客户才会认可排查的结论,客户才会找第三方安全软件开发商反馈问题。对于本例中的问题,我们有个临时的规避办法,我们只要传入两个有效的参数即可,当然在对应的代码中,我们并不关心这两个参数在函数调用完成之后的返回值,不再传入两个NULL参数。

5、安全软件注入到软件中,注入模块发生了内存泄露,直接导致软件内存耗尽后发生闪退

       有个客户在某台机器上运行的我们的软件,每次大概运行半个多小时后软件就会出现闪退崩溃,问题基本是必现的。软件运行一段时间后发生闪退崩溃,可能是内存泄漏引起的。有内存泄露的代码在频繁地执行,泄露的内存越来越多,接近或达到用户态虚拟内存的上限(32位程序默认的用户态虚拟内存位2GB),就会导致Out of memory内存耗尽的异常,程序就会发生闪退崩溃。

       于是让客户重新运行软件,按照之前的操作步骤操作,然后在Windows任务管理器中持续地观察软件进程占用的内存情况,看看内存是否在持续地升高。之前我们讲过,Windows任务管理器中看不到进程占用的用户态虚拟内存,需要使用Process Explorer去查看。不过任务管理器中看内存的变化趋势是可以的,也能看到内存在持续增长的。我们推荐使用Process Explorer工具去查看虚拟内存占用。

       经观察,软件中确实存在内存泄露,大概半个小时后内存就耗完了。然后就是使用工具去分析内存泄露的模块及位置了。当时选择Windbg去检测内存泄露,将Windbg附加到目标进程上去监测。至于如何使用Windbg去检测内存泄露,此处就不再赘述了,可以查看我的文章:
使用Windbg定位Windows C++程序中的内存泄漏icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/121295720       经分析,内存泄露发生在某个dll模块中,然后查看该dll模块的路径,发现是客户安装的某个安全软件的路径,即该dll模块是某安全软件中的。安全软件中的模块,怎么会跑到我们的软件进程空间中来的呢?答案只有一个,这个dll库是远程注入到我们的软件进程中的,安全软件正是通过这个注入模块对我们的软件进行监控的。

这个问题应该和客户机器的系统环境有关,如果是软件本身模块有内存泄漏,应该在公司内部测试环境中就发现了,因为半个小时左右就能复现,在公司环境中不用专门长时间拷机就能复现。

       我们给客户的结论是,安全软件的注入模块有内存泄露,需要客户联系安全软件的开发厂商去核实排查一下。但客户有些不认可我们的结论,他们给出的理由是,运行其他软件都没问题,为啥运行我们的软件就有内存泄露呢?后来将发生泄漏模块所属的安全软件卸载掉后,我们的软件运行就没有泄露了,所以基本确定泄露和这个安全软件有关,客户才愿意承认可能是安全软件引起的。然后联系了安全软件厂商,协调了他们的相关开发人员,然后创建了讨论组。

       经排查得知,安全软件在拦截UDP数据包进行分析时有内存泄露,而我们的软件在加入会议后,源源不断的音音视频码流都是使用UDP传输的,所以导致内存一直在持续的泄露,然后内存很快就耗尽,程序发生闪退了。

至于软件是如何实现远程注入的,可以查看《Windows核心编程》一书中的第22章(DLL注入与API拦截)的内容。

6、最后

        本文详细讲述了几个项目中遇到的远程注入对软件产生影响的问题实例,有很强的实战参考价值,希望能给大家提供一定的借鉴或参考。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1236793.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VM——绘制亮度均匀性曲线

1、需求:检测汽车内饰氛围灯的亮度均匀性,并绘制均匀性曲线 2、结果: 3、方法: 主要分为3步 (1)提取氛围灯ROI,忽略背景 (2)对提取到的ROI图进行切片处理,计算出每个切片的亮度均值 (3)绘制均匀性曲线 3.1 提取氛围灯ROI step1: 转成黑白图 step2:通过blob和…

C++医学影像PACS系统源码,影像归档和通信系统全套源码

C医学影像PACS系统源码 PACS系统,意为影像归档和通信系统。它是应用在医院影像科室的系统,主要的任务就是把日常产生的各种医学影像(包括核磁,CT,超声,各种X光机,各种红外仪、显微仪等设备产生的…

启动Dubbo项目注册Zookeeper时提示zookeeper not connected异常原理解析

原创/朱季谦 遇到一个很诡异的问题,我在启动多个配置相同zookeeper的Dubbo项目时,其他项目都是正常启动,唯独有一个项目在启动过程中,Dubbo注册zookeeper协议时,竟然出现了这样的异常提示—— Caused by: java.lang.…

Rust可空类型Option

文章目录 Option基础模式匹配unwrap Rust基础教程:初步⚙所有权⚙结构体和枚举类⚙函数进阶⚙泛型和特征⚙并发和线程通信⚙cargo包管理 Rust进阶教程:用宏实现参数可变的函数⚙类函数宏 Option基础 在一些编程语言中,允许存在空值&#xf…

用 HLS 实现 UART

用 HLS 实现 UART 介绍 UART 是一种旧的串行通信机制,但仍在很多平台中使用。它在 HDL 语言中的实现并不棘手,可以被视为本科生的作业。在这里,我将通过这个例子来展示在 HLS 中实现它是多么容易和有趣。 因此,从概念上讲&#xf…

来吧,SpringBoot的自动配置原理都在这里了

💗推荐阅读文章💗 🌸JavaSE系列🌸👉1️⃣《JavaSE系列教程》🌺MySQL系列🌺👉2️⃣《MySQL系列教程》🍀JavaWeb系列🍀👉3️⃣《JavaWeb系列教程》…

【C++】类和对象一

今天来到了类和对象部分,我们知道C语言是面向过程编程,而C是面向对象编程,那么怎么个具体实现方法呢?简单来说,就是C语言对结构体的定义和对结构体的操作是分开的,这样就显得过程很独立;而C是把…

单链表OJ--8.相交链表

8.相交链表 160. 相交链表 - 力扣(LeetCode) /* 解题思路: 此题可以先计算出两个链表的长度,让长的链表先走相差的长度,然后两个链表同时走,直到遇到相同的节点,即为第一个公共节点 */struct Li…

紧跟热点:教你如何快速掌握ChatGPT

2023年随着OpenAI开发者大会的召开,最重磅更新当属GPTs,多模态API,未来自定义专属的GPT。微软创始人比尔盖茨称ChatGPT的出现有着重大历史意义,不亚于互联网和个人电脑的问世。360创始人周鸿祎认为未来各行各业如果不能搭上这班车…

【Mysql系列】LAG与LEAD开窗函数

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

怎么查看虚拟机的网关

1、点击编辑,再选择虚拟网络编辑器 2、选择VMnet8,点击NAT设置 3、查看网关IP

kafka权限认证 topic权限认证 权限动态认证-亲测成功

kafka权限认证 topic权限认证 权限动态认证-亲测成功 kafka动态认证 自定义认证 安全认证-亲测成功 MacBook Linux安装Kafka Linux解压安装Kafka 介绍 1、Kafka的权限分类 身份认证(Authentication):对client 与服务器的连接进行身份认证…

Python批量备份交换机配置+自动巡检

自动巡检功能考虑到不同设备回显有所不同,需要大量正则匹配,暂时没时间搞这些,所以索性将命令回显全部显示,没做进一步的回显提取。 以下是程序运行示例:#自动备份配置: 备份完成后,将配置保存于…

机器学习的概念和类型

1、人工智能、机器学习、深度学习之间的关系 人工智能(AI)是广泛的概念,指赋予计算机智能特性。机器学习(ML)是AI的一个分支,是指通过计算机学习和改进性能。深度学习(DL)是ML的一类…

java疫情期间社区出入管理系统-计算机毕业设计源码21295

摘 要 信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻克的课题。针对疫情期间社区出入管理等问题,对…

【开源】基于Vue和SpringBoot的创意工坊双创管理系统

项目编号: S 049 ,文末获取源码。 \color{red}{项目编号:S049,文末获取源码。} 项目编号:S049,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 管理员端2.2 Web 端2.3 移动端 三、…

并行与分布式计算 第8章 并行计算模型

文章目录 并行与分布式计算 第8章 并行计算模型8.1 并行算法基础8.1.1 并行算法的定义8.1.2并行算法的分类8.1.3算法的复杂度 8.2 并行计算模型8.2.1 PRAM (SIMD-SM)模型8.2.3 BSP (MIMD-DM)模型8.2.4LogP(MIMD-DM)模型 并行与分布式计算 第8章 并行计算…

小米集团收入增长失速已久:穿越寒冬,雷军的路走对了吗?

撰稿|行星 来源|贝多财经 11月20日,小米集团(HK:01810,下称“小米”)发布了截至2023年9月30日的第三季度业绩公告。 财报显示,在智能手机出货量下行、平均售价下跌的背景下,小米逆势而上,实现…

猫咪不长肉怎么回事?搬空家底的增肥效果好的猫罐头分享

秋冬到了,北方有供暖还好,咱南方的小猫咪全靠一身正气,不囤点脂肪天生怕冷的小猫咪要怎么过冬啊?咋吃都吃不胖的猫可愁怀铲屎官了,想想我新手养猫那些年,为了给我家猫养胖点我是做了不少努力,当…