-
-
[原创]RING3过主防读物理内存、读写IO端口
-
发表于:
2012-3-4 16:58
21174
-
最近拜读了王爽老师的《汇编语言》,学到了不少东西,终于能勉强逆点简单的小程序了。于是想到了Extreme神犇很早以前提出的这个点子:调用带正规签名的驱动来干坏事- -
鲁大师有正规数字签名,所以它的驱动加载时不会被主防报警,而鲁大师驱动里也没有验证调用者,所以可以利用~
灵感来自Extreme神犇~以前ASM完全不懂,用IDA只会F5,一看IoDispatchControl就苦逼了,所以一直搞不定(F5的话,SystemBuffer显示成一个什么.Type,完全驴唇不对马嘴,可怕- -||)
于是逆了ComputerZ.sys
一开始我直接拿安装的旧版逆,结果基本接口搞得差不多了之后发现新版的360硬件大师驱动更新了= =旧的没用了。。而内部实现也有变化然后苦逼了,又下了个新的360硬件大师
果然360还是考虑得周到些,加入了SeTokenIsAdmin权限验证,调用Function时对参数的检查也严格了些,不过还是没有验证调用者XD
最后鼓捣鼓捣还是成功了
下面是我逆出的伪码(为啥说是伪码呢?因为我就是边看反汇编边翻译。。只逆了一些关键的接口,没除错,编译不能,所以只能用来看看思路,说是C代码有点对不起观众- -|| 逆得很挫,大牛见笑了。。):
#include <ntddk.h>
BOOLEAN read_port_uchar(USHORT usPort, PULONG buffer)
{
if (!is_port_legal(usPort)) {
return FALSE;
}
_asm {
in buffer,usPort
}
return TRUE;
}
BOOLEAN read_physical_address_by_uchar(PHYSICAL_ADDRESS PhyAddr)
{
PUCHAR Register = MmMapIoSpace(PhyAddr.LowPart, 0, 4, 0);
if (Register == NULL) {
return FALSE;
}
READ_REGISTER_BUFFER_UCHAR(Register, &PhyAddr.HighPart, 4);
MmUnmapIoSpace(Register, 4);
return TRUE;
}
BOOLEAN read_physical_address_by_ulong(PHYSICAL_ADDRESS PhyAddr, ULONG NumberOfBytes)
{
PULONG Register = MmMapIoSpace(PhyAddr.LowPart, 0, NumberOfBytes, 0);
if (Register == NULL) {
return FALSE;
}
READ_REGISTER_BUFFER_ULONG(Register, &PhyAddr.HighPart, NumberOfBytes / 4);
MmUnmapIoSpace(Register, NumberOfBytes);
return TRUE;
}
NTSTATUS __stdcall DispatchIoControl(int DeviceObject, PIRP Irp)
{
NTSTATUS ulReturn = STATUS_SUCCESS;
PIO_STACK_LOCATION IrpSp = Irp->Tail.Overlay.CurrentStackLocation;
if (IrpSp->MajorFunction != IRP_MJ_CREATE && IrpSp->MajorFunction != IRP_MJ_CLOSE) {
if (IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL) {
if (!check_admin_token()) { // 验证administrator权限
ulReturn = 0xC0000022;
goto skip;
}
PVOID pSystemBuffer = pIrp->SystemBuffer;
if (pSystemBuffer == 0) {
ulReturn = 0xC000000D;
goto skip;
}
//esi = pIrp->SystemBuffer;
//edi = IrpSp
ULONG port_data_buffer;
switch (IrpSp->IoControlCode) {
// ......
case 0xF10024C0: {
//rdmsr
break;
}
case 0xF10024C4: {
//wrmsr
break;
}
case 0xF1002500: {
//read_physical_address_uchar
// 如前文所说,这句判断就是新版驱动里360加的
if (IrpSp->InputBufferLength < 12) {
ulReturn = 0xC00000EF;
goto skip;
}
if (IrpSp->OutputBufferLength >= pReadBuffer->Length) {
//ecx = *pReadBuffer->Address;
read_physical_address_uchar((ULONG*)pSystemBuffer, (UCHAR*)four_bytes_buffer);
*(ULONG*)pSystemBuffer = *(ULONG*)four_bytes_buffer;
} else {
ulReturn = 0xC0000206;
goto skip
}
break;
}
case 0xF1002508: {
//loc_109D6 -> read_physical_address
if (IrpSp->InputBufferLength < 12) {
ulReturn = 0xC00000EF;
goto skip;
}
if (IrpSp->OutputBufferLength >= pReadBuffer->Length) {
// 虽然传过去的是PHYSICAL_ADDRESS结构,不过实际上HighPart是作为缓冲区地址的,即pSystemBuffer,没有考虑4GB以上物理内存
PHYSICAL_ADDRESS PhyAddr;
PhyAddr.LowPart = *(ULONG*)pSystemBuffer; // address
PhyAddr.HighPart = (ULONG*)pSystemBuffer; // buffer
read_physical_address(PhyAddr, *(ULONG*)(pSystemBuffer + 4));
} else {
ulReturn = 0xC0000206;
goto skip
}
break;
}
case 0xF1002540: {
//read_io_port_uchar
if (IrpSp->InputBufferLength < 12 || IrpSp->OutputBufferLength < 12 ) {
ulReturn = 0xC00000EF;
goto skip;
}
read_port_uchar(*(USHORT*)SystemBuffer, &port_data_buffer);
*(ULONG*)SystemBuffer = port_data_buffer;
*(ULONG*)(SystemBuffer + 4) = 0;
*(ULONG*)(SystemBuffer + 8) = ulReturn;
break;
}
case 0xF1002544: {
//write_io_port_uchar
if (IrpSp->InputBufferLength < 12 || IrpSp->OutputBufferLength < 12 ) {
ulReturn = 0xC00000EF;
goto skip;
}
port_data_buffer = *(PUCHAR*)(pSystemBuffer + 4);
BOOLEAN bStatus = write_port_uchar(*(USHORT*)SystemBuffer, port_data_buffer);
if (bStatus != TRUE) {
ulReturn = 0xC00000EF;
goto skip;
}
*(ULONG*)SystemBuffer = 0;
*(ULONG*)(SystemBuffer + 4) = 0;
*(ULONG*)(SystemBuffer + 8) = ulReturn;
break;
}
case 0xF1002548: {
//read_io_port_ushort
break;
}
case 0xF100254C: {
//write_io_port_ushort
break;
}
case 0xF1002550: {
//read_io_port_ulong
break;
}
case 0xF1002554: {
//write_io_port_ulong
break;
}
case 0xF1002618: {
//write_physical_address
break;
}
// ......
casedefault: {
ulReturn = 0xC0000010;
if (IrpSp->InputBufferLength >= 12 && IrpSp->OutputBufferLength >= 12) {
write_sub(*(PULONG*)SystemBuffer, *(PULONG*)(SystemBuffer + 4), *(PULONG*)(SystemBuffer + 8));
}
//????????????????????????????????
}
}
}
}
skip:
return ulReturn;
}
int __stdcall DriverEntry_Internal(PDRIVER_OBJECT DriverObject, int)
{
WCHAR SourceString[18] = L"\\Device\\ComputerZ";
UNICODE_STRING SymbolicLinkName;
RtlInitUnicodeString(&SymbolicLinkName, SourceString);
WCHAR DestinationChars[22] = L"DosDevices\ComputerZ";
UNICODE DestinationString;
RtlInitUnicodeString(&DestinationString, DestinationChars);
NTSTATUS Status = IoCreateDevice(DriverObject, 0, &DestinationString, 0xF100, 0, 0);
if (NT_SUCCESS(Status)) {
Status = IoCreateSymbolicLink(&SymbolicLinkName, &DestinationString);
if (NT_SUCCESS(Status)) {
DriverObject->MajorFunction[IRP_MJ_CREATE] = (PVOID)DispatchIoControl;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PVOID)DispatchIoControl;
DriverObject->DriverUnload = (PVOID)DriverUnload;
}
}
return 0;
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)