Rizin
unix-like reverse engineering framework and cli tools
iob_net.c File Reference
#include <errno.h>
#include <rz_crypto.h>
#include <rz_hash.h>
#include <rz_socket.h>
#include <rz_util.h>
#include "kd.h"
#include "transport.h"

Go to the source code of this file.

Classes

struct  iobnet_t
 

Macros

#define BUF_SIZE   4096
 

Typedefs

typedef struct iobnet_t iobnet_t
 

Functions

static ut64 base36_decode (const char *str)
 
static bool _initializeDatakey (iobnet_t *obj, ut8 *resbuf, int size)
 
static void * iob_net_open (const char *path)
 
static bool iob_net_close (void *p)
 
static bool _encrypt (iobnet_t *obj, ut8 *buf, int size, int type)
 
static ut8_createKDNetPacket (iobnet_t *obj, const ut8 *buf, int size, int *osize, ut64 seqno, ut8 type)
 
static bool _decrypt (iobnet_t *obj, ut8 *buf, int size, int type)
 
static bool _sendResponsePacket (iobnet_t *obj, const ut8 *pokedata)
 
static bool _processControlPacket (iobnet_t *obj, const ut8 *ctrlbuf, int size)
 
bool _verifyhmac (iobnet_t *obj)
 
static int iob_net_read (void *p, uint8_t *obuf, const uint64_t count, const int timeout)
 
static int iob_net_write (void *p, const uint8_t *buf, const uint64_t count, const int timeout)
 

Variables

static const char d32 [] = "[\\]^_`abcd$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$efghijklmnopqrstuvwxyz{|}~"
 
static const ut64 pow36 []
 
io_backend_t iob_net
 

Macro Definition Documentation

◆ BUF_SIZE

#define BUF_SIZE   4096

Definition at line 13 of file iob_net.c.

Typedef Documentation

◆ iobnet_t

typedef struct iobnet_t iobnet_t

Function Documentation

◆ _createKDNetPacket()

static ut8* _createKDNetPacket ( iobnet_t obj,
const ut8 buf,
int  size,
int osize,
ut64  seqno,
ut8  type 
)
static

Definition at line 241 of file iob_net.c.

