From 76ae39ee4b145498f0a008b66aab01982e0fef3a Mon Sep 17 00:00:00 2001 From: Albert <91817958+cgfandia-tii@users.noreply.github.com> Date: Fri, 3 Jun 2022 13:14:33 +0400 Subject: [PATCH 1/9] fix: ql_syscall_faccessat Dirty fix --- qiling/os/posix/syscall/unistd.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/qiling/os/posix/syscall/unistd.py b/qiling/os/posix/syscall/unistd.py index fe0c01ca6..bb2f7517b 100644 --- a/qiling/os/posix/syscall/unistd.py +++ b/qiling/os/posix/syscall/unistd.py @@ -143,12 +143,14 @@ def ql_syscall_faccessat(ql: Qiling, dfd: int, filename: int, mode: int): if not os.path.exists(real_path): regreturn = -1 - - elif stat.S_ISFIFO(Stat(real_path).st_mode): + else: regreturn = 0 + # TODO: according to real implementation, idk why here was a FIFO check + # elif stat.S_ISFIFO(Stat(real_path).st_mode): + # regreturn = 0 - else: - regreturn = -1 + # else: + # regreturn = -1 if regreturn == -1: ql.log.debug(f'File not found or skipped: {access_path}') From 211dd07870de027d7d1341a2a2e7b1b0013c0c31 Mon Sep 17 00:00:00 2001 From: Albert <91817958+cgfandia-tii@users.noreply.github.com> Date: Fri, 3 Jun 2022 13:53:25 +0400 Subject: [PATCH 2/9] fix: ql_syscall_writev Remove `buf` decoding with `utf-8` encoding due to possible errors --- qiling/os/posix/syscall/uio.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiling/os/posix/syscall/uio.py b/qiling/os/posix/syscall/uio.py index f07346a04..6c8e6e3d6 100644 --- a/qiling/os/posix/syscall/uio.py +++ b/qiling/os/posix/syscall/uio.py @@ -17,7 +17,7 @@ def ql_syscall_writev(ql: Qiling, fd: int, vec: int, vlen: int): regreturn += l buf = ql.mem.read(addr, l) - ql.log.debug(f'{buf.decode()!r}') + ql.log.debug(f'{bytes(buf)}') if hasattr(ql.os.fd[fd], 'write'): ql.os.fd[fd].write(buf) From 49644092a0efd08b7280e51bf59d16774f0a9036 Mon Sep 17 00:00:00 2001 From: Albert <91817958+cgfandia-tii@users.noreply.github.com> Date: Fri, 3 Jun 2022 18:09:55 +0400 Subject: [PATCH 3/9] fix: `ql_syscall_connect`, `ql_syscall_bind` Add support for the abstract socket namespace --- qiling/os/posix/syscall/socket.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/qiling/os/posix/syscall/socket.py b/qiling/os/posix/syscall/socket.py index a80c7b998..588b77299 100644 --- a/qiling/os/posix/syscall/socket.py +++ b/qiling/os/posix/syscall/socket.py @@ -67,6 +67,17 @@ def ql_bin_to_ip(ip): return ipaddress.ip_address(ip).compressed +def ql_unix_socket_path(ql: Qiling, sun_path: bytearray) -> str: + sun_path_str = sun_path.decode() + if sun_path[0] == 0: + # Abstract Unix namespace + # TODO: isolate from host namespace + # TODO: Windows + ql.log.warning(f'Beware! Usage of hosts abstract socket namespace {bytes(sun_path)}') + return sun_path_str + return ql.os.path.transform_to_real_path(sun_path_str) + + def ql_syscall_socket(ql: Qiling, socket_domain, socket_type, socket_protocol): idx = next((i for i in range(NR_OPEN) if ql.os.fd[i] is None), -1) regreturn = idx @@ -115,8 +126,7 @@ def ql_syscall_connect(ql: Qiling, connect_sockfd, connect_addr, connect_addrlen try: if s.family == family: if s.family == AF_UNIX: - sun_path = sock_addr[2 : ].split(b"\x00")[0] - sun_path = ql.os.path.transform_to_real_path(sun_path.decode()) + sun_path = ql_unix_socket_path(ql, sock_addr[2:]) s.connect(sun_path) regreturn = 0 elif s.family == AF_INET: @@ -297,8 +307,7 @@ def ql_syscall_bind(ql: Qiling, bind_fd, bind_addr, bind_addrlen): port = port + 8000 if sin_family == 1: - path = data[2 : ].split(b'\x00')[0] - path = ql.os.path.transform_to_real_path(path.decode()) + path = ql_unix_socket_path(ql, data[2:]) ql.log.info(path) ql.os.fd[bind_fd].bind(path) From 1d271bf53b0c5960a58700ce6a3aeed52e118147 Mon Sep 17 00:00:00 2001 From: Albert <91817958+cgfandia-tii@users.noreply.github.com> Date: Fri, 3 Jun 2022 18:35:19 +0400 Subject: [PATCH 4/9] fix: `ql_unix_socket_path` Remove leading null bytes from the path --- qiling/os/posix/syscall/socket.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/qiling/os/posix/syscall/socket.py b/qiling/os/posix/syscall/socket.py index 588b77299..76feafd92 100644 --- a/qiling/os/posix/syscall/socket.py +++ b/qiling/os/posix/syscall/socket.py @@ -68,14 +68,14 @@ def ql_bin_to_ip(ip): def ql_unix_socket_path(ql: Qiling, sun_path: bytearray) -> str: - sun_path_str = sun_path.decode() if sun_path[0] == 0: # Abstract Unix namespace # TODO: isolate from host namespace # TODO: Windows ql.log.warning(f'Beware! Usage of hosts abstract socket namespace {bytes(sun_path)}') - return sun_path_str - return ql.os.path.transform_to_real_path(sun_path_str) + return sun_path.decode() + sun_path = sun_path.split(b'\0')[0].decode() + return ql.os.path.transform_to_real_path(sun_path) def ql_syscall_socket(ql: Qiling, socket_domain, socket_type, socket_protocol): From 59ecb1fe7e2b64f6298d7794fdf284023a0b394c Mon Sep 17 00:00:00 2001 From: Albert <91817958+cgfandia-tii@users.noreply.github.com> Date: Fri, 3 Jun 2022 18:44:56 +0400 Subject: [PATCH 5/9] fix: `ql_syscall_sendto` Add `ql_unix_socket_path` for the `AF_UNIX` --- qiling/os/posix/syscall/socket.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/qiling/os/posix/syscall/socket.py b/qiling/os/posix/syscall/socket.py index 76feafd92..0c18fa2e5 100644 --- a/qiling/os/posix/syscall/socket.py +++ b/qiling/os/posix/syscall/socket.py @@ -609,8 +609,7 @@ def ql_syscall_sendto(ql: Qiling, sockfd: int, sendto_buf, sendto_len, sendto_fl ql.log.debug("sendto() len is " + str(sendto_len)) if sin_family == 1: - path = data[2 : ].split(b'\x00')[0] - path = ql.os.path.transform_to_real_path(path.decode()) + path = ql_unix_socket_path(ql, data[2:]) ql.log.debug("sendto() path is " + str(path)) regreturn = sock.sendto(bytes(tmp_buf), sendto_flags, path) From 0f07bb6f1b5075112dc5042526430649a1eb7c03 Mon Sep 17 00:00:00 2001 From: Albert Farrakhov Date: Mon, 6 Jun 2022 15:34:29 +0400 Subject: [PATCH 6/9] fix: `__getdents_common` `ino64_t` and `off64_t` are `unsigned long long` - not pointers --- qiling/os/posix/syscall/unistd.py | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/qiling/os/posix/syscall/unistd.py b/qiling/os/posix/syscall/unistd.py index bb2f7517b..20af7c8a1 100644 --- a/qiling/os/posix/syscall/unistd.py +++ b/qiling/os/posix/syscall/unistd.py @@ -738,7 +738,7 @@ def _type_mapping(ent): return bytes([t]) if ql.os.fd[fd].tell() == 0: - n = ql.arch.pointersize + large_field_size = 8 if is_64 else 4 total_size = 0 results = os.scandir(ql.os.fd[fd].name) _ent_count = 0 @@ -748,27 +748,20 @@ def _type_mapping(ent): d_off = 0 d_name = (result.name if isinstance(result, os.DirEntry) else result._str).encode() + b'\x00' d_type = _type_mapping(result) - d_reclen = n + n + 2 + len(d_name) + 1 - - # TODO: Dirty fix for X8664 MACOS 11.6 APFS - # For some reason MACOS return int value is 64bit - try: - packed_d_ino = (ql.pack(d_ino), n) - except: - packed_d_ino = (ql.pack64(d_ino), n) + d_reclen = large_field_size + large_field_size + 2 + len(d_name) + 1 if is_64: fields = ( - (ql.pack(d_ino), n), - (ql.pack(d_off), n), + (ql.pack64(d_ino), large_field_size), + (ql.pack64(d_off), large_field_size), (ql.pack16(d_reclen), 2), (d_type, 1), (d_name, len(d_name)) ) else: fields = ( - packed_d_ino, - (ql.pack(d_off), n), + (ql.pack(d_ino), large_field_size), + (ql.pack(d_off), large_field_size), (ql.pack16(d_reclen), 2), (d_name, len(d_name)), (d_type, 1) From 7b506668300e8bd7e14f3e251f5aeccfb592c2a7 Mon Sep 17 00:00:00 2001 From: Albert Farrakhov Date: Mon, 6 Jun 2022 18:37:12 +0400 Subject: [PATCH 7/9] fix: `ql_syscall_recvfrom` Add Unix abstract namespace handling --- qiling/os/posix/syscall/socket.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/qiling/os/posix/syscall/socket.py b/qiling/os/posix/syscall/socket.py index 0c18fa2e5..ca0cf94ae 100644 --- a/qiling/os/posix/syscall/socket.py +++ b/qiling/os/posix/syscall/socket.py @@ -554,19 +554,22 @@ def ql_syscall_recvfrom(ql: Qiling, sockfd: int, buf: int, length: int, flags: i ql.log.debug("%s" % tmp_buf) sin_family = int(sock.family) - data = struct.pack("H", tmp_addr[1]) - data += ipaddress.ip_address(tmp_addr[0]).packed + sockaddr_out += struct.pack(">H", tmp_addr[1]) + sockaddr_out += ipaddress.ip_address(tmp_addr[0]).packed addrlen = ql.mem.read_ptr(addrlen) - data = data[:addrlen] + sockaddr_out = sockaddr_out[:addrlen] - ql.mem.write(addr, data) + if addr: + ql.mem.write(addr, sockaddr_out) ql.mem.write(buf, tmp_buf) return len(tmp_buf) From c83cb19305d52b06852317182e635180fe7cfc2b Mon Sep 17 00:00:00 2001 From: Albert <91817958+cgfandia-tii@users.noreply.github.com> Date: Thu, 30 Jun 2022 09:27:23 +0400 Subject: [PATCH 8/9] fix: remove comments --- qiling/os/posix/syscall/unistd.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/qiling/os/posix/syscall/unistd.py b/qiling/os/posix/syscall/unistd.py index 7e85a7cb0..475890d1d 100644 --- a/qiling/os/posix/syscall/unistd.py +++ b/qiling/os/posix/syscall/unistd.py @@ -145,12 +145,6 @@ def ql_syscall_faccessat(ql: Qiling, dfd: int, filename: int, mode: int): regreturn = -1 else: regreturn = 0 - # TODO: according to real implementation, idk why here was a FIFO check - # elif stat.S_ISFIFO(Stat(real_path).st_mode): - # regreturn = 0 - - # else: - # regreturn = -1 if regreturn == -1: ql.log.debug(f'File not found or skipped: {access_path}') From bc53bb467cc4bea08b6a1b5d67016f1774402667 Mon Sep 17 00:00:00 2001 From: Albert Farrakhov Date: Tue, 5 Jul 2022 14:39:59 +0400 Subject: [PATCH 9/9] fix: revert to arch-dependent `getdents` --- qiling/os/posix/syscall/unistd.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/qiling/os/posix/syscall/unistd.py b/qiling/os/posix/syscall/unistd.py index 475890d1d..4e4e38170 100644 --- a/qiling/os/posix/syscall/unistd.py +++ b/qiling/os/posix/syscall/unistd.py @@ -728,7 +728,7 @@ def _type_mapping(ent): return bytes([t]) if ql.os.fd[fd].tell() == 0: - large_field_size = 8 if is_64 else 4 + n = ql.arch.pointersize total_size = 0 results = os.scandir(ql.os.fd[fd].name) _ent_count = 0 @@ -738,20 +738,27 @@ def _type_mapping(ent): d_off = 0 d_name = (result.name if isinstance(result, os.DirEntry) else result._str).encode() + b'\x00' d_type = _type_mapping(result) - d_reclen = large_field_size + large_field_size + 2 + len(d_name) + 1 + d_reclen = n + n + 2 + len(d_name) + 1 + + # TODO: Dirty fix for X8664 MACOS 11.6 APFS + # For some reason MACOS return int value is 64bit + try: + packed_d_ino = (ql.pack(d_ino), n) + except: + packed_d_ino = (ql.pack64(d_ino), n) if is_64: fields = ( - (ql.pack64(d_ino), large_field_size), - (ql.pack64(d_off), large_field_size), + (ql.pack(d_ino), n), + (ql.pack(d_off), n), (ql.pack16(d_reclen), 2), (d_type, 1), (d_name, len(d_name)) ) else: fields = ( - (ql.pack(d_ino), large_field_size), - (ql.pack(d_off), large_field_size), + packed_d_ino, + (ql.pack(d_off), n), (ql.pack16(d_reclen), 2), (d_name, len(d_name)), (d_type, 1)