首页
论坛
课程
招聘
[原创]另一种读写进程内存空间的方法
2008-5-16 17:16 59671

[原创]另一种读写进程内存空间的方法

2008-5-16 17:16
59671
cc682
http://netroc682.spaces.live.com/
    丢一个比较难防的读写其他进程内存空间的方法出来,嘿嘿。貌似我还没想到什么好办法可以防住的。
    内存空间不能跨进程访问的原因主要在于不同进程都有自己的页目录和页表。进程切换的很大一块也就是切换掉页目录。
    Windows自己的ReadProcessMemory最终也是通过KeStackAttachProcess附加到目标进程空间执行拷贝的。但是中间的N个内核函数调用现在被很多保护系统Hook掉并保护起来了,所以要通过这层层关卡读到东西还是不那么简单的。Unhook?自己实现内核函数?都很麻烦。
    其实,仅仅是需要拿到目标进程的页目录,然后直接从目标地址拷贝出来而已,完全可以用简单得多的办法来达到这个目的。
    所有的XXAttachProcess函数最终都通过_KiSwapProcess切换进程环境,_KiSwapProcess中会将目标进程的页目录指针放入CR3。这个过程我们可以自己来实现,唯一需要的就是拿到目标进程的EPROCESS而已,而这有无数种方法可以达到。整个过程基本上没有能当作非正常访问的证据以阻止掉的。
    首先来看一下几个内核结构:
    每个进程都有一个内核里面的进程结构_EPROCESS,前面几个字段如下:
