首页
社区
课程
招聘
[原创] 精确逆向windows未公开函数 RtlpGetAssemblyStorageMapRootLocation
发表于: 2022-6-7 15:34 15788

[原创] 精确逆向windows未公开函数 RtlpGetAssemblyStorageMapRootLocation

2022-6-7 15:34
15788

精确逆向未公开的windows内部函数RtlpGetAssemblyStorageMapRootLocation的源代码。截止2022年5月30日,该函数没有在网络上找到任何有效的公开信息。

从函数名称推测,函数的功能是获取程序集存储映射的根位置。 借助IDA Pro,分析该函数的参数、局部变量和相关调用。详细IDA Pro反汇编代码请访问 https://gitee.com/asminlife/rtlp-get-assembly-storage-map-root-location-reversing/blob/master/%E5%8F%8D%E6%B1%87%E7%BC%96%E4%BB%A3%E7%A0%81.asm

函数的相关调用

这些错误信息表明,函数可能通过查询注册表键值来获得程序集的位置信息。

第一个参数先被放在eax中,随后 arg_0 的值给了RootDirectory ,根据_OBJECT_ATTRIBUTES结构的定义,可以确定arg_0是HANDLE类型,它是一个根对象目录句柄。

第二个参数移动到ecx,随后它被保存在局部变量var_224,最后var_224的地址传递给了ObjectAttributes.ObjectName所以第二个参数是对象名称,根据 _OBJECT_ATTRIBUTES结构的定义,它是PUNICODE_STRING类型

观察这些指令对第三个参数arg_8的操作,表明它是一个32位指针,暂时不明确类型。

初步判断,函数应该是通过传递根对象目录句柄、对象名称和一个未知指针参数来获取程序集的位置。

这段代码主要是初始化一些局部变量,把对象名称存储到var_224,然后开始检查参数。 任意一个参数为0,则函数退出,并返回一个错误代码。以下是代码还原:

这段代码主要是对ObjectAttributes结构的成员进行初始化,用第一个参数作为对象目录句柄,第二个参数作为对象名称。随后调用ZwOpenKey函数打开对象arg_4的注册表项,以下是代码还原:

这段代码调用ZwQueryValueKey函数,以下是MSDN上的函数说明

调用ZwQueryValueKey函数时,第三个参数是一个枚举变量,它在KEY_VALUE_INFORMATION_CLASS中定义。它确定了第四个参数 KeyValueInformation 缓冲区中返回的信息的类型。 调用时向KeyValueInformationClass传递的实际参数为数值2,所以我们可以确定第四个参数KeyValueInformation指向一个KEY_VALUE_PARTIAL_INFORMATION结构体变量。 此外,stru_7DF1C658被发现是一个在函数外部定义的LSA_UNICODE_STRING结构体变量,里面保存的是注册表的键"Location", 现在我们可以确认之前的猜测,函数确实是通过查询注册表键值来获得程序集的位置信息。 根据ZwQueryValueKey的最后一个参数信息,修改局部变量ResultLength的类型为ULONG。 以下是代码还原:

如果调用ZwOpenKey失败,则跳转到.text:7DF1C534 ,如果调用ZwQueryValueKey失败则跳转到.text:7DF1C56E,两个代码段处理的目的都是为了打印错误消息,并跳转到程序结尾loc_7DF1C631。这里列出代码详细逻辑:

在前面调用ZwQueryValueKey的第三个参数(KeyValueInformationClass)时我们看到,它指出了KeyValueInformation的类型信息, KeyValueInformationClass的实际参数的值为2。根据函数ZwQueryValueKey的说明,这个值是枚举类型KEY_VALUE_INFORMATION_CLASS定义的, 参考定义我们得出KEY_VALUE_INFORMATION_CLASS的值2对应的项为为KEY_VALUE_PARTIAL_INFORMATION。也就是说,KeyValueInformation指向一个 KEY_VALUE_PARTIAL_INFORMATION结构体变量。到这里,我们已经可以完全的推断出KeyValueInformation附近几个局部变量的数据类型和含义了。

回顾IDA Pro给出的局部变量分析:

结合KEY_VALUE_PARTIAL_INFORMATION结构体的定义,我们可以得出

KeyValueInformation中保存着键值和相关信息,是本函数的关键数据结构。

指令比较了KeyValueInformation->Type值和1是否相等,根据winnt.h中对KeyValueInformation->Type值的宏定义, 指令的意图在于测试获得的键值是否为unicode空终止字符串。如果不是,则调用DbgPrintEx输出错误信息。(错误信息aSxsAssemblySto_1的内容也印证了这个推断) 至此,代码还原如下:

如果键值是unicode空终止字符串,则程序跳转到loc_7DF1C59B。这段代码检查了Size也就是KeyValueInformation->DataLength的值,DataLength描述的是以字节为单位的数据长度。指令使用了al和1进行测试, 实际上是对比了DataLength的最低位是否为1,如果为1,则表明它是一个单数。而微软保存unicode字符的类型是一个16位utf-16的类型。 也就是说,无论保存的键值长度是多少,它的字节数都为偶数。在这里测试最低位是否为单数,再根据错误消息aSxsAssemblySto_3[] = "SXS: Assembly storage root location value has non-even size"的定义,编写者似乎在确认键值的unicode规范性。 代码还原如下:

如果键值的unicode规范性OK,则程序跳转到loc_7DF1C5BC。这里首先分析数据的类型,因为这段代码的指令对数据的操作让人感到很疑惑。