241  {
242  // Calculate the pad size for KD packet.
243  // The KD packet is 16-byte aligned in KDNet.
244  ut8 padsize = -(size + 8) & 0x0F;
245 
246  int encsize = sizeof(kdnet_packet_t) + KDNET_DATA_SIZE + size + padsize + KDNET_HMAC_SIZE;
247  ut8 *encbuf = calloc(1, encsize);
248  if (!encbuf) {
249  return NULL;
250  }
251 
252  // Write KDNet Header
253  rz_write_at_be32(encbuf, KDNET_MAGIC, 0); // Magic
254  rz_write_at_be8(encbuf, obj->version, 4); // Protocol Number
255  rz_write_at_be8(encbuf, type, 5); // Channel Type
256  // Write KDNet Data (8 bytes)
257  // seqno (7 bytes) | direction (4 bits) | padsize (4 bits)
258  // seqno - sequence number
259  // direction - 0x0 Debuggee -> Debugger, 0x8 Debugger -> Debuggee
260  rz_write_at_be64(encbuf, ((seqno << 8) | 0x8 << 4 | padsize), 6);
261 
262  // Copy KD Packet from buffer
263  memcpy(encbuf + sizeof(kdnet_packet_t) + KDNET_DATA_SIZE, buf, size);
264 
265  // Generate HMAC from KDNet Data to KD packet
266  int off = sizeof(kdnet_packet_t) + KDNET_DATA_SIZE + size + padsize;
267 
268  const ut8 *digest = NULL;
270  if (!md) {
271  free(encbuf);
272  return NULL;
273  }
274 
275  if (!rz_hash_cfg_update(md, encbuf, off) ||
276  !rz_hash_cfg_final(md) ||
277  !(digest = rz_hash_cfg_get_result(md, "sha256", NULL))) {
278  free(encbuf);
280  return NULL;
281  }
282 
283  memcpy(encbuf + off, digest, KDNET_HMAC_SIZE);
285 
286  // Encrypt the KDNet Data, KD Packet and padding
287  if (!_encrypt(obj, encbuf + sizeof(kdnet_packet_t), encsize - sizeof(kdnet_packet_t), type)) {
288  free(encbuf);
289  return NULL;
290  }
291 
292  if (osize) {
293  *osize = encsize;
294  }
295  return encbuf;
296 }
#define NULL
Definition: cris-opc.c:27
RZ_API RZ_BORROW const ut8 * rz_hash_cfg_get_result(RZ_NONNULL RzHashCfg *md, RZ_NONNULL const char *name, RZ_NONNULL ut32 *size)
Returns the digest value of the requested algorithm name.
Definition: hash.c:445
RZ_API void rz_hash_cfg_free(RZ_NONNULL RzHashCfg *md)
Definition: hash.c:186
RZ_API RZ_OWN RzHashCfg * rz_hash_cfg_new_with_algo(RZ_NONNULL RzHash *rh, RZ_NONNULL const char *name, RZ_NULLABLE const ut8 *key, ut64 key_size)
Returns a message digest context with the give algo already configured.
Definition: hash.c:161
RZ_API bool rz_hash_cfg_update(RZ_NONNULL RzHashCfg *md, RZ_NONNULL const ut8 *data, ut64 size)
Inserts data into each the message digest contextes.
Definition: hash.c:337
RZ_API bool rz_hash_cfg_final(RZ_NONNULL RzHashCfg *md)
Generates the final value of the message digest contextes.
Definition: hash.c:359
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
voidpf void * buf
Definition: ioapi.h:138
static bool _encrypt(iobnet_t *obj, ut8 *buf, int size, int type)
Definition: iob_net.c:182
#define KDNET_MAGIC
Definition: kd.h:246
#define KDNET_DATA_SIZE
Definition: kd.h:262
#define KDNET_HMAC_SIZE
Definition: kd.h:248
#define KDNET_HMACKEY_SIZE
Definition: kd.h:247
uint8_t ut8
Definition: lh5801.h:11
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
int type
Definition: mipsasm.c:17
int off
Definition: pal.c:13
static void rz_write_at_be8(void *dest, ut8 val, size_t offset)
Definition: rz_endian.h:46
static void rz_write_at_be32(void *dest, ut32 val, size_t offset)
Definition: rz_endian.h:103
static void rz_write_at_be64(void *dest, ut64 val, size_t offset)
Definition: rz_endian.h:124
ut8 hmackey[KDNET_HMACKEY_SIZE]
Definition: iob_net.c:33
RzHash * hash
Definition: iob_net.c:38
ut8 version
Definition: iob_net.c:37

References _encrypt(), calloc(), free(), iobnet_t::hash, iobnet_t::hmackey, KDNET_DATA_SIZE, KDNET_HMAC_SIZE, KDNET_HMACKEY_SIZE, KDNET_MAGIC, benchmark::md, memcpy(), NULL, off, rz_hash_cfg_final(), rz_hash_cfg_free(), rz_hash_cfg_get_result(), rz_hash_cfg_new_with_algo(), rz_hash_cfg_update(), rz_write_at_be32(), rz_write_at_be64(), rz_write_at_be8(), type, and iobnet_t::version.

Referenced by _sendResponsePacket(), and iob_net_write().

◆ _decrypt()

static bool _decrypt ( iobnet_t obj,
ut8 buf,
int  size,
int  type 
)
static

Definition at line 298 of file iob_net.c.

