代码之家  ›  专栏  ›  技术社区  ›  user1474685

使用ctypes获取令牌信息

  •  0
  • user1474685  · 技术社区  · 11 年前

    我正在尝试对ctypes使用GetTokenInformation函数。 问题是它将始终打印“无”。

    import winappdbg
    from ctypes import *
    
    LPVOID = c_void_p
    PVOID = LPVOID
    PSID = PVOID
    DWORD = c_uint32
    
    
    class SID_AND_ATTRIBUTES(Structure):
        _fields_ = [
            ("Sid",         PSID),
            ("Attributes",  DWORD),
        ]
    
    class TOKEN_USER(Structure):
        _fields_ = [
            ("User", SID_AND_ATTRIBUTES),]
    
    tokenprivs = (winappdbg.win32.TOKEN_QUERY | winappdbg.win32.TOKEN_READ | winappdbg.win32.TOKEN_IMPERSONATE | winappdbg.win32.TOKEN_QUERY_SOURCE | winappdbg.win32.TOKEN_DUPLICATE | winappdbg.win32.TOKEN_ASSIGN_PRIMARY)
    hProcess = winappdbg.win32.OpenProcess(winappdbg.win32.PROCESS_QUERY_INFORMATION, False, winappdbg.win32.GetCurrentProcessId())
    hToken = winappdbg.win32.OpenProcessToken(hProcess, DesiredAccess = tokenprivs)
    
    tokeninformation = TOKEN_USER()
    dwLength = DWORD(0)
    windll.advapi32.GetTokenInformation(hToken, winappdbg.win32.TokenUser, byref(tokeninformation), sizeof(TOKEN_USER), byref(dwLength))
    print tokeninformation.User.Sid
    

    注:我知道win32security.GetTokenInformation存在。但我想使用ctyps,因为它是真正的流程处理程序。

    编辑:

    工作代码:

    import winappdbg
    from ctypes import *
    
    LPVOID = c_void_p
    PVOID = LPVOID
    PSID = PVOID
    DWORD = c_uint32
    
    class SID_AND_ATTRIBUTES(Structure):
        _fields_ = [
            ("Sid",         PSID),
            ("Attributes",  DWORD),
        ]
    
    class TOKEN_USER(Structure):
        _fields_ = [
            ("User", SID_AND_ATTRIBUTES),]
    
    tokenprivs = (winappdbg.win32.TOKEN_QUERY | winappdbg.win32.TOKEN_READ | winappdbg.win32.TOKEN_IMPERSONATE | winappdbg.win32.TOKEN_QUERY_SOURCE | winappdbg.win32.TOKEN_DUPLICATE | winappdbg.win32.TOKEN_ASSIGN_PRIMARY)
    hProcess = winappdbg.win32.OpenProcess(winappdbg.win32.PROCESS_QUERY_INFORMATION, False, winappdbg.win32.GetCurrentProcessId())
    hToken = winappdbg.win32.OpenProcessToken(hProcess, DesiredAccess = tokenprivs)
    
    dwSize = DWORD(0)
    pStringSid = winappdbg.win32.LPSTR()
    
    windll.advapi32.GetTokenInformation(hToken, winappdbg.win32.TokenUser, None, 0, byref(dwSize))
    
    address = windll.kernel32.LocalAlloc(0x0040, dwSize)
    print "Address: " + str(address)
    
    windll.advapi32.GetTokenInformation(hToken, winappdbg.win32.TokenUser, address, dwSize, byref(dwSize))
    print FormatError(GetLastError())
    
    pToken_User = cast(address, POINTER(TOKEN_USER))
    
    windll.advapi32.ConvertSidToStringSidA(pToken_User.contents.User.Sid, byref(pStringSid))
    print "SID: " + pStringSid.value
    
    1 回复  |  直到 11 年前
        1
  •  0
  •   Yirkha    11 年前

    尽管对令牌信息类的查询 TokenUser 存储a TOKEN_USER 结构,它本身并不包含所有所需的信息。正如您在结构的文档中看到的,它只包含 SID_AND_ATTRIBUTES 结构,该结构仅包含 指针,指针 转换为SID和带标志的整数。

    如果您添加了更多错误检查,您将看到 GetTokenInformation() 不成功,报告的错误代码为 ERROR_INSUFFICIENT_BUFFER (122)和 dwLength 设置为大约36(绝对大于 sizeof(TOKEN_USER) ,仅为8)。

    显然,该函数希望目标缓冲区中有足够的空间来存储SID本身,然后从记录的输出结构中指向额外的数据 标记用户(_U) .


    我不太了解Ctypes,但您需要将输出缓冲区创建为一个真正的缓冲区/数组,而不仅仅是结构,并对其执行一些强制转换以获取数据。您可以采取简单的方法,在第一次尝试时创建足够大的缓冲区,或者调用函数两次,第一次获取所需的缓冲区长度,第二次填充。