首页
社区
课程
招聘
[原创]PE文件格式学习小结 之 校验和的计算
发表于: 2008-3-26 14:05 15757

[原创]PE文件格式学习小结 之 校验和的计算

2008-3-26 14:05
15757
大部分PE文件都不使用文件头中的CheckSum域的校验和值,不过有些PE文件,如关键的系统服务程序文件以及驱动程序文件则该值必须正确,否则系统加载器将拒绝加载。PE

头部的CheckSum 可以使用Imagehlp.dll的导出函数 CheckSumMappedFile计算,在MSDN中纪录的这个函数的定义是这样的:

PIMAGE_NT_HEADERS CheckSumMappedFile(
	IN LPVOID BaseAddress,  
	IN DWORD FileLength, 
	OUT LPDWORD HeaderSum, 
	OUT LPDWORD CheckSum 
);
它的使用方法我在网上没有找到具体的例子!我们可以逆向一下LordPE看一下:

0040FF50  /$  8B15 C8DF4100 mov     edx, dword ptr [41DFC8]
0040FF56  |.  83EC 14       sub     esp, 14
0040FF59  |.  8D4424 00     lea     eax, dword ptr [esp]
0040FF5D  |.  8D4C24 04     lea     ecx, dword ptr [esp+4]
0040FF61  |.  50            push    eax
0040FF62  |.  A1 CCDF4100   mov     eax, dword ptr [41DFCC]
0040FF67  |.  51            push    ecx
0040FF68  |.  52            push    edx
0040FF69  |.  50            push    eax
0040FF6A  |.  FF15 74904100 call    dword ptr [<&IMAGEHLP.CheckSumMappedFile>]   ;  IMAGEHLP.CheckSumMappedFile
0040FF70  |.  85C0          test    eax, eax
0040FF72  |.  75 04         jnz     short 0040FF78
0040FF74  |.  83C4 14       add     esp, 14
0040FF77  |.  C3            retn
0040FF78  |>  8B4C24 00     mov     ecx, dword ptr [esp]
0040FF7C  |.  8B15 68BC4100 mov     edx, dword ptr [41BC68]                      ;  LordPE_h.0041BCB0
0040FF82  |.  51            push    ecx
0040FF83  |.  8D4424 0C     lea     eax, dword ptr [esp+C]
0040FF87  |.  52            push    edx                                          ; |Format => "%08lX"
0040FF88  |.  50            push    eax                                          ; |s
0040FF89  |.  FF15 C0924100 call    dword ptr [<&USER32.wsprintfA>]              ; \wsprintfA
0040FF8F  |.  8B5424 24     mov     edx, dword ptr [esp+24]
0040FF93  |.  83C4 0C       add     esp, 0C
0040FF96  |.  8D4C24 08     lea     ecx, dword ptr [esp+8]
0040FF9A  |.  51            push    ecx                                          ; /Text
0040FF9B  |.  68 00040000   push    400                                          ; |ControlID = 400 (1024.)
0040FFA0  |.  52            push    edx                                          ; |hWnd
0040FFA1  |.  FF15 0C924100 call    dword ptr [<&USER32.SetDlgItemTextA>]        ; \SetDlgItemTextA
0040FFA7  |.  B8 01000000   mov     eax, 1
0040FFAC  |.  83C4 14       add     esp, 14
0040FFAF  \.  C3            retn
这里我给出我的使用例子!
在工程中导入imagehlp.lib:	#pragma comment(lib, "imagehlp.lib")

unsigned long LoadPEFile(char *FileName, char **Buffer)
{
	FILE *fp = fopen(FileName, "rb");
	fseek(fp, 0, SEEK_END);
	unsigned long len = ftell(fp);
	fseek(fp, 0, SEEK_SET);
	*Buffer = new char[len + 4];
	memset(*Buffer, 0x0, len + 4);
	unsigned long i = 0;
	while(i < len)
	{
		fread(*Buffer + i, 4, 1, fp);
		i+=4;
	}
	fclose(fp);
	return len;
}


void OnCheckSum() 
{
	char *Buffer = NULL;
	char *PEFile = "c:\\ps.exe";
	DWORD HeaderSum,CheckSum;
	unsigned long len = LoadPEFile(PEFile, &Buffer);
	::CheckSumMappedFile(Buffer, len, &HeaderSum, &CheckSum);
	m_CheckSum.Format(_T("%.8X"),CheckSum);

	UpdateData(FALSE);
}