298  {
299  bool ret = false;
300  RzCrypto *cry = rz_crypto_new();
301  if (!cry) {
302  return false;
303  }
304  if (!rz_crypto_use(cry, "aes-cbc")) {
305  goto end;
306  }
307 
308  // Set AES-256 Key based on the KDNet packet type
309  switch (type) {
311  if (!rz_crypto_set_key(cry, obj->datakey, sizeof(obj->datakey), 0, 1)) {
312  goto end;
313  }
314  break;
316  if (!rz_crypto_set_key(cry, obj->key, sizeof(obj->key), 0, 1)) {
317  goto end;
318  }
319  break;
320  default:
321  goto end;
322  }
323 
324  // Set IV to the 16 bytes HMAC at the end of KDNet packet
326  goto end;
327  }
328 
329  // Decrypt the buffer except HMAC
330  if (rz_crypto_final(cry, buf, size - KDNET_HMAC_SIZE) == 0) {
331  goto end;
332  }
333  // Overwrite it with decrypted data
334  int sz;
335  const ut8 *decbuf = rz_crypto_get_output(cry, &sz);
336  if (!decbuf) {
337  goto end;
338  }
339  memcpy(buf, decbuf, size - KDNET_HMAC_SIZE);
340  ret = true;
341 
342 end:
343  rz_crypto_free(cry);
344  return ret;
345 }
RZ_API bool rz_crypto_set_iv(RzCrypto *cry, const ut8 *iv, int ivlen)
Definition: crypto.c:161
RZ_API int rz_crypto_final(RzCrypto *cry, const ut8 *buf, int len)
Definition: crypto.c:170
RZ_API const ut8 * rz_crypto_get_output(RzCrypto *cry, int *size)
Definition: crypto.c:193
RZ_API bool rz_crypto_set_key(RzCrypto *cry, const ut8 *key, int keylen, int mode, int direction)
Definition: crypto.c:151
RZ_API void rz_crypto_free(RzCrypto *cry)
Definition: crypto.c:116
RZ_API RzCrypto * rz_crypto_new(void)
Definition: crypto.c:83
RZ_API bool rz_crypto_use(RzCrypto *cry, const char *algo)
Definition: crypto.c:130
#define KDNET_PACKET_TYPE_DATA
Definition: kd.h:250
#define KDNET_PACKET_TYPE_CONTROL
Definition: kd.h:251
ut8 key[32]
Definition: iob_net.c:29
ut8 datakey[32]
Definition: iob_net.c:31

References iobnet_t::datakey, test_evm::end, KDNET_HMAC_SIZE, KDNET_PACKET_TYPE_CONTROL, KDNET_PACKET_TYPE_DATA, iobnet_t::key, memcpy(), rz_crypto_final(), rz_crypto_free(), rz_crypto_get_output(), rz_crypto_new(), rz_crypto_set_iv(), rz_crypto_set_key(), rz_crypto_use(), and type.

Referenced by iob_net_read().

◆ _encrypt()

static bool _encrypt ( iobnet_t obj,
ut8 buf,
int  size,
int  type 
)
static

Definition at line 182 of file iob_net.c.

182  {
183  bool ret = false;
184  RzCrypto *cry = rz_crypto_new();
185  if (!cry) {
186  return false;
187  }
188  if (!rz_crypto_use(cry, "aes-cbc")) {
189  goto end;
190  }
191 
192  // Set AES-256 Key based on the KDNet packet type
193  switch (type) {
195  if (!rz_crypto_set_key(cry, obj->datakey, sizeof(obj->datakey), 0, 0)) {
196  goto end;
197  }
198  break;
199  case KDNET_PACKET_TYPE_CONTROL: // Control Channel
200  if (!rz_crypto_set_key(cry, obj->key, sizeof(obj->key), 0, 0)) {
201  goto end;
202  }
203  break;
204  default:
205  goto end;
206  }
207 
208  // Set IV to the 16 bytes HMAC at the end of KDNet packet
210  goto end;
211  }
212 
213  // Encrypt the buffer except HMAC
214  if (rz_crypto_final(cry, buf, size - KDNET_HMAC_SIZE) == 0) {
215  goto end;
216  }
217  // Overwrite the buffer with encrypted data
218  int sz;
219  const ut8 *encbuf = rz_crypto_get_output(cry, &sz);
220  if (!encbuf) {
221  goto end;
222  }
223  memcpy(buf, encbuf, size - KDNET_HMAC_SIZE);
224 
225  ret = true;
226 end:
227  rz_crypto_free(cry);
228  return ret;
229 }

References iobnet_t::datakey, test_evm::end, KDNET_HMAC_SIZE, KDNET_PACKET_TYPE_CONTROL, KDNET_PACKET_TYPE_DATA, iobnet_t::key, memcpy(), rz_crypto_final(), rz_crypto_free(), rz_crypto_get_output(), rz_crypto_new(), rz_crypto_set_iv(), rz_crypto_set_key(), rz_crypto_use(), and type.

Referenced by _createKDNetPacket().