指令明确的告诉我们,arg_8(ESI)指向的是一个2字节的数据,考虑到之后的比较指令 是jbe,则arg_8指向的可能是一个2字节的unsigned short int变量,因为被比较的数是ULONG类型。

指令告诉我们,arg_8+2指向的也是一个2字节的,它也可能是unsigned short int的变量。

再分析这段代码的逻辑结构:

这里的esi是参数arg_8,代码把arg_8+2处的2个字节扩展并传送到ecx 接下来的一条指令

,这里的eax是KeyValueInformation.DataLength(ULONG类型) 代码编写者试图对比两个变量的大小。如果DataLength更大,则将DataLength和0FFFEh进行对比,如果它仍然大于0FFFEh,则打印错误消息 并返回错误代码。考虑到windows径的最大长度为MAX_PATH,定义为 260 个字符,除去驱动器标识x:\和空结尾,则最大长度为0xFFFE,代码应该 在测试路径是否越过最大的长度。根据错误消息aSxsAssemblySto_0的提示,也可以确认这一点。

如果DataLength比arg_8+2更小或相等,则程序会跳转到loc_7DF1C60B,调用memcpy函数把键值拷贝 到arg_8+4指向的指针(arg_8指向的是一个重要的数据结构),随后代码将DataLength的低16位拷贝到 arg_8, 并返回0表示函数成功。

如果DataLength比arg_8+2更大,但小于等于0xFFFE,则程序跳转到loc_7DF1C5E9,将DataLength的低16位拷贝到arg_8+2。 随后调用未公开的函数RtlpAllocateEnvBlock 分配DataLength低16位的数量的线程环境块TEB,由于RtlpAllocateEnvBlock没有公开信息,目前只是对函数功能的推测。最后,代码 检查RtlpAllocateEnvBlock是否调用成功,如果成功则程序跳转到loc_7DF1C60B,调用memcpy函数把键值拷贝 到arg_8+4指向的指针(进一步确认了arg_8指向的是一个重要数据结构),随后代码将DataLength的低16位拷贝到 arg_8, 并返回0表示函数成功。

至此,整个函数逆向分析工作已经全部完成,函数通过打开对象的注册表项,查询注册表键Location的值来获取程序集的路径。在获取路径之后,对路径字符串进行了一系列的unicode检查。如果路径字符串合规,则将键值DataLength和参数arg_8指向的前4个字节进行一系列对比,并根据对比结果进行相关数据操作。最终,程序集的路径字符串被拷贝到arg_8+4指向的地址,函数返回0。其中,RtlpAllocateEnvBlock函数的功能仍然是一个迷,arg_8指向的详细数据结构也仍然是一个迷。但是,目前不再深究这些谜题的答案。完整的还原代码请访问https://gitee.com/asminlife/rtlp-get-assembly-storage-map-root-location-reversing/blob/master/%E8%BF%98%E5%8E%9F%E4%BB%A3%E7%A0%81.c

