• 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)
    {
    ……  
    }
  • 相关阅读:
    ZwQuerySystemInformation的用法
    将十进制整型数转成 2~36(不包含10) 进制数
    简化版C语言文法 130
    Python基础综合练习 130
    编译原理 130
    词法分析 130
    熟悉常用的Linux操作 130
    129有确定性的有穷自动机 130
    实验一.词法分析实验 130
    1.大 数据概述 130
  • 原文地址:https://www.cnblogs.com/Ox9A82/p/5520166.html
Copyright © 2020-2023  润新知