前段时间在某群里看到 TesDrvPt.sys 这个驱动被病毒利用,之后就被某杀毒产商报毒..
之后就向朋友要了这驱动来看看,就有了此文.

这里我随便贴贴代码,让贴子看起来不太单调.
附件包含 idb、驱动源码、demo 源码.(记得好像有两个 IOCTL 的功能没调试过,其它的应该没问题)

代码:
.text:000114D3                         ;
.text:000114D3                         ;  IoControlCode = 22E05Ch
.text:000114D3                         ;
.text:000114D3                         ;  通过 Ring3 层传入的 Pid,读取该进程指定 Address 数据.
.text:000114D3                         ;
.text:000114D3                         ;  //////////////////////////////////////////////////////////////////////////
.text:000114D3                         ;
.text:000114D3                         ;  此 IoControlCode 处理函数相关数据描述
.text:000114D3                         ;
.text:000114D3                         ;  SysteBuffer 结构如下:
.text:000114D3                         ;    0x00  ULONG ulOperTag;            // 标识操作行为
.text:000114D3                         ;    0x04  ULONG ulReserve;            // 保留
.text:000114D3                         ;    0x08  ULONG ulProcessId;          // Pid
.text:000114D3                         ;    0x0C  PVOID pAddress;             // 读取地址
.text:000114D3                         ;    0x10  ULONG ulBufferLength;       // Buffer 长度
.text:000114D3                         ;    0x14  UCHAR ucBuffer[1];          // Buffer
.text:000114D3                         ;
.text:000114D3 85 DB                                   test    ebx, ebx
.text:000114D5 0F 84 6D 01 00 00                       jz      loc_11648
.text:000114DB 3B D6                                   cmp     edx, esi        ; if InputBufferLength != OutputBufferLength then jmp
.text:000114DD 0F 85 65 01 00 00                       jnz     loc_11648
.text:000114E3 83 FE 14                                cmp     esi, 14h
.text:000114E6 0F 82 5C 01 00 00                       jb      loc_11648
.text:000114EC 81 3B 4D 45 4D 50                       cmp     dword ptr [ebx], 'PMEM'
.text:000114F2 0F 85 50 01 00 00                       jnz     loc_11648
.text:000114F8 8B 43 10                                mov     eax, [ebx+10h]
.text:000114FB 8D 48 14                                lea     ecx, [eax+14h]
.text:000114FE 3B F1                                   cmp     esi, ecx
.text:00011500 0F 85 42 01 00 00                       jnz     loc_11648
.text:00011506 50                                      push    eax             ; size_t
.text:00011507 8D 43 14                                lea     eax, [ebx+14h]
.text:0001150A 50                                      push    eax             ; void *
.text:0001150B FF 73 0C                                push    dword ptr [ebx+0Ch] ; void *
.text:0001150E FF 73 08                                push    dword ptr [ebx+8] ; int
.text:00011511 E8 48 08 00 00                          call    sub_11D5E       ; _in      Arg1 : ProcessId
.text:00011511                                                                 ; _in      Arg2 : Address
.text:00011511                                                                 ; _in_out  Arg3 : Buffer
.text:00011511                                                                 ; _in      Arg4 : BufferLength
.text:00011511                                                                 ;
.text:00011511                                                                 ; 读取 ProcessId 标识进程里指定 Address.
.text:00011511                                                                 ; 复制 Address 数据至 Buffer(长度为 BufferLength).
.text:00011516 E9 57 FF FF FF                          jmp     loc_11472
.text:0001151B                         ; ---------------------------------------------------------------------------
.text:0001151B                         ;
.text:0001151B                         ;  IoControlCode = 22E058h
.text:0001151B                         ;
.text:0001151B                         ;  通过 Ring3 层传入指定地址,映射该地址读取其物理地址数据.
.text:0001151B                         ;
.text:0001151B                         ;  //////////////////////////////////////////////////////////////////////////
.text:0001151B                         ;
.text:0001151B                         ;  InputBufferLength 和 OutputBufferLength 长度均为 20Ch.
.text:0001151B                         ;
.text:0001151B                         ;  SysteBuffer 结构如下:
.text:0001151B                         ;    0x00 ULONG ulOperTag;            // 标识操作行为
.text:0001151B                         ;    0x04 ULONG ulReserve1;           // 保留
.text:0001151B                         ;    0x08 PVOID pAddress;             // 读取地址
.text:0001151B                         ;    0x0C ULONG ulBufferLength;       // BufferLength
.text:0001151B                         ;    0x10 UCHAR ucBuffer[1];          // Buffer
.text:0001151B                         ;
.text:0001151B
.text:0001151B                         loc_1151B:                              ; CODE XREF: DeviceControlRoutine+190j
.text:0001151B 85 DB                                   test    ebx, ebx
.text:0001151D 0F 84 25 01 00 00                       jz      loc_11648
.text:00011523 3B D6                                   cmp     edx, esi        ; if InputBufferLength != OutputBufferLength then jmp
.text:00011525 0F 85 1D 01 00 00                       jnz     loc_11648
.text:0001152B 83 FE 10                                cmp     esi, 10h
.text:0001152E 0F 82 14 01 00 00                       jb      loc_11648
.text:00011534 81 3B 4D 45 4D 4B                       cmp     dword ptr [ebx], 'KMEM'
.text:0001153A 0F 85 08 01 00 00                       jnz     loc_11648
.text:00011540 8B 43 0C                                mov     eax, [ebx+0Ch]
.text:00011543 8D 48 10                                lea     ecx, [eax+10h]
.text:00011546 3B F1                                   cmp     esi, ecx
.text:00011548 0F 85 FA 00 00 00                       jnz     loc_11648
.text:0001154E 50                                      push    eax             ; Length
.text:0001154F 8D 43 10                                lea     eax, [ebx+10h]
.text:00011552 50                                      push    eax             ; void *
.text:00011553 FF 73 08                                push    dword ptr [ebx+8] ; Mdl
.text:00011556 E8 13 07 00 00                          call    sub_11C6E       ; _in      Arg1 : Address
.text:00011556                                                                 ; _in_out  Arg2 : Buffer
.text:00011556                                                                 ; _in      Arg3 : Length
.text:00011556                                                                 ;
.text:00011556                                                                 ; 映射 Address,复制 Address 地址处数据至 Buffer(长度为 Length).
.text:0001155B E9 12 FF FF FF                          jmp     loc_11472
代码:
NTSTATUS ReadProcessMemoryData(ULONG ulPid, 
                               ULONG ulAddress, 
                               PUCHAR pBuffer, 
                               ULONG ulBufferLength)
{
    NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;

    PEPROCESS pProcessObject = NULL;
    KAPC_STATE apcState;

    BOOLEAN bIsAttack = FALSE;

    __try
    {
        if (ulPid <= 8 || 0 >= ulAddress || !pBuffer || 0 >= ulBufferLength)
        {
            goto _abort;
        }

        if (0x10000 > ulAddress || (PULONG_PTR)MmHighestUserAddress < (PULONG_PTR)ulAddress)
        {
            goto _abort;
        }

        ntStatus = PsLookupProcessByProcessId((HANDLE)ulPid, &pProcessObject);
        if (!NT_SUCCESS(ntStatus))
        {
            goto _abort;
        }

        if (pProcessObject != IoGetCurrentProcess())
        {
            KeStackAttachProcess((PKPROCESS)pProcessObject, &apcState);
            bIsAttack = TRUE;
        }

        if (pProcessObject != IoGetCurrentProcess())
        {
            goto _cleanup;
        }

        RtlCopyMemory(pBuffer, (PUCHAR)(ULONG_PTR)ulAddress, ulBufferLength);

        ntStatus = STATUS_SUCCESS;
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        ntStatus = STATUS_UNSUCCESSFUL;
    }

_cleanup:

    if (bIsAttack)
    {
        KeUnstackDetachProcess(&apcState);
        pProcessObject = NULL;
    }

_abort:

    return ntStatus;
}

