首页
社区
课程
招聘
[求助]自己加载ntdll并做重定位时碰到的问题
发表于: 2011-1-15 03:29 11996

[求助]自己加载ntdll并做重定位时碰到的问题

2011-1-15 03:29
11996
在学习PE格式,写了程序在内存中加载一个ntdll.dll的复本并人工对它做重定位,但发现有些地方与系统加载的ntdll有些差异,如:
_NlsMbCodePageTag:
7C99B0A0 01 00            add         dword ptr [eax],eax
7C99B0A2 00 00            add         byte ptr [eax],al
7C99B0A4 00 00            add         byte ptr [eax],al
7C99B0A6 00 00            add         byte ptr [eax],al

但自己加载的ntdll同样偏移位置上的数据却全部是0。对比了磁盘中的ntdll.dll数据发现这些地方数值上的确都是0。
这些差异不是因为重定位造成的,那它们从哪来?操作系统加载ntdll时对它填充的吗?

其它信息:
XP SP3操作系统
_NlsMbCodePageTag 在ntdll.dll的“.data”节,在本节的偏移量是160字节(可用PE工具直接提取这节的信息查看)。
ntdll.dll没有导入表,只根据“.reloc”节的信息做了重定位,重定位的代码如下(pBaseAddress是自己加载的ntdll基址,已做过对齐):
IMAGE_DOS_HEADER *pIDH = (IMAGE_DOS_HEADER *)pBaseAddress;
IMAGE_NT_HEADERS *pINH = (IMAGE_NT_HEADERS *)(pIDH->e_lfanew + (char *)pBaseAddress);
if (pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size <= 0) return;
if (pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress <= 0) return;

long delta = (long)pBaseAddress - pINH->OptionalHeader.ImageBase;

PIMAGE_BASE_RELOCATION pIBR = (PIMAGE_BASE_RELOCATION)(pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress + (DWORD)pBaseAddress);
while (pIBR->VirtualAddress && pIBR->SizeOfBlock)
{
	WORD *pLocData = (WORD *)((int)pIBR + sizeof(IMAGE_BASE_RELOCATION));
	int NumberOfReloc = (pIBR->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION))/sizeof(WORD);
	for (int i = 0; i < NumberOfReloc; ++i) if ((pLocData[i]&0xF000) == 0x3000)
	{
		long *p = (long *)((DWORD)pBaseAddress + pIBR->VirtualAddress + (pLocData[i]&0x0FFF));
		*p += delta;
	}
	pIBR = PIMAGE_BASE_RELOCATION(((DWORD)pIBR) + pIBR->SizeOfBlock);
}

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (5)
雪    币: 242
活跃值: (14)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
1、.data是数据段
2、ntdll是进程创建后的第一个模块,里面是有些trick的。
2011-1-26 02:02
0
雪    币: 55
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
楼上的能介绍一下有哪些trick吗?给资料我自己看也行~
2011-2-15 14:26
0
雪    币: 249
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
给资料我自己看也行~
2011-2-16 16:00
0
雪    币: 233
活跃值: (26)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
.版本 2

.子程序 DoRelocation, , , 完成重定位表地址的修正
.参数 NewBase, 整数型
.局部变量 pLoc, IMAGE_BASE_RELOCATION
.局部变量 Delta, 整数型
.局部变量 pLocData, 短整数型, , "0"
.局部变量 NumberOfReloc, 整数型
.局部变量 i, 整数型
.局部变量 j, 整数型
.局部变量 pAddress, 整数型

Delta = NewBase - pNTHeader.OptionalHeader.ImageBase  ' 新装载地址-原始装载地址=差值

i = NewBase + pNTHeader.OptionalHeader.DataDirectory [6].VirtualAddress  ' VirtualAddress=重定位内存页起始RVA地址
RtlMoveMemory_IMAGE_BASE_RELOCATION_1 (pLoc, i, 8)  ' 对应IMAGE_BASE_RELOCATION结构

.判断循环首 (pLoc.VirtualAddress ≠ 0)
    重定义数组 (pLocData, 假, (pLoc.SizeOfBlock - 8) ÷ 2)  ' (pLoc.SizeOfBlock - 8) ÷ 2=重定位地址个数
    RtlMoveMemory_数组_短整_1 (pLocData, i + 8, pLoc.SizeOfBlock - 8)  ' 直接把数据拷贝到数组中..
    NumberOfReloc = (pLoc.SizeOfBlock - 8) ÷ 2  ' 重定位地址个数
    .计次循环首 (NumberOfReloc, j)
        .如果真 (位与 (pLocData [j], 61440) = 12288)  ' 取高4位,判断重定位项属性
            pAddress = NewBase + pLoc.VirtualAddress + 位与 (pLocData [j], 4095)  ' 4095=111111111111(2进制) 取低12位,重定位内存页起始RVA地址+pLocData=需要修改地址的偏移,然后在加上装载地址
            RtlMoveMemory_整数_2 (pAddress, 取字节集数据 (指针到字节集 (pAddress, 4), #整数型, ) + Delta, 4)  ' 把需要修改的地址的值取出来,加上差值,就完成了重定位的修改
        .如果真结束

    .计次循环尾 ()
    i = i + pLoc.SizeOfBlock
    RtlMoveMemory_IMAGE_BASE_RELOCATION_1 (pLoc, i, 8)  ' 下一个重定位内存页起始RVA地址
.判断循环尾 ()
2011-2-16 20:14
0
雪    币: 233
活跃值: (26)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
表BS我发易代码。。。
2011-2-16 20:15
0
游客
登录 | 注册 方可回帖
返回
//