使用ctypes的GetTokenInformation

时间:2014-08-18 21:42:54

标签: python winapi token ctypes

我试图使用带有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

P.S。我知道win32security.GetTokenInformation存在。但是我想使用ctypes,因为真正的进程处理程序。

编辑:

工作代码:

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 个答案:

答案 0 :(得分:1)

虽然对令牌信息类TokenUser的查询在目标缓冲区中存储了TOKEN_USER结构,但它本身并不包含所有必需的信息。正如你在结构的文档中看到的那样,它只包含SID_AND_ATTRIBUTES结构,而结构只包含一个指针到一个SID和一个带有标志的整数。

如果您添加了更多错误检查,您会看到对GetTokenInformation()的调用失败,报告的错误代码为ERROR_INSUFFICIENT_BUFFER(122)且dwLength设置为某事像36(肯定超过sizeof(TOKEN_USER),只有8)。

显然,函数需要在目标缓冲区中有足够的空间来存储甚至SID本身,然后从记录的输出结构TOKEN_USER指向那些额外的数据。


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