◆ _initializeDatakey()

static bool _initializeDatakey ( iobnet_t obj,
ut8 resbuf,
int  size 
)
static

Definition at line 88 of file iob_net.c.

88  {
89  RzHashSize digest_size = 0;
90  const ut8 *digest = NULL;
91  RzHashCfg *md = rz_hash_cfg_new_with_algo2(obj->hash, "sha256");
92  if (!md) {
93  return false;
94  }
95 
96  if (!rz_hash_cfg_update(md, obj->key, 32) ||
97  !rz_hash_cfg_update(md, resbuf, size) ||
99  !(digest = rz_hash_cfg_get_result(md, "sha256", &digest_size))) {
100 
102  return false;
103  }
104 
105  memcpy(obj->datakey, digest, digest_size);
107 
108  return true;
109 }
ut32 RzHashSize
Definition: rz_hash.h:24

References iobnet_t::datakey, iobnet_t::hash, iobnet_t::key, benchmark::md, memcpy(), NULL, rz_hash_cfg_final(), rz_hash_cfg_free(), rz_hash_cfg_get_result(), and rz_hash_cfg_update().

Referenced by _sendResponsePacket().

◆ _processControlPacket()

static bool _processControlPacket ( iobnet_t obj,
const ut8 ctrlbuf,
int  size 
)
static

Definition at line 400 of file iob_net.c.

400  {
401  if (obj->hasDatakey) {
402  return true;
403  }
404  // Read KDNet Data to verify direction flag
405  ut64 kdnetdata = rz_read_be64(ctrlbuf);
406  if ((kdnetdata & 0x80) != 0) {
407  eprintf("Error: KdNet wrong direction flag\n");
408  return false;
409  }
410 
411  // Respond to the control packet
412  if (!_sendResponsePacket(obj, ctrlbuf)) {
413  eprintf("Error: KdNet sending the response packet\n");
414  return false;
415  }
416 
417  return true;
418 }
static bool _sendResponsePacket(iobnet_t *obj, const ut8 *pokedata)
Definition: iob_net.c:352
#define eprintf(x, y...)
Definition: rlcc.c:7
static ut64 rz_read_be64(const void *src)
Definition: rz_endian.h:108
bool hasDatakey
Definition: iob_net.c:17
ut64(WINAPI *w32_GetEnabledXStateFeatures)()

References _sendResponsePacket(), eprintf, iobnet_t::hasDatakey, rz_read_be64(), and ut64().

Referenced by iob_net_read().

◆ _sendResponsePacket()

static bool _sendResponsePacket ( iobnet_t obj,
const ut8 pokedata 
)
static

Definition at line 352 of file iob_net.c.

352  {
353  size_t i;
354  int size;
355 
356  // Create the following buffer as the KD packet in the KDNet Response packet:
357  // 0x01
358  // 0x02
359  // 32 bytes of Client Key from the first 32 bytes data of the Poke packet,
360  // 32 bytes of Randomly generated Host Key,
361  // 256 bytes of zeroes
362  ut8 *resbuf = calloc(1, 322);
363  if (!resbuf) {
364  return false;
365  }
366  // 0x01 0x02
367  resbuf[0] = 0x01;
368  resbuf[1] = 0x02;
369  // Copy 32 bytes Client Key after the KDNet Data
370  memcpy(resbuf + 2, pokedata + 10, 32);
371  // Generate 32 bytes random Host Key
372  for (i = 0; i < 32; i++) {
373  int rand = rz_num_rand(0xFF);
374  resbuf[i + 34] = rand & 0xFF;
375  }
376 
377  // Set seqno to the same seqno in Poke packet
378  ut64 seqno = rz_read_be64(pokedata) >> 8;
379  ut8 *pkt = _createKDNetPacket(obj, resbuf, 322, &size, seqno, 1);
380  if (!pkt) {
381  free(resbuf);
382  return false;
383  }
385  if (rz_socket_write(obj->sock, (void *)pkt, size) < 0) {
386  free(pkt);
387  free(resbuf);
388  return false;
389  }
390 
391  _initializeDatakey(obj, resbuf, 322);
392  obj->hasDatakey = true;
394 
395  free(pkt);
396  free(resbuf);
397  return true;
398 }
lzma_index ** i
Definition: index.h:629
static bool _initializeDatakey(iobnet_t *obj, ut8 *resbuf, int size)
Definition: iob_net.c:88
static ut8 * _createKDNetPacket(iobnet_t *obj, const ut8 *buf, int size, int *osize, ut64 seqno, ut8 type)
Definition: iob_net.c:241
RZ_API int rz_num_rand(int max)
Definition: unum.c:47
RZ_API int rz_socket_write(RzSocket *s, void *buf, int len)
Definition: socket.c:724
RzSocket * sock
Definition: iob_net.c:16
RzThreadLock * key_lock
Definition: iob_net.c:35
RZ_API void rz_th_lock_leave(RZ_NONNULL RzThreadLock *thl)
Releases a RzThreadLock structure.
Definition: thread_lock.c:75
RZ_API void rz_th_lock_enter(RZ_NONNULL RzThreadLock *thl)
Acquires a RzThreadLock structure.
Definition: thread_lock.c:45

