首页
社区
课程
招聘
[原创]内存镜像拷贝_已贴代码
2019-4-9 14:41 6130

[原创]内存镜像拷贝_已贴代码

2019-4-9 14:41
6130
extern "C" __declspec(dllexport) void* __stdcall  GetShadowModuleMem(char * ModuleName)

{
	MODULEINFO tModuleinfo ;
	MEMORY_BASIC_INFORMATION memInfo;
	PVOID nSectionBase = NULL;
	INT nSectionSize = NULL;
	INT nQueryMem = NULL;
	char* tMouduleBase = NULL;

	HMODULE hMouduleBase = GetModuleHandle(ModuleName); //获取模块句柄_基地址
	BOOL tIf = GetModuleInformation(GetCurrentProcess(), hMouduleBase, &tModuleinfo, sizeof(tModuleinfo));
	INT nMouduleSize = tModuleinfo.SizeOfImage;
	PVOID pMouduleEndSize = (char*)hMouduleBase + nMouduleSize;
	if (tIf)
	{
		PVOID pShadowMoudule = VirtualAlloc(NULL, nMouduleSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);//申请同等大小的内存 
		if (pShadowMoudule == NULL)
		{
			return 0;
		}
		nSectionBase = hMouduleBase;

		tMouduleBase = (char*)pShadowMoudule;

		do 
		{
			nQueryMem = VirtualQuery(nSectionBase, &memInfo, sizeof(memInfo));
			if (nQueryMem==0)
			{
				break;
			}
			if (memInfo.Type == MEM_IMAGE)
			{
				
				nSectionBase = memInfo.BaseAddress;
				nSectionSize = memInfo.RegionSize;
				nSectionBase = (char*)nSectionBase + nSectionSize;
				if (nSectionBase >= pMouduleEndSize)
				{
					break;
				}
				else

				{
					DWORD dOldProtect = NULL;
					if (IsBadReadPtr(memInfo.BaseAddress, memInfo.RegionSize) != 0)
					{
						if(VirtualProtect(memInfo.BaseAddress, memInfo.RegionSize, PAGE_EXECUTE_READWRITE, &dOldProtect))
						{
							memcpy(tMouduleBase, memInfo.BaseAddress, memInfo.RegionSize); //拷贝模块到申请的内存中
							tMouduleBase = (char*)tMouduleBase + memInfo.RegionSize;
							VirtualProtect(memInfo.BaseAddress, memInfo.RegionSize, dOldProtect, &dOldProtect);
						}
						else 
						{
							tMouduleBase = (char*)tMouduleBase + memInfo.RegionSize;
						}
					}
					else 
					{
						memcpy(tMouduleBase, memInfo.BaseAddress, memInfo.RegionSize); //拷贝模块到申请的内存中
						tMouduleBase = (char*)tMouduleBase + memInfo.RegionSize;
					}
				}
			}
		} while (nQueryMem != 0);

		return pShadowMoudule;
	}
	return 0;

/*
	INT nMouduleSize = _getModuleBaseAddr(hMouduleBase);//从PEB中获取模块所占内存空间大小
	if (nMouduleSize=0)
	{
		return 0;
	}

*/

}
写了一个动态内存中拷贝模块镜像 然后 计算CRC的动态校验.现在有个问题.个别dll  如ntdll  属性啥都对..拉进去就崩溃..修改属性也是没问题的.但是就是拷贝崩溃..有没有大佬知道什么问题..已经动态调试执行过了  ntdll 代码段属性为0  修改属性OK 但是执行还是崩溃..
又调试了下 大概知道问题了..但是还是很好奇.为啥会这么分配..


内存查询属性页又是另一个状态...有没有大佬解释下..

这里是内存页状态.. 理论上来说  内存不都应该是一个块连续一个块么..如果不是.那么 类似这种的我要怎么写..因为是计算crc 内存块大小和节段之间距离需要一致..

------------------------------------------------------------------------------
结贴.不影响模块拷贝.虚块内存也是在里边的.内存模块大小没有错误..感谢楼下老哥 指出错误..一直用VirtualProtect 从未判断过返回..- - 感谢指点..这么写没有问题..   读出来的模块大小是对了..一直纠结错地方了..   不用管怎么分配 舍弃不能读的内存就好了..

------------------------------------------------------------------------------------------------------------------------------------------
那么顺便写下关于 VMP 3.2 sdk中的 VMProtectIsValidImageCRC 如何处理.
以我自己加壳的程序为例.随意对校验代码段数据进行 硬件访问断点.找到类似以下伪代码 的地方.