NTSTATUS ReadMemoryData(ULONG ulAddress, 
                        PUCHAR pBuffer, 
                        ULONG ulBufferLength)
{
    NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;

    PMDL pMdl = NULL;
    PVOID pMappingAddress = NULL;

    __try
    {
        if (0 >= ulAddress || (PULONG_PTR)ulAddress < (PULONG_PTR)MmSystemRangeStart || 
            !pBuffer || 0 >= ulBufferLength)
        {
            goto _abort;
        }

        if (!PageAddressIsValid(ulAddress, ulBufferLength))
        {
            goto _abort;
        }

        pMdl = IoAllocateMdl((PVOID)ulAddress, ulBufferLength, FALSE, FALSE, NULL);
        if (!pMdl)
        {
            goto _abort;
        }

        MmBuildMdlForNonPagedPool(pMdl);

        if (pMdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA | MDL_SOURCE_IS_NONPAGED_POOL))
        {
            pMappingAddress = pMdl->MappedSystemVa;
        }
        else
        {
            pMappingAddress = MmMapLockedPagesSpecifyCache(
                pMdl, 
                KernelMode, 
                MmCached, 
                NULL, 
                FALSE, 
                NormalPagePriority);
        }

        if (!pMappingAddress || !PageAddressIsValid((ULONG)pMappingAddress, ulBufferLength))
        {
            goto _cleanup;
        }

        RtlCopyMemory(pBuffer, pMappingAddress, ulBufferLength);

        ntStatus = STATUS_SUCCESS;
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        ntStatus = STATUS_UNSUCCESSFUL;
    }

_cleanup:

    if (pMdl)
    {
        IoFreeMdl(pMdl);
        pMdl = NULL;
    }

_abort:

    return ntStatus;
}
ps:idb 文件需 ida5.5 打开!

如 idb 分析错误或源码编写有误,请大家指点指点.~
上传的附件 TesDrvPt v1.0.5.0.rar
TesDrvPt.rar
TesDrvPt Demo.rar