Rizin
unix-like reverse engineering framework and cli tools
rz_axml.h File Reference
#include <rz_types.h>

Go to the source code of this file.

Functions

RZ_API RZ_OWN char * rz_axml_decode (RZ_NONNULL const ut8 *buffer, const ut64 size)
 Decode a buffer with Android XML to regular XML string representation. More...
 

Function Documentation

◆ rz_axml_decode()

RZ_API RZ_OWN char* rz_axml_decode ( RZ_NONNULL const ut8 data,
const ut64  data_size 
)

Decode a buffer with Android XML to regular XML string representation.

Parameters
dataBuffer containing the AXML data
data_sizeSize of the buffer data
Returns
String with the regular XML string

Definition at line 303 of file axml.c.

303  {
304  string_pool_t *pool = NULL;
305  namespace_t *namespace = NULL;
306  const ut32 *resource_map = NULL;
307  ut32 resource_map_length = 0;
308  RzStrBuf *sb = NULL;
309  st32 depth = 0;
310 
312  if (data_size == 0) {
313  return strdup("");
314  }
315 
316  RzBuffer *buffer = rz_buf_new_with_pointers(data, data_size, false);
317  if (!buffer) {
318  RZ_LOG_ERROR("Error allocating RzBuffer\n");
319  goto error;
320  }
321 
322  ut64 offset = 0;
323 
324  chunk_header_t header = { 0 };
325  if (rz_buf_fread_at(buffer, offset, (ut8 *)&header, "ssi", 1) != sizeof(header)) {
326  goto bad;
327  }
328 
329  if (header.type != TYPE_XML) {
330  goto bad;
331  }
332 
333  ut64 binary_size = header.size;
334  if (binary_size > data_size) {
335  goto bad;
336  }
337 
338  offset += sizeof(header);
339 
340  sb = rz_strbuf_new("");
341 
342  while (offset < binary_size) {
343  if (rz_buf_fread_at(buffer, offset, (ut8 *)&header, "ssi", 1) != sizeof(header)) {
344  goto bad;
345  }
346 
347  ut16 type = header.type;
348 
349  // After reading the original chunk header, read the type-specific
350  // header
351  offset += sizeof(header);
352 
353  switch (type) {
354  case TYPE_STRING_POOL: {
355  ut16 header_size = header.size;
356  if (header_size == 0 || header_size > data_size) {
357  goto bad;
358  }
359 
360  pool = malloc(header_size);
361  if (!pool) {
362  goto bad;
363  }
364 
365  if (rz_buf_read_at(buffer, offset, (void *)pool, header_size) != header_size) {
366  goto bad;
367  }
368  break;
369  }
370  case TYPE_START_ELEMENT: {
371  // The string pool must be the first header
372  if (!pool) {
373  goto bad;
374  }
375 
376  ut16 header_size = header.size;
377  if (header_size == 0 || header_size > data_size) {
378  goto bad;
379  }
380 
381  start_element_t *element = malloc(header_size);
382  if (!element) {
383  goto bad;
384  }
385 
386  if (rz_buf_read_at(buffer, offset, (void *)element, header_size) != header_size) {
387  free(element);
388  goto bad;
389  }
390 
391  if (!dump_element(sb, pool, namespace, data, data_size, element,
392  resource_map, resource_map_length, &depth, true)) {
393  free(element);
394  goto bad;
395  }
396 
397  depth++;
398 
399  free(element);
400  break;
401  }
402  case TYPE_END_ELEMENT: {
403  depth--;
404  if (depth < 0) {
405  goto bad;
406  }
407 
409  if (rz_buf_read_at(buffer, offset, (void *)&end, sizeof(end)) != sizeof(end)) {
410  goto bad;
411  }
412 
413  // The beginning of the start and end element structs
414  // are the same, so we can use this interchangably
415  if (!dump_element(sb, pool, namespace, data, data_size, (start_element_t *)&end,
416  resource_map, resource_map_length, &depth, false)) {
417  goto bad;
418  }
419  break;
420  }
422  // If there is already a start namespace, override it
423  free(namespace);
424  namespace = malloc(sizeof(*namespace));
425  if (rz_buf_fread_at(buffer, offset, (ut8 *)namespace, "iiii", 1) != sizeof(*namespace)) {
426  goto bad;
427  }
428  break;
429  case TYPE_END_NAMESPACE:
430  break;
431  case TYPE_RESOURCE_MAP:
432  resource_map = (ut32 *)(data + offset);
433  resource_map_length = header.size;
434  if (resource_map_length > data_size - offset) {
435  goto bad;
436  }
437  resource_map_length /= sizeof(ut32);
438  break;
439  default:
440  RZ_LOG_WARN("Type is not recognized: %#x\n", type);
441  }
442 
443  offset += header.size - sizeof(header);
444  }
445 
447  free(pool);
448  free(namespace);
449  return rz_strbuf_drain(sb);
450 bad:
451  RZ_LOG_ERROR("Invalid Android Binary XML\n");
452 error:
453  if (buffer)
455  free(pool);
457  return NULL;
458 }
string_pool_t
Definition: axml.c:53
end_element_t
Definition: axml.c:98
static bool dump_element(RzStrBuf *sb, string_pool_t *pool, namespace_t *namespace, const ut8 *data, ut64 data_size, start_element_t *element, const ut32 *resource_map, ut32 resource_map_length, st32 *depth, bool start)
Definition: axml.c:221
@ TYPE_END_ELEMENT
Definition: axml.c:16
@ TYPE_STRING_POOL
Definition: axml.c:11
@ TYPE_START_ELEMENT
Definition: axml.c:15
@ TYPE_XML
Definition: axml.c:12
@ TYPE_RESOURCE_MAP
Definition: axml.c:17
@ TYPE_START_NAMESPACE
Definition: axml.c:13
@ TYPE_END_NAMESPACE
Definition: axml.c:14
static SblHeader sb
Definition: bin_mbn.c:26
#define NULL
Definition: cris-opc.c:27
uint16_t ut16
uint32_t ut32
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf uLong offset
Definition: ioapi.h:144
uint8_t ut8
Definition: lh5801.h:11
void * malloc(size_t size)
Definition: malloc.c:123
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")
#define header(is_bt, len_min, ret_op)
int type
Definition: mipsasm.c:17
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
RZ_API st64 rz_buf_read_at(RZ_NONNULL RzBuffer *b, ut64 addr, RZ_NONNULL RZ_OUT ut8 *buf, ut64 len)
Read len bytes of the buffer at the specified address.
Definition: buf.c:1136
RZ_API RZ_OWN RzBuffer * rz_buf_new_with_pointers(const ut8 *bytes, ut64 len, bool steal)
Creates a new buffer with a bytes array.
Definition: buf.c:552
RZ_API st64 rz_buf_fread_at(RZ_NONNULL RzBuffer *b, ut64 addr, RZ_NONNULL ut8 *buf, RZ_NONNULL const char *fmt, int n)
...
Definition: buf.c:1001
RZ_API void rz_buf_free(RzBuffer *b)
Free all internal data hold by the buffer and the buffer.
Definition: buf.c:1253
#define RZ_LOG_WARN(fmtstr,...)
Definition: rz_log.h:56
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API RZ_OWN char * rz_strbuf_drain(RzStrBuf *sb)
Definition: strbuf.c:342
RZ_API RzStrBuf * rz_strbuf_new(const char *s)
Definition: strbuf.c:8
RZ_API void rz_strbuf_free(RzStrBuf *sb)
Definition: strbuf.c:358
#define st32
Definition: rz_types_base.h:12
Definition: buffer.h:15
void error(const char *msg)
Definition: untgz.c:593
ut64(WINAPI *w32_GetEnabledXStateFeatures)()

References dump_element(), test_evm::end, end_element_t, error(), free(), header, malloc(), NULL, rz_buf_fread_at(), rz_buf_free(), rz_buf_new_with_pointers(), rz_buf_read_at(), RZ_LOG_ERROR, RZ_LOG_WARN, rz_return_val_if_fail, rz_strbuf_drain(), rz_strbuf_free(), rz_strbuf_new(), sb, st32, strdup(), string_pool_t, type, TYPE_END_ELEMENT, TYPE_END_NAMESPACE, TYPE_RESOURCE_MAP, TYPE_START_ELEMENT, TYPE_START_NAMESPACE, TYPE_STRING_POOL, TYPE_XML, and ut64().

Referenced by cmd_print_fromage().