diff options
Diffstat (limited to 'plugins/python')
-rw-r--r-- | plugins/python/lnxsyscalls/lnxsyscalls.py | 517 |
1 files changed, 517 insertions, 0 deletions
diff --git a/plugins/python/lnxsyscalls/lnxsyscalls.py b/plugins/python/lnxsyscalls/lnxsyscalls.py new file mode 100644 index 0000000..92d5763 --- /dev/null +++ b/plugins/python/lnxsyscalls/lnxsyscalls.py @@ -0,0 +1,517 @@ +#!/usr/bin/python + +from pyoida import Plugin +from pyoida.analysis import RenderingOptions +from pyoida.arch import ArchProcessorType + + +class SysCallDB(): + """xxx""" + + def __init__(self): + + self.__syscalls = [ + "__NR_restart_syscall", + "__NR_exit", + "__NR_fork", + "__NR_read", + "__NR_write", + "__NR_open", + "__NR_close", + "__NR_waitpid", + "__NR_creat", + "__NR_link", + "__NR_unlink", + "__NR_execve", + "__NR_chdir", + "__NR_time", + "__NR_mknod", + "__NR_chmod", + "__NR_lchown", + "__NR_break", + "__NR_oldstat", + "__NR_lseek", + "__NR_getpid", + "__NR_mount", + "__NR_umount", + "__NR_setuid", + "__NR_getuid", + "__NR_stime", + "__NR_ptrace", + "__NR_alarm", + "__NR_oldfstat", + "__NR_pause", + "__NR_utime", + "__NR_stty", + "__NR_gtty", + "__NR_access", + "__NR_nice", + "__NR_ftime", + "__NR_sync", + "__NR_kill", + "__NR_rename", + "__NR_mkdir", + "__NR_rmdir", + "__NR_dup", + "__NR_pipe", + "__NR_times", + "__NR_prof", + "__NR_brk", + "__NR_setgid", + "__NR_getgid", + "__NR_signal", + "__NR_geteuid", + "__NR_getegid", + "__NR_acct", + "__NR_umount2", + "__NR_lock", + "__NR_ioctl", + "__NR_fcntl", + "__NR_mpx", + "__NR_setpgid", + "__NR_ulimit", + "__NR_oldolduname", + "__NR_umask", + "__NR_chroot", + "__NR_ustat", + "__NR_dup2", + "__NR_getppid", + "__NR_getpgrp", + "__NR_setsid", + "__NR_sigaction", + "__NR_sgetmask", + "__NR_ssetmask", + "__NR_setreuid", + "__NR_setregid", + "__NR_sigsuspend", + "__NR_sigpending", + "__NR_sethostname", + "__NR_setrlimit", + "__NR_getrlimit", + "__NR_getrusage", + "__NR_gettimeofday", + "__NR_settimeofday", + "__NR_getgroups", + "__NR_setgroups", + "__NR_select", + "__NR_symlink", + "__NR_oldlstat", + "__NR_readlink", + "__NR_uselib", + "__NR_swapon", + "__NR_reboot", + "__NR_readdir", + "__NR_mmap", + "__NR_munmap", + "__NR_truncate", + "__NR_ftruncate", + "__NR_fchmod", + "__NR_fchown", + "__NR_getpriority", + "__NR_setpriority", + "__NR_profil", + "__NR_statfs", + "__NR_fstatfs", + "__NR_ioperm", + "__NR_socketcall", + "__NR_syslog", + "__NR_setitimer", + "__NR_getitimer", + "__NR_stat", + "__NR_lstat", + "__NR_fstat", + "__NR_olduname", + "__NR_iopl", + "__NR_vhangup", + "__NR_idle", + "__NR_vm86old", + "__NR_wait4", + "__NR_swapoff", + "__NR_sysinfo", + "__NR_ipc", + "__NR_fsync", + "__NR_sigreturn", + "__NR_clone", + "__NR_setdomainname", + "__NR_uname", + "__NR_modify_ldt", + "__NR_adjtimex", + "__NR_mprotect", + "__NR_sigprocmask", + "__NR_create_module", + "__NR_init_module", + "__NR_delete_module", + "__NR_get_kernel_syms", + "__NR_quotactl", + "__NR_getpgid", + "__NR_fchdir", + "__NR_bdflush", + "__NR_sysfs", + "__NR_personality", + "__NR_afs_syscall", + "__NR_setfsuid", + "__NR_setfsgid", + "__NR__llseek", + "__NR_getdents", + "__NR__newselect", + "__NR_flock", + "__NR_msync", + "__NR_readv", + "__NR_writev", + "__NR_getsid", + "__NR_fdatasync", + "__NR__sysctl", + "__NR_mlock", + "__NR_munlock", + "__NR_mlockall", + "__NR_munlockall", + "__NR_sched_setparam", + "__NR_sched_getparam", + "__NR_sched_setscheduler", + "__NR_sched_getscheduler", + "__NR_sched_yield", + "__NR_sched_get_priority_max", + "__NR_sched_get_priority_min", + "__NR_sched_rr_get_interval", + "__NR_nanosleep", + "__NR_mremap", + "__NR_setresuid", + "__NR_getresuid", + "__NR_vm86", + "__NR_query_module", + "__NR_poll", + "__NR_nfsservctl", + "__NR_setresgid", + "__NR_getresgid", + "__NR_prctl", + "__NR_rt_sigreturn", + "__NR_rt_sigaction", + "__NR_rt_sigprocmask", + "__NR_rt_sigpending", + "__NR_rt_sigtimedwait", + "__NR_rt_sigqueueinfo", + "__NR_rt_sigsuspend", + "__NR_pread64", + "__NR_pwrite64", + "__NR_chown", + "__NR_getcwd", + "__NR_capget", + "__NR_capset", + "__NR_sigaltstack", + "__NR_sendfile", + "__NR_getpmsg", + "__NR_putpmsg", + "__NR_vfork", + "__NR_ugetrlimit", + "__NR_mmap2", + "__NR_truncate64", + "__NR_ftruncate64", + "__NR_stat64", + "__NR_lstat64", + "__NR_fstat64", + "__NR_lchown32", + "__NR_getuid32", + "__NR_getgid32", + "__NR_geteuid32", + "__NR_getegid32", + "__NR_setreuid32", + "__NR_setregid32", + "__NR_getgroups32", + "__NR_setgroups32", + "__NR_fchown32", + "__NR_setresuid32", + "__NR_getresuid32", + "__NR_setresgid32", + "__NR_getresgid32", + "__NR_chown32", + "__NR_setuid32", + "__NR_setgid32", + "__NR_setfsuid32", + "__NR_setfsgid32", + "__NR_pivot_root", + "__NR_mincore", + "__NR_madvise", + "__NR_madvise1", + "__NR_getdents64", + "__NR_fcntl64", + "__NR_unused", + "__NR_gettid", + "__NR_readahead", + "__NR_setxattr", + "__NR_lsetxattr", + "__NR_fsetxattr", + "__NR_getxattr", + "__NR_lgetxattr", + "__NR_fgetxattr", + "__NR_listxattr", + "__NR_llistxattr", + "__NR_flistxattr", + "__NR_removexattr", + "__NR_lremovexattr", + "__NR_fremovexattr", + "__NR_tkill", + "__NR_sendfile64", + "__NR_futex", + "__NR_sched_setaffinity", + "__NR_sched_getaffinity", + "__NR_set_thread_area", + "__NR_get_thread_area", + "__NR_io_setup", + "__NR_io_destroy", + "__NR_io_getevents", + "__NR_io_submit", + "__NR_io_cancel", + "__NR_fadvise64", + "__NR_unused", + "__NR_exit_group", + "__NR_lookup_dcookie", + "__NR_epoll_create", + "__NR_epoll_ctl", + "__NR_epoll_wait", + "__NR_remap_file_pages", + "__NR_set_tid_address", + "__NR_timer_create", + "__NR_timer_settime", + "__NR_timer_gettime", + "__NR_timer_getoverrun", + "__NR_timer_delete", + "__NR_clock_settime", + "__NR_clock_gettime", + "__NR_clock_getres", + "__NR_clock_nanosleep", + "__NR_statfs64", + "__NR_fstatfs64", + "__NR_tgkill", + "__NR_utimes", + "__NR_fadvise64_64", + "__NR_vserver", + "__NR_mbind", + "__NR_get_mempolicy", + "__NR_set_mempolicy", + "__NR_mq_open", + "__NR_mq_unlink", + "__NR_mq_timedsend", + "__NR_mq_timedreceive", + "__NR_mq_notify", + "__NR_mq_getsetattr", + "__NR_kexec_load", + "__NR_waitid", + "__NR_sys_setaltroot", + "__NR_add_key", + "__NR_request_key", + "__NR_keyctl", + "__NR_ioprio_set", + "__NR_ioprio_get", + "__NR_inotify_init", + "__NR_inotify_add_watch", + "__NR_inotify_rm_watch", + "__NR_migrate_pages", + "__NR_openat", + "__NR_mkdirat", + "__NR_mknodat", + "__NR_fchownat", + "__NR_futimesat", + "__NR_fstatat64", + "__NR_unlinkat", + "__NR_renameat", + "__NR_linkat", + "__NR_symlinkat", + "__NR_readlinkat", + "__NR_fchmodat", + "__NR_faccessat", + "__NR_pselect6", + "__NR_ppoll", + "__NR_unshare", + "__NR_set_robust_list", + "__NR_get_robust_list", + "__NR_splice", + "__NR_sync_file_range", + "__NR_tee", + "__NR_vmsplice", + "__NR_move_pages", + "__NR_getcpu", + "__NR_epoll_pwait", + "__NR_utimensat", + "__NR_signalfd", + "__NR_timerfd_create", + "__NR_eventfd", + "__NR_fallocate", + "__NR_timerfd_settime", + "__NR_timerfd_gettime", + "__NR_signalfd4", + "__NR_eventfd2", + "__NR_epoll_create1", + "__NR_dup3", + "__NR_pipe2", + "__NR_inotify_init1", + "__NR_preadv", + "__NR_pwritev", + "__NR_rt_tgsigqueueinfo", + "__NR_perf_event_open" + ] + + self.__args = { + "sys_restart_syscall" : [], + "sys_exit" : ["int error_code"], + "sys_write" : ["unsigned int fd", "const char __user *buf", "size_t count"] + } + + def get_syscall_name(self, index): + """Convert a syscall index into a human name.""" + + return self.__syscalls[index] + + + def get_syscall_args(self, name): + """Provide the function name, the needed registers and the used arguments of a syscall.""" + + name = name.replace("__NR_", "sys_") + + try: + args = self.__args[name] + except: + return None + + targets = {} + + if len(args) >= 4: + + pass + + else: + + registers = ["ebx", "ecx", "edx", "esi", "edi"] + + i = 0 + + for val in args: + targets[registers[i]] = val + i = i + 1 + + return [name, targets] + + + + +class LinuxSysCallsPlugin(Plugin): + """A simple example class""" + + + + def __rendering_options(self, binary): + """Build the options needed to get the ASM code only.""" + + exe = binary.get_format() + + ropts = RenderingOptions(exe) + + ropts.show_code(True) + ropts.show_address = False + + return ropts + + def __is_syscall(self, code): + """Tell weither the ASM line of code is a syscall or not.""" + + result = False + + if code.find("int") != -1: + + list = code.split("\t") + + if len(list) == 2: + result = list == ["int", "0x80"] + + return result + + def __find_used_register(self, ropts, start, target): + """Look for a given register used to supply argument for a syscall.""" + + for found in reversed(start): + + code = found.get_text(ropts) + parts = code.expandtabs(1).replace(",", "").split(" ") + + # Next registers are used by a new interruption + if parts[0] == "int": + continue + + # No operand + if len(parts) == 1: + continue + + # Only simple cases are processed... + if parts[1] == target: + if len(parts) == 2: + return None + else: + return [found, parts[2]] + + return None + + def run(self, binary): + """Resolve all registers / interruptions involved in a syscall.""" + + db = SysCallDB() + + ropts = self.__rendering_options(binary) + + lines = binary.get_lines() + + for line in lines: + code = line.get_text(ropts) + if self.__is_syscall(code): + + # What kind of syscall ? + + line_eax = self.__find_used_register(ropts, line, "eax") + + if line_eax is None: + line.comment = "== UNIX Syscall ==" + continue + + index = int(line_eax[1], 16) + name = db.get_syscall_name(index) + + line_eax[0].comment = name + + # What function / arguments ? + + targets = db.get_syscall_args(name) + + if targets == None: + + line.comment = "== UNIX Syscall ==" + continue + + else: + + line.comment = "== UNIX Syscall to %s() ==" % (targets[0]) + + for reg, arg in targets[1].items(): + + found = self.__find_used_register(ropts, line, reg) + + if found != None: + found[0].comment = arg + + + + + + +def get_instance(binary): + + print " --- toto from Python ---" + + + + a = LinuxSysCallsPlugin() + + a.run(binary) + + return Plugin.PGA_CODE_PROCESS + + + + |