References _createKDNetPacket(), _initializeDatakey(), calloc(), free(), iobnet_t::hasDatakey, i, iobnet_t::key_lock, memcpy(), rz_num_rand(), rz_read_be64(), rz_socket_write(), rz_th_lock_enter(), rz_th_lock_leave(), iobnet_t::sock, and ut64().

Referenced by _processControlPacket().

◆ _verifyhmac()

bool _verifyhmac ( iobnet_t obj)

Definition at line 420 of file iob_net.c.

420  {
421  const ut8 *digest = NULL;
423  if (!md) {
424  return false;
425  }
426 
428  !rz_hash_cfg_final(md) ||
429  !(digest = rz_hash_cfg_get_result(md, "sha256", NULL))) {
431  return false;
432  }
433 
434  bool result = !memcmp(digest, obj->read_buf + obj->read_size - KDNET_HMAC_SIZE, KDNET_HMAC_SIZE);
436 
437  return result;
438 }
int read_size
Definition: iob_net.c:26
ut8 read_buf[BUF_SIZE]
Definition: iob_net.c:24

References iobnet_t::hash, iobnet_t::hmackey, KDNET_HMAC_SIZE, KDNET_HMACKEY_SIZE, benchmark::md, NULL, iobnet_t::read_buf, iobnet_t::read_size, rz_hash_cfg_final(), rz_hash_cfg_free(), rz_hash_cfg_get_result(), rz_hash_cfg_new_with_algo(), and rz_hash_cfg_update().

Referenced by iob_net_read().

◆ base36_decode()

static ut64 base36_decode ( const char *  str)
static

Definition at line 48 of file iob_net.c.

48  {
49  ut64 ret = 0;
50  size_t i;
51  size_t len = strlen(str);
52  // 64-bit base36 str has at most 13 characters
53  if (len > 13) {
54  eprintf("Error: base36_decode supports up to 64-bit values only\n");
55  return 0;
56  }
57  for (i = 0; i < len; i++) {
58  char c = str[len - i - 1];
59  // "01234567890abcdefghijklmnopqrstuvwxyz"
60  if (c < '0' || c > 'z' || ('9' < c && c < 'a')) {
61  eprintf("Error: %s is not a valid base36 encoded string\n", str);
62  return 0;
63  }
64  ut8 v = d32[c - '0'];
65  // Character does not exist in base36 encoding
66  if (v == '$') {
67  eprintf("Error: %s is not a valid base36 encoded string\n", str);
68  return 0;
69  }
70  v -= 91;
71  // Check for overflow
72  if (i == 12) {
73  if (v > 3 || UT64_ADD_OVFCHK(ret, v * pow36[i])) {
74  printf("Error: base36_decode supports up to 64-bit values only\n");
75  return 0;
76  }
77  }
78  ret += v * pow36[i];
79  }
80  return ret;
81 }
size_t len
Definition: 6502dis.c:15
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
const char * v
Definition: dsignal.c:12
static const ut64 pow36[]
Definition: iob_net.c:44
static const char d32[]
Definition: iob_net.c:42
#define UT64_ADD_OVFCHK(x, y)
#define c(i)
Definition: sha256.c:43

