Commit 54b3449c authored by Aleksey R.'s avatar Aleksey R.

moved to githomelab.ru

parent 27da13ac
This diff is collapsed.
import os
import pykd
STANDARD_ACCESS_MASKS = {
0x00010000 : "DELETE",
0x00020000 : "READ_CONTROL",
0x00040000 : "WRITE_DAC",
0x00080000 : "WRITE_OWNER",
0x00100000 : "SYNCHRONIZE",
}
FILE_ACCESS_MASKS = {
0x0001 : "FILE_READ_DATA",
0x0002 : "FILE_WRITE_DATA",
0x0004 : "FILE_APPEND_DATA",
0x0008 : "FILE_READ_EA",
0x0010 : "FILE_WRITE_EA",
0x0020 : "FILE_EXECUTE",
0x0080 : "FILE_READ_ATTRIBUTES",
0x0100 : "FILE_WRITE_ATTRIBUTES",
}
def format_file_access_masks(masks):
"Print access masks for file object as string"
if 0 == masks:
return "0"
ret_val = list()
for current_mask in STANDARD_ACCESS_MASKS:
if current_mask & masks:
ret_val.append( STANDARD_ACCESS_MASKS[current_mask] )
masks = masks & (~current_mask)
for current_mask in FILE_ACCESS_MASKS:
if current_mask & masks:
ret_val.append( FILE_ACCESS_MASKS[current_mask] )
masks = masks & (~current_mask)
if masks:
raise RuntimeError( "Unknown access mask: {}".format("|".join(ret_val + ["0x{:x}".format(masks), ])) )
return " | ".join(ret_val)
def generate_enum_map(info_class):
result = dict()
for i in info_class.fields()[:-1]: # skip MaximumInformation
result[getattr(info_class, i[0])] = i[0]
return result
def generate_mask_map(access_addr, length_addr, count):
access = pykd.loadDWords(access_addr, count)
length = pykd.loadBytes(length_addr, count)
result = dict()
for i in range(count):
if length[i] != 0:
result[i] = access[i]
return result
class Masks:
def __init__(self, nt):
self.values = dict()
self.enums = dict()
info_class = nt.type("_FILE_INFORMATION_CLASS")
self.enums["FILE_INFORMATION_CLASS"] = generate_enum_map(info_class)
self.values["NtQueryInformationFile"] = generate_mask_map( nt.IopQueryOperationAccess,
nt.IopQueryOperationLength,
info_class.FileMaximumInformation )
self.values["NtSetInformationFile"] = generate_mask_map( nt.IopSetOperationAccess,
nt.IopSetOperationLength,
info_class.FileMaximumInformation )
info_class = nt.type("_FSINFOCLASS")
self.enums["FSINFOCLASS"] = generate_enum_map(info_class)
self.values["NtQueryVolumeInformationFile"] = generate_mask_map( nt.IopQueryFsOperationAccess,
nt.IopQueryFsOperationLength,
info_class.FileFsMaximumInformation )
self.values["NtSetVolumeInformationFile"] = generate_mask_map( nt.IopSetFsOperationAccess,
nt.IopSetFsOperationLength,
info_class.FileFsMaximumInformation )
self.version = nt.getVersion()
def print_table(f, collected, function_name, enum_name):
# Headers
versions = [".".join(["{}".format(n) for n in x.version]) for x in collected]
f.write( "| | {} | |\n".format(" | ".join(versions)) )
f.write( "| {} |\n".format(" | ".join(["---" for i in range(len(versions) + 2)])) )
values = list()
for x in collected:
values += [ i for i in x.values[function_name] ]
for i in sorted( set(values) ):
names = set([ x.enums[enum_name][i] for x in collected if i in x.enums[enum_name] ])
f.write( "| {}(={}) |".format("/".join(names), i) )
prev = None
for x in collected:
am = ""
color = ""
if i in x.values[function_name]:
am = format_file_access_masks(x.values[function_name][i])
if not prev is None:
if not prev:
color = "![A](plus_green.png)"
elif prev != am:
color = "![C](arrow_circle_double.png)"
elif i < max([ j for j in x.values[function_name] ]):
am = "![X](deny_rd_cr.png)"
f.write( " {}{} |".format(color, am) )
prev = am
f.write( " {}(={}) |\n".format("/".join(names), i) )
f.write( "| | {} | |\n".format(" | ".join(versions)) )
def collect(fs_path):
collected = list()
if not os.path.isfile(fs_path):
for name in os.listdir(fs_path):
full_name = os.path.join(fs_path, name)
if not os.path.isfile(full_name):
collected += collect(full_name)
elif name.lower() == "ntoskrnl.exe":
collected += collect(full_name)
else:
print( "Processing: {} ... ".format(fs_path) )
dump = pykd.loadDump(fs_path)
nt = pykd.module( os.path.splitext(os.path.basename(fs_path))[0] )
collected.append( Masks(nt) )
pykd.closeDump(dump)
return collected
def main():
collected = sorted(collect(".\\src"), key=lambda x: x.version[2])
print( "Generate README.md... " )
with open(".\\README.md", "w") as f:
f.write( "# ioam\n" )
f.write( "\n" )
f.write( "Required access masks (ACCESS_MASK) for system calls: [NtQueryInformationFile](#ntqueryinformationfile), [NtSetInformationFile](ntsetinformationfile), [NtQueryVolumeInformationFile](ntqueryvolumeinformationfile), [NtSetVolumeInformationFile](ntsetvolumeinformationfile).\n" )
f.write( "\n" )
f.write( "# NtQueryInformationFile\n" )
f.write( "\n" )
print_table( f, collected, "NtQueryInformationFile", "FILE_INFORMATION_CLASS" )
f.write( "\n" )
f.write( "# NtSetInformationFile\n" )
f.write( "\n" )
print_table( f, collected, "NtSetInformationFile", "FILE_INFORMATION_CLASS" )
f.write( "\n" )
f.write( "# NtQueryVolumeInformationFile\n" )
f.write( "\n" )
print_table( f, collected, "NtQueryVolumeInformationFile", "FSINFOCLASS" )
f.write( "\n" )
f.write( "# NtSetVolumeInformationFile\n" )
f.write( "\n" )
print_table( f, collected, "NtSetVolumeInformationFile", "FSINFOCLASS" )
f.write( "\n" )
f.write( "# How to generate README.md\n" )
f.write( "\n" )
f.write( "```\n" )
f.write( "> python ioam.py\n" )
f.write( "```\n" )
print( "README.md successfully generated" )
if __name__ == "__main__":
main()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment