mirror of
https://github.com/hakril/PythonForWindows
synced 2026-06-08 14:31:45 +00:00
Improving volume objects + adding CurrentProcess.peb.apisetmap with ApiSetMap parsing capabilities
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
// API SET MAP Stuff
|
||||
// From apiset.h
|
||||
|
||||
|
||||
// Used in V6
|
||||
typedef struct _API_SET_VALUE_ENTRY {
|
||||
ULONG Flags;
|
||||
ULONG NameOffset;
|
||||
ULONG NameLength;
|
||||
ULONG ValueOffset;
|
||||
ULONG ValueLength;
|
||||
} API_SET_VALUE_ENTRY, *PAPI_SET_VALUE_ENTRY;
|
||||
|
||||
typedef struct _API_SET_NAMESPACE_ENTRY {
|
||||
ULONG Flags;
|
||||
ULONG NameOffset;
|
||||
ULONG NameLength;
|
||||
ULONG AliasOffset;
|
||||
ULONG AliasLength;
|
||||
ULONG DataOffset; // API_SET_VALUE_ARRAY
|
||||
} API_SET_NAMESPACE_ENTRY, *PAPI_SET_NAMESPACE_ENTRY;
|
||||
|
||||
|
||||
typedef struct _API_SET_NAMESPACE_ARRAY {
|
||||
ULONG Version;
|
||||
ULONG Size;
|
||||
ULONG Flags;
|
||||
ULONG Count;
|
||||
API_SET_NAMESPACE_ENTRY Array[ANYSIZE_ARRAY];
|
||||
} API_SET_NAMESPACE_ARRAY, *PAPI_SET_NAMESPACE_ARRAY;
|
||||
|
||||
|
||||
// Version 2
|
||||
|
||||
typedef struct _API_SET_VALUE_ENTRY_V2 {
|
||||
ULONG NameOffset;
|
||||
ULONG NameLength;
|
||||
ULONG ValueOffset;
|
||||
ULONG ValueLength;
|
||||
} API_SET_VALUE_ENTRY_V2, *PAPI_SET_VALUE_ENTRY_V2;
|
||||
|
||||
typedef struct _API_SET_VALUE_ARRAY_V2 {
|
||||
ULONG Count;
|
||||
API_SET_VALUE_ENTRY_V2 Array[ANYSIZE_ARRAY];
|
||||
} API_SET_VALUE_ARRAY_V2,*PAPI_SET_VALUE_ARRAY_V2;
|
||||
|
||||
typedef struct _API_SET_NAMESPACE_ENTRY_V2 {
|
||||
ULONG NameOffset;
|
||||
ULONG NameLength;
|
||||
ULONG DataOffset; // _API_SET_VALUE_ARRAY_V2
|
||||
} API_SET_NAMESPACE_ENTRY_V2, *PAPI_SET_NAMESPACE_ENTRY_V2;
|
||||
|
||||
typedef struct _API_SET_NAMESPACE_ARRAY_V2 {
|
||||
ULONG Version;
|
||||
ULONG Count;
|
||||
API_SET_NAMESPACE_ENTRY_V2 Array[ANYSIZE_ARRAY];
|
||||
} API_SET_NAMESPACE_ARRAY_V2, *PAPI_SET_NAMESPACE_ARRAY_V2;
|
||||
|
||||
// Version 4
|
||||
|
||||
typedef struct _API_SET_VALUE_ARRAY_V4 {
|
||||
ULONG GuessFlags;
|
||||
ULONG Count;
|
||||
API_SET_VALUE_ENTRY_V2 Array[ANYSIZE_ARRAY];
|
||||
} API_SET_VALUE_ARRAY_V4,*PAPI_SET_VALUE_ARRAY_V2;
|
||||
|
||||
typedef struct _API_SET_NAMESPACE_ARRAY_V4 {
|
||||
ULONG Version;
|
||||
ULONG Size;
|
||||
ULONG Flags;
|
||||
ULONG Count;
|
||||
API_SET_NAMESPACE_ENTRY Array[ANYSIZE_ARRAY];
|
||||
} API_SET_NAMESPACE_ARRAY_V4, *PAPI_SET_NAMESPACE_ARRAY_V4;
|
||||
|
||||
typedef struct _API_SET_NAMESPACE_ENTRY_V4 {
|
||||
ULONG Flags;
|
||||
ULONG NameOffset;
|
||||
ULONG NameLength;
|
||||
ULONG AliasOffset;
|
||||
ULONG AliasLength;
|
||||
ULONG DataOffset;
|
||||
} API_SET_NAMESPACE_ENTRY_V4, *PAPI_SET_NAMESPACE_ENTRY_V4;
|
||||
|
||||
|
||||
|
||||
// Version 6
|
||||
|
||||
typedef struct _API_SET_NAMESPACE_ENTRY_V6 {
|
||||
ULONG Flags;
|
||||
ULONG NameOffset;
|
||||
ULONG NameLength;
|
||||
ULONG HashedLength;
|
||||
ULONG ValueOffset;
|
||||
ULONG ValueCount;
|
||||
} API_SET_NAMESPACE_ENTRY_V6;
|
||||
|
||||
|
||||
typedef struct _API_SET_NAMESPACE_V6 {
|
||||
ULONG Version;
|
||||
ULONG Size;
|
||||
ULONG Flags;
|
||||
ULONG Count;
|
||||
ULONG EntryOffset;
|
||||
ULONG HashOffset;
|
||||
ULONG HashFactor;
|
||||
} API_SET_NAMESPACE_V6;
|
||||
|
||||
// STOP API-SET-MAP
|
||||
@@ -0,0 +1,166 @@
|
||||
typedef enum _FILE_INFORMATION_CLASS {
|
||||
FakeFileInformationZero,
|
||||
FileDirectoryInformation,
|
||||
FileFullDirectoryInformation,
|
||||
FileBothDirectoryInformation,
|
||||
FileBasicInformation,
|
||||
FileStandardInformation,
|
||||
FileInternalInformation,
|
||||
FileEaInformation,
|
||||
FileAccessInformation,
|
||||
FileNameInformation,
|
||||
FileRenameInformation,
|
||||
FileLinkInformation,
|
||||
FileNamesInformation,
|
||||
FileDispositionInformation,
|
||||
FilePositionInformation,
|
||||
FileFullEaInformation,
|
||||
FileModeInformation,
|
||||
FileAlignmentInformation,
|
||||
FileAllInformation,
|
||||
FileAllocationInformation,
|
||||
FileEndOfFileInformation,
|
||||
FileAlternateNameInformation,
|
||||
FileStreamInformation,
|
||||
FilePipeInformation,
|
||||
FilePipeLocalInformation,
|
||||
FilePipeRemoteInformation,
|
||||
FileMailslotQueryInformation,
|
||||
FileMailslotSetInformation,
|
||||
FileCompressionInformation,
|
||||
FileObjectIdInformation,
|
||||
FileCompletionInformation,
|
||||
FileMoveClusterInformation,
|
||||
FileQuotaInformation,
|
||||
FileReparsePointInformation,
|
||||
FileNetworkOpenInformation,
|
||||
FileAttributeTagInformation,
|
||||
FileTrackingInformation,
|
||||
FileIdBothDirectoryInformation,
|
||||
FileIdFullDirectoryInformation,
|
||||
FileValidDataLengthInformation,
|
||||
FileShortNameInformation,
|
||||
FileIoCompletionNotificationInformation,
|
||||
FileIoStatusBlockRangeInformation,
|
||||
FileIoPriorityHintInformation,
|
||||
FileSfioReserveInformation,
|
||||
FileSfioVolumeInformation,
|
||||
FileHardLinkInformation,
|
||||
FileProcessIdsUsingFileInformation,
|
||||
FileNormalizedNameInformation,
|
||||
FileNetworkPhysicalNameInformation,
|
||||
FileIdGlobalTxDirectoryInformation,
|
||||
FileIsRemoteDeviceInformation,
|
||||
FileUnusedInformation,
|
||||
FileNumaNodeInformation,
|
||||
FileStandardLinkInformation,
|
||||
FileRemoteProtocolInformation,
|
||||
FileRenameInformationBypassAccessCheck,
|
||||
FileLinkInformationBypassAccessCheck,
|
||||
FileVolumeNameInformation,
|
||||
FileIdInformation,
|
||||
FileIdExtdDirectoryInformation,
|
||||
FileReplaceCompletionInformation,
|
||||
FileHardLinkFullIdInformation,
|
||||
FileIdExtdBothDirectoryInformation,
|
||||
FileDispositionInformationEx,
|
||||
FileRenameInformationEx,
|
||||
FileRenameInformationExBypassAccessCheck,
|
||||
FileMaximumInformation
|
||||
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
|
||||
|
||||
typedef enum _IO_PRIORITY_HINT {
|
||||
IoPriorityVeryLow = 0,
|
||||
IoPriorityLow = 1,
|
||||
IoPriorityNormal = 2,
|
||||
IoPriorityHigh = 3,
|
||||
IoPriorityCritical = 4,
|
||||
MaxIoPriorityTypes = 5
|
||||
} IO_PRIORITY_HINT;
|
||||
|
||||
|
||||
typedef struct _FILE_INTERNAL_INFORMATION {
|
||||
LARGE_INTEGER IndexNumber;
|
||||
} FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION;
|
||||
|
||||
|
||||
typedef struct _FILE_ALIGNMENT_INFORMATION {
|
||||
ULONG AlignmentRequirement;
|
||||
} FILE_ALIGNMENT_INFORMATION, *PFILE_ALIGNMENT_INFORMATION;
|
||||
|
||||
|
||||
typedef struct _FILE_ATTRIBUTE_TAG_INFORMATION {
|
||||
ULONG FileAttributes;
|
||||
ULONG ReparseTag;
|
||||
} FILE_ATTRIBUTE_TAG_INFORMATION, *PFILE_ATTRIBUTE_TAG_INFORMATION;
|
||||
|
||||
typedef struct _FILE_BASIC_INFORMATION {
|
||||
LARGE_INTEGER CreationTime;
|
||||
LARGE_INTEGER LastAccessTime;
|
||||
LARGE_INTEGER LastWriteTime;
|
||||
LARGE_INTEGER ChangeTime;
|
||||
ULONG FileAttributes;
|
||||
} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;
|
||||
|
||||
typedef struct _FILE_EA_INFORMATION {
|
||||
ULONG EaSize;
|
||||
} FILE_EA_INFORMATION, *PFILE_EA_INFORMATION;
|
||||
|
||||
typedef struct _FILE_IO_PRIORITY_HINT_INFORMATION {
|
||||
IO_PRIORITY_HINT PriorityHint;
|
||||
} FILE_IO_PRIORITY_HINT_INFORMATION, *PFILE_IO_PRIORITY_HINT_INFORMATION;
|
||||
|
||||
|
||||
typedef struct _FILE_MODE_INFORMATION {
|
||||
ULONG Mode;
|
||||
} FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION;
|
||||
|
||||
typedef struct _FILE_NAME_INFORMATION {
|
||||
ULONG FileNameLength;
|
||||
WCHAR FileName[1];
|
||||
} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;
|
||||
|
||||
|
||||
typedef struct _FILE_NETWORK_OPEN_INFORMATION {
|
||||
LARGE_INTEGER CreationTime;
|
||||
LARGE_INTEGER LastAccessTime;
|
||||
LARGE_INTEGER LastWriteTime;
|
||||
LARGE_INTEGER ChangeTime;
|
||||
LARGE_INTEGER AllocationSize;
|
||||
LARGE_INTEGER EndOfFile;
|
||||
ULONG FileAttributes;
|
||||
} FILE_NETWORK_OPEN_INFORMATION, *PFILE_NETWORK_OPEN_INFORMATION;
|
||||
|
||||
typedef struct _FILE_STANDARD_INFORMATION {
|
||||
LARGE_INTEGER AllocationSize;
|
||||
LARGE_INTEGER EndOfFile;
|
||||
ULONG NumberOfLinks;
|
||||
BOOLEAN DeletePending;
|
||||
BOOLEAN Directory;
|
||||
} FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION;
|
||||
|
||||
typedef struct _FILE_ACCESS_INFORMATION {
|
||||
ACCESS_MASK AccessFlags;
|
||||
} FILE_ACCESS_INFORMATION, *PFILE_ACCESS_INFORMATION;
|
||||
|
||||
typedef struct _FILE_POSITION_INFORMATION {
|
||||
LARGE_INTEGER CurrentByteOffset;
|
||||
} FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION;
|
||||
|
||||
typedef struct _FILE_IS_REMOTE_DEVICE_INFORMATION {
|
||||
BOOLEAN IsRemote;
|
||||
} FILE_IS_REMOTE_DEVICE_INFORMATION, *PFILE_IS_REMOTE_DEVICE_INFORMATION;
|
||||
|
||||
|
||||
|
||||
typedef struct _FILE_ALL_INFORMATION {
|
||||
FILE_BASIC_INFORMATION BasicInformation;
|
||||
FILE_STANDARD_INFORMATION StandardInformation;
|
||||
FILE_INTERNAL_INFORMATION InternalInformation;
|
||||
FILE_EA_INFORMATION EaInformation;
|
||||
FILE_ACCESS_INFORMATION AccessInformation;
|
||||
FILE_POSITION_INFORMATION PositionInformation;
|
||||
FILE_MODE_INFORMATION ModeInformation;
|
||||
FILE_ALIGNMENT_INFORMATION AlignmentInformation;
|
||||
FILE_NAME_INFORMATION NameInformation;
|
||||
} FILE_ALL_INFORMATION, *PFILE_ALL_INFORMATION;
|
||||
@@ -0,0 +1,23 @@
|
||||
import argparse
|
||||
import windows
|
||||
|
||||
def read_apisetmap():
|
||||
cp = windows.current_process
|
||||
apisetmap_addr = cp.peb.ApiSetMap
|
||||
print("ApiSetMap address <{0:#x}>".format(apisetmap_addr))
|
||||
apisetmap_version = cp.read_dword(apisetmap_addr)
|
||||
print("ApiSetMap version <{0}>".format(apisetmap_version))
|
||||
meminfo = cp.query_memory(apisetmap_addr)
|
||||
print(meminfo)
|
||||
data = cp.read_memory(meminfo.BaseAddress, meminfo.RegionSize)
|
||||
return data
|
||||
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(prog=__file__)
|
||||
parser.add_argument('filename', default="apisetmap.dmp", help='The filename in which the ApiSetMap is dumped')
|
||||
res = parser.parse_args()
|
||||
|
||||
with open(res.filename, "wb") as f:
|
||||
f.write(read_apisetmap().encode("base64"))
|
||||
print("<{0}> generated".format(res.filename))
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,48 @@
|
||||
import pytest
|
||||
import windows
|
||||
import windows.remotectypes as rctypes
|
||||
|
||||
from pfwtest import *
|
||||
|
||||
def assert_struct_offset(struct, field, offset):
|
||||
assert getattr(struct, field).offset == offset
|
||||
|
||||
if windows.current_process.bitness == 32:
|
||||
PEB32 = windows.generated_def.PEB
|
||||
PEB64 = rctypes.transform_type_to_remote64bits(windows.generated_def.PEB)
|
||||
else:
|
||||
PEB32 = rctypes.transform_type_to_remote32bits(windows.generated_def.PEB)
|
||||
PEB64 = windows.generated_def.PEB
|
||||
|
||||
def test_peb32_fields():
|
||||
assert_peb_offset = lambda field, offset: assert_struct_offset(PEB32, field, offset)
|
||||
assert_peb_offset("BeingDebugged", 2)
|
||||
assert_peb_offset("ImageBaseAddress", 0x8)
|
||||
assert_peb_offset("Ldr", 0xc)
|
||||
assert_peb_offset("ProcessParameters", 0x10)
|
||||
assert_peb_offset("KernelCallbackTable", 0x2c)
|
||||
assert_peb_offset("UserSharedInfoPtr", 0x2c)
|
||||
assert_peb_offset("ApiSetMap", 0x38)
|
||||
assert_peb_offset("NumberOfProcessors", 0x64)
|
||||
assert_peb_offset("GdiHandleBuffer", 0xc4)
|
||||
assert_peb_offset("PostProcessInitRoutine", 0x14c) # Field just after 'GdiHandleBuffer' allow to also check the 'GdiHandleBuffer' size hack
|
||||
assert_peb_offset("SessionId", 0x1d4)
|
||||
assert_peb_offset("CSDVersion", 0x01F0)
|
||||
assert_peb_offset("MinimumStackCommit", 0x0208)
|
||||
|
||||
|
||||
def test_peb64_fields():
|
||||
assert_peb_offset = lambda field, offset: assert_struct_offset(PEB64, field, offset)
|
||||
assert_peb_offset("BeingDebugged", 2)
|
||||
assert_peb_offset("ImageBaseAddress", 0x10)
|
||||
assert_peb_offset("Ldr", 0x18)
|
||||
assert_peb_offset("ProcessParameters", 0x20)
|
||||
assert_peb_offset("KernelCallbackTable", 0x58)
|
||||
assert_peb_offset("UserSharedInfoPtr", 0x58)
|
||||
assert_peb_offset("ApiSetMap", 0x68)
|
||||
assert_peb_offset("NumberOfProcessors", 0xb8)
|
||||
assert_peb_offset("GdiHandleBuffer", 0x140)
|
||||
assert_peb_offset("PostProcessInitRoutine", 0x230) # Field just after 'GdiHandleBuffer' allow to also check the 'GdiHandleBuffer' size hack
|
||||
assert_peb_offset("SessionId", 0x2c0)
|
||||
assert_peb_offset("CSDVersion", 0x02E8)
|
||||
assert_peb_offset("MinimumStackCommit", 0x0318)
|
||||
+2
-4
@@ -356,8 +356,7 @@ class AlpcClient(AlpcTransportBase):
|
||||
x = self.connect_to_port(port_name, "")
|
||||
|
||||
def _alpc_port_to_unicode_string(self, name):
|
||||
utf16_len = len(name) * 2
|
||||
return gdef.UNICODE_STRING(utf16_len, utf16_len, ctypes.cast(gdef.PWSTR(name), gdef.PVOID))
|
||||
return gdef.UNICODE_STRING.from_string(name)
|
||||
|
||||
def connect_to_port(self, port_name, connect_message=None,
|
||||
port_attr=None, port_attr_flags=0x10000, obj_attr=None,
|
||||
@@ -452,8 +451,7 @@ class AlpcServer(AlpcTransportBase):
|
||||
self.create_port(port_name)
|
||||
|
||||
def _alpc_port_to_unicode_string(self, name):
|
||||
utf16_len = len(name) * 2
|
||||
return gdef.UNICODE_STRING(utf16_len, utf16_len, ctypes.cast(gdef.PWSTR(name), gdef.PVOID))
|
||||
return gdef.UNICODE_STRING.from_string(name)
|
||||
|
||||
def create_port(self, port_name, msglen=None, port_attr_flags=0, obj_attr=None, port_attr=None):
|
||||
"""Create the ALPC port ``port_name``. Most of the parameters have defauls value is ``None`` is passed.
|
||||
|
||||
@@ -346,6 +346,11 @@ def get_short_path(path):
|
||||
rsize = winproxy.GetShortPathNameA(path, buffer, size)
|
||||
return buffer[:rsize]
|
||||
|
||||
def dospath_to_ntpath(dospath):
|
||||
ustring = gdef.UNICODE_STRING()
|
||||
windows.winproxy.RtlDosPathNameToNtPathName_U(dospath, ustring, None, None)
|
||||
return ustring.str
|
||||
|
||||
|
||||
def get_shared_mapping(name, size=0x1000):
|
||||
# TODO: real code
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
import windows
|
||||
import windows.generated_def as gdef
|
||||
|
||||
from windows import utils
|
||||
|
||||
|
||||
def get_api_set_map_for_current_process(base):
|
||||
base = windows.current_process.peb.ApiSetMap
|
||||
version = windows.current_process.read_dword(base)
|
||||
if version not in API_SET_MAP_BY_VERSION:
|
||||
raise NotImplementedError("ApiSetMap version <{0}> not implemented, please contact me, I need a sample to implem it ;)")
|
||||
return API_SET_MAP_BY_VERSION[version](base)
|
||||
|
||||
|
||||
class ApiSetMap(object):
|
||||
def __init__(self, base):
|
||||
self.base = base
|
||||
self.target = windows.current_process
|
||||
|
||||
# helpers
|
||||
def read_apiset_wstring(self, offset, length):
|
||||
return self.target.read_memory(self.base + offset, length).decode("utf-16")
|
||||
|
||||
# Low-level version-dependent parsing function
|
||||
def entries_array(self):
|
||||
raise NotImplementedError("Should be implemented by subclasses")
|
||||
|
||||
def get_entry_name(self, entry):
|
||||
raise NotImplementedError("Should be implemented by subclasses")
|
||||
|
||||
def get_entry_name_basicimpl(self, entry):
|
||||
return self.read_apiset_wstring(entry.NameOffset, entry.NameLength)
|
||||
|
||||
def values_for_entry(self, entry):
|
||||
raise NotImplementedError("Should be implemented by subclasses")
|
||||
|
||||
@utils.fixedpropety
|
||||
def resolution_dict(self):
|
||||
res = {}
|
||||
for entry in self.entries_array():
|
||||
values = self.values_for_entry(entry)
|
||||
if not values:
|
||||
final_value = None
|
||||
else:
|
||||
final_value = values[-1]
|
||||
res[self.get_entry_name(entry)] = final_value
|
||||
return res
|
||||
|
||||
def resolve(self, dllname):
|
||||
return self.resolution_dict[dllname]
|
||||
|
||||
|
||||
|
||||
class ApiSetMapVersion2(ApiSetMap):
|
||||
def namespace(self):
|
||||
return gdef.API_SET_NAMESPACE_ARRAY_V2.from_address(self.base)
|
||||
|
||||
def entries_array(self):
|
||||
namespace = self.namespace()
|
||||
array_addr = ctypes.addressof(namespace.Array)
|
||||
array_size = namespace.Count
|
||||
return (gdef.API_SET_NAMESPACE_ENTRY_V2 * array_size).from_address(array_addr)
|
||||
|
||||
get_entry_name = ApiSetMap.get_entry_name_basicimpl
|
||||
|
||||
def values_for_entry(self, entry):
|
||||
values_array_v2 = (gdef.API_SET_VALUE_ARRAY_V2).from_address(self.base + entry.DataOffset)
|
||||
array_size = values_array_v2.Count
|
||||
array_addr = ctypes.addressof(values_array_v2.Array)
|
||||
values_array = (gdef.API_SET_VALUE_ENTRY_V2 * array_size).from_address(array_addr)
|
||||
res = []
|
||||
for value in values_array:
|
||||
if value.ValueLength:
|
||||
v = self.read_apiset_wstring(value.ValueOffset, value.ValueLength)
|
||||
res.append(v)
|
||||
return res
|
||||
|
||||
|
||||
class ApiSetMapVersion4(ApiSetMap):
|
||||
def namespace(self):
|
||||
return gdef.API_SET_NAMESPACE_ARRAY_V4.from_address(self.base)
|
||||
|
||||
def entries_array(self):
|
||||
namespace = self.namespace()
|
||||
array_addr = ctypes.addressof(namespace.Array)
|
||||
array_size = namespace.Count
|
||||
return (gdef.API_SET_NAMESPACE_ENTRY_V4 * array_size).from_address(array_addr)
|
||||
|
||||
get_entry_name = ApiSetMap.get_entry_name_basicimpl
|
||||
|
||||
def values_for_entry(self, entry):
|
||||
values_array_v2 = (gdef.API_SET_VALUE_ARRAY_V4).from_address(self.base + entry.DataOffset)
|
||||
array_size = values_array_v2.Count
|
||||
array_addr = ctypes.addressof(values_array_v2.Array)
|
||||
values_array = (gdef.API_SET_VALUE_ENTRY * array_size).from_address(array_addr)
|
||||
res = []
|
||||
for value in values_array:
|
||||
if value.ValueLength:
|
||||
v = self.read_apiset_wstring(value.ValueOffset, value.ValueLength)
|
||||
res.append(v)
|
||||
return res
|
||||
|
||||
class ApiSetMapVersion6(ApiSetMap):
|
||||
def namespace(self):
|
||||
return gdef.API_SET_NAMESPACE_V6.from_address(self.base)
|
||||
|
||||
get_entry_name = ApiSetMap.get_entry_name_basicimpl
|
||||
|
||||
def entries_array(self):
|
||||
namespace = self.namespace()
|
||||
array_offset = namespace.EntryOffset
|
||||
array_size = namespace.Count
|
||||
return (gdef.API_SET_NAMESPACE_ENTRY_V6 * array_size).from_address(self.base + array_offset)
|
||||
|
||||
def values_for_entry(self, entry):
|
||||
values_array = (gdef.API_SET_VALUE_ENTRY * entry.ValueCount).from_address(self.base + entry.ValueOffset)
|
||||
res = []
|
||||
for value in values_array:
|
||||
if value.ValueLength:
|
||||
v = self.read_apiset_wstring(value.ValueOffset, value.ValueLength)
|
||||
res.append(v)
|
||||
return res
|
||||
|
||||
API_SET_MAP_BY_VERSION = {
|
||||
2: ApiSetMapVersion2,
|
||||
4: ApiSetMapVersion4,
|
||||
6: ApiSetMapVersion6,
|
||||
}
|
||||
@@ -25,6 +25,7 @@ from windows.generated_def.ntstatus import NtStatusException
|
||||
|
||||
from windows.winobject import exception
|
||||
from windows.winobject import sid
|
||||
from windows.winobject import apisetmap
|
||||
|
||||
|
||||
TimeInfo = namedtuple("TimeInfo", ["creation", "exit", "kernel", "user"])
|
||||
@@ -62,9 +63,8 @@ class AutoHandle(object):
|
||||
|
||||
def __del__(self):
|
||||
# sys.path is not None -> check if python shutdown
|
||||
if sys.path is not None and hasattr(self, "_handle") and self._handle:
|
||||
if hasattr(sys, "path") and sys.path is not None and hasattr(self, "_handle") and self._handle:
|
||||
# Prevent some bug where dbgprint might be None when __del__ is called in a closing process
|
||||
# for i in vars(sys).items(): print(i)
|
||||
dbgprint("Closing Handle {0} for {1}".format(hex(self._handle), self), "HANDLE") if dbgprint is not None else None
|
||||
self._close_function(self._handle)
|
||||
|
||||
@@ -690,6 +690,13 @@ class Process(AutoHandle):
|
||||
PROCESS_MODE_BACKGROUND_END,
|
||||
REALTIME_PRIORITY_CLASS)
|
||||
|
||||
def query_info(self, information_class, data=None):
|
||||
winproxy.NtQueryInformationProcess(self.handle, information_class, byref(data), sizeof(data))
|
||||
return data
|
||||
|
||||
def set_info(self, information_class, data):
|
||||
winproxy.NtSetInformationProcess(self.handle, information_class, byref(data), sizeof(data))
|
||||
|
||||
def get_priority(self):
|
||||
return self.PRIORITY_CLASS_MAPPER[winproxy.GetPriorityClass(self.handle)]
|
||||
|
||||
@@ -1324,6 +1331,28 @@ class PEB(gdef.PEB):
|
||||
current_dll = list_entry_ptr.TO_LDR_ENTRY()
|
||||
return [LoadedModule.from_address(addressof(LDR)) for LDR in res]
|
||||
|
||||
@staticmethod
|
||||
def _extract_environment(env_block_addr, target):
|
||||
result = []
|
||||
while True:
|
||||
venv = target.read_wstring(env_block_addr)
|
||||
if not venv:
|
||||
return result
|
||||
result.append(venv)
|
||||
env_block_addr += ((len(venv) + 1) * 2)
|
||||
# raise RuntimeError("Out of infinite loop")
|
||||
|
||||
@property
|
||||
def environment(self):
|
||||
# TODO: Tests
|
||||
return self._extract_environment(self.ProcessParameters.contents.Environment, windows.current_process)
|
||||
|
||||
@property
|
||||
def apisetmap(self):
|
||||
if windows.system.version < (6,2):
|
||||
raise NotImplementedError("ApiSetMap does not exist prior to Windows 7")
|
||||
return apisetmap.get_api_set_map_for_current_process(self.ApiSetMap)
|
||||
|
||||
|
||||
# Memory stuff
|
||||
|
||||
@@ -1426,6 +1455,17 @@ class RemotePEB(rctypes.RemoteStructure.from_structure(PEB)):
|
||||
current_dll = self.ptr_flink_to_remote_module(list_entry_ptr)
|
||||
return res
|
||||
|
||||
@property
|
||||
def environment(self):
|
||||
# TODO: Tests
|
||||
return self._extract_environment(self.ProcessParameters.contents.Environment, self._target)
|
||||
|
||||
@property
|
||||
def apisetmap(self):
|
||||
raise NotImplementedError("ApiSetMap for remote process not implemented yet")
|
||||
|
||||
|
||||
|
||||
|
||||
if CurrentProcess().bitness == 32:
|
||||
class RemoteLoadedModule64(rctypes.transform_type_to_remote64bits(LoadedModule)):
|
||||
@@ -1468,6 +1508,13 @@ if CurrentProcess().bitness == 32:
|
||||
current_dll = self.ptr_flink_to_remote_module(list_entry_ptr)
|
||||
return res
|
||||
|
||||
@property
|
||||
def environment(self):
|
||||
# TODO: Tests
|
||||
return self._extract_environment(self.ProcessParameters.contents.Environment, self._target)
|
||||
|
||||
apisetmap = RemotePEB.apisetmap
|
||||
|
||||
if CurrentProcess().bitness == 64:
|
||||
|
||||
class RemoteLoadedModule32(rctypes.transform_type_to_remote32bits(LoadedModule)):
|
||||
@@ -1507,4 +1554,11 @@ if CurrentProcess().bitness == 64:
|
||||
res.append(current_dll)
|
||||
list_entry_ptr = current_dll.InMemoryOrderLinks.Flink.raw_value
|
||||
current_dll = self.ptr_flink_to_remote_module(list_entry_ptr)
|
||||
return res
|
||||
return res
|
||||
|
||||
@property
|
||||
def environment(self):
|
||||
# TODO: Tests
|
||||
return self._extract_environment(self.ProcessParameters.contents.Environment, self._target)
|
||||
|
||||
apisetmap = RemotePEB.apisetmap
|
||||
@@ -5,10 +5,12 @@ from windows import winproxy
|
||||
import windows.generated_def as gdef
|
||||
from windows.generated_def.winstructs import *
|
||||
|
||||
from .process import AutoHandle
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
|
||||
class LogicalDrive(object):
|
||||
class LogicalDrive(AutoHandle):
|
||||
DRIVE_TYPE = gdef.FlagMapper(DRIVE_UNKNOWN, DRIVE_NO_ROOT_DIR, DRIVE_REMOVABLE,
|
||||
DRIVE_FIXED, DRIVE_REMOTE, DRIVE_CDROM, DRIVE_RAMDISK)
|
||||
|
||||
@@ -42,12 +44,26 @@ class LogicalDrive(object):
|
||||
raise ValueError("[Unexpected result] query_dos_device(logicaldrive) returned multiple path")
|
||||
return res[0]
|
||||
|
||||
def query_info(self, info):
|
||||
return windows.utils.query_volume_information(self.handle, info)
|
||||
|
||||
@property
|
||||
def volume_info(self):
|
||||
return self.query_info(gdef.FileFsVolumeInformation)
|
||||
|
||||
@property
|
||||
def serial(self):
|
||||
return self.volume_info.VolumeSerialNumber
|
||||
|
||||
def _get_handle(self):
|
||||
nt_name = windows.utils.dospath_to_ntpath(self.name)
|
||||
handle = windows.winproxy.CreateFileA(nt_name, gdef.GENERIC_READ,
|
||||
gdef.FILE_SHARE_READ, None, gdef.OPEN_EXISTING, gdef.FILE_FLAG_BACKUP_SEMANTICS , None)
|
||||
return handle
|
||||
|
||||
def __repr__(self):
|
||||
return """<{0} "{1}" ({2})>""".format(type(self).__name__, self.name, self.type.name)
|
||||
|
||||
|
||||
|
||||
def enum_logical_drive():
|
||||
return [LogicalDrive(name) for name in get_logical_drive_names()]
|
||||
|
||||
@@ -63,7 +79,7 @@ def get_info(drivename):
|
||||
fs_name = ctypes.c_buffer(size)
|
||||
flags = DWORD()
|
||||
winproxy.GetVolumeInformationA(drivename, volume_name, size, None, None, ctypes.byref(flags), fs_name, size)
|
||||
raise NotImplementedError("get_info")
|
||||
return volume_name[:10], fs_name[:10]
|
||||
|
||||
def query_dos_device(name):
|
||||
size = 0x1000
|
||||
|
||||
@@ -841,6 +841,12 @@ def NtQueryInformationProcess(ProcessHandle, ProcessInformationClass, ProcessInf
|
||||
return NtQueryInformationProcess.ctypes_function(ProcessHandle, ProcessInformationClass, ProcessInformation, ProcessInformationLength, ReturnLength)
|
||||
|
||||
|
||||
@NtdllProxy('NtSetInformationProcess', error_ntstatus)
|
||||
def NtSetInformationProcess(ProcessHandle, ProcessInformationClass, ProcessInformation, ProcessInformationLength=0):
|
||||
if not ProcessInformationLength:
|
||||
ProcessInformationLength = ctypes.sizeof(ProcessInformation)
|
||||
return NtSetInformationProcess.ctypes_function(ProcessHandle, ProcessInformationClass, ProcessInformation, ProcessInformationLength)
|
||||
|
||||
@NtdllProxy('NtQueryInformationThread', error_ntstatus)
|
||||
def NtQueryInformationThread(ThreadHandle, ThreadInformationClass, ThreadInformation, ThreadInformationLength=0, ReturnLength=None):
|
||||
if ReturnLength is None:
|
||||
@@ -1013,6 +1019,10 @@ def RtlGetCompressionWorkSpaceSize(CompressionFormatAndEngine, CompressBufferWor
|
||||
return RtlGetCompressionWorkSpaceSize.ctypes_function(CompressionFormatAndEngine, CompressBufferWorkSpaceSize, CompressFragmentWorkSpaceSize)
|
||||
|
||||
|
||||
@NtdllProxy("RtlDosPathNameToNtPathName_U", zero_is_fail_error_check)
|
||||
def RtlDosPathNameToNtPathName_U(DosName, NtName=None, PartName=None, RelativeName=None):
|
||||
return RtlDosPathNameToNtPathName_U.ctypes_function(DosName, NtName, PartName, RelativeName)
|
||||
|
||||
|
||||
# Section stuff
|
||||
|
||||
@@ -1045,6 +1055,11 @@ def RtlGetUnloadEventTraceEx(ElementSize, ElementCount, EventTrace):
|
||||
def TpCallbackSendAlpcMessageOnCompletion(TpHandle, PortHandle, Flags, SendMessage):
|
||||
return TpCallbackSendAlpcMessageOnCompletion.ctypes_function(TpHandle, PortHandle, Flags, SendMessage)
|
||||
|
||||
# Not exported
|
||||
|
||||
# @NtdllProxy("ApiSetResolveToHost")
|
||||
# def ApiSetResolveToHost(Schema, FileNameIn, ParentName, Resolved, HostBinary):
|
||||
# return ApiSetResolveToHost.ctypes_function(Schema, FileNameIn, ParentName, Resolved, HostBinary)
|
||||
|
||||
|
||||
# ##### ADVAPI32 ####### #
|
||||
|
||||
Reference in New Issue
Block a user