首页
社区
课程
招聘
[原创]ring0注入ring3的一种新方法
发表于: 2009-12-29 17:26 33361

[原创]ring0注入ring3的一种新方法

2009-12-29 17:26
33361
插APC越来越不好使了,想到了一种新的方法,实践了一下,发出来与大家分享。

其实要注入ring3的进程,本质上只是想要借用该进程中的某一个线程来执行一段其它代码而已,再透彻一点讲只是要借用一下某个线程的eip来暂时指向我们想让它执行的代码。当然,用完过后要想办法让eip能回到原位,这样就不会对该ring3线程本身的工作产生干扰。

具体来讲可以这样做:

1、先在要注入的进程中找到一个没有退出的,并且没有被挂起的用户线程。(其实如果找被挂起的还省事一点,就是等的时间长了点,要等它resume过后,注入的代码才会被执行。这里以挂起的为例)

2、挂起该线程。这是为了防止它被调度,因为我们要修改它的EIP。但是KeSuspendThread是没有导出的,需要自己实现。(附件的示例代码中是通过查找特征码来做的)

3、我们先来看一看准备注入到Ring3的代码。在本示例中,我准备注入的代码如下:
////////////////////////////////////////////////
//
//  被注入到ring3进程的代码
//
////////////////////////////////////////////////
_declspec (naked) void ShellCode() {
	_asm {
		push eax
		// 弹个MessageBox为例
		push 0
		push 0
		push 0
		push 0
		mov eax, 0x77D66484		// MessageBoxW 的地址,XP SP2
		call eax
		pop eax
		// jmp ds:12345678H, 绝对地址跳转
		_emit 0xEA
		_emit 0x78
		_emit 0x56
		_emit 0x34
		_emit 0x12
		_emit 0x1B
		_emit 0x00
	}
}

ShellCode以MessageBoxW(0,0,0,0)为例,代码最后需要有个jmp ds:0x12345678的绝对跳转,这是为了跳回EIP原来的地方。
所以现在要做的就是把0x12345678改成KTHREAD->KTRAP_FRAME->EIP中的值,再把ShellCode拷贝到该Ring3线程能够抚摸到的位置,最后把KTHREAD->KTRAP_FRAME->EIP改成ShellCode被拷贝到的地址。
那么将ShellCode拷贝到什么地方呢?我一开始为了方便,将ShellCode拷贝到了KUSER_SHARED_DATA的后面,这样可以避免申请空间,以及KeStackAttachProcess等麻烦。KUSER_SHARED_DATA所在的地址被同时映射到了内核空间(0xffdf0000)和用户空间(0x7ffe0000)中,大小为4K,但是其实KUSER_SHARED_DATA连1K都没占到,所以可以把ShellCode拷到KUSER_SHARED_DATA的后面,非常理想^_^。
代码片断如下:
// 将ShellCode中的0x12345678改成eip,为了ShellCode执行完后自动跳回
for( i = (ULONG)ShellCode; i <= (ULONG)ShellCode + 0x20; ++i ) {
	if( MmIsAddressValid((PVOID)i) && MmIsAddressValid((PVOID)(i+3)) ){
		if ( *(PULONG)i == 0x12345678 ) {
			DbgPrint("find modify point\n");
			*(PULONG)i = pTrapFrame->Eip;
			break;
		}
	}
}

// 拷贝ShellCode到“飞地”(使用内核地址)
RtlCopyMemory( (PVOID)0xffdf0800, ShellCode, 0x20 );

// pTrapFrame->EIP指向“飞地”(使用用户态地址)
pTrapFrame->Eip = 0x7ffe0800;

后来发现在非调试模式下,执行KUSER_SHARED_DATA处的代码会导致DEP暴走,遂老老实实地自己分配空间了。
代码片断如下:
// 将ShellCode中的0x12345678改成eip,为了ShellCode执行完后自动跳回
for( i = (ULONG)ShellCode; i <= (ULONG)ShellCode + 0x20; ++i ) {
	if( MmIsAddressValid((PVOID)i) && MmIsAddressValid((PVOID)(i+3)) ){
		if ( *(PULONG)i == 0x12345678 ) {
			DbgPrint("find modify point\n");
			*(PULONG)i = pTrapFrame->Eip;
			break;
		}
	}
}

// 下面的代码是分配空间来放置ShellCode
// 调用一些相应函数来实现更好,我比较懒,就硬编码了
InitializeObjectAttributes(&oa,0,0,0,0);
pCid = (CLIENT_ID*)((ULONG)pThread + 0x1ec);		// Cid 	XP SP2
ntstatus = ZwOpenProcess( 
	&hProcess, 
	PROCESS_ALL_ACCESS, 
	&oa, 
	pCid 
	);
if ( NT_SUCCESS(ntstatus) ) {
	PVOID pBuff = NULL;
	SIZE_T size = 0x20;
	ntstatus = NtAllocateVirtualMemory(
		hProcess, 
		&pBuff, 
		0, 
		&size, 
		MEM_RESERVE | MEM_COMMIT,
		PAGE_EXECUTE_READWRITE
		);
	if( NT_SUCCESS(ntstatus) ) {
		KAPC_STATE kapc;
		// 拷贝ShellCode到目标进程中去
		KeStackAttachProcess(pProcess,&kapc);
		RtlCopyMemory(pBuff,ShellCode,size);
		KeUnstackDetachProcess (&kapc);
		// pTrapFrame->Eip指向ShellCode
		pTrapFrame->Eip = (ULONG)pBuff;
	}
	ZwClose(hProcess);
}