ObjectAttributes= _OBJECT_ATTRIBUTES ptr -240h
ResultLength= dword ptr -228h
var_224= dword ptr -224h
KeyHandle= dword ptr -220h
KeyValueInformation= byte ptr -21Ch
var_218= dword ptr -218h
Size= dword ptr -214h
Src= byte ptr -210h
var_4= dword ptr -4
arg_0= dword ptr  8
arg_4= dword ptr  0Ch
arg_8= dword ptr  10h
ObjectAttributes= _OBJECT_ATTRIBUTES ptr -240h
ResultLength= dword ptr -228h
var_224= dword ptr -224h
KeyHandle= dword ptr -220h
KeyValueInformation= byte ptr -21Ch
var_218= dword ptr -218h
Size= dword ptr -214h
Src= byte ptr -210h
var_4= dword ptr -4
arg_0= dword ptr  8
arg_4= dword ptr  0Ch
arg_8= dword ptr  10h
.text:7DF1C529    call    _ZwOpenKey@12; ZwOpenKey(x,x,x)
.text:7DF1C563    call    _ZwQueryValueKey@24; ZwQueryValueKey(x,x,x,x,x,x)
.text:7DF1C57E    call    _DbgPrintEx
.text:7DF1C5AD    call    _DbgPrintEx
.text:7DF1C5DA    call    _DbgPrintEx
.text:7DF1C5F1    call    ds:_RtlAllocateStringRoutine; RtlpAllocateEnvBlock(x)
.text:7DF1C616    call    _memcpy
.text:7DF1C63F    call    _NtClose@4; NtClose(x)
.text:7DF1C64E    call    @__security_check_cookie@4; __security_check_cookie(x)
.text:7DF1C529    call    _ZwOpenKey@12; ZwOpenKey(x,x,x)
.text:7DF1C563    call    _ZwQueryValueKey@24; ZwQueryValueKey(x,x,x,x,x,x)
.text:7DF1C57E    call    _DbgPrintEx
.text:7DF1C5AD    call    _DbgPrintEx
.text:7DF1C5DA    call    _DbgPrintEx
.text:7DF1C5F1    call    ds:_RtlAllocateStringRoutine; RtlpAllocateEnvBlock(x)
.text:7DF1C616    call    _memcpy
.text:7DF1C63F    call    _NtClose@4; NtClose(x)
.text:7DF1C64E    call    @__security_check_cookie@4; __security_check_cookie(x)
'SXS: Unable to open storage root subkey %wZ; Status = 0x%08lx',0Ah
'SXS: Unabel to query location from storage root subkey %wZ; Statu'    //微软工程师把Unable写成了Unabel
'SXS: Assembly storage root location value type is not REG_SZ',0Ah
'SXS: Assembly storage root location for %wZ does not fit in a UNICODE STRING'
'SXS: Assembly storage root location value has non-even size',0Ah,0
'SXS: Unable to open storage root subkey %wZ; Status = 0x%08lx',0Ah
'SXS: Unabel to query location from storage root subkey %wZ; Statu'    //微软工程师把Unable写成了Unabel
'SXS: Assembly storage root location value type is not REG_SZ',0Ah
'SXS: Assembly storage root location for %wZ does not fit in a UNICODE STRING'
'SXS: Assembly storage root location value has non-even size',0Ah,0
.text:7DF1C4AF                 mov     eax, [ebp+arg_0]       
.text:7DF1C4E7                 mov     [ebp+ObjectAttributes.RootDirectory], eax
.text:7DF1C4AF                 mov     eax, [ebp+arg_0]       
.text:7DF1C4E7                 mov     [ebp+ObjectAttributes.RootDirectory], eax
.text:7DF1C4B2                 mov     ecx, [ebp+arg_4]
.text:7DF1C4BD                 mov     [ebp+var_224], ecx
.text:7DF1C4ED                 lea     eax, [ebp+var_224]
.text:7DF1C4F3                 mov     [ebp+ObjectAttributes.ObjectName], eax
.text:7DF1C4B2                 mov     ecx, [ebp+arg_4]
.text:7DF1C4BD                 mov     [ebp+var_224], ecx
.text:7DF1C4ED                 lea     eax, [ebp+var_224]
.text:7DF1C4F3                 mov     [ebp+ObjectAttributes.ObjectName], eax
.text:7DF1C4B9                 mov     esi, [ebp+arg_8]
.text:7DF1C5BC                 movzx   ecx, word ptr [esi+2]
.text:7DF1C5E9                 mov     [esi+2], ax
.text:7DF1C5F7                 mov     [esi+4], eax
.text:7DF1C4B9                 mov     esi, [ebp+arg_8]
.text:7DF1C5BC                 movzx   ecx, word ptr [esi+2]
.text:7DF1C5E9                 mov     [esi+2], ax
.text:7DF1C5F7                 mov     [esi+4], eax
HANDLE    arg_0,           //根对象目录句柄
PUNICODE_STRING    arg_4,  //对象名称
ptr_32    arg_8;          //未知指针
HANDLE    arg_0,           //根对象目录句柄
PUNICODE_STRING    arg_4,  //对象名称
ptr_32    arg_8;          //未知指针
.text:7DF1C49A ; __stdcall RtlpGetAssemblyStorageMapRootLocation(x, x, x)
.text:7DF1C49A _RtlpGetAssemblyStorageMapRootLocation@12 proc near
.text:7DF1C49A                                         ; CODE XREF: RtlpAssemblyStorageMapResolutionDefaultCallback(x,x,x)+2D255↑p
.text:7DF1C49A
.text:7DF1C49A ObjectAttributes= _OBJECT_ATTRIBUTES ptr -240h
.text:7DF1C49A ResultLength    = dword ptr -228h
.text:7DF1C49A var_224           = dword ptr -224h
.text:7DF1C49A KeyHandle       = dword ptr -220h
.text:7DF1C49A KeyValueInformation= byte ptr -21Ch
.text:7DF1C49A var_218         = dword ptr -218h
.text:7DF1C49A Size            = dword ptr -214h
.text:7DF1C49A Src             = byte ptr -210h
.text:7DF1C49A var_4           = dword ptr -4
.text:7DF1C49A arg_0           = dword ptr  8
.text:7DF1C49A arg_4           = dword ptr  0Ch
.text:7DF1C49A arg_8           = dword ptr  10h
.text:7DF1C49A
.text:7DF1C49A                 mov     edi, edi
.text:7DF1C49C                 push    ebp
.text:7DF1C49D                 mov     ebp, esp
.text:7DF1C49F                 sub     esp, 240h
.text:7DF1C4A5                 mov     eax, ___security_cookie
.text:7DF1C4AA                 xor     eax, ebp
.text:7DF1C4AC                 mov     [ebp+security_cookie], eax    ;var_4
.text:7DF1C4AF                 mov     eax, [ebp+arg_0] ; eax = arg_0 , HANDLE
.text:7DF1C4B2                 mov     ecx, [ebp+arg_4] ; ecx = arg_4 ,对象名称
.text:7DF1C4B5                 push    ebx
.text:7DF1C4B6                 xor     ebx, ebx        ; ebx = 0
.text:7DF1C4B8                 push    esi
.text:7DF1C4B9                 mov     esi, [ebp+arg_8] ; esi = arg_8 ,指针
.text:7DF1C4BC                 push    edi
.text:7DF1C4BD                 mov     [ebp+var_224], ecx
.text:7DF1C4C3                 mov     [ebp+KeyHandle], ebx
.text:7DF1C4C9                 mov     [ebp+ResultLength], ebx
.text:7DF1C4CF                 cmp     eax, ebx
.text:7DF1C4D1                 jz      loc_7DF1C62C
.text:7DF1C4D7                 cmp     ecx, ebx
.text:7DF1C4D9                 jz      loc_7DF1C62C
.text:7DF1C4DF                 cmp     esi, ebx
.text:7DF1C4E1                 jz      loc_7DF1C62C
.text:7DF1C49A ; __stdcall RtlpGetAssemblyStorageMapRootLocation(x, x, x)
.text:7DF1C49A _RtlpGetAssemblyStorageMapRootLocation@12 proc near
.text:7DF1C49A                                         ; CODE XREF: RtlpAssemblyStorageMapResolutionDefaultCallback(x,x,x)+2D255↑p
.text:7DF1C49A
.text:7DF1C49A ObjectAttributes= _OBJECT_ATTRIBUTES ptr -240h
.text:7DF1C49A ResultLength    = dword ptr -228h
.text:7DF1C49A var_224           = dword ptr -224h
.text:7DF1C49A KeyHandle       = dword ptr -220h
.text:7DF1C49A KeyValueInformation= byte ptr -21Ch
.text:7DF1C49A var_218         = dword ptr -218h
.text:7DF1C49A Size            = dword ptr -214h
.text:7DF1C49A Src             = byte ptr -210h
.text:7DF1C49A var_4           = dword ptr -4
.text:7DF1C49A arg_0           = dword ptr  8
.text:7DF1C49A arg_4           = dword ptr  0Ch
.text:7DF1C49A arg_8           = dword ptr  10h
.text:7DF1C49A
.text:7DF1C49A                 mov     edi, edi
.text:7DF1C49C                 push    ebp
.text:7DF1C49D                 mov     ebp, esp
.text:7DF1C49F                 sub     esp, 240h
.text:7DF1C4A5                 mov     eax, ___security_cookie
.text:7DF1C4AA                 xor     eax, ebp
.text:7DF1C4AC                 mov     [ebp+security_cookie], eax    ;var_4
.text:7DF1C4AF                 mov     eax, [ebp+arg_0] ; eax = arg_0 , HANDLE
.text:7DF1C4B2                 mov     ecx, [ebp+arg_4] ; ecx = arg_4 ,对象名称
.text:7DF1C4B5                 push    ebx
.text:7DF1C4B6                 xor     ebx, ebx        ; ebx = 0
.text:7DF1C4B8                 push    esi
.text:7DF1C4B9                 mov     esi, [ebp+arg_8] ; esi = arg_8 ,指针
.text:7DF1C4BC                 push    edi
.text:7DF1C4BD                 mov     [ebp+var_224], ecx
.text:7DF1C4C3                 mov     [ebp+KeyHandle], ebx
.text:7DF1C4C9                 mov     [ebp+ResultLength], ebx
.text:7DF1C4CF                 cmp     eax, ebx
.text:7DF1C4D1                 jz      loc_7DF1C62C
.text:7DF1C4D7                 cmp     ecx, ebx
.text:7DF1C4D9                 jz      loc_7DF1C62C
.text:7DF1C4DF                 cmp     esi, ebx
.text:7DF1C4E1                 jz      loc_7DF1C62C
extern dword security_cookie = 0BB40E64Eh;                        //var_4,在外部定义的未知类型变量,大小为dword
 
// 返回值是某种错误代码类型,大小为dword
dword RtlpGetAssemblyStorageMapRootLocation(HANDLE arg_0, PUNICODE_STRING arg_4, ptr_32 arg_8)
{
    PUNICODE_STRING    temp_arg_4    = arg_4;       
    HANDLE            KeyHandle    = 0;
    PULONG            ResultLength    = 0;
 
    if (arg_0 == 0 || arg_4 == 0 || arg_8 == 0) {                // 任意参数为空则函数退出,并跳转到loc_7DF1C62C
        if(KeyHandle != 0)                       
            NtClose(KeyHandle);
        __security_check_cookie(security_cookie);           
        return 0C000000Dh;
    }
}
extern dword security_cookie = 0BB40E64Eh;                        //var_4,在外部定义的未知类型变量,大小为dword
 
// 返回值是某种错误代码类型,大小为dword
dword RtlpGetAssemblyStorageMapRootLocation(HANDLE arg_0, PUNICODE_STRING arg_4, ptr_32 arg_8)
{
    PUNICODE_STRING    temp_arg_4    = arg_4;       
    HANDLE            KeyHandle    = 0;
    PULONG            ResultLength    = 0;
 
    if (arg_0 == 0 || arg_4 == 0 || arg_8 == 0) {                // 任意参数为空则函数退出,并跳转到loc_7DF1C62C
        if(KeyHandle != 0)                       
            NtClose(KeyHandle);
        __security_check_cookie(security_cookie);           
        return 0C000000Dh;
    }
}
.text:7DF1C4E7                 mov     [ebp+ObjectAttributes.RootDirectory], eax
.text:7DF1C4ED                 lea     eax, [ebp+var_224]
.text:7DF1C4F3                 mov     [ebp+ObjectAttributes.ObjectName], eax
.text:7DF1C4F9                 lea     eax, [ebp+ObjectAttributes]
.text:7DF1C4FF                 push    eax             ; ObjectAttributes
.text:7DF1C500                 push    1               ; DesiredAccess
.text:7DF1C502                 lea     eax, [ebp+KeyHandle]
.text:7DF1C508                 push    eax             ; KeyHandle
.text:7DF1C509                 mov     [ebp+ObjectAttributes.Length], 18h
.text:7DF1C513                 mov     [ebp+ObjectAttributes.Attributes], 40h ; '@'
.text:7DF1C51D                 mov     [ebp+ObjectAttributes.SecurityDescriptor], ebx
.text:7DF1C523                 mov     [ebp+ObjectAttributes.SecurityQualityOfService], ebx
.text:7DF1C529                 call    _ZwOpenKey@12   ; ZwOpenKey(x,x,x)
.text:7DF1C52E                 mov     edi, eax
.text:7DF1C530                 cmp     edi, ebx
.text:7DF1C532                 jge     short loc_7DF1C543
.text:7DF1C4E7                 mov     [ebp+ObjectAttributes.RootDirectory], eax
.text:7DF1C4ED                 lea     eax, [ebp+var_224]
.text:7DF1C4F3                 mov     [ebp+ObjectAttributes.ObjectName], eax
.text:7DF1C4F9                 lea     eax, [ebp+ObjectAttributes]
.text:7DF1C4FF                 push    eax             ; ObjectAttributes
.text:7DF1C500                 push    1               ; DesiredAccess
.text:7DF1C502                 lea     eax, [ebp+KeyHandle]
.text:7DF1C508                 push    eax             ; KeyHandle
.text:7DF1C509                 mov     [ebp+ObjectAttributes.Length], 18h
.text:7DF1C513                 mov     [ebp+ObjectAttributes.Attributes], 40h ; '@'
.text:7DF1C51D                 mov     [ebp+ObjectAttributes.SecurityDescriptor], ebx
.text:7DF1C523                 mov     [ebp+ObjectAttributes.SecurityQualityOfService], ebx
.text:7DF1C529                 call    _ZwOpenKey@12   ; ZwOpenKey(x,x,x)
.text:7DF1C52E                 mov     edi, eax
.text:7DF1C530                 cmp     edi, ebx
.text:7DF1C532                 jge     short loc_7DF1C543
OBJECT_ATTRIBUTES ObjectAttributes;
ObjectAttributes.RootDirectory                = arg_0;            //根对象目录句柄
ObjectAttributes.ObjectName                    = &temp_arg_4;        //对象名称,arg_4
ObjectAttributes.Length                        = 0x18;
ObjectAttributes.Attributes                    = 0x40;                //使用不区分大小写的方式比较对象名称
ObjectAttributes.SecurityDescriptor            = 0;
ObjectAttributes.SecurityQualityOfService    = 0;
 