References c, d32, eprintf, i, len, pow36, printf(), cmd_descs_generate::str, ut64(), UT64_ADD_OVFCHK, and v.

Referenced by iob_net_open().

◆ iob_net_close()

static bool iob_net_close ( void *  p)
static

Definition at line 168 of file iob_net.c.

168  {
169  int ret = true;
170  iobnet_t *obj = (iobnet_t *)p;
171 
172  if (rz_socket_close(obj->sock)) {
173  ret = false;
174  }
175 
176  rz_socket_free(obj->sock);
177  rz_hash_free(obj->hash);
178  free(obj);
179  return ret;
180 }
RZ_API void rz_hash_free(RzHash *rh)
Definition: hash.c:597
void * p
Definition: libc.cpp:67
RZ_API int rz_socket_close(RzSocket *s)
Definition: socket.c:419
RZ_API int rz_socket_free(RzSocket *s)
Definition: socket.c:453

References free(), iobnet_t::hash, p, rz_hash_free(), rz_socket_close(), rz_socket_free(), and iobnet_t::sock.

◆ iob_net_open()

static void* iob_net_open ( const char *  path)
static

Definition at line 111 of file iob_net.c.

111  {
112  size_t i;
113 
114  iobnet_t *obj = RZ_NEW0(iobnet_t);
115  if (!obj) {
116  return NULL;
117  }
118  obj->hash = rz_hash_new();
119  obj->key_lock = rz_th_lock_new(false);
120  if (!obj->key_lock) {
121  free(obj);
122  return NULL;
123  }
124 
125  char *host = strdup(path);
126  char *port = strchr(host, ':');
127  if (RZ_STR_ISEMPTY(port)) {
128  free(host);
129  free(obj);
130  return NULL;
131  }
132  *port++ = 0;
133  char *key = strchr(port, ':');
134  if (RZ_STR_ISEMPTY(key)) {
135  free(host);
136  free(obj);
137  return NULL;
138  }
139  *key++ = 0;
140 
141  // Decode AES-256 Control Key (x.x.x.x) from base36
142  char *nkey;
143  for (i = 0; i < 4 && key; key = nkey, i++) {
144  nkey = strchr(key, '.');
145  if (nkey) {
146  *nkey++ = 0;
147  }
148  rz_write_le64(obj->key + i * 8, base36_decode(key));
149  }
150 
151  // HMAC Key is the negation of AES-256 Control Key bytes
152  for (i = 0; i < 32; i++) {
153  obj->hmackey[i] = ~(obj->key[i]);
154  }
155 
156  RzSocket *sock = rz_socket_new(0);
157  if (!rz_socket_connect_udp(sock, host, port, 1)) {
158  free(host);
159  free(obj);
160  return NULL;
161  }
162  obj->sock = sock;
163 
164  free(host);
165  return (void *)obj;
166 }
static static fork const void static count static fd const char const char static newpath const char static path const char path
Definition: sflib.h:35
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len key
Definition: sflib.h:118
RZ_API RzHash * rz_hash_new(void)
Definition: hash.c:585
static ut64 base36_decode(const char *str)
Definition: iob_net.c:48
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
static void rz_write_le64(void *dest, ut64 val)
Definition: rz_endian.h:277
RZ_API RzSocket * rz_socket_new(bool is_ssl)
Definition: socket.c:179
#define rz_socket_connect_udp(a, b, c, d)
Definition: rz_socket.h:100
#define RZ_STR_ISEMPTY(x)
Definition: rz_str.h:67
#define RZ_NEW0(x)
Definition: rz_types.h:284
RZ_API RZ_OWN RzThreadLock * rz_th_lock_new(bool recursive)
Allocates and initialize a RzThreadLock structure.
Definition: thread_lock.c:14

References base36_decode(), free(), iobnet_t::hash, iobnet_t::hmackey, i, key, iobnet_t::key, iobnet_t::key_lock, NULL, path, rz_hash_new(), RZ_NEW0, rz_socket_connect_udp, rz_socket_new(), RZ_STR_ISEMPTY, rz_th_lock_new(), rz_write_le64(), iobnet_t::sock, and strdup().

◆ iob_net_read()

static int iob_net_read ( void *  p,
uint8_t obuf,
const uint64_t  count,
const int  timeout 
)
static