typedef struct _EPROCESS {
    KPROCESS Pcb;
    EX_PUSH_LOCK ProcessLock;
……

Pcb中就包含我们需要的页目录地址:
typedef struct _KPROCESS {
    DISPATCHER_HEADER Header;
    LIST_ENTRY ProfileListHead;
    ULONG_PTR DirectoryTableBase[2];
……

    系统一般只使用DirectoryTableBase[0],DirectoryTableBase[1]是用于hyperspace的。我们只需要拿到目标进程里面的DirectoryTableBase[0]值并直接设置到CR3中就可以读取了。
    假设要读取PID为1000的进程从0x400000开始的100个字节,只需要按下面的步骤实现:
1、        获取PID=1000的进程的_EPROCESS,读取_EPROCESS::Pcb::DirectoryTableBase[0]
2、        将页目录的值mov到cr3中。
3、        直接将0x400000的地址memcpy到内核空间地址中
4、        恢复cr3的值。
    下面是我测试使用的代码片断,图方便使用了PsLookupProcessByProcessId来获取EPROCESS,实际上这个函数多半被处理过的,所以很可能拿不到。解决的方法之一是可以通过PsSetCreateProcessNotifyRoutine挂一个回调,在里面通过PsLookupProcessByProcessId获取每个进程的EPROCESS地址并缓存起来后面使用。
这是DispatchIoCtrl里面的
switch(irpStack->Parameters.DeviceIoControl.IoControlCode)
	{
	case IOCTL_READMEM:
		pstReadInfo = Irp->AssociatedIrp.SystemBuffer;
		ntStatus = STATUS_SUCCESS;
		if ( pstReadInfo->ulLen > 1000 || 
			irpStack->Parameters.DeviceIoControl.InputBufferLength < pstReadInfo->ulLen ||
			pstReadInfo->ulStart >= (PVOID)0x80000000 ||
			(ULONG)pstReadInfo->ulStart + pstReadInfo->ulLen >= 0x80000000)
		{
			DbgPrint( "Read range invalid\r\n");
			ntStatus = STATUS_UNSUCCESSFUL;
			break;
		}
		__try
		{									
			if (PsLookupProcessByProcessId((HANDLE)(pstReadInfo->ulPid),&pstEProcess) == STATUS_SUCCESS)
			{
				pbyBuff = (PUCHAR)ExAllocatePoolWithTag( NonPagedPool, pstReadInfo->ulLen, 'PMRD');
				ASSERT( pbyBuff);
			}
			else
			{
				DbgPrint( "PsLookupProcessByProcessId fail\r\n");
				ntStatus = STATUS_UNSUCCESSFUL;
				break;
			}
			ntStatus = ReadProcessMemory( pstEProcess, pbyBuff, pstReadInfo->ulStart, pstReadInfo->ulLen);
			if ( ntStatus == STATUS_SUCCESS)
			{
				RtlCopyMemory( pstReadInfo, pbyBuff, pstReadInfo->ulLen);
			}
			else
			{
				ntStatus = STATUS_UNSUCCESSFUL;
				break;
			}
			ExFreePool( pbyBuff);
			pbyBuff = NULL;
		}
		__except(1)
		{
			ntStatus=STATUS_UNSUCCESSFUL;
		}
		break;
……

这是读取内存的:
NTSTATUS ReadProcessMemory( PEPROCESS pstEProcess, PUCHAR pucBuff, PVOID pStart, ULONG ulLen)
{
	PKPROCESS pstKProcess = NULL;
	PEPROCESS pstCurrent = NULL;
	ULONG ulPDT = 0; 
	ULONG ulOldCr3 = 0;

	pstKProcess = &pstEProcess->Pcb;
	ulPDT = pstKProcess->DirectoryTableBase[0];

	//load cr3
	_asm
	{
		cli;
		mov eax, cr3;
		mov ulOldCr3, eax;
		mov eax, ulPDT;
		mov cr3,eax
	}
	_asm sti;
	RtlCopyMemory( pucBuff, pStart, ulLen); //直接复制内存
	_asm cli;
	_asm
	{
		mov eax, ulOldCr3;
		mov cr3,eax;
		sti;
	}
	return STATUS_SUCCESS;
}

    这个代码有些细节并没有处理,只是尝试了一下新的访问进程内存的方式。除了拿EPROCESS之外,中间没有使用任何系统函数,所以常规办法基本上是没有办法挡住的。进程保护技术看来实现起来难度还是很大啊。还是那句话,一点突破,满盘皆输。

看雪招聘平台创建简历并且简历完整度达到90%及以上可获得500看雪币~

收藏
点赞0
打赏
分享
最新回复 (66)
雪    币: 200
活跃值: 活跃值 (13)
能力值: (RANK:650 )
在线值:
发帖
回帖
粉丝
shoooo 活跃值 16 2008-5-16 17:22
2
0
这不是肯德基
雪    币: 219
活跃值: 活跃值 (59)
能力值: ( LV13,RANK:530 )
在线值:
发帖
回帖
粉丝
foxabu 活跃值 13 2008-5-16 17:54
3
0
不会说肯德基 ,只有顶。
雪    币: 218
活跃值: 活跃值 (11)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
rick 活跃值 7 2008-5-16 19:10
4
0
强,顶。。。。
雪    币: 19
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
fancily 活跃值 2008-5-16 19:31
5
0
强....烈学习...
雪    币: 235
活跃值: 活跃值 (14)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
whtyy 活跃值 1 2008-5-16 21:52
6
0
汗.....
雪    币: 1835
活跃值: 活跃值 (132)
能力值: (RANK:330 )
在线值:
发帖
回帖
粉丝
Bughoho 活跃值 8 2008-5-16 21:55
7
0
这不是肯德基~~这不是肯德基~~
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
linyboy 活跃值 2008-5-17 06:32
8
0
这种方法很好
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
北方滴狼 活跃值 2008-5-17 07:35
9
0
这是麦当劳
雪    币: 195
活跃值: 活跃值 (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
aki 活跃值 2 2008-5-17 08:23
10
0
这也不是麦当劳
雪    币: 308
活跃值: 活跃值 (76)
能力值: ( LV12,RANK:470 )
在线值:
发帖
回帖
粉丝
zhuwg 活跃值 11 2008-5-17 08:28
11
0
那这是啥呢
雪    币: 5536
活跃值: 活跃值 (56)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
forgot 活跃值 26 2008-5-17 13:04
12
0
hook int 14 模仿 armadillo 的 copymemII,直接改cr3就找不到了
雪    币: 14
活跃值: 活跃值 (60)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
NetRoc 活跃值 12 2008-5-17 16:56
13
0
内核里面,没有谁更利害,只有谁更变态。这种较量最后吃亏的总是正常软件。
挂Trap0E是很危险滴,搞你的办法也是多多滴,嘿嘿
雪    币: 5536
活跃值: 活跃值 (56)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
forgot 活跃值 26 2008-5-17 19:09
14
0
你搞不了我,我不懂内核,内核都是大牛玩的,我也不会写驱动,不给你机会搞我。哦也。
雪    币: 1835
活跃值: 活跃值 (132)
能力值: (RANK:330 )
在线值:
发帖
回帖
粉丝
Bughoho 活跃值 8 2008-5-17 19:33
15
0
我也来加一个哦也
雪    币: 666
活跃值: 活跃值 (65)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
elance 活跃值 6 2008-5-17 21:27
16
0
很强悍,学习。
雪    币: 326
活跃值: 活跃值 (15)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
快雪时晴 活跃值 4 2008-5-17 22:25
17
0
我是外星人,哦耶
雪    币: 204
活跃值: 活跃值 (68)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
菜菜小J 活跃值 2008-5-17 23:49
18
0
妈妈说咱啃不起!

感谢楼主!
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
XiaoYo 活跃值 2008-5-19 08:38
19
0
好东西 收下~
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
wsyzyddd 活跃值 1 2008-5-19 10:08
20
0
我加2个"哦也"
雪    币: 2071
活跃值: 活跃值 (14)
能力值: (RANK:170 )
在线值:
发帖
回帖
粉丝
Aker 活跃值 4 2008-5-19 11:39
21
0
说了就做,学习一个
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wttxjp 活跃值 2008-5-19 17:06
22
0
这样写得控制好中断
雪    币: 185
活跃值: 活跃值 (17)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
driverox 活跃值 2 2008-5-19 19:44
23
0
俺也来一个:哦也  ---  收藏了!
雪    币: 190
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
gdlian 活跃值 2008-5-19 20:02
24
0
很容易蓝屏的吧
雪    币: 150
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cpuArt 活跃值 2008-5-20 01:55
25
0
膜拜中 。。。
游客
登录 | 注册 方可回帖
返回