if (ZwOpenKey(&KeyHandle, 1, ObjectAttributes) >= 0) {            //打开注册表项
    //跳转到loc_7DF1C543
}
OBJECT_ATTRIBUTES ObjectAttributes;
ObjectAttributes.RootDirectory                = arg_0;            //根对象目录句柄
ObjectAttributes.ObjectName                    = &temp_arg_4;        //对象名称,arg_4
ObjectAttributes.Length                        = 0x18;
ObjectAttributes.Attributes                    = 0x40;                //使用不区分大小写的方式比较对象名称
ObjectAttributes.SecurityDescriptor            = 0;
ObjectAttributes.SecurityQualityOfService    = 0;
 
if (ZwOpenKey(&KeyHandle, 1, ObjectAttributes) >= 0) {            //打开注册表项
    //跳转到loc_7DF1C543
}
.text:7DF1C543 loc_7DF1C543: 
.text:7DF1C543                 lea     eax, [ebp+ResultLength]
.text:7DF1C549                 push    eax             ; ResultLength
.text:7DF1C54A                 push    218h            ; Length
.text:7DF1C54F                 lea     eax, [ebp+KeyValueInformation]
.text:7DF1C555                 push    eax             ; KeyValueInformation
.text:7DF1C556                 push    2               ; KeyValueInformationClass
.text:7DF1C558                 push    offset stru_7DF1C658 ; ValueName
.text:7DF1C55D                 push    [ebp+KeyHandle] ; KeyHandle
.text:7DF1C563                 call    _ZwQueryValueKey@24 ; ZwQueryValueKey(x,x,x,x,x,x)
.text:7DF1C568                 mov     edi, eax
.text:7DF1C56A                 cmp     edi, ebx
.text:7DF1C56C                 jge     short loc_7DF1C58B
.text:7DF1C543 loc_7DF1C543: 
.text:7DF1C543                 lea     eax, [ebp+ResultLength]
.text:7DF1C549                 push    eax             ; ResultLength
.text:7DF1C54A                 push    218h            ; Length
.text:7DF1C54F                 lea     eax, [ebp+KeyValueInformation]
.text:7DF1C555                 push    eax             ; KeyValueInformation
.text:7DF1C556                 push    2               ; KeyValueInformationClass
.text:7DF1C558                 push    offset stru_7DF1C658 ; ValueName
.text:7DF1C55D                 push    [ebp+KeyHandle] ; KeyHandle
.text:7DF1C563                 call    _ZwQueryValueKey@24 ; ZwQueryValueKey(x,x,x,x,x,x)
.text:7DF1C568                 mov     edi, eax
.text:7DF1C56A                 cmp     edi, ebx
.text:7DF1C56C                 jge     short loc_7DF1C58B
NTSYSAPI NTSTATUS ZwQueryValueKey(
  [in]            HANDLE                      KeyHandle,                //键句柄
  [in]            PUNICODE_STRING             ValueName,                //键值名称
  [in]            KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,    //确定 KeyValueInformation 缓冲区中返回的信息的类型
  [out, optional] PVOID                       KeyValueInformation,        //接收请求信息的指针
  [in]            ULONG                       Length,                    //指定 KeyValueInformation 缓冲区的大小(以字节为单位)
  [out]           PULONG                      ResultLength
);
NTSYSAPI NTSTATUS ZwQueryValueKey(
  [in]            HANDLE                      KeyHandle,                //键句柄
  [in]            PUNICODE_STRING             ValueName,                //键值名称
  [in]            KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,    //确定 KeyValueInformation 缓冲区中返回的信息的类型
  [out, optional] PVOID                       KeyValueInformation,        //接收请求信息的指针
  [in]            ULONG                       Length,                    //指定 KeyValueInformation 缓冲区的大小(以字节为单位)
  [out]           PULONG                      ResultLength
);
#include <lsalookup.h>                            //LSA_UNICODE_STRING结构体头文件
 
extern LSA_UNICODE_STRING stru_7DF1C658 = { 0x10, 0x12, L"Location" };
 
 
    PUNICODE_STRING        temp_arg_4 = arg_4;            //保存对象名称
    HANDLE                KeyHandle = 0;
    ULONG                ResultLength = 0;
    PVOID                KeyValueInformation;       
 
        //返回注册表键Location的值
        //KeyValueInformation返回一个KEY_VALUE_PARTIAL_INFORMATION结构的指针,就是location信息
 
        if (ZwQueryValueKey(KeyHandle, stru_7DF1C658, 2, &KeyValueInformation, 0x218, &ResultLength) >= 0) {
            //跳转到loc_7DF1C58B
        }
#include <lsalookup.h>                            //LSA_UNICODE_STRING结构体头文件
 
extern LSA_UNICODE_STRING stru_7DF1C658 = { 0x10, 0x12, L"Location" };
 
 
    PUNICODE_STRING        temp_arg_4 = arg_4;            //保存对象名称
    HANDLE                KeyHandle = 0;
    ULONG                ResultLength = 0;
    PVOID                KeyValueInformation;       
 
        //返回注册表键Location的值
        //KeyValueInformation返回一个KEY_VALUE_PARTIAL_INFORMATION结构的指针,就是location信息
 
        if (ZwQueryValueKey(KeyHandle, stru_7DF1C658, 2, &KeyValueInformation, 0x218, &ResultLength) >= 0) {
            //跳转到loc_7DF1C58B
        }
.text:7DF1C534                 push    edi
.text:7DF1C535                 lea     eax, [ebp+var_224]
.text:7DF1C53B                 push    eax
.text:7DF1C53C                 push    offset aSxsUnableToOpe ; "SXS: Unable to open storage root subkey"...
.text:7DF1C541                 jmp     short loc_7DF1C57B
.text:7DF1C534                 push    edi
.text:7DF1C535                 lea     eax, [ebp+var_224]
.text:7DF1C53B                 push    eax
.text:7DF1C53C                 push    offset aSxsUnableToOpe ; "SXS: Unable to open storage root subkey"...
.text:7DF1C541                 jmp     short loc_7DF1C57B
.text:7DF1C56E                 push    edi
.text:7DF1C56F                 lea     eax, [ebp+var_224]
.text:7DF1C575                 push    eax
.text:7DF1C576                 push    offset aSxsUnabelToQue ; "SXS: Unabel to query location from stor"...
.text:7DF1C56E                 push    edi
.text:7DF1C56F                 lea     eax, [ebp+var_224]
.text:7DF1C575                 push    eax
.text:7DF1C576                 push    offset aSxsUnabelToQue ; "SXS: Unabel to query location from stor"...
.text:7DF1C57B loc_7DF1C57B:                           ; CODE XREF: RtlpGetAssemblyStorageMapRootLocation(x,x,x)+A7↑j
.text:7DF1C57B                 push    ebx             ; Level
.text:7DF1C57C                 push    33h ; '3'       ; ComponentId
.text:7DF1C57E                 call    _DbgPrintEx
.text:7DF1C583                 add     esp, 14h
.text:7DF1C586                 jmp     loc_7DF1C631
.text:7DF1C57B loc_7DF1C57B:                           ; CODE XREF: RtlpGetAssemblyStorageMapRootLocation(x,x,x)+A7↑j
.text:7DF1C57B                 push    ebx             ; Level
.text:7DF1C57C                 push    33h ; '3'       ; ComponentId
.text:7DF1C57E                 call    _DbgPrintEx
.text:7DF1C583                 add     esp, 14h
.text:7DF1C586                 jmp     loc_7DF1C631
#include <ntdef.h>                                            //OBJECT_ATTRIBUTES结构体头文件
#include <lsalookup.h>                                        //LSA_UNICODE_STRING结构体头文件
#include <Wdm.h>                                            //DbgPrintEx函数头文件
 
extern dword security_cookie            = 0xBB40E64E;        // var_4,值来自在外部定义的未知类型变量___security_cookie
extern LSA_UNICODE_STRING stru_7DF1C658 = { 0x10, 0x12, L"Location" };
extern const char aSxsUnableToOpe[]        = "SXS: Unable to open storage root subkey %wZ; Status = 0x%08lx\n";
extern const char aSxsUnabelToQue[]        = "SXS: Unabel to query location from storage root subkey %wZ; Statu";
 
