前段时间在某群里看到 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; }
如 idb 分析错误或源码编写有误,请大家指点指点.~