Qiling-side IPC client — sends requests to the proxy process.
| 83 | |
| 84 | |
| 85 | class ProxyClient: |
| 86 | """Qiling-side IPC client — sends requests to the proxy process.""" |
| 87 | |
| 88 | def __init__(self, sock: socket.socket): |
| 89 | self._sock = sock |
| 90 | |
| 91 | def syscall(self, nr: int, args: tuple) -> int: |
| 92 | """Forward a raw syscall. Returns kernel-convention result (negative errno on error).""" |
| 93 | padded = tuple(args) + (0,) * (6 - len(args)) |
| 94 | payload = struct.pack(SYSCALL_REQ_FMT, nr, *padded[:6]) |
| 95 | |
| 96 | # send request |
| 97 | header = struct.pack(HEADER_FMT, MsgType.SYSCALL, len(payload)) |
| 98 | self._sock.sendall(header + payload) |
| 99 | |
| 100 | # recv response |
| 101 | resp_header = _recvall(self._sock, HEADER_SIZE) |
| 102 | _, resp_len = struct.unpack(HEADER_FMT, resp_header) |
| 103 | resp_payload = _recvall(self._sock, resp_len) |
| 104 | |
| 105 | retval, errno_val = struct.unpack(SYSCALL_RESP_FMT, resp_payload) |
| 106 | return retval |
| 107 | |
| 108 | def syscall_ex(self, nr: int, args: Sequence[int], |
| 109 | in_bufs: Sequence[Tuple[int, bytes]], |
| 110 | out_specs: Sequence[Tuple[int, int]]) -> Tuple[int, List[bytes]]: |
| 111 | """Forward a syscall with buffer marshaling. |
| 112 | |
| 113 | Args: |
| 114 | nr: host syscall number. |
| 115 | args: 6 integer arg values; for buffer args these are placeholders — |
| 116 | the proxy replaces them with the buffer address before invoking. |
| 117 | in_bufs: list of (arg_idx, data) — buffers to copy in. |
| 118 | out_specs: list of (arg_idx, length) — buffers to copy out. |
| 119 | |
| 120 | Returns: |
| 121 | (retval, out_bufs) where out_bufs is a list aligned with out_specs. |
| 122 | """ |
| 123 | padded = tuple(args) + (0,) * (6 - len(args)) |
| 124 | payload = bytearray(struct.pack(SYSCALL_REQ_FMT, nr, *padded[:6])) |
| 125 | |
| 126 | payload.append(len(in_bufs)) |
| 127 | for arg_idx, data in in_bufs: |
| 128 | payload += struct.pack('!BI', arg_idx, len(data)) |
| 129 | payload += data |
| 130 | |
| 131 | payload.append(len(out_specs)) |
| 132 | for arg_idx, length in out_specs: |
| 133 | payload += struct.pack('!BI', arg_idx, length) |
| 134 | |
| 135 | header = struct.pack(HEADER_FMT, MsgType.SYSCALL_EX, len(payload)) |
| 136 | self._sock.sendall(header + bytes(payload)) |
| 137 | |
| 138 | resp_header = _recvall(self._sock, HEADER_SIZE) |
| 139 | _, resp_len = struct.unpack(HEADER_FMT, resp_header) |
| 140 | resp_payload = _recvall(self._sock, resp_len) |
| 141 | |
| 142 | retval, _errno, num_out = struct.unpack( |