Definition at line 440 of file iob_net.c.

440  {
441  kdnet_packet_t pkt = { 0 };
442  iobnet_t *obj = (iobnet_t *)p;
443 
444  if (obj->read_size == 0) {
445  do {
446  obj->read_size = rz_socket_read(obj->sock, obj->read_buf, BUF_SIZE);
447  if (obj->read_size < sizeof(kdnet_packet_t) + KDNET_HMAC_SIZE) {
448  // Continue if RzCons breaks
449  if (errno == EINTR) {
450  continue;
451  }
452  goto fail;
453  }
454  memcpy(&pkt, obj->read_buf, sizeof(kdnet_packet_t));
455 
456  // Verify the KDNet Header magic
457  if (rz_read_be32(obj->read_buf) != KDNET_MAGIC) {
458  eprintf("Error: KdNet bad magic\n");
459  goto fail;
460  }
461 
462  // Decrypt the KDNet Data and KD Packet
463  if (!_decrypt(obj, obj->read_buf + sizeof(kdnet_packet_t), obj->read_size - sizeof(kdnet_packet_t), pkt.type)) {
464  goto fail;
465  }
466 
467  // Verify the KDNet HMAC
468  if (!_verifyhmac(obj)) {
469  eprintf("Error: KdNet failed authentication\n");
470  goto fail;
471  }
472 
473  // Process KDNet Control Packets
474  if (pkt.type == KDNET_PACKET_TYPE_CONTROL) {
475  obj->version = pkt.version;
476  if (!_processControlPacket(obj, obj->read_buf + sizeof(kdnet_packet_t), obj->read_size)) {
477  eprintf("Error: KdNet failed to process Control packet\n");
478  goto fail;
479  };
480  obj->read_size = 0;
481  }
482  } while (pkt.type == KDNET_PACKET_TYPE_CONTROL);
483 
484  // Remove padding from the buffer
485  ut8 padsize = rz_read_at_be64(obj->read_buf, sizeof(kdnet_packet_t)) & 0xF;
486  obj->read_size -= KDNET_HMAC_SIZE + padsize;
487 
488  // Seek to KD packet
489  obj->read_off = sizeof(kdnet_packet_t) + KDNET_DATA_SIZE;
490 
491  // KD_PACKET_TYPE_UNUSED KD packet does not have a checksum,
492  // but kd_read_packet always read for the 4-byte checksum
493  if (rz_read_at_be16(obj->read_buf, obj->read_off + 4) == KD_PACKET_TYPE_UNUSED) {
494  obj->read_size += 4;
495  }
496  }
497 
498  if (count + obj->read_off > obj->read_size) {
499  eprintf("Error: KdNet out-of-bounds read\n");
500  goto fail;
501  }
502 
503  // Copy remaining data in buffer
504  size_t c = RZ_MIN(count, obj->read_size - obj->read_off);
505  memcpy(obuf, obj->read_buf + obj->read_off, c);
506  obj->read_off += c;
507 
508  // Reset the internal buffer when finished
509  if (obj->read_off == obj->read_size) {
510  obj->read_size = 0;
511  }
512 
513  return count;
514 fail:
515  obj->read_size = 0;
516  return -1;
517 }
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
static bool _processControlPacket(iobnet_t *obj, const ut8 *ctrlbuf, int size)
Definition: iob_net.c:400
#define BUF_SIZE
Definition: iob_net.c:13
bool _verifyhmac(iobnet_t *obj)
Definition: iob_net.c:420
static bool _decrypt(iobnet_t *obj, ut8 *buf, int size, int type)
Definition: iob_net.c:298
@ KD_PACKET_TYPE_UNUSED
Definition: kd.h:19
static ut64 rz_read_at_be64(const void *src, size_t offset)
Definition: rz_endian.h:114
static ut32 rz_read_be32(const void *src)
Definition: rz_endian.h:87
static ut16 rz_read_at_be16(const void *src, size_t offset)
Definition: rz_endian.h:55
RZ_API void RZ_API int rz_socket_read(RzSocket *s, ut8 *read, int len)
Definition: socket.c:783
#define RZ_MIN(x, y)
#define EINTR
Definition: sftypes.h:114
ut32 read_off
Definition: iob_net.c:25
#define fail(test)
Definition: tests.h:29
static unsigned char * obuf
Definition: z80asm.c:36

