Ejemplo n.º 1
0
static bool lc_dump_dyld_export_trie(char *trie, char *p, char *buf, uint32_t bufidx, uint32_t bufsize, lambchop_logger *logger) {
  uint64_t infolen = parse_uleb128(&p);
  uint8_t children;
  int i;

  if (infolen) {
    char *q = p + infolen;
    uint64_t flags = parse_uleb128(&p);
    uint64_t address;
    uint64_t kind = flags & EXPORT_SYMBOL_FLAGS_KIND_MASK;
    flags &= ~EXPORT_SYMBOL_FLAGS_KIND_MASK;
    buf[bufidx] = '\0';
    if (kind == EXPORT_SYMBOL_FLAGS_KIND_REGULAR) {
      address = parse_uleb128(&p);
      lambchop_info(logger,
                    "export_info: infolen = %llu, symbol = %s, flags = 0x%llx, kind=EXPORT_SYMBOL_FLAGS_KIND_REGULAR, address = %llx\n",
                    infolen, buf, flags, address);
    } else {
      lambchop_err(logger,
                   "unsupported export info: infolen = %llu, symbol = %s, flags = 0x%llx, kind=0x%llx\n",
                   infolen, buf, flags, kind);
      return false;
    }
    if (p != q) {
      lambchop_err(logger, "failed to parse export trie: infolen = %llu, flags = 0x%llx, kind = 0x%llx\n", infolen, flags, kind);
      return false;
    }
  }
  children = (uint8_t)(*p);
  p++;
  for (i = 0; i < children; i++) {
    int len = strlen(p);
    uint64_t offset;
    // TODO check bufsize
    memcpy(buf + bufidx, p, len);
    p += len + 1;
    offset = parse_uleb128(&p);
    if (!lc_dump_dyld_export_trie(trie, trie + offset, buf, bufidx + len, bufsize, logger)) {
      return false;
    }
  }
  return true;
}
Ejemplo n.º 2
0
static int64_t parse_sleb128(char **pp) {
  char *s, *e;
  uint64_t uleb;
  int n;

  s = *pp;
  uleb = parse_uleb128(pp);
  e = *pp;
  n = e - s;
  return (int64_t)(uleb - pow(128, n));
}
Ejemplo n.º 3
0
/* Parses the ARM attributes section's 'eabi' subsection */
int parse_eabi_attr_aeabi_subsection(int fd, off_t* pos, size_t sh_size, char wchar_size)
{
  unsigned long int attr, value;
  int ret;
  char buf[1024];
  
  if (sh_size < 1)
  {
    printf("Error: aeabi subsection too small.\n");
    return 1;
  }
  
  unsigned char tag;
  if (read(fd, &tag, sizeof(tag)) != sizeof(tag))
  {
    perror("reading aeabi subsection tag\n");
    return 1;
  }
  ++(*pos);
  
  // if tag = section or tag = symbol, skip over section/symbol identifiers
  if (tag == 2 || tag == 3)
  {
    unsigned long int id;
    do
    {
      ret = parse_uleb128(fd, &id, pos, sh_size);
      if (ret != 0)
        return ret;
    } while (id != 0);    
  }
  
  while (*pos < sh_size)
  {
    ret = parse_uleb128(fd, &attr, pos, sh_size);
    if (ret != 0)
      return ret;
      
    switch (attr)
    {
      case 4: // Tag_CPU_raw_name 
      case 5: // Tag_CPU_name 
      case 67: // Tag_conformance 
      case 32: // Tag_compatibility
        ret = parse_ntbs(fd, buf, sizeof(buf), pos, sh_size);
        if (ret != 0)
          return ret;
        break;
      case 18: // Tag_ABI_PCS_wchar_t
        ret = parse_uleb128(fd, &value, pos, sh_size);
        if (ret != 0)
          return ret;
        printf("Tag_ABI_PCS_wchar_t = %ld", value);
        if (wchar_size >= 0)
        {
          if (value > 0x7f)
          {
            // This utility does not support resizing structures
            printf("Error: Unable to patch Tag_ABI_PCS_wchar_t: old value is too big.\n");
          }
          if (lseek(fd, -1, SEEK_CUR) == (off_t)-1)
          {
            perror("seeking to patch");
            return 1;
          }
          if (write(fd, &wchar_size, sizeof(wchar_size)) != sizeof(wchar_size))
          {
            perror("patching");
            return 1;
          }
          printf(", patched to %d\n", wchar_size);
        }
        else
        {
          printf("\n");
        }
        break;
      default:
        // skip over tag -- for >32, we follow ARM's convention
        if (attr > 32)
        {
          if ((attr % 2) == 0) // even
            ret = parse_uleb128(fd, &value, pos, sh_size);
          else // odd
            ret = parse_ntbs(fd, NULL, 0, pos, sh_size);
        }
        else
        {
          // all NTBS tags are in the switch above; the rest are ULEB128
          ret = parse_uleb128(fd, &value, pos, sh_size);
        }
        if (ret != 0)
          return ret;
        break;
    }
  }
  
  return 0;
}
Ejemplo n.º 4
0
osrstats *parse_osr(const unsigned char *s, int len){
    osrstats *ret = malloc(sizeof(osrstats));

    unsigned char *p = (unsigned char *)s;
    const void *end = s+len;

#define INC(x) do { \
    p+=x; \
    if((const void*)p >= end) \
        goto fail; \
    } while(0);


    // mode
    ret->mode = *p;
    INC(1);

    // don't care
    INC(4);

    // osu file MD5
    if(*p != 0x0B) goto fail;
    INC(1);
    if(*p != 0x20) goto fail;
    INC(1);
    memcpy(&ret->md5_map, p, sizeof(MD5));
    INC(0x20);

    // user name
    {
        if(*p != 0x0B) goto fail;
        INC(1);
        // FIXME: username len > 128
        uint8_t len = *p;
        if(len >= 128) goto fail;
        INC(1);
        memcpy(&ret->username, p, len);
        ret->username[len] = 0;
        INC(len);
    }

    // replay MD5
    if(*p != 0x0B) goto fail;
    INC(1);
    if(*p != 0x20) goto fail;
    INC(1);
    memcpy(&ret->md5_osr, p, sizeof(MD5));
    INC(0x20);

    // Stats
    ret->n_300  = *(uint16_t *)p; INC(2);
    ret->n_100  = *(uint16_t *)p; INC(2);
    ret->n_50   = *(uint16_t *)p; INC(2);
    ret->n_geki = *(uint16_t *)p; INC(2);
    ret->n_katu = *(uint16_t *)p; INC(2); 
    ret->n_miss = *(uint16_t *)p; INC(2); 

    ret->score = *(uint32_t *)p; INC(4); 
    ret->max_combo = *(uint16_t *)p; INC(2); 
    ret->perfect = *(bool *)p; INC(1);
    ret->mods = *(uint32_t *)p; INC(4); 

    // HP Graph
    {
        if(*p != 0x0B) goto fail;
        INC(1);
        uint32_t len;
        int n = parse_uleb128(p, &len);
        INC(n);
        // TODO
        INC(len);
    }
    
    
    // Datetime
    uint64_t rawtime = *(uint64_t *)p - 621355968000000000;
    ret->achieve_time.tv_sec = rawtime / 10000000;
    ret->achieve_time.tv_usec = rawtime % 10000000;
    INC(8)

    return ret;

