diff options
Diffstat (limited to 'miasm/os_dep')
| -rw-r--r-- | miasm/os_dep/__init__.py | 1 | ||||
| -rw-r--r-- | miasm/os_dep/common.py | 169 | ||||
| -rw-r--r-- | miasm/os_dep/linux/__init__.py | 1 | ||||
| -rw-r--r-- | miasm/os_dep/linux/environment.py | 993 | ||||
| -rw-r--r-- | miasm/os_dep/linux/syscall.py | 1129 | ||||
| -rw-r--r-- | miasm/os_dep/linux_stdlib.py | 213 | ||||
| -rw-r--r-- | miasm/os_dep/win_32_structs.py | 231 | ||||
| -rw-r--r-- | miasm/os_dep/win_api_x86_32.py | 3595 | ||||
| -rw-r--r-- | miasm/os_dep/win_api_x86_32_seh.py | 705 |
9 files changed, 0 insertions, 7037 deletions
diff --git a/miasm/os_dep/__init__.py b/miasm/os_dep/__init__.py deleted file mode 100644 index 6aa660d8..00000000 --- a/miasm/os_dep/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"Operating System specific methods" diff --git a/miasm/os_dep/common.py b/miasm/os_dep/common.py deleted file mode 100644 index 74100817..00000000 --- a/miasm/os_dep/common.py +++ /dev/null @@ -1,169 +0,0 @@ -import os - -from future.utils import viewitems - -from miasm.core.utils import force_bytes, force_str -from miasm.jitter.csts import PAGE_READ, PAGE_WRITE -from miasm.core.utils import get_caller_name -from miasm.core.utils import pck64, upck64 - -BASE_SB_PATH = "file_sb" -WIN_CODEPAGE = "cp1252" - -def get_win_str_a(jitter, ad_str, max_char=None): - l = 0 - tmp = ad_str - while ((max_char is None or l < max_char) and - jitter.vm.get_mem(tmp, 1) != b"\x00"): - tmp += 1 - l += 1 - data = jitter.vm.get_mem(ad_str, l) - ret = data.decode(WIN_CODEPAGE) - return ret - - -def get_win_str_w(jitter, ad_str, max_char=None): - l = 0 - tmp = ad_str - while ((max_char is None or l < max_char) and - jitter.vm.get_mem(tmp, 2) != b"\x00\x00"): - tmp += 2 - l += 2 - s = jitter.vm.get_mem(ad_str, l) - s = s.decode("utf-16le") - return s - -def encode_win_str_a(value): - value = value.encode(WIN_CODEPAGE) + b"\x00" - return value - -def encode_win_str_w(value): - value = value.encode("utf-16le") + b'\x00' * 2 - return value - - -def set_win_str_a(jitter, addr, value): - value = encode_win_str_a(value) - jitter.vm.set_mem(addr, value) - - -def set_win_str_w(jitter, addr, value): - value = encode_win_str_w(value) - jitter.vm.set_mem(addr, value) - - -class heap(object): - - "Light heap simulation" - - addr = 0x20000000 - align = 0x1000 - size = 32 - mask = (1 << size) - 1 - - def next_addr(self, size): - """ - @size: the size to allocate - return the future checnk address - """ - ret = self.addr - self.addr = (self.addr + size + self.align - 1) - self.addr &= self.mask ^ (self.align - 1) - return ret - - def alloc(self, jitter, size, perm=PAGE_READ | PAGE_WRITE, cmt=""): - """ - @jitter: a jitter instance - @size: the size to allocate - @perm: permission flags (see vm_alloc doc) - """ - return self.vm_alloc(jitter.vm, size, perm=perm, cmt=cmt) - - def vm_alloc(self, vm, size, perm=PAGE_READ | PAGE_WRITE, cmt=""): - """ - @vm: a VmMngr instance - @size: the size to allocate - @perm: permission flags (PAGE_READ, PAGE_WRITE, PAGE_EXEC or any `|` - combination of them); default is PAGE_READ|PAGE_WRITE - """ - addr = self.next_addr(size) - vm.add_memory_page( - addr, - perm, - b"\x00" * (size), - "Heap alloc by %s %s" % (get_caller_name(2), cmt) - ) - return addr - - def get_size(self, vm, ptr): - """ - @vm: a VmMngr instance - @size: ptr to get the size of the associated allocation. - - `ptr` can be the base address of a previous allocation, or an address - within the allocated range. The size of the whole allocation is always - returned, regardless ptr is the base address or not. - """ - assert vm.is_mapped(ptr, 1) - data = vm.get_all_memory() - ptr_page = data.get(ptr, None) - if ptr_page is None: - for address, page_info in viewitems(data): - if address <= ptr < address + page_info["size"]: - ptr_page = page_info - break - else: - raise RuntimeError("Must never happen (unmapped but mark as mapped by API)") - return ptr_page["size"] - - -def windows_to_sbpath(path): - """Convert a Windows path to a valid filename within the sandbox - base directory. - - """ - path = [elt for elt in path.lower().replace('/', '_').split('\\') if elt] - return os.path.join(BASE_SB_PATH, *path) - - -def unix_to_sbpath(path): - """Convert a POSIX path to a valid filename within the sandbox - base directory. - - """ - path = [elt for elt in path.split('/') if elt] - return os.path.join(BASE_SB_PATH, *path) - -def get_fmt_args(fmt, cur_arg, get_str, get_arg_n): - idx = 0 - fmt = get_str(fmt) - chars_format = '%cdfsuxX' - char_percent = '%' - char_string = 's' - output = "" - - while True: - if idx == len(fmt): - break - char = fmt[idx:idx+1] - idx += 1 - if char == char_percent: - token = char_percent - while True: - char = fmt[idx:idx+1] - idx += 1 - token += char - if char in chars_format: - break - if char == char_percent: - output += char - continue - if token.endswith(char_string): - addr = get_arg_n(cur_arg) - arg = get_str(addr) - else: - arg = get_arg_n(cur_arg) - char = token % arg - cur_arg += 1 - output += char - return output diff --git a/miasm/os_dep/linux/__init__.py b/miasm/os_dep/linux/__init__.py deleted file mode 100644 index 4434ce50..00000000 --- a/miasm/os_dep/linux/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# Linux emulation diff --git a/miasm/os_dep/linux/environment.py b/miasm/os_dep/linux/environment.py deleted file mode 100644 index 3ba4382f..00000000 --- a/miasm/os_dep/linux/environment.py +++ /dev/null @@ -1,993 +0,0 @@ -from __future__ import print_function -from collections import namedtuple -import functools -import logging -import os -import re -import struct -import termios - -from future.utils import viewitems - -from miasm.core.interval import interval -from miasm.jitter.csts import PAGE_READ, PAGE_WRITE - - -REGEXP_T = type(re.compile(r'')) - -StatInfo = namedtuple("StatInfo", [ - "st_dev", "st_ino", "st_nlink", "st_mode", "st_uid", "st_gid", "st_rdev", - "st_size", "st_blksize", "st_blocks", "st_atime", "st_atimensec", - "st_mtime", "st_mtimensec", "st_ctime", "st_ctimensec" -]) -StatFSInfo = namedtuple("StatFSInfo", [ - "f_type", "f_bsize", "f_blocks", "f_bfree", "f_bavail", "f_files", - "f_ffree", "f_fsid", "f_namelen", "f_frsize", "f_flags", "f_spare", -]) - -log = logging.getLogger("environment") -console_handler = logging.StreamHandler() -console_handler.setFormatter(logging.Formatter("[%(levelname)-8s]: %(message)s")) -log.addHandler(console_handler) -log.setLevel(logging.WARNING) - -class FileDescriptor(object): - """Stand for a file descriptor on a system - - According to inode(7), following types are possibles: - - socket - - symbolic link - - regular file - - block device - - directory - - character device - - FIFO - """ - - # st_mode's file type - file_type = None - # st_mode's file mode (9 least bits are file permission bits) - file_mode = 0o0777 - # st_dev / st_rdev - cont_device_id = None - device_id = 0 - # inode number (st_ino) - inode = None - # Number of hardlink (st_nlink) - nlink = 0 - # Owner / group - uid = None - gid = None - # Size (st_size / st_blksize / st_blocks) - size = 0 - blksize = 0 - blocks = 0 - # Times - atime = 0 - atimensec = 0 - mtime = 0 - mtimensec = 0 - ctime = 0 - ctimensec = 0 - - def __init__(self, number): - self.number = number - self.is_closed = False - - def stat(self): - mode = self.file_type | self.file_mode - return StatInfo( - st_dev=self.cont_device_id, st_ino=self.inode, - st_nlink=self.nlink, st_mode=mode, - st_uid=self.uid, st_gid=self.gid, - st_rdev=self.device_id, st_size=self.size, - st_blksize=self.blksize, st_blocks=self.blocks, - st_atime=self.atime, st_atimensec=self.atimensec, - st_mtime=self.mtime, st_mtimensec=self.mtimensec, - st_ctime=self.ctime, st_ctimensec=self.ctimensec - ) - - def close(self): - self.is_closed = True - - -class FileDescriptorCharDevice(FileDescriptor): - file_type = 0o0020000 # S_IFCHR - file_mode = 0o0620 - cont_device_id = 1 - device_id = 1 - - -class FileDescriptorSTDIN(FileDescriptorCharDevice): - """Special file descriptor standinf for STDIN""" - inode = 0 - - def read(self, count): - raise RuntimeError("Not implemented") - - -class FileDescriptorSTDOUT(FileDescriptorCharDevice): - """Special file descriptor standinf for STDOUT""" - inode = 1 - - def write(self, data): - print("[STDOUT] %s" % data.rstrip()) - - -class FileDescriptorSTDERR(FileDescriptorCharDevice): - """Special file descriptor standinf for STDERR""" - inode = 2 - - def write(self, data): - print("[STDERR] %s" % data.rstrip()) - - -class FileDescriptorDirectory(FileDescriptor): - """FileDescription designing a directory""" - - file_type = 0o0040000 # S_IFDIR - - def __init__(self, number, flags, filesystem, real_path): - super(FileDescriptorDirectory, self).__init__(number) - self.filesystem = filesystem - self.real_path = real_path - self.cur_listdir = None - self.flags = flags - - def listdir(self): - if self.cur_listdir is None: - self.cur_listdir = os.listdir(self.real_path) - while self.cur_listdir: - yield self.cur_listdir.pop() - - -class FileDescriptorRegularFile(FileDescriptor): - """FileDescriptor designing a regular file""" - - file_type = 0o0100000 # S_IFREG - - def __init__(self, number, flags, filesystem, real_fd): - super(FileDescriptorRegularFile, self).__init__(number) - self.flags = flags - self.filesystem = filesystem - self.real_fd = real_fd - - def write(self, data): - raise RuntimeError("Not implemented") - - def read(self, count): - return os.read(self.real_fd, count) - - def close(self): - super(FileDescriptorRegularFile, self).close() - return os.close(self.real_fd) - - def lseek(self, offset, whence): - return os.lseek(self.real_fd, offset, whence) # SEEK_SET - - def tell(self): - return self.lseek(0, 1) # SEEK_CUR - - def seek(self, offset): - return self.lseek(offset, 0) # SEEK_SET - - -class FileDescriptorSocket(FileDescriptor): - """FileDescription standing for a socket""" - - file_type = 0o0140000 # S_IFSOCK - - def __init__(self, number, family, type_, protocol): - super(FileDescriptorSocket, self).__init__(number) - self.family = family - self.type_ = type_ - self.protocol = protocol - - -class FileSystem(object): - """File system abstraction - Provides standard operations on the filesystem, (a bit like FUSE) - - API using FileSystem only used sandbox-side path. FileSystem should be the - only object able to interact with real path, outside the sandbox. - - Thus, if `resolve_path` is correctly implemented and used, it should not be - possible to modify files outside the sandboxed path - """ - - device_id = 0x1234 # ID of device containing file (stat.st_dev) - blocksize = 0x1000 # Size of block on this filesystem - f_type = 0xef53 # (Type of filesystem) EXT4_SUPER_MAGIC - nb_total_block = 0x1000 - nb_free_block = 0x100 - nb_avail_block = nb_free_block # Available to unprivileged user - nb_total_fnode = 100 # Total file nodes in filesystem - nb_free_fnode = 50 - max_filename_len = 256 - fragment_size = 0 - mount_flags = 0 - - def __init__(self, base_path, linux_env): - self.base_path = base_path - self.linux_env = linux_env - self.passthrough = [] - self.path_to_inode = {} # Real path (post-resolution) -> inode number - - def resolve_path(self, path, follow_link=True): - """Resolve @path to the corresponding sandboxed path""" - - # path_bytes is used for Python 2 / Python 3 compatibility - path_bytes = not isinstance(path, str) - path_sep = os.path.sep.encode() if path_bytes else os.path.sep - - if path_bytes: - def _convert(subpath): - if not isinstance(subpath, str): - return subpath - return subpath.encode() - def _convert_re(expr): - if isinstance(expr.pattern, str): - try: - return re.compile( - expr.pattern.encode(), - flags=expr.flags & ~re.UNICODE - ) - except UnicodeEncodeError: - # Will never match - log.warning( - 'Cannot convert regexp to bytes %r %r', - expr.pattern, - expr.flags, - exc_info=True, - ) - return re.compile(b'$X') - return expr - else: - def _convert(subpath): - if not isinstance(subpath, str): - return subpath.decode() - return subpath - def _convert_re(expr): - if not isinstance(expr.pattern, str): - try: - return re.compile( - expr.pattern.decode(), - flags=expr.flags & re.UNICODE - ) - except UnicodeDecodeError: - # Will never match - log.warning( - 'Cannot convert regexp to str %r %r', - expr.pattern, - expr.flags, - exc_info=True, - ) - return re.compile(r'$X') - return expr - - # Remove '../', etc. - path = os.path.normpath(path) - - # Passthrough - for passthrough in self.passthrough: - if isinstance(passthrough, REGEXP_T): - if _convert_re(passthrough).match(path): - return path - elif _convert(passthrough) == path: - return path - - # Remove leading '/' if any - path = path.lstrip(path_sep) - - base_path = os.path.abspath(_convert(self.base_path)) - out_path = os.path.join(base_path, path) - assert out_path.startswith(base_path + path_sep) - if os.path.islink(out_path): - link_target = os.readlink(out_path) - # Link can be absolute or relative -> absolute - link = os.path.normpath(os.path.join(os.path.dirname(path), link_target)) - if follow_link: - out_path = self.resolve_path(link) - else: - out_path = link - return out_path - - def get_path_inode(self, real_path): - inode = self.path_to_inode.setdefault(real_path, len(self.path_to_inode)) - return inode - - def exists(self, path): - sb_path = self.resolve_path(path) - return os.path.exists(sb_path) - - def readlink(self, path): - sb_path = self.resolve_path(path, follow_link=False) - if not os.path.islink(sb_path): - return None - return os.readlink(sb_path) - - def statfs(self): - return StatFSInfo( - f_type=self.f_type, f_bsize=self.blocksize, - f_blocks=self.nb_total_block, f_bfree=self.nb_free_block, - f_bavail=self.nb_avail_block, f_files=self.nb_total_fnode, - f_ffree=self.nb_free_fnode, f_fsid=self.device_id, - f_namelen=self.max_filename_len, - f_frsize=self.fragment_size, f_flags=self.mount_flags, f_spare=0) - - def getattr_(self, path, follow_link=True): - sb_path = self.resolve_path(path, follow_link=follow_link) - flags = self.linux_env.O_RDONLY - if os.path.isdir(sb_path): - flags |= self.linux_env.O_DIRECTORY - - fd = self.open_(path, flags, follow_link=follow_link) - info = self.linux_env.fstat(fd) - self.linux_env.close(fd) - return info - - def open_(self, path, flags, follow_link=True): - path = self.resolve_path(path, follow_link=follow_link) - if not os.path.exists(path): - # ENOENT (No such file or directory) - return -1 - fd = self.linux_env.next_fd() - acc_mode = flags & self.linux_env.O_ACCMODE - - if os.path.isdir(path): - assert flags & self.linux_env.O_DIRECTORY == self.linux_env.O_DIRECTORY - if acc_mode == self.linux_env.O_RDONLY: - fdesc = FileDescriptorDirectory(fd, flags, self, path) - else: - raise RuntimeError("Not implemented") - elif os.path.isfile(path): - if acc_mode == os.O_RDONLY: - # Read only - real_fd = os.open(path, os.O_RDONLY) - else: - raise RuntimeError("Not implemented") - fdesc = FileDescriptorRegularFile(fd, flags, self, real_fd) - - elif os.path.islink(path): - raise RuntimeError("Not implemented") - else: - raise RuntimeError("Unknown file type for %r" % path) - - self.linux_env.file_descriptors[fd] = fdesc - # Set stat info - fdesc.cont_device_id = self.device_id - fdesc.inode = self.get_path_inode(path) - fdesc.uid = self.linux_env.user_uid - fdesc.gid = self.linux_env.user_gid - size = os.path.getsize(path) - fdesc.size = size - fdesc.blksize = self.blocksize - fdesc.blocks = (size + ((512 - (size % 512)) % 512)) // 512 - return fd - - -class Networking(object): - """Network abstraction""" - - def __init__(self, linux_env): - self.linux_env = linux_env - - def socket(self, family, type_, protocol): - fd = self.linux_env.next_fd() - fdesc = FileDescriptorSocket(fd, family, type_, protocol) - self.linux_env.file_descriptors[fd] = fdesc - return fd - - -class LinuxEnvironment(object): - """A LinuxEnvironment regroups information to simulate a Linux-like - environment""" - - # To be overridden - platform_arch = None - - # User information - user_uid = 1000 - user_euid = 1000 - user_gid = 1000 - user_egid = 1000 - user_name = b"user" - - # Memory mapping information - brk_current = 0x74000000 - mmap_current = 0x75000000 - - # System information - sys_sysname = b"Linux" - sys_nodename = b"user-pc" - sys_release = b"4.13.0-19-generic" - sys_version = b"#22-Ubuntu" - sys_machine = None - - # Filesystem - filesystem_base = "file_sb" - file_descriptors = None - - # Current process - process_tid = 1000 - process_pid = 1000 - - # Syscall restrictions - ioctl_allowed = None # list of (fd, cmd), None value for wildcard - ioctl_disallowed = None # list of (fd, cmd), None value for wildcard - - # Time - base_time = 1531900000 - - # Arch specific constant - O_ACCMODE = None - O_CLOEXEC = None - O_DIRECTORY = None - O_LARGEFILE = None - O_NONBLOCK = None - O_RDONLY = None - - def __init__(self): - stdin = FileDescriptorSTDIN(0) - stdout = FileDescriptorSTDOUT(1) - stderr = FileDescriptorSTDERR(2) - for std in [stdin, stdout, stderr]: - std.uid = self.user_uid - std.gid = self.user_gid - self.file_descriptors = { - 0: stdin, - 1: stdout, - 2: stderr, - } - self.ioctl_allowed = [ - (0, termios.TCGETS), - (0, termios.TIOCGWINSZ), - (0, termios.TIOCSWINSZ), - (1, termios.TCGETS), - (1, termios.TIOCGWINSZ), - (1, termios.TIOCSWINSZ), - ] - self.ioctl_disallowed = [ - (2, termios.TCGETS), - (0, termios.TCSETSW), - ] - self.filesystem = FileSystem(self.filesystem_base, self) - self.network = Networking(self) - - def next_fd(self): - return len(self.file_descriptors) - - def clock_gettime(self): - out = self.base_time - self.base_time += 1 - return out - - def open_(self, path, flags, follow_link=True): - """Stub for 'open' syscall""" - return self.filesystem.open_(path, flags, follow_link=follow_link) - - def socket(self, family, type_, protocol): - """Stub for 'socket' syscall""" - return self.network.socket(family, type_, protocol) - - def fstat(self, fd): - """Get file status through fd""" - fdesc = self.file_descriptors.get(fd) - if fdesc is None: - return None - return fdesc.stat() - - def stat(self, path): - """Get file status through path""" - return self.filesystem.getattr_(path) - - def lstat(self, path): - """Get file status through path (not following links)""" - return self.filesystem.getattr_(path, follow_link=False) - - def close(self, fd): - """Stub for 'close' syscall""" - fdesc = self.file_descriptors.get(fd) - if fdesc is None: - return None - return fdesc.close() - - def write(self, fd, data): - """Stub for 'write' syscall""" - fdesc = self.file_descriptors.get(fd) - if fdesc is None: - return None - fdesc.write(data) - return len(data) - - def read(self, fd, count): - """Stub for 'read' syscall""" - fdesc = self.file_descriptors.get(fd) - if fdesc is None: - return None - return fdesc.read(count) - - def getdents(self, fd, count, packing_callback): - """Stub for 'getdents' syscall - - 'getdents64' must be handled by caller (only the structure layout is - modified) - - @fd: getdents' fd argument - @count: getdents' count argument - @packing_callback(cur_len, d_ino, d_type, name) -> entry - """ - fdesc = self.file_descriptors[fd] - if not isinstance(fdesc, FileDescriptorDirectory): - raise RuntimeError("Not implemented") - - out = b"" - # fdesc.listdir continues from where it stopped - for name in fdesc.listdir(): - d_ino = 1 # Not the real one - d_type = 0 # DT_UNKNOWN (getdents(2) "All applications must properly - # handle a return of DT_UNKNOWN.") - entry = packing_callback(len(out), d_ino, d_type, name) - - if len(out) + len(entry) > count: - # Report to a further call - fdesc.cur_listdir.append(name) - break - out = out + entry - return out - - def ioctl(self, fd, cmd, arg): - """Stub for 'ioctl' syscall - Return the list of element to pack back depending on target ioctl - If the ioctl is disallowed, return False - """ - allowed = False - disallowed = False - for test in [(fd, cmd), (None, cmd), (fd, None)]: - if test in self.ioctl_allowed: - allowed = True - if test in self.ioctl_disallowed: - disallowed = True - - if allowed and disallowed: - raise ValueError("fd: %x, cmd: %x is allowed and disallowed" % (fd, cmd)) - - if allowed: - if cmd == termios.TCGETS: - return 0, 0, 0, 0 - elif cmd == termios.TIOCGWINSZ: - # struct winsize - # { - # unsigned short ws_row; /* rows, in characters */ - # unsigned short ws_col; /* columns, in characters */ - # unsigned short ws_xpixel; /* horizontal size, pixels */ - # unsigned short ws_ypixel; /* vertical size, pixels */ - # }; - return 1000, 360, 1000, 1000 - elif cmd == termios.TIOCSWINSZ: - # Ignore it - return - else: - raise RuntimeError("Not implemented") - - elif disallowed: - return False - - else: - raise KeyError("Unknown ioctl fd:%x cmd:%x" % (fd, cmd)) - - def mmap(self, addr, len_, prot, flags, fd, off, vmmngr): - """Stub for 'mmap' syscall - - 'mmap2' must be implemented by calling this function with off * 4096 - """ - if addr == 0: - addr = self.mmap_current - self.mmap_current += (len_ + 0x1000) & ~0xfff - - all_mem = vmmngr.get_all_memory() - mapped = interval( - [ - (start, start + info["size"] - 1) - for start, info in viewitems(all_mem) - ] - ) - - MAP_FIXED = 0x10 - if flags & MAP_FIXED: - # Alloc missing and override - missing = interval([(addr, addr + len_ - 1)]) - mapped - for start, stop in missing: - vmmngr.add_memory_page( - start, - PAGE_READ|PAGE_WRITE, - b"\x00" * (stop - start + 1), - "mmap allocated" - ) - else: - # Find first candidate segment nearby addr - for start, stop in mapped: - if stop < addr: - continue - rounded = (stop + 1 + 0x1000) & ~0xfff - if (interval([(rounded, rounded + len_)]) & mapped).empty: - addr = rounded - break - else: - assert (interval([(addr, addr + len_)]) & mapped).empty - - vmmngr.add_memory_page( - addr, - PAGE_READ|PAGE_WRITE, - b"\x00" * len_, - "mmap allocated" - ) - - if fd == 0xffffffff: - MAP_ANONYMOUS = 0x20 # mman.h - # fd and offset are ignored if MAP_ANONYMOUS flag is present - if not(flags & MAP_ANONYMOUS) and off != 0: - raise RuntimeError("Not implemented") - data = b"\x00" * len_ - else: - fdesc = self.file_descriptors[fd] - cur_pos = fdesc.tell() - fdesc.seek(off) - data = fdesc.read(len_) - fdesc.seek(cur_pos) - - vmmngr.set_mem(addr, data) - return addr - - def brk(self, addr, vmmngr): - """Stub for 'brk' syscall""" - if addr == 0: - addr = self.brk_current - else: - all_mem = vmmngr.get_all_memory() - mapped = interval( - [ - (start, start + info["size"] - 1) - for start, info in viewitems(all_mem) - ] - ) - - # Alloc missing and override - missing = interval([(self.brk_current, addr)]) - mapped - for start, stop in missing: - vmmngr.add_memory_page( - start, - PAGE_READ|PAGE_WRITE, - b"\x00" * (stop - start + 1), - "BRK" - ) - - self.brk_current = addr - return addr - - -class LinuxEnvironment_x86_32(LinuxEnvironment): - platform_arch = b"x86_32" - sys_machine = b"x86_32" - - # TODO FIXME - ## O_ACCMODE = 0x3 - ## O_CLOEXEC = 0x80000 - ## O_DIRECTORY = 0x10000 - ## O_LARGEFILE = 0x8000 - ## O_NONBLOCK = 0x800 - ## O_RDONLY = 0 - - -class LinuxEnvironment_x86_64(LinuxEnvironment): - platform_arch = b"x86_64" - sys_machine = b"x86_64" - - O_ACCMODE = 0x3 - O_CLOEXEC = 0x80000 - O_DIRECTORY = 0x10000 - O_LARGEFILE = 0x8000 - O_NONBLOCK = 0x800 - O_RDONLY = 0 - - -class LinuxEnvironment_arml(LinuxEnvironment): - platform_arch = b"arml" - sys_machine = b"arml" - - O_ACCMODE = 0x3 - O_CLOEXEC = 0x80000 - O_DIRECTORY = 0x4000 - O_LARGEFILE = 0x20000 - O_NONBLOCK = 0x800 - O_RDONLY = 0 - - # ARM specific - tls = 0 - # get_tls: __kuser_helper_version >= 1 - # cmpxchg: __kuser_helper_version >= 2 - # memory_barrier: __kuser_helper_version >= 3 - kuser_helper_version = 3 - - -class LinuxEnvironment_mips32b(LinuxEnvironment): - platform_arch = b"mips32b" - sys_machine = b"mips32b" - - -class AuxVec(object): - """Auxiliary vector abstraction, filled with default values - (mainly based on https://lwn.net/Articles/519085) - - # Standard usage - >>> auxv = AuxVec(elf_base_addr, cont_target.entry_point, linux_env) - - # Enable AT_SECURE - >>> auxv = AuxVec(..., AuxVec.AT_SECURE=1) - # Modify AT_RANDOM - >>> auxv = AuxVec(..., AuxVec.AT_RANDOM="\x00"*0x10) - - # Using AuxVec instance for stack preparation - # First, fill memory with vectors data - >>> for AT_number, data in auxv.data_to_map(): - dest_ptr = ... - copy_to_dest(data, dest_ptr) - auxv.ptrs[AT_number] = dest_ptr - # Then, get the key: value (with value being sometime a pointer) - >>> for auxid, auxval in auxv.iteritems(): - ... - """ - - AT_PHDR = 3 - AT_PHNUM = 5 - AT_PAGESZ = 6 - AT_ENTRY = 9 - AT_UID = 11 - AT_EUID = 12 - AT_GID = 13 - AT_EGID = 14 - AT_PLATFORM = 15 - AT_HWCAP = 16 - AT_SECURE = 23 - AT_RANDOM = 25 - AT_SYSINFO_EHDR = 33 - - def __init__(self, elf_phdr_vaddr, entry_point, linux_env, **kwargs): - """Instantiate an AuxVec, with required elements: - - elf_phdr_vaddr: virtual address of the ELF's PHDR in memory - - entry_point: virtual address of the ELF entry point - - linux_env: LinuxEnvironment instance, used to provides some of the - option values - - Others options can be overridden by named arguments - - """ - self.info = { - self.AT_PHDR: elf_phdr_vaddr, - self.AT_PHNUM: 9, - self.AT_PAGESZ: 0x1000, - self.AT_ENTRY: entry_point, - self.AT_UID: linux_env.user_uid, - self.AT_EUID: linux_env.user_euid, - self.AT_GID: linux_env.user_gid, - self.AT_EGID: linux_env.user_egid, - self.AT_PLATFORM: linux_env.platform_arch, - self.AT_HWCAP: 0, - self.AT_SECURE: 0, - self.AT_RANDOM: b"\x00" * 0x10, - # vDSO is not mandatory - self.AT_SYSINFO_EHDR: None, - } - self.info.update(kwargs) - self.ptrs = {} # info key -> corresponding virtual address - - def data_to_map(self): - """Iterator on (AT_number, data) - Once the data has been mapped, the corresponding ptr must be set in - 'self.ptrs[AT_number]' - """ - for AT_number in [self.AT_PLATFORM, self.AT_RANDOM]: - yield (AT_number, self.info[AT_number]) - - def iteritems(self): - """Iterator on auxiliary vector id and values""" - for AT_number, value in viewitems(self.info): - if AT_number in self.ptrs: - value = self.ptrs[AT_number] - if value is None: - # AT to ignore - continue - yield (AT_number, value) - - items = iteritems - -def prepare_loader_x86_64(jitter, argv, envp, auxv, linux_env, - hlt_address=0x13371acc): - """Fill the environment with enough information to run a linux loader - - @jitter: Jitter instance - @argv: list of strings - @envp: dict of environment variables names to their values - @auxv: AuxVec instance - @hlt_address (default to 0x13371acc): stopping address - - Example of use: - >>> jitter = machine.jitter() - >>> jitter.init_stack() - >>> linux_env = LinuxEnvironment_x86_64() - >>> argv = ["/bin/ls", "-lah"] - >>> envp = {"PATH": "/usr/local/bin", "USER": linux_env.user_name} - >>> auxv = AuxVec(elf_base_addr, entry_point, linux_env) - >>> prepare_loader_x86_64(jitter, argv, envp, auxv, linux_env) - # One may want to enable syscall handling here - # The program can now run from the loader - >>> jitter.init_run(ld_entry_point) - >>> jitter.continue_run() - """ - # Stack layout looks like - # [data] - # - auxv values - # - envp name=value - # - argv arguments - # [auxiliary vector] - # [environment pointer] - # [argument vector] - - for AT_number, data in auxv.data_to_map(): - data += b"\x00" - jitter.cpu.RSP -= len(data) - ptr = jitter.cpu.RSP - jitter.vm.set_mem(ptr, data) - auxv.ptrs[AT_number] = ptr - - env_ptrs = [] - for name, value in viewitems(envp): - env = b"%s=%s\x00" % (name, value) - jitter.cpu.RSP -= len(env) - ptr = jitter.cpu.RSP - jitter.vm.set_mem(ptr, env) - env_ptrs.append(ptr) - - argv_ptrs = [] - for arg in argv: - arg += b"\x00" - jitter.cpu.RSP -= len(arg) - ptr = jitter.cpu.RSP - jitter.vm.set_mem(ptr, arg) - argv_ptrs.append(ptr) - - jitter.push_uint64_t(hlt_address) - jitter.push_uint64_t(0) - jitter.push_uint64_t(0) - for auxid, auxval in viewitems(auxv): - jitter.push_uint64_t(auxval) - jitter.push_uint64_t(auxid) - jitter.push_uint64_t(0) - for ptr in reversed(env_ptrs): - jitter.push_uint64_t(ptr) - jitter.push_uint64_t(0) - for ptr in reversed(argv_ptrs): - jitter.push_uint64_t(ptr) - jitter.push_uint64_t(len(argv)) - - - -def _arml__kuser_get_tls(linux_env, jitter): - # __kuser_get_tls - jitter.pc = jitter.cpu.LR - jitter.cpu.R0 = linux_env.tls - return True - -def _arml__kuser_cmpxchg(jitter): - oldval = jitter.cpu.R0 - newval = jitter.cpu.R1 - ptr = jitter.cpu.R2 - - value = struct.unpack("<I", jitter.vm.get_mem(ptr, 4))[0] - if value == oldval: - jitter.vm.set_mem(ptr, struct.pack("<I", newval)) - jitter.cpu.R0 = 0 - jitter.cpu.cf = 1 - else: - jitter.cpu.R0 = -1 - jitter.cpu.cf = 0 - - jitter.pc = jitter.cpu.LR - return True - -def _arml__kuser_memory_barrier(jitter): - # __kuser_memory_barrier - jitter.pc = jitter.cpu.LR - return True - -def _arml__kuser_helper_version(linux_env, jitter): - jitter.pc = jitter.cpu.LR - jitter.cpu.R0 = linux_env.kuser_helper_version - return True - - -def prepare_loader_arml(jitter, argv, envp, auxv, linux_env, - hlt_address=0x13371acc): - """Fill the environment with enough information to run a linux loader - - @jitter: Jitter instance - @argv: list of strings - @envp: dict of environment variables names to their values - @auxv: AuxVec instance - @hlt_address (default to 0x13371acc): stopping address - - Example of use: - >>> jitter = machine.jitter() - >>> jitter.init_stack() - >>> linux_env = LinuxEnvironment_arml() - >>> argv = ["/bin/ls", "-lah"] - >>> envp = {"PATH": "/usr/local/bin", "USER": linux_env.user_name} - >>> auxv = AuxVec(elf_base_addr, entry_point, linux_env) - >>> prepare_loader_arml(jitter, argv, envp, auxv, linux_env) - # One may want to enable syscall handling here - # The program can now run from the loader - >>> jitter.init_run(ld_entry_point) - >>> jitter.continue_run() - """ - # Stack layout looks like - # [data] - # - auxv values - # - envp name=value - # - argv arguments - # [auxiliary vector] - # [environment pointer] - # [argument vector] - - for AT_number, data in auxv.data_to_map(): - data += b"\x00" - jitter.cpu.SP -= len(data) - ptr = jitter.cpu.SP - jitter.vm.set_mem(ptr, data) - auxv.ptrs[AT_number] = ptr - - env_ptrs = [] - for name, value in viewitems(envp): - env = b"%s=%s\x00" % (name, value) - jitter.cpu.SP -= len(env) - ptr = jitter.cpu.SP - jitter.vm.set_mem(ptr, env) - env_ptrs.append(ptr) - - argv_ptrs = [] - for arg in argv: - arg += b"\x00" - jitter.cpu.SP -= len(arg) - ptr = jitter.cpu.SP - jitter.vm.set_mem(ptr, arg) - argv_ptrs.append(ptr) - - jitter.push_uint32_t(hlt_address) - jitter.push_uint32_t(0) - jitter.push_uint32_t(0) - for auxid, auxval in viewitems(auxv): - jitter.push_uint32_t(auxval) - jitter.push_uint32_t(auxid) - jitter.push_uint32_t(0) - for ptr in reversed(env_ptrs): - jitter.push_uint32_t(ptr) - jitter.push_uint32_t(0) - for ptr in reversed(argv_ptrs): - jitter.push_uint32_t(ptr) - jitter.push_uint32_t(len(argv)) - - # Add kernel user helpers - # from Documentation/arm/kernel_user_helpers.txt - - if linux_env.kuser_helper_version >= 1: - jitter.add_breakpoint( - 0xFFFF0FE0, - functools.partial(_arml__kuser_get_tls, linux_env) - ) - - if linux_env.kuser_helper_version >= 2: - jitter.add_breakpoint(0XFFFF0FC0, _arml__kuser_cmpxchg) - - if linux_env.kuser_helper_version >= 3: - jitter.add_breakpoint(0xFFFF0FA0, _arml__kuser_memory_barrier) - - jitter.add_breakpoint(0xffff0ffc, _arml__kuser_helper_version) diff --git a/miasm/os_dep/linux/syscall.py b/miasm/os_dep/linux/syscall.py deleted file mode 100644 index bbaae1bc..00000000 --- a/miasm/os_dep/linux/syscall.py +++ /dev/null @@ -1,1129 +0,0 @@ -from builtins import range -import fcntl -import functools -import logging -import struct -import termios - -from miasm.jitter.csts import EXCEPT_INT_XX, EXCEPT_SYSCALL -from miasm.core.utils import pck64 - -log = logging.getLogger('syscalls') -hnd = logging.StreamHandler() -hnd.setFormatter(logging.Formatter("[%(levelname)-8s]: %(message)s")) -log.addHandler(hnd) -log.setLevel(logging.WARNING) - - -def _dump_struct_stat_x86_64(info): - data = struct.pack( - "QQQIIIIQQQQQQQQQQQQQ", - info.st_dev, - info.st_ino, - info.st_nlink, - info.st_mode, - info.st_uid, - info.st_gid, - 0, # 32 bit padding - info.st_rdev, - info.st_size, - info.st_blksize, - info.st_blocks, - info.st_atime, - info.st_atimensec, - info.st_mtime, - info.st_mtimensec, - info.st_ctime, - info.st_ctimensec, - 0, # unused - 0, # unused - 0, # unused - ) - return data - - -def _dump_struct_stat_arml(info): - data = struct.pack( - "QIIIIIIIIIIIIIIIIII", - info.st_dev, - 0, # pad - info.st_ino, - info.st_mode, - info.st_nlink, - info.st_uid, - info.st_gid, - info.st_rdev, - info.st_size, - info.st_blksize, - info.st_blocks, - info.st_atime, - info.st_atimensec, - info.st_mtime, - info.st_mtimensec, - info.st_ctime, - info.st_ctimensec, - 0, # unused - 0, # unused - ) - return data - - -def sys_x86_64_rt_sigaction(jitter, linux_env): - # Parse arguments - sig, act, oact, sigsetsize = jitter.syscall_args_systemv(4) - log.debug("sys_rt_sigaction(%x, %x, %x, %x)", sig, act, oact, sigsetsize) - - # Stub - if oact != 0: - # Return an empty old action - jitter.vm.set_mem(oact, b"\x00" * sigsetsize) - jitter.syscall_ret_systemv(0) - - -def sys_generic_brk(jitter, linux_env): - # Parse arguments - addr, = jitter.syscall_args_systemv(1) - log.debug("sys_brk(%d)", addr) - - # Stub - jitter.syscall_ret_systemv(linux_env.brk(addr, jitter.vm)) - - -def sys_x86_32_newuname(jitter, linux_env): - # struct utsname { - # char sysname[]; /* Operating system name (e.g., "Linux") */ - # char nodename[]; /* Name within "some implementation-defined - # network" */ - # char release[]; /* Operating system release (e.g., "2.6.28") */ - # char version[]; /* Operating system version */ - # char machine[]; /* Hardware identifier */ - # } - - # Parse arguments - nameptr, = jitter.syscall_args_systemv(1) - log.debug("sys_newuname(%x)", nameptr) - - # Stub - info = [ - linux_env.sys_sysname, - linux_env.sys_nodename, - linux_env.sys_release, - linux_env.sys_version, - linux_env.sys_machine - ] - # TODO: Elements start at 0x41 multiples on my tests... - output = b"" - for elem in info: - output += elem - output += b"\x00" * (0x41 - len(elem)) - jitter.vm.set_mem(nameptr, output) - jitter.syscall_ret_systemv(0) - - -def sys_x86_64_newuname(jitter, linux_env): - # struct utsname { - # char sysname[]; /* Operating system name (e.g., "Linux") */ - # char nodename[]; /* Name within "some implementation-defined - # network" */ - # char release[]; /* Operating system release (e.g., "2.6.28") */ - # char version[]; /* Operating system version */ - # char machine[]; /* Hardware identifier */ - # } - - # Parse arguments - nameptr, = jitter.syscall_args_systemv(1) - log.debug("sys_newuname(%x)", nameptr) - - # Stub - info = [ - linux_env.sys_sysname, - linux_env.sys_nodename, - linux_env.sys_release, - linux_env.sys_version, - linux_env.sys_machine - ] - # TODO: Elements start at 0x41 multiples on my tests... - output = b"" - for elem in info: - output += elem - output += b"\x00" * (0x41 - len(elem)) - jitter.vm.set_mem(nameptr, output) - jitter.syscall_ret_systemv(0) - - -def sys_arml_newuname(jitter, linux_env): - # struct utsname { - # char sysname[]; /* Operating system name (e.g., "Linux") */ - # char nodename[]; /* Name within "some implementation-defined - # network" */ - # char release[]; /* Operating system release (e.g., "2.6.28") */ - # char version[]; /* Operating system version */ - # char machine[]; /* Hardware identifier */ - # } - - # Parse arguments - nameptr, = jitter.syscall_args_systemv(1) - log.debug("sys_newuname(%x)", nameptr) - - # Stub - info = [ - linux_env.sys_sysname, - linux_env.sys_nodename, - linux_env.sys_release, - linux_env.sys_version, - linux_env.sys_machine - ] - # TODO: Elements start at 0x41 multiples on my tests... - output = b"" - for elem in info: - output += elem - output += b"\x00" * (0x41 - len(elem)) - jitter.vm.set_mem(nameptr, output) - jitter.syscall_ret_systemv(0) - - -def sys_generic_access(jitter, linux_env): - # Parse arguments - pathname, mode = jitter.syscall_args_systemv(2) - rpathname = jitter.get_c_str(pathname) - rmode = mode - if mode == 1: - rmode = "F_OK" - elif mode == 2: - rmode = "R_OK" - log.debug("sys_access(%s, %s)", rpathname, rmode) - - # Stub - # Do not check the mode - if linux_env.filesystem.exists(rpathname): - jitter.syscall_ret_systemv(0) - else: - jitter.syscall_ret_systemv(-1) - - -def sys_x86_64_openat(jitter, linux_env): - # Parse arguments - dfd, filename, flags, mode = jitter.syscall_args_systemv(4) - rpathname = jitter.get_c_str(filename) - log.debug("sys_openat(%x, %r, %x, %x)", dfd, rpathname, flags, mode) - - # Stub - # flags, openat particularity over 'open' are ignored - jitter.syscall_ret_systemv(linux_env.open_(rpathname, flags)) - - -def sys_x86_64_newstat(jitter, linux_env): - # Parse arguments - filename, statbuf = jitter.syscall_args_systemv(2) - rpathname = jitter.get_c_str(filename) - log.debug("sys_newstat(%r, %x)", rpathname, statbuf) - - # Stub - if linux_env.filesystem.exists(rpathname): - info = linux_env.stat(rpathname) - data = _dump_struct_stat_x86_64(info) - jitter.vm.set_mem(statbuf, data) - jitter.syscall_ret_systemv(0) - else: - # ENOENT (No such file or directory) - jitter.syscall_ret_systemv(-1) - - -def sys_arml_stat64(jitter, linux_env): - # Parse arguments - filename, statbuf = jitter.syscall_args_systemv(2) - rpathname = jitter.get_c_str(filename) - log.debug("sys_newstat(%r, %x)", rpathname, statbuf) - - # Stub - if linux_env.filesystem.exists(rpathname): - info = linux_env.stat(rpathname) - data = _dump_struct_stat_arml(info) - jitter.vm.set_mem(statbuf, data) - jitter.syscall_ret_systemv(0) - else: - # ENOENT (No such file or directory) - jitter.syscall_ret_systemv(-1) - - -def sys_x86_64_writev(jitter, linux_env): - # Parse arguments - fd, vec, vlen = jitter.syscall_args_systemv(3) - log.debug("sys_writev(%d, %d, %x)", fd, vec, vlen) - - # Stub - fdesc = linux_env.file_descriptors[fd] - for iovec_num in range(vlen): - # struct iovec { - # void *iov_base; /* Starting address */ - # size_t iov_len; /* Number of bytes to transfer */ - # }; - iovec = jitter.vm.get_mem(vec + iovec_num * 8 * 2, 8*2) - iov_base, iov_len = struct.unpack("QQ", iovec) - fdesc.write(jitter.get_c_str(iov_base)[:iov_len]) - - jitter.syscall_ret_systemv(vlen) - - -def sys_arml_writev(jitter, linux_env): - # Parse arguments - fd, vec, vlen = jitter.syscall_args_systemv(3) - log.debug("sys_writev(%d, %d, %x)", fd, vec, vlen) - - # Stub - fdesc = linux_env.file_descriptors[fd] - for iovec_num in range(vlen): - # struct iovec { - # void *iov_base; /* Starting address */ - # size_t iov_len; /* Number of bytes to transfer */ - # }; - iovec = jitter.vm.get_mem(vec + iovec_num * 4 * 2, 4*2) - iov_base, iov_len = struct.unpack("II", iovec) - fdesc.write(jitter.get_c_str(iov_base)[:iov_len]) - - jitter.syscall_ret_systemv(vlen) - - -def sys_generic_exit_group(jitter, linux_env): - # Parse arguments - status, = jitter.syscall_args_systemv(1) - log.debug("sys_exit_group(%d)", status) - - # Stub - log.debug("Exit with status code %d", status) - jitter.running = False - - -def sys_generic_read(jitter, linux_env): - # Parse arguments - fd, buf, count = jitter.syscall_args_systemv(3) - log.debug("sys_read(%d, %x, %x)", fd, buf, count) - - # Stub - data = linux_env.read(fd, count) - jitter.vm.set_mem(buf, data) - jitter.syscall_ret_systemv(len(data)) - - -def sys_x86_64_fstat(jitter, linux_env): - # Parse arguments - fd, statbuf = jitter.syscall_args_systemv(2) - log.debug("sys_fstat(%d, %x)", fd, statbuf) - - # Stub - info = linux_env.fstat(fd) - data = _dump_struct_stat_x86_64(info) - jitter.vm.set_mem(statbuf, data) - jitter.syscall_ret_systemv(0) - - -def sys_arml_fstat64(jitter, linux_env): - # Parse arguments - fd, statbuf = jitter.syscall_args_systemv(2) - log.debug("sys_fstat(%d, %x)", fd, statbuf) - - # Stub - info = linux_env.fstat(fd) - data = _dump_struct_stat_arml(info) - jitter.vm.set_mem(statbuf, data) - jitter.syscall_ret_systemv(0) - - -def sys_generic_mmap(jitter, linux_env): - # Parse arguments - addr, len_, prot, flags, fd, off = jitter.syscall_args_systemv(6) - log.debug("sys_mmap(%x, %x, %x, %x, %x, %x)", addr, len_, prot, flags, fd, off) - - # Stub - addr = linux_env.mmap(addr, len_, prot & 0xFFFFFFFF, flags & 0xFFFFFFFF, - fd & 0xFFFFFFFF, off, jitter.vm) - jitter.syscall_ret_systemv(addr) - - -def sys_generic_mmap2(jitter, linux_env): - # Parse arguments - addr, len_, prot, flags, fd, off = jitter.syscall_args_systemv(6) - log.debug("sys_mmap2(%x, %x, %x, %x, %x, %x)", addr, len_, prot, flags, fd, off) - off = off * 4096 - - # Stub - addr = linux_env.mmap(addr, len_, prot & 0xFFFFFFFF, flags & 0xFFFFFFFF, - fd & 0xFFFFFFFF, off, jitter.vm) - jitter.syscall_ret_systemv(addr) - - -def sys_generic_mprotect(jitter, linux_env): - # Parse arguments - start, len_, prot = jitter.syscall_args_systemv(3) - assert jitter.vm.is_mapped(start, len_) - log.debug("sys_mprotect(%x, %x, %x)", start, len_, prot) - - # Do nothing - jitter.syscall_ret_systemv(0) - - -def sys_generic_close(jitter, linux_env): - # Parse arguments - fd, = jitter.syscall_args_systemv(1) - log.debug("sys_close(%x)", fd) - - # Stub - linux_env.close(fd) - jitter.syscall_ret_systemv(0) - - -def sys_x86_64_arch_prctl(jitter, linux_env): - # Parse arguments - code_name = { - 0x1001: "ARCH_SET_GS", - 0x1002: "ARCH_SET_FS", - 0x1003: "ARCH_GET_FS", - 0x1004: "ARCH_GET_GS", - 0x1011: "ARCH_GET_CPUID", - 0x1012: "ARCH_SET_CPUID", - 0x2001: "ARCH_MAP_VDSO_X32", - 0x2002: "ARCH_MAP_VDSO_32", - 0x2003: "ARCH_MAP_VDSO_64", - 0x3001: "ARCH_CET_STATUS", - 0x3002: "ARCH_CET_DISABLE", - 0x3003: "ARCH_CET_LOCK", - 0x3004: "ARCH_CET_EXEC", - 0x3005: "ARCH_CET_ALLOC_SHSTK", - 0x3006: "ARCH_CET_PUSH_SHSTK", - 0x3007: "ARCH_CET_LEGACY_BITMAP", - } - code = jitter.cpu.RDI - rcode = code_name[code] - addr = jitter.cpu.RSI - log.debug("sys_arch_prctl(%s, %x)", rcode, addr) - - if code == 0x1002: - jitter.cpu.set_segm_base(jitter.cpu.FS, addr) - elif code == 0x3001: - # CET status (disabled) - jitter.vm.set_mem(addr, pck64(0)) - else: - raise RuntimeError("Not implemented") - jitter.cpu.RAX = 0 - - -def sys_x86_64_set_tid_address(jitter, linux_env): - # Parse arguments - tidptr = jitter.cpu.RDI - # clear_child_tid = tidptr - log.debug("sys_set_tid_address(%x)", tidptr) - - jitter.cpu.RAX = linux_env.process_tid - - -def sys_x86_64_set_robust_list(jitter, linux_env): - # Parse arguments - head = jitter.cpu.RDI - len_ = jitter.cpu.RSI - # robust_list = head - log.debug("sys_set_robust_list(%x, %x)", head, len_) - jitter.cpu.RAX = 0 - -def sys_x86_64_rt_sigprocmask(jitter, linux_env): - # Parse arguments - how = jitter.cpu.RDI - nset = jitter.cpu.RSI - oset = jitter.cpu.RDX - sigsetsize = jitter.cpu.R10 - log.debug("sys_rt_sigprocmask(%x, %x, %x, %x)", how, nset, oset, sigsetsize) - if oset != 0: - raise RuntimeError("Not implemented") - jitter.cpu.RAX = 0 - - -def sys_x86_64_prlimit64(jitter, linux_env): - # Parse arguments - pid = jitter.cpu.RDI - resource = jitter.cpu.RSI - new_rlim = jitter.cpu.RDX - if new_rlim != 0: - raise RuntimeError("Not implemented") - old_rlim = jitter.cpu.R10 - log.debug("sys_prlimit64(%x, %x, %x, %x)", pid, resource, new_rlim, - old_rlim) - - # Stub - if resource == 3: - # RLIMIT_STACK - jitter.vm.set_mem(old_rlim, - struct.pack("QQ", - 0x100000, - 0x7fffffffffffffff, # RLIM64_INFINITY - )) - else: - raise RuntimeError("Not implemented") - jitter.cpu.RAX = 0 - - -def sys_x86_64_statfs(jitter, linux_env): - # Parse arguments - pathname = jitter.cpu.RDI - buf = jitter.cpu.RSI - rpathname = jitter.get_c_str(pathname) - log.debug("sys_statfs(%r, %x)", rpathname, buf) - - # Stub - if not linux_env.filesystem.exists(rpathname): - jitter.cpu.RAX = -1 - else: - info = linux_env.filesystem.statfs() - raise RuntimeError("Not implemented") - - -def sys_x86_64_ioctl(jitter, linux_env): - # Parse arguments - fd, cmd, arg = jitter.syscall_args_systemv(3) - log.debug("sys_ioctl(%x, %x, %x)", fd, cmd, arg) - - info = linux_env.ioctl(fd, cmd, arg) - if info is False: - jitter.syscall_ret_systemv(-1) - else: - if cmd == termios.TCGETS: - data = struct.pack("BBBB", *info) - jitter.vm.set_mem(arg, data) - elif cmd == termios.TIOCGWINSZ: - data = struct.pack("HHHH", *info) - jitter.vm.set_mem(arg, data) - else: - assert data is None - jitter.syscall_ret_systemv(0) - - -def sys_arml_ioctl(jitter, linux_env): - # Parse arguments - fd, cmd, arg = jitter.syscall_args_systemv(3) - log.debug("sys_ioctl(%x, %x, %x)", fd, cmd, arg) - - info = linux_env.ioctl(fd, cmd, arg) - if info is False: - jitter.syscall_ret_systemv(-1) - else: - if cmd == termios.TCGETS: - data = struct.pack("BBBB", *info) - jitter.vm.set_mem(arg, data) - elif cmd == termios.TIOCGWINSZ: - data = struct.pack("HHHH", *info) - jitter.vm.set_mem(arg, data) - else: - assert data is None - jitter.syscall_ret_systemv(0) - -def sys_generic_open(jitter, linux_env): - # Parse arguments - filename, flags, mode = jitter.syscall_args_systemv(3) - rpathname = jitter.get_c_str(filename) - log.debug("sys_open(%r, %x, %x)", rpathname, flags, mode) - # Stub - # 'mode' is ignored - jitter.syscall_ret_systemv(linux_env.open_(rpathname, flags)) - - -def sys_generic_write(jitter, linux_env): - # Parse arguments - fd, buf, count = jitter.syscall_args_systemv(3) - log.debug("sys_write(%d, %x, %x)", fd, buf, count) - - # Stub - data = jitter.vm.get_mem(buf, count) - jitter.syscall_ret_systemv(linux_env.write(fd, data)) - - -def sys_x86_64_getdents(jitter, linux_env): - # Parse arguments - fd = jitter.cpu.RDI - dirent = jitter.cpu.RSI - count = jitter.cpu.RDX - log.debug("sys_getdents(%x, %x, %x)", fd, dirent, count) - - # Stub - def packing_callback(cur_len, d_ino, d_type, name): - # struct linux_dirent { - # unsigned long d_ino; /* Inode number */ - # unsigned long d_off; /* Offset to next linux_dirent */ - # unsigned short d_reclen; /* Length of this linux_dirent */ - # char d_name[]; /* Filename (null-terminated) */ - # /* length is actually (d_reclen - 2 - - # offsetof(struct linux_dirent, d_name)) */ - # /* - # char pad; // Zero padding byte - # char d_type; // File type (only since Linux - # // 2.6.4); offset is (d_reclen - 1) - # */ - # } - d_reclen = 8 * 2 + 2 + 1 + len(name) + 1 - d_off = cur_len + d_reclen - entry = struct.pack("QqH", d_ino, d_off, d_reclen) + \ - name.encode("utf8") + b"\x00" + struct.pack("B", d_type) - assert len(entry) == d_reclen - return entry - - out = linux_env.getdents(fd, count, packing_callback) - jitter.vm.set_mem(dirent, out) - jitter.cpu.RAX = len(out) - - -def sys_arml_getdents64(jitter, linux_env): - # Parse arguments - fd = jitter.cpu.R0 - dirent = jitter.cpu.R1 - count = jitter.cpu.R2 - log.debug("sys_getdents64(%x, %x, %x)", fd, dirent, count) - - # Stub - def packing_callback(cur_len, d_ino, d_type, name): - # struct linux_dirent64 { - # ino64_t d_ino; /* 64-bit inode number */ - # off64_t d_off; /* 64-bit offset to next structure */ - # unsigned short d_reclen; /* Size of this dirent */ - # unsigned char d_type; /* File type */ - # char d_name[]; /* Filename (null-terminated) */ - # }; - d_reclen = 8 * 2 + 2 + 1 + len(name) + 1 - d_off = cur_len + d_reclen - entry = struct.pack("QqHB", d_ino, d_off, d_reclen, d_type) + \ - name + b"\x00" - assert len(entry) == d_reclen - return entry - - out = linux_env.getdents(fd, count, packing_callback) - jitter.vm.set_mem(dirent, out) - jitter.cpu.R0 = len(out) - - -def sys_x86_64_newlstat(jitter, linux_env): - # Parse arguments - filename = jitter.cpu.RDI - statbuf = jitter.cpu.RSI - rpathname = jitter.get_c_str(filename) - log.debug("sys_newlstat(%s, %x)", rpathname, statbuf) - - # Stub - if not linux_env.filesystem.exists(rpathname): - # ENOENT (No such file or directory) - jitter.cpu.RAX = -1 - else: - info = linux_env.lstat(rpathname) - data = _dump_struct_stat_x86_64(info) - jitter.vm.set_mem(statbuf, data) - jitter.cpu.RAX = 0 - - -def sys_arml_lstat64(jitter, linux_env): - # Parse arguments - filename = jitter.cpu.R0 - statbuf = jitter.cpu.R1 - rpathname = jitter.get_c_str(filename) - log.debug("sys_newlstat(%s, %x)", rpathname, statbuf) - - # Stub - if not linux_env.filesystem.exists(rpathname): - # ENOENT (No such file or directory) - jitter.cpu.R0 = -1 - else: - info = linux_env.lstat(rpathname) - data = _dump_struct_stat_arml(info) - jitter.vm.set_mem(statbuf, data) - jitter.cpu.R0 = 0 - - -def sys_x86_64_lgetxattr(jitter, linux_env): - # Parse arguments - pathname = jitter.cpu.RDI - name = jitter.cpu.RSI - value = jitter.cpu.RDX - size = jitter.cpu.R10 - rpathname = jitter.get_c_str(pathname) - rname = jitter.get_c_str(name) - log.debug("sys_lgetxattr(%r, %r, %x, %x)", rpathname, rname, value, size) - - # Stub - jitter.vm.set_mem(value, b"\x00" * size) - jitter.cpu.RAX = 0 - - -def sys_x86_64_getxattr(jitter, linux_env): - # Parse arguments - pathname = jitter.cpu.RDI - name = jitter.cpu.RSI - value = jitter.cpu.RDX - size = jitter.cpu.R10 - rpathname = jitter.get_c_str(pathname) - rname = jitter.get_c_str(name) - log.debug("sys_getxattr(%r, %r, %x, %x)", rpathname, rname, value, size) - - # Stub - jitter.vm.set_mem(value, b"\x00" * size) - jitter.cpu.RAX = 0 - - -def sys_x86_64_socket(jitter, linux_env): - # Parse arguments - family = jitter.cpu.RDI - type_ = jitter.cpu.RSI - protocol = jitter.cpu.RDX - log.debug("sys_socket(%x, %x, %x)", family, type_, protocol) - - jitter.cpu.RAX = linux_env.socket(family, type_, protocol) - - -def sys_x86_64_connect(jitter, linux_env): - # Parse arguments - fd = jitter.cpu.RDI - uservaddr = jitter.cpu.RSI - addrlen = jitter.cpu.RDX - raddr = jitter.get_c_str(uservaddr + 2) - log.debug("sys_connect(%x, %r, %x)", fd, raddr, addrlen) - - # Stub - # Always refuse the connection - jitter.cpu.RAX = -1 - - -def sys_x86_64_clock_gettime(jitter, linux_env): - # Parse arguments - which_clock = jitter.cpu.RDI - tp = jitter.cpu.RSI - log.debug("sys_clock_gettime(%x, %x)", which_clock, tp) - - # Stub - value = linux_env.clock_gettime() - jitter.vm.set_mem(tp, struct.pack("Q", value)) - jitter.cpu.RAX = 0 - - -def sys_x86_64_lseek(jitter, linux_env): - # Parse arguments - fd = jitter.cpu.RDI - offset = jitter.cpu.RSI - whence = jitter.cpu.RDX - log.debug("sys_lseek(%d, %x, %x)", fd, offset, whence) - - # Stub - fdesc = linux_env.file_descriptors[fd] - mask = (1 << 64) - 1 - if offset > (1 << 63): - offset = - ((offset ^ mask) + 1) - - new_offset = fdesc.lseek(offset, whence) - jitter.cpu.RAX = new_offset - - -def sys_x86_64_munmap(jitter, linux_env): - # Parse arguments - addr = jitter.cpu.RDI - len_ = jitter.cpu.RSI - log.debug("sys_munmap(%x, %x)", addr, len_) - - # Do nothing - jitter.cpu.RAX = 0 - - -def sys_x86_64_readlink(jitter, linux_env): - # Parse arguments - path = jitter.cpu.RDI - buf = jitter.cpu.RSI - bufsize = jitter.cpu.RDX - rpath = jitter.get_c_str(path) - log.debug("sys_readlink(%r, %x, %x)", rpath, buf, bufsize) - - # Stub - link = linux_env.filesystem.readlink(rpath) - if link is None: - # Not a link - jitter.cpu.RAX = -1 - else: - data = link[:bufsize - 1] + b"\x00" - jitter.vm.set_mem(buf, data) - jitter.cpu.RAX = len(data) - 1 - -def sys_x86_64_getpid(jitter, linux_env): - # Parse arguments - log.debug("sys_getpid()") - - # Stub - jitter.cpu.RAX = linux_env.process_pid - - -def sys_x86_64_sysinfo(jitter, linux_env): - # Parse arguments - info = jitter.cpu.RDI - log.debug("sys_sysinfo(%x)", info) - - # Stub - data = struct.pack("QQQQQQQQQQHQQI", - 0x1234, # uptime - 0x2000, # loads (1 min) - 0x2000, # loads (5 min) - 0x2000, # loads (15 min) - 0x10000000, # total ram - 0x10000000, # free ram - 0x10000000, # shared memory - 0x0, # memory used by buffers - 0x0, # total swap - 0x0, # free swap - 0x1, # nb current processes - 0x0, # total high mem - 0x0, # available high mem - 0x1, # memory unit size - ) - jitter.vm.set_mem(info, data) - jitter.cpu.RAX = 0 - - -def sys_generic_geteuid(jitter, linux_env): - # Parse arguments - log.debug("sys_geteuid()") - - # Stub - jitter.syscall_ret_systemv(linux_env.user_euid) - - -def sys_generic_getegid(jitter, linux_env): - # Parse arguments - log.debug("sys_getegid()") - - # Stub - jitter.syscall_ret_systemv(linux_env.user_egid) - - -def sys_generic_getuid(jitter, linux_env): - # Parse arguments - log.debug("sys_getuid()") - - # Stub - jitter.syscall_ret_systemv(linux_env.user_uid) - - -def sys_generic_getgid(jitter, linux_env): - # Parse arguments - log.debug("sys_getgid()") - - # Stub - jitter.syscall_ret_systemv(linux_env.user_gid) - - -def sys_generic_setgid(jitter, linux_env): - # Parse arguments - gid, = jitter.syscall_args_systemv(1) - log.debug("sys_setgid(%x)", gid) - - # Stub - # Denied if different - if gid != linux_env.user_gid: - jitter.syscall_ret_systemv(-1) - else: - jitter.syscall_ret_systemv(0) - - -def sys_generic_setuid(jitter, linux_env): - # Parse arguments - uid, = jitter.syscall_args_systemv(1) - log.debug("sys_setuid(%x)", uid) - - # Stub - # Denied if different - if uid != linux_env.user_uid: - jitter.syscall_ret_systemv(-1) - else: - jitter.syscall_ret_systemv(0) - - -def sys_arml_set_tls(jitter, linux_env): - # Parse arguments - ptr = jitter.cpu.R0 - log.debug("sys_set_tls(%x)", ptr) - - # Stub - linux_env.tls = ptr - jitter.cpu.R0 = 0 - - -def sys_generic_fcntl64(jitter, linux_env): - # Parse arguments - fd, cmd, arg = jitter.syscall_args_systemv(3) - log.debug("sys_fcntl(%x, %x, %x)", fd, cmd, arg) - - # Stub - fdesc = linux_env.file_descriptors[fd] - if cmd == fcntl.F_GETFL: - jitter.syscall_ret_systemv(fdesc.flags) - elif cmd == fcntl.F_SETFL: - # Ignore flag change - jitter.syscall_ret_systemv(0) - elif cmd == fcntl.F_GETFD: - jitter.syscall_ret_systemv(fdesc.flags) - elif cmd == fcntl.F_SETFD: - # Ignore flag change - jitter.syscall_ret_systemv(0) - else: - raise RuntimeError("Not implemented") - - -def sys_x86_64_pread64(jitter, linux_env): - # Parse arguments - fd = jitter.cpu.RDI - buf = jitter.cpu.RSI - count = jitter.cpu.RDX - pos = jitter.cpu.R10 - log.debug("sys_pread64(%x, %x, %x, %x)", fd, buf, count, pos) - - # Stub - fdesc = linux_env.file_descriptors[fd] - cur_pos = fdesc.tell() - fdesc.seek(pos) - data = fdesc.read(count) - jitter.vm.set_mem(buf, data) - fdesc.seek(cur_pos) - jitter.cpu.RAX = len(data) - - -def sys_arml_gettimeofday(jitter, linux_env): - # Parse arguments - tv = jitter.cpu.R0 - tz = jitter.cpu.R1 - log.debug("sys_gettimeofday(%x, %x)", tv, tz) - - # Stub - value = linux_env.clock_gettime() - if tv: - jitter.vm.set_mem(tv, struct.pack("II", value, 0)) - if tz: - jitter.vm.set_mem(tz, struct.pack("II", 0, 0)) - jitter.cpu.R0 = 0 - - -def sys_mips32b_socket(jitter, linux_env): - # Parse arguments - family, type_, protocol = jitter.syscall_args_systemv(3) - log.debug("sys_socket(%x, %x, %x)", family, type_, protocol) - - ret1 = linux_env.socket(family, type_, protocol) - jitter.syscall_ret_systemv(ret1, 0, 0) - - -syscall_callbacks_x86_32 = { - 0x7A: sys_x86_32_newuname, -} - - -syscall_callbacks_x86_64 = { - 0x0: sys_generic_read, - 0x1: sys_generic_write, - 0x2: sys_generic_open, - 0x3: sys_generic_close, - 0x4: sys_x86_64_newstat, - 0x5: sys_x86_64_fstat, - 0x6: sys_x86_64_newlstat, - 0x8: sys_x86_64_lseek, - 0x9: sys_generic_mmap, - 0x10: sys_x86_64_ioctl, - 0xA: sys_generic_mprotect, - 0xB: sys_x86_64_munmap, - 0xC: sys_generic_brk, - 0xD: sys_x86_64_rt_sigaction, - 0xE: sys_x86_64_rt_sigprocmask, - 0x11: sys_x86_64_pread64, - 0x14: sys_x86_64_writev, - 0x15: sys_generic_access, - 0x27: sys_x86_64_getpid, - 0x29: sys_x86_64_socket, - 0x2A: sys_x86_64_connect, - 0x3F: sys_x86_64_newuname, - 0x48: sys_generic_fcntl64, - 0x4E: sys_x86_64_getdents, - 0x59: sys_x86_64_readlink, - 0x63: sys_x86_64_sysinfo, - 0x66: sys_generic_getuid, - 0x68: sys_generic_getgid, - 0x6B: sys_generic_geteuid, - 0x6C: sys_generic_getegid, - 0xE4: sys_x86_64_clock_gettime, - 0x89: sys_x86_64_statfs, - 0x9E: sys_x86_64_arch_prctl, - 0xBF: sys_x86_64_getxattr, - 0xC0: sys_x86_64_lgetxattr, - 0xDA: sys_x86_64_set_tid_address, - 0xE7: sys_generic_exit_group, - 0x101: sys_x86_64_openat, - 0x111: sys_x86_64_set_robust_list, - 0x12E: sys_x86_64_prlimit64, -} - - -syscall_callbacks_arml = { - - 0x3: sys_generic_read, - 0x4: sys_generic_write, - 0x5: sys_generic_open, - 0x6: sys_generic_close, - 0x2d: sys_generic_brk, - 0x21: sys_generic_access, - 0x36: sys_arml_ioctl, - 0x7a: sys_arml_newuname, - 0x7d: sys_generic_mprotect, - 0x92: sys_arml_writev, - 0xc0: sys_generic_mmap2, - 0xc3: sys_arml_stat64, - 0xc4: sys_arml_lstat64, - 0xc5: sys_arml_fstat64, - 0xc7: sys_generic_getuid, - 0xc8: sys_generic_getgid, - 0xc9: sys_generic_geteuid, - 0xcA: sys_generic_getegid, - 0x4e: sys_arml_gettimeofday, - 0xd5: sys_generic_setuid, - 0xd6: sys_generic_setgid, - 0xd9: sys_arml_getdents64, - 0xdd: sys_generic_fcntl64, - 0xf8: sys_generic_exit_group, - - # ARM-specific ARM_NR_BASE == 0x0f0000 - 0xf0005: sys_arml_set_tls, -} - - -syscall_callbacks_mips32b = { - 0x1057: sys_mips32b_socket, -} - -def syscall_x86_64_exception_handler(linux_env, syscall_callbacks, jitter): - """Call to actually handle an EXCEPT_SYSCALL exception - In the case of an error raised by a SYSCALL, call the corresponding - syscall_callbacks - @linux_env: LinuxEnvironment_x86_64 instance - @syscall_callbacks: syscall number -> func(jitter, linux_env) - """ - - # Dispatch to SYSCALL stub - syscall_number = jitter.cpu.RAX - callback = syscall_callbacks.get(syscall_number) - if callback is None: - raise KeyError( - "No callback found for syscall number 0x%x" % syscall_number - ) - callback(jitter, linux_env) - log.debug("-> %x", jitter.cpu.RAX) - - # Clean exception and move pc to the next instruction, to let the jitter - # continue - jitter.cpu.set_exception(jitter.cpu.get_exception() ^ EXCEPT_SYSCALL) - return True - - - -def syscall_x86_32_exception_handler(linux_env, syscall_callbacks, jitter): - """Call to actually handle an EXCEPT_INT_XX exception - In the case of an error raised by a SYSCALL, call the corresponding - syscall_callbacks - @linux_env: LinuxEnvironment_x86_32 instance - @syscall_callbacks: syscall number -> func(jitter, linux_env) - """ - # Ensure the jitter has break on a SYSCALL - if jitter.cpu.interrupt_num != 0x80: - return True - - # Dispatch to SYSCALL stub - syscall_number = jitter.cpu.EAX - callback = syscall_callbacks.get(syscall_number) - if callback is None: - raise KeyError( - "No callback found for syscall number 0x%x" % syscall_number - ) - callback(jitter, linux_env) - log.debug("-> %x", jitter.cpu.EAX) - - # Clean exception and move pc to the next instruction, to let the jitter - # continue - jitter.cpu.set_exception(jitter.cpu.get_exception() ^ EXCEPT_INT_XX) - return True - - - -def syscall_arml_exception_handler(linux_env, syscall_callbacks, jitter): - """Call to actually handle an EXCEPT_PRIV_INSN exception - In the case of an error raised by a SYSCALL, call the corresponding - syscall_callbacks - @linux_env: LinuxEnvironment_arml instance - @syscall_callbacks: syscall number -> func(jitter, linux_env) - """ - # Ensure the jitter has break on a SYSCALL - if jitter.cpu.interrupt_num != 0x0: - return True - - # Dispatch to SYSCALL stub - syscall_number = jitter.cpu.R7 - callback = syscall_callbacks.get(syscall_number) - if callback is None: - raise KeyError( - "No callback found for syscall number 0x%x" % syscall_number - ) - callback(jitter, linux_env) - log.debug("-> %x", jitter.cpu.R0) - - # Clean exception and move pc to the next instruction, to let the jitter - # continue - jitter.cpu.set_exception(jitter.cpu.get_exception() ^ EXCEPT_INT_XX) - return True - - - -def syscall_mips32b_exception_handler(linux_env, syscall_callbacks, jitter): - """Call to actually handle an EXCEPT_SYSCALL exception - In the case of an error raised by a SYSCALL, call the corresponding - syscall_callbacks - @linux_env: LinuxEnvironment_mips32b instance - @syscall_callbacks: syscall number -> func(jitter, linux_env) - """ - - # Dispatch to SYSCALL stub - syscall_number = jitter.cpu.V0 - callback = syscall_callbacks.get(syscall_number) - if callback is None: - raise KeyError( - "No callback found for syscall number 0x%x" % syscall_number - ) - callback(jitter, linux_env) - log.debug("-> %x", jitter.cpu.V0) - - # Clean exception and move pc to the next instruction, to let the jitter - # continue - jitter.cpu.set_exception(jitter.cpu.get_exception() ^ EXCEPT_SYSCALL) - return True - - - -def enable_syscall_handling(jitter, linux_env, syscall_callbacks): - """Activate handling of syscall for the current jitter instance. - Syscall handlers are provided by @syscall_callbacks - @linux_env: LinuxEnvironment instance - @syscall_callbacks: syscall number -> func(jitter, linux_env) - - Example of use: - >>> linux_env = LinuxEnvironment_x86_64() - >>> enable_syscall_handling(jitter, linux_env, syscall_callbacks_x86_64) - """ - arch_name = jitter.jit.arch_name - if arch_name == "x8664": - handler = syscall_x86_64_exception_handler - handler = functools.partial(handler, linux_env, syscall_callbacks) - jitter.add_exception_handler(EXCEPT_SYSCALL, handler) - elif arch_name == "x8632": - handler = syscall_x86_32_exception_handler - handler = functools.partial(handler, linux_env, syscall_callbacks) - jitter.add_exception_handler(EXCEPT_INT_XX, handler) - elif arch_name == "arml": - handler = syscall_arml_exception_handler - handler = functools.partial(handler, linux_env, syscall_callbacks) - jitter.add_exception_handler(EXCEPT_INT_XX, handler) - elif arch_name == "mips32b": - handler = syscall_mips32b_exception_handler - handler = functools.partial(handler, linux_env, syscall_callbacks) - jitter.add_exception_handler(EXCEPT_SYSCALL, handler) - else: - raise ValueError("No syscall handler implemented for %s" % arch_name) diff --git a/miasm/os_dep/linux_stdlib.py b/miasm/os_dep/linux_stdlib.py deleted file mode 100644 index f0c708ba..00000000 --- a/miasm/os_dep/linux_stdlib.py +++ /dev/null @@ -1,213 +0,0 @@ -#-*- coding:utf-8 -*- - -from __future__ import print_function -import struct -from sys import stdout - -try: - # Python3 binary stdout - stdout = stdout.buffer -except AttributeError: - pass - -from miasm.core.utils import int_to_byte, cmp_elts -from miasm.os_dep.common import heap -from miasm.os_dep.common import get_fmt_args as _get_fmt_args - - -class c_linobjs(object): - - base_addr = 0x20000000 - align_addr = 0x1000 - def __init__(self): - self.alloc_ad = self.base_addr - self.alloc_align = self.align_addr - self.heap = heap() - -linobjs = c_linobjs() - -ABORT_ADDR = 0x1337beef - -def xxx___libc_start_main(jitter): - """Basic implementation of __libc_start_main - - int __libc_start_main(int *(main) (int, char * *, char * *), int argc, - char * * ubp_av, void (*init) (void), - void (*fini) (void), void (*rtld_fini) (void), - void (* stack_end)); - - Note: - - init, fini, rtld_fini are ignored - - return address is forced to ABORT_ADDR, to avoid calling abort/hlt/... - - in powerpc, signature is: - - int __libc_start_main (int argc, char **argv, char **ev, ElfW (auxv_t) * - auxvec, void (*rtld_fini) (void), struct startup_info - *stinfo, char **stack_on_entry) - - """ - global ABORT_ADDR - if jitter.arch.name == "ppc32": - ret_ad, args = jitter.func_args_systemv( - ["argc", "argv", "ev", "aux_vec", "rtld_fini", "st_info", - "stack_on_entry"] - ) - - # Mimic glibc implementation - if args.stack_on_entry != 0: - argc = struct.unpack(">I", - jitter.vm.get_mem(args.stack_on_entry, 4))[0] - argv = args.stack_on_entry + 4 - envp = argv + ((argc + 1) * 4) - else: - argc = args.argc - argv = args.argv - envp = args.ev - # sda_base, main, init, fini - _, main, _, _ = struct.unpack(">IIII", - jitter.vm.get_mem(args.st_info, 4 * 4)) - - else: - ret_ad, args = jitter.func_args_systemv( - ["main", "argc", "ubp_av", "init", "fini", "rtld_fini", "stack_end"] - ) - - main = args.main - # done by __libc_init_first - size = jitter.lifter.pc.size // 8 - argc = args.argc - argv = args.ubp_av - envp = argv + (args.argc + 1) * size - - - # Call int main(int argc, char** argv, char** envp) - jitter.func_ret_systemv(main) - ret_ad = ABORT_ADDR - jitter.func_prepare_systemv(ret_ad, argc, argv, envp) - return True - - -def xxx_isprint(jitter): - ''' - #include <ctype.h> - int isprint(int c); - - checks for any printable character including space. - ''' - ret_addr, args = jitter.func_args_systemv(['c']) - ret = 1 if 0x20 <= args.c & 0xFF < 0x7f else 0 - return jitter.func_ret_systemv(ret_addr, ret) - - -def xxx_memcpy(jitter): - ''' - #include <string.h> - void *memcpy(void *dest, const void *src, size_t n); - - copies n bytes from memory area src to memory area dest. - ''' - ret_addr, args = jitter.func_args_systemv(['dest', 'src', 'n']) - jitter.vm.set_mem(args.dest, jitter.vm.get_mem(args.src, args.n)) - return jitter.func_ret_systemv(ret_addr, args.dest) - - -def xxx_memset(jitter): - ''' - #include <string.h> - void *memset(void *s, int c, size_t n); - - fills the first n bytes of the memory area pointed to by s with the constant - byte c.''' - - ret_addr, args = jitter.func_args_systemv(['dest', 'c', 'n']) - jitter.vm.set_mem(args.dest, int_to_byte(args.c & 0xFF) * args.n) - return jitter.func_ret_systemv(ret_addr, args.dest) - - -def xxx_puts(jitter): - ''' - #include <stdio.h> - int puts(const char *s); - - writes the string s and a trailing newline to stdout. - ''' - ret_addr, args = jitter.func_args_systemv(['s']) - index = args.s - char = jitter.vm.get_mem(index, 1) - while char != b'\x00': - stdout.write(char) - index += 1 - char = jitter.vm.get_mem(index, 1) - stdout.write(b'\n') - return jitter.func_ret_systemv(ret_addr, 1) - - -def get_fmt_args(jitter, fmt, cur_arg): - return _get_fmt_args(fmt, cur_arg, jitter.get_c_str, jitter.get_arg_n_systemv) - - -def xxx_snprintf(jitter): - ret_addr, args = jitter.func_args_systemv(['string', 'size', 'fmt']) - cur_arg, fmt = 3, args.fmt - size = args.size if args.size else 1 - output = get_fmt_args(jitter, fmt, cur_arg) - output = output[:size - 1] - ret = len(output) - jitter.set_c_str(args.string, output) - return jitter.func_ret_systemv(ret_addr, ret) - - -def xxx_sprintf(jitter): - ret_addr, args = jitter.func_args_systemv(['string', 'fmt']) - cur_arg, fmt = 2, args.fmt - output = get_fmt_args(jitter, fmt, cur_arg) - ret = len(output) - jitter.set_c_str(args.string, output) - return jitter.func_ret_systemv(ret_addr, ret) - - -def xxx_printf(jitter): - ret_addr, args = jitter.func_args_systemv(['fmt']) - cur_arg, fmt = 1, args.fmt - output = get_fmt_args(jitter, fmt, cur_arg) - ret = len(output) - stdout.write(output.encode('utf8')) - return jitter.func_ret_systemv(ret_addr, ret) - - -def xxx_strcpy(jitter): - ret_ad, args = jitter.func_args_systemv(["dst", "src"]) - str_src = jitter.get_c_str(args.src) - jitter.set_c_str(args.dst, str_src) - jitter.func_ret_systemv(ret_ad, args.dst) - - -def xxx_strlen(jitter): - ret_ad, args = jitter.func_args_systemv(["src"]) - str_src = jitter.get_c_str(args.src) - jitter.func_ret_systemv(ret_ad, len(str_src)) - - -def xxx_malloc(jitter): - ret_ad, args = jitter.func_args_systemv(["msize"]) - addr = linobjs.heap.alloc(jitter, args.msize) - jitter.func_ret_systemv(ret_ad, addr) - - -def xxx_free(jitter): - ret_ad, args = jitter.func_args_systemv(["ptr"]) - jitter.func_ret_systemv(ret_ad, 0) - - -def xxx_strcmp(jitter): - ret_ad, args = jitter.func_args_systemv(["ptr_str1", "ptr_str2"]) - s1 = jitter.get_c_str(args.ptr_str1) - s2 = jitter.get_c_str(args.ptr_str2) - jitter.func_ret_systemv(ret_ad, cmp_elts(s1, s2)) - - -def xxx_strncmp(jitter): - ret_ad, args = jitter.func_args_systemv(["ptr_str1", "ptr_str2", "size"]) - s1 = jitter.get_c_str(args.ptr_str1, args.size) - s2 = jitter.get_c_str(args.ptr_str2, args.size) - jitter.func_ret_systemv(ret_ad, cmp_elts(s1, s2)) diff --git a/miasm/os_dep/win_32_structs.py b/miasm/os_dep/win_32_structs.py deleted file mode 100644 index fc9c62ea..00000000 --- a/miasm/os_dep/win_32_structs.py +++ /dev/null @@ -1,231 +0,0 @@ -from miasm.core.types import MemStruct, Num, Ptr, Str, \ - Array, RawStruct, Union, \ - BitField, Self, Void, Bits, \ - set_allocator, MemUnion, Struct - - -class UnicodeString(MemStruct): - fields = [ - ("length", Num("H")), - ("maxlength", Num("H")), - ("data", Ptr("<I", Str("utf16"))), - ] - - -class ListEntry(MemStruct): - fields = [ - ("flink", Ptr("<I", Void())), - ("blink", Ptr("<I", Void())), - ] - - -class LdrDataEntry(MemStruct): - - """ - +0x000 InLoadOrderLinks : _LIST_ENTRY - +0x008 InMemoryOrderLinks : _LIST_ENTRY - +0x010 InInitializationOrderLinks : _LIST_ENTRY - +0x018 DllBase : Ptr32 Void - +0x01c EntryPoint : Ptr32 Void - +0x020 SizeOfImage : Uint4B - +0x024 FullDllName : _UNICODE_STRING - +0x02c BaseDllName : _UNICODE_STRING - +0x034 Flags : Uint4B - +0x038 LoadCount : Uint2B - +0x03a TlsIndex : Uint2B - +0x03c HashLinks : _LIST_ENTRY - +0x03c SectionPointer : Ptr32 Void - +0x040 CheckSum : Uint4B - +0x044 TimeDateStamp : Uint4B - +0x044 LoadedImports : Ptr32 Void - +0x048 EntryPointActivationContext : Ptr32 Void - +0x04c PatchInformation : Ptr32 Void - """ - - fields = [ - ("InLoadOrderLinks", ListEntry), - ("InMemoryOrderLinks", ListEntry), - ("InInitializationOrderLinks", ListEntry), - ("DllBase", Ptr("<I", Void())), - ("EntryPoint", Ptr("<I", Void())), - ("SizeOfImage", Num("<I")), - ("FullDllName", UnicodeString), - ("BaseDllName", UnicodeString), - ("Flags", Array(Num("B"), 4)), - ("LoadCount", Num("H")), - ("TlsIndex", Num("H")), - ("union1", Union([ - ("HashLinks", Ptr("<I", Void())), - ("SectionPointer", Ptr("<I", Void())), - ])), - ("CheckSum", Num("<I")), - ("union2", Union([ - ("TimeDateStamp", Num("<I")), - ("LoadedImports", Ptr("<I", Void())), - ])), - ("EntryPointActivationContext", Ptr("<I", Void())), - ("PatchInformation", Ptr("<I", Void())), - - ] - - -class PEB_LDR_DATA(MemStruct): - - """ - +0x000 Length : Uint4B - +0x004 Initialized : UChar - +0x008 SsHandle : Ptr32 Void - +0x00c InLoadOrderModuleList : _LIST_ENTRY - +0x014 InMemoryOrderModuleList : _LIST_ENTRY - +0x01C InInitializationOrderModuleList : _LIST_ENTRY - """ - - fields = [ - ("Length", Num("<I")), - ("Initialized", Num("<I")), - ("SsHandle", Ptr("<I", Void())), - ("InLoadOrderModuleList", ListEntry), - ("InMemoryOrderModuleList", ListEntry), - ("InInitializationOrderModuleList", ListEntry) - ] - - -class PEB(MemStruct): - - """ - +0x000 InheritedAddressSpace : UChar - +0x001 ReadImageFileExecOptions : UChar - +0x002 BeingDebugged : UChar - +0x003 SpareBool : UChar - +0x004 Mutant : Ptr32 Void - +0x008 ImageBaseAddress : Ptr32 Void - +0x00c Ldr : Ptr32 _PEB_LDR_DATA - +0x010 processparameter - """ - - fields = [ - ("InheritedAddressSpace", Num("B")), - ("ReadImageFileExecOptions", Num("B")), - ("BeingDebugged", Num("B")), - ("SpareBool", Num("B")), - ("Mutant", Ptr("<I", Void())), - ("ImageBaseAddress", Num("<I")), - ("Ldr", Ptr("<I", PEB_LDR_DATA)), - ] - - -class EXCEPTION_REGISTRATION_RECORD(MemStruct): - """ - +0x00 Next : struct _EXCEPTION_REGISTRATION_RECORD * - +0x04 Handler : Ptr32 Void - """ - - fields = [ - ("Next", Ptr("<I", Self())), - ("Handler", Ptr("<I", Void())), - ] - - -class EXCEPTION_RECORD(MemStruct): - """ - DWORD ExceptionCode; - DWORD ExceptionFlags; - struct _EXCEPTION_RECORD *ExceptionRecord; - PVOID ExceptionAddress; - DWORD NumberParameters; - ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; - """ - EXCEPTION_MAXIMUM_PARAMETERS = 15 - - fields = [ - ("ExceptionCode", Num("<I")), - ("ExceptionFlags", Num("<I")), - ("ExceptionRecord", Ptr("<I", Self())), - ("ExceptionAddress", Ptr("<I", Void())), - ("NumberParameters", Num("<I")), - ("ExceptionInformation", Ptr("<I", Void())), - ] - - -class NT_TIB(MemStruct): - - """ - +00 struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList - +04 void *StackBase - +08 void *StackLimit - +0c void *SubSystemTib - +10 void *FiberData - +10 uint32 Version - +14 void *ArbitraryUserPointer - +18 struct _NT_TIB *Self - """ - - fields = [ - ("ExceptionList", Ptr("<I", EXCEPTION_REGISTRATION_RECORD)), - ("StackBase", Ptr("<I", Void())), - ("StackLimit", Ptr("<I", Void())), - ("SubSystemTib", Ptr("<I", Void())), - (None, Union([ - ("FiberData", Ptr("<I", Void())), - ("Version", Num("<I")) - ])), - ("ArbitraryUserPointer", Ptr("<I", Void())), - ("Self", Ptr("<I", Self())), - ] - - -class TEB(MemStruct): - - """ - +0x000 NtTib : _NT_TIB - +0x01c EnvironmentPointer : Ptr32 Void - +0x020 ClientId : _CLIENT_ID - +0x028 ActiveRpcHandle : Ptr32 Void - +0x02c ThreadLocalStoragePointer : Ptr32 Void - +0x030 ProcessEnvironmentBlock : Ptr32 _PEB - +0x034 LastErrorValue : Uint4B - ... - """ - - fields = [ - ("NtTib", NT_TIB), - ("EnvironmentPointer", Ptr("<I", Void())), - ("ClientId", Array(Num("B"), 0x8)), - ("ActiveRpcHandle", Ptr("<I", Void())), - ("ThreadLocalStoragePointer", Ptr("<I", Void())), - ("ProcessEnvironmentBlock", Ptr("<I", PEB)), - ("LastErrorValue", Num("<I")), - ] - - -class ContextException(MemStruct): - fields = [ - ("ContextFlags", Num("<I")), - ("dr0", Num("<I")), - ("dr1", Num("<I")), - ("dr2", Num("<I")), - ("dr3", Num("<I")), - ("dr4", Num("<I")), - ("dr5", Num("<I")), - - ("Float", Array(Num("B"), 112)), - - ("gs", Num("<I")), - ("fs", Num("<I")), - ("es", Num("<I")), - ("ds", Num("<I")), - - ("edi", Num("<I")), - ("esi", Num("<I")), - ("ebx", Num("<I")), - ("edx", Num("<I")), - ("ecx", Num("<I")), - ("eax", Num("<I")), - ("ebp", Num("<I")), - ("eip", Num("<I")), - - ("cs", Num("<I")), - ("eflags", Num("<I")), - ("esp", Num("<I")), - ("ss", Num("<I")), - ] diff --git a/miasm/os_dep/win_api_x86_32.py b/miasm/os_dep/win_api_x86_32.py deleted file mode 100644 index 6e568abb..00000000 --- a/miasm/os_dep/win_api_x86_32.py +++ /dev/null @@ -1,3595 +0,0 @@ -from __future__ import print_function -# -# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -from past.builtins import cmp -import struct -import os -import stat -import time -import string -import logging -from zlib import crc32 -from io import StringIO -import time -import datetime - -from future.utils import PY3, viewitems, viewvalues - -try: - from Crypto.Hash import MD5, SHA -except ImportError: - print("cannot find crypto, skipping") - -from miasm.jitter.csts import PAGE_READ, PAGE_WRITE, PAGE_EXEC -from miasm.core.utils import pck16, pck32, hexdump, whoami, int_to_byte -from miasm.os_dep.common import heap, windows_to_sbpath -from miasm.os_dep.common import set_win_str_w, set_win_str_a -from miasm.os_dep.common import get_fmt_args as _get_fmt_args -from miasm.os_dep.common import get_win_str_a, get_win_str_w -from miasm.os_dep.common import encode_win_str_a, encode_win_str_w -from miasm.os_dep.win_api_x86_32_seh import tib_address - -log = logging.getLogger("win_api_x86_32") -console_handler = logging.StreamHandler() -console_handler.setFormatter(logging.Formatter("[%(levelname)-8s]: %(message)s")) -log.addHandler(console_handler) -log.setLevel(logging.WARN) - -DATE_1601_TO_1970 = 116444736000000000 - -MAX_PATH = 260 - - -""" -typedef struct tagPROCESSENTRY32 { - DWORD dwSize; - DWORD cntUsage; - DWORD th32ProcessID; - ULONG_PTR th32DefaultHeapID; - DWORD th32ModuleID; - DWORD cntThreads; - DWORD th32ParentProcessID; - LONG pcPriClassBase; - DWORD dwFlags; - TCHAR szExeFile[MAX_PATH]; -} PROCESSENTRY32, *PPROCESSENTRY32; -""" - - -ACCESS_DICT = {0x0: 0, - 0x1: 0, - 0x2: PAGE_READ, - 0x4: PAGE_READ | PAGE_WRITE, - 0x10: PAGE_EXEC, - 0x20: PAGE_EXEC | PAGE_READ, - 0x40: PAGE_EXEC | PAGE_READ | PAGE_WRITE, - 0x80: PAGE_EXEC | PAGE_READ | PAGE_WRITE, - # 0x80: PAGE_EXECUTE_WRITECOPY - 0x100: 0 - } - -ACCESS_DICT_INV = dict((x[1], x[0]) for x in viewitems(ACCESS_DICT)) - - -class whandle(object): - - def __init__(self, name, info): - self.name = name - self.info = info - - def __repr__(self): - return '<%r %r %r>' % (self.__class__.__name__, self.name, self.info) - - -class handle_generator(object): - - def __init__(self): - self.offset = 600 - self.all_handles = {} - - def add(self, name, info=None): - self.offset += 1 - h = whandle(name, info) - self.all_handles[self.offset] = h - - log.debug(repr(self)) - return self.offset - - def __repr__(self): - out = '<%r\n' % self.__class__.__name__ - ks = list(self.all_handles) - ks.sort() - - for k in ks: - out += " %r %r\n" % (k, self.all_handles[k]) - out += '>' - return out - - def __contains__(self, e): - return e in self.all_handles - - def __getitem__(self, item): - return self.all_handles.__getitem__(item) - - def __delitem__(self, item): - self.all_handles.__delitem__(item) - - -class c_winobjs(object): - - def __init__(self): - self.alloc_ad = 0x20000000 - self.alloc_align = 0x1000 - self.heap = heap() - self.handle_toolhelpsnapshot = 0xaaaa00 - self.toolhelpsnapshot_info = {} - self.handle_curprocess = 0xaaaa01 - self.dbg_present = 0 - self.tickcount = 0 - self.dw_pid_dummy1 = 0x111 - self.dw_pid_explorer = 0x222 - self.dw_pid_dummy2 = 0x333 - self.dw_pid_cur = 0x444 - self.module_fname_nux = None - self.module_name = "test.exe" - self.module_path = "c:\\mydir\\" + self.module_name - self.hcurmodule = None - self.module_filesize = None - self.getversion = 0x0A280105 - self.getforegroundwindow = 0x333333 - self.cryptcontext_hwnd = 0x44400 - self.cryptcontext_bnum = 0x44000 - self.cryptcontext_num = 0 - self.cryptcontext = {} - self.phhash_crypt_md5 = 0x55555 - # key used by EncodePointer and DecodePointer - # (kernel32) - self.ptr_encode_key = 0xabababab - self.files_hwnd = {} - self.windowlong_dw = 0x77700 - self.module_cur_hwnd = 0x88800 - self.module_file_nul = 0x999000 - self.runtime_dll = None - self.current_pe = None - self.tls_index = 0xf - self.tls_values = {} - self.handle_pool = handle_generator() - self.handle_mapped = {} - self.hkey_handles = { - 0x80000001: b"hkey_current_user", - 0x80000002: b"hkey_local_machine" - } - self.cur_dir = "c:\\tmp" - - self.nt_mdl = {} - self.nt_mdl_ad = None - self.nt_mdl_cur = 0 - self.win_event_num = 0x13370 - self.cryptdll_md5_h = {} - - self.lastwin32error = 0 - self.mutex = {} - self.env_variables = {} - self.events_pool = {} - self.find_data = None - - self.allocated_pages = {} - self.current_datetime = datetime.datetime( - year=2017, month=8, day=21, - hour=13, minute=37, - second=11, microsecond=123456 - ) - -winobjs = c_winobjs() - - -process_list = [ - [ - 0x40, # DWORD dwSize; - 0, # DWORD cntUsage; - winobjs.dw_pid_dummy1, # DWORD th32ProcessID; - 0x11111111, # ULONG_PTR th32DefaultHeapID; - 0x11111112, # DWORD th32ModuleID; - 1, # DWORD cntThreads; - winobjs.dw_pid_explorer, # DWORD th32ParentProcessID; - 0xbeef, # LONG pcPriClassBase; - 0x0, # DWORD dwFlags; - "dummy1.exe" # TCHAR szExeFile[MAX_PATH]; - ], - [ - 0x40, # DWORD dwSize; - 0, # DWORD cntUsage; - winobjs.dw_pid_explorer, # DWORD th32ProcessID; - 0x11111111, # ULONG_PTR th32DefaultHeapID; - 0x11111112, # DWORD th32ModuleID; - 1, # DWORD cntThreads; - 4, # DWORD th32ParentProcessID; - 0xbeef, # LONG pcPriClassBase; - 0x0, # DWORD dwFlags; - "explorer.exe" # TCHAR szExeFile[MAX_PATH]; - ], - - [ - 0x40, # DWORD dwSize; - 0, # DWORD cntUsage; - winobjs.dw_pid_dummy2, # DWORD th32ProcessID; - 0x11111111, # ULONG_PTR th32DefaultHeapID; - 0x11111112, # DWORD th32ModuleID; - 1, # DWORD cntThreads; - winobjs.dw_pid_explorer, # DWORD th32ParentProcessID; - 0xbeef, # LONG pcPriClassBase; - 0x0, # DWORD dwFlags; - "dummy2.exe" # TCHAR szExeFile[MAX_PATH]; - ], - - [ - 0x40, # DWORD dwSize; - 0, # DWORD cntUsage; - winobjs.dw_pid_cur, # DWORD th32ProcessID; - 0x11111111, # ULONG_PTR th32DefaultHeapID; - 0x11111112, # DWORD th32ModuleID; - 1, # DWORD cntThreads; - winobjs.dw_pid_explorer, # DWORD th32ParentProcessID; - 0xbeef, # LONG pcPriClassBase; - 0x0, # DWORD dwFlags; - winobjs.module_name # TCHAR szExeFile[MAX_PATH]; - ], - - -] - - -class hobj(object): - pass - - -class mdl(object): - - def __init__(self, ad, l): - self.ad = ad - self.l = l - - def __bytes__(self): - return struct.pack('LL', self.ad, self.l) - - def __str__(self): - if PY3: - return repr(self) - return self.__bytes__() - - -def kernel32_HeapAlloc(jitter): - ret_ad, args = jitter.func_args_stdcall(["heap", "flags", "size"]) - alloc_addr = winobjs.heap.alloc(jitter, args.size, cmt=hex(ret_ad)) - jitter.func_ret_stdcall(ret_ad, alloc_addr) - - -def kernel32_HeapFree(jitter): - ret_ad, _ = jitter.func_args_stdcall(["heap", "flags", "pmem"]) - jitter.func_ret_stdcall(ret_ad, 1) - - -def kernel32_GlobalAlloc(jitter): - ret_ad, args = jitter.func_args_stdcall(["uflags", "msize"]) - alloc_addr = winobjs.heap.alloc(jitter, args.msize) - jitter.func_ret_stdcall(ret_ad, alloc_addr) - - -def kernel32_LocalFree(jitter): - ret_ad, _ = jitter.func_args_stdcall(["lpvoid"]) - jitter.func_ret_stdcall(ret_ad, 0) - - -def kernel32_LocalAlloc(jitter): - ret_ad, args = jitter.func_args_stdcall(["uflags", "msize"]) - alloc_addr = winobjs.heap.alloc(jitter, args.msize) - jitter.func_ret_stdcall(ret_ad, alloc_addr) - -def msvcrt_new(jitter): - ret_ad, args = jitter.func_args_cdecl(["size"]) - alloc_addr = winobjs.heap.alloc(jitter, args.size) - jitter.func_ret_cdecl(ret_ad, alloc_addr) - -globals()['msvcrt_??2@YAPAXI@Z'] = msvcrt_new - -def msvcrt_delete(jitter): - ret_ad, args = jitter.func_args_cdecl(["ptr"]) - jitter.func_ret_cdecl(ret_ad, 0) - -globals()['msvcrt_??3@YAXPAX@Z'] = msvcrt_delete - -def kernel32_GlobalFree(jitter): - ret_ad, _ = jitter.func_args_stdcall(["addr"]) - jitter.func_ret_stdcall(ret_ad, 0) - - -def kernel32_IsDebuggerPresent(jitter): - ret_ad, _ = jitter.func_args_stdcall(0) - jitter.func_ret_stdcall(ret_ad, winobjs.dbg_present) - - -def kernel32_CreateToolhelp32Snapshot(jitter): - ret_ad, _ = jitter.func_args_stdcall(["dwflags", "th32processid"]) - jitter.func_ret_stdcall(ret_ad, winobjs.handle_toolhelpsnapshot) - - -def kernel32_GetCurrentProcess(jitter): - ret_ad, _ = jitter.func_args_stdcall(0) - jitter.func_ret_stdcall(ret_ad, winobjs.handle_curprocess) - - -def kernel32_GetCurrentProcessId(jitter): - ret_ad, _ = jitter.func_args_stdcall(0) - jitter.func_ret_stdcall(ret_ad, winobjs.dw_pid_cur) - - -def kernel32_Process32First(jitter): - ret_ad, args = jitter.func_args_stdcall(["s_handle", "ad_pentry"]) - - pentry = struct.pack( - 'IIIIIIIII', *process_list[0][:-1] - ) + (process_list[0][-1] + '\x00').encode('utf8') - jitter.vm.set_mem(args.ad_pentry, pentry) - winobjs.toolhelpsnapshot_info[args.s_handle] = 0 - - jitter.func_ret_stdcall(ret_ad, 1) - - -def kernel32_Process32Next(jitter): - ret_ad, args = jitter.func_args_stdcall(["s_handle", "ad_pentry"]) - - winobjs.toolhelpsnapshot_info[args.s_handle] += 1 - if winobjs.toolhelpsnapshot_info[args.s_handle] >= len(process_list): - ret = 0 - else: - ret = 1 - n = winobjs.toolhelpsnapshot_info[args.s_handle] - pentry = struct.pack( - 'IIIIIIIII', *process_list[n][:-1]) + (process_list[n][-1]+ '\x00').encode('utf8') - jitter.vm.set_mem(args.ad_pentry, pentry) - jitter.func_ret_stdcall(ret_ad, ret) - - -def kernel32_GetTickCount(jitter): - ret_ad, _ = jitter.func_args_stdcall(0) - winobjs.tickcount += 1 - jitter.func_ret_stdcall(ret_ad, winobjs.tickcount) - - -def kernel32_GetVersion(jitter): - ret_ad, _ = jitter.func_args_stdcall(0) - jitter.func_ret_stdcall(ret_ad, winobjs.getversion) - - -def kernel32_GetVersionEx(jitter, str_size, encode_str): - ret_ad, args = jitter.func_args_stdcall(["ptr_struct"]) - - size = jitter.vm.get_u32(args.ptr_struct) - if size in [0x14+str_size, 0x1c+str_size]: - tmp = struct.pack( - "IIIII%dsHHHBB" % str_size, - 0x114, # struct size - 0x5, # maj vers - 0x2, # min vers - 0xa28, # build nbr - 0x2, # platform id - encode_str("Service pack 4"), - 3, # wServicePackMajor - 0, # wServicePackMinor - 0x100, # wSuiteMask - 1, # wProductType - 0 # wReserved - ) - tmp = tmp[:size] - jitter.vm.set_mem(args.ptr_struct, tmp) - ret = 1 - else: - ret = 0 - jitter.func_ret_stdcall(ret_ad, ret) - - -kernel32_GetVersionExA = lambda jitter: kernel32_GetVersionEx(jitter, 128, - encode_win_str_a) -kernel32_GetVersionExW = lambda jitter: kernel32_GetVersionEx(jitter, 256, - encode_win_str_w) - - -def kernel32_GetPriorityClass(jitter): - ret_ad, _ = jitter.func_args_stdcall(["hwnd"]) - jitter.func_ret_stdcall(ret_ad, 0) - - -def kernel32_SetPriorityClass(jitter): - ret_ad, _ = jitter.func_args_stdcall(["hwnd", "dwpclass"]) - jitter.func_ret_stdcall(ret_ad, 0) - - -def kernel32_CloseHandle(jitter): - ret_ad, _ = jitter.func_args_stdcall(["hwnd"]) - jitter.func_ret_stdcall(ret_ad, 1) - -def kernel32_EncodePointer(jitter): - """ - PVOID EncodePointer( - _In_ PVOID Ptr - ); - - Encoding globally available pointers helps protect them from being - exploited. The EncodePointer function obfuscates the pointer value - with a secret so that it cannot be predicted by an external agent. - The secret used by EncodePointer is different for each process. - - A pointer must be decoded before it can be used. - - """ - ret, args = jitter.func_args_stdcall(1) - jitter.func_ret_stdcall(ret, args[0] ^ winobjs.ptr_encode_key) - return True - -def kernel32_DecodePointer(jitter): - """ - PVOID DecodePointer( - PVOID Ptr - ); - - The function returns the decoded pointer. - - """ - ret, args = jitter.func_args_stdcall(1) - jitter.func_ret_stdcall(ret, args[0] ^ winobjs.ptr_encode_key) - return True - -def user32_GetForegroundWindow(jitter): - ret_ad, _ = jitter.func_args_stdcall(0) - jitter.func_ret_stdcall(ret_ad, winobjs.getforegroundwindow) - - -def user32_FindWindowA(jitter): - ret_ad, args = jitter.func_args_stdcall(["pclassname", "pwindowname"]) - if args.pclassname: - classname = get_win_str_a(jitter, args.pclassname) - log.info("FindWindowA classname %s", classname) - if args.pwindowname: - windowname = get_win_str_a(jitter, args.pwindowname) - log.info("FindWindowA windowname %s", windowname) - jitter.func_ret_stdcall(ret_ad, 0) - - -def user32_GetTopWindow(jitter): - ret_ad, _ = jitter.func_args_stdcall(["hwnd"]) - jitter.func_ret_stdcall(ret_ad, 0) - - -def user32_BlockInput(jitter): - ret_ad, _ = jitter.func_args_stdcall(["blockit"]) - jitter.func_ret_stdcall(ret_ad, 1) - - -def advapi32_CryptAcquireContext(jitter, funcname, get_str): - ret_ad, args = jitter.func_args_stdcall(["phprov", "pszcontainer", - "pszprovider", "dwprovtype", - "dwflags"]) - prov = get_str(args.pszprovider) if args.pszprovider else "NONE" - log.debug('prov: %r', prov) - jitter.vm.set_u32(args.phprov, winobjs.cryptcontext_hwnd) - jitter.func_ret_stdcall(ret_ad, 1) - - -def advapi32_CryptAcquireContextA(jitter): - advapi32_CryptAcquireContext(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr)) - - -def advapi32_CryptAcquireContextW(jitter): - advapi32_CryptAcquireContext(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr)) - - -def advapi32_CryptCreateHash(jitter): - ret_ad, args = jitter.func_args_stdcall(["hprov", "algid", "hkey", - "dwflags", "phhash"]) - - winobjs.cryptcontext_num += 1 - - if args.algid == 0x00008003: - log.debug('algo is MD5') - jitter.vm.set_u32( - args.phhash, - winobjs.cryptcontext_bnum + winobjs.cryptcontext_num - ) - winobjs.cryptcontext[ - winobjs.cryptcontext_bnum + winobjs.cryptcontext_num] = hobj() - winobjs.cryptcontext[ - winobjs.cryptcontext_bnum + winobjs.cryptcontext_num].h = MD5.new() - elif args.algid == 0x00008004: - log.debug('algo is SHA1') - jitter.vm.set_u32( - args.phhash, - winobjs.cryptcontext_bnum + winobjs.cryptcontext_num - ) - winobjs.cryptcontext[ - winobjs.cryptcontext_bnum + winobjs.cryptcontext_num] = hobj() - winobjs.cryptcontext[ - winobjs.cryptcontext_bnum + winobjs.cryptcontext_num].h = SHA.new() - else: - raise ValueError('un impl algo1') - jitter.func_ret_stdcall(ret_ad, 1) - - -def advapi32_CryptHashData(jitter): - ret_ad, args = jitter.func_args_stdcall(["hhash", "pbdata", "dwdatalen", - "dwflags"]) - - if not args.hhash in winobjs.cryptcontext: - raise ValueError("unknown crypt context") - - data = jitter.vm.get_mem(args.pbdata, args.dwdatalen) - log.debug('will hash %X', args.dwdatalen) - log.debug(repr(data[:0x10]) + "...") - winobjs.cryptcontext[args.hhash].h.update(data) - jitter.func_ret_stdcall(ret_ad, 1) - - -def advapi32_CryptGetHashParam(jitter): - ret_ad, args = jitter.func_args_stdcall(["hhash", "param", "pbdata", - "dwdatalen", "dwflags"]) - - if not args.hhash in winobjs.cryptcontext: - raise ValueError("unknown crypt context") - - if args.param == 2: - # HP_HASHVAL - # XXX todo: save h state? - h = winobjs.cryptcontext[args.hhash].h.digest() - jitter.vm.set_mem(args.pbdata, h) - jitter.vm.set_u32(args.dwdatalen, len(h)) - elif args.param == 4: - # HP_HASHSIZE - ret = winobjs.cryptcontext[args.hhash].h.digest_size - jitter.vm.set_u32(args.pbdata, ret) - jitter.vm.set_u32(args.dwdatalen, 4) - else: - raise ValueError('not impl', args.param) - - jitter.func_ret_stdcall(ret_ad, 1) - - -def advapi32_CryptReleaseContext(jitter): - ret_ad, _ = jitter.func_args_stdcall(["hhash", "flags"]) - jitter.func_ret_stdcall(ret_ad, 0) - - -def advapi32_CryptDeriveKey(jitter): - ret_ad, args = jitter.func_args_stdcall(["hprov", "algid", "hbasedata", - "dwflags", "phkey"]) - - if args.algid == 0x6801: - log.debug('using DES') - else: - raise ValueError('un impl algo2') - h = winobjs.cryptcontext[args.hbasedata].h.digest() - log.debug('hash %r', h) - winobjs.cryptcontext[args.hbasedata].h_result = h - jitter.vm.set_u32(args.phkey, args.hbasedata) - jitter.func_ret_stdcall(ret_ad, 1) - - -def advapi32_CryptDestroyHash(jitter): - ret_ad, _ = jitter.func_args_stdcall(["hhash"]) - jitter.func_ret_stdcall(ret_ad, 1) - - -def advapi32_CryptDecrypt(jitter): - # ret_ad, _ = jitter.func_args_stdcall(["hkey", "hhash", "final", - # "dwflags", "pbdata", - # "pdwdatalen"]) - raise ValueError("Not implemented") - # jitter.func_ret_stdcall(ret_ad, 1) - - -def kernel32_CreateFile(jitter, funcname, get_str): - ret_ad, args = jitter.func_args_stdcall(["lpfilename", "access", - "dwsharedmode", - "lpsecurityattr", - "dwcreationdisposition", - "dwflagsandattr", - "htemplatefile"]) - if args.lpfilename == 0: - jitter.func_ret_stdcall(ret_ad, 0xffffffff) - return - - fname = get_str(args.lpfilename) - log.info('CreateFile fname %s', fname) - ret = 0xffffffff - - log.debug("%r %r", fname.lower(), winobjs.module_path.lower()) - is_original_file = fname.lower() == winobjs.module_path.lower() - - if fname.upper() in [r"\\.\SICE", r"\\.\NTICE", r"\\.\SIWVID", r'\\.\SIWDEBUG']: - pass - elif fname.upper() in ['NUL']: - ret = winobjs.module_cur_hwnd - else: - # sandbox path - sb_fname = windows_to_sbpath(fname) - if args.access & 0x80000000 or args.access == 1: - # read and maybe write - if args.dwcreationdisposition == 2: - # create_always - if os.access(sb_fname, os.R_OK): - # but file exist - pass - else: - raise NotImplementedError("Untested case") # to test - # h = open(sb_fname, 'rb+') - elif args.dwcreationdisposition == 3: - # open_existing - if os.access(sb_fname, os.R_OK): - s = os.stat(sb_fname) - if stat.S_ISDIR(s.st_mode): - ret = winobjs.handle_pool.add(sb_fname, 0x1337) - else: - open_mode = 'rb' - if (args.access & 0x40000000) or args.access == 2: - open_mode = 'r+b' - h = open(sb_fname, open_mode) - ret = winobjs.handle_pool.add(sb_fname, h) - else: - log.warning("FILE %r (%s) DOES NOT EXIST!", fname, sb_fname) - elif args.dwcreationdisposition == 1: - # create new - if os.access(sb_fname, os.R_OK): - # file exist - # ret = 80 - winobjs.lastwin32error = 80 - else: - # first create an empty file - open(sb_fname, 'wb').close() - # then open - h = open(sb_fname, 'r+b') - ret = winobjs.handle_pool.add(sb_fname, h) - elif args.dwcreationdisposition == 4: - # open_always - if os.access(sb_fname, os.R_OK): - s = os.stat(sb_fname) - if stat.S_ISDIR(s.st_mode): - ret = winobjs.handle_pool.add(sb_fname, 0x1337) - else: - h = open(sb_fname, 'r+b') - ret = winobjs.handle_pool.add(sb_fname, h) - else: - raise NotImplementedError("Untested case") - else: - raise NotImplementedError("Untested case") - elif (args.access & 0x40000000) or args.access == 2: - # write but not read - if args.dwcreationdisposition == 3: - # open existing - if is_original_file: - # cannot open self in write mode! - pass - elif os.access(sb_fname, os.R_OK): - s = os.stat(sb_fname) - if stat.S_ISDIR(s.st_mode): - # open dir - ret = winobjs.handle_pool.add(sb_fname, 0x1337) - else: - h = open(sb_fname, 'wb') - ret = winobjs.handle_pool.add(sb_fname, h) - else: - raise NotImplementedError("Untested case") # to test - elif args.dwcreationdisposition == 5: - # truncate_existing - if is_original_file: - pass - else: - raise NotImplementedError("Untested case") # to test - else: - # raise NotImplementedError("Untested case") # to test - h = open(sb_fname, 'wb') - ret = winobjs.handle_pool.add(sb_fname, h) - else: - raise NotImplementedError("Untested case") - - # h = open(sb_fname, 'rb+') - # ret = winobjs.handle_pool.add(sb_fname, h) - log.debug('CreateFile ret %x', ret) - jitter.func_ret_stdcall(ret_ad, ret) - - -def kernel32_CreateFileA(jitter): - kernel32_CreateFile(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr)) - - -def kernel32_CreateFileW(jitter): - kernel32_CreateFile(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr)) - - -def kernel32_ReadFile(jitter): - ret_ad, args = jitter.func_args_stdcall(["hwnd", "lpbuffer", - "nnumberofbytestoread", - "lpnumberofbytesread", - "lpoverlapped"]) - if args.hwnd == winobjs.module_cur_hwnd: - pass - elif args.hwnd in winobjs.handle_pool: - pass - else: - raise ValueError('unknown hwnd!') - - data = None - if args.hwnd in winobjs.files_hwnd: - data = winobjs.files_hwnd[ - winobjs.module_cur_hwnd].read(args.nnumberofbytestoread) - elif args.hwnd in winobjs.handle_pool: - wh = winobjs.handle_pool[args.hwnd] - data = wh.info.read(args.nnumberofbytestoread) - else: - raise ValueError('unknown filename') - - if data is not None: - if (args.lpnumberofbytesread): - jitter.vm.set_u32(args.lpnumberofbytesread, len(data)) - jitter.vm.set_mem(args.lpbuffer, data) - - jitter.func_ret_stdcall(ret_ad, 1) - - -def kernel32_GetFileSize(jitter): - ret_ad, args = jitter.func_args_stdcall(["hwnd", "lpfilesizehight"]) - - if args.hwnd == winobjs.module_cur_hwnd: - ret = len(open(winobjs.module_fname_nux, "rb").read()) - elif args.hwnd in winobjs.handle_pool: - wh = winobjs.handle_pool[args.hwnd] - ret = len(open(wh.name, "rb").read()) - else: - raise ValueError('unknown hwnd!') - - if args.lpfilesizehight != 0: - jitter.vm.set_u32(args.lpfilesizehight, ret) - jitter.func_ret_stdcall(ret_ad, ret) - - -def kernel32_GetFileSizeEx(jitter): - ret_ad, args = jitter.func_args_stdcall(["hwnd", "lpfilesizehight"]) - - if args.hwnd == winobjs.module_cur_hwnd: - l = len(open(winobjs.module_fname_nux, "rb").read()) - elif args.hwnd in winobjs.handle_pool: - wh = winobjs.handle_pool[args.hwnd] - l = len(open(wh.name, "rb").read()) - else: - raise ValueError('unknown hwnd!') - - if args.lpfilesizehight == 0: - raise NotImplementedError("Untested case") - jitter.vm.set_mem(args.lpfilesizehight, pck32( - l & 0xffffffff) + pck32((l >> 32) & 0xffffffff)) - jitter.func_ret_stdcall(ret_ad, 1) - - -def kernel32_FlushInstructionCache(jitter): - ret_ad, _ = jitter.func_args_stdcall(["hprocess", "lpbasead", "dwsize"]) - jitter.func_ret_stdcall(ret_ad, 0x1337) - - -def kernel32_VirtualProtect(jitter): - ret_ad, args = jitter.func_args_stdcall(['lpvoid', 'dwsize', - 'flnewprotect', - 'lpfloldprotect']) - # XXX mask hpart - flnewprotect = args.flnewprotect & 0xFFF - if not flnewprotect in ACCESS_DICT: - raise ValueError('unknown access dw!') - - if args.lpfloldprotect: - old = jitter.vm.get_mem_access(args.lpvoid) - jitter.vm.set_u32(args.lpfloldprotect, ACCESS_DICT_INV[old]) - - paddr = args.lpvoid - (args.lpvoid % winobjs.alloc_align) - paddr_max = (args.lpvoid + args.dwsize + winobjs.alloc_align - 1) - paddr_max_round = paddr_max - (paddr_max % winobjs.alloc_align) - psize = paddr_max_round - paddr - for addr, items in list(winobjs.allocated_pages.items()): - alloc_addr, alloc_size = items - if (paddr + psize <= alloc_addr or - paddr > alloc_addr + alloc_size): - continue - size = jitter.vm.get_all_memory()[addr]["size"] - # Page is included in Protect area - if (paddr <= addr < addr + size <= paddr + psize): - log.warn("set page %x %x", addr, ACCESS_DICT[flnewprotect]) - jitter.vm.set_mem_access(addr, ACCESS_DICT[flnewprotect]) - continue - - # Page is partly in Protect area: splitting is needed - if (addr <= paddr < addr + size or - addr <= paddr + psize < addr + size): - - old_access = jitter.vm.get_mem_access(addr) - - # splits = [ - # addr -> max(paddr, addr) - # max(paddr, addr) -> min(addr + size, paddr + psize) - # min(addr + size, paddr + psize) -> addr + size - # ] - splits = [ - (addr, old_access, - jitter.vm.get_mem(addr, max(paddr, addr) - addr)), - (max(paddr, addr), ACCESS_DICT[flnewprotect], - jitter.vm.get_mem( - max(paddr, addr), - min(addr + size, paddr + psize) - max(paddr, addr))), - (min(addr + size, paddr + psize), old_access, - jitter.vm.get_mem( - min(addr + size, paddr + psize), - addr + size - min(addr + size, paddr + psize))) - ] - - jitter.vm.remove_memory_page(addr) - for split_addr, split_access, split_data in splits: - if not split_data: - continue - log.warn("create page %x %x", split_addr, - ACCESS_DICT[flnewprotect]) - jitter.vm.add_memory_page( - split_addr, split_access, split_data, - "VirtualProtect split ret 0x%X" % ret_ad) - winobjs.allocated_pages[split_addr] = (alloc_addr, alloc_size) - jitter.func_ret_stdcall(ret_ad, 1) - - -def kernel32_VirtualAlloc(jitter): - ret_ad, args = jitter.func_args_stdcall(['lpvoid', 'dwsize', - 'alloc_type', 'flprotect']) - - - if not args.flprotect in ACCESS_DICT: - raise ValueError('unknown access dw!') - - if args.lpvoid == 0: - alloc_addr = winobjs.heap.next_addr(args.dwsize) - winobjs.allocated_pages[alloc_addr] = (alloc_addr, args.dwsize) - jitter.vm.add_memory_page( - alloc_addr, ACCESS_DICT[args.flprotect], b"\x00" * args.dwsize, - "Alloc in %s ret 0x%X" % (whoami(), ret_ad)) - else: - all_mem = jitter.vm.get_all_memory() - if args.lpvoid in all_mem: - alloc_addr = args.lpvoid - jitter.vm.set_mem_access(args.lpvoid, ACCESS_DICT[args.flprotect]) - else: - alloc_addr = winobjs.heap.next_addr(args.dwsize) - winobjs.allocated_pages[alloc_addr] = (alloc_addr, args.dwsize) - # alloc_addr = args.lpvoid - jitter.vm.add_memory_page( - alloc_addr, ACCESS_DICT[args.flprotect], b"\x00" * args.dwsize, - "Alloc in %s ret 0x%X" % (whoami(), ret_ad)) - - log.info('VirtualAlloc addr: 0x%x', alloc_addr) - jitter.func_ret_stdcall(ret_ad, alloc_addr) - - -def kernel32_VirtualFree(jitter): - ret_ad, _ = jitter.func_args_stdcall(["lpvoid", "dwsize", "alloc_type"]) - jitter.func_ret_stdcall(ret_ad, 0) - - -def user32_GetWindowLongA(jitter): - ret_ad, _ = jitter.func_args_stdcall(["hwnd", "nindex"]) - jitter.func_ret_stdcall(ret_ad, winobjs.windowlong_dw) - - -def user32_SetWindowLongA(jitter): - ret_ad, _ = jitter.func_args_stdcall(["hwnd", "nindex", "newlong"]) - jitter.func_ret_stdcall(ret_ad, winobjs.windowlong_dw) - - -def kernel32_GetModuleFileName(jitter, funcname, set_str): - ret_ad, args = jitter.func_args_stdcall(["hmodule", "lpfilename", "nsize"]) - - if args.hmodule in [0, winobjs.hcurmodule]: - p = winobjs.module_path[:] - elif (winobjs.runtime_dll and - args.hmodule in viewvalues(winobjs.runtime_dll.name2off)): - name_inv = dict( - [ - (x[1], x[0]) - for x in viewitems(winobjs.runtime_dll.name2off) - ] - ) - p = name_inv[args.hmodule] - else: - log.warning(('Unknown module 0x%x.' + - 'Set winobjs.hcurmodule and retry'), args.hmodule) - p = None - - if p is None: - l = 0 - elif args.nsize < len(p): - p = p[:args.nsize] - l = len(p) - else: - l = len(p) - - if p: - set_str(args.lpfilename, p) - - jitter.func_ret_stdcall(ret_ad, l) - - -def kernel32_GetModuleFileNameA(jitter): - kernel32_GetModuleFileName(jitter, whoami(), lambda addr,value: set_win_str_a(jitter, addr, value)) - - -def kernel32_GetModuleFileNameW(jitter): - kernel32_GetModuleFileName(jitter, whoami(), lambda addr,value: set_win_str_w(jitter, addr, value)) - - -def kernel32_CreateMutex(jitter, funcname, get_str): - ret_ad, args = jitter.func_args_stdcall(["mutexattr", "initowner", - "lpname"]) - - if args.lpname: - name = get_str(args.lpname) - log.info("CreateMutex %r", name) - else: - name = None - if args.initowner: - if name in winobjs.mutex: - raise NotImplementedError("Untested case") - # ret = 0 - else: - winobjs.mutex[name] = id(name) & 0xFFFFFFFF - ret = winobjs.mutex[name] - else: - if name in winobjs.mutex: - raise NotImplementedError("Untested case") - # ret = 0 - else: - winobjs.mutex[name] = id(name) & 0xFFFFFFFF - ret = winobjs.mutex[name] - jitter.func_ret_stdcall(ret_ad, ret) - - -def kernel32_CreateMutexA(jitter): - kernel32_CreateMutex(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr)) - - -def kernel32_CreateMutexW(jitter): - kernel32_CreateMutex(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr)) - - -def shell32_SHGetSpecialFolderLocation(jitter): - ret_ad, args = jitter.func_args_stdcall(["hwndowner", "nfolder", "ppidl"]) - jitter.vm.set_u32(args.ppidl, args.nfolder) - jitter.func_ret_stdcall(ret_ad, 0) - - -def kernel32_SHGetPathFromIDList(jitter, funcname, set_str): - ret_ad, args = jitter.func_args_stdcall(["pidl", "ppath"]) - - if args.pidl == 7: # CSIDL_STARTUP: - s = "c:\\doc\\user\\startmenu\\programs\\startup" - set_str(args.ppath, s) - else: - raise ValueError('pidl not implemented', args.pidl) - jitter.func_ret_stdcall(ret_ad, 1) - - -def shell32_SHGetPathFromIDListW(jitter): - kernel32_SHGetPathFromIDList(jitter, whoami(), lambda addr,value: set_win_str_w(jitter, addr, value)) - - -def shell32_SHGetPathFromIDListA(jitter): - kernel32_SHGetPathFromIDList(jitter, whoami(), lambda addr,value: set_win_str_a(jitter, addr, value)) - - -def kernel32_GetLastError(jitter): - ret_ad, _ = jitter.func_args_stdcall(0) - jitter.func_ret_stdcall(ret_ad, winobjs.lastwin32error) - - -def kernel32_SetLastError(jitter): - ret_ad, args = jitter.func_args_stdcall(["errcode"]) - # lasterr addr - # ad = tib_address + 0x34 - # jitter.vm.set_mem(ad, pck32(args.errcode)) - winobjs.lastwin32error = args.errcode - jitter.func_ret_stdcall(ret_ad, 0) - - -def kernel32_RestoreLastError(jitter): - kernel32_SetLastError(jitter) - - -def kernel32_LoadLibrary(jitter, get_str): - ret_ad, args = jitter.func_args_stdcall(["dllname"]) - - libname = get_str(args.dllname, 0x100) - ret = winobjs.runtime_dll.lib_get_add_base(libname) - log.info("Loading %r ret 0x%x", libname, ret) - jitter.func_ret_stdcall(ret_ad, ret) - - -def kernel32_LoadLibraryA(jitter): - kernel32_LoadLibrary(jitter, lambda addr, max_char=None:get_win_str_a(jitter, addr, max_char)) - - -def kernel32_LoadLibraryW(jitter): - kernel32_LoadLibrary(jitter, lambda addr, max_char=None:get_win_str_w(jitter, addr, max_char)) - - -def kernel32_LoadLibraryEx(jitter, get_str): - ret_ad, args = jitter.func_args_stdcall(["dllname", "hfile", "flags"]) - - if args.hfile != 0: - raise NotImplementedError("Untested case") - libname = get_str(args.dllname, 0x100) - ret = winobjs.runtime_dll.lib_get_add_base(libname) - log.info("Loading %r ret 0x%x", libname, ret) - jitter.func_ret_stdcall(ret_ad, ret) - - -def kernel32_LoadLibraryExA(jitter): - kernel32_LoadLibraryEx(jitter, lambda addr, max_char=None:get_win_str_a(jitter, addr, max_char)) - - -def kernel32_LoadLibraryExW(jitter): - kernel32_LoadLibraryEx(jitter, lambda addr, max_char=None:get_win_str_w(jitter, addr, max_char)) - - -def kernel32_GetProcAddress(jitter): - ret_ad, args = jitter.func_args_stdcall(["libbase", "fname"]) - fname = args.fname - if fname >= 0x10000: - fname = jitter.get_c_str(fname, 0x100) - if not fname: - fname = None - if fname is not None: - ad = winobjs.runtime_dll.lib_get_add_func(args.libbase, fname) - else: - ad = 0 - log.info("GetProcAddress %r %r ret 0x%x", args.libbase, fname, ad) - jitter.add_breakpoint(ad, jitter.handle_lib) - jitter.func_ret_stdcall(ret_ad, ad) - - -def kernel32_GetModuleHandle(jitter, funcname, get_str): - ret_ad, args = jitter.func_args_stdcall(["dllname"]) - - if args.dllname: - libname = get_str(args.dllname) - if libname: - ret = winobjs.runtime_dll.lib_get_add_base(libname) - else: - log.warning('unknown module!') - ret = 0 - log.info("GetModuleHandle %r ret 0x%x", libname, ret) - else: - ret = winobjs.current_pe.NThdr.ImageBase - log.info("GetModuleHandle default ret 0x%x", ret) - jitter.func_ret_stdcall(ret_ad, ret) - - -def kernel32_GetModuleHandleA(jitter): - kernel32_GetModuleHandle(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr)) - - -def kernel32_GetModuleHandleW(jitter): - kernel32_GetModuleHandle(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr)) - - -def kernel32_VirtualLock(jitter): - ret_ad, _ = jitter.func_args_stdcall(["lpaddress", "dwsize"]) - jitter.func_ret_stdcall(ret_ad, 1) - - -class systeminfo(object): - oemId = 0 - dwPageSize = 0x1000 - lpMinimumApplicationAddress = 0x10000 - lpMaximumApplicationAddress = 0x7ffeffff - dwActiveProcessorMask = 0x1 - numberOfProcessors = 0x1 - ProcessorsType = 586 - dwAllocationgranularity = 0x10000 - wProcessorLevel = 0x6 - ProcessorRevision = 0xf0b - - def pack(self): - return struct.pack('IIIIIIIIHH', - self.oemId, - self.dwPageSize, - self.lpMinimumApplicationAddress, - self.lpMaximumApplicationAddress, - self.dwActiveProcessorMask, - self.numberOfProcessors, - self.ProcessorsType, - self.dwAllocationgranularity, - self.wProcessorLevel, - self.ProcessorRevision) - - -def kernel32_GetSystemInfo(jitter): - ret_ad, args = jitter.func_args_stdcall(["sys_ptr"]) - sysinfo = systeminfo() - jitter.vm.set_mem(args.sys_ptr, sysinfo.pack()) - jitter.func_ret_stdcall(ret_ad, 0) - - -def kernel32_IsWow64Process(jitter): - ret_ad, args = jitter.func_args_stdcall(["process", "bool_ptr"]) - jitter.vm.set_u32(args.bool_ptr, 0) - jitter.func_ret_stdcall(ret_ad, 1) - - -def kernel32_GetCommandLine(jitter, set_str): - ret_ad, _ = jitter.func_args_stdcall(0) - alloc_addr = winobjs.heap.alloc(jitter, 0x1000) - set_str(alloc_addr, '"%s"' % winobjs.module_path) - jitter.func_ret_stdcall(ret_ad, alloc_addr) - - -def kernel32_GetCommandLineA(jitter): - kernel32_GetCommandLine(jitter, lambda addr, value: set_win_str_a(jitter, addr, value)) - - -def kernel32_GetCommandLineW(jitter): - kernel32_GetCommandLine(jitter, lambda addr, value: set_win_str_w(jitter, addr, value)) - - -def shell32_CommandLineToArgvW(jitter): - ret_ad, args = jitter.func_args_stdcall(["pcmd", "pnumargs"]) - cmd = get_win_str_w(jitter, args.pcmd) - if cmd.startswith('"') and cmd.endswith('"'): - cmd = cmd[1:-1] - log.info("CommandLineToArgv %r", cmd) - tks = cmd.split(' ') - addr = winobjs.heap.alloc(jitter, len(cmd) * 2 + 4 * len(tks)) - addr_ret = winobjs.heap.alloc(jitter, 4 * (len(tks) + 1)) - o = 0 - for i, t in enumerate(tks): - set_win_str_w(jitter, addr + o, t) - jitter.vm.set_u32(addr_ret + 4 * i, addr + o) - o += len(t)*2 + 2 - - jitter.vm.set_u32(addr_ret + 4 * (i+1), 0) - jitter.vm.set_u32(args.pnumargs, len(tks)) - jitter.func_ret_stdcall(ret_ad, addr_ret) - -def cryptdll_MD5Init(jitter): - ret_ad, args = jitter.func_args_stdcall(["ad_ctx"]) - index = len(winobjs.cryptdll_md5_h) - h = MD5.new() - winobjs.cryptdll_md5_h[index] = h - - jitter.vm.set_u32(args.ad_ctx, index) - jitter.func_ret_stdcall(ret_ad, 0) - - -def cryptdll_MD5Update(jitter): - ret_ad, args = jitter.func_args_stdcall(["ad_ctx", "ad_input", "inlen"]) - - index = jitter.vm.get_u32(args.ad_ctx) - if not index in winobjs.cryptdll_md5_h: - raise ValueError('unknown h context', index) - - data = jitter.vm.get_mem(args.ad_input, args.inlen) - winobjs.cryptdll_md5_h[index].update(data) - log.debug(hexdump(data)) - - jitter.func_ret_stdcall(ret_ad, 0) - - -def cryptdll_MD5Final(jitter): - ret_ad, args = jitter.func_args_stdcall(["ad_ctx"]) - - index = jitter.vm.get_u32(args.ad_ctx) - if not index in winobjs.cryptdll_md5_h: - raise ValueError('unknown h context', index) - h = winobjs.cryptdll_md5_h[index].digest() - jitter.vm.set_mem(args.ad_ctx + 88, h) - jitter.func_ret_stdcall(ret_ad, 0) - - -def ntdll_RtlInitAnsiString(jitter): - ret_ad, args = jitter.func_args_stdcall(["ad_ctx", "ad_str"]) - - s = get_win_str_a(jitter, args.ad_str) - l = len(s) - jitter.vm.set_mem(args.ad_ctx, - pck16(l) + pck16(l + 1) + pck32(args.ad_str)) - jitter.func_ret_stdcall(ret_ad, 0) - - -def ntdll_RtlHashUnicodeString(jitter): - ret_ad, args = jitter.func_args_stdcall(["ad_ctxu", "case_i", "h_id", - "phout"]) - - if args.h_id != 1: - raise ValueError('unk hash unicode', args.h_id) - - l1, l2, ptra = struct.unpack('HHL', jitter.vm.get_mem(args.ad_ctxu, 8)) - s = jitter.vm.get_mem(ptra, l1) - s = s[:-1] - hv = 0 - - if args.case_i: - s = s.lower() - for c in s: - hv = ((65599 * hv) + ord(c)) & 0xffffffff - jitter.vm.set_u32(args.phout, hv) - jitter.func_ret_stdcall(ret_ad, 0) - - -def kernel32_RtlMoveMemory(jitter): - ret_ad, args = jitter.func_args_stdcall(["ad_dst", "ad_src", "m_len"]) - data = jitter.vm.get_mem(args.ad_src, args.m_len) - jitter.vm.set_mem(args.ad_dst, data) - jitter.func_ret_stdcall(ret_ad, 0) - - -def ntdll_RtlAnsiCharToUnicodeChar(jitter): - ret_ad, args = jitter.func_args_stdcall(['ad_ad_ch']) - ad_ch = jitter.vm.get_u32(args.ad_ad_ch) - ch = ord(jitter.vm.get_mem(ad_ch, 1)) - jitter.vm.set_u32(args.ad_ad_ch, ad_ch + 1) - jitter.func_ret_stdcall(ret_ad, ch) - - -def ntdll_RtlFindCharInUnicodeString(jitter): - ret_ad, args = jitter.func_args_stdcall(["flags", "main_str_ad", - "search_chars_ad", "pos_ad"]) - - if args.flags != 0: - raise ValueError('unk flags') - - ml1, ml2, mptra = struct.unpack('HHL', - jitter.vm.get_mem(args.main_str_ad, 8)) - sl1, sl2, sptra = struct.unpack( - 'HHL', jitter.vm.get_mem(args.search_chars_ad, 8)) - main_data = jitter.vm.get_mem(mptra, ml1)[:-1] - search_data = jitter.vm.get_mem(sptra, sl1)[:-1] - - pos = None - for i, c in enumerate(main_data): - for s in search_data: - if s == c: - pos = i - break - if pos: - break - if pos is None: - ret = 0xC0000225 - jitter.vm.set_u32(args.pos_ad, 0) - else: - ret = 0 - jitter.vm.set_u32(args.pos_ad, pos) - - jitter.func_ret_stdcall(ret_ad, ret) - - -def ntdll_RtlComputeCrc32(jitter): - ret_ad, args = jitter.func_args_stdcall(["dwinit", "pdata", "ilen"]) - data = jitter.vm.get_mem(args.pdata, args.ilen) - crc_r = crc32(data, args.dwinit) - jitter.func_ret_stdcall(ret_ad, crc_r) - - -def ntdll_RtlExtendedIntegerMultiply(jitter): - ret_ad, args = jitter.func_args_stdcall(['multiplicand_low', - 'multiplicand_high', - 'multiplier']) - a = (args.multiplicand_high << 32) + args.multiplicand_low - a = a * args.multiplier - jitter.func_ret_stdcall(ret_ad, a & 0xffffffff, (a >> 32) & 0xffffffff) - - -def ntdll_RtlLargeIntegerAdd(jitter): - ret_ad, args = jitter.func_args_stdcall(['a_low', 'a_high', - 'b_low', 'b_high']) - a = (args.a_high << 32) + args.a_low + (args.b_high << 32) + args.b_low - jitter.func_ret_stdcall(ret_ad, a & 0xffffffff, (a >> 32) & 0xffffffff) - - -def ntdll_RtlLargeIntegerShiftRight(jitter): - ret_ad, args = jitter.func_args_stdcall(['a_low', 'a_high', 's_count']) - a = ((args.a_high << 32) + args.a_low) >> args.s_count - jitter.func_ret_stdcall(ret_ad, a & 0xffffffff, (a >> 32) & 0xffffffff) - - -def ntdll_RtlEnlargedUnsignedMultiply(jitter): - ret_ad, args = jitter.func_args_stdcall(['a', 'b']) - a = args.a * args.b - jitter.func_ret_stdcall(ret_ad, a & 0xffffffff, (a >> 32) & 0xffffffff) - - -def ntdll_RtlLargeIntegerSubtract(jitter): - ret_ad, args = jitter.func_args_stdcall(['a_low', 'a_high', - 'b_low', 'b_high']) - a = (args.a_high << 32) + args.a_low - (args.b_high << 32) + args.b_low - jitter.func_ret_stdcall(ret_ad, a & 0xffffffff, (a >> 32) & 0xffffffff) - - -def ntdll_RtlCompareMemory(jitter): - ret_ad, args = jitter.func_args_stdcall(['ad1', 'ad2', 'm_len']) - data1 = jitter.vm.get_mem(args.ad1, args.m_len) - data2 = jitter.vm.get_mem(args.ad2, args.m_len) - - i = 0 - while data1[i] == data2[i]: - i += 1 - if i >= args.m_len: - break - - jitter.func_ret_stdcall(ret_ad, i) - - -def user32_GetMessagePos(jitter): - ret_ad, _ = jitter.func_args_stdcall(0) - jitter.func_ret_stdcall(ret_ad, 0x00110022) - - -def kernel32_Sleep(jitter): - ret_ad, _ = jitter.func_args_stdcall(['t']) - jitter.func_ret_stdcall(ret_ad, 0) - - -def ntdll_ZwUnmapViewOfSection(jitter): - ret_ad, _ = jitter.func_args_stdcall(['h', 'ad']) - jitter.func_ret_stdcall(ret_ad, 0) - - -def kernel32_IsBadReadPtr(jitter): - ret_ad, _ = jitter.func_args_stdcall(['lp', 'ucb']) - jitter.func_ret_stdcall(ret_ad, 0) - - -def ntoskrnl_KeInitializeEvent(jitter): - ret_ad, args = jitter.func_args_stdcall(['my_event', 'my_type', - 'my_state']) - jitter.vm.set_u32(args.my_event, winobjs.win_event_num) - winobjs.win_event_num += 1 - - jitter.func_ret_stdcall(ret_ad, 0) - - -def ntoskrnl_RtlGetVersion(jitter): - ret_ad, args = jitter.func_args_stdcall(['ptr_version']) - - s = struct.pack("IIIII", - 0x114, # struct size - 0x5, # maj vers - 0x2, # min vers - 0x666, # build nbr - 0x2, # platform id - ) + encode_win_str_w("Service pack 4") - - jitter.vm.set_mem(args.ptr_version, s) - jitter.func_ret_stdcall(ret_ad, 0) - - -def ntoskrnl_RtlVerifyVersionInfo(jitter): - ret_ad, args = jitter.func_args_stdcall(['ptr_version']) - - s = jitter.vm.get_mem(args.ptr_version, 0x5 * 4) - s_size, s_majv, s_minv, s_buildn, s_platform = struct.unpack('IIIII', s) - raise NotImplementedError("Untested case") - # jitter.vm.set_mem(args.ptr_version, s) - # jitter.func_ret_stdcall(ret_ad, 0) - - -def hal_ExAcquireFastMutex(jitter): - ret_ad, _ = jitter.func_args_stdcall(0) - jitter.func_ret_stdcall(ret_ad, 0) - - -def mdl2ad(n): - return winobjs.nt_mdl_ad + 0x10 * n - - -def ad2mdl(ad): - return ((ad - winobjs.nt_mdl_ad) & 0xFFFFFFFF) // 0x10 - - -def ntoskrnl_IoAllocateMdl(jitter): - ret_ad, args = jitter.func_args_stdcall(["v_addr", "l", "second_buf", - "chargequota", "pirp"]) - m = mdl(args.v_addr, args.l) - winobjs.nt_mdl[winobjs.nt_mdl_cur] = m - jitter.vm.set_mem(mdl2ad(winobjs.nt_mdl_cur), bytes(m)) - jitter.func_ret_stdcall(ret_ad, mdl2ad(winobjs.nt_mdl_cur)) - winobjs.nt_mdl_cur += 1 - - -def ntoskrnl_MmProbeAndLockPages(jitter): - ret_ad, args = jitter.func_args_stdcall(["p_mdl", "access_mode", "op"]) - - if not ad2mdl(args.p_mdl) in winobjs.nt_mdl: - raise ValueError('unk mdl', hex(args.p_mdl)) - jitter.func_ret_stdcall(ret_ad, 0) - - -def ntoskrnl_MmMapLockedPagesSpecifyCache(jitter): - ret_ad, args = jitter.func_args_stdcall(["p_mdl", "access_mode", - "cache_type", "base_ad", - "bugcheckonfailure", - "priority"]) - if not ad2mdl(args.p_mdl) in winobjs.nt_mdl: - raise ValueError('unk mdl', hex(args.p_mdl)) - - jitter.func_ret_stdcall(ret_ad, winobjs.nt_mdl[ad2mdl(args.p_mdl)].ad) - - -def ntoskrnl_MmProtectMdlSystemAddress(jitter): - ret_ad, args = jitter.func_args_stdcall(["p_mdl", "prot"]) - if not ad2mdl(args.p_mdl) in winobjs.nt_mdl: - raise ValueError('unk mdl', hex(args.p_mdl)) - - jitter.func_ret_stdcall(ret_ad, 0) - - -def ntoskrnl_MmUnlockPages(jitter): - ret_ad, args = jitter.func_args_stdcall(['p_mdl']) - if not ad2mdl(args.p_mdl) in winobjs.nt_mdl: - raise ValueError('unk mdl', hex(args.p_mdl)) - - jitter.func_ret_stdcall(ret_ad, 0) - - -def ntoskrnl_IoFreeMdl(jitter): - ret_ad, args = jitter.func_args_stdcall(['p_mdl']) - if not ad2mdl(args.p_mdl) in winobjs.nt_mdl: - raise ValueError('unk mdl', hex(args.p_mdl)) - del(winobjs.nt_mdl[ad2mdl(args.p_mdl)]) - jitter.func_ret_stdcall(ret_ad, 0) - - -def hal_ExReleaseFastMutex(jitter): - ret_ad, _ = jitter.func_args_stdcall(0) - jitter.func_ret_stdcall(ret_ad, 0) - - -def ntoskrnl_RtlQueryRegistryValues(jitter): - ret_ad, args = jitter.func_args_stdcall(["relativeto", "path", - "querytable", - "context", - "environ"]) - # path = get_win_str_w(jitter, args.path) - jitter.func_ret_stdcall(ret_ad, 0) - - -def ntoskrnl_ExAllocatePoolWithTagPriority(jitter): - ret_ad, args = jitter.func_args_stdcall(["pool_type", - "nbr_of_bytes", - "tag", "priority"]) - alloc_addr = winobjs.heap.next_addr(args.nbr_of_bytes) - jitter.vm.add_memory_page( - alloc_addr, PAGE_READ | PAGE_WRITE, b"\x00" * args.nbr_of_bytes, - "Alloc in %s ret 0x%X" % (whoami(), ret_ad)) - - jitter.func_ret_stdcall(ret_ad, alloc_addr) - - -def my_lstrcmp(jitter, funcname, get_str): - ret_ad, args = jitter.func_args_stdcall(["ptr_str1", "ptr_str2"]) - s1 = get_str(args.ptr_str1) - s2 = get_str(args.ptr_str2) - log.info("Compare %r with %r", s1, s2) - jitter.func_ret_stdcall(ret_ad, cmp(s1, s2)) - -def msvcrt_wcscmp(jitter): - ret_ad, args = jitter.func_args_cdecl(["ptr_str1", "ptr_str2"]) - s1 = get_win_str_w(jitter, args.ptr_str1) - s2 = get_win_str_w(jitter, args.ptr_str2) - log.debug("%s('%s','%s')" % (whoami(), s1, s2)) - jitter.func_ret_cdecl(ret_ad, cmp(s1, s2)) - -def msvcrt__wcsicmp(jitter): - ret_ad, args = jitter.func_args_cdecl(["ptr_str1", "ptr_str2"]) - s1 = get_win_str_w(jitter, args.ptr_str1) - s2 = get_win_str_w(jitter, args.ptr_str2) - log.debug("%s('%s','%s')" % (whoami(), s1, s2)) - jitter.func_ret_cdecl(ret_ad, cmp(s1.lower(), s2.lower())) - -def msvcrt__wcsnicmp(jitter): - ret_ad, args = jitter.func_args_cdecl(["ptr_str1", "ptr_str2", "count"]) - s1 = get_win_str_w(jitter, args.ptr_str1) - s2 = get_win_str_w(jitter, args.ptr_str2) - log.debug("%s('%s','%s',%d)" % (whoami(), s1, s2, args.count)) - jitter.func_ret_cdecl(ret_ad, cmp(s1.lower()[:args.count], s2.lower()[:args.count])) - -def msvcrt_wcsncpy(jitter): - ret_ad, args = jitter.func_args_cdecl(["dst", "src", "n"]) - src = get_win_str_w(jitter, args.src) - dst = src[:args.n] - jitter.vm.set_mem(args.dst, b"\x00\x00" * args.n) - jitter.vm.set_mem(args.dst, dst.encode("utf-16le")) - jitter.func_ret_cdecl(ret_ad, args.dst) - -def kernel32_lstrcmpA(jitter): - my_lstrcmp(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr)) - - -def kernel32_lstrcmpiA(jitter): - my_lstrcmp(jitter, whoami(), lambda x: get_win_str_a(jitter, x).lower()) - - -def kernel32_lstrcmpW(jitter): - my_lstrcmp(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr)) - - -def kernel32_lstrcmpiW(jitter): - my_lstrcmp(jitter, whoami(), lambda x: get_win_str_w(jitter, x).lower()) - - -def kernel32_lstrcmpi(jitter): - my_lstrcmp(jitter, whoami(), lambda x: get_win_str_a(jitter, x).lower()) - - -def my_strcpy(jitter, funcname, get_str, set_str): - ret_ad, args = jitter.func_args_stdcall(["ptr_str1", "ptr_str2"]) - s2 = get_str(args.ptr_str2) - set_str(args.ptr_str1, s2) - log.info("Copy '%r'", s2) - jitter.func_ret_stdcall(ret_ad, args.ptr_str1) - - -def kernel32_lstrcpyW(jitter): - my_strcpy(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr), lambda addr,value: set_win_str_w(jitter, addr, value)) - - -def kernel32_lstrcpyA(jitter): - my_strcpy(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr), lambda addr,value: set_win_str_a(jitter, addr, value)) - - -def kernel32_lstrcpy(jitter): - my_strcpy(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr), lambda addr,value: set_win_str_a(jitter, addr, value)) - -def msvcrt__mbscpy(jitter): - ret_ad, args = jitter.func_args_cdecl(["ptr_str1", "ptr_str2"]) - s2 = get_win_str_w(jitter, args.ptr_str2) - set_win_str_w(jitter, args.ptr_str1, s2) - jitter.func_ret_cdecl(ret_ad, args.ptr_str1) - -def msvcrt_wcscpy(jitter): - return msvcrt__mbscpy(jitter) - - -def kernel32_lstrcpyn(jitter): - ret_ad, args = jitter.func_args_stdcall(["ptr_str1", "ptr_str2", - "mlen"]) - s2 = get_win_str_a(jitter, args.ptr_str2) - if len(s2) >= args.mlen: - s2 = s2[:args.mlen - 1] - log.info("Copy '%r'", s2) - set_win_str_a(jitter, args.ptr_str1, s2) - jitter.func_ret_stdcall(ret_ad, args.ptr_str1) - - -def my_strlen(jitter, funcname, get_str, mylen): - ret_ad, args = jitter.func_args_stdcall(["src"]) - src = get_str(args.src) - length = mylen(src) - log.info("Len of '%r' -> 0x%x", src, length) - jitter.func_ret_stdcall(ret_ad, length) - - -def kernel32_lstrlenA(jitter): - my_strlen(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr), len) - - -def kernel32_lstrlenW(jitter): - my_strlen(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr), len) - - -def kernel32_lstrlen(jitter): - my_strlen(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr), len) - - -def my_lstrcat(jitter, funcname, get_str, set_str): - ret_ad, args = jitter.func_args_stdcall(['ptr_str1', 'ptr_str2']) - s1 = get_str(args.ptr_str1) - s2 = get_str(args.ptr_str2) - set_str(args.ptr_str1, s1 + s2) - jitter.func_ret_stdcall(ret_ad, args.ptr_str1) - - -def kernel32_lstrcatA(jitter): - my_lstrcat(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr), lambda addr,value: set_win_str_a(jitter, addr, value)) - - -def kernel32_lstrcatW(jitter): - my_lstrcat(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr), lambda addr,value: set_win_str_w(jitter, addr, value)) - - -def kernel32_GetUserGeoID(jitter): - ret_ad, args = jitter.func_args_stdcall(["geoclass"]) - if args.geoclass == 14: - ret = 12345678 - elif args.geoclass == 16: - ret = 55667788 - else: - raise ValueError('unknown geolcass') - jitter.func_ret_stdcall(ret_ad, ret) - - -def my_GetVolumeInformation(jitter, funcname, get_str, set_str): - ret_ad, args = jitter.func_args_stdcall(["lprootpathname", - "lpvolumenamebuffer", - "nvolumenamesize", - "lpvolumeserialnumber", - "lpmaximumcomponentlength", - "lpfilesystemflags", - "lpfilesystemnamebuffer", - "nfilesystemnamesize"]) - if args.lprootpathname: - s = get_str(args.lprootpathname) - log.info('GetVolumeInformation %r', s) - - - if args.lpvolumenamebuffer: - s = "volumename" - s = s[:args.nvolumenamesize] - set_str(args.lpvolumenamebuffer, s) - - if args.lpvolumeserialnumber: - jitter.vm.set_u32(args.lpvolumeserialnumber, 11111111) - if args.lpmaximumcomponentlength: - jitter.vm.set_u32(args.lpmaximumcomponentlength, 0xff) - if args.lpfilesystemflags: - jitter.vm.set_u32(args.lpfilesystemflags, 22222222) - - if args.lpfilesystemnamebuffer: - s = "filesystemname" - s = s[:args.nfilesystemnamesize] - set_str(args.lpfilesystemnamebuffer, s) - - jitter.func_ret_stdcall(ret_ad, 1) - - -def kernel32_GetVolumeInformationA(jitter): - my_GetVolumeInformation( - jitter, whoami(), lambda addr:get_win_str_a(jitter, addr), lambda addr,value: set_win_str_a(jitter, addr, value)) - - -def kernel32_GetVolumeInformationW(jitter): - my_GetVolumeInformation(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr), lambda addr,value: set_win_str_w(jitter, addr, value)) - - -def kernel32_MultiByteToWideChar(jitter): - MB_ERR_INVALID_CHARS = 0x8 - CP_ACP = 0x000 - CP_1252 = 0x4e4 - - ret_ad, args = jitter.func_args_stdcall(["codepage", "dwflags", - "lpmultibytestr", - "cbmultibyte", - "lpwidecharstr", - "cchwidechar"]) - if args.codepage != CP_ACP and args.codepage != CP_1252: - raise NotImplementedError - # according to MSDN: - # "Note that, if cbMultiByte is 0, the function fails." - if args.cbmultibyte == 0: - raise ValueError - # according to MSDN: - # "Alternatively, this parameter can be set to -1 if the string is - # null-terminated." - if args.cbmultibyte == 0xffffffff: - src_len = 0 - while jitter.vm.get_mem(args.lpmultibytestr + src_len, 1) != b'\0': - src_len += 1 - src = jitter.vm.get_mem(args.lpmultibytestr, src_len) - else: - src = jitter.vm.get_mem(args.lpmultibytestr, args.cbmultibyte) - if args.dwflags & MB_ERR_INVALID_CHARS: - # will raise an exception if decoding fails - s = src.decode("cp1252", errors="replace").encode("utf-16le") - else: - # silently replace undecodable chars with U+FFFD - s = src.decode("cp1252", errors="replace").encode("utf-16le") - if args.cchwidechar > 0: - # return value is number of bytes written - retval = min(args.cchwidechar, len(s)) - jitter.vm.set_mem(args.lpwidecharstr, s[:retval]) - else: - # return value is number of bytes to write - # i.e., size of dest. buffer to allocate - retval = len(s) - jitter.func_ret_stdcall(ret_ad, retval) - - -def kernel32_WideCharToMultiByte(jitter): - """ - int WideCharToMultiByte( - UINT CodePage, - DWORD dwFlags, - _In_NLS_string_(cchWideChar)LPCWCH lpWideCharStr, - int cchWideChar, - LPSTR lpMultiByteStr, - int cbMultiByte, - LPCCH lpDefaultChar, - LPBOOL lpUsedDefaultChar - ); - - """ - CP_ACP = 0x000 - CP_1252 = 0x4e4 - - ret, args = jitter.func_args_stdcall([ - 'CodePage', 'dwFlags', 'lpWideCharStr', 'cchWideChar', - 'lpMultiByteStr', 'cbMultiByte', 'lpDefaultChar', 'lpUsedDefaultChar', - ]) - if args.CodePage != CP_ACP and args.CodePage != CP_1252: - raise NotImplementedError - cchWideChar = args.cchWideChar - if cchWideChar == 0xffffffff: - cchWideChar = len(get_win_str_w(jitter, args.lpWideCharStr)) + 1 - src = jitter.vm.get_mem(args.lpWideCharStr, cchWideChar * 2) - dst = src.decode("utf-16le").encode("cp1252", errors="replace") - if args.cbMultiByte > 0: - # return value is the number of bytes written - retval = min(args.cbMultiByte, len(dst)) - jitter.vm.set_mem(args.lpMultiByteStr, dst[:retval]) - else: - # return value is the size of the buffer to allocate - # to get the multibyte string - retval = len(dst) - jitter.func_ret_stdcall(ret, retval) - - -def my_GetEnvironmentVariable(jitter, funcname, get_str, set_str, mylen): - ret_ad, args = jitter.func_args_stdcall(["lpname", "lpbuffer", - "nsize"]) - - s = get_str(args.lpname) - log.info('GetEnvironmentVariable %r', s) - if s in winobjs.env_variables: - v = winobjs.env_variables[s] - else: - log.warning('WARNING unknown env variable %r', s) - v = "" - set_str(args.lpbuffer, v) - jitter.func_ret_stdcall(ret_ad, mylen(v)) - - -def kernel32_GetEnvironmentVariableA(jitter): - my_GetEnvironmentVariable(jitter, whoami(), - lambda addr:get_win_str_a(jitter, addr), - lambda addr,value: set_win_str_a(jitter, addr, value), - len) - - -def kernel32_GetEnvironmentVariableW(jitter): - my_GetEnvironmentVariable(jitter, whoami(), - lambda addr:get_win_str_w(jitter, addr), - lambda addr,value: set_win_str_w(jitter, addr, value), - len) - - -def my_GetSystemDirectory(jitter, funcname, set_str): - ret_ad, args = jitter.func_args_stdcall(["lpbuffer", "usize"]) - s = "c:\\windows\\system32" - l = len(s) - set_str(args.lpbuffer, s) - jitter.func_ret_stdcall(ret_ad, l) - - - -def kernel32_GetSystemDirectoryA(jitter): - my_GetSystemDirectory(jitter, whoami(), lambda addr,value: set_win_str_a(jitter, addr, value)) - - -def kernel32_GetSystemDirectoryW(jitter): - my_GetSystemDirectory(jitter, whoami(), lambda addr,value: set_win_str_w(jitter, addr, value)) - - -def my_CreateDirectory(jitter, funcname, get_str): - ret_ad, args = jitter.func_args_stdcall(['lppath', 'secattrib']) - # path = get_str(jitter, args.lppath) - jitter.func_ret_stdcall(ret_ad, 0x1337) - - -def kernel32_CreateDirectoryW(jitter): - my_CreateDirectory(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr)) - - -def kernel32_CreateDirectoryA(jitter): - my_CreateDirectory(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr)) - - - -def my_CreateEvent(jitter, funcname, get_str): - ret_ad, args = jitter.func_args_stdcall(["lpeventattributes", - "bmanualreset", - "binitialstate", - "lpname"]) - s = get_str(args.lpname) if args.lpname else None - if not s in winobjs.events_pool: - winobjs.events_pool[s] = (args.bmanualreset, args.binitialstate) - else: - log.warning('WARNING: known event') - jitter.func_ret_stdcall(ret_ad, id(s) & 0xFFFFFFFF) - - -def kernel32_CreateEventA(jitter): - my_CreateEvent(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr)) - - -def kernel32_CreateEventW(jitter): - my_CreateEvent(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr)) - - -def kernel32_WaitForSingleObject(jitter): - ret_ad, args = jitter.func_args_stdcall(['handle', 'dwms']) - - t_start = time.time() * 1000 - found = False - while True: - if args.dwms and args.dwms + t_start > time.time() * 1000: - ret = 0x102 - break - for key, value in viewitems(winobjs.events_pool): - if key != args.handle: - continue - found = True - if value[1] == 1: - ret = 0 - break - if not found: - log.warning('unknown handle') - ret = 0xffffffff - break - time.sleep(0.1) - jitter.func_ret_stdcall(ret_ad, ret) - - -def kernel32_SetFileAttributesA(jitter): - ret_ad, args = jitter.func_args_stdcall(["lpfilename", - "dwfileattributes"]) - if args.lpfilename: - # fname = get_win_str_a(jitter, args.lpfilename) - ret = 1 - else: - ret = 0 - jitter.vm.set_u32(tib_address + 0x34, 3) - - jitter.func_ret_stdcall(ret_ad, ret) - - -def ntdll_RtlMoveMemory(jitter): - ret_ad, args = jitter.func_args_stdcall(["dst", "src", "l"]) - s = jitter.vm.get_mem(args.src, args.l) - jitter.vm.set_mem(args.dst, s) - jitter.func_ret_stdcall(ret_ad, 1) - - -def ntdll_ZwQuerySystemInformation(jitter): - ret_ad, args = jitter.func_args_stdcall(["systeminformationclass", - "systeminformation", - "systeminformationl", - "returnl"]) - if args.systeminformationclass == 2: - # SYSTEM_PERFORMANCE_INFORMATION - o = struct.pack('II', 0x22222222, 0x33333333) - o += b"\x00" * args.systeminformationl - o = o[:args.systeminformationl] - jitter.vm.set_mem(args.systeminformation, o) - else: - raise ValueError('unknown sysinfo class', - args.systeminformationclass) - jitter.func_ret_stdcall(ret_ad, 0) - - -def ntdll_ZwProtectVirtualMemory(jitter): - ret_ad, args = jitter.func_args_stdcall(["handle", "lppvoid", - "pdwsize", - "flnewprotect", - "lpfloldprotect"]) - - ad = jitter.vm.get_u32(args.lppvoid) - # dwsize = upck32(jitter.vm.get_mem(args.pdwsize, 4)) - # XXX mask hpart - flnewprotect = args.flnewprotect & 0xFFF - - if not flnewprotect in ACCESS_DICT: - raise ValueError('unknown access dw!') - jitter.vm.set_mem_access(ad, ACCESS_DICT[flnewprotect]) - - # XXX todo real old protect - jitter.vm.set_u32(args.lpfloldprotect, 0x40) - - jitter.func_ret_stdcall(ret_ad, 1) - - -def ntdll_ZwAllocateVirtualMemory(jitter): - ret_ad, args = jitter.func_args_stdcall(["handle", "lppvoid", - "zerobits", "pdwsize", - "alloc_type", - "flprotect"]) - - # ad = upck32(jitter.vm.get_mem(args.lppvoid, 4)) - dwsize = jitter.vm.get_u32(args.pdwsize) - - if not args.flprotect in ACCESS_DICT: - raise ValueError('unknown access dw!') - - alloc_addr = winobjs.heap.next_addr(dwsize) - jitter.vm.add_memory_page( - alloc_addr, ACCESS_DICT[args.flprotect], b"\x00" * dwsize, - "Alloc in %s ret 0x%X" % (whoami(), ret_ad)) - jitter.vm.set_u32(args.lppvoid, alloc_addr) - - jitter.func_ret_stdcall(ret_ad, 0) - - -def ntdll_ZwFreeVirtualMemory(jitter): - ret_ad, args = jitter.func_args_stdcall(["handle", "lppvoid", - "pdwsize", "alloc_type"]) - # ad = upck32(jitter.vm.get_mem(args.lppvoid, 4)) - # dwsize = upck32(jitter.vm.get_mem(args.pdwsize, 4)) - jitter.func_ret_stdcall(ret_ad, 0) - - -def ntdll_RtlInitString(jitter): - ret_ad, args = jitter.func_args_stdcall(["pstring", "source"]) - s = get_win_str_a(jitter, args.source) - l = len(s) + 1 - o = struct.pack('HHI', l, l, args.source) - jitter.vm.set_mem(args.pstring, o) - jitter.func_ret_stdcall(ret_ad, 0) - - -def ntdll_RtlAnsiStringToUnicodeString(jitter): - ret_ad, args = jitter.func_args_stdcall(["dst", "src", "alloc_str"]) - - l1, l2, p_src = struct.unpack('HHI', jitter.vm.get_mem(args.src, 0x8)) - s = get_win_str_a(jitter, p_src) - l = (len(s) + 1) * 2 - if args.alloc_str: - alloc_addr = winobjs.heap.next_addr(l) - jitter.vm.add_memory_page( - alloc_addr, PAGE_READ | PAGE_WRITE, b"\x00" * l, - "Alloc in %s ret 0x%X" % (whoami(), ret_ad)) - else: - alloc_addr = p_src - set_win_str_w(jitter, alloc_addr, s) - o = struct.pack('HHI', l, l, alloc_addr) - jitter.vm.set_mem(args.dst, o) - jitter.func_ret_stdcall(ret_ad, 0) - - -def ntdll_LdrLoadDll(jitter): - ret_ad, args = jitter.func_args_stdcall(["path", "flags", - "modname", "modhandle"]) - - l1, l2, p_src = struct.unpack('HHI', - jitter.vm.get_mem(args.modname, 0x8)) - s = get_win_str_w(jitter, p_src) - libname = s.lower() - - ad = winobjs.runtime_dll.lib_get_add_base(libname) - log.info("Loading %r ret 0x%x", s, ad) - jitter.vm.set_u32(args.modhandle, ad) - - jitter.func_ret_stdcall(ret_ad, 0) - - -def ntdll_RtlFreeUnicodeString(jitter): - ret_ad, args = jitter.func_args_stdcall(['src']) - # l1, l2, p_src = struct.unpack('HHI', jitter.vm.get_mem(args.src, 0x8)) - # s = get_win_str_w(jitter, p_src) - jitter.func_ret_stdcall(ret_ad, 0) - - -def ntdll_LdrGetProcedureAddress(jitter): - ret_ad, args = jitter.func_args_stdcall(["libbase", "pfname", - "opt", "p_ad"]) - - l1, l2, p_src = struct.unpack('HHI', jitter.vm.get_mem(args.pfname, 0x8)) - fname = get_win_str_a(jitter, p_src) - - ad = winobjs.runtime_dll.lib_get_add_func(args.libbase, fname) - jitter.add_breakpoint(ad, jitter.handle_lib) - - jitter.vm.set_u32(args.p_ad, ad) - - jitter.func_ret_stdcall(ret_ad, 0) - - -def ntdll_memset(jitter): - ret_ad, args = jitter.func_args_cdecl(['addr', 'c', 'size']) - jitter.vm.set_mem(args.addr, int_to_byte(args.c) * args.size) - jitter.func_ret_cdecl(ret_ad, args.addr) - - -def msvcrt_memset(jitter): - ret_ad, args = jitter.func_args_cdecl(['addr', 'c', 'size']) - jitter.vm.set_mem(args.addr, int_to_byte(args.c) * args.size) - jitter.func_ret_cdecl(ret_ad, args.addr) - -def msvcrt_strrchr(jitter): - ret_ad, args = jitter.func_args_cdecl(['pstr','c']) - s = get_win_str_a(jitter, args.pstr) - c = int_to_byte(args.c).decode() - ret = args.pstr + s.rfind(c) - log.info("strrchr(%x '%s','%s') = %x" % (args.pstr,s,c,ret)) - jitter.func_ret_cdecl(ret_ad, ret) - -def msvcrt_wcsrchr(jitter): - ret_ad, args = jitter.func_args_cdecl(['pstr','c']) - s = get_win_str_w(jitter, args.pstr) - c = int_to_byte(args.c).decode() - ret = args.pstr + (s.rfind(c)*2) - log.info("wcsrchr(%x '%s',%s) = %x" % (args.pstr,s,c,ret)) - jitter.func_ret_cdecl(ret_ad, ret) - -def msvcrt_memcpy(jitter): - ret_ad, args = jitter.func_args_cdecl(['dst', 'src', 'size']) - s = jitter.vm.get_mem(args.src, args.size) - jitter.vm.set_mem(args.dst, s) - jitter.func_ret_cdecl(ret_ad, args.dst) - -def msvcrt_realloc(jitter): - ret_ad,args = jitter.func_args_cdecl(['ptr','new_size']) - if args.ptr == 0: - addr = winobjs.heap.alloc(jitter, args.new_size) - else: - addr = winobjs.heap.alloc(jitter, args.new_size) - size = winobjs.heap.get_size(jitter.vm, args.ptr) - data = jitter.vm.get_mem(args.ptr, size) - jitter.vm.set_mem(addr, data) - jitter.func_ret_cdecl(ret_ad, addr) - -def msvcrt_memcmp(jitter): - ret_ad, args = jitter.func_args_cdecl(['ps1', 'ps2', 'size']) - s1 = jitter.vm.get_mem(args.ps1, args.size) - s2 = jitter.vm.get_mem(args.ps2, args.size) - ret = cmp(s1, s2) - jitter.func_ret_cdecl(ret_ad, ret) - - -def shlwapi_PathFindExtensionA(jitter): - ret_ad, args = jitter.func_args_stdcall(['path_ad']) - path = get_win_str_a(jitter, args.path_ad) - i = path.rfind('.') - if i == -1: - i = args.path_ad + len(path) - else: - i = args.path_ad + i - jitter.func_ret_stdcall(ret_ad, i) - - -def shlwapi_PathRemoveFileSpecW(jitter): - ret_ad, args = jitter.func_args_stdcall(['path_ad']) - path = get_win_str_w(jitter, args.path_ad) - i = path.rfind('\\') - if i == -1: - i = 0 - jitter.vm.set_mem(args.path_ad + i * 2, b"\x00\x00") - path = get_win_str_w(jitter, args.path_ad) - jitter.func_ret_stdcall(ret_ad, 1) - - -def shlwapi_PathIsPrefixW(jitter): - ret_ad, args = jitter.func_args_stdcall(['ptr_prefix', 'ptr_path']) - prefix = get_win_str_w(jitter, args.ptr_prefix) - path = get_win_str_w(jitter, args.ptr_path) - - if path.startswith(prefix): - ret = 1 - else: - ret = 0 - jitter.func_ret_stdcall(ret_ad, ret) - - -def shlwapi_PathIsDirectoryW(jitter): - ret_ad, args = jitter.func_args_stdcall(['ptr_path']) - fname = get_win_str_w(jitter, args.ptr_path) - - sb_fname = windows_to_sbpath(fname) - - s = os.stat(sb_fname) - ret = 0 - if stat.S_ISDIR(s.st_mode): - ret = 1 - - jitter.func_ret_cdecl(ret_ad, ret) - - -def shlwapi_PathIsFileSpec(jitter, funcname, get_str): - ret_ad, args = jitter.func_args_stdcall(['path_ad']) - path = get_str(args.path_ad) - if path.find(':') != -1 and path.find('\\') != -1: - ret = 0 - else: - ret = 1 - - jitter.func_ret_stdcall(ret_ad, ret) - - -def shlwapi_PathGetDriveNumber(jitter, funcname, get_str): - ret_ad, args = jitter.func_args_stdcall(['path_ad']) - path = get_str(args.path_ad) - l = ord(path[0].upper()) - ord('A') - if 0 <= l <= 25: - ret = l - else: - ret = -1 - - jitter.func_ret_stdcall(ret_ad, ret) - - -def shlwapi_PathGetDriveNumberA(jitter): - shlwapi_PathGetDriveNumber(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr)) - - -def shlwapi_PathGetDriveNumberW(jitter): - shlwapi_PathGetDriveNumber(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr)) - - -def shlwapi_PathIsFileSpecA(jitter): - shlwapi_PathIsFileSpec(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr)) - - -def shlwapi_PathIsFileSpecW(jitter): - shlwapi_PathIsFileSpec(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr)) - - -def shlwapi_StrToIntA(jitter): - ret_ad, args = jitter.func_args_stdcall(['i_str_ad']) - i_str = get_win_str_a(jitter, args.i_str_ad) - try: - i = int(i_str) - except: - log.warning('WARNING cannot convert int') - i = 0 - - jitter.func_ret_stdcall(ret_ad, i) - - -def shlwapi_StrToInt64Ex(jitter, funcname, get_str): - ret_ad, args = jitter.func_args_stdcall(['pstr', 'flags', 'pret']) - i_str = get_str(args.pstr) - - if args.flags == 0: - r = int(i_str) - elif args.flags == 1: - r = int(i_str, 16) - else: - raise ValueError('cannot decode int') - - jitter.vm.set_mem(args.pret, struct.pack('q', r)) - jitter.func_ret_stdcall(ret_ad, 1) - - -def shlwapi_StrToInt64ExA(jitter): - shlwapi_StrToInt64Ex(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr)) - - -def shlwapi_StrToInt64ExW(jitter): - shlwapi_StrToInt64Ex(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr)) - - -def user32_IsCharAlpha(jitter, funcname, get_str): - ret_ad, args = jitter.func_args_stdcall(["c"]) - try: - c = int_to_byte(args.c) - except: - log.error('bad char %r', args.c) - c = "\x00" - if c.isalpha(jitter): - ret = 1 - else: - ret = 0 - jitter.func_ret_stdcall(ret_ad, ret) - - -def user32_IsCharAlphaA(jitter): - user32_IsCharAlpha(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr)) - - -def user32_IsCharAlphaW(jitter): - user32_IsCharAlpha(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr)) - - -def user32_IsCharAlphaNumericA(jitter): - ret_ad, args = jitter.func_args_stdcall(["c"]) - c = int_to_byte(args.c) - if c.isalnum(jitter): - ret = 1 - else: - ret = 0 - jitter.func_ret_stdcall(ret_ad, ret) - -def get_fmt_args(jitter, fmt, cur_arg, get_str): - return _get_fmt_args(fmt, cur_arg, get_str, jitter.get_arg_n_cdecl) - -def msvcrt_sprintf_str(jitter, get_str): - ret_ad, args = jitter.func_args_cdecl(['string', 'fmt']) - cur_arg, fmt = 2, args.fmt - return ret_ad, args, get_fmt_args(jitter, fmt, cur_arg, get_str) - -def msvcrt_sprintf(jitter): - ret_ad, args, output = msvcrt_sprintf_str(jitter, lambda addr:get_win_str_a(jitter, addr)) - ret = len(output) - log.info("sprintf() = '%s'" % (output)) - jitter.vm.set_mem(args.string, (output + '\x00').encode('utf8')) - return jitter.func_ret_cdecl(ret_ad, ret) - -def msvcrt_swprintf(jitter): - ret_ad, args = jitter.func_args_cdecl(['string', 'fmt']) - cur_arg, fmt = 2, args.fmt - output = get_fmt_args(jitter, fmt, cur_arg, lambda addr:get_win_str_w(jitter, addr)) - ret = len(output) - log.info("swprintf('%s') = '%s'" % (get_win_str_w(jitter, args.fmt), output)) - jitter.vm.set_mem(args.string, output.encode("utf-16le") + b'\x00\x00') - return jitter.func_ret_cdecl(ret_ad, ret) - -def msvcrt_fprintf(jitter): - ret_addr, args = jitter.func_args_cdecl(['file', 'fmt']) - cur_arg, fmt = 2, args.fmt - output = get_fmt_args(jitter, fmt, cur_arg, lambda addr:get_win_str_a(jitter, addr)) - ret = len(output) - log.info("fprintf(%x, '%s') = '%s'" % (args.file, lambda addr:get_win_str_a(jitter, addr)(args.fmt), output)) - - fd = jitter.vm.get_u32(args.file + 0x10) - if not fd in winobjs.handle_pool: - raise NotImplementedError("Untested case") - winobjs.handle_pool[fd].info.write(output) - - return jitter.func_ret_cdecl(ret_addr, ret) - -def shlwapi_StrCmpNIA(jitter): - ret_ad, args = jitter.func_args_stdcall(["ptr_str1", "ptr_str2", - "nchar"]) - s1 = get_win_str_a(jitter, args.ptr_str1).lower() - s2 = get_win_str_a(jitter, args.ptr_str2).lower() - s1 = s1[:args.nchar] - s2 = s2[:args.nchar] - jitter.func_ret_stdcall(ret_ad, cmp(s1, s2)) - - -def advapi32_RegCreateKeyW(jitter): - ret_ad, args = jitter.func_args_stdcall(["hkey", "subkey", - "phandle"]) - s_subkey = get_win_str_w(jitter, args.subkey).lower() if args.subkey else "" - - ret_hkey = 0 - ret = 2 - if args.hkey in winobjs.hkey_handles: - ret = 0 - if s_subkey: - ret_hkey = hash(s_subkey) & 0xffffffff - winobjs.hkey_handles[ret_hkey] = s_subkey - else: - ret_hkey = args.hkey - - log.info("RegCreateKeyW(%x, '%s') = (%x,%d)" % (args.hkey, s_subkey, ret_hkey, ret)) - jitter.vm.set_u32(args.phandle, ret_hkey) - - jitter.func_ret_stdcall(ret_ad, ret) - -def kernel32_GetCurrentDirectoryA(jitter): - ret_ad, args = jitter.func_args_stdcall(["size","buf"]) - dir_ = winobjs.cur_dir - log.debug("GetCurrentDirectory() = '%s'" % dir_) - set_win_str_a(jitter, args.buf, dir_[:args.size-1]) - ret = len(dir_) - if args.size <= len(dir_): - ret += 1 - jitter.func_ret_stdcall(ret_ad, ret) - -def advapi32_RegOpenKeyEx(jitter, funcname, get_str): - ret_ad, args = jitter.func_args_stdcall(["hkey", "subkey", - "reserved", "access", - "phandle"]) - s_subkey = get_str(args.subkey).lower() if args.subkey else "" - - ret_hkey = 0 - ret = 2 - if args.hkey in winobjs.hkey_handles: - if s_subkey: - h = hash(s_subkey) & 0xffffffff - if h in winobjs.hkey_handles: - ret_hkey = h - ret = 0 - else: - log.error('unknown skey') - - jitter.vm.set_u32(args.phandle, ret_hkey) - - jitter.func_ret_stdcall(ret_ad, ret) - - -def advapi32_RegOpenKeyExA(jitter): - advapi32_RegOpenKeyEx(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr)) - - -def advapi32_RegOpenKeyExW(jitter): - advapi32_RegOpenKeyEx(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr)) - - -def advapi32_RegSetValue(jitter, funcname, get_str): - ret_ad, args = jitter.func_args_stdcall(["hkey", "psubkey", - "valuetype", "pvalue", - "vlen"]) - if args.psubkey: - log.info("Subkey %s", get_str(args.psubkey)) - if args.pvalue: - log.info("Value %s", get_str(args.pvalue)) - jitter.func_ret_stdcall(ret_ad, 0) - -def advapi32_RegSetValueEx(jitter, funcname, get_str): - ret_ad, args = jitter.func_args_stdcall(["hkey", "lpvaluename", - "reserved", "dwtype", - "lpdata", "cbData"]) - hkey = winobjs.hkey_handles.get(args.hkey, "unknown HKEY") - value_name = get_str(args.lpvaluename) if args.lpvaluename else "" - data = get_str(args.lpdata) if args.lpdata else "" - log.info("%s('%s','%s'='%s',%x)" % (funcname, hkey, value_name, data, args.dwtype)) - jitter.func_ret_stdcall(ret_ad, 0) - -def advapi32_RegCloseKey(jitter): - ret_ad, args = jitter.func_args_stdcall(["hkey"]) - del winobjs.hkey_handles[args.hkey] - log.info("RegCloseKey(%x)" % args.hkey) - jitter.func_ret_stdcall(ret_ad, 0) - -def advapi32_RegSetValueExA(jitter): - advapi32_RegSetValueEx(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr)) - - -def advapi32_RegSetValueExW(jitter): - advapi32_RegOpenKeyEx(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr)) - - -def advapi32_RegSetValueA(jitter): - advapi32_RegSetValue(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr)) - - -def advapi32_RegSetValueW(jitter): - advapi32_RegSetValue(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr)) - - -def kernel32_GetThreadLocale(jitter): - ret_ad, _ = jitter.func_args_stdcall(0) - jitter.func_ret_stdcall(ret_ad, 0x40c) - -def kernel32_SetCurrentDirectory(jitter, get_str): - ret_ad, args = jitter.func_args_stdcall(['dir']) - dir_ = get_str(args.dir) - log.debug("SetCurrentDirectory('%s') = 1" % dir_) - winobjs.cur_dir = dir_ - jitter.func_ret_stdcall(ret_ad, 1) - -def kernel32_SetCurrentDirectoryW(jitter): - return kernel32_SetCurrentDirectory(jitter, lambda addr:get_win_str_w(jitter, addr)) - -def kernel32_SetCurrentDirectoryA(jitter): - return kernel32_SetCurrentDirectory(jitter, lambda addr:get_win_str_a(jitter, addr)) - -def msvcrt_wcscat(jitter): - ret_ad, args = jitter.func_args_cdecl(['ptr_str1', 'ptr_str2']) - s1 = get_win_str_w(jitter, args.ptr_str1) - s2 = get_win_str_w(jitter, args.ptr_str2) - log.info("strcat('%s','%s')" % (s1,s2)) - set_win_str_w(jitter, args.ptr_str1, s1 + s2) - jitter.func_ret_cdecl(ret_ad, args.ptr_str1) - - -def kernel32_GetLocaleInfo(jitter, funcname, set_str): - ret_ad, args = jitter.func_args_stdcall(["localeid", "lctype", - "lplcdata", "cchdata"]) - - buf = None - ret = 0 - if args.localeid == 0x40c: - if args.lctype == 0x3: - buf = "ENGLISH" - buf = buf[:args.cchdata - 1] - set_str(args.lplcdata, buf) - ret = len(buf) - else: - raise ValueError('unimpl localeid') - - jitter.func_ret_stdcall(ret_ad, ret) - - -def kernel32_GetLocaleInfoA(jitter): - kernel32_GetLocaleInfo(jitter, whoami(), lambda addr,value: set_win_str_a(jitter, addr, value)) - - -def kernel32_GetLocaleInfoW(jitter): - kernel32_GetLocaleInfo(jitter, whoami(), lambda addr,value: set_win_str_w(jitter, addr, value)) - - -def kernel32_TlsAlloc(jitter): - ret_ad, _ = jitter.func_args_stdcall(0) - winobjs.tls_index += 1 - jitter.func_ret_stdcall(ret_ad, winobjs.tls_index) - - -def kernel32_TlsFree(jitter): - ret_ad, _ = jitter.func_args_stdcall(["tlsindex"]) - jitter.func_ret_stdcall(ret_ad, 0) - - -def kernel32_TlsSetValue(jitter): - ret_ad, args = jitter.func_args_stdcall(["tlsindex", "tlsvalue"]) - winobjs.tls_values[args.tlsindex] = args.tlsvalue - jitter.func_ret_stdcall(ret_ad, 1) - - -def kernel32_TlsGetValue(jitter): - ret_ad, args = jitter.func_args_stdcall(["tlsindex"]) - if not args.tlsindex in winobjs.tls_values: - raise ValueError("unknown tls val", repr(args.tlsindex)) - jitter.func_ret_stdcall(ret_ad, winobjs.tls_values[args.tlsindex]) - - -def user32_GetKeyboardType(jitter): - ret_ad, args = jitter.func_args_stdcall(["typeflag"]) - - ret = 0 - if args.typeflag == 0: - ret = 4 - else: - raise ValueError('unimpl keyboard type') - - jitter.func_ret_stdcall(ret_ad, ret) - - -class startupinfo(object): - """ - typedef struct _STARTUPINFOA { - /* 00000000 */ DWORD cb; - /* 00000004 */ LPSTR lpReserved; - /* 00000008 */ LPSTR lpDesktop; - /* 0000000C */ LPSTR lpTitle; - /* 00000010 */ DWORD dwX; - /* 00000014 */ DWORD dwY; - /* 00000018 */ DWORD dwXSize; - /* 0000001C */ DWORD dwYSize; - /* 00000020 */ DWORD dwXCountChars; - /* 00000024 */ DWORD dwYCountChars; - /* 00000028 */ DWORD dwFillAttribute; - /* 0000002C */ DWORD dwFlags; - /* 00000030 */ WORD wShowWindow; - /* 00000032 */ WORD cbReserved2; - /* 00000034 */ LPBYTE lpReserved2; - /* 00000038 */ HANDLE hStdInput; - /* 0000003C */ HANDLE hStdOutput; - /* 00000040 */ HANDLE hStdError; - } STARTUPINFOA, *LPSTARTUPINFOA; - - """ - # TODO: fill with relevant values - # for now, struct is just a placeholder - cb = 0x0 - lpReserved = 0x0 - lpDesktop = 0x0 - lpTitle = 0x0 - dwX = 0x0 - dwY = 0x0 - dwXSize = 0x0 - dwYSize = 0x0 - dwXCountChars = 0x0 - dwYCountChars = 0x0 - dwFillAttribute = 0x0 - dwFlags = 0x0 - wShowWindow = 0x0 - cbReserved2 = 0x0 - lpReserved2 = 0x0 - hStdInput = 0x0 - hStdOutput = 0x0 - hStdError = 0x0 - - def pack(self): - return struct.pack('IIIIIIIIIIIIHHIIII', - self.cb, - self.lpReserved, - self.lpDesktop, - self.lpTitle, - self.dwX, - self.dwY, - self.dwXSize, - self.dwYSize, - self.dwXCountChars, - self.dwYCountChars, - self.dwFillAttribute, - self.dwFlags, - self.wShowWindow, - self.cbReserved2, - self.lpReserved2, - self.hStdInput, - self.hStdOutput, - self.hStdError) - - -def kernel32_GetStartupInfo(jitter, funcname, set_str): - """ - void GetStartupInfo( - LPSTARTUPINFOW lpStartupInfo - ); - - Retrieves the contents of the STARTUPINFO structure that was specified - when the calling process was created. - - https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getstartupinfow - - """ - ret_ad, args = jitter.func_args_stdcall(["ptr"]) - jitter.vm.set_mem(args.ptr, startupinfo().pack()) - jitter.func_ret_stdcall(ret_ad, args.ptr) - - -def kernel32_GetStartupInfoA(jitter): - kernel32_GetStartupInfo(jitter, whoami(), lambda addr,value: set_win_str_a(jitter, addr, value)) - - -def kernel32_GetStartupInfoW(jitter): - kernel32_GetStartupInfo(jitter, whoami(), lambda addr,value: set_win_str_w(jitter, addr, value)) - - -def kernel32_GetCurrentThreadId(jitter): - ret_ad, _ = jitter.func_args_stdcall(0) - jitter.func_ret_stdcall(ret_ad, 0x113377) - - -def kernel32_InitializeCriticalSection(jitter): - ret_ad, _ = jitter.func_args_stdcall(["lpcritic"]) - jitter.func_ret_stdcall(ret_ad, 0) - - -def user32_GetSystemMetrics(jitter): - ret_ad, args = jitter.func_args_stdcall(["nindex"]) - - ret = 0 - if args.nindex in [0x2a, 0x4a]: - ret = 0 - else: - raise ValueError('unimpl index') - jitter.func_ret_stdcall(ret_ad, ret) - - -def wsock32_WSAStartup(jitter): - ret_ad, args = jitter.func_args_stdcall(["version", "pwsadata"]) - jitter.vm.set_mem(args.pwsadata, b"\x01\x01\x02\x02WinSock 2.0\x00") - jitter.func_ret_stdcall(ret_ad, 0) - - -def get_current_filetime(): - """ - Get current filetime - https://msdn.microsoft.com/en-us/library/ms724228 - """ - curtime = winobjs.current_datetime - unixtime = int(time.mktime(curtime.timetuple())) - filetime = (int(unixtime * 1000000 + curtime.microsecond) * 10 + - DATE_1601_TO_1970) - return filetime - - -def unixtime_to_filetime(unixtime): - """ - Convert unixtime to filetime - https://msdn.microsoft.com/en-us/library/ms724228 - """ - return (unixtime * 10000000) + DATE_1601_TO_1970 - - -def filetime_to_unixtime(filetime): - """ - Convert filetime to unixtime - # https://msdn.microsoft.com/en-us/library/ms724228 - """ - return int((filetime - DATE_1601_TO_1970) // 10000000) - - -def datetime_to_systemtime(curtime): - - s = struct.pack('HHHHHHHH', - curtime.year, # year - curtime.month, # month - curtime.weekday(), # dayofweek - curtime.day, # day - curtime.hour, # hour - curtime.minute , # minutes - curtime.second, # seconds - int(curtime.microsecond // 1000), # millisec - ) - return s - - -def kernel32_GetSystemTimeAsFileTime(jitter): - ret_ad, args = jitter.func_args_stdcall(["lpSystemTimeAsFileTime"]) - - current_filetime = get_current_filetime() - filetime = struct.pack('II', - current_filetime & 0xffffffff, - (current_filetime>>32) & 0xffffffff) - - jitter.vm.set_mem(args.lpSystemTimeAsFileTime, filetime) - jitter.func_ret_stdcall(ret_ad, 0) - - -def kernel32_GetLocalTime(jitter): - ret_ad, args = jitter.func_args_stdcall(["lpsystemtime"]) - systemtime = datetime_to_systemtime(winobjs.current_datetime) - jitter.vm.set_mem(args.lpsystemtime, systemtime) - jitter.func_ret_stdcall(ret_ad, args.lpsystemtime) - - -def kernel32_GetSystemTime(jitter): - ret_ad, args = jitter.func_args_stdcall(["lpsystemtime"]) - systemtime = datetime_to_systemtime(winobjs.current_datetime) - jitter.vm.set_mem(args.lpsystemtime, systemtime) - jitter.func_ret_stdcall(ret_ad, args.lpsystemtime) - - -def kernel32_CreateFileMapping(jitter, funcname, get_str): - ret_ad, args = jitter.func_args_stdcall(["hfile", "lpattr", "flprotect", - "dwmaximumsizehigh", - "dwmaximumsizelow", "lpname"]) - - if args.hfile == 0xffffffff: - # Create null mapping - if args.dwmaximumsizehigh: - raise NotImplementedError("Untested case") - hmap = StringIO("\x00" * args.dwmaximumsizelow) - hmap_handle = winobjs.handle_pool.add('filemem', hmap) - - ret = winobjs.handle_pool.add('filemapping', hmap_handle) - else: - if not args.hfile in winobjs.handle_pool: - raise ValueError('unknown handle') - ret = winobjs.handle_pool.add('filemapping', args.hfile) - jitter.func_ret_stdcall(ret_ad, ret) - - -def kernel32_CreateFileMappingA(jitter): - kernel32_CreateFileMapping(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr)) - - -def kernel32_CreateFileMappingW(jitter): - kernel32_CreateFileMapping(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr)) - - -def kernel32_MapViewOfFile(jitter): - ret_ad, args = jitter.func_args_stdcall(["hfile", "flprotect", - "dwfileoffsethigh", - "dwfileoffsetlow", - "length"]) - - if not args.hfile in winobjs.handle_pool: - raise ValueError('unknown handle') - hmap = winobjs.handle_pool[args.hfile] - if not hmap.info in winobjs.handle_pool: - raise ValueError('unknown file handle') - - hfile_o = winobjs.handle_pool[hmap.info] - fd = hfile_o.info - fd.seek((args.dwfileoffsethigh << 32) | args.dwfileoffsetlow) - data = fd.read(args.length) if args.length else fd.read() - length = len(data) - - log.debug('MapViewOfFile len: %x', len(data)) - - if not args.flprotect in ACCESS_DICT: - raise ValueError('unknown access dw!') - - alloc_addr = winobjs.heap.alloc(jitter, len(data)) - jitter.vm.set_mem(alloc_addr, data) - - winobjs.handle_mapped[alloc_addr] = (hfile_o, args.dwfileoffsethigh, - args.dwfileoffsetlow, length) - - jitter.func_ret_stdcall(ret_ad, alloc_addr) - - -def kernel32_UnmapViewOfFile(jitter): - ret_ad, args = jitter.func_args_stdcall(['ad']) - - if not args.ad in winobjs.handle_mapped: - raise NotImplementedError("Untested case") - """ - hfile_o, dwfileoffsethigh, dwfileoffsetlow, length = winobjs.handle_mapped[ad] - off = (dwfileoffsethigh<<32) | dwfileoffsetlow - s = jitter.vm.get_mem(ad, length) - hfile_o.info.seek(off) - hfile_o.info.write(s) - hfile_o.info.close() - """ - jitter.func_ret_stdcall(ret_ad, 1) - - -def kernel32_GetDriveType(jitter, funcname, get_str): - ret_ad, args = jitter.func_args_stdcall(['pathname']) - - p = get_str(args.pathname) - p = p.upper() - - log.debug('Drive: %r', p) - - ret = 0 - if p[0] == "C": - ret = 3 - - jitter.func_ret_stdcall(ret_ad, ret) - - -def kernel32_GetDriveTypeA(jitter): - kernel32_GetDriveType(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr)) - - -def kernel32_GetDriveTypeW(jitter): - kernel32_GetDriveType(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr)) - - -def kernel32_GetDiskFreeSpace(jitter, funcname, get_str): - ret_ad, args = jitter.func_args_stdcall(["lprootpathname", - "lpsectorpercluster", - "lpbytespersector", - "lpnumberoffreeclusters", - "lptotalnumberofclusters"]) - jitter.vm.set_u32(args.lpsectorpercluster, 8) - jitter.vm.set_u32(args.lpbytespersector, 0x200) - jitter.vm.set_u32(args.lpnumberoffreeclusters, 0x222222) - jitter.vm.set_u32(args.lptotalnumberofclusters, 0x333333) - jitter.func_ret_stdcall(ret_ad, 1) - - -def kernel32_GetDiskFreeSpaceA(jitter): - kernel32_GetDiskFreeSpace(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr)) - - -def kernel32_GetDiskFreeSpaceW(jitter): - kernel32_GetDiskFreeSpace(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr)) - - -def kernel32_VirtualQuery(jitter): - ret_ad, args = jitter.func_args_stdcall(["ad", "lpbuffer", "dwl"]) - - all_mem = jitter.vm.get_all_memory() - found = None - for basead, m in viewitems(all_mem): - if basead <= args.ad < basead + m['size']: - found = args.ad, m - break - if not found: - raise ValueError('cannot find mem', hex(args.ad)) - - if args.dwl != 0x1c: - raise ValueError('strange mem len', hex(args.dwl)) - s = struct.pack('IIIIIII', - args.ad, - basead, - ACCESS_DICT_INV[m['access']], - m['size'], - 0x1000, - ACCESS_DICT_INV[m['access']], - 0x01000000) - jitter.vm.set_mem(args.lpbuffer, s) - jitter.func_ret_stdcall(ret_ad, args.dwl) - - -def kernel32_GetProcessAffinityMask(jitter): - ret_ad, args = jitter.func_args_stdcall(["hprocess", - "procaffmask", - "systemaffmask"]) - jitter.vm.set_u32(args.procaffmask, 1) - jitter.vm.set_u32(args.systemaffmask, 1) - jitter.func_ret_stdcall(ret_ad, 1) - - -def msvcrt_rand(jitter): - ret_ad, _ = jitter.func_args_cdecl(0) - jitter.func_ret_stdcall(ret_ad, 0x666) - -def msvcrt_srand(jitter): - ret_ad, _ = jitter.func_args_cdecl(['seed']) - jitter.func_ret_stdcall(ret_ad, 0) - -def msvcrt_wcslen(jitter): - ret_ad, args = jitter.func_args_cdecl(["pwstr"]) - s = get_win_str_w(jitter, args.pwstr) - jitter.func_ret_cdecl(ret_ad, len(s)) - -def kernel32_SetFilePointer(jitter): - ret_ad, args = jitter.func_args_stdcall(["hwnd", "dinstance", - "p_dinstance_high", - "movemethod"]) - - if args.hwnd == winobjs.module_cur_hwnd: - pass - elif args.hwnd in winobjs.handle_pool: - pass - else: - raise ValueError('unknown hwnd!') - - # data = None - if args.hwnd in winobjs.files_hwnd: - winobjs.files_hwnd[winobjs.module_cur_hwnd].seek(args.dinstance, args.movemethod) - elif args.hwnd in winobjs.handle_pool: - wh = winobjs.handle_pool[args.hwnd] - wh.info.seek(args.dinstance, args.movemethod) - else: - raise ValueError('unknown filename') - jitter.func_ret_stdcall(ret_ad, args.dinstance) - - -def kernel32_SetFilePointerEx(jitter): - ret_ad, args = jitter.func_args_stdcall(["hwnd", "dinstance_l", - "dinstance_h", - "pnewfileptr", - "movemethod"]) - dinstance = args.dinstance_l | (args.dinstance_h << 32) - if dinstance: - raise ValueError('Not implemented') - if args.pnewfileptr: - raise ValueError('Not implemented') - if args.hwnd == winobjs.module_cur_hwnd: - pass - elif args.hwnd in winobjs.handle_pool: - pass - else: - raise ValueError('unknown hwnd!') - - # data = None - if args.hwnd in winobjs.files_hwnd: - winobjs.files_hwnd[winobjs.module_cur_hwnd].seek(dinstance, args.movemethod) - elif args.hwnd in winobjs.handle_pool: - wh = winobjs.handle_pool[args.hwnd] - wh.info.seek(dinstance, args.movemethod) - else: - raise ValueError('unknown filename') - jitter.func_ret_stdcall(ret_ad, 1) - - -def kernel32_SetEndOfFile(jitter): - ret_ad, args = jitter.func_args_stdcall(['hwnd']) - if args.hwnd in winobjs.handle_pool: - wh = winobjs.handle_pool[args.hwnd] - wh.info.seek(0, 2) - else: - raise ValueError('unknown filename') - jitter.func_ret_stdcall(ret_ad, 1) - - -def kernel32_FlushFileBuffers(jitter): - ret_ad, args = jitter.func_args_stdcall(['hwnd']) - if args.hwnd in winobjs.handle_pool: - pass - else: - raise ValueError('unknown filename') - jitter.func_ret_stdcall(ret_ad, 1) - - -def kernel32_WriteFile(jitter): - ret_ad, args = jitter.func_args_stdcall(["hwnd", "lpbuffer", - "nnumberofbytestowrite", - "lpnumberofbyteswrite", - "lpoverlapped"]) - data = jitter.vm.get_mem(args.lpbuffer, args.nnumberofbytestowrite) - - if args.hwnd == winobjs.module_cur_hwnd: - pass - elif args.hwnd in winobjs.handle_pool: - pass - else: - raise ValueError('unknown hwnd!') - - if args.hwnd in winobjs.files_hwnd: - winobjs.files_hwnd[winobjs.module_cur_hwnd].write(data) - elif args.hwnd in winobjs.handle_pool: - wh = winobjs.handle_pool[args.hwnd] - wh.info.write(data) - else: - raise ValueError('unknown filename') - - if (args.lpnumberofbyteswrite): - jitter.vm.set_u32(args.lpnumberofbyteswrite, len(data)) - - jitter.func_ret_stdcall(ret_ad, 1) - - -def user32_IsCharUpperA(jitter): - ret_ad, args = jitter.func_args_stdcall(["c"]) - ret = 0 if args.c & 0x20 else 1 - jitter.func_ret_stdcall(ret_ad, ret) - - -def user32_IsCharLowerA(jitter): - ret_ad, args = jitter.func_args_stdcall(["c"]) - ret = 1 if args.c & 0x20 else 0 - jitter.func_ret_stdcall(ret_ad, ret) - - -def kernel32_GetSystemDefaultLangID(jitter): - ret_ad, _ = jitter.func_args_stdcall(0) - jitter.func_ret_stdcall(ret_ad, 0x409) # encglish - - -def msvcrt_malloc(jitter): - ret_ad, args = jitter.func_args_cdecl(["msize"]) - addr = winobjs.heap.alloc(jitter, args.msize) - jitter.func_ret_cdecl(ret_ad, addr) - - -def msvcrt_free(jitter): - ret_ad, _ = jitter.func_args_cdecl(["ptr"]) - jitter.func_ret_cdecl(ret_ad, 0) - - -def msvcrt_fseek(jitter): - ret_ad, args = jitter.func_args_cdecl(['stream', 'offset', 'orig']) - fd = jitter.vm.get_u32(args.stream + 0x10) - - if not fd in winobjs.handle_pool: - raise NotImplementedError("Untested case") - o = winobjs.handle_pool[fd] - o.info.seek(args.offset, args.orig) - jitter.func_ret_cdecl(ret_ad, 0) - - -def msvcrt_ftell(jitter): - ret_ad, args = jitter.func_args_cdecl(["stream"]) - fd = jitter.vm.get_u32(args.stream + 0x10) - - if not fd in winobjs.handle_pool: - raise NotImplementedError("Untested case") - o = winobjs.handle_pool[fd] - off = o.info.tell() - jitter.func_ret_cdecl(ret_ad, off) - - -def msvcrt_rewind(jitter): - ret_ad, args = jitter.func_args_cdecl(["stream"]) - fd = jitter.vm.get_u32(args.stream + 0x10) - if not fd in winobjs.handle_pool: - raise NotImplementedError("Untested case") - o = winobjs.handle_pool[fd] - # off = o.info.seek(0, 0) - jitter.func_ret_cdecl(ret_ad, 0) - - -def msvcrt_fread(jitter): - ret_ad, args = jitter.func_args_cdecl(["buf", "size", "nmemb", "stream"]) - fd = jitter.vm.get_u32(args.stream + 0x10) - if not fd in winobjs.handle_pool: - raise NotImplementedError("Untested case") - - data = winobjs.handle_pool[fd].info.read(args.size * args.nmemb) - jitter.vm.set_mem(args.buf, data) - jitter.func_ret_cdecl(ret_ad, args.nmemb) - - -def msvcrt_fwrite(jitter): - ret_ad, args = jitter.func_args_cdecl(["buf", "size", "nmemb", "stream"]) - fd = jitter.vm.get_u32(args.stream + 0x10) - if not fd in winobjs.handle_pool: - raise NotImplementedError("Unknown file handle!") - - data = jitter.vm.get_mem(args.buf, args.size*args.nmemb) - winobjs.handle_pool[fd].info.write(data) - jitter.func_ret_cdecl(ret_ad, args.nmemb) - - -def msvcrt_fclose(jitter): - ret_ad, args = jitter.func_args_cdecl(['stream']) - fd = jitter.vm.get_u32(args.stream + 0x10) - - if not fd in winobjs.handle_pool: - raise NotImplementedError("Untested case") - o = winobjs.handle_pool[fd] - # off = o.info.close() - jitter.func_ret_cdecl(ret_ad, 0) - - -def msvcrt_atexit(jitter): - ret_ad, _ = jitter.func_args_cdecl(["func"]) - jitter.func_ret_cdecl(ret_ad, 0) - - -def user32_MessageBoxA(jitter): - ret_ad, args = jitter.func_args_stdcall(["hwnd", "lptext", - "lpcaption", "utype"]) - - text = get_win_str_a(jitter, args.lptext) - caption = get_win_str_a(jitter, args.lpcaption) - - log.info('Caption: %r Text: %r', caption, text) - - jitter.func_ret_stdcall(ret_ad, 0) - - -def kernel32_myGetTempPath(jitter, set_str): - ret_ad, args = jitter.func_args_stdcall(["l", "buf"]) - l = 'c:\\temp\\' - if len(l) < args.l: - set_str(args.buf, l) - jitter.func_ret_stdcall(ret_ad, len(l)) - - -def kernel32_GetTempPathA(jitter): - kernel32_myGetTempPath(jitter, lambda addr,value: set_win_str_a(jitter, addr, value)) - - -def kernel32_GetTempPathW(jitter): - kernel32_myGetTempPath(jitter, lambda addr,value: set_win_str_w(jitter, addr, value)) - - -temp_num = 0 - - -def kernel32_GetTempFileNameA(jitter): - global temp_num - ret_ad, args = jitter.func_args_stdcall(["path", "ext", "unique", "buf"]) - - temp_num += 1 - ext = get_win_str_a(jitter, args.ext) if args.ext else 'tmp' - path = get_win_str_a(jitter, args.path) if args.path else "xxx" - fname = path + "\\" + "temp%.4d" % temp_num + "." + ext - jitter.vm.set_mem(args.buf, fname.encode('utf-8')) - - jitter.func_ret_stdcall(ret_ad, 0) - - -class win32_find_data(object): - fileattrib = 0 - creationtime = 0 - lastaccesstime = 0 - lastwritetime = 0 - filesizehigh = 0 - filesizelow = 0 - dwreserved0 = 0 - dwreserved1 = 0x1337beef - cfilename = "" - alternamefilename = "" - - def __init__(self, **kargs): - for k, v in viewitems(kargs): - setattr(self, k, v) - - def toStruct(self, encode_str=encode_win_str_w): - s = struct.pack('=IQQQIIII', - self.fileattrib, - self.creationtime, - self.lastaccesstime, - self.lastwritetime, - self.filesizehigh, - self.filesizelow, - self.dwreserved0, - self.dwreserved1) - fname = encode_str(self.cfilename) + b'\x00' * MAX_PATH - fname = fname[:MAX_PATH] - s += fname - fname = encode_str(self.alternamefilename) + b'\x00' * 14 - fname = fname[:14] - s += fname - return s - - -class find_data_mngr(object): - - def __init__(self): - self.patterns = {} - self.flist = [] - # handle number -> (flist index, current index in list) - self.handles = {} - - def add_list(self, pattern, flist): - index = len(self.flist) - self.flist.append(flist) - - self.patterns[pattern] = index - - def findfirst(self, pattern): - assert(pattern in self.patterns) - findex = self.patterns[pattern] - h = len(self.handles) + 1 - self.handles[h] = [findex, 0] - return h - - def findnext(self, h): - assert(h in self.handles) - findex, index = self.handles[h] - if index >= len(self.flist[findex]): - return None - fname = self.flist[findex][index] - self.handles[h][1] += 1 - - return fname - -def my_FindFirstFile(jitter, pfilepattern, pfindfiledata, get_win_str, encode_str): - filepattern = get_win_str(jitter, pfilepattern) - h = winobjs.find_data.findfirst(filepattern) - - fname = winobjs.find_data.findnext(h) - fdata = win32_find_data(cfilename=fname) - - jitter.vm.set_mem(pfindfiledata, fdata.toStruct(encode_str=encode_str)) - return h - -def kernel32_FindFirstFileA(jitter): - ret_ad, args = jitter.func_args_stdcall(["pfilepattern", "pfindfiledata"]) - h = my_FindFirstFile(jitter, args.pfilepattern, args.pfindfiledata, - get_win_str_a, encode_win_str_a) - jitter.func_ret_stdcall(ret_ad, h) - -def kernel32_FindFirstFileW(jitter): - ret_ad, args = jitter.func_args_stdcall(["pfilepattern", "pfindfiledata"]) - h = my_FindFirstFile(jitter, args.pfilepattern, args.pfindfiledata, - get_win_str_w, encode_win_str_w) - jitter.func_ret_stdcall(ret_ad, h) - -def kernel32_FindFirstFileExA(jitter): - ret_ad, args = jitter.func_args_stdcall([ - "lpFileName", - "fInfoLevelId", - "lpFindFileData", - "fSearchOp", - "lpSearchFilter", - "dwAdditionalFlags"]) - h = my_FindFirstFile(jitter, args.lpFileName, args.lpFindFileData, - get_win_str_a, encode_win_str_a) - jitter.func_ret_stdcall(ret_ad, h) - -def kernel32_FindFirstFileExW(jitter): - ret_ad, args = jitter.func_args_stdcall([ - "lpFileName", - "fInfoLevelId", - "lpFindFileData", - "fSearchOp", - "lpSearchFilter", - "dwAdditionalFlags"]) - h = my_FindFirstFile(jitter, args.lpFileName, args.lpFindFileData, - get_win_str_w, encode_win_str_w) - jitter.func_ret_stdcall(ret_ad, h) - -def my_FindNextFile(jitter, encode_str): - ret_ad, args = jitter.func_args_stdcall(["handle", "pfindfiledata"]) - fname = winobjs.find_data.findnext(args.handle) - if fname is None: - winobjs.lastwin32error = 0x12 # ERROR_NO_MORE_FILES - ret = 0 - else: - ret = 1 - fdata = win32_find_data(cfilename=fname) - jitter.vm.set_mem(args.pfindfiledata, fdata.toStruct(encode_str=encode_str)) - jitter.func_ret_stdcall(ret_ad, ret) - -kernel32_FindNextFileA = lambda jitter: my_FindNextFile(jitter, encode_win_str_a) -kernel32_FindNextFileW = lambda jitter: my_FindNextFile(jitter, encode_win_str_w) - -def kernel32_GetNativeSystemInfo(jitter): - ret_ad, args = jitter.func_args_stdcall(["sys_ptr"]) - sysinfo = systeminfo() - jitter.vm.set_mem(args.sys_ptr, sysinfo.pack()) - jitter.func_ret_stdcall(ret_ad, 0) - - -def raw2guid(r): - o = struct.unpack('IHHHBBBBBB', r) - return '{%.8X-%.4X-%.4X-%.4X-%.2X%.2X%.2X%.2X%.2X%.2X}' % o - - -digs = string.digits + string.ascii_lowercase - - -def int2base(x, base): - if x < 0: - sign = -1 - elif x == 0: - return '0' - else: - sign = 1 - x *= sign - digits = [] - while x: - digits.append(digs[x % base]) - x /= base - if sign < 0: - digits.append('-') - digits.reverse() - return ''.join(digits) - - -def msvcrt__ultow(jitter): - ret_ad, args = jitter.func_args_cdecl(["value", "p", "radix"]) - - value = args.value & 0xFFFFFFFF - if not args.radix in [10, 16, 20]: - raise ValueError("Not tested") - s = int2base(value, args.radix) - set_win_str_w(jitter, args.p, s) - jitter.func_ret_cdecl(ret_ad, args.p) - - -def msvcrt_myfopen(jitter, get_str): - ret_ad, args = jitter.func_args_cdecl(["pfname", "pmode"]) - - fname = get_str(args.pfname) - rw = get_str(args.pmode) - log.info("fopen %r, %r", fname, rw) - - if rw in ['r', 'rb', 'wb+','wb','wt']: - sb_fname = windows_to_sbpath(fname) - h = open(sb_fname, rw) - eax = winobjs.handle_pool.add(sb_fname, h) - dwsize = 0x20 - alloc_addr = winobjs.heap.alloc(jitter, dwsize) - pp = pck32(0x11112222) + pck32(0) + pck32(0) + pck32(0) + pck32(eax) - jitter.vm.set_mem(alloc_addr, pp) - - else: - raise ValueError('unknown access mode %s' % rw) - - jitter.func_ret_cdecl(ret_ad, alloc_addr) - - -def msvcrt__wfopen(jitter): - msvcrt_myfopen(jitter, lambda addr:get_win_str_w(jitter, addr)) - - -def msvcrt_fopen(jitter): - msvcrt_myfopen(jitter, lambda addr:get_win_str_a(jitter, addr)) - - -def msvcrt_strlen(jitter): - ret_ad, args = jitter.func_args_cdecl(["src"]) - - s = get_win_str_a(jitter, args.src) - jitter.func_ret_cdecl(ret_ad, len(s)) - - -def kernel32_QueryPerformanceCounter(jitter): - ret_ad, args = jitter.func_args_stdcall(["lpPerformanceCount"]) - jitter.vm.set_mem(args.lpPerformanceCount, struct.pack('<Q', 0x1)) - jitter.func_ret_stdcall(ret_ad, 1) - - -def kernel32_InitializeCriticalSectionEx(jitter): - ''' - LPCRITICAL_SECTION lpCriticalSection, - DWORD dwSpinCount, - DWORD Flags - ''' - ret_ad, args = jitter.func_args_stdcall(["lpCriticalSection", "dwSpinCount", "Flags"]) - jitter.func_ret_stdcall(ret_ad, 1) - - -def kernel32_EnterCriticalSection(jitter): - ''' - void EnterCriticalSection( - LPCRITICAL_SECTION lpCriticalSection - ); - ''' - ret_ad, args = jitter.func_args_stdcall(["lpCriticalSection"]) - jitter.func_ret_stdcall(ret_ad, 0x0) - - -def kernel32_LeaveCriticalSection(jitter): - ''' - void LeaveCriticalSection( - LPCRITICAL_SECTION lpCriticalSection - ); - ''' - ret_ad, args = jitter.func_args_stdcall(["lpCriticalSection"]) - jitter.func_ret_stdcall(ret_ad, 0x0) - - -class FLS(object): - def __init__(self): - self.slots = [] - - def kernel32_FlsAlloc(self, jitter): - ''' - DWORD FlsAlloc( - PFLS_CALLBACK_FUNCTION lpCallback - ); - ''' - ret_ad, args = jitter.func_args_stdcall(["lpCallback"]) - index = len(self.slots) - self.slots.append(0x0) - jitter.func_ret_stdcall(ret_ad, index) - - def kernel32_FlsSetValue(self, jitter): - ''' - BOOL FlsSetValue( - DWORD dwFlsIndex, - PVOID lpFlsData - ); - ''' - ret_ad, args = jitter.func_args_stdcall(["dwFlsIndex", "lpFlsData"]) - self.slots[args.dwFlsIndex] = args.lpFlsData - jitter.func_ret_stdcall(ret_ad, 1) - - def kernel32_FlsGetValue(self, jitter): - ''' - PVOID FlsGetValue( - DWORD dwFlsIndex - ); - ''' - ret_ad, args = jitter.func_args_stdcall(["dwFlsIndex"]) - jitter.func_ret_stdcall(ret_ad, self.slots[args.dwFlsIndex]) - -fls = FLS() - - -def kernel32_GetProcessHeap(jitter): - ''' - HANDLE GetProcessHeap(); - ''' - ret_ad, args = jitter.func_args_stdcall([]) - hHeap = 0x67676767 - jitter.func_ret_stdcall(ret_ad, hHeap) - - -STD_INPUT_HANDLE = 0xfffffff6 -STD_OUTPUT_HANDLE = 0xfffffff5 -STD_ERROR_HANDLE = 0xfffffff4 - - -def kernel32_GetStdHandle(jitter): - ''' - HANDLE WINAPI GetStdHandle( - _In_ DWORD nStdHandle - ); - - STD_INPUT_HANDLE (DWORD)-10 - The standard input device. Initially, this is the console input buffer, CONIN$. - - STD_OUTPUT_HANDLE (DWORD)-11 - The standard output device. Initially, this is the active console screen buffer, CONOUT$. - - STD_ERROR_HANDLE (DWORD)-12 - The standard error device. Initially, this is the active console screen buffer, CONOUT$. - ''' - ret_ad, args = jitter.func_args_stdcall(["nStdHandle"]) - jitter.func_ret_stdcall(ret_ad, { - STD_OUTPUT_HANDLE: 1, - STD_ERROR_HANDLE: 2, - STD_INPUT_HANDLE: 3, - }[args.nStdHandle]) - - -FILE_TYPE_UNKNOWN = 0x0000 -FILE_TYPE_CHAR = 0x0002 - - -def kernel32_GetFileType(jitter): - ''' - DWORD GetFileType( - HANDLE hFile - ); - ''' - ret_ad, args = jitter.func_args_stdcall(["hFile"]) - jitter.func_ret_stdcall(ret_ad, { - # STD_OUTPUT_HANDLE - 1: FILE_TYPE_CHAR, - # STD_ERROR_HANDLE - 2: FILE_TYPE_CHAR, - # STD_INPUT_HANDLE - 3: FILE_TYPE_CHAR, - }.get(args.hFile, FILE_TYPE_UNKNOWN)) - - -def kernel32_IsProcessorFeaturePresent(jitter): - ''' - BOOL IsProcessorFeaturePresent( - DWORD ProcessorFeature - ); - ''' - ret_ad, args = jitter.func_args_stdcall(["ProcessorFeature"]) - jitter.func_ret_stdcall(ret_ad, { - # PF_ARM_64BIT_LOADSTORE_ATOMIC - 25: False, - # PF_ARM_DIVIDE_INSTRUCTION_AVAILABLE - 24: False, - # PF_ARM_EXTERNAL_CACHE_AVAILABLE - 26: False, - # PF_ARM_FMAC_INSTRUCTIONS_AVAILABLE - 27: False, - # PF_ARM_VFP_32_REGISTERS_AVAILABLE - 18: False, - # PF_3DNOW_INSTRUCTIONS_AVAILABLE - 7: False, - # PF_CHANNELS_ENABLED - 16: True, - # PF_COMPARE_EXCHANGE_DOUBLE - 2: False, - # PF_COMPARE_EXCHANGE128 - 14: False, - # PF_COMPARE64_EXCHANGE128 - 15: False, - # PF_FASTFAIL_AVAILABLE - 23: False, - # PF_FLOATING_POINT_EMULATED - 1: False, - # PF_FLOATING_POINT_PRECISION_ERRATA - 0: True, - # PF_MMX_INSTRUCTIONS_AVAILABLE - 3: True, - # PF_NX_ENABLED - 12: True, - # PF_PAE_ENABLED - 9: True, - # PF_RDTSC_INSTRUCTION_AVAILABLE - 8: True, - # PF_RDWRFSGSBASE_AVAILABLE - 22: True, - # PF_SECOND_LEVEL_ADDRESS_TRANSLATION - 20: True, - # PF_SSE3_INSTRUCTIONS_AVAILABLE - 13: True, - # PF_VIRT_FIRMWARE_ENABLED - 21: False, - # PF_XMMI_INSTRUCTIONS_AVAILABLE - 6: True, - # PF_XMMI64_INSTRUCTIONS_AVAILABLE - 10: True, - # PF_XSAVE_ENABLED - 17: False, - }[args.ProcessorFeature]) - - -def kernel32_GetACP(jitter): - ''' - UINT GetACP(); - ''' - ret_ad, args = jitter.func_args_stdcall([]) - # Windows-1252: Latin 1 / Western European Superset of ISO-8859-1 (without C1 controls). - jitter.func_ret_stdcall(ret_ad, 1252) - - -# ref: https://docs.microsoft.com/en-us/windows/win32/intl/code-page-identifiers -VALID_CODE_PAGES = { - 37,437,500,708,709,710,720,737,775,850,852,855,857,858,860,861,862,863,864,865,866,869,870,874,875, - 932,936,949,950,1026,1047,1140,1141,1142,1143,1144,1145,1146,1147,1148,1149,1200,1201,1250,1251,1252, - 1253,1254,1255,1256,1257,1258,1361,10000,10001,10002,10003,10004,10005,10006,10007,10008,10010,10017, - 10021,10029,10079,10081,10082,12000,12001,20000,20001,20002,20003,20004,20005,20105,20106,20107,20108, - 20127,20261,20269,20273,20277,20278,20280,20284,20285,20290,20297,20420,20423,20424,20833,20838,20866, - 20871,20880,20905,20924,20932,20936,20949,21025,21027,21866,28591,28592,28593,28594,28595,28596,28597, - 28598,28599,28603,28605,29001,38598,50220,50221,50222,50225,50227,50229,50930,50931,50933,50935,50936, - 50937,50939,51932,51936,51949,51950,52936,54936,57002,57003,57004,57005,57006,57007,57008,57009,57010, - 57011,65000,65001 -} - - -def kernel32_IsValidCodePage(jitter): - ''' - BOOL IsValidCodePage( - UINT CodePage - ); - ''' - ret_ad, args = jitter.func_args_stdcall(["CodePage"]) - jitter.func_ret_stdcall(ret_ad, args.CodePage in VALID_CODE_PAGES) - - -def kernel32_GetCPInfo(jitter): - ''' - BOOL GetCPInfo( - UINT CodePage, - LPCPINFO lpCPInfo - ); - ''' - ret_ad, args = jitter.func_args_stdcall(["CodePage", "lpCPInfo"]) - assert args.CodePage == 1252 - # ref: http://www.rensselaer.org/dept/cis/software/g77-mingw32/include/winnls.h - #define MAX_LEADBYTES 12 - #define MAX_DEFAULTCHAR 2 - jitter.vm.set_mem(args.lpCPInfo, struct.pack('<I', 0x1) + b'??' + b'\x00' * 12) - jitter.func_ret_stdcall(ret_ad, 1) - - -def kernel32_GetStringTypeW(jitter): - """ - BOOL GetStringTypeW( - DWORD dwInfoType, - _In_NLS_string_(cchSrc)LPCWCH lpSrcStr, - int cchSrc, - LPWORD lpCharType - ); - - Retrieves character type information for the characters in the specified - Unicode source string. For each character in the string, the function - sets one or more bits in the corresponding 16-bit element of the output - array. Each bit identifies a given character type, for example, letter, - digit, or neither. - - """ - # These types support ANSI C and POSIX (LC_CTYPE) character typing - # functions.A bitwise-OR of these values is retrieved in the array in the - # output buffer when dwInfoType is set to CT_CTYPE1. For DBCS locales, the - # type attributes apply to both narrow characters and wide characters. The - # Japanese hiragana and katakana characters, and the kanji ideograph - # characters all have the C1_ALPHA attribute. - CT_TYPE1 = 0x01 - # TODO handle other types of information - # (CT_TYPE2, CT_TYPE3) - # for now, they raise NotImplemented - CT_TYPE2 = 0x02 - CT_TYPE3 = 0x03 - - C1_UPPER = 0x0001 # Uppercase - C1_LOWER = 0x0002 # Lowercase - C1_DIGIT = 0x0004 # Decimal digits - C1_SPACE = 0x0008 # Space characters - C1_PUNCT = 0x0010 # Punctuation - C1_CNTRL = 0x0020 # Control characters - C1_BLANK = 0x0040 # Blank characters - C1_XDIGIT = 0x0080 # Hexadecimal digits - C1_ALPHA = 0x0100 # Any linguistic character: alphabetical, syllabary, or ideographic - C1_DEFINED = 0x0200 # A defined character, but not one of the other C1_* types - - # the following sets have been generated from the Linux python library curses - # e.g., C1_PUNCT_SET = [chr(i) for i in range(256) if curses.ascii.ispunct(chr(i))] - C1_PUNCT_SET = ['!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', - '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', - '^', '_', '`', '{', '|', '}', '~'] - C1_CNTRL_SET = ['\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', - '\x07', '\x08', '\t', '\n', '\x0b', '\x0c', '\r', '\x0e', '\x0f', - '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', - '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f', - '\x7f'] - C1_BLANK_SET = ['\t', ' '] - C1_XDIGIT_SET = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', - 'B', 'C', 'D', 'E', 'F', 'a', 'b', 'c', 'd', 'e', 'f'] - - ret, args = jitter.func_args_stdcall(['dwInfoType', 'lpSrcStr', 'cchSrc', - 'lpCharType']) - s = jitter.vm.get_mem(args.lpSrcStr, args.cchSrc).decode("utf-16") - if args.dwInfoType == CT_TYPE1: - # iterate over characters from the decoded W string - for i, c in enumerate(s): - # TODO handle non-ascii characters - if not c.isascii(): - continue - val = 0 - if c.isupper(): - val |= C1_UPPER - if c.islower(): - val |= C1_LOWER - if c.isdigit(): - val |= C1_DIGIT - if c.isspace(): - val |= C1_SPACE - if c in C1_PUNCT_SET: - val |= C1_PUNCT - if c in C1_CNTRL_SET: - val |= C1_CNTRL - if c in C1_BLANK_SET: - val |= C1_BLANK - if c in C1_XDIGIT_SET: - val |= C1_XDIGIT - if c.isalpha(): - val |= C1_ALPHA - if val == 0: - val = C1_DEFINED - jitter.vm.set_u16(args.lpCharType + i * 2, val) - elif args.dwInfoType == CT_TYPE2: - raise NotImplemented - elif args.dwInfoType == CT_TYPE3: - raise NotImplemented - else: - raise ValueError("CT_TYPE unknown: %i" % args.dwInfoType) - jitter.func_ret_stdcall(ret, 1) - return True diff --git a/miasm/os_dep/win_api_x86_32_seh.py b/miasm/os_dep/win_api_x86_32_seh.py deleted file mode 100644 index 57416477..00000000 --- a/miasm/os_dep/win_api_x86_32_seh.py +++ /dev/null @@ -1,705 +0,0 @@ -#-*- coding:utf-8 -*- - -# -# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -import logging -import os -import struct - -from future.utils import viewitems - -from miasm.loader import pe_init - -from miasm.jitter.csts import PAGE_READ, PAGE_WRITE -from miasm.core.utils import pck32 -import miasm.arch.x86.regs as x86_regs - -from miasm.os_dep.win_32_structs import LdrDataEntry, ListEntry, \ - TEB, NT_TIB, PEB, PEB_LDR_DATA, ContextException, \ - EXCEPTION_REGISTRATION_RECORD, EXCEPTION_RECORD - -# Constants Windows -EXCEPTION_BREAKPOINT = 0x80000003 -EXCEPTION_SINGLE_STEP = 0x80000004 -EXCEPTION_ACCESS_VIOLATION = 0xc0000005 -EXCEPTION_INT_DIVIDE_BY_ZERO = 0xc0000094 -EXCEPTION_PRIV_INSTRUCTION = 0xc0000096 -EXCEPTION_ILLEGAL_INSTRUCTION = 0xc000001d - - -log = logging.getLogger("seh_helper") -console_handler = logging.StreamHandler() -console_handler.setFormatter(logging.Formatter("[%(levelname)-8s]: %(message)s")) -log.addHandler(console_handler) -log.setLevel(logging.INFO) - -# fs:[0] Page (TIB) -tib_address = 0x7ff70000 -PEB_AD = 0x7ffdf000 -LDR_AD = 0x340000 -DEFAULT_SEH = 0x7ffff000 - -MAX_MODULES = 0x40 - -peb_address = PEB_AD -peb_ldr_data_offset = 0x1ea0 -peb_ldr_data_address = LDR_AD + peb_ldr_data_offset - - -modules_list_offset = 0x1f00 - -InInitializationOrderModuleList_offset = 0x1ee0 -InInitializationOrderModuleList_address = LDR_AD + \ - InInitializationOrderModuleList_offset - -InLoadOrderModuleList_offset = 0x1ee0 + \ - MAX_MODULES * 0x1000 -InLoadOrderModuleList_address = LDR_AD + \ - InLoadOrderModuleList_offset - - -process_environment_address = 0x10000 -process_parameters_address = 0x200000 - -return_from_exception = 0x6eadbeef - - -name2module = [] -main_pe = None -main_pe_name = "c:\\xxx\\toto.exe" - -MAX_SEH = 5 - - -def build_teb(jitter, teb_address): - """ - Build TEB information using following structure: - - @jitter: jitter instance - @teb_address: the TEB address - """ - - # Only allocate space for ExceptionList/ProcessEnvironmentBlock/Self - jitter.vm.add_memory_page( - teb_address, - PAGE_READ | PAGE_WRITE, - b"\x00" * NT_TIB.get_offset("StackBase"), - "TEB.NtTib.ExceptionList" - ) - jitter.vm.add_memory_page( - teb_address + NT_TIB.get_offset("Self"), - PAGE_READ | PAGE_WRITE, - b"\x00" * (NT_TIB.sizeof() - NT_TIB.get_offset("Self")), - "TEB.NtTib.Self" - ) - jitter.vm.add_memory_page( - teb_address + TEB.get_offset("ProcessEnvironmentBlock"), - PAGE_READ | PAGE_WRITE, - b"\x00" * ( - TEB.get_offset("LastErrorValue") - - TEB.get_offset("ProcessEnvironmentBlock") - ), - "TEB.ProcessEnvironmentBlock" - ) - Teb = TEB(jitter.vm, teb_address) - Teb.NtTib.ExceptionList = DEFAULT_SEH - Teb.NtTib.Self = teb_address - Teb.ProcessEnvironmentBlock = peb_address - -def build_peb(jitter, peb_address): - """ - Build PEB information using following structure: - - @jitter: jitter instance - @peb_address: the PEB address - """ - - if main_pe: - offset, length = 8, 4 - else: - offset, length = 0xC, 0 - length += 4 - - jitter.vm.add_memory_page( - peb_address + offset, - PAGE_READ | PAGE_WRITE, - b"\x00" * length, - "PEB + 0x%x" % offset - ) - - Peb = PEB(jitter.vm, peb_address) - if main_pe: - Peb.ImageBaseAddress = main_pe.NThdr.ImageBase - Peb.Ldr = peb_ldr_data_address - - -def build_ldr_data(jitter, modules_info): - """ - Build Loader information using following structure: - - +0x000 Length : Uint4B - +0x004 Initialized : UChar - +0x008 SsHandle : Ptr32 Void - +0x00c InLoadOrderModuleList : _LIST_ENTRY - +0x014 InMemoryOrderModuleList : _LIST_ENTRY - +0x01C InInitializationOrderModuleList : _LIST_ENTRY - # dummy dll base - +0x024 DllBase : Ptr32 Void - - @jitter: jitter instance - @modules_info: LoadedModules instance - - """ - # ldr offset pad - offset = 0xC - addr = LDR_AD + peb_ldr_data_offset - ldrdata = PEB_LDR_DATA(jitter.vm, addr) - - main_pe = modules_info.name2module.get(main_pe_name, None) - ntdll_pe = modules_info.name2module.get("ntdll.dll", None) - - - size = 0 - if main_pe: - size += ListEntry.sizeof() * 2 - main_addr_entry = modules_info.module2entry[main_pe] - if ntdll_pe: - size += ListEntry.sizeof() - ntdll_addr_entry = modules_info.module2entry[ntdll_pe] - - jitter.vm.add_memory_page( - addr + offset, - PAGE_READ | PAGE_WRITE, - b"\x00" * size, - "Loader struct" - ) # (ldrdata.get_size() - offset)) - - last_module = modules_info.module2entry[ - modules_info.modules[-1]] - - if main_pe: - ldrdata.InLoadOrderModuleList.flink = main_addr_entry - ldrdata.InLoadOrderModuleList.blink = last_module - - - ldrdata.InMemoryOrderModuleList.flink = main_addr_entry + \ - LdrDataEntry.get_type().get_offset("InMemoryOrderLinks") - ldrdata.InMemoryOrderModuleList.blink = last_module + \ - LdrDataEntry.get_type().get_offset("InMemoryOrderLinks") - if ntdll_pe: - ldrdata.InInitializationOrderModuleList.flink = ntdll_addr_entry + \ - LdrDataEntry.get_type().get_offset("InInitializationOrderLinks") - ldrdata.InInitializationOrderModuleList.blink = last_module + \ - LdrDataEntry.get_type().get_offset("InInitializationOrderLinks") - - # Add dummy dll base - jitter.vm.add_memory_page(peb_ldr_data_address + 0x24, - PAGE_READ | PAGE_WRITE, pck32(0), - "Loader struct dummy dllbase") - - -class LoadedModules(object): - - """Class representing modules in memory""" - - def __init__(self): - self.modules = [] - self.name2module = {} - self.module2entry = {} - self.module2name = {} - - def add(self, name, module, module_entry): - """Track a new module - @name: module name (with extension) - @module: module object - @module_entry: address of the module entry - """ - - self.modules.append(module) - self.name2module[name] = module - self.module2entry[module] = module_entry - self.module2name[module] = name - - def __repr__(self): - return "\n".join(str(x) for x in viewitems(self.name2module)) - - -def create_modules_chain(jitter, name2module): - """ - Create the modules entries. Those modules are not linked in this function. - - @jitter: jitter instance - @name2module: dict containing association between name and its pe instance - """ - - modules_info = LoadedModules() - base_addr = LDR_AD + modules_list_offset # XXXX - offset_name = 0x500 - offset_path = 0x600 - - out = "" - for i, (fname, pe_obj) in enumerate(viewitems(name2module), 1): - if pe_obj is None: - log.warning("Unknown module: omitted from link list (%r)", - fname) - continue - addr = base_addr + i * 0x1000 - bpath = fname.replace('/', '\\') - bname_str = os.path.split(fname)[1].lower() - bname_unicode = bname_str.encode("utf-16le") - log.info("Add module %x %r", pe_obj.NThdr.ImageBase, bname_str) - - modules_info.add(bname_str, pe_obj, addr) - - # Allocate a partial LdrDataEntry (0-Flags) - jitter.vm.add_memory_page( - addr, - PAGE_READ | PAGE_WRITE, - b"\x00" * LdrDataEntry.get_offset("Flags"), - "Module info %r" % bname_str - ) - - LdrEntry = LdrDataEntry(jitter.vm, addr) - - LdrEntry.DllBase = pe_obj.NThdr.ImageBase - LdrEntry.EntryPoint = pe_obj.Opthdr.AddressOfEntryPoint - LdrEntry.SizeOfImage = pe_obj.NThdr.sizeofimage - LdrEntry.FullDllName.length = len(bname_unicode) - LdrEntry.FullDllName.maxlength = len(bname_unicode) + 2 - LdrEntry.FullDllName.data = addr + offset_path - LdrEntry.BaseDllName.length = len(bname_unicode) - LdrEntry.BaseDllName.maxlength = len(bname_unicode) + 2 - LdrEntry.BaseDllName.data = addr + offset_name - - jitter.vm.add_memory_page( - addr + offset_name, - PAGE_READ | PAGE_WRITE, - bname_unicode + b"\x00" * 2, - "Module name %r" % bname_str - ) - - if isinstance(bpath, bytes): - bpath = bpath.decode('utf8') - bpath_unicode = bpath.encode('utf-16le') - jitter.vm.add_memory_page( - addr + offset_path, - PAGE_READ | PAGE_WRITE, - bpath_unicode + b"\x00" * 2, - "Module path %r" % bname_str - ) - - return modules_info - - -def set_link_list_entry(jitter, loaded_modules, modules_info, offset): - for i, module in enumerate(loaded_modules): - cur_module_entry = modules_info.module2entry[module] - prev_module = loaded_modules[(i - 1) % len(loaded_modules)] - next_module = loaded_modules[(i + 1) % len(loaded_modules)] - prev_module_entry = modules_info.module2entry[prev_module] - next_module_entry = modules_info.module2entry[next_module] - if i == 0: - prev_module_entry = peb_ldr_data_address + 0xC - if i == len(loaded_modules) - 1: - next_module_entry = peb_ldr_data_address + 0xC - - list_entry = ListEntry(jitter.vm, cur_module_entry + offset) - list_entry.flink = next_module_entry + offset - list_entry.blink = prev_module_entry + offset - - - -def fix_InLoadOrderModuleList(jitter, modules_info): - """Fix InLoadOrderModuleList double link list. First module is the main pe, - then ntdll, kernel32. - - @jitter: the jitter instance - @modules_info: the LoadedModules instance - """ - - log.debug("Fix InLoadOrderModuleList") - main_pe = modules_info.name2module.get(main_pe_name, None) - kernel32_pe = modules_info.name2module.get("kernel32.dll", None) - ntdll_pe = modules_info.name2module.get("ntdll.dll", None) - special_modules = [main_pe, kernel32_pe, ntdll_pe] - if not all(special_modules): - log.warn( - 'No main pe, ldr data will be unconsistant %r', special_modules) - loaded_modules = modules_info.modules - else: - loaded_modules = [module for module in modules_info.modules - if module not in special_modules] - loaded_modules[0:0] = [main_pe] - loaded_modules[1:1] = [ntdll_pe] - loaded_modules[2:2] = [kernel32_pe] - - set_link_list_entry(jitter, loaded_modules, modules_info, 0x0) - - -def fix_InMemoryOrderModuleList(jitter, modules_info): - """Fix InMemoryOrderLinks double link list. First module is the main pe, - then ntdll, kernel32. - - @jitter: the jitter instance - @modules_info: the LoadedModules instance - """ - - log.debug("Fix InMemoryOrderModuleList") - main_pe = modules_info.name2module.get(main_pe_name, None) - kernel32_pe = modules_info.name2module.get("kernel32.dll", None) - ntdll_pe = modules_info.name2module.get("ntdll.dll", None) - special_modules = [main_pe, kernel32_pe, ntdll_pe] - if not all(special_modules): - log.warn('No main pe, ldr data will be unconsistant') - loaded_modules = modules_info.modules - else: - loaded_modules = [module for module in modules_info.modules - if module not in special_modules] - loaded_modules[0:0] = [main_pe] - loaded_modules[1:1] = [ntdll_pe] - loaded_modules[2:2] = [kernel32_pe] - - set_link_list_entry(jitter, loaded_modules, modules_info, 0x8) - - -def fix_InInitializationOrderModuleList(jitter, modules_info): - """Fix InInitializationOrderModuleList double link list. First module is the - ntdll, then kernel32. - - @jitter: the jitter instance - @modules_info: the LoadedModules instance - - """ - - log.debug("Fix InInitializationOrderModuleList") - main_pe = modules_info.name2module.get(main_pe_name, None) - kernel32_pe = modules_info.name2module.get("kernel32.dll", None) - ntdll_pe = modules_info.name2module.get("ntdll.dll", None) - special_modules = [main_pe, kernel32_pe, ntdll_pe] - if not all(special_modules): - log.warn('No main pe, ldr data will be unconsistant') - loaded_modules = modules_info.modules - else: - loaded_modules = [module for module in modules_info.modules - if module not in special_modules] - loaded_modules[0:0] = [ntdll_pe] - loaded_modules[1:1] = [kernel32_pe] - - set_link_list_entry(jitter, loaded_modules, modules_info, 0x10) - - -def add_process_env(jitter): - """ - Build a process environment structure - @jitter: jitter instance - """ - - env_unicode = 'ALLUSEESPROFILE=C:\\Documents and Settings\\All Users\x00'.encode('utf-16le') - env_unicode += b"\x00" * 0x10 - jitter.vm.add_memory_page( - process_environment_address, - PAGE_READ | PAGE_WRITE, - env_unicode, - "Process environment" - ) - jitter.vm.set_mem(process_environment_address, env_unicode) - - -def add_process_parameters(jitter): - """ - Build a process parameters structure - @jitter: jitter instance - """ - - o = b"" - o += pck32(0x1000) # size - o += b"E" * (0x48 - len(o)) - o += pck32(process_environment_address) - jitter.vm.add_memory_page( - process_parameters_address, - PAGE_READ | PAGE_WRITE, - o, "Process parameters" - ) - - -# http://blog.fireeye.com/research/2010/08/download_exec_notes.html -seh_count = 0 - - -def init_seh(jitter): - """ - Build the modules entries and create double links - @jitter: jitter instance - """ - - global seh_count - seh_count = 0 - tib_ad = jitter.cpu.get_segm_base(jitter.cpu.FS) - build_teb(jitter, tib_ad) - build_peb(jitter, peb_address) - - modules_info = create_modules_chain(jitter, name2module) - fix_InLoadOrderModuleList(jitter, modules_info) - fix_InMemoryOrderModuleList(jitter, modules_info) - fix_InInitializationOrderModuleList(jitter, modules_info) - - build_ldr_data(jitter, modules_info) - add_process_env(jitter) - add_process_parameters(jitter) - - - -def regs2ctxt(jitter, context_address): - """ - Build x86_32 cpu context for exception handling - @jitter: jitload instance - """ - - ctxt = ContextException(jitter.vm, context_address) - ctxt.memset(b"\x00") - # ContextFlags - # XXX - - # DRX - ctxt.dr0 = 0 - ctxt.dr1 = 0 - ctxt.dr2 = 0 - ctxt.dr3 = 0 - ctxt.dr4 = 0 - ctxt.dr5 = 0 - - # Float context - # XXX - - # Segment selectors - ctxt.gs = jitter.cpu.GS - ctxt.fs = jitter.cpu.FS - ctxt.es = jitter.cpu.ES - ctxt.ds = jitter.cpu.DS - - # Gpregs - ctxt.edi = jitter.cpu.EDI - ctxt.esi = jitter.cpu.ESI - ctxt.ebx = jitter.cpu.EBX - ctxt.edx = jitter.cpu.EDX - ctxt.ecx = jitter.cpu.ECX - ctxt.eax = jitter.cpu.EAX - ctxt.ebp = jitter.cpu.EBP - ctxt.eip = jitter.cpu.EIP - - # CS - ctxt.cs = jitter.cpu.CS - - # Eflags - # XXX TODO real eflag - - # ESP - ctxt.esp = jitter.cpu.ESP - - # SS - ctxt.ss = jitter.cpu.SS - - -def ctxt2regs(jitter, ctxt_ptr): - """ - Restore x86_32 registers from an exception context - @ctxt: the serialized context - @jitter: jitload instance - """ - - ctxt = ContextException(jitter.vm, ctxt_ptr) - - # Selectors - jitter.cpu.GS = ctxt.gs - jitter.cpu.FS = ctxt.fs - jitter.cpu.ES = ctxt.es - jitter.cpu.DS = ctxt.ds - - # Gpregs - jitter.cpu.EDI = ctxt.edi - jitter.cpu.ESI = ctxt.esi - jitter.cpu.EBX = ctxt.ebx - jitter.cpu.EDX = ctxt.edx - jitter.cpu.ECX = ctxt.ecx - jitter.cpu.EAX = ctxt.eax - jitter.cpu.EBP = ctxt.ebp - jitter.cpu.EIP = ctxt.eip - - # CS - jitter.cpu.CS = ctxt.cs - - # Eflag - # XXX TODO - - # ESP - jitter.cpu.ESP = ctxt.esp - # SS - jitter.cpu.SS = ctxt.ss - - -def fake_seh_handler(jitter, except_code, previous_seh=None): - """ - Create an exception context - @jitter: jitter instance - @except_code: x86 exception code - @previous_seh: (optional) last SEH address when multiple SEH are used - """ - global seh_count - log.info('Exception at %x %r', jitter.cpu.EIP, seh_count) - seh_count += 1 - - # Get space on stack for exception handling - new_ESP = jitter.cpu.ESP - 0x3c8 - exception_base_address = new_ESP - exception_record_address = exception_base_address + 0xe8 - context_address = exception_base_address + 0xfc - fake_seh_address = exception_base_address + 0x14 - - # Save a CONTEXT - regs2ctxt(jitter, context_address) - jitter.cpu.ESP = new_ESP - - # Get current seh (fs:[0]) - tib = NT_TIB(jitter.vm, tib_address) - seh = tib.ExceptionList.deref - if previous_seh: - # Recursive SEH - while seh.get_addr() != previous_seh: - seh = seh.Next.deref - seh = seh.Next.deref - - log.debug( - 'seh_ptr %x { old_seh %r eh %r} ctx_addr %x', - seh.get_addr(), - seh.Next, - seh.Handler, - context_address - ) - - # Write exception_record - except_record = EXCEPTION_RECORD(jitter.vm, exception_record_address) - except_record.memset(b"\x00") - except_record.ExceptionCode = except_code - except_record.ExceptionAddress = jitter.cpu.EIP - - # Prepare the stack - jitter.push_uint32_t(context_address) # Context - jitter.push_uint32_t(seh.get_addr()) # SEH - jitter.push_uint32_t(except_record.get_addr()) # ExceptRecords - jitter.push_uint32_t(return_from_exception) # Ret address - - # Set fake new current seh for exception - log.debug("Fake seh ad %x", fake_seh_address) - fake_seh = EXCEPTION_REGISTRATION_RECORD(jitter.vm, fake_seh_address) - fake_seh.Next.val = tib.ExceptionList.val - fake_seh.Handler = 0xaaaaaaaa - tib.ExceptionList.val = fake_seh.get_addr() - dump_seh(jitter) - - # Remove exceptions - jitter.vm.set_exception(0) - jitter.cpu.set_exception(0) - - # XXX set ebx to nul? - jitter.cpu.EBX = 0 - - log.debug('Jumping at %r', seh.Handler) - return seh.Handler.val - - -def dump_seh(jitter): - """ - Walk and dump the SEH entries - @jitter: jitter instance - """ - log.debug('Dump_seh. Tib_address: %x', tib_address) - cur_seh_ptr = NT_TIB(jitter.vm, tib_address).ExceptionList - loop = 0 - while cur_seh_ptr and jitter.vm.is_mapped(cur_seh_ptr.val, - len(cur_seh_ptr)): - if loop > MAX_SEH: - log.debug("Too many seh, quit") - return - err = cur_seh_ptr.deref - log.debug('\t' * (loop + 1) + 'seh_ptr: %x { prev_seh: %r eh %r }', - err.get_addr(), err.Next, err.Handler) - cur_seh_ptr = err.Next - loop += 1 - - -def set_win_fs_0(jitter, fs=4): - """ - Set FS segment selector and create its corresponding segment - @jitter: jitter instance - @fs: segment selector value - """ - jitter.cpu.FS = fs - jitter.cpu.set_segm_base(fs, tib_address) - segm_to_do = set([x86_regs.FS]) - return segm_to_do - - -def return_from_seh(jitter): - """Handle the return from an exception handler - @jitter: jitter instance""" - - # Get object addresses - seh_address = jitter.vm.get_u32(jitter.cpu.ESP + 0x4) - context_address = jitter.vm.get_u32(jitter.cpu.ESP + 0x8) - - # Get registers changes - log.debug('Context address: %x', context_address) - status = jitter.cpu.EAX - ctxt2regs(jitter, context_address) - - # Rebuild SEH (remove fake SEH) - tib = NT_TIB(jitter.vm, tib_address) - seh = tib.ExceptionList.deref - log.debug('Old seh: %x New seh: %x', seh.get_addr(), seh.Next.val) - tib.ExceptionList.val = seh.Next.val - dump_seh(jitter) - - # Handle returned values - if status == 0x0: - # ExceptionContinueExecution - log.debug('SEH continue') - jitter.pc = jitter.cpu.EIP - log.debug('Context::Eip: %x', jitter.pc) - - elif status == 1: - # ExceptionContinueSearch - log.debug("Delegate to the next SEH handler") - # exception_base_address: context_address - 0xfc - # -> exception_record_address: exception_base_address + 0xe8 - exception_record = EXCEPTION_RECORD(jitter.vm, - context_address - 0xfc + 0xe8) - - pc = fake_seh_handler(jitter, exception_record.ExceptionCode, - seh_address) - jitter.pc = pc - - else: - # https://msdn.microsoft.com/en-us/library/aa260344%28v=vs.60%29.aspx - # But the type _EXCEPTION_DISPOSITION may take 2 others values: - # - ExceptionNestedException = 2 - # - ExceptionCollidedUnwind = 3 - raise ValueError("Valid values are ExceptionContinueExecution and " - "ExceptionContinueSearch") - - # Jitter's breakpoint compliant - return True |