4、KeRusumeThread,恢复该线程的执行,于是该线程会先去执行ShellCode。

以下是注入扫雷的截图:


完整示例代码见附件(测试平台XP SP2)。

[课程]Android-CTF解题方法汇总!

上传的附件:
收藏
免费 8
支持
分享
最新回复 (32)
雪    币: 1025
活跃值: (225)
能力值: ( LV12,RANK:310 )
在线值:
发帖
回帖
粉丝
2
顶一个
2009-12-29 17:30
0
雪    币: 1361
活跃值: (1052)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
占位  坐板凳 学习了
2009-12-29 17:32
0
雪    币: 635
活跃值: (101)
能力值: ( LV12,RANK:420 )
在线值:
发帖
回帖
粉丝
4
都RING0了,还注个什么劲。
2009-12-29 17:36
0
雪    币: 636
活跃值: (174)
能力值: ( LV9,RANK:260 )
在线值:
发帖
回帖
粉丝
5
我想在ring0中调用ring3的函数……
2009-12-29 17:41
0
雪    币: 581
活跃值: (149)
能力值: ( LV12,RANK:600 )
在线值:
发帖
回帖
粉丝
6
代码很暴力。。。
2009-12-29 17:55
0
雪    币: 221
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
去年写过,你这个代码,微点会报毒. attach过去别分配内存,直接写PE即可.
上传的附件:
  • 1.jpg (45.50kb,1895次下载)
2009-12-29 17:56
0
雪    币: 564
活跃值: (42)
能力值: ( LV12,RANK:230 )
在线值:
发帖
回帖
粉丝
8
不错,,下载看看学习。。。
2009-12-29 18:10
0
雪    币: 1407
活跃值: (17)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
暑假里在某博客看到过类似方法
2009-12-29 18:24
0
雪    币: 635
活跃值: (101)
能力值: ( LV12,RANK:420 )
在线值:
发帖
回帖
粉丝
10
都进RING0了,还执行个什么劲RING3代码
2009-12-29 18:51
0
雪    币: 206
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
不错,好东西。学习学习
2009-12-29 21:13
0
雪    币: 225
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
2009-12-29 21:25
0
雪    币: 227
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
2009-12-29 21:30
0
雪    币: 636
活跃值: (174)
能力值: ( LV9,RANK:260 )
在线值:
发帖
回帖
粉丝
14
这个方法和SetThreadContext法差不多
2009-12-30 08:55
0
雪    币: 635
活跃值: (101)
能力值: ( LV12,RANK:420 )
在线值:
发帖
回帖
粉丝
15
进不去RING0,千方百计要进RING0,进了RING0,又想跑出来执行RING3,一个字,*
2009-12-30 10:09
0
雪    币: 636
活跃值: (174)
能力值: ( LV9,RANK:260 )
在线值:
发帖
回帖
粉丝
16
……

Ring3进Ring0,Ring0 Call Ring3,两者各有用处嘛,又没什么冲突……
2009-12-30 10:27
0
雪    币: 796
活跃值: (370)
能力值: ( LV9,RANK:380 )
在线值:
发帖
回帖
粉丝
17
[QUOTE=菊冬;735480]去年写过,你这个代码,微点会报毒. attach过去别分配内存,直接写PE即可.
[/QUOTE]

一看注释说明,肯定是sudami的  
2009-12-30 11:17
0
雪    币: 4583
活跃值: (3567)
能力值: ( LV12,RANK:230 )
在线值:
发帖
回帖
粉丝
18
你可以关掉KUSER_SHARED_DATA所在PTE的NX位啊,然后就不存在你说的这个问题了。

顺便就你的原始需求,可以看看MS09-050的remote kernel shellcode,那是一个精彩的演示。
2009-12-30 13:20
0
雪    币: 636
活跃值: (174)
能力值: ( LV9,RANK:260 )
在线值:
发帖
回帖
粉丝
19
谢谢指点!学习了!
2009-12-30 13:45
0
雪    币: 33
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
您回了 3 贴 , 终于把这个贱字加进来, 看来实在是憋不住了?

RING0 执行 ring3 不是有很多人都发出来过 ,

技术分析而已,为什么一定说贱呢?

不知道这个算不算 "语言挑衅"?
2009-12-30 13:56
0
雪    币: 445
活跃值: (52)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
21
太好了,~好事!
2009-12-30 14:09
0
雪    币: 445
活跃值: (52)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
22
唉~没办法呀~牛人嘛!
2009-12-30 14:11
0
雪    币: 45
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
剑圣 剑魔 剑魂
2009-12-30 15:10
0
雪    币: 284
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
狂战士来了。膜拜fypher大牛
2010-2-5 17:49
0
雪    币: 152
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
为了显示一个GUI。。。。。。。
2010-2-7 22:46
0
游客
登录 | 注册 方可回帖
返回
//