#undef INC

fail:
    free(ret);
    return NULL;
}
Ejemplo n.º 5
0
static bool lc_dump_dyld_bind_info(uint32_t offset, uint32_t size, char *img, lambchop_logger *logger) {
  char *bind_info = img + offset;
  char *p = bind_info;
  if (!size) {
    return true;
  }
  while (p < (bind_info + size)) {
    uint8_t opcode = *p & BIND_OPCODE_MASK;
    uint8_t immediate = *p & BIND_IMMEDIATE_MASK;
    const char *type;
    int64_t sleb;
    uint64_t uleb, uleb2;
    p++;
    switch(opcode) {
      case BIND_OPCODE_DONE:
        return true;
      case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
        lambchop_info(logger, "bind_info: op=BIND_OPCODE_SET_DYLIB_ORDINAL_IMM ordinal=%d\n", immediate);
        break;
      case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
        uleb = parse_uleb128(&p);
        lambchop_info(logger, "bind_info: op=BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB ordinal=%d\n", uleb);
        break;
      case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
        lambchop_info(logger,
                      "bind_info: op=BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM flags=0x%x, symbol = %s\n",
                      immediate, p);
        p += strlen(p) + 1;
        break;
      case BIND_OPCODE_SET_TYPE_IMM:
        type = bind_type(immediate);
        if (!type) {
          lambchop_err(logger, "unsupported bind type 0x%x\n", immediate);
          return false;
        }
        lambchop_info(logger, "bind_info: op=BIND_OPCODE_SET_TYPE_IMM type=%s\n", type);
        break;
      case BIND_OPCODE_SET_ADDEND_SLEB:
        sleb = parse_sleb128(&p);
        lambchop_info(logger, "bind_info: op=BIND_OPCODE_SET_ADDEND_SLEB addend=%lld\n", sleb);
        break;
      case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
        uleb = parse_uleb128(&p);
        lambchop_info(logger,
                      "bind_info: op=BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB segment=%d offset=0x%x\n",
                      immediate, uleb);
        break;
      case BIND_OPCODE_ADD_ADDR_ULEB:
        uleb = parse_uleb128(&p);
        lambchop_info(logger, "bind_info: op=BIND_OPCODE_ADD_ADDR_ULEB offset=0x%x\n", uleb);
        break;
      case BIND_OPCODE_DO_BIND:
        lambchop_info(logger, "bind_info: op=BIND_OPCODE_DO_BIND\n");
        break;
      case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
        uleb = parse_uleb128(&p);
        lambchop_info(logger, "bind_info: op=BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB offset=0x%x\n", uleb);
        break;
      case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
        lambchop_info(logger, "bind_info: op=BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED offset=0x%x\n", immediate);
        break;
      case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
        uleb = parse_uleb128(&p);
        uleb2 = parse_uleb128(&p);
        lambchop_info(logger,
                      "bind_info: op=BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB, times=%d, offset=0x%x\n",
                      uleb, uleb2);
        break;
      default:
        lambchop_err(logger, "unsupported bind info opcode 0x%x\n", opcode);
        return false;
    }
  }
  lambchop_err(logger, "BIND_OPCODE_DONE not found\n");
  return false;
}
Ejemplo n.º 6
0
static bool lc_dump_dyld_rebase_info(struct dyld_info_command *command, char *img, lambchop_logger *logger) {
  char *rebase_info = img + command->rebase_off;
  char *p = rebase_info;
  int i;
  if (!command->rebase_size) {
    return true;
  }
  while (p < (rebase_info + command->rebase_size)) {
    uint8_t opcode = *p & REBASE_OPCODE_MASK;
    uint8_t immediate = *p & REBASE_IMMEDIATE_MASK;
    uint64_t uleb, uleb2;
    const char *type;
    p++;
    switch(opcode) {
      case REBASE_OPCODE_DONE:
        return true;
      case REBASE_OPCODE_SET_TYPE_IMM:
        /*REBASE_TYPE_POINTER: ポインタの中身を書き換える*/
        type = rebase_type(immediate);
        if (!type) {
          lambchop_err(logger, "unsupported rebase type 0x%x\n", immediate);
          return false;
        }
        lambchop_info(logger, "rebase_info: op=REBASE_OPCODE_SET_TYPE_IMM type=%s\n", type);
        break;
      case REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
        /*
         * どのセグメントのどのオフセットを書き換えるかを指定する。
         * この命令ではセグメントのインデックスを immediate によって与える。
         * セグメントのインデックスは0から数える。
         * セグメントのインデックスが2だった場合は3つ目のセグメント。
         */
        uleb = parse_uleb128(&p);
        lambchop_info(logger,
                      "rebase_info: op=REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB, segment=%u, offset=0x%x\n",
                      immediate, uleb);
        break;
      case REBASE_OPCODE_ADD_ADDR_ULEB:
        uleb = parse_uleb128(&p);
        lambchop_info(logger, "rebase_info: op=REBASE_OPCODE_ADD_ADDR_ULEB, offset = 0x%x\n", uleb);
        break;
      case REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
        lambchop_info(logger, "rebase_info: op=REBASE_OPCODE_ADD_ADDR_IMM_SCALED, immediate = 0x%x\n", immediate);
        break;
      case REBASE_OPCODE_DO_REBASE_IMM_TIMES:
        /*
         * 指定した回数 segment の offset の rebase を繰り返す。
         * 書き換えるべき値は毎回ポインタのサイズ分だけずれる(REBASE_TYPE_POINTER の場合)。
         * segment や offset には REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB などで指定された値を用いる。
         * この命令では繰り返しの回数は immediate によって与えられる。
         */
        lambchop_info(logger, "rebase_info: op=REBASE_OPCODE_DO_REBASE_IMM_TIMES, times=%d\n", immediate);
        break;
      case REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
        uleb = parse_uleb128(&p);
        lambchop_info(logger, "rebase_info: op=REBASE_OPCODE_DO_REBASE_ULEB_TIMES, times=%d\n", uleb);
        break;
      case REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
        /*
         * rebase を実行した後に、uleb でのアドレス加算を行う。
         */
        uleb = parse_uleb128(&p);
        lambchop_info(logger,
                      "rebase_info: op=REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB, immediate=0x%x, offset=0x%x\n",
                      immediate, uleb);
        break;
      case REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
        /**
         * rebase を最初のuleb128回繰り返す。繰り返しの度に次のuleb128回オフセットをずらす。
         */
        uleb = parse_uleb128(&p);
        uleb2 = parse_uleb128(&p);
        lambchop_info(logger,
                      "rebase_info: op=REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB, times=%d, offset=0x%x\n",
                      uleb, uleb2);
        break;
      default:
        lambchop_err(logger, "unsupported rebase info opcode 0x%x\n", opcode);
        return false;
    }
  }
  lambchop_err(logger, "REBASE_OPCODE_DONE not found\n");
  return false;
}