首页
社区
课程
招聘
[原创]RING3过主防读物理内存、读写IO端口
发表于: 2012-3-4 16:58 21215

[原创]RING3过主防读物理内存、读写IO端口

2012-3-4 16:58
21215

最近拜读了王爽老师的《汇编语言》,学到了不少东西,终于能勉强逆点简单的小程序了。于是想到了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;
}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 6
支持
分享
最新回复 (19)
雪    币: 120
活跃值: (160)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
360会检测程序的调用方的。。。不是鲁大师自己加载驱动,应该也会报吧。
2012-3-4 18:56
0
雪    币: 142
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
好骚的代码.....
2012-3-4 18:57
0
雪    币: 227
活跃值: (66)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
4
会报。不过让鲁大师自己加载的话可以绕过。
目测可以读注册表找到鲁大师路径然后手动CreateProcess,没试过,仅学习研究>.<
2012-3-4 19:34
0
雪    币: 2323
活跃值: (4118)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
5
现在好像很多都是利用正常的东西,来做不正常的事~~
2012-3-4 20:00
0
雪    币: 88
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6

好猥琐的思路。。
2012-3-10 11:56
0
雪    币: 284
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
竟然用ring3,结果调用驱动?太强大了.
只能膜拜,无法学习。
2012-3-10 12:40
0
雪    币: 276
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
代码的确很骚。支持。
2012-3-10 17:47
0
雪    币: 1149
活跃值: (908)
能力值: ( LV13,RANK:260 )
在线值:
发帖
回帖
粉丝
9
F5的话,SystemBuffer显示成一个什么.Type,完全驴唇不对马嘴,可怕- -||

把对应的irp结构提取出来,做成.h 文件,然后加载 ,一切都是c 格式了....没必要去计 偏移.....
2012-3-10 18:19
0
雪    币: 544
活跃值: (264)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
10
驱动不验证调用者就是个悲剧,如何去验证调用者又是一个悲剧
2012-3-11 00:11
0
雪    币: 249
活跃值: (71)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
11
BOOLEAN write_physical_address_by_ulong(PHYSICAL_ADDRESS PhyAddr)
{
    PUCHAR Register = MmMapIoSpace(PhyAddr.LowPart, 0, 4, 0);
    if (Register == NULL) {
        return FALSE;
    }
    WRITE_REGISTER_ULONG(Register, &PhyAddr.HighPart, 4);
    MmUnmapIoSpace(Register, 4);
    return TRUE;
}

BOOLEAN write_physical_address_by_uchar(PHYSICAL_ADDRESS PhyAddr)
{
    PUCHAR Register = MmMapIoSpace(PhyAddr.LowPart, 0, 1, 0);
    if (Register == NULL) {
        return FALSE;
    }
    WRITE_REGISTER_UCHAR(Register, &PhyAddr.HighPart);
    MmUnmapIoSpace(Register, 1);
    return TRUE;
}
2012-3-11 10:07
0
雪    币: 249
活跃值: (71)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
12


好复杂的流程图,楼主究竟如何快速分析的
上传的附件:
2012-3-11 11:03
0
雪    币: 1233
活跃值: (907)
能力值: ( LV12,RANK:750 )
在线值:
发帖
回帖
粉丝
13
不错不错,鼓励一下,虽然看不懂 哈哈
2012-3-11 11:53
0
雪    币: 90
活跃值: (91)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
潜力贴留名.Opera插图补丁.颜色补丁.字数补丁..
2012-3-11 17:50
0
雪    币: 227
活跃值: (66)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
15
[QUOTE=cxthl;1052174]

好复杂的流程图,楼主究竟如何快速分析的[/QUOTE]

这种switch用反汇编代码视图看会好很多~另外我也不太喜欢用流程图视图
2012-3-11 17:56
0
雪    币: 34
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
16
蛋碎啊~ 123456
2012-3-12 01:27
0
雪    币: 102
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
64 位系统下可以么?

之前也是写了个类似WinIO的,后来签了个名。不然64位下用不了啊  哎
2012-3-29 00:10
0
雪    币: 1774
活跃值: (1045)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
弱弱地问句,如何进行合法签名?
2012-3-31 02:56
0
雪    币: 50
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
楼主能 不能搞定顺网的那个驱动防火墙呀,那家伙就需要在R3层搞!
2012-4-3 17:59
0
雪    币: 163
活跃值: (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
我说你们这么那么有时间呢!不得不服啊。。什么人都有,
2012-4-3 20:55
0
游客
登录 | 注册 方可回帖
返回
//