反调试——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检测的更多相关文章

  1. 基于TLS的反调试技术

    TLS(Thread Local Storage 线程局部存储) 一个进程中的每个线程在访问同一个线程局部存储时,访问到的都是独立的绑定于该线程的数据块.在PEB(进程环境块)中TLS存储槽共64个( ...

  2. 【Python3爬虫】突破反爬之应对前端反调试手段

    一.前言 在我们爬取某些网站的时候,会想要打开 DevTools 查看元素或者抓包分析,但按下 F12 的时候,却出现了下面这一幕:   此时网页暂停加载,自动跳转到 Source 页面并打开了一个 ...

  3. C/C++ 程序反调试的方法

    C/C++ 要实现程序反调试有多种方法,BeingDebugged,NtGlobalFlag,ProcessHeap,CheckRemoteDebuggerPresent,STARTUPINFO,Is ...

  4. 编译Android内核 For nexus 5 以及绕过Android的反调试

    本文博客链接:http://blog.csdn.net/qq1084283172/article/details/54880488 前面的博客中已经记录了Nexus 5手机的Android 4.4.4 ...

  5. 反调试技术常用API,用来对付检测od和自动退出程序

    在调试一些病毒程序的时候,可能会碰到一些反调试技术,也就是说,被调试的程序可以检测到自己是否被调试器附加了,如果探知自己正在被调试,肯定是有人试图反汇编啦之类的方法破解自己.为了了解如何破解反调试技术 ...

  6. 反调试——11——检测TF标志寄存器

    反调试--11--检测TF标志寄存器 在intel的x86寄存器中有一种叫标志寄存器: 标志寄存器中的TF(Trap Flag)位,CPU在执行完一条指令后,如果检测到标志寄存器的TF位为1,则会产生 ...

  7. WinDbg调试流程的学习及对TP反调试的探索

    基础知识推荐阅读<软件调试>的第十八章 内核调试引擎 我在里直接总结一下内核调试引擎的几个关键标志位,也是TP进行反调试检测的关键位. KdPitchDebugger : Boolean ...

  8. JavaScript反调试技巧

    一.函数重定义 这是一种最基本也是最常用的代码反调试技术了.在JavaScript中,我们可以对用于收集信息的函数进行重定义.比如说,console.log()函数可以用来收集函数和变量等信息,并将其 ...

  9. Windows 下常见的反调试方法

    稍稍总结一下在Crack或Rervese中比较常见的一些反调试方法,实现起来也比较简单,之后有写的Demo源码参考,没有太大的难度. ①最简单也是最基础的,Windows提供的API接口:IsDebu ...

随机推荐

  1. 痞子衡嵌入式:简析i.MXRT1170 XECC功能特点及其保护串行NOR Flash和SDRAM之道

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是i.MXRT1170 XECC功能特点及其保护串行NOR Flash和SDRAM之道. ECC 是 "Error Correc ...

  2. 有关Java动态数组的一个小问题

    前言 问题描述 今天遇到一个关于集合的问题,觉得比较有趣,记录一下,这个问题是:定义一个用户类,至少包含姓名,年龄,生日,qq邮箱,初始化10个用户,利用String操作,提取qq到List集合中,姓 ...

  3. Java - 记录01_开发环境搭建

    时间:2017-07-04 记录:byzqy 一.什么是JDK JDK(Java Development Kit):Java开发工具集,即Java语言的软件开发工具包. SDK(Software De ...

  4. (五)羽夏看C语言——结构体与类

    写在前面   由于此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇 ...

  5. dotnet C# 给结构体字段赋值非线程安全

    在 dotnet 运行时中,给引用对象进行赋值替换的时候,是线程安全的.给结构体对象赋值,如果此结构体是某个类的成员字段,那么此赋值不一定是线程安全的.是否线程安全,取决于结构体的大小,取决于此结构体 ...

  6. 性能测试工具JMeter 基础(二)—— 主界面介绍

    主界面介绍 JMeter的主界面主要分为菜单导航栏.工具栏.计划树标签栏.内容栏 菜单导航栏:全部的功能的都包含在菜单栏中 工具栏:相当于菜单栏常用功能的快捷按钮 计划树标签栏:显示测试用例(计划)相 ...

  7. vim编辑器设置

    由于ubantu自带的vi编辑器并不好用,而开发一般使用vim编辑器,vim需要自己安装(sudo apt-get install vim 即可安装),但是默认的设置使用起来很不舒服,因此可以通过修改 ...

  8. openswan专栏序言

    openswan专栏序言 "一杯茶,一包烟,一个bug解一天!!!". ​ 2020年春季,正值新冠病毒在全球肆虐之际,美国的疫情已经相当的严峻,每天仍以3万速度狂奔.而国内的疫情 ...

  9. AQS深入分析

    一.node概念 1.当线程获取锁失败时,会被打包成一个node放到同步队列中 2.node属性 当线程获取锁失败时,会被打包成一个node放到同步队列中,所以node属性中有一个thread属性; ...

  10. 植入式Web前端开发

    在博客园.凡科建站和其他的一些CMS系统中,提供有允许管理者向网页中插入自定义HTML代码的功能,我将其称之为"植入式"的Web前端代码. 因为CSS和JavaScript可以直接 ...