学到了!软件产品安全性?

李志宽
• 阅读 1170

背景

为了提高开发的软件产品安全性,大部分选择的方案防护方案是,通过用成熟的加固软件进行对自己研发的软件做防护,从而达到对软件搭建一个安全防护墙。加固软件主要做的两件事,对软件中关键代码的保护以及提高对软件逆向反编译的门槛。

那么软件安全性防护墙的第一道门那就是反调试。反调试技术又细分为静态反调试和动态反调试。下面就针对window端的进行梳理反调试检测方案。

进程环境块BeingDebugged检测

通过读取进程环境块PEB中,是否设置BeingDebugged标志(其实这个标志IsDebuggerPresent跟这个函数内部执行效果是一样的),这个PEB(进程环境块)指针指向的值。

在x86环境下通过FS:[0x30]获取PEB的值;

在X64环境下通过GS:[0x60]获取PEB值;

当这个值等于0的情况下,表示没被调试,否则就处于调试状态。

学到了!软件产品安全性?

进程环境块NtGlobalFlag检测

进程环境块PEB中NtGlobalFlag是一个DWORD值,这个值包含操作系统设置的许多标志,这些标志会影响进程的运行方式。这个字段在程序正常运行的情况下值默认为0,在被调试器调试的时候(如ollydbg动态调试),这个字段为0x70(注意:ollydbg附加状态下是没改变的)。

进程环境块HeapFlags检测

当程序在调试下运行,并使用调试器进程创建标志创建时,HeapFlags标志更正常程序运行的标志值是不一致的。

对于X86系统,Vista以上版本的HeapFlags位于0x40偏移, 低于Vista版本的位于0x0C

对于X64系统,Vista以上版本的HeapFlags位于0x70偏移,低于Vista版本的位于0x14偏移

如果这个HeapFlags的值大于2,那么表示处于被调试状态,如果这个值等于2,那么属于正常状态。

进程环境块ForceFlags检测

当程序在调试下运行,并使用调试器进程创建标志创建时,ForceFlags标志跟正常运行的程序是不一致的。

对于X86系统,Vista以上版本的HeapFlags位于0x44偏移, 低于Vista版本的位于0x10偏移

对于X64系统,Vista以上版本的HeapFlags位于0x74偏移,低于Vista版本的位于0x18偏移

如果这个ForceFlags的值大于0,那么表示处于被调试状态,如果这个值等于2,那么属于正常状态。

IsDebuggerPresent 检测

通过直接利用系统 IsDebuggerPresent函数,进行判断当前程序是否处于调试状态。

如果程序处于调试状态的情况下,那么这个函数的返回返回真,否则返回假。

学到了!软件产品安全性?

CheckRemoteDebuggerPresent 检测

它是微软公开的系统函数,通过利用它可以用于检测,软件是否正在调试远程进程(同一机器上的不同进程中,是否附加到当前进程)。

我们还可以将其用作另一种方法来检测,软件是否处于正在调试。此函数在内部调用NTDLL模块的导出PROCESSINFOCLASS设置为NtQueryInformationProcess函数7(进程调试端口)。本质上是通过NtQueryInformationProcess函数查询是否使用调试端口。

学到了!软件产品安全性?

NtQueryInformationProcess 检测

这个是微软未公开的函数,下面是这个函数的参数信息,可以利用这个函数的第三个参数值,也就是利用PROCESSINFOCLASS值,进行判断是否处于调试状态。

学到了!软件产品安全性?

当程序处于调试状态时,系统会给它分配一个调试端口(Debug Port),当程序正常运行状态时ProcessDebugPort的值为0,当程序处于调试状态ProcessDebugPort的值为0xFFFFFFFF。

当程序处于调试状态时,这个PROCESSINFOCLASS指向ProcessDebugObjectHandle的值是一个句柄值,当程序处于正常状态这个ProcessDebugObjectHandle值为NULL值。

当程序处于调试状态时,这个PROCESSINFOCLASS指向ProcessDebugFlags的值为0,当程序处于正常状态 时,这个ProcessDebugFlags值为1。

学到了!软件产品安全性?

SetUnhandleExceptionFilte 检测

通过利用SetUnhandledExceptionFilter,可以注册一个异常处理函数,当一个异常产生,而且我们的 try - catch(或 try - expect)异常捕获中,没有处理处理这个异常时,异常会转交给 SetUnhandledExceptionFilter 。如果程序存在调试器状态,则调试器就会接管这个异常,那么这个异常就不会走到 SetUnhandledExceptionFilter 注册的异常处理函数。

