diff --git a/samples/ntcall.py b/samples/ntcall.py new file mode 100644 index 0000000..be137e2 --- /dev/null +++ b/samples/ntcall.py @@ -0,0 +1,175 @@ +import windows +import windows.generated_def as gdef +import argparse + +KNOWN_NTCALL = {} + +def ntcall(f): + assert f.__name__.startswith("do_") + KNOWN_NTCALL[f.__name__[3:]] = f + return f + +def add_alias(f, name): + KNOWN_NTCALL[name] = f + return + + +def craft_root(root): + if root == "currentdir": + return current_dir() + raw_root_arguments = root.split("!") + root_arguments = parser.parse_args(raw_root_arguments) + print("ROOT: {0}".format(root_arguments)) + root_handle = do_ntcall_from_args(root_arguments, subcall=True) + print("Root handle is {0!r}".format(root_handle)) + return root_handle + + +def current_dir(): + print("Using for root") + return windows.current_process.peb.ProcessParameters[0].CurrentDirectory.Handle + +def obj_attr_from_args(args): + if args.translate: + print("Translating DOSpath to NtPath") + print(" * DOS: {0}".format(args.path)) + args.path = windows.utils.dospath_to_ntpath(args.path) + print(" * NT : {0}".format(args.path)) + + + objattr = gdef.OBJECT_ATTRIBUTES.from_string(args.path) + if args.root: + objattr.RootDirectory = craft_root(args.root) + if args.attributes: + objattr.Attributes = args.attributes + return objattr + +@ntcall +def do_ntcreatefile(object_attributes): + nh = gdef.HANDLE() + access = gdef.MAXIMUM_ALLOWED + ioblock = gdef.IO_STATUS_BLOCK() + alloc_size = gdef.LARGE_INTEGER(0) + attrib = gdef.FILE_ATTRIBUTE_NORMAL + share = gdef.FILE_SHARE_READ + disposition = gdef.FILE_OPEN + options = 0 + eabuff = None + easize = 0 + windows.winproxy.NtCreateFile(nh, access, object_attributes, ioblock, alloc_size, attrib, share, disposition, options, eabuff, easize) + return nh.value + +@ntcall +def do_ntopenfile(object_attributes): + nh = gdef.HANDLE() + access = gdef.MAXIMUM_ALLOWED + ioblock = gdef.IO_STATUS_BLOCK() + share = gdef.FILE_SHARE_READ + options = 0 + windows.winproxy.NtOpenFile(nh, access, object_attributes, ioblock, share, options) + return nh.value + + +@ntcall +def do_ntopenkey(object_attributes): + nh = gdef.HANDLE() + windows.winproxy.NtOpenKey(nh, gdef.MAXIMUM_ALLOWED, object_attributes) + return nh.value + +@ntcall +def do_ntcreatenamedpipefile(object_attributes): + handle = gdef.HANDLE() + access = gdef.GENERIC_READ | gdef.GENERIC_WRITE | gdef.SYNCHRONIZE + ioblock = gdef.IO_STATUS_BLOCK() + share = 3 + disposition = 0x2 + options = 0 + writemode = 1 + readmode = 1 + nonblock = 0 + MaxInstances = 0xffffffff + InBufferSize = 0x1000 + OutBufferSize = 0x1000 + timeout = gdef.LARGE_INTEGER(0xffffffffb8797400) + windows.winproxy.NtCreateNamedPipeFile(handle,access,object_attributes,ioblock,share,disposition,options,writemode,readmode,nonblock,MaxInstances,InBufferSize,OutBufferSize,timeout) + return handle.value + +@ntcall +def do_ntopendir(object_attributes): + nh = gdef.HANDLE() + windows.winproxy.NtOpenDirectoryObject(nh, gdef.MAXIMUM_ALLOWED, object_attributes) + return nh.value + + +@ntcall +def do_ntcreatesection(object_attributes): + nh = gdef.HANDLE() + access = gdef.MAXIMUM_ALLOWED + size = gdef.LARGE_INTEGER(0x1000) + prot = gdef.PAGE_READONLY + alloc_attr = gdef.SEC_COMMIT + windows.winproxy.NtCreateSection(nh, access, object_attributes, size, prot, alloc_attr, None) + return nh.value + +@ntcall +def do_ntopensection(object_attributes): + nh = gdef.HANDLE() + access = gdef.MAXIMUM_ALLOWED + windows.winproxy.NtOpenSection(nh, access, object_attributes) + return nh.value + +@ntcall +def do_ntopensymboliclinkobject(object_attributes): + nh = gdef.HANDLE() + access = gdef.MAXIMUM_ALLOWED + windows.winproxy.NtOpenSymbolicLinkObject(nh, access , object_attributes) + return nh.value + +add_alias(do_ntopensymboliclinkobject, "opensymlink") + +@ntcall +def do_ntcreatesymboliclinkobject(object_attributes): + nh = gdef.HANDLE() + access = gdef.MAXIMUM_ALLOWED + # dest = gdef.UNICODE_STRING.from_string(r"\RPC Control\yolo_link") # Make a param + dest = gdef.UNICODE_STRING.from_string(r"\Device\NamedPipe") # Make a param + windows.winproxy.NtCreateSymbolicLinkObject(nh, access, object_attributes, dest) + return nh.value + + +def do_ntcall_from_args(args, subcall=False): + obj_attr = obj_attr_from_args(args) + if not subcall: + print("== Object Attribute ==") + else: + print("== Object Attribute (for root directory) ==") + windows.utils.sprint(obj_attr, name=" objattr") + func = KNOWN_NTCALL[args.function] + try: + handle = func(obj_attr) + except WindowsError as e: + print("== NtCall Error ==") + print(" {0!r}".format(e)) + if subcall: + raise + return False + print("== NtCall Success ==") + print(" handle={0:#x}".format(handle)) + print("== Handle analysis ==") + hinfo = [x for x in windows.current_process.handles if x.value == handle][0] + print(" * Name: {0}".format(hinfo.name)) + print(" * Type: {0}".format(hinfo.type)) + print(" * Addr: {0:#x}".format(hinfo.pAddress)) + return handle + + +parser = argparse.ArgumentParser(prog=__file__) +parser.add_argument("function", choices=KNOWN_NTCALL) +parser.add_argument("path") +parser.add_argument("--root") +parser.add_argument("--attributes", type=int) +parser.add_argument("--translate", action="store_true", help="Translate using ") + + +args = parser.parse_args() +do_ntcall_from_args(args) \ No newline at end of file