首页
社区
课程
招聘
TLS回调 和 PE校验和
发表于: 2010-3-4 16:50 15187

TLS回调 和 PE校验和

2010-3-4 16:50
15187
原谅我一次提俩问题
①关于TSL回调 先参考一篇文章 http://bbs.pediy.com/showthread.php?t=108015
说在VC6.0下有bug,确实我试了好多次都不行
换2005,发现Debug版本可以,但Release版本就不行了  请问是为什么
有人说 那个obj文件的问题  说怎么怎么弄  最后还要属性也一样 obj文件咋查属性?
告诉为什么Release版本不行  然后告诉我怎么样才能使Release行就ok
②关于PE校验和
下面一段代码给出了3种实现  其中第一种是我翻译第三种得来的
#include "StdAfx.h"
#include "windows.h"
#include "imagehlp.h"

int main(int argc, char* argv[])
{
	char buf[300];
	ZeroMemory(buf, 300);
// 	printf("Hello World!\n");
// 	printf("Input your file path and name:\n");
// 	scanf("%s", &buf);
// 	printf("Your file name is: %s\n", buf);
	
	HANDLE hFile = CreateFile("a.exe",
		GENERIC_READ | GENERIC_WRITE,
		FILE_SHARE_READ,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL);
	if(hFile == INVALID_HANDLE_VALUE){
		printf("Open File Failed!\n");
		return 0;
	}
	
	HANDLE hFileMapping = CreateFileMapping(hFile,
		NULL,
		PAGE_READWRITE,
		0, 0, 0);
	if(hFileMapping == NULL){
		printf("Create Mapping File Failed!\n");
		CloseHandle(hFile);
		return 0;
	}
	
	LPVOID lpBase = MapViewOfFile(hFileMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
	if(lpBase == NULL){
		printf("Failed to Map the File!\n");
		CloseHandle(hFileMapping);
		CloseHandle(hFile);
	}
	
	PIMAGE_DOS_HEADER dosH = (PIMAGE_DOS_HEADER)lpBase;
	if(dosH->e_magic == 0x5a4d){
		DWORD off = dosH->e_lfanew;
		PIMAGE_NT_HEADERS ntH = (PIMAGE_NT_HEADERS)((PBYTE)dosH + off);
		if(ntH->Signature == 0x4550){
			printf("It's a PE File.\n");
			DWORD checksum = ntH->OptionalHeader.CheckSum;
			printf("CheckSum is : 0x%08X\n", checksum);
			ntH->OptionalHeader.CheckSum = 0;
			DWORD fileSize = GetFileSize(hFile, 0);
			DWORD checksum2 = 0;
/**************************C语言的方式*******************************/
			WORD *p = (WORD*)lpBase;
			DWORD dwLength = fileSize;
			__asm
			{
				clc
			}
			for (DWORD i=0; i<fileSize/2; i++)
			{
				checksum2 += *p++;
				if ((checksum2 | 0x0000FFFF) != 0x0000FFFF)
				{
					checksum2++;
					checksum2 &= 0x0000ffff;
				}
				dwLength -= 2;
			}
			if (dwLength == 1)
			{
				checksum2 += *(unsigned char*)p;
			}
			checksum2 += fileSize;
			printf("*******1******** 0x%.8X\n", checksum2);
/**************************Windows API方式*******************************/
			DWORD s1,s2;
			::CheckSumMappedFile(lpBase, fileSize, &s1, &s2);
			printf("*******2******** 0x%.8X\n", s2);
/**************************汇编方式*******************************/

			checksum2 = 0;
			__asm{
				pushad
					xor eax, eax
					mov ebx, fileSize
					mov ecx, ebx
					push ecx
					shr ecx, 1
					mov esi, lpBase
					clc
cal_checksum:
				adc ax, word ptr [esi]
					inc esi
					inc esi
					loop cal_checksum
					adc ax, 0
					
					pop ecx
					test ecx, 1
					jz __end
					xor edi, edi
					movzx di, byte ptr [esi]
					clc
					add ax, di
__end:
				add eax, ebx ;
				mov checksum2, eax
					popad
			}
			
			printf("*******3******** 0x%08X\n", checksum2);
			ntH->OptionalHeader.CheckSum = checksum;
		}
	}
	UnmapViewOfFile(lpBase);
	CloseHandle(hFileMapping);
	CloseHandle(hFile);
	return 0;
}

然后我的问题是:
假如exe的PE头里面的校验和为0x00000000(这很正常,很多的PE头里的CheckSum字段都是0),用LordPE查一下发现是0x00123456,然后我们保存(不要点确定,要点保存),然后我们比较保存后和保存前的俩exe files,结果就是PE头里的CheckSum子段由0x00000000变成了0x00123456,然后我们用上面那个程序去检查刚修改完的exe  发现了和修改前的校验和一样!!
但是明明这个字段改变了啊?为什么?很迷茫。。。

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (18)
雪    币: 724
活跃值: (81)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
第一个问题:关于TLS回调,我已在帖子http://bbs.pediy.com/showthread.php?t=108015中回答过了,你看一下吧,有问题再讨论。
第二个问题:
用LordPE查一下发现是0x00123456
说明LordPE经过计算后认为PE头中的CheckSum的值应为0x00123456,如果你保存了,LoadPE只是将值写到CheckSum中,再次用LordPE检查刚修改完的EXE,它仍然认为PE头的CheckSum值应该为0x00123456,或者说,CheckSum的现值不影响CheckSum计算,从你贴的代码也可以看到:
ntH->OptionalHeader.CheckSum = 0;

在计算CheckSum之前已先将它清零了。
2010-3-4 17:06
0
雪    币: 458
活跃值: (421)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
3
to LS:
第一个问题 你没有看仔细
第二个问题感谢你的回答,是我看的不仔细
2010-3-4 17:11
0
雪    币: 724
活跃值: (81)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
这么说看过我的回复了,我只能猜你现在的问题是obj的属性问题,obj也是PE结构,它的节头(SECTION HEADER)和EXE文件中的是一样的,VC6中的tlssup.obj中的CRT$XLA和CRT$XLZ节的属性都应是0XC0300040,而2008带的不是。
关于VS2005,我没这个版本,无法验证问题是什么。
2010-3-4 17:33
0
雪    币: 724
活跃值: (81)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
    我来对这个问题进行一下总结,并给出新的解决方法。
    TLS回调问题,网上已有人给出了解决方案,但总是有一些问题,基本如下:
            1、VC6不支持。
            2、VS2005的Debug版正常,Release版不正常。
            3、VS2005的Release版正常,Debug版不正常。
    VC6不支持的原因是VC6带的TLSSUP.OBJ有问题,它已定义了回调表的第一项,并且为0,0意味着回调表的结束,因此我们加的函数都不会被调用。
    对于第2个问题,我没遇到,倒是遇到了第3个问题。对这个问题进行了一下研究,发现问题所在:在Link过程中节.CRT$XLA和.CRT$XLB合并时,应该是按字母顺序无间隙合并,但在DEBUG版的输出中实事并非如此,顺序没错,但却产生了很大的间隙,间隙填0,相当于在我们的回调表前加0若干个0,又是回调表提前结束,这也许是BUG。针对第二种情况,我没有遇到,不知道是否是这个原因,如果是,则我想应是LINK的BUG。
        针对上述问题,本来我想可以使用VS2008的tlssup.obj,但是它与VC6的不兼容,改起来比较麻烦,后来我突然想到,也许我们可以自己创建一个tlssup.obj,基于这个思路,写了自己的tlssup,目前测试结果显示,它可以兼容VC6,VS2005,VS2008,代码如下:

           /*文件名:tlssup.c, 要求以C方式编译, 如果你的工程是CPP工程,请针对此源文件取消预编译头*/
            #include <windows.h>
            #include <winnt.h>

            int _tls_index=0;

            #pragma data_seg(".tls")
            int _tls_start=0;
            #pragma data_seg(".tls$ZZZ")
            int _tls_end=0;
            #pragma data_seg(".CRT$XLA")
            int __xl_a=0;
            #pragma data_seg(".CRT$XLZ")
            int __xl_z=0;

            #pragma data_seg(".rdata$T")

            extern PIMAGE_TLS_CALLBACK my_tls_callbacktbl[];

            IMAGE_TLS_DIRECTORY32 _tls_used={(DWORD)&_tls_start,(DWORD)&_tls_end,(DWORD)&_tls_index,(DWORD)my_tls_callbacktbl,0,0};

            /*tlssup.c结束*/

        然后,我们在其它CPP文件中定义my_tls_callbacktbl如下即可:
            extern "C" PIMAGE_TLS_CALLBACK my_tls_callbacktbl[] = {my_tls_callback1,0};        //可以有多个回调,但一定要在最后加一个空项,否则很可能出错。
        当然下面一行也不能少:
    #pragma comment(linker, "/INCLUDE:__tls_used")
    2010-3-5 09:10
    0
    雪    币: 724
    活跃值: (81)
    能力值: ( LV3,RANK:20 )
    在线值:
    发帖
    回帖
    粉丝
    6
    楼主在线却不结帖,为何?问题没解决?
    2010-3-10 15:34
    0
    雪    币: 285
    活跃值: (16)
    能力值: ( LV3,RANK:20 )
    在线值:
    发帖
    回帖
    粉丝
    7
    就是脱着你的分不给你呗
    2010-3-10 20:19
    0
    雪    币: 1632
    活跃值: (13)
    能力值: ( LV2,RANK:10 )
    在线值:
    发帖
    回帖
    粉丝
    8
    楼主是我朋友,相信解决的话会结贴的,各位放心。
    2010-3-10 20:23
    0
    雪    币: 458
    活跃值: (421)
    能力值: ( LV9,RANK:610 )
    在线值:
    发帖
    回帖
    粉丝
    9
    你说话有点良心好不好  这几天比较忙  而且前几天我回老家一趟这一下就是5天的时间  没有上网
    我刚回来一天多   没来得及调试
    ps.给不给分管你什么事
    2010-3-10 21:52
    0
    雪    币: 309
    活跃值: (10)
    能力值: ( LV2,RANK:10 )
    在线值:
    发帖
    回帖
    粉丝
    10
    额,那位老兄,开开玩笑而以。
    我们都是大丈夫,要容得起玩笑话。。。
    2010-3-10 22:11
    0
    雪    币: 458
    活跃值: (421)
    能力值: ( LV9,RANK:610 )
    在线值:
    发帖
    回帖
    粉丝
    11
    将tlssup.c加入自己的工程  然后
    右键点这个.c文件  
    选择Setting->C/C++->Gategory->Precomliled Headers->Not using precompiled headers
    2010-3-11 09:29
    0
    雪    币: 656
    活跃值: (448)
    能力值: ( LV12,RANK:360 )
    在线值:
    发帖
    回帖
    粉丝
    12
    现金?
    2010-3-12 09:41
    0
    雪    币: 458
    活跃值: (421)
    能力值: ( LV9,RANK:610 )
    在线值:
    发帖
    回帖
    粉丝
    13
    ?啥意思。。。
    2010-3-12 10:21
    0
    雪    币: 78
    活跃值: (10)
    能力值: ( LV2,RANK:10 )
    在线值:
    发帖
    回帖
    粉丝
    14
    虽然结贴了还是发表一下自己找到的东西
    TLS_CallBack漫谈:原理、编程、手工感染及检测
    上传的附件:
    2010-3-12 21:25
    0
    雪    币: 213
    活跃值: (147)
    能力值: ( LV2,RANK:10 )
    在线值:
    发帖
    回帖
    粉丝
    15
    我来分享收获的喜悦。
    2010-4-22 11:29
    0
    雪    币: 219
    活跃值: (10)
    能力值: ( LV2,RANK:10 )
    在线值:
    发帖
    回帖
    粉丝
    16
    好帖 顶,留个脚印
    2010-12-6 19:48
    0
    雪    币: 220
    活跃值: (55)
    能力值: ( LV2,RANK:10 )
    在线值:
    发帖
    回帖
    粉丝
    17
    做个记号,好贴,以后用得着!
    2011-12-27 15:53
    0
    雪    币: 57
    活跃值: (10)
    能力值: ( LV2,RANK:10 )
    在线值:
    发帖
    回帖
    粉丝
    18
    mark....
    2011-12-27 17:21
    0
    雪    币: 2
    活跃值: (10)
    能力值: ( LV2,RANK:10 )
    在线值:
    发帖
    回帖
    粉丝
    19
    学习 了
    2013-8-20 23:35
    0
    游客
    登录 | 注册 方可回帖
    返回
    //