反调试——7——CRC检测
反调试——7——CRC检测
CRC32:
CRC的全称是循环冗余校验,作用是为了检测数据的完整性。
CRC32的检测原理:
程序被编译后,代码段是固定的,因为已经被写死了。
我们在调试程序的时候,打断点或者修改代码都会影响CRC32的值,这个时候只需要检测CRC32的某一时刻值和最初的CRC32值是否一致就可以判断代码是否被修改了。
如果装了好压这个软件可以直接通过右键查看到CRC32的值:

这里我找了一个简单的CRC32的代码来测试一下:
#include<iostream>
uint32_t crc32_table[256];
int make_crc32_table()
{
uint32_t c;
int i = 0;
int bit = 0;
for (i = 0; i < 256; i++)
{
c = (uint32_t)i;
for (bit = 0; bit < 8; bit++)
{
if (c & 1)
{
c = (c >> 1) ^ (0xEDB88320);
}
else
{
c = c >> 1;
}
}
crc32_table[i] = c;
}
return 1;
}
uint32_t make_crc(unsigned char* string, uint32_t size)
{
uint32_t crc= 0xFFFFFFFF;
make_crc32_table();
while (size--)
crc = (crc >> 8) ^ (crc32_table[(crc ^ *string++) & 0xff]);
return crc;
}
利用CRC32检测自己程序是否被修改:
通过对代码段进行CRC32判断来处理。首先要拿到代码段,通过Windows 的PE文件的结构体 Dos头->NT头->(采用VS里的结构体)拿到区段头->然后通过区段头得到区段的信息。
char *buffer=(char*)GetModuleHandleA(0);//参数为0就获取当前进程的句柄
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)buffer;
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(pDosHeader->e_lfanew + buffer);
PIMAGE_SECTION_HEADER pSectionHeader = IMAGE_FIRST_SECTION(pNtHeader);
for (int i = 0; i < pNtHeader->FileHeader.NumberOfSections - 1; i++)
{
}
判断是否是代码段:
代码段顾名思义,就是执行代码的东西。在PE文件中的区段头里有一个字段可以判断属性:
typedef struct _IMAGE_SECTION_HEADER {
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
union {
DWORD PhysicalAddress;
DWORD VirtualSize;
} Misc;
DWORD VirtualAddress;
DWORD SizeOfRawData;
DWORD PointerToRawData;
DWORD PointerToRelocations;
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics;//这个
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER
Characteristics这个字段标识了是否是可执行。在CFF里面查看:


这里通过我的测试,在修改可读可写的属性时会修改最高字段的值,如果有就加2,然后别的就修改别的值,所以这里我们判断首位是不是6就可以判断是不是代码段了。
void Crc32Test()
{
char *buffer=(char*)GetModuleHandleA(0);//参数为0就获取当前进程的句柄
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)buffer;
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(pDosHeader->e_lfanew + buffer);
PIMAGE_SECTION_HEADER pSectionHeader = IMAGE_FIRST_SECTION(pNtHeader);
for (int i = 0; i < pNtHeader->FileHeader.NumberOfSections - 1; i++)
{
if (pSectionHeader->Characteristics / 0x10000000 == 6)
{
cout << pSectionHeader->Name << endl;
auto CrcNum = make_crc((unsigned char*)(pSectionHeader->VirtualAddress + buffer), pSectionHeader->Misc.VirtualSize);
cout << CrcNum << endl;
}
pSectionHeader++;
}
}
然后通过ollydbg随便打一个int3断点(因为int3断点会添加一个CC在里面所以肯定的改变了代码段的内容的)再运行来看CRC的值是否改变:

