#!/usr/bin/perl
#
# author: pof <eslack.org>
# perl port: elektranox <gmail.com>
#

my %linux_syscalls = (
	"00" => "LINUX_sys_setup[sys_ni_syscall]",
	"01" => "LINUX_sys_exit",
	"02" => "LINUX_sys_fork",
	"03" => "LINUX_sys_read",
	"04" => "LINUX_sys_write",
	"04" => "LINUX_sys_write",
	"05" => "LINUX_sys_open",
	"06" => "LINUX_sys_close",
	"07" => "LINUX_sys_waitpid",
	"00" => "LINUX_sys_creat",
	"00" => "LINUX_sys_link",
	"0a" => "LINUX_sys_unlink",
	"0b" => "LINUX_sys_execve",
	"0c" => "LINUX_sys_chdir",
	"0d" => "LINUX_sys_time",
	"0e" => "LINUX_sys_mknod",
	"0f" => "LINUX_sys_chmod",
	"10" => "LINUX_sys_lchown",
	"11" => "LINUX_sys_break[sys_ni_syscall]",
	"12" => "LINUX_sys_oldstat[sys_stat]",
	"13" => "LINUX_sys_lseek",
	"14" => "LINUX_sys_getpid",
	"15" => "LINUX_sys_mount",
	"16" => "LINUX_sys_umount[sys_oldumount]",
	"17" => "LINUX_sys_setuid",
	"18" => "LINUX_sys_getuid",
	"19" => "LINUX_sys_stime",
	"1a" => "LINUX_sys_ptrace",
	"1b" => "LINUX_sys_alarm",
	"1c" => "LINUX_sys_oldfstat[sys_fstat]",
	"1d" => "LINUX_sys_pause",
	"1e" => "LINUX_sys_utime",
	"1f" => "LINUX_sys_stty[sys_ni_syscall]",
	"20" => "LINUX_sys_gtty[sys_ni_syscall]",
	"21" => "LINUX_sys_access",
	"22" => "LINUX_sys_nice",
	"23" => "LINUX_sys_ftime[sys_ni_syscall]",
	"24" => "LINUX_sys_sync",
	"25" => "LINUX_sys_kill",
	"26" => "LINUX_sys_rename",
	"27" => "LINUX_sys_mkdir",
	"28" => "LINUX_sys_rmdir",
	"29" => "LINUX_sys_dup",
	"2a" => "LINUX_sys_pipe",
	"2b" => "LINUX_sys_times",
	"2c" => "LINUX_sys_prof[sys_ni_syscall]",
	"2d" => "LINUX_sys_brk",
	"2e" => "LINUX_sys_setgid",
	"2f" => "LINUX_sys_getgid",
	"30" => "LINUX_sys_signal",
	"31" => "LINUX_sys_geteuid",
	"32" => "LINUX_sys_getegid",
	"33" => "LINUX_sys_acct",
	"34" => "LINUX_sys_umount2[sys_umount]",
	"35" => "LINUX_sys_lock[sys_ni_syscall]",
	"36" => "LINUX_sys_ioctl",
	"37" => "LINUX_sys_fcntl",
	"38" => "LINUX_sys_mpx[sys_ni_syscall]",
	"39" => "LINUX_sys_setpgid",
	"3a" => "LINUX_sys_ulimit[sys_ni_syscall]",
	"3b" => "LINUX_sys_oldolduname",
	"3c" => "LINUX_sys_umask",
	"3d" => "LINUX_sys_chroot",
	"3e" => "LINUX_sys_ustat",
	"3f" => "LINUX_sys_dup2",
	"40" => "LINUX_sys_getppid",
	"41" => "LINUX_sys_getpgrp",
	"42" => "LINUX_sys_setsid",
	"43" => "LINUX_sys_sigaction",
	"44" => "LINUX_sys_sgetmask",
	"45" => "LINUX_sys_ssetmask",
	"46" => "LINUX_sys_setreuid",
	"47" => "LINUX_sys_setregid",
	"48" => "LINUX_sys_sigsuspend",
	"49" => "LINUX_sys_sigpending",
	"4a" => "LINUX_sys_sethostname",
	"4b" => "LINUX_sys_setrlimit",
	"4c" => "LINUX_sys_getrlimit",
	"4d" => "LINUX_sys_getrusage",
	"4e" => "LINUX_sys_gettimeofday",
	"4f" => "LINUX_sys_settimeofday",
	"50" => "LINUX_sys_getgroups",
	"51" => "LINUX_sys_setgroups",
	"52" => "LINUX_sys_select[old_select]",
	"53" => "LINUX_sys_symlink",
	"54" => "LINUX_sys_oldlstat[sys_lstat]",
	"55" => "LINUX_sys_readlink",
	"56" => "LINUX_sys_uselib",
	"57" => "LINUX_sys_swapon",
	"58" => "LINUX_sys_reboot",
	"59" => "LINUX_sys_readdir[old_readdir]",
	"5a" => "LINUX_sys_mmap[old_mmap]",
	"5b" => "LINUX_sys_munmap",
	"5c" => "LINUX_sys_truncate",
	"5d" => "LINUX_sys_ftruncate",
	"5e" => "LINUX_sys_fchmod",
	"5f" => "LINUX_sys_fchown",
	"60" => "LINUX_sys_getpriority",
	"61" => "LINUX_sys_setpriority",
	"62" => "LINUX_sys_profil[sys_ni_syscall]",
	"63" => "LINUX_sys_statfs",
	"64" => "LINUX_sys_fstatfs",
	"65" => "LINUX_sys_ioperm",
	"66" => "LINUX_sys_socketcall",
	"67" => "LINUX_sys_syslog",
	"68" => "LINUX_sys_setitimer",
	"69" => "LINUX_sys_getitimer",
	"6a" => "LINUX_sys_stat[sys_newstat]",
	"6b" => "LINUX_sys_lstat[sys_newlstat]",
	"6c" => "LINUX_sys_fstat[sys_newfstat]",
	"6d" => "LINUX_sys_olduname[sys_uname]",
	"6e" => "LINUX_sys_iopl",
	"6f" => "LINUX_sys_vhangup",
	"70" => "LINUX_sys_idle",
	"71" => "LINUX_sys_vm86old",
	"72" => "LINUX_sys_wait4",
	"73" => "LINUX_sys_swapoff",
	"74" => "LINUX_sys_sysinfo",
	"75" => "LINUX_sys_ipc",
	"76" => "LINUX_sys_fsync",
	"77" => "LINUX_sys_sigreturn",
	"78" => "LINUX_sys_clone",
	"79" => "LINUX_sys_setdomainname",
	"7a" => "LINUX_sys_uname[sys_newuname]",
	"7b" => "LINUX_sys_modify_ldt",
	"7c" => "LINUX_sys_adjtimex",
	"7d" => "LINUX_sys_mprotect",
	"7e" => "LINUX_sys_sigprocmask",
	"7f" => "LINUX_sys_create_module",
	"81" => "LINUX_sys_delete_module",
	"82" => "LINUX_sys_get_kernel_syms",
	"83" => "LINUX_sys_quotactl",
	"84" => "LINUX_sys_getpgid",
	"85" => "LINUX_sys_fchdir",
	"86" => "LINUX_sys_bdflush",
	"87" => "LINUX_sys_sysfs",
	"88" => "LINUX_sys_personality",
	"89" => "LINUX_sys_afs_syscall[sys_ni_syscall]",
	"8a" => "LINUX_sys_setfsuid",
	"8b" => "LINUX_sys_setfsgid",
	"8c" => "LINUX_sys__llseek[sys_lseek]",
	"8d" => "LINUX_sys_getdents",
	"8e" => "LINUX_sys__newselect[sys_select]",
	"8f" => "LINUX_sys_flock",
	"90" => "LINUX_sys_msync",
	"91" => "LINUX_sys_readv",
	"92" => "LINUX_sys_writev",
	"93" => "LINUX_sys_getsid",
	"94" => "LINUX_sys_fdatasync",
	"95" => "LINUX_sys__sysctl[sys_sysctl]",
	"96" => "LINUX_sys_mlock",
	"97" => "LINUX_sys_munlock",
	"98" => "LINUX_sys_mlockall",
	"99" => "LINUX_sys_munlockall",
	"9a" => "LINUX_sys_sched_setparam",
	"9b" => "LINUX_sys_sched_getparam",
	"9c" => "LINUX_sys_sched_setscheduler",
	"9d" => "LINUX_sys_sched_getscheduler",
	"9e" => "LINUX_sys_sched_yield",
	"9f" => "LINUX_sys_sched_get_priority_max",
	"a0" => "LINUX_sys_sched_get_priority_min",
	"a1" => "LINUX_sys_sched_rr_get_interval",
	"a2" => "LINUX_sys_nanosleep",
	"a3" => "LINUX_sys_mremap",
	"a4" => "LINUX_sys_setresuid",
	"a5" => "LINUX_sys_getresuid",
	"a6" => "LINUX_sys_vm86",
	"a7" => "LINUX_sys_query_module",
	"a8" => "LINUX_sys_poll",
	"a9" => "LINUX_sys_nfsservctl",
	"aa" => "LINUX_sys_setresgid",
	"ab" => "LINUX_sys_getresgid",
	"ac" => "LINUX_sys_prctl",
	"ad" => "LINUX_sys_rt_sigreturn",
	"ae" => "LINUX_sys_rt_sigaction",
	"af" => "LINUX_sys_rt_sigprocmask",
	"b0" => "LINUX_sys_rt_sigpending",
	"b1" => "LINUX_sys_rt_sigtimedwait",
	"b2" => "LINUX_sys_rt_sigqueueinfo",
	"b3" => "LINUX_sys_rt_sigsuspend",
	"b4" => "LINUX_sys_pread",
	"b5" => "LINUX_sys_pwrite",
	"b6" => "LINUX_sys_chown",
	"b7" => "LINUX_sys_getcwd",
	"b8" => "LINUX_sys_capget",
	"b9" => "LINUX_sys_capset",
	"ba" => "LINUX_sys_sigaltstack",
	"bb" => "LINUX_sys_sendfile",
	"bc" => "LINUX_sys_getpmsg[sys_ni_syscall]",
	"bd" => "LINUX_sys_putpmsg[sys_ni_syscall]",
	"be" => "LINUX_sys_vfork",
);