// 返回值是某种错误代码类型,大小为dword
dword RtlpGetAssemblyStorageMapRootLocation(HANDLE arg_0,            //根对象目录句柄
                                            PUNICODE_STRING arg_4,    //对象名称
                                            ptr_32 arg_8)            //未知指针
{
    dword                return_code                = 0;                // 函数返回代码
    PUNICODE_STRING        temp_arg_4                = arg_4;            // 对象名称
    HANDLE                KeyHandle                = 0;
    ULONG                ResultLength            = 0;
    PVOID                KeyValueInformation        = NULL;                // 指向注册表键值信息
    OBJECT_ATTRIBUTES    ObjectAttributes;
    ObjectAttributes.RootDirectory                = arg_0;            // 根对象目录句柄
    ObjectAttributes.ObjectName                    = &temp_arg_4;        // 对象名称,arg_4
    ObjectAttributes.Length                        = 0x18;
    ObjectAttributes.Attributes                    = 0x40;                // 使用不区分大小写的方式比较对象名称
    ObjectAttributes.SecurityDescriptor            = 0;
    ObjectAttributes.SecurityQualityOfService    = 0;
 
 
    if (arg_0 != 0 && arg_4 != 0 && arg_8 != 0) {                                // 参数检查
 
        return_code = ZwOpenKey(&KeyHandle, 1, ObjectAttributes);                // 打开注册表项
        if (return_code < 0)
            DbgPrintEx(0x33, 0, aSxsUnableToOpe, &temp_arg_4, return_code);        // 打开注册表项失败,打印错误消息
        else {                                                                    // 成功打开,获取注册表键Location的值
 
            return_code = ZwQueryValueKey(KeyHandle, stru_7DF1C658, 2, &KeyValueInformation, 0x218, &ResultLength);
            if (return_code < 0)
                DbgPrintEx(0x33, 0, aSxsUnabelToQue, &temp_arg_4, return_code);    //查询键值失败,打印错误消息
            else {
                //跳转到loc_7DF1C58B
            }
        }
    }
    else
        return_code = 0xC000000D;
 
    if (KeyHandle != 0)                                                            // 程序退出,loc_7DF1C631
        NtClose(KeyHandle);
    __security_check_cookie(security_cookie);
    return return_code;
}
#include <ntdef.h>                                            //OBJECT_ATTRIBUTES结构体头文件
#include <lsalookup.h>                                        //LSA_UNICODE_STRING结构体头文件
#include <Wdm.h>                                            //DbgPrintEx函数头文件
 
extern dword security_cookie            = 0xBB40E64E;        // var_4,值来自在外部定义的未知类型变量___security_cookie
extern LSA_UNICODE_STRING stru_7DF1C658 = { 0x10, 0x12, L"Location" };
extern const char aSxsUnableToOpe[]        = "SXS: Unable to open storage root subkey %wZ; Status = 0x%08lx\n";
extern const char aSxsUnabelToQue[]        = "SXS: Unabel to query location from storage root subkey %wZ; Statu";
 