References _decrypt(), _processControlPacket(), _verifyhmac(), BUF_SIZE, c, count, EINTR, eprintf, fail, KD_PACKET_TYPE_UNUSED, KDNET_DATA_SIZE, KDNET_HMAC_SIZE, KDNET_MAGIC, KDNET_PACKET_TYPE_CONTROL, memcpy(), obuf, p, iobnet_t::read_buf, iobnet_t::read_off, iobnet_t::read_size, RZ_MIN, rz_read_at_be16(), rz_read_at_be64(), rz_read_be32(), rz_socket_read(), iobnet_t::sock, and iobnet_t::version.

◆ iob_net_write()

static int iob_net_write ( void *  p,
const uint8_t buf,
const uint64_t  count,
const int  timeout 
)
static

Definition at line 519 of file iob_net.c.

519  {
520  static ut64 seqno = 1;
521  iobnet_t *obj = (iobnet_t *)p;
522  if (obj->write_size == 0) {
523  // kd_packet_t
524  if (count == sizeof(kd_packet_t)) {
525  kd_packet_t pkt;
526  memcpy(&pkt, buf, sizeof(kd_packet_t));
527 
528  obj->write_size = sizeof(kd_packet_t) + pkt.length;
529  obj->write_off = count;
530  memcpy(obj->write_buf, buf, count);
531  } else { // breakin packet "b"
532  memcpy(obj->write_buf, buf, count);
533  obj->write_size = count;
534  obj->write_off = count;
535  }
536  } else {
537  memcpy(obj->write_buf + obj->write_off, buf, count);
538  obj->write_off += count;
539  }
540 
541  if (obj->write_off == obj->write_size) {
542  int size;
544  ut8 *pkt = _createKDNetPacket(obj, obj->write_buf, obj->write_size, &size, seqno, 0);
545  if (!pkt) {
547  return -1;
548  }
549  if (rz_socket_write(obj->sock, (void *)pkt, size) < 0) {
550  free(pkt);
552  return -1;
553  }
555  seqno++;
556 
557  obj->write_size = 0;
558  free(pkt);
559  }
560 
561  return count;
562 }
ut8 write_buf[BUF_SIZE]
Definition: iob_net.c:20
ut32 write_off
Definition: iob_net.c:21
int write_size
Definition: iob_net.c:22

References _createKDNetPacket(), count, free(), iobnet_t::key_lock, memcpy(), p, rz_socket_write(), rz_th_lock_enter(), rz_th_lock_leave(), iobnet_t::sock, ut64(), iobnet_t::write_buf, iobnet_t::write_off, and iobnet_t::write_size.

Variable Documentation

◆ d32

const char d32[] = "[\\]^_`abcd$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$efghijklmnopqrstuvwxyz{|}~"
static

Definition at line 42 of file iob_net.c.

Referenced by base36_decode().

◆ iob_net

io_backend_t iob_net
Initial value:
= {
.name = "kdnet",
.type = KD_IO_NET,
.init = NULL,
.deinit = NULL,
.config = NULL,
.open = &iob_net_open,
.close = &iob_net_close,
.read = &iob_net_read,
.write = &iob_net_write,
}
static int iob_net_write(void *p, const uint8_t *buf, const uint64_t count, const int timeout)
Definition: iob_net.c:519
static void * iob_net_open(const char *path)
Definition: iob_net.c:111
static int iob_net_read(void *p, uint8_t *obuf, const uint64_t count, const int timeout)
Definition: iob_net.c:440
static bool iob_net_close(void *p)
Definition: iob_net.c:168
#define KD_IO_NET
Definition: transport.h:18

Definition at line 564 of file iob_net.c.

Referenced by __open().

◆ pow36

const ut64 pow36[]
static
Initial value:
= { 1, 36, 1296, 46656, 1679616, 60466176, 2176782336,
78364164096, 2821109907456, 101559956668416, 3656158440062976,
131621703842267136, 4738381338321616896 }

Definition at line 44 of file iob_net.c.

Referenced by base36_decode().