die "Usage: rsc syscall-flag [file]\n" unless(@ARGV);
my $file=$ARGV[0];

# get rabin informations
my @foo=split('\n', `rabin -e $file`);
my @foomem=split(' ', $foo[0]);
my @foodsk=split(' ', $foo[1]);
my $mem=hex $foomem[0];
my $dsk=hex $foodsk[0];

#FIXME: remove the grep things
my @syscalls=split('\n', `objdump -d $file | grep -4 'int    \$0x80' | egrep "(int|eax)"`);
my $cont=0;

for my $i (0 .. $#syscalls) {
	# Get current line
	$line=$syscalls[$i];

	# Calculate offset
	@foo=split(':', $line);
	$offset=$foo[0];
	$offset =~ s/^\s+//;
	$offset = hex $offset;
	$offset = $offset - $mem + $dsk;
	$offset = sprintf("%x", $offset);

	# Get current call byte
	@foo=split(' ', $line);
	$call=$foo[2];

	# FIXME: support for other Operating Systems (NetBSD, ...)
	if ($linux_syscalls{$call}) {
		$input = %linux_syscalls->{$call};
	} elsif($call == "80") {
		@foo=split(' ', $line);
		$pre=$foo[1];
		
		if($pre == "cd") {
			print ":fn $input @ 0x$offset\n";
			$cont++;
		} else {
			$input="LINUX_sys_init_module";
		}
	}
}
print STDERR "$cont syscalls added\n"