// 返回值是某种错误代码类型,大小为dword
dword RtlpGetAssemblyStorageMapRootLocation(HANDLE arg_0,            //根对象目录句柄
                                            PUNICODE_STRING arg_4,    //对象名称
                                            ptr_32 arg_8)            //未知指针
{
    dword                return_code                = 0;                // 函数返回代码
    PUNICODE_STRING        temp_arg_4                = arg_4;            // 对象名称
    HANDLE                KeyHandle                = 0;
    ULONG                ResultLength            = 0;
    PVOID                KeyValueInformation        = NULL;                // 指向注册表键值信息
    OBJECT_ATTRIBUTES    ObjectAttributes;
    ObjectAttributes.RootDirectory                = arg_0;            // 根对象目录句柄
    ObjectAttributes.ObjectName                    = &temp_arg_4;        // 对象名称,arg_4
    ObjectAttributes.Length                        = 0x18;
    ObjectAttributes.Attributes                    = 0x40;                // 使用不区分大小写的方式比较对象名称
    ObjectAttributes.SecurityDescriptor            = 0;
    ObjectAttributes.SecurityQualityOfService    = 0;
 
 
    if (arg_0 != 0 && arg_4 != 0 && arg_8 != 0) {                                // 参数检查
 
        return_code = ZwOpenKey(&KeyHandle, 1, ObjectAttributes);                // 打开注册表项
        if (return_code < 0)
            DbgPrintEx(0x33, 0, aSxsUnableToOpe, &temp_arg_4, return_code);        // 打开注册表项失败,打印错误消息
        else {                                                                    // 成功打开,获取注册表键Location的值
 
            return_code = ZwQueryValueKey(KeyHandle, stru_7DF1C658, 2, &KeyValueInformation, 0x218, &ResultLength);
            if (return_code < 0)
                DbgPrintEx(0x33, 0, aSxsUnabelToQue, &temp_arg_4, return_code);    //查询键值失败,打印错误消息
            else {
                //跳转到loc_7DF1C58B

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2022-6-7 18:59 被mb_yx编辑 ,原因: 修正参数检查的逻辑错误
收藏
免费 5
支持
分享
最新回复 (8)
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
2

NTSTATUS
RtlpGetAssemblyStorageMapRootLocation(
    HANDLE KeyHandle,
    PCUNICODE_STRING SubKeyName,
    PUNICODE_STRING Root
    );

NTSTATUS
RtlpGetAssemblyStorageMapRootLocation(
    HANDLE KeyHandle,
    PCUNICODE_STRING SubKeyName,
    PUNICODE_STRING Root
    )
{
    NTSTATUS Status = STATUS_SUCCESS;
    OBJECT_ATTRIBUTES Obja;
    HANDLE SubKeyHandle = NULL;
    ULONG ResultLength = 0;

    struct {
        KEY_VALUE_PARTIAL_INFORMATION kvpi;
        WCHAR Buffer[DOS_MAX_PATH_LENGTH];
    } ValueData;

    static const WCHAR ValueNameBuffer[] = L"Location";
    static const UNICODE_STRING ValueName = { sizeof(ValueNameBuffer) - sizeof(WCHAR), sizeof(ValueNameBuffer), (PWSTR) ValueNameBuffer };

    if ((KeyHandle == NULL) ||
        (SubKeyName == NULL) ||
        (Root == NULL)) {
        Status = STATUS_INVALID_PARAMETER;
        goto Exit;
    }

    InitializeObjectAttributes(
        &Obja,
        (PUNICODE_STRING) &SubKeyName,
        OBJ_CASE_INSENSITIVE,
        KeyHandle,
        NULL);

    Status = NtOpenKey(&SubKeyHandle, KEY_QUERY_VALUE, &Obja);
    if (!NT_SUCCESS(Status)) {
        DbgPrintEx(
            DPFLTR_SXS_ID,
            DPFLTR_ERROR_LEVEL,
            "SXS: Unable to open storage root subkey %wZ; Status = 0x%08lx\n", &SubKeyName, Status);

        goto Exit;
    }

    Status = NtQueryValueKey(
        SubKeyHandle,
        (PUNICODE_STRING) &ValueName,
        KeyValuePartialInformation,
        &ValueData,
        sizeof(ValueData),
        &ResultLength);
    if (!NT_SUCCESS(Status)) {
        DbgPrintEx(
            DPFLTR_SXS_ID,
            DPFLTR_ERROR_LEVEL,
            "SXS: Unabel to query location from storage root subkey %wZ; Status = 0x%08lx\n", &SubKeyName, Status);

        goto Exit;
    }

    if (ValueData.kvpi.Type != REG_SZ) {
        DbgPrintEx(
            DPFLTR_SXS_ID,
            DPFLTR_ERROR_LEVEL,
            "SXS: Assembly storage root location value type is not REG_SZ\n");
        Status = STATUS_OBJECT_PATH_NOT_FOUND;
        goto Exit;
    }

    if ((ValueData.kvpi.DataLength % 2) != 0) {
        DbgPrintEx(
            DPFLTR_SXS_ID,
            DPFLTR_ERROR_LEVEL,
            "SXS: Assembly storage root location value has non-even size\n");
        Status = STATUS_OBJECT_PATH_NOT_FOUND;
        goto Exit;
    }

    if (ValueData.kvpi.DataLength > Root->MaximumLength) {
        if (ValueData.kvpi.DataLength > UNICODE_STRING_MAX_BYTES) {
            DbgPrintEx(
                DPFLTR_SXS_ID,
                DPFLTR_ERROR_LEVEL,
                "SXS: Assembly storage root location for %wZ does not fit in a UNICODE STRING\n", &SubKeyName);

            Status = STATUS_NAME_TOO_LONG;
            goto Exit;
        }

        Root->MaximumLength = (USHORT) ValueData.kvpi.DataLength;
        Root->Buffer = (PWSTR)(RtlAllocateStringRoutine)(Root->MaximumLength);
        if (Root->Buffer == NULL) {
            Status = STATUS_NO_MEMORY;
            goto Exit;
        }
    }

    RtlCopyMemory(
        Root->Buffer,
        ValueData.kvpi.Data,
        ValueData.kvpi.DataLength);

    Root->Length = (USHORT) ValueData.kvpi.DataLength;

    Status = STATUS_SUCCESS;

Exit:
    if (SubKeyHandle != NULL) {
        RTL_SOFT_VERIFY(NT_SUCCESS(NtClose(SubKeyHandle)));
    }

    return Status;
}


最后于 2022-6-11 13:17 被cvcvxk编辑 ,原因:
2022-6-11 13:15
0
雪    币: 724
活跃值: (291)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3

仔细阅读了了@cvcvxk 兄改进后的代码,对原文代码的改进之处
- 对第三个参数的类型做出了准确的判断
- 使用了更文档化的SMB错误类别和代码
- 更优美的代码结构

学习了,感谢 :-)

最后于 2022-6-11 16:04 被mb_yx编辑 ,原因:
2022-6-11 14:55
0
雪    币: 9
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
学习了,非常感谢楼主分析的资料        ·············感谢 :-)

2022-6-12 16:38
0
雪    币: 576
活跃值: (2035)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
谷歌大法好
http://218.94.103.156:8090/download/developer/xpsource/Win2K3/NT/base/ntdll/sxsstorage.c
2022-6-12 18:38
0
雪    币: 724
活跃值: (291)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
kakasasa 谷歌大法好 http://218.94.103.156:8090/download/developer/xpsource/Win2K3/NT/base/ntdll/sxsstorage.c
真没想到,竟然有公开的微软源代码。。。谢谢分享。
2022-6-12 19:55
0
雪    币: 635
活跃值: (1162)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
为何不来个x64的
2022-6-13 10:37
0
雪    币: 9
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
8
楼主忙活了一个月,
搞了半天源代码早就有了,白忙活了。。。哈哈
2022-6-15 10:02
0
雪    币: 422
活跃值: (249)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
win xp 和  server 2003 代码网上早就有泄漏了

https://github.com/selfrender/Windows-Server-2003
2022-7-2 11:49
0
游客
登录 | 注册 方可回帖
返回
//