Files
hakril-PythonForWindows/windows/winobject/apisetmap.py
T

147 lines
5.1 KiB
Python

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 apisetmap_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
@utils.fixedpropety
def resolution_dict(self):
res = {}
for name, resolved_name in self.apisetmap_dict.items():
# ApiSetResolveToHost does not care about last version + extension
# It remove everything after the last '-'
# Possible to have no '-' ?
try:
cutname = name[:name.rindex("-") + 1]
except ValueError as e:
cutname = name
res[cutname] = resolved_name
return res
def resolve(self, dllname):
try:
cutname = dllname[:dllname.rindex("-") + 1]
except ValueError as e:
return None
return self.resolution_dict[cutname]
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,
}