仅供小菜娱乐!
高手莫要见笑.
测试环境:XP3
编译环境:VS2005
一般的程序保护中监测代码只检查程序中的代码是否遭到了篡改是不够的, 应监测代码相互之间也要进行防篡改检查, 如果监测代码相互之间不进行防篡改检查, 就会很容易地被攻击者各个击破。
将被检查的代码区域组成一张网, 组成这张网的代码区域可以是程序中的代码, 也可以是监测代码或者响应代码, 监测代码计算一或多个代码区域的HASH值, 一旦监测代码发现某个区域中的代码遭到了篡改, 响应代码就会用存放在其他地方的备份代码替换掉该区域中的代码(或者做其它事), 多个监测代码可以检查同一个区域, 这样可能通过增加监测和响应代码的数量或者使它们之间关系变得更为复杂.
下面是简单的小示例:
1.要计算某个函的的hash值,得获得该函数大小.
//获取函数的大小: 参数 address 指向函数的起始地址
uint32 GetFunSize(addr_t address)
{
BYTE Fun_end[] = {0x88, 0x88, 0x88, 0x88}; //函数结尾的标志
uint32 Fun_size = 0;
while(TRUE)
{
if(!memcmp((BYTE*)address + Fun_size, Fun_end, sizeof(Fun_end))) //找到结束标志
{
while(TRUE)
{
if ( 0XC3 == *((BYTE*)address+ Fun_size))//找到返回
{
return Fun_size;
}
Fun_size++;
}
}
Fun_size++;
}
}
2.计算函数hash值.
//获取Hash值: 参数 address 指向函数的起始地址, Size函数大小
uint32 hash(addr_t addr, int Size)
{
if (NULL == addr || 0 == Size)
{
return 0;
}
uint32 h = *addr;
for (int i=1; i<Size; i++)
{
addr++;
h ^= *addr;;
}
return h;
}
3.简单调用,监测是否被修改,如果遭到了篡改,拷贝备份好的修复.
int Decrypt(int User_Key, int Data)
{
DWORD lpflOldProtect = 0;
uint32 FunSize = GetFunSize((addr_t)GetKey);
uint32 hGetKeyVal = hash((addr_t)GetKey, FunSize);
printf("GetKey 大小为 : %X\n",FunSize);
printf("GetKey HASH为 : %X\n",hGetKeyVal);
//判断是否被修改,被修改后恢复
if( hGetKeyVal != GetKeyHASH )
{
//将备份函数拷过去
VirtualProtect(GetKey,FunSize, PAGE_EXECUTE_READWRITE, &lpflOldProtect);
memcpy(GetKey, GetKey_Back, FunSize);
VirtualProtect(GetKey,FunSize, lpflOldProtect, &lpflOldProtect);
}
int key = GetKey(User_Key);
__asm
{
JMP END
_emit 0x88
_emit 0x88
_emit 0x88
_emit 0x88
}
END:
return Data ^ key;
}
4.运行成功后如下图所示
5.具体请看源码
src.rar
bin.zip
[课程]Android-CTF解题方法汇总!