mov reg32,dword ptr ds:[reg32]
mov reg32,dword ptr ds:[reg32+0x4]
add reg32,0x4
test reg32,reg32
je xxxxaddr

@calc_CRC:
 movzx reg32,byte ptr ds:[reg32]
 xor reg32,reg32
 and reg32,0xFF
 mov reg32,dword ptr ds:[reg32*4+0xxxxxxx]
 shr reg32,0x8
 xor reg32,reg32
 xor reg32,0xxxxxxxxxxx
 dec reg32
jnz calc_CRC

部分代码可能不一样 以实例为准.
已知 :
mov reg32,dword ptr ds:[reg32]    //预计算crc地址
mov reg32,dword ptr ds:[reg32+0x4] //预计算crc大小

以我hook例子为例
mov eax,[edi]
mov edx,[edi+4]
sub eax,ModuleBaseAddr
add eax,ShadowModuleBaseAddr
jmp xxxx
四行汇编即可搞定.
关于 内存随机校验 主要用到函数为 
RDTSC
处理此处即可  至于 VMP3.x 未研究  大体方向应该是一致的.不排除改变框架.


拷贝原始内存 此处hook即可.让其计算原始代码. 另一简便方法是如果代码VM处理的不是很有逻辑的话.这里 观察 轮转寄存器 找到原始esp 可以回溯到  VMProtectIsValidImageCRC 的返回地址 直接修改返回值即可. 如果不嫌麻烦 到 jnz calc_CRC的下一行 然后对计算保存值进行关注  轮转就对保存位置下访问 避免跟踪无效数据.找到 vmp中计算 vm_add的地址修改也可以.不过 这种方法对vmp 3.x 不是很有效.需要修改很多地方..当然  找到vm_add地址之后 纯手动跟踪 找到crc表也可以.然后对表下访问 看解码算法 直接改表返回去 也米问题.  懒人 推荐直接改这个 calc)crc. 如果研究方向 还是推荐 改表.

PS: 这个代码主要用来 保护代码的..同理 也可以 针对要保护内存这样计算动态crc.虽然强度低点.也不失为一个思路.虽然一个特征码搞定 但是  可以逆向思维.不对原始段做crc而是拷贝之后 对镜像段做crc.  感谢各位老哥指点..专业写BUG..专业debuff.

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

最后于 2019-4-10 05:11 被bambooqj编辑 ,原因:
收藏
免费 1
打赏
分享
最新回复 (8)
雪    币: 1787
活跃值: (340)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
yezhulove 2019-4-9 14:49
2
0
VirtualProtect(memInfo.BaseAddress, memInfo.RegionSize, PAGE_EXECUTE_READWRITE, &dOldProtect)== S_OK  

返回值是BOOL。。。。
雪    币: 781
活跃值: (1091)
能力值: ( LV5,RANK:78 )
在线值:
发帖
回帖
粉丝
bambooqj 2019-4-9 15:36
3
0
yezhulove VirtualProtect(memInfo.BaseAddress, memInfo.RegionSize, PAGE_EXECUTE_READWRITE, &dOldProtect)== ...
这个还真没注意 哈哈哈哈..我改下.这么写好像也没问题吧..
最后于 2019-4-9 15:39 被bambooqj编辑 ,原因:
雪    币: 1787
活跃值: (340)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
yezhulove 2019-4-9 16:33
4
0
bambooqj yezhulove VirtualProtect(memInfo.BaseAddress, memInfo.RegionSize, PAGE_EXECUTE_ ...
S_OK  是0,怎么会没问题
雪    币: 6124
活跃值: (4176)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
黑洛 1 2019-4-9 16:43
5
0
支持我竹子大diao
雪    币: 781
活跃值: (1091)
能力值: ( LV5,RANK:78 )
在线值:
发帖
回帖
粉丝
bambooqj 2019-4-9 18:14
6
0
yezhulove S_OK 是0,怎么会没问题
我的意思是  他成不成功 理论上 应该修改之后就能拷贝的..我现在主要问题是ntdll的代码段 无法拷贝..很奇怪..
雪    币: 1449
活跃值: (642)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
半个大西瓜 2019-4-9 19:22
7
0
因为shadow module,某部分内存页面可能是reverse状态
雪    币: 781
活跃值: (1091)
能力值: ( LV5,RANK:78 )
在线值:
发帖
回帖
粉丝
bambooqj 2019-4-10 05:14
8
0
wx_寻找清鸟 因为shadow module,某部分内存页面可能是reverse状态
感谢大佬..我已经研究明白了..钻牛角了..
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_qgowmxdw 2020-4-29 17:29
9
0
支持我竹子大diao
游客
登录 | 注册 方可回帖
返回