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

目录

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.mzph.cn/news/157870.shtml

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

相关文章

什么是图神经网络

当这两种技术融合在一起时,就可以创造出一些新颖、奇妙的东西——比如手机和浏览器融合在一起,产生了智能手机。 如今,科研人员正在将人工智能发现模式的能力应用于存储各种数据点之间关系信息的大型图数据库。与此同时,就产生了…

FreeRTOS源码阅读笔记4--semphr.h

信号量是特殊的队列--无法存储消息的队列,相关的接口函数声明在semphr.h中,通过宏定义替换队列函数实现。 4.1创建二值信号量xSemaphoreCreateBinary() 4.1.1函数原型 queueQUEUE_TYPE_BINARY_SEMAPHORE:一个宏,表示创建队列的…

这是一棵适合搜索二叉树

🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨ 🐻强烈推荐优质专栏: 🍔🍟🌯C的世界(持续更新中) 🐻推荐专栏1: 🍔🍟🌯C语言初阶 🐻推荐专栏2: 🍔…

单链表OJ题--9.环形链表

9.环形链表 141. 环形链表 - 力扣(LeetCode) /* 解题思路: 定义快慢指针fast,slow, 如果链表确实有环,fast指针一定会在环内追上slow指针。 */typedef struct ListNode Node; bool hasCycle(struct ListNode *head) {Node* slow …

深信服技术认证“SCSA-S”划重点:渗透测试工具使用

为帮助大家更加系统化的学习网络安全知识,尽快通过深信服安全服务认证工程师认证,深信服推出“SCSA-S认证备考秘笈”共十期内容,“考试重点”内容框架,帮助大家快速get重点知识~ 划重点来啦 深信服安全服务认证工程师(…

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

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

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

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

图解Spark Graphx基于connectedComponents函数实现连通图底层原理

原创/朱季谦 第一次写这么长的graphx源码解读,还是比较晦涩,有较多不足之处,争取改进。 一、连通图说明 连通图是指图中的任意两个顶点之间都存在路径相连而组成的一个子图。 用一个图来说明,例如,下面这个叫graph…

【教3妹学编程-算法题】最大异或乘积

3妹:2哥,你有没有看到新闻“18岁父亲为4岁儿子落户现身亲子鉴定” 2哥 : 啥?18岁就当爹啦? 3妹:确切的说是14岁好吧。 2哥 : 哎,想我30了, 还是个单身狗。 3妹:别急啊, 2…

已完结7个,再启动1个新项目,嘎嘎强!

作者:小傅哥 博客:https://bugstack.cn 沉淀、分享、成长,让自己和他人都能有所收获!😄 大家好,我是技术UP主小傅哥。 💐又到了启动新项目的时候,死鬼开心嘛。小傅哥的星球&#xf…

数据库课后习题加真题

文章目录 第二章第三章第四到六章某年真题 第二章 第三章 3.8 对于教学数据库的三个基本表: s( 学号 ‾ \underline{学号} 学号​,姓名,年龄, 性别) sc( 学号 , 课程号 ‾ \underline{学号, 课程号} 学号,课程号​, 成绩) c( 课程号 ‾ \un…

【C++】类与对象(中)

一、类的默认成员函数 如果一个类中什么成员都没有,简称为空类。 空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。 默认成员函数:用户没有显式实现,编译器会自…

[超详细]基于YOLO&OpenCV的人流量统计监测系统(源码&部署教程)

1.图片识别 2.视频识别 [YOLOv7]基于YOLO&Deepsort的人流量统计系统(源码&部署教程)_哔哩哔哩_bilibili 3.Deepsort目标追踪 (1)获取原始视频帧 (2)利用目标检测器对视频帧中的目标进行检测 &#xff08…

oracle21c报错 【ORA-65096: 公用用户名或角色名无效】

1.数据库版本 oracle21c 2.问题提示 创建用户提示【ORA-65096: 公用用户名或角色名无效】 create user 自定义用户名 identified by 密码;--例:用户为test1,密码为123456 create user test1 identified by 123456;三.解决办法及结果 oracle11g之后的版本&#xff…

将kali系统放在U盘中插入电脑直接进入kali系统

首先准备一个空白的 U 盘。 Kali Linux | Penetration Testing and Ethical Hacking Linux Distribution 在 Windows 上制作 Kali 可启动 USB 驱动器 Making a Kali Bootable USB Drive on Windows | Kali Linux Documentation 1. 首先下载 .iso 镜像 Index of /kali-images…

构建 App 的方法

目录 构建 App 使用 App 设计工具以交互方式构建 App 使用 MATLAB 函数以编程方式构建 App 构建实时编辑器任务 可以使用 MATLAB 来构建可以集成到各种环境中的交互式用户界面。可以构建两种类型的用户界面: App - 基于用户交互执行操作的自包含界面 实时编辑器…

【HCSD大咖直播】亲授大厂面试秘诀【云驻共创】

同学们,毕业季是否找到了自己心仪的工作呢?是否了解大厂面试流程、要求以及技巧呢?华为云IoT高级工程师,传授大厂面试秘诀,教大家如何轻松get大厂offer!提前为大厂面试做准备,赢在起跑线&#x…

uniapp和vue3+ts创建自定义下拉选择框组件

使用uniapp开发小程序的时候,使用了uview的ui组件,但是里面没有下拉选择组件,只有Picker 选择器,但是我们想要使用下拉选择的组件,所以需要自定义个一个下拉选择的自定义组件,我就只能自己动手创建这个自定…

31、Flink的SQL Gateway介绍及示例

Flink 系列文章 1、Flink 部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接 13、Flink 的table api与sql的基本概念、通用api介绍及入门示例 14、Flink 的table api与sql之数据类型: 内置数据类型以及它们的属性 15、Flink 的ta…

梳理一名Go后端程序员日常用的软件~

大家好,我是豆小匠。 这期分享下我日常工作用到的软件和工具! 省流版图片↓↓↓ 工具分为四类:编码软件、笔记/文档软件、开发工具和日常软件等。 1. 编码软件 1.1. Goland 出自JetBrain家族,IDE的王者,作为我的…