前段时间在某群里看到 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 分析错误或源码编写有误,请大家指点指点.~
[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。