checksum的编程实现

checksum的编程实现,第1张

/// <summary>

/// 获取校验和,ASCII编码

/// </summary>

/// <param name="s"></param>

/// <param checkSum="s"></param>

#region 获取校验和,ASCII编码

/// <summary>

/// 获取校验和,ASCII编码

/// </summary>

/// <param name="s"></param>

/// <param checkSum="s"></param>

private bool GetCheckSum( string s , out string checkSum )

{

checkSum = ""

if ( 0 == s.Length )

return false

int sIndex = s.IndexOf( '$' ) + 1

int eIndex = s.IndexOf( "**" )

string str = ""

if ( sIndex <1 || eIndex <1 )

str = s

else

str = s.Substring( sIndex , eIndex - sIndex )

byte [] cs = Encoding.ASCII.GetBytes( str )

//核心部分

for ( int i = 0 i <cs.Length - 1 i++ )

{

cs [i + 1] = (byte) ( cs [i] ^ cs [i + 1] )

}

checkSum = cs [cs.Length - 1].ToString( "x2" ).ToUpper()

//checkSum = Convert.ToString( cs [cs.Length - 1] , 16 ).ToUpper()

return true

}

校验和(Checksum)

PE的可选映像头(IMAGE_OPTION_HEADER)里面,有一个Checksum字段,是该文件的校验和,一般EXE文件可以使0,但一些重要的和系统DLL及驱动文件必须有一个校验和.

Windows 提供了一个API函数MapFileAndCheckSum 测试文件的Checksum,它位于IMAGEHLP.DLL链接库里,其原型:

ULONG MapFileAndCheckSum

{

LPSTR FileName, // 文件名

LPDWORD HeaderSum, // 指向PE文件头的CheckSum

LPDWORD new_checksum // 指向新计算出的Checksum

}

程序一旦运行后,new_checksum 地址处将放当前的文件的校验和,old_checksum地址指向PE文件的checksum字段

安全的方法是将此值放在注册表里,需要时比较.

内存映像校验

磁盘文件完整性校验可以抵抗解密者直接修改文件,但对内存补丁却没有效果,必须对内存关键的代码进行校验.

1 对整个代码进行校验

每个程序至少有一个代码区块和数据区块,数据区块属性可读写,程序运行时全局变量通常会放在这里,这些数据会动态变化,因此校验这部分是没什么意义,而代码段只读,存放的是程序代码,在程序中数据数不会变的,因此用这部分进行内存校验是可行的.

具体实现方法:

(1) 从内存中映像中得到PE相关数据,如代码块的RVA和内存大小

(2) 根据得到代码区块的RVA值和内存大小,计算出内存数据的CRC-32值

(3) 读取自身文件先前存储的CRC-32值(PE文件头前一个字段),这个值是通过软件写进去的.

(4) 比较两个CRC-32值.

这样比较内存的代码段校验,只要内存的数据被修改,就能发现。

BOOL CodeSectionCRC32()

{

PIMAGE_DOS_HEADER pDosHeader = NULL

PIMAGE_NT_HEADERS pNTHeader = NULL

PIMAGE_SECTION_HEADER pSection = NULL

DWORD ImageBase,OriginalCRC32

ImageBase = (DWORD)GetModuleHandle(NULL)// 取基址

pDosHeader = (PIMAGE_DOS_HEADER)ImageBase

pNtHeader = (PIMAGE_NT_HEADER32)((DWORD)pDosHeader + pDosHeader ->e_lfanew)

// 定位到PE文件头前4个字节值,并读取存储在这里的CRC -32值

OriginalCRC32 = *((DWORD*)(DWORD)pNtHeader - 4)

pSecHeader = IMAGE_FIRST_SECTION(pNtHeader) // 得到第一个区块的地址

//假设第一个区块就是代码区块

if(OriginalCRC32 == CRC32((BYTE*)ImageBase + pSecHeader ->VirtualAddress)

// 为了方便加壳

// 上一句也可为if(OriginalCRC32 == CRC32((BYTE *)0x401000, 0x36AE)

return TRUE

else

return FALSE

}


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/7888203.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-11
下一篇 2023-04-11

发表评论

登录后才能评论

评论列表(0条)

保存