当然,在有些时候,我们并不能使用IMAGEHLP.CheckSumMappedFile函数,必须让我们自己动手来计算!

也可以在将该域清0后按照如下简单的等价算法计算:

  如果PE文件大小是奇数字节,则以0补足,使之按偶数字节。将PE文件头的CheckSum 域清0,然后以两个字节为单位进行adc运算,最后和将该累加和同文件实际大小进行adc运

算即得到校验和的值。
    具体的计算方法,"hume"老大早就写过一篇了~,这里我就不自己写了,就直接引用他的~~

下面的cal_checksum过程假设esi 已经指向PE文件头,文件头部CheckSum域已经被清0,CF 标志位已经被复位:
;调用示例: 
;clc 
;push pe_fileseize 
;call cal_checksum
cal_checksum: 
adc bp,word [esi] ;初始esi指向文件头,ebx 中保存的是文件大小
inc esi 
inc esi 
loop cal_checksum 
mov ebx,[esp+4] 
add ebp,ebx ;ebp 中存放的就是PE 的校验和
ret 4 

        具体的代码,大家可以看hume老大发表的帖子,我就不写了~

[课程]Linux pwn 探索篇!

收藏
免费 8
支持
分享
最新回复 (12)
雪    币: 297
活跃值: (27)
能力值: ( LV13,RANK:380 )
在线值:
发帖
回帖
粉丝
2
Hume有一处笔误,也被你不客气地复制粘贴了。

最后和将该累加和同文件实际大小进行adc运算即得到校验和的值。
->
最后和将该累加和同文件实际大小进行add运算即得到校验和的值。
2008-3-26 21:14
0
雪    币: 65
活跃值: (811)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
3
改过来了~~~
嘿嘿`~
2008-3-26 21:39
0
雪    币: 282
活跃值: (31)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
......
2008-3-28 08:32
0
雪    币: 197
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
我来给你顶一下
2008-3-28 16:51
0
雪    币: 334
活跃值: (22)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
再次顶一下,嘿嘿
2008-3-28 17:12
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
第二次看见CheckSumMappedFile
学习一下。。。。
2008-3-28 17:14
0
雪    币: 65
活跃值: (811)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
8

这样就能骗到精华了?
以后要加紧努力,使劲忽悠~~~
2008-3-30 21:14
0
雪    币: 243
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
搞不懂lz"逆向一下LordPE"有什么意义
2008-3-30 22:44
0
雪    币: 229
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
OK,好东西收了!!!
2008-4-1 01:36
0
雪    币: 65
活跃值: (811)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
11
至于,逆向一下LordPE的意义,那要看你怎么来理解逆向!
如果是从学习人家编程方式的方向来理解的话!
我逆向它是因为我刚开始的时候我不会算校验和,想看一下LordPE是怎么计算的,当我发现它是用CheckSumMappedFile()的时候,我在网上又没有找到CheckSumMappedFile()的具体使用方法,所以就逆向它,看看这个函数怎么用了!!

如果单纯的从逆向角度来理解的话,我纯粹就是为了锻炼一下自己的软件调试能力,因为,我分析程序的时候,很多的地方我都断不下来!

如果非要讲出一个什么意义的话,那我也可以说,没有意义,因为这个文章不是为了教大家怎么计算校验和,因为我还不够资格,我帖这个帖子就是为了把我从逆向中学习编程的过程纪录一下,只是纪录一下思路,让大家看看有没有什么问题,没有别的意思,所以,这个帖子本身的意义就不打,这也是为什么我不是只帖出我写的C程序的原因!
2008-4-29 08:33
0
雪    币: 4593
活跃值: (3572)
能力值: ( LV12,RANK:230 )
在线值:
发帖
回帖
粉丝
12
这个,不应该太迷信网络搜索,事实上MSDN里的介绍就足够了。
2008-4-29 09:20
0
雪    币: 7309
活跃值: (3778)
能力值: (RANK:1130 )
在线值:
发帖
回帖
粉丝
13
也许是MSDN觉得太简单了,没给例子
2008-4-29 10:08
0
游客
登录 | 注册 方可回帖
返回
//