反调试——7——CRC检测
2021/10/9 23:40:40
本文主要是介绍反调试——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检测的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享