这里果然是改变了。
小结
CRC是一个演算东西的内容,类似于一些hash运行把,就是把一坨东西来计算一个值出来,由于一个程序写好了之后代码段是不会改变的,所以我们可以把它用来计算代码段的内容,然后再程序里面时刻计算这个值有没有改变来判断是否被修改了代码。
完整代码:反调试--CRC检测 - Sna1lGo - 博客园 (cnblogs.com)
反调试——7——CRC检测的更多相关文章
- 基于TLS的反调试技术
TLS(Thread Local Storage 线程局部存储) 一个进程中的每个线程在访问同一个线程局部存储时,访问到的都是独立的绑定于该线程的数据块.在PEB(进程环境块)中TLS存储槽共64个( ...
- 【Python3爬虫】突破反爬之应对前端反调试手段
一.前言 在我们爬取某些网站的时候,会想要打开 DevTools 查看元素或者抓包分析,但按下 F12 的时候,却出现了下面这一幕: 此时网页暂停加载,自动跳转到 Source 页面并打开了一个 ...
- C/C++ 程序反调试的方法
C/C++ 要实现程序反调试有多种方法,BeingDebugged,NtGlobalFlag,ProcessHeap,CheckRemoteDebuggerPresent,STARTUPINFO,Is ...
- 编译Android内核 For nexus 5 以及绕过Android的反调试
本文博客链接:http://blog.csdn.net/qq1084283172/article/details/54880488 前面的博客中已经记录了Nexus 5手机的Android 4.4.4 ...
- 反调试技术常用API,用来对付检测od和自动退出程序
在调试一些病毒程序的时候,可能会碰到一些反调试技术,也就是说,被调试的程序可以检测到自己是否被调试器附加了,如果探知自己正在被调试,肯定是有人试图反汇编啦之类的方法破解自己.为了了解如何破解反调试技术 ...
- 反调试——11——检测TF标志寄存器
反调试--11--检测TF标志寄存器 在intel的x86寄存器中有一种叫标志寄存器: 标志寄存器中的TF(Trap Flag)位,CPU在执行完一条指令后,如果检测到标志寄存器的TF位为1,则会产生 ...
- WinDbg调试流程的学习及对TP反调试的探索
基础知识推荐阅读<软件调试>的第十八章 内核调试引擎 我在里直接总结一下内核调试引擎的几个关键标志位,也是TP进行反调试检测的关键位. KdPitchDebugger : Boolean ...
- JavaScript反调试技巧
一.函数重定义 这是一种最基本也是最常用的代码反调试技术了.在JavaScript中,我们可以对用于收集信息的函数进行重定义.比如说,console.log()函数可以用来收集函数和变量等信息,并将其 ...
- Windows 下常见的反调试方法
稍稍总结一下在Crack或Rervese中比较常见的一些反调试方法,实现起来也比较简单,之后有写的Demo源码参考,没有太大的难度. ①最简单也是最基础的,Windows提供的API接口:IsDebu ...
随机推荐
- vue 中this.$on 为什么要放在created中?
最近在思考一个问题为什么一定要在created中写this.$on,可以放在mounted中吗 如果触发和监听组件在页面上都创建了,那么可以放在mounted中 这种情况在实际工作中比较常见,如果在触 ...
- HCNP Routing&Switching之OSPF LSA类型
前文我们了解了OSPF中的虚连接相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15202348.html:今天我们来聊一聊OSPF数据包中LSA类型相 ...
- Faiss使用多线程出现的性能问题
Faiss使用多线程出现的性能问题 faiss在增加CPU的情况下,反而出现效率低下的问题. 从理论上看,作为一个CPU/GPU计算型的应用,更多的核意味着更大的计算吞吐能力,性能只会越来越好才是. ...
- (原创)[C#] DataTable排序扩展方法
一,前言 DataTable的应用极其广泛,对DataTable进行排序也有很多方式,每种的实现方式都不难,但是使用起来却比较繁琐,所以本人便写了一个扩展方法,专门对DataTable进行操作. 本篇 ...
- RHEL7.2系统下的软件管理(yum)、本地yum源和网络yum源的搭建
在Liunx系统中,rpm和yum都可以安装软件,但rpm存在安装软件的依赖性,yum安装软件需要yum源 1.yum yum install softwarename ##安装 yum repoli ...
- Python中的变量以及变量的命名
1.变量的定义 在 python 中,每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建 等号(=)用来给变量赋值 =左边是一个变量名 =右边是存储在变量中的值 变量名=值 变量定义之后,后续就 ...
- Mybatis源码解析4——SqlSession
上一篇文章中,我们介绍了 SqlSessionFactory 的创建过程,忘记了的,可以回顾一下,或者看下下面这张图也行. 接下来,可乐讲给大家介绍 Mybatis 中另一个重量级嘉宾--SqlSes ...
- Insights直播预告 | 多媒体管线服务,助您轻松进入“技术流”创新阵地
[导读] 随着各类音视频移动应用快速发展,短视频.线上直播等娱乐方式逐渐为大众所喜爱.优质的视听效果和交互体验,往往能吸引更多的用户.多媒体管线服务作为一个轻量级的多媒体开发框架,其跨平台.高性能的多 ...
- ELK学习之Logstash+Kafka篇
上一篇介绍了一下Logstash的数据处理过程以及一些基本的配置功能,同时也提到了Logstash作为一个数据采集端,支持对接多种输入数据源,其中就包括Kafka.那么这次的学习不妨研究一下Logst ...
- 《手把手教你》系列技巧篇(二十六)-java+ selenium自动化测试-浏览器操作(详细教程)
1.简介 在Web自动化的操作中,我们通常需要使用一些方法来操作浏览器,今天就来学习一下.这一篇宏哥主要是介绍一下,在自动化测试的时候,我们常见的一些浏览器操作有哪些,宏哥将会一一介绍和讲解. 2.浏 ...