原理:通过设置一个SetUnhandledExceptionFilter。然后利用RaiseException提出一个异常交给异常处理机制 由于没有设置相应的异常处理程序, 当程序被调试时,会通知进程的调试器,而不会调用UnhandledExceptionFilter。

学到了!软件产品安全性?

SetHandleInformation 检测

通过创建一个互斥体对象,利用# SetHandleInformation将互斥体对象句柄标志改为HANDLE_FLAG_PROTECT_FROM_CLOSE,然后关闭句柄,如果是在调试器状态下,它会抛出EXCEPTION_EXECUTE_HANDLER异常,只要捕获到异常那么就表示程序被调试。

学到了!软件产品安全性?

CloseHandle 检测

利用异常捕获机制,给CloseHandle函数一个无效的句柄作为输入参数,在程序在没有被调试时,将会返回一个错误代码;而程序被调试器调试时,将会触发一个EXCEPTION_INVALID_HANDLE的异常。

学到了!软件产品安全性?

父进程反调试检测

在window系统中explorer是程序管理器或者文件管理器,一般双击运行的进程,它的父进程就都是explorer程序,如果是被调试进程启动的话那么父进程是调速器进程。通过利用CreateToolhelp32Snapshot函数或ZwQueryInformationProcess函数进行检测进程的父进程名称。

学到了!软件产品安全性?

硬件断点反调试检测

硬件断点是intel在其处理器体系结构中实现的一种技术,通过使用Dr0-Dr7的特殊寄存器进行控制。在32位寄存器中Dr0-Dr3是保存断点地址,只要识别Dr0-Dr3寄存器的值不为0,那么就属于调试状态。

软件断点反调试检测

在IA-32指令集中使用操作码0xCC,表示软件断点,也就是INT3断点。

通过Int3产生异常中断的反调试相对比较经典。Ollydbg的断点机制就是利用这个机制, 当INT3 被执行到时, 如果程序未被调试, 将会异常处理器程序继续执行。而INT3指令常被调试器用于设置软件断点,int 3会导致调试器误认为这是一个自己的断点,从而不会进入异常处理程序。

其他反调试检测

通过利用FindWindow(),GetWindowLongA(),EnumWindow()等函数,进行遍历检测调试器的的窗口及控件相关信息;

通过CreateToolhelp32Snapshot等函数遍历运行进程,检测调试器相关的进程名信息,

通过查找注册表方式,检测调试器的信息。

通过检测驱动设备名称,检测调试器的特征码相关信息。

总结

以上梳理的应用层反调试方案建议结合使用,可以同时提高对应的难点。反调试只是一定情况下提高软件安全门槛,因为虽然有反调试方案,但同时也会有过掉反调试的方案。一般过掉反调试检测方案,通过将关键的反调试检测地方给 nop掉或者hook掉关键函数。反调试和反反调试的方案都是相对的,并不是绝对的安全。反调试强度更高的方案在于驱动层去检测实现。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Easter79 Easter79
3年前
sql注入
反引号是个比较特别的字符,下面记录下怎么利用0x00SQL注入反引号可利用在分隔符及注释作用,不过使用范围只于表名、数据库名、字段名、起别名这些场景,下面具体说下1)表名payload:select\from\users\whereuser\_id1limit0,1;!(https://o
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Stella981 Stella981
3年前
Nginx + lua +[memcached,redis]
精品案例1、Nginxluamemcached,redis实现网站灰度发布2、分库分表/基于Leaf组件实现的全球唯一ID(非UUID)3、Redis独立数据监控,实现订单超时操作/MQ死信操作SelectPollEpollReactor模型4、分布式任务调试Quartz应用
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Stella981 Stella981
3年前
Nginx反向代理upstream模块介绍
!(https://oscimg.oschina.net/oscnet/1e67c46e359a4d6c8f36b590a372961f.gif)!(https://oscimg.oschina.net/oscnet/819eda5e7de54c23b54b04cfc00d3206.jpg)1.Nginx反
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
李志宽
李志宽
Lv1
男 · 长沙幻音科技有限公司 · 网络安全工程师
李志宽、前百创作者、渗透测试专家、闷骚男一位、有自己的摇滚乐队
文章
89
粉丝
25
获赞
43