-
Notifications
You must be signed in to change notification settings - Fork 474
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Syscalls linux32 #1170
base: master
Are you sure you want to change the base?
Syscalls linux32 #1170
Changes from 1 commit
1a8b917
20e9a75
eca3635
13e8a4f
c3854c5
84d96a1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -68,6 +68,157 @@ def _dump_struct_stat_arml(info): | |
return data | ||
|
||
|
||
def sys_x86_32_execve(jitter, linux_env): | ||
# int execve(const char *pathname, char *const argv[], | ||
# char *const envp[]); | ||
pathname_addr, argv_ptr, envp_addr = jitter.syscall_args_systemv(3) | ||
pathname = jitter.get_c_str(pathname_addr) | ||
argv = [] | ||
i = 0 | ||
argv_addr = jitter.vm.get_u32(argv_ptr) | ||
while argv_addr != 0: | ||
argv.append(jitter.get_c_str(argv_addr)) | ||
argv_ptr += 4 | ||
argv_addr = jitter.vm.get_u32(argv_ptr) | ||
envp = [] | ||
i = 0 | ||
while envp_addr != 0: | ||
argv.append(jitter.get_c_str(envp_addr)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe it's There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also yes |
||
i += 4 | ||
argv_addr = jitter.vm.get_u32(jitter.cpu.EDX+i) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe it's There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep |
||
log.debug("sys_execve(%s, [%s], [%s])", pathname, | ||
", ".join(argv), ", ".join(envp)) | ||
jitter.syscall_ret_systemv(0) | ||
|
||
|
||
def sys_x86_64_execve(jitter, linux_env): | ||
# int execve(const char *pathname, char *const argv[], | ||
# char *const envp[]); | ||
# TODO : merge that into a generic execve | ||
pathname_addr, argv_ptr, envp_addr = jitter.syscall_args_systemv(3) | ||
pathname = jitter.get_c_str(pathname_addr) | ||
argv = [] | ||
i = 0 | ||
argv_addr = jitter.vm.get_u64(argv_ptr) | ||
while argv_addr != 0: | ||
argv.append(jitter.get_c_str(argv_addr)) | ||
argv_ptr += 8 | ||
argv_addr = jitter.vm.get_u64(argv_ptr) | ||
envp = [] | ||
i = 0 | ||
while envp_addr != 0: | ||
argv.append(jitter.get_c_str(envp_addr)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same remarks here for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Damn copy paste |
||
i += 8 | ||
argv_addr = jitter.vm.get_u64(jitter.cpu.EDX+i) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same remarks here for |
||
log.debug("sys_execve(%s, [%s], [%s])", pathname, | ||
", ".join(argv), ", ".join(envp)) | ||
jitter.syscall_ret_systemv(0) | ||
|
||
|
||
def sys_x86_32_socket(jitter, linux_env): | ||
# int socketcall(int call, unsigned long *args) | ||
# Redirect to several other socket syscalls | ||
SOCKET_DOMAINS = { | ||
0: "AF_UNSPEC", | ||
1: "AF_UNIX", | ||
2: "AF_INET", | ||
3: "AF_AX25", | ||
4: "AF_IPX", | ||
5: "AF_APPLETALK", | ||
6: "AF_NETROM", | ||
7: "AF_BRIDGE", | ||
8: "AF_AAL5", | ||
9: "AF_X25", #Who cares ? | ||
10: "AF_INET6", | ||
11: "AF_MAX" | ||
} | ||
|
||
SOCKET_TYPE = { | ||
1: "SOCK_STREAM", | ||
2: "SOCK_DGRAM", | ||
3: "SOCK_RAW" | ||
} | ||
|
||
if jitter.cpu.EBX == 1: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we could use constant instead of |
||
# int socket(int domain, int type, int protocol); | ||
domain = jitter.vm.get_u32(jitter.cpu.ESP) | ||
stype = jitter.vm.get_u32(jitter.cpu.ESP+4) | ||
proto = jitter.vm.get_u32(jitter.cpu.ESP+8) | ||
fd = linux_env.socket(domain, stype, proto) | ||
log.debug("socket(%s, %s, %s)", SOCKET_DOMAINS[domain], | ||
SOCKET_TYPE[stype], proto) | ||
jitter.syscall_ret_systemv(fd) | ||
elif jitter.cpu.EBX == 2: | ||
# int bind(int sockfd, const struct sockaddr *addr, | ||
# socklen_t addrlen); | ||
fd = jitter.vm.get_u32(jitter.cpu.ESP) | ||
socklen = jitter.vm.get_u32(jitter.cpu.ESP+8) | ||
sockaddr = jitter.vm.get_mem(jitter.cpu.ESP+4, socklen) | ||
family = struct.unpack("H", sockaddr[0:2])[0] | ||
if family == 2: | ||
# IPv4 | ||
port = struct.unpack(">H", sockaddr[2:4])[0] | ||
ip = ".".join([str(i) for i in struct.unpack("BBBB", sockaddr[4:8])]) | ||
log.debug("socket_bind(fd, [%s, %i, %s], %i)", SOCKET_DOMAINS[family], | ||
port, ip, socklen) | ||
else: | ||
log.debug("socket_bind(fd, sockaddr, socklen_t)") | ||
jitter.syscall_ret_systemv(0) | ||
elif jitter.cpu.EBX == 3: | ||
# int connect(int sockfd, const struct sockaddr *addr, | ||
# socklen_t addrlen); | ||
fd = jitter.vm.get_u32(jitter.cpu.ESP) | ||
socklen = jitter.vm.get_u32(jitter.cpu.ESP+8) | ||
# Not the exact size because shellcodes won't provide the full struct | ||
sockaddr = jitter.vm.get_mem(jitter.vm.get_u32(jitter.cpu.ESP+4), 8) | ||
family = struct.unpack("H", sockaddr[0:2])[0] | ||
if family == 2: | ||
# IPv4 | ||
port = struct.unpack(">H", sockaddr[2:4])[0] | ||
ip = ".".join([str(i) for i in struct.unpack("BBBB", sockaddr[4:8])]) | ||
log.debug("socket_connect(fd, [%s, %i, %s], %i)", SOCKET_DOMAINS[family], | ||
port, ip, socklen) | ||
else: | ||
log.debug("socket_connect(fd, sockaddr, socklen)") | ||
jitter.syscall_ret_systemv(0) | ||
Te-k marked this conversation as resolved.
Show resolved
Hide resolved
|
||
elif jitter.cpu.EBX == 4: | ||
# int listen(int sockfd, int backlog); | ||
sockfd = jitter.vm.get_u32(jitter.cpu.ESP) | ||
backlog = jitter.vm.get_u32(jitter.cpu.ESP+4) | ||
log.debug("socket_listen(%x, %x)", sockfd, backlog) | ||
jitter.syscall_ret_systemv(0) | ||
elif jitter.cpu.EBX == 5: | ||
# int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); | ||
sockfd = jitter.vm.get_u32(jitter.cpu.ESP) | ||
sockaddr = jitter.vm.get_u32(jitter.cpu.ESP+4) | ||
addrlen = jitter.vm.get_u32(jitter.cpu.ESP+8) | ||
log.debug("socket_accept(%x, %x, %x)", sockfd, sockaddr, addrlen) | ||
jitter.syscall_ret_systemv(0) | ||
elif jitter.cpu.EBX == 14: | ||
# SYS_SETSOCKOPT | ||
# int setsockopt(int sockfd, int level, int optname, | ||
# const void *optval, socklen_t optlen); | ||
sockfd = jitter.vm.get_u32(jitter.cpu.ESP) | ||
level = jitter.vm.get_u32(jitter.cpu.ESP+4) | ||
optname = jitter.vm.get_u32(jitter.cpu.ESP+8) | ||
optval_addr = jitter.vm.get_u32(jitter.cpu.ESP+12) | ||
optlen = jitter.vm.get_u32(jitter.cpu.ESP+16) | ||
log.debug("socket_setsockopt(%x, %x, %x, %x, %x)", sockfd, level, optname, | ||
optval_addr, optlen) | ||
jitter.syscall_ret_systemv(0) | ||
else: | ||
print(jitter.cpu.EBX) | ||
raise NotImplemented() | ||
|
||
|
||
def sys_generic_chmod(jitter, linux_env): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we could really apply the chmod on the file located in the file sandbox |
||
# int chmod(const char *pathname, mode_t mode); | ||
path_addr, mode = jitter.syscall_args_systemv(2) | ||
pathname = jitter.get_c_str(path_addr) | ||
log.debug("sys_chmod(%s, %x)", pathname, mode) | ||
jitter.syscall_ret_systemv(0) | ||
|
||
|
||
def sys_x86_64_rt_sigaction(jitter, linux_env): | ||
# Parse arguments | ||
sig, act, oact, sigsetsize = jitter.syscall_args_systemv(4) | ||
|
@@ -531,7 +682,12 @@ def sys_generic_write(jitter, linux_env): | |
|
||
# Stub | ||
data = jitter.vm.get_mem(buf, count) | ||
jitter.syscall_ret_systemv(linux_env.write(fd, data)) | ||
r = linux_env.write(fd, data) | ||
if r is None: | ||
log.debug("-> write : failed") | ||
jitter.syscall_ret_systemv(-1) | ||
else: | ||
jitter.syscall_ret_systemv(r) | ||
|
||
|
||
def sys_x86_64_getdents(jitter, linux_env): | ||
|
@@ -614,6 +770,14 @@ def sys_x86_64_newlstat(jitter, linux_env): | |
jitter.cpu.RAX = 0 | ||
|
||
|
||
def sys_generic_exit(jitter, linux_env): | ||
# void exit(int status); | ||
status, = jitter.syscall_args_systemv(1) | ||
log.debug("sys_exit(%i)", status) | ||
jitter.run = False | ||
jitter.pc = 0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe you don't need to set |
||
|
||
|
||
def sys_arml_lstat64(jitter, linux_env): | ||
# Parse arguments | ||
filename = jitter.cpu.R0 | ||
|
@@ -821,6 +985,14 @@ def sys_generic_setgid(jitter, linux_env): | |
jitter.syscall_ret_systemv(0) | ||
|
||
|
||
def sys_generic_setreuid(jitter, linux_env): | ||
# Parse arguments | ||
ruid, euid = jitter.syscall_args_systemv(2) | ||
log.debug("sys_setreuid(%x, %x)", ruid, euid) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could use the current Linux env |
||
|
||
jitter.syscall_ret_systemv(0) | ||
|
||
|
||
def sys_generic_setuid(jitter, linux_env): | ||
# Parse arguments | ||
uid, = jitter.syscall_args_systemv(1) | ||
|
@@ -899,7 +1071,16 @@ def sys_arml_gettimeofday(jitter, linux_env): | |
|
||
|
||
syscall_callbacks_x86_32 = { | ||
0x1: sys_generic_exit, | ||
0x3: sys_generic_read, | ||
0x4: sys_generic_write, | ||
0x5: sys_generic_open, | ||
0xB: sys_x86_32_execve, | ||
0xF: sys_generic_chmod, | ||
0x46: sys_generic_setreuid, | ||
0x66: sys_x86_32_socket, | ||
0x7A: sys_x86_32_newuname, | ||
0x7D: sys_generic_mprotect, | ||
} | ||
|
||
|
||
|
@@ -925,15 +1106,18 @@ def sys_arml_gettimeofday(jitter, linux_env): | |
0x27: sys_x86_64_getpid, | ||
0x29: sys_x86_64_socket, | ||
0x2A: sys_x86_64_connect, | ||
0x3B: sys_x86_64_execve, | ||
0x3F: sys_x86_64_newuname, | ||
0x48: sys_generic_fcntl64, | ||
0x4E: sys_x86_64_getdents, | ||
0x59: sys_x86_64_readlink, | ||
0x5A: sys_generic_chmod, | ||
0x63: sys_x86_64_sysinfo, | ||
0x66: sys_generic_getuid, | ||
0x68: sys_generic_getgid, | ||
0x6B: sys_generic_geteuid, | ||
0x6C: sys_generic_getegid, | ||
0x71: sys_generic_setreuid, | ||
0xE4: sys_x86_64_clock_gettime, | ||
0x89: sys_x86_64_statfs, | ||
0x9E: sys_x86_64_arch_prctl, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it's not a good idea to have a default
read
here. Maybe we can raise an error with pure abstract function, in order to for the user subclass this in order to implements it's own read.See for example
miasm/miasm/ir/translators/translator.py
Line 50 in 4c2320b
The user can subclass its own
LinuxEnvironement
and set a brand newself.network
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea, but it seems hard to subclass, it means you have to implement a subclass of
FileDescriptorSocket
,Network
andLinuxEnvironment
, and make all this work together, right ?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kind of. It will give something like:
But maybe there is better: we could modify those classes to have a class variable which embed their needs. For example, for Networking:
So the "overhead" may just be:
But I am not really sure if this is a suitable python pattern.
Or maybe
Networking
should take it's generator asinit
argument ?It's a problem we already face in the
SandBox
object, which depends on os, arch, ...@commial @p-l- I am interested if you have some feed on this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure this is the same problem than the multiple inheritance of Sandbox. IMHO, it looks like more what we've done in
Jitcore
withCgen
orSymbExecClass
, which reflects your last proposal.In my opinion, the question is "what we want to provides, and what customization should be reasonably easy to implements?".
I agree with the fact that it should be easy to modify what the socket returns, its state, etc. i'm not sure that the more global Networking part needs that kind of customization possibility.
A pattern we can use would be to provides a kind of "socket factory" (sorry for this word, but it is what it is) that the Network would use to creates its sockets.
It could be a function, taking as input the socket parameters and returning an instance with the socket "interface", ie. a subclass of the socket fd.
It could also be a class, taking as
__init__
these parameters, and asked just after for successful creation or not (to keep the possibility to easiliy deny socket creation). I rather prefer the function solution, as it could be easier to return default implementation or several socket families implementation.This "factory function" is then an attribute of the Networking class, and could be replaced with a dedicated function / property.
If this pattern become more frequent for the Linux kernel stub implementation, we could have a "config-like" class containing several factories functions, or hooks.
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the socket factory would be an attribute of Network ?
Using it would be something like :
Is that correct ?