逆向分析TesSafe.sys
//------------------------------ => TesSafe.sys --------------------------------------//// File MD5: E780032179272AFD93BCF4A9A67C7706
// Version: 0.0.6.5
//-----------------------------------------------------------------------------------------//
// 定义
extern "C"
{
#include <ntddk.h>
}
DWORD dword_14288 = 0xBB40E64E; // 这个变量有初值
DWORD dword_142C4 = 0;
DWORD dword_14050 = 5;
DWORD dword_1431C = 0; // 这个四字节变量保存一个指向PsGetProcessImageFileName的指针
DWORD dword_14338 = 0;
PKEVENT unk_143C0 = NULL;
KSPIN_LOCK SpinLock = 0; // 实际上是DWORD
PVOID unk_14328 = NULL;
PVOID unk_142B4 = NULL;
PVOID unk_143E0 = NULL;
PVOID BaseAddress = NULL;
// 其实内核函数默认调用方法就是stdcall,下面的_stdcall都是不用加的。
// 不过为了说明,还是都加上了。
VOID _stdcall proc_1121F(); // 防止动态调试
VOID _stdcall sub_11000(PVOID, DWORD, DWORD);
VOID _stdcall sub_118D0();
VOID _stdcall sub_1230C(); // 实现挂钩
// 下面的函数就是int __stdcall sub_112DA(HANDLE ProcessHandle, int, int, int, int)
NTSTATUS _stdcall Hook_ObOpenObjectByPointer(PVOID Object,ULONG HandleAttributes, PACCESS_STATE PassedAccessState, ACCESS_MASK DesiredAccess,
POBJECT_TYPE ObjectType, KPROCESSOR_MODE AccessMode, PHANDLE Handle);
VOID __stdcall NotifyRoutine(HANDLE ParentId, HANDLE ProcessId, BOOLEAN Create);
NTSTATUS _stdcall sub_11E48(DWORD, PVOID, PVOID);
NTSTATUS _stdcall DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
VOID _stdcall DriverUnload(PDRIVER_OBJECT pDrvObj);
// 实现
extern "C" NTSTATUS _stdcall DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING puRegistryString)
{
// 实际上这个为入口点,不过为了方便就写在了一起
if(dword_14288 != 0 && dword_14288 == 0xBB40E64E) // 十进制3141592654,晕倒。如果下面的异或操作已经执行过奇数次,那么这两个值不等
{
// 不过实际上由于 dword_14288 != 0的判断,不可以执行奇数次
dword_14288 = *(DWORD*)KeTickCount ^ dword_14288; // 与那个大PI异或
}
// 这里有一个长跳转,可能做过手脚
// jmp to text.12996,开始进入正事
// 定义变量
// sub esp,14H
// 由后面的反汇编我们可以知道定义了些什么
UNICODE_STRING SymbolicLinkName;
UNICODE_STRING DestinationString;
PDEVICE_OBJECT DeviceObject = NULL;
// 这个是我自己定义的,实际上在堆栈中没有分配
NTSTATUS st = STATUS_SUCCESS;
NTSTATUS stPre = STATUS_SUCCESS;
// 初始化
DestinationString.Length = 0;
DestinationString.MaximunLength = 0;
SymbolicLinkName.Length = 0;
SymbolicLinkName.MaximnumLength = 0;
_asm call loc_129C5; // 这个花指令思路比较新
_asm emit 0fH;
_asm emit 88H;
_asm jmp loc_129D3; // IDA认错指令了,它认为是:db eb; pop cs
loc_129C5:
_asm pop ecx; // 第一次执行,ecx == loc_129C5 - 3,就是那个0fH 第二次执行为cs
_asm jmp loc_129CA; // 这个作者用了这么多嵌入汇编?要知道jmp和call是不能过IDA的
// 花指令
_asm emit 50H;
_asm emit 33H;
loc_129CA:
_asm add ecx,2; // 第一次执行 ecx == loc_129C5 - 1,就是loc_129C5上面那条指令,IDA将它认出来了。
// 第二次执行时 ecx = loc_129D3
_asm jmp loc_129D0;
_asm emit 76H;
loc_129D0:
goto ecx; // 原来这里的指令是 push ecx, retn,相当于jmp
// 第二次执行时跳到了loc_129D3处
loc_129D3:
// 花指令段结束。开始!
// 这里最好把前面那些花指令Undefine掉,使得IDA认为这是一个函数。
// 这样就可以显示函数的参数名了。
proc_11218(); // 里面有jmp 1121F,进去
RtlInitUnicodeString(&DestinationString, L"//Device//TesSafe");
st = IoCreateDevice(DriverObject, 0, &DestinationString, 0x22,
0, FALSE, &DeviceObject);
// 反汇编里有一句 mov ,eax 可能是因为参数DriverObject已经不再使用
// 可以用来放st ,这是编译器优化的结果
if(!NT_SUCCESS(st))
{
return st;
}
RtlInitUnicodeString(&SourceString, L"//DosDevices//TesSafe");
st = IoCreateSymbolicLink(&SymbolicLinkName, &DestinationString);
stPre = st;
if(!NT_SUCCESS(st))
{
return st;
}
// 这里有个小花
_asm call loc_12A34;
_asm emit 83H;
_asm emit 0F8H;
_asm emit 2H;
_asm emit 74H;
loc_12A34:
_asm add esp,4; // 保持堆栈平衡
DriverObject->MajorFunction = DispatchIoctl;
DriverObject->MajorFunction = DispatchIoctl;
DriverObject->MajorFunction = DispatchIoctl;
DriverObject->MajorFunction = DispatchIoctl;
st = sub_11E48(&dword_142B0, &unk_142B4, &unk_143E0);
if(!NT_SUCCESS(st))
{
IoDeleteSymolicLink(&SymbolicLinkName);
// 这里还有一个判断,用于判断上次的st是否为TRUE
if(!NT_SUCCESS(stPre))
{
IoDeleteDevice(DeviceObject);
}
return st;
}
// 这里来了个小花(call loc_12A8A),将它去掉
_asm call loc_12A8A;
_asm emit 74H;
loc_12A8A:
_asm add esp,4; // 平衡堆栈
BaseAddess = MmAllocateNonCachedMemory(0x2000);
return st;
}
// 防止动态调试
**** Hidden Message ***** dddddddddddddddddddddddddddd 回复 1# agess
ccccccccccccccccccccccccccccccc 板凳哈哈我饿饿 11111111111111 定了 谢谢楼主共享 看见好看就撒旦个好看个 怎么有师傅会 逆向分析TesSafe.sys 谢谢分享谢谢分享