zoukankan      html  css  js  c++  java
  • PowerTool x64驱动模块逆向分析(持续更新)

    比赛打完了,来继续搞了,因为那个主动防御正在写,所以想找找思路正好想到可以来逆向一下PT的驱动模块看看pt大大是怎么写的程序。

    PT x64版本的驱动模块是这个kEvP64.sys。

    0x0

    先来看看DriverEntry

     1 //IDA伪代码
     2 __int64 __fastcall sub_3A010(struct _DRIVER_OBJECT *a1, __int64 a2)
     3 {
     4   char *v2; // rdi@1
     5   signed __int64 i; // rcx@1
     6   char *v4; // rdi@4
     7   __int64 v5; // rsi@4
     8   signed __int64 j; // rcx@4
     9   _UNKNOWN *v7; // rdi@7
    10   char *v8; // rsi@7
    11   signed __int64 k; // rcx@7
    12   __int64 result; // rax@11
    13   unsigned int v11; // [sp+48h] [bp-A0h]@10
    14   NTSTATUS v12; // [sp+48h] [bp-A0h]@12
    15   NTSTATUS v13; // [sp+48h] [bp-A0h]@14
    16   char v14; // [sp+ACh] [bp-3Ch]@1
    17   char v15; // [sp+C0h] [bp-28h]@4
    18   struct _DRIVER_OBJECT *DriverObject; // [sp+F0h] [bp+8h]@1
    19 
    20   DriverObject = a1;
    21   v2 = &v14;
    22   for ( i = 4i64; i; --i )
    23     *v2++ = 0;
    24   v4 = &v15;
    25   v5 = a2;
    26   for ( j = 16i64; j; --j )
    27     *v4++ = *(_BYTE *)v5++;
    28   v7 = &unk_37C60;
    29   v8 = &v15;
    30   for ( k = 16i64; k; --k )
    31   {
    32     *(_BYTE *)v7 = *v8++;
    33     v7 = (char *)v7 + 1;
    34   }
    35   RtlGetVersion(&unk_37AE0);
    36   v11 = sub_19A30();
    37   if ( (v11 & 0x80000000) == 0 )
    38   {
    39     sub_39010();
    40     DriverObject->DriverUnload = (PDRIVER_UNLOAD)sub_29870;
    41     RtlInitUnicodeString(&DeviceName, L"\Device\kEvP64");
    42     v12 = IoCreateDevice(DriverObject, 0, &DeviceName, 0x22u, 0x100u, 0, &DeviceObject);
    43     if ( v12 >= 0 )
    44     {
    45       DriverObject->MajorFunction[0] = (PDRIVER_DISPATCH)sub_298F0;
    46       DriverObject->MajorFunction[2] = (PDRIVER_DISPATCH)sub_298F0;
    47       DriverObject->MajorFunction[14] = (PDRIVER_DISPATCH)sub_29940;
    48       RtlInitUnicodeString(&SymbolicLinkName, L"\DosDevices\kEvP64");
    49       v13 = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
    50       if ( v13 >= 0 )
    51       {
    52         FltRegisterFilter(DriverObject, &unk_300C0, &qword_37AA8);
    53         *((_DWORD *)DriverObject->DriverSection + 26) |= 0x20u;
    54         qword_37C28 = (__int64)DriverObject;
    55         result = 0i64;
    56       }
    57       else
    58       {
    59         IoDeleteDevice(DeviceObject);
    60         result = (unsigned int)v13;
    61       }
    62     }
    63     else
    64     {
    65       result = (unsigned int)v12;
    66     }
    67   }
    68   else
    69   {
    70     result = v11;
    71   }
    72   return result;
    73 }

    函数的26、27行把程序的注册表目录的字符串保存到了局部数组中,然后又存在了一个全局的缓冲区里,应该是一个全局数组。

    然后是进行系统版本的判断,对于驱动模块来说判断系统很重要,否则很容易造成蓝屏。

    使用RtlGetVersion获得一个有关系统信息的结构,WDK中对这个函数的描述如下

    RtlGetVersion
    The RtlGetVersion routine returns version information about the currently running operating system.
    
    NTSTATUS
      RtlGetVersion(
        IN OUT PRTL_OSVERSIONINFOW  lpVersionInformation
        );

    来看看pt是怎么对版本进行的判断,

    首先是对IRQL进行的判断,代码如下

    1   if ( (signed int)(unsigned __int8)sub_11030() > 1 )
    2   {
    3     v0 = sub_11030();
    4     DbgPrint("EX: Pageable code called at IRQL %d
    ", v0);
    5     sub_11020();
    6   }

    其中sub_11030的反汇编如下

    刚开始没明白是什么意思,后来查了一下原来X64的IRQL储存在CR8里,这个以前还真的不知道,学到了。

    判断了一下IRQL是否合理,然后就是具体的判断了。

      1   v2 = dword_37964;
      2   v4 = dword_37968;
      3   v3 = (unsigned __int16)word_37A74;
      4   DbgPrint(
      5     "[kEvP64]Windows %d.%d, SP%d.%d, build %d
    ",
      6     (unsigned int)dword_37964,
      7     (unsigned int)dword_37968,
      8     (unsigned __int16)word_37A74);
      9   dword_37908 = 0;
     10   dword_378E0 = 0;
     11   if ( v2 == 5 && v4 == 1 )
     12   {
     13     dword_378FC = 51;
     14     if ( !v3 )
     15       return 3221225659i64;
     16     if ( v3 == 1 )
     17       return 3221225659i64;
     18     if ( v3 != 2 && v3 != 3 )
     19       return 3221225659i64;
     20     return 0i64;
     21   }
     22   if ( v2 == 5 && v4 == 2 )
     23   {
     24     dword_378FC = 52;
     25     if ( v3 && v3 != 1 && v3 != 2 )
     26       return 3221225659i64;
     27     return 0i64;
     28   }
     29   if ( v2 == 6 && !v4 )
     30   {
     31     dword_378FC = 60;
     32     if ( v3 )
     33     {
     34       if ( v3 == 1 )
     35       {
     36         dword_37C40 = 16;
     37         dword_37C50 = 40;
     38       }
     39       else
     40       {
     41         if ( v3 != 2 )
     42           return 3221225659i64;
     43         dword_37C40 = 16;
     44         dword_37C50 = 40;
     45       }
     46     }
     47     else
     48     {
     49       dword_37C40 = 120;
     50       dword_37C50 = 144;
     51     }
     52     dword_37C58 = 20;
     53     dword_37C70 = 352;
     54     dword_37C54 = 876;
     55     dword_378E4 = 11;
     56     dword_37A90 = 216;
     57     dword_378F8 = 16;
     58     dword_378F0 = 632;
     59     dword_37AC0 = 24;
     60     dword_37C44 = 104;
     61     dword_37C48 = 992;
     62     dword_37BF4 = 856;
     63     dword_37930 = 115;
     64     dword_378F4 = 340;
     65     dword_37AB0 = 904;
     66     dword_37C4C = 896;
     67     dword_37920 = 904;
     68     dword_37AC4 = 896;
     69     dword_37BF8 = 339;
     70     dword_37888 = 1056;
     71     dword_37908 = 48;
     72     dword_377CC = 580;
     73     dword_37894 = 48;
     74     dword_377C4 = 41;
     75     dword_377B0 = 32;
     76     dword_377B4 = 370;
     77     dword_377B8 = 79;
     78     dword_377BC = 80;
     79     dword_377C0 = 22;
     80     dword_3788C = 440;
     81     dword_37890 = 712;
     82     dword_37898 = 2416;
     83     dword_3789C = 2424;
     84     dword_378A0 = 56;
     85     return 0i64;
     86   }
     87   if ( v2 == 6 && v4 == 1 )
     88   {
     89     dword_378FC = 61;
     90     if ( v3 && v3 != 1 )
     91       return 3221225659i64;
     92     dword_37C58 = 20;
     93     dword_37C70 = 512;
     94     dword_37C54 = 1084;
     95     dword_378E4 = 11;
     96     dword_37A90 = 376;
     97     dword_378F8 = 16;
     98     dword_37C40 = 16;
     99     dword_37C50 = 40;
    100     dword_378F0 = 800;
    101     dword_37AC0 = 24;
    102     dword_37C44 = 112;
    103     dword_37C48 = 1040;
    104     dword_37BF4 = 904;
    105     dword_37C30 = 1048;
    106     dword_37C14 = 912;
    107     dword_37930 = 123;
    108     dword_378F4 = 356;
    109     dword_37BF8 = 502;
    110     dword_37888 = 1056;
    111     dword_37AB0 = 960;
    112     dword_37C4C = 952;
    113     dword_37920 = 952;
    114     dword_37AC4 = 944;
    115     dword_37908 = 48;
    116     dword_377CC = 620;
    117     dword_37894 = 48;
    118     dword_377C4 = 41;
    119     dword_377B0 = 32;
    120     dword_377B4 = 379;
    121     dword_377B8 = 79;
    122     dword_377BC = 80;
    123     dword_377C0 = 22;
    124     dword_3788C = 600;
    125     dword_37890 = 744;
    126     dword_37898 = 1352;
    127     dword_3789C = 1360;
    128     dword_378A0 = 64;
    129     DbgPrint("[kEvP64]Initialized version-specific data for Windows 7 SP%d
    ", v3);
    130     return 0i64;
    131   }
    132   if ( v2 == 6 && v4 == 2 )
    133   {
    134     dword_378FC = 62;
    135     dword_37C58 = 20;
    136     dword_37C70 = 1032;
    137     dword_37C54 = -1;
    138     dword_378E4 = -1;
    139     dword_37A90 = 456;
    140     dword_378F8 = 16;
    141     dword_37C40 = 16;
    142     dword_37C50 = 40;
    143     dword_378F0 = 1048;
    144     dword_37AC0 = 24;
    145     dword_37908 = 48;
    146     dword_37C10 = 19;
    147     dword_378E0 = 20;
    148     dword_37C44 = 184;
    149     dword_37C48 = 1008;
    150     dword_37BF4 = 880;
    151     dword_37C30 = 1008;
    152     dword_37C14 = 880;
    153     dword_37930 = 195;
    154     dword_378F4 = 388;
    155     dword_37BF8 = 562;
    156     dword_37888 = 1024;
    157     dword_37AB0 = 928;
    158     dword_37C4C = 920;
    159     dword_37920 = 928;
    160     dword_37AC4 = 920;
    161     dword_377CC = 644;
    162     dword_37894 = 48;
    163     dword_377C4 = 42;
    164     dword_377B0 = 33;
    165     dword_377B4 = 402;
    166     dword_377B8 = 80;
    167     dword_377BC = 81;
    168     dword_377C0 = 23;
    169     dword_3788C = 920;
    170     dword_37890 = 784;
    171     dword_37898 = 328;
    172     dword_3789C = 336;
    173     dword_378A0 = 72;
    174     DbgPrint("[kEvP64]Initialized version-specific data for Windows 8 SP%d
    ", v3);
    175     return 0i64;
    176   }
    177   if ( v2 == 6 && v4 == 3 )
    178   {
    179     dword_378FC = 63;
    180     dword_37C54 = -1;
    181     dword_378E4 = -1;
    182     dword_37C58 = 20;
    183     dword_378F8 = 16;
    184     dword_37C70 = 1032;
    185     dword_37A90 = 728;
    186     dword_37C40 = 16;
    187     dword_37C50 = 40;
    188     dword_378F0 = 1048;
    189     dword_37AC0 = 24;
    190     dword_37908 = 48;
    191     dword_37C10 = 16;
    192     dword_378E0 = 17;
    193     dword_37C44 = 184;
    194     dword_37C48 = 1656;
    195     dword_37BF4 = 1528;
    196     dword_37C30 = 1656;
    197     dword_37C14 = 1528;
    198     dword_37930 = 195;
    199     dword_378F4 = 388;
    200     dword_37BF8 = 562;
    201     dword_37888 = 760;
    202     dword_37AB0 = 1576;
    203     dword_37C4C = 1568;
    204     dword_37920 = 1576;
    205     dword_37AC4 = 1568;
    206     dword_377CC = 644;
    207     dword_37894 = 48;
    208     dword_377C4 = 43;
    209     dword_377B0 = 34;
    210     dword_377B4 = 408;
    211     dword_377B8 = 81;
    212     dword_377BC = 82;
    213     dword_377C0 = 24;
    214     dword_3788C = 920;
    215     dword_37890 = 784;
    216     dword_37898 = 328;
    217     dword_3789C = 336;
    218     dword_378A0 = 72;
    219     DbgPrint("[kEvP64]Initialized version-specific data for Windows 8.1 SP%d
    ", v3);
    220     return 0i64;
    221   }
    222   if ( v2 == 10 && !v4 )
    223   {
    224     dword_378FC = 100;
    225     dword_37C54 = -1;
    226     dword_378E4 = -1;
    227     dword_37C58 = 20;
    228     dword_378F8 = 16;
    229     dword_37C70 = 1048;
    230     dword_37A90 = 736;
    231     dword_378F0 = 1064;
    232     dword_37C40 = 16;
    233     dword_37C50 = 40;
    234     dword_37AC0 = 24;
    235     dword_37908 = 48;
    236     dword_37C10 = 16;
    237     dword_378E0 = 17;
    238     dword_37C44 = 184;
    239     dword_37C48 = 1664;
    240     dword_37BF4 = 1536;
    241     dword_37C30 = 1664;
    242     dword_37C14 = 1536;
    243     dword_37930 = 195;
    244     dword_378F4 = 388;
    245     dword_37BF8 = 562;
    246     dword_37888 = 760;
    247     dword_37AB0 = 1584;
    248     dword_37C4C = 1576;
    249     dword_37920 = 1584;
    250     dword_37AC4 = 1576;
    251     dword_377CC = 644;
    252     dword_37894 = 48;
    253     dword_377C4 = 44;
    254     dword_377B0 = 35;
    255     dword_377B4 = 416;
    256     dword_377B8 = 82;
    257     dword_377BC = 83;
    258     dword_377C0 = 25;
    259     dword_3788C = 936;
    260     dword_37890 = 784;
    261     dword_37898 = 328;
    262     dword_3789C = 336;
    263     dword_378A0 = 72;
    264     return 0i64;
    265   }
    266   if ( v2 == 10 && v4 || v2 > 0xA )
    267   {
    268     dword_378FC = -1;
    269     result = 3221225659i64;
    270   }
    271   else
    272   {
    273     result = 3221225659i64;
    274   }
    275   return result;
    276 }

    其中v2,v3,v4都是结构体中的成员,就是上面用RtlGetVersion获取到的结构体。

    类似于return 3221225659i64;这种是NTSTATUS值,0就是STATUS_SUCESS,下面还可以看到

    (v11 & 0x80000000) == 0

    这种写法就是NT_SUCESS()宏

     来具体看下这种判断过程是怎么个意思

     dword_37960 = 284;
      v2 = RtlGetVersion(&dword_37960);

    这个是指定使用了RTL_OSVERSIONINFOEXW结构,因为RtlGetVersion这个函数其实可以支持两种格式的输出。

    根据反汇编的结果还原了一下C的源码,应该是根据不同的系统版本设置了全局变量不同的值,但是目前还不知道这些变量的作用,判断系统方法比较简单,根据dwMajorVersion判断主版本号,dwMinorVersion判断副版本号,再根据需要去判断wServicePackMajor的值就可以实现了。

      1 RTL_OSVERSIONINFOEXW Struct={284};
      2 ULONG Version;
      3 NTSTATUS CheckVersion(void)
      4 {
      5     ULONG MajorVersion;
      6     ULONG MinorVersion;
      7     ULONG ServicePackMajor;
      8     ULONG IRQL;
      9     ULONG result;
     10     RtlGetVersion(&Struct);
     11     if(KeGetCurrentirql()>PASSIVE_LEVEL)
     12     {
     13         IRQL=KeGetCurrentirql();
     14         DbgPrint("EX: Pageable code called at IRQL %d
    ", IRQL);
     15         _asm{int 0x2c};
     16     }
     17     MajorVersion=Struct.dwMajorVersion;
     18     MinorVersion=Struct.dwMinorVersion;
     19     ServicePackMajor=Struct.wServicePackMajor;
     20     DbgPrint(
     21     "[kEvP64]Windows %d.%d, SP%d.%d, build %d
    ",Struct.dwMajorVersion,Struct.dwMinorVersion,Struct.wServicePackMajor);
     22     if(MajorVersion==5&&MinorVersion==1)
     23     {    
     24         //WINDOWS_XP
     25         Version=51;
     26         if(!ServicePackMajor)
     27             return 3221225659;
     28         if(ServicePackMajor==1)
     29             return 3221225659;
     30         if(ServicePackMajor!=2&&ServicePackMajor!=3)
     31             return 3221225659;
     32         return STATUS_SUCCESS;
     33     }
     34     if(MajorVersion==5&&MinorVersion==2)
     35     {
     36         //WINDOWS_2003
     37         Version=52;
     38         if(ServicePackMajor&&ServicePackMajor!=1&&ServicePackMajor!=2)
     39             return 3221225659;
     40         return STATUS_SUCCESS;
     41     }
     42     if(MajorVersion==6&&!MinorVersion)
     43     {
     44         //WINDOWS_2003
     45         Version=60;
     46         if(ServicePackMajor)
     47         {
     48             if(ServicePackMajor==1)
     49             {
     50                 dword_37C40 = 16;
     51                 dword_37C50 = 40;
     52             }
     53             else
     54             {
     55                 if(ServicePackMajor!=2)
     56                     return 3221225659;
     57                 dword_37C40 = 16;
     58                 dword_37C50 = 40;
     59             }
     60         }
     61         else
     62         {
     63             dword_37C40 = 120;
     64             dword_37C50 = 144;
     65         }
     66         dword_37C58 = 20;
     67         dword_37C70 = 352;
     68         dword_37C54 = 876;
     69         dword_378E4 = 11;
     70         dword_37A90 = 216;
     71         dword_378F8 = 16;
     72         dword_378F0 = 632;
     73         dword_37AC0 = 24;
     74         dword_37C44 = 104;
     75         dword_37C48 = 992;
     76         dword_37BF4 = 856;
     77         dword_37930 = 115;
     78         dword_378F4 = 340;
     79         dword_37AB0 = 904;
     80         dword_37C4C = 896;
     81         dword_37920 = 904;
     82         dword_37AC4 = 896;
     83         dword_37BF8 = 339;
     84         dword_37888 = 1056;
     85         dword_37908 = 48;
     86         dword_377CC = 580;
     87         dword_37894 = 48;
     88         dword_377C4 = 41;
     89         dword_377B0 = 32;
     90         dword_377B4 = 370;
     91         dword_377B8 = 79;
     92         dword_377BC = 80;
     93         dword_377C0 = 22;
     94         dword_3788C = 440;
     95         dword_37890 = 712;
     96         dword_37898 = 2416;
     97         dword_3789C = 2424;
     98         dword_378A0 = 56;
     99         return STATUS_SUCCESS;
    100     }
    101     if(MajorVersion==6&&MinorVersion==1)
    102     {
    103         //WINDOWS_7
    104         Version=61;
    105         if(ServicePackMajor&&ServicePackMajor!=1)
    106             return 3221225659;
    107         dword_37C58 = 20;
    108         dword_37C70 = 512;
    109         dword_37C54 = 1084;
    110         dword_378E4 = 11;
    111         dword_37A90 = 376;
    112         dword_378F8 = 16;
    113         dword_37C40 = 16;
    114         dword_37C50 = 40;
    115         dword_378F0 = 800;
    116         dword_37AC0 = 24;
    117         dword_37C44 = 112;
    118         dword_37C48 = 1040;
    119         dword_37BF4 = 904;
    120         dword_37C30 = 1048;
    121         dword_37C14 = 912;
    122         dword_37930 = 123;
    123         dword_378F4 = 356;
    124         dword_37BF8 = 502;
    125         dword_37888 = 1056;
    126         dword_37AB0 = 960;
    127         dword_37C4C = 952;
    128         dword_37920 = 952;
    129         dword_37AC4 = 944;
    130         dword_37908 = 48;
    131         dword_377CC = 620;
    132         dword_37894 = 48;
    133         dword_377C4 = 41;
    134         dword_377B0 = 32;
    135         dword_377B4 = 379;
    136         dword_377B8 = 79;
    137         dword_377BC = 80;
    138         dword_377C0 = 22;
    139         dword_3788C = 600;
    140         dword_37890 = 744;
    141         dword_37898 = 1352;
    142         dword_3789C = 1360;
    143         dword_378A0 = 64;
    144         DbgPrint("[kEvP64]Initialized version-specific data for Windows 7 SP%d
    ", ServicePackMajor);
    145         return STATUS_SUCCESS;
    146   
    147     }
    148     if(MajorVersion==6&&MinorVersion==2)
    149     {
    150         //WINDOWS_8
    151         dword_378FC = 62;
    152         dword_37C58 = 20;
    153         dword_37C70 = 1032;
    154         dword_37C54 = -1;
    155         dword_378E4 = -1;
    156         dword_37A90 = 456;
    157         dword_378F8 = 16;
    158         dword_37C40 = 16;
    159         dword_37C50 = 40;
    160         dword_378F0 = 1048;
    161         dword_37AC0 = 24;
    162         dword_37908 = 48;
    163         dword_37C10 = 19;
    164         dword_378E0 = 20;
    165         dword_37C44 = 184;
    166         dword_37C48 = 1008;
    167         dword_37BF4 = 880;
    168         dword_37C30 = 1008;
    169         dword_37C14 = 880;
    170         dword_37930 = 195;
    171         dword_378F4 = 388;
    172         dword_37BF8 = 562;
    173         dword_37888 = 1024;
    174         dword_37AB0 = 928;
    175         dword_37C4C = 920;
    176         dword_37920 = 928;
    177         dword_37AC4 = 920;
    178         dword_377CC = 644;
    179         dword_37894 = 48;
    180         dword_377C4 = 42;
    181         dword_377B0 = 33;
    182         dword_377B4 = 402;
    183         dword_377B8 = 80;
    184         dword_377BC = 81;
    185         dword_377C0 = 23;
    186         dword_3788C = 920;
    187         dword_37890 = 784;
    188         dword_37898 = 328;
    189         dword_3789C = 336;
    190         dword_378A0 = 72;
    191         DbgPrint("[kEvP64]Initialized version-specific data for Windows 8 SP%d
    ", ServicePackMajor);
    192         return STATUS_SUCCESS;
    193     }
    194      if ( MajorVersion == 6 && MinorVersion == 3 )
    195     {
    196         //WINDOWS_8.1
    197         dword_378FC = 63;
    198         dword_37C54 = -1;
    199         dword_378E4 = -1;
    200         dword_37C58 = 20;
    201         dword_378F8 = 16;
    202         dword_37C70 = 1032;
    203         dword_37A90 = 728;
    204         dword_37C40 = 16;
    205         dword_37C50 = 40;
    206         dword_378F0 = 1048;
    207         dword_37AC0 = 24;
    208         dword_37908 = 48;
    209         dword_37C10 = 16;
    210         dword_378E0 = 17;
    211         dword_37C44 = 184;
    212         dword_37C48 = 1656;
    213         dword_37BF4 = 1528;
    214         dword_37C30 = 1656;
    215         dword_37C14 = 1528;
    216         dword_37930 = 195;
    217         dword_378F4 = 388;
    218         dword_37BF8 = 562;
    219         dword_37888 = 760;
    220         dword_37AB0 = 1576;
    221         dword_37C4C = 1568;
    222         dword_37920 = 1576;
    223         dword_37AC4 = 1568;
    224         dword_377CC = 644;
    225         dword_37894 = 48;
    226         dword_377C4 = 43;
    227         dword_377B0 = 34;
    228         dword_377B4 = 408;
    229         dword_377B8 = 81;
    230         dword_377BC = 82;
    231         dword_377C0 = 24;
    232         dword_3788C = 920;
    233         dword_37890 = 784;
    234         dword_37898 = 328;
    235         dword_3789C = 336;
    236         dword_378A0 = 72;
    237         DbgPrint("[kEvP64]Initialized version-specific data for Windows 8.1 SP%d
    ", ServicePackMajor);
    238         return STATUS_SUCCESS;
    239     }
    240   if ( MajorVersion == 10 && !MinorVersion )
    241     {
    242         //WINDOWS_10
    243         dword_378FC = 100;
    244         dword_37C54 = -1;
    245         dword_378E4 = -1;
    246         dword_37C58 = 20;
    247         dword_378F8 = 16;
    248         dword_37C70 = 1048;
    249         dword_37A90 = 736;
    250         dword_378F0 = 1064;
    251         dword_37C40 = 16;
    252         dword_37C50 = 40;
    253         dword_37AC0 = 24;
    254         dword_37908 = 48;
    255         dword_37C10 = 16;
    256         dword_378E0 = 17;
    257         dword_37C44 = 184;
    258         dword_37C48 = 1664;
    259         dword_37BF4 = 1536;
    260         dword_37C30 = 1664;
    261         dword_37C14 = 1536;
    262         dword_37930 = 195;
    263         dword_378F4 = 388;
    264         dword_37BF8 = 562;
    265         dword_37888 = 760;
    266         dword_37AB0 = 1584;
    267         dword_37C4C = 1576;
    268         dword_37920 = 1584;
    269         dword_37AC4 = 1576;
    270         dword_377CC = 644;
    271         dword_37894 = 48;
    272         dword_377C4 = 44;
    273         dword_377B0 = 35;
    274         dword_377B4 = 416;
    275         dword_377B8 = 82;
    276         dword_377BC = 83;
    277         dword_377C0 = 25;
    278         dword_3788C = 936;
    279         dword_37890 = 784;
    280         dword_37898 = 328;
    281         dword_3789C = 336;
    282         dword_378A0 = 72;
    283         return STATUS_SUCCESS;
    284     }
    285   if ( MajorVersion == 10 && MajorVersion || MinorVersion > 0xA )
    286     {
    287         dword_378FC = -1;
    288         result = 3221225659;
    289     }
    290   else
    291     {
    292         result = 3221225659;
    293     }
    294   return result;
    295 }
    View Code

    因为代码比较长,我默认折叠了,想看的可以看下。

     我们继续往下看了,接下来主要做了如下几件事:

    1. 创建一个设备
    2. 创建符号链接
    3. 设置设备分发函数
    4. 注册一个过滤驱动

    首先作者实现了一个获取导出函数地址的函数,我想这是因为作者想使用一些已经导出但是没有在WDK文档中的函数吧。我这里取名为GetFuncAddress了。我用C重写了一下这个函数,如下

    //根据反汇编写的
    PVOID GetFuncAddress(WCHAR *Name)
    {
        ULONG IRQL;
        UNICODE_STRING UnicodeFindName;
        WCHAR *BufPointer=Name;
        if(KeGetCurrentirql()>1)
        {
            IRQL=KeGetCurrentirql();
            DbgPrint("EX: Pageable code called at IRQL %d
    ", IRQL);
            _asm{int 0x2C};
        }
        RtlInitUnicodeString(&UnicodeFindName,BufPointer);
        return MmGetSystemRoutineAddress(&UnicodeFindName);
    }

    然后作者用这个函数获取一些函数的地址(先判断了一下系统的版本),函数的列表如下

    "ExfUnblockPushLock"
    "ObGetObjectType"
    "ObDereferenceObject"
    "PsAcquireProcessExitSynchronization"
    "PsIsProtectedProcess"
    "PsReleaseProcessExitSynchronization"
    "PsResumeProcess"
    "PsSuspendProcess"
    "KeSetAffinityThread"

     这些部分都在第39行的sub_39010();函数中,程序判断完系统版本后马上就执行了这个函数。

    这个函数的伪代码如下

     1 __int64 sub_39010()
     2 {
     3   unsigned __int8 v0; // al@2
     4   __int64 result; // rax@15
     5 
     6   if ( (signed int)(unsigned __int8)sub_11030() > 1 )
     7   {
     8     v0 = sub_11030();
     9     DbgPrint("EX: Pageable code called at IRQL %d
    ", v0);
    10     sub_11020();
    11   }
    12   if ( (unsigned int)dword_378FC >= 0x3E )
    13     qword_37AB8 = (__int64)sub_392B0(L"ExfUnblockPushLock");
    14   qword_37928 = (__int64)sub_392B0(L"ObGetObjectType");
    15   qword_378E8 = (__int64)sub_392B0(L"ObDereferenceObject");
    16   qword_378D8 = (__int64)sub_392B0(L"PsAcquireProcessExitSynchronization");
    17   qword_37A98 = (__int64)sub_392B0(L"PsIsProtectedProcess");
    18   qword_37C38 = (__int64)sub_392B0(L"PsReleaseProcessExitSynchronization");
    19   qword_37900 = (__int64)sub_392B0(L"PsResumeProcess");
    20   qword_37C20 = (__int64)sub_392B0(L"PsSuspendProcess");
    21   qword_378B8 = (__int64)sub_392B0(L"KeSetAffinityThread");
    22   sub_26AD0((__int64)qword_39A00, (__int64)"KfdClassify2");
    23   sub_26AD0((__int64)qword_39A00, (__int64)"GetCalloutEntry ");
    24   sub_26AD0((__int64)qword_39A00, (__int64)"InitDefaultCallout ");
    25   qword_377F8 = sub_26AD0((__int64)qword_39A70, (__int64)"KeInsertQueueApc");
    26   if ( !qword_377F8 )
    27     qword_377F8 = (__int64)sub_392B0(L"KeInsertQueueApc");
    28   qword_37800 = sub_26AD0((__int64)qword_39A70, (__int64)"PsSetCreateProcessNotifyRoutine");
    29   if ( !qword_37800 )
    30     qword_37800 = (__int64)sub_392B0(L"PsSetCreateProcessNotifyRoutine");
    31   qword_37808 = sub_26AD0((__int64)qword_39A70, (__int64)"PsSetCreateThreadNotifyRoutine");
    32   if ( !qword_37808 )
    33     qword_37808 = (__int64)sub_392B0(L"PsSetCreateThreadNotifyRoutine");
    34   qword_37810 = sub_26AD0((__int64)qword_39A70, (__int64)"PsSetLoadImageNotifyRoutine");
    35   if ( !qword_37810 )
    36     qword_37810 = (__int64)sub_392B0(L"PsSetLoadImageNotifyRoutine");
    37   qword_37818 = sub_26AD0((__int64)qword_39A70, (__int64)"CmUnRegisterCallback");
    38   if ( !qword_37818 )
    39     qword_37818 = (__int64)sub_392B0(L"CmUnRegisterCallback");
    40   result = sub_26AD0((__int64)qword_39A70, (__int64)"IoRegisterShutdownNotification");
    41   qword_37820 = result;
    42   if ( !result )
    43   {
    44     result = (__int64)sub_392B0(L"IoRegisterShutdownNotification");
    45     qword_37820 = result;
    46   }
    47   return result;
    48 }

    这个函数首先判断了一下IRQL这个在之前就已经分析过了,然后判断了一下系统版本,通过验证之后用自己实现的GetFuncAddress函数来获取这些函数的地址,并把地址储存在全局变量中sub_392B0就是GetFuncAddress(),然后又调用了sub_26AD0()这个函数,这个函数中又调用了这个函数

     1 //IDA伪代码,被sub_39010()调用
     2 PVOID __fastcall sub_260D0(unsigned int a1)
     3 {
     4   PVOID result; // rax@3
     5   int v2; // [sp+20h] [bp-28h]@4
     6   int v3; // [sp+24h] [bp-24h]@4
     7   SIZE_T NumberOfBytes; // [sp+28h] [bp-20h]@1
     8   PVOID P; // [sp+30h] [bp-18h]@2
     9   unsigned int v6; // [sp+50h] [bp+8h]@1
    10 
    11   v6 = a1;
    12   for ( LODWORD(NumberOfBytes) = 256; ; LODWORD(NumberOfBytes) = v3 + 256 )
    13   {
    14     P = ExAllocatePool(0, (unsigned int)NumberOfBytes);
    15     if ( !P )
    16       return 0i64;
    17     v3 = 0;
    18     v2 = ZwQuerySystemInformation(v6, P, (unsigned int)NumberOfBytes, &v3);
    19     if ( v2 == -1073741820 )
    20     {
    21       ExFreePoolWithTag(P, 0);
    22       P = 0i64;
    23       if ( v3 )
    24         continue;
    25     }
    26     break;
    27   }
    28   if ( v2 >= 0 )
    29   {
    30     result = P;
    31   }
    32   else
    33   {
    34     sub_199F0(P);
    35     result = 0i64;
    36   }
    37   return result;
    38 }

    这是调用ZwQuerySystemInformation()函数的11号功能也就是SystemModuleInformation功能,这个函数经常在安全类程序中调用,作为一个常规的枚举模块的方法。用循环是为了让ZwQuerySystemInformation返回需要的合适的大小。这个函数返回的结构如下

    1 typedef struct _SYSTEM_MODULE_INFORMATION {
    2 ULONG Count;
    3 SYSTEM_MODULE_INFORMATION_ENTRY Module[1];
    4 } SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;

    Count为个数,有多少Count就有多少的SYSTEM_MODULE_INFORMATION_ENTRY,其中这个数组中的项的结构如下:

    typedef struct _SYSTEM_MODULE_INFORMATION_ENTRY {
    HANDLE Section;
    PVOID MappedBase;
    PVOID Base;
    ULONG Size;
    ULONG Flags;
    USHORT LoadOrderIndex;
    USHORT InitOrderIndex;
    USHORT LoadCount;
    USHORT PathLength;
    CHAR ImageName[256];
    } SYSTEM_MODULE_INFORMATION_ENTRY,
    *PSYSTEM_MODULE_INFORMATION_ENTRY;

     注意这个调用返回的第一个模块一定是ntoskrnl.exe模块,很多人就是通过这个调用去获取内核模块的信息的。

      1 __int64 __fastcall sub_21DB0(const char *a1)
      2 {
      3   __int64 result; // rax@2
      4   UNICODE_STRING String1; // [sp+20h] [bp-108h]@3
      5   UNICODE_STRING String2; // [sp+30h] [bp-F8h]@12
      6   NTSTATUS v4; // [sp+40h] [bp-E8h]@1
      7   PCWSTR v5; // [sp+48h] [bp-E0h]@1
      8   __int64 v6; // [sp+50h] [bp-D8h]@1
      9   __int64 v7; // [sp+58h] [bp-D0h]@1
     10   __int64 v8; // [sp+60h] [bp-C8h]@1
     11   __int64 v9; // [sp+68h] [bp-C0h]@1
     12   __int64 v10; // [sp+70h] [bp-B8h]@1
     13   unsigned int i; // [sp+78h] [bp-B0h]@1
     14   UNICODE_STRING v12; // [sp+80h] [bp-A8h]@1
     15   UNICODE_STRING v13; // [sp+90h] [bp-98h]@19
     16   STRING v14; // [sp+A0h] [bp-88h]@3
     17   STRING v15; // [sp+B0h] [bp-78h]@8
     18   PCWSTR v16; // [sp+C0h] [bp-68h]@1
     19   __int64 v17; // [sp+C8h] [bp-60h]@1
     20   __int64 v18; // [sp+D0h] [bp-58h]@1
     21   __int64 v19; // [sp+D8h] [bp-50h]@1
     22   UNICODE_STRING UnicodeString; // [sp+E0h] [bp-48h]@8
     23   int j; // [sp+F0h] [bp-38h]@1
     24   PVOID v22; // [sp+F8h] [bp-30h]@1
     25   UNICODE_STRING DestinationString; // [sp+100h] [bp-28h]@1
     26   __int64 v24; // [sp+110h] [bp-18h]@1
     27   PCSZ SourceString; // [sp+130h] [bp+8h]@1
     28 
     29   SourceString = a1;
     30   v24 = 0i64;
     31   v4 = 0;
     32   i = 0;
     33   j = 0;
     34   v5 = L"hal.dll";
     35   v6 = (__int64)L"halacpi.dll";
     36   v7 = (__int64)L"halapic.dll";
     37   v8 = (__int64)L"halmps.dll";
     38   v9 = (__int64)L"halaacpi.dll";
     39   v10 = (__int64)L"halmacpi.dll";
     40   v16 = L"ntoskrnl.exe";
     41   v17 = (__int64)L"ntkrnlpa.exe";
     42   v18 = (__int64)L"ntkrnlmp.exe";
     43   v19 = (__int64)L"ntkrpamp.exe";
     44   v22 = 0i64;
     45   RtlInitUnicodeString(&DestinationString, L"hal.dll");
     46   RtlInitUnicodeString(&v12, L"ntoskrnl.exe");
     47   v22 = sub_260D0(11u);
     48   if ( v22 )
     49   {
     50     RtlInitAnsiString(&v14, SourceString);
     51     v4 = RtlAnsiStringToUnicodeString(&String1, &v14, 1u);
     52     if ( v4 >= 0 )
     53     {
     54       for ( i = 0; ; ++i )
     55       {
     56         if ( i < *(_DWORD *)v22 )
     57         {
     58           RtlInitAnsiString(&v15, (PCSZ)v22 + 296 * i + *((_WORD *)v22 + 148 * i + 23) + 48);
     59           v4 = RtlAnsiStringToUnicodeString(&UnicodeString, &v15, 1u);
     60           if ( v4 < 0 )
     61             continue;
     62           if ( RtlEqualUnicodeString(&String1, &DestinationString, 0) )
     63           {
     64             for ( j = 0; j < 6; ++j )
     65             {
     66               RtlInitUnicodeString(&String2, (&v5)[4 * j]);
     67               if ( RtlEqualUnicodeString(&UnicodeString, &String2, 0) )
     68               {
     69                 v24 = *((_QWORD *)v22 + 37 * i + 3);
     70                 break;
     71               }
     72             }
     73           }
     74           else if ( RtlEqualUnicodeString(&String1, &v12, 0) )
     75           {
     76             for ( j = 0; j < 4; ++j )
     77             {
     78               RtlInitUnicodeString(&v13, (&v16)[4 * j]);
     79               if ( RtlEqualUnicodeString(&UnicodeString, &v13, 0) )
     80               {
     81                 v24 = *((_QWORD *)v22 + 37 * i + 3);
     82                 break;
     83               }
     84             }
     85           }
     86           else if ( RtlEqualUnicodeString(&String1, &UnicodeString, 0) )
     87           {
     88             v24 = *((_QWORD *)v22 + 37 * i + 3);
     89           }
     90           RtlFreeUnicodeString(&UnicodeString);
     91           if ( !v24 )
     92             continue;
     93         }
     94         break;
     95       }
     96       RtlFreeUnicodeString(&String1);
     97       sub_199F0(v22);
     98       result = v24;
     99     }
    100     else
    101     {
    102       result = 0i64;
    103     }
    104   }
    105   else
    106   {
    107     result = 0i64;
    108   }
    109   return result;
    110 }

    这个是遍历刚才得到的结果,就是刚才得到的SYSTEM_MODULE_INFORMATION结构。如果要得到的目标模块是nt内核模块或是hal.dll的话就特殊处理

    0x1

    接下来就是进入正题了,来看看PT的分发例程,在看分发例程之前先总结下,如下图

    图中的真正的功能函数就是我们要分析的重点,PT的大部分功能都在这里完成。

    0x2

    我们来看switch语句,这个语句由最后的一个 DbgPrint("[kEvP64] Unknown IOCTL: 0x%X (%04X,%04X) ", v37, (v37 & 0xFFFF0000) >> 16, (v37 >> 2) & 0xFFF);就可以看出是DeviceIoControl函数来发送的一些自定义的IOCTL。但是我们没有办法知道具体的含义,因为这些都是自定义的,在C中定义IOCTL也只是用一个宏来完成。

    来看下这里

    1 //IDA伪代码  
    2 Irp = a2;
    3 v35 = -1073741808;
    4 v27 = 0i64;
    5 v28 = sub_11100((__int64)a2);

    注意第5行的sub_11100,参数a2是Irp指针,它的反汇编如下图

    只是一个简单的移位操作是吧。我猜这个应该就是IoGetCurrentIrpStackLocation()这个函数,可见IRP中是存有当前IRP栈的指针的。首先是对比Irp栈的总层数是不是大于当前层数,然后就是取出当前栈的指针(这个指针在Irp结构中)返回了。

     而我们常用的操作就是

    PIO_STACK_LOCATION irpSp;
    IoControlCode=irpSp->Parameters.DeviceIoControl.IoControlCode;
    switch(IoControlCode)
    {
    ……  
    }
  • 相关阅读:
    html5+css3中的background: -moz-linear-gradient 用法 (转载)
    CentOS 安装Apache服务
    Linux 笔记
    CURL 笔记
    Spring Application Context文件没有提示功能解决方法
    LeetCode 389. Find the Difference
    LeetCode 104. Maximum Depth of Binary Tree
    LeetCode 520. Detect Capital
    LeetCode 448. Find All Numbers Disappeared in an Array
    LeetCode 136. Single Number
  • 原文地址:https://www.cnblogs.com/Ox9A82/p/5520166.html
Copyright © 2011-2022 走看看