Exemple #1
0
int CElfHlp::SaveText(char* outfile)
{
  FILE*f=fopen(outfile, "wb");
  if (f==NULL)
    return result = ERR_CANTCREATEFILE;
  for(DWORD i=0; i<len; )
  {
    if (flag[i] & FL_LABEL)
      fprintf(f, "[LABEL]\n");
    if (hdr == 0)
      fprintf(f, "%08X ", i);
    else
      fprintf(f, "%08X/.%08X ", i, offs2va(i));
    fprintf(f, "%s%s%s%s ",
      flag[i] & FL_EXEC     ? "E" : " ",
      flag[i] & FL_CODE     ? "C" : " ",
      flag[i] & (FL_INJECTED|FL_INJECTED_START) ? "I" : " ",
      flag[i] & (FL_FREE    |FL_FREE_START    ) ? "F" : " " );
    DWORD op_len = 1;
    if (flag[i] & FL_OPCODE)
      op_len = ade32_disasm(&buf[i], NULL);
    for(DWORD t=0; t<op_len; t++)
    {
      fprintf(f, " %02X", buf[i+t]);
      if (arg1 != 0)
      if (arg1[i+t] != 0)
        fprintf(f, "<%08X>", arg1[i+t]);
    }
    fprintf(f, "\n");
    i += op_len;
  }
  fprintf(f, "[EOF]\n");
  return result = ERR_SUCCESS;
} // CElfHlp::SaveText
Exemple #2
0
//搜索PsLookProcessThreadByCide函数, 取得未导出的PspCidTable地址
BOOLEAN
GetPspCidTableAddress()
{
    ULONG length, functionAddress, current;
    UNICODE_STRING functionName;

    //获得PsLookupProcessThreadByCid路径
    RtlInitUnicodeString(&functionName, 
                         L"PsLookupProcessThreadByCid");
    functionAddress = (ULONG)MmGetSystemRoutineAddress(&functionName);
    if(functionAddress == 0)
        return FALSE;

    //搜索 push    _PspCidTable指令, 获得PspCidTable地址
    current = functionAddress;
    length = 0;
    do{
        current += length;
        length = ade32_disasm((PVOID)current);
        if(length == 6 && (*(USHORT*)current == 0x35ff || *(USHORT*)current == 0x3d8b))
        {
            current += 2;
            PspCidTable = *(PVOID*)(*(ULONG*)current);
            return TRUE;
        }
    }while(length != 0 && current <= functionAddress + 0x100);

    return FALSE; 
}
Exemple #3
0
ADDERAPI unsigned long x86_get_instruction( void *python_ptr, x86_instruction *op )
{
	if ( !isInitialized ) {
		init_x86();
	}
	try {
		return ade32_disasm( (BYTE*)python_ptr, (disasm_struct*)op, ade32_flagtable );
	} catch (...) {
		return 0;
	}
}
Exemple #4
0
int CElfHlp::Inject(CElfHlp* S, DWORD hook_offs, DWORD in_flags)
{
  // check if valid hook offset

  if (hook_offs+16 > len)
    return result = ERR_BADHOOKOFFS;

  // find place for original bytes within code snippet

  DWORD orig_bytes = NONE;
  for(DWORD a=0; a<S->len; a++)
    if (memcmp(&S->buf[a], "$ORIGINAL_BYTES$", 16)==0)
    {
      memset(&S->buf[a], 0x90, 16);
      orig_bytes = a;
      break;
    }
  if (orig_bytes == NONE)
    return result = ERR_NOORIGBYTESSIGN;

  // copy opcodes from hook_offs into code snippet.
  // summary opcodes size must be >= 5 bytes, to place jmp

  DWORD link = 0;

  DWORD jmpback = NONE;
  for(DWORD ip=hook_offs; ip<len; )
  {
    if (OPT_DUMP)
      printf("orig opcode at %08X/.%08X\n", ip, offs2va(ip));

    if ((flag[ip] & FL_OPCODE) == 0)
      return result = ERR_NOTOPCODEATHOOK;

    disasm_struct diza;
    DWORD op_len = ade32_disasm(&buf[ip], &diza);
    if (op_len == 0)
      return result = ERR_INTERNAL1;

    if (diza.disasm_flag & (C_REL|C_STOP))
      return result = ERR_JMPRETATHOOK;

    ip += op_len;
    DWORD orig_len = ip - hook_offs;

    if (orig_len >= 5)      // 5 bytes for jmp to snippet
    {
      // copy original bytes
      memcpy(&S->buf[orig_bytes], &buf[hook_offs], orig_len);

      // fill original bytes with NOPs, check/setup flags
      for(DWORD t=hook_offs; t<hook_offs+orig_len; t++)
      {
        if ( (flag[t] & FL_FREE) || ((flag[t] & FL_CODE)==0) )
          return result = ERR_BADHOOKOFFS;
        flag[t] |= FL_OPCODE;
        arg1[t] = 0;
        buf[t] = 0x90;      // padd jmp to snippet with NOPs
      }

      // used to build jmp to snippet later
      link = hook_offs;

      // address to return back
      jmpback = hook_offs+5;

      break;
    }
  }
  if (jmpback == NONE)
    return result = ERR_INTERNAL2;

  // disassemble snippet

  if (S->DisasmSnippet() != ERR_SUCCESS)
    return result = S->result;

  // step 1 -- copy opcodes from snippet S into current file

  DWORD next_b = 0, next_sz = 0;

  for(DWORD a=0; a<S->len; )
  {
    if ((S->flag[a] & FL_OPCODE)==0)
      return result = ERR_INTERNAL3;

    disasm_struct diza;
    DWORD op_len = ade32_disasm(&S->buf[a], &diza);
    if (op_len == 0)
      return result = ERR_INTERNAL4;

    if ( (in_flags & IN_KILLNOP) &&
         (op_len == 1) &&
         (S->buf[a] == 0x90) &&
         ((S->flag[a] & FL_LABEL)==0) )
    {
      // skip NOP's
    }
    else
    {

      // replace short jxx'es with near ones

      BYTE new_op[32];
      memcpy(new_op, &S->buf[a], op_len);
      int new_op_len = op_len;
      DWORD rel_to = NONE;

      if (diza.disasm_flag & C_REL)
      {
        if ((diza.disasm_opcode & 0xFC) == 0xE0)
          return result = ERR_NOTSUPP;

        if ((diza.disasm_opcode & 0xF0) == 0x70)
        {
          new_op[0] = 0x0F;
          new_op[1] = diza.disasm_opcode ^ (0x70 ^ 0x80);
          new_op_len = 6;
        }
        if (diza.disasm_opcode == 0xEB)
        {
          new_op[0] = 0xE9;
          new_op_len = 5;
        }

        if (diza.disasm_datasize == 1) rel_to = a + op_len + diza.disasm_data_c[0];
        if (diza.disasm_datasize == 2) rel_to = a + op_len + diza.disasm_data_s[0];
        if (diza.disasm_datasize == 4) rel_to = a + op_len + diza.disasm_data_l[0];
      }

      // search for suitable free space area

      DWORD need_size = new_op_len + (diza.disasm_flag & C_STOP ? 0 : 5);

      if ((next_b != 0) && (next_sz < need_size))
        next_b = next_sz = 0;

      DWORD szS  = need_size;
      DWORD szE  = MaxIslandLen+1;
      int   szST = 1;
      if (in_flags & IN_BIGFIRST)
      {
        szS  = MaxIslandLen;
        szE  = need_size-1;
        szST = -1;
      }

      for(DWORD sz=szS; sz!=szE; sz+=szST)
      for(DWORD b=0; b<len; b++)
      {
        // start of free area?
        if ( ((flag[b] & FL_FREE_START) && (arg1[b] == sz)) ||
             (next_b != 0) )
        {
          if (next_b != 0) { b = next_b; sz = next_sz; };
          next_b = next_sz = 0;

          // if required, set link from previous island to current

          if (link != 0)
          {
            if (OPT_DUMP)
              printf("link  : %08X/.%08X  jmp_to=%08X/.%08X\n",
                link, offs2va(link), b, offs2va(b) );

            // jmp - set new flags
            for(DWORD t=0; t<5; t++)
            {
              flag[link+t] |= FL_CODE | FL_INJECTED;
              arg1[link+t] = 0;
            }
            flag[link+0] |= FL_OPCODE | FL_INJECTED_START;
            flag[link+4] |= FL_OPCODE_END;

            // jmp - build bytes
            buf[link+0] = 0xE9;
            *(DWORD*)&buf[link+1] = offs2va(b) - offs2va(link+5);

            // link fixed
            link = 0;
          }

          // copy opcode from snippet to file

          if (OPT_DUMP)
            printf("opcode: %08X/.%08X  snippet=%08X new_op_len=%d free_len=%d rel_to=%08X\n",
              b, offs2va(b), a, new_op_len, sz, rel_to );

          // clear old flags
          for(DWORD t=b; t<b+sz; t++)
          {
            flag[t] &= ~(FL_FREE_START | FL_FREE | FL_OPCODE | FL_CODE);
            arg1[t] = 0;
          }

          // orig opcode - copy bytes
          memcpy(&buf[b], new_op, new_op_len);

          // orig opcode - set new flags
          for(DWORD t=b; t<b+new_op_len; t++)
            flag[t] |= FL_CODE | FL_INJECTED;
          flag[b] |= FL_OPCODE | FL_INJECTED_START;
          flag[b+new_op_len-1] |= FL_OPCODE_END;
          arg1[b] = a;

          // build jmp back to original bytes + 5
          if ( (new_op_len == 5) &&
               (buf[b]==0xBC) &&        // mov esp, 0aa55aa55h
               (*(DWORD*)&buf[b+1] == 0xAA55AA55) )
          {
            if (OPT_DUMP)
              printf("jmpback: %08X/.%08X jmpto=%08X/.%08X\n",
                b, offs2va(b), jmpback, va2offs(jmpback));

            buf[b+0] = 0xE9;
            *(DWORD*)&buf[b+1] = offs2va(jmpback) - offs2va(b+5);
          }

          // if opcode has relative argument, mark it to fix on step 2
          if (diza.disasm_flag & C_REL)
          {
            flag[b+new_op_len-4] |= FL_FIXREL;
            *(DWORD*)&buf[b+new_op_len-4] = rel_to;
          }

          // remember address to fix link
          if ((diza.disasm_flag & C_STOP) == 0)
            link = b + new_op_len;

          // check if we can place next opcode into the same island
          if (a+op_len < S->len)
          {
            disasm_struct diza2;
            DWORD op_len2 = ade32_disasm(&S->buf[a+op_len], &diza2);
            if (op_len2 == 0)
              return result = ERR_INTERNAL5;
            if ( sz - new_op_len >= op_len2+5 )
            if (((diza2.disasm_flag & C_REL)==0)||(diza2.disasm_datasize == 4))
            {
              next_b  = b  + new_op_len;
              next_sz = sz - new_op_len;
//            printf("***NEXT*** sz=%d\n", next_sz);
            }
          }

          goto linked;
        }
      }//for sz,b

      return result = ERR_NOSPACE;
linked: ;
    }

    // go to the next snippet's opcode
    a += op_len;

  }//for a -- for each opcode within code snippet S

  // step 2 -- fix relative jmps

  for(DWORD b=0; b<len; b++)
  if (flag[b] & FL_FIXREL)
  {
    flag[b] &= ~FL_FIXREL;

    DWORD rel_to = *(DWORD*)&buf[b];
    DWORD link_to = 0;
    for(DWORD t=0; t<len; t++)
    if (flag[t] & FL_INJECTED_START)
    if (arg1[t] == rel_to)
    {
      link_to = t;
      break;
    }
    if (link_to == 0)
      return result = ERR_INTERNAL6;

    if (OPT_DUMP)
      printf("fixjmp: %08X/.%08X link_to=%08X/.%08X\n",
        b, offs2va(b), link_to, offs2va(link_to) );

    *(DWORD*)&buf[b] = offs2va(link_to) - offs2va(b+4);
  }//for b

  // done

  return result = ERR_SUCCESS;
} // CElfHlp::Inject
Exemple #5
0
int CElfHlp::DisasmSnippet()
{
  hdr = 0;

  DWORD ip = 0;

  for(;;)
  {
    if (OPT_DUMP)
      printf("  %08X  ", ip);

    // disassemble opcode
    disasm_struct diza;
    DWORD op_len = ade32_disasm(&buf[ip], &diza);
    if (op_len == 0)
    {
      if (OPT_DUMP)
        printf("break: disasm error\n");
      return result = ERR_DISASM;
    }

    if (OPT_DUMP)
    {
      for(DWORD t=0; t<op_len; t++)
        printf(" %02X", buf[ip+t]);
      printf("\n");
    }

    // check if special flags are present within current opcode.
    for(DWORD t = 1; t < op_len; t++)
      if (flag[ip + t] & (FL_LABEL | FL_CODE | FL_OPCODE | FL_ANALYZED))
      {
        if (OPT_DUMP)
          printf("quit: ERR_DISASM\n");
        return result = ERR_DISASM;
      }

    // after each opcode, flow can have 2 ways
    // (jmp/call tables are not processed yet)

    DWORD nxt = ip + op_len;    // normal way
    DWORD rel = NONE;           // jmp,call,jxx-way

    if (diza.disasm_flag & C_REL)  // have relative arg?
    {
      if (diza.disasm_datasize == 1) // jcc,jcxz,loop/z/nz,jmps
        rel = nxt + diza.disasm_data_c[0];
      if (diza.disasm_datasize == 4) // jcc near,call,jmp
        rel = nxt + diza.disasm_data_l[0];
    }

    // process both ways

    if (rel != NONE)
    {
      if (rel > len)
      {
        if (OPT_DUMP)
          printf("break: rel out of range\n");
        return result = ERR_DISASM;
      }

      // ptr into the middle of the opcode?
      if ( (flag[rel] & FL_CODE) && (!(flag[rel] & FL_OPCODE)) )
      {
        if (OPT_DUMP)
          printf("break: ptr into the middle of the opcode\n");
        return result = ERR_DISASM;
      }

      flag[rel] |= FL_LABEL;
    }

    // set flags for current opcode

    for(DWORD t = 0; t < op_len; t++)
    {
      flag[ip + t] |= FL_CODE | FL_ANALYZED;
      flag[ip + t] &= ~(FL_OPCODE | FL_NEXT);
    }
    flag[ip] |= FL_OPCODE;
    flag[ip + op_len - 1] |= FL_OPCODE_END;

    // if jmp-alike, swap nxt & rel, to follow jmp's label immediately

    if ((nxt == NONE) && (rel != NONE))
      nxt = rel;

    // go next opcode

    if (nxt == NONE)
    {
      if (OPT_DUMP)
        printf("break: STOP\n");
      break;
    }
    if (nxt > len)
    {
      if (OPT_DUMP)
        printf("break: nxt out of range\n");
      return result = ERR_DISASM;
    }

    ip = nxt;

    if (ip == len)
    {
      if (OPT_DUMP)
        printf("break: eof\n");
      break;
    }

  } // cycle until eof

  return result = ERR_SUCCESS;
} // CElfHlp::DisasmSnippet
Exemple #6
0
int CElfHlp::Analyze()
{
  // allocate additional array(s)

  arg1 = new DWORD[ len+1 ];
  if (arg1 == NULL)
    return result = ERR_NOMEMORY;
  memset(arg1, 0x00, (len+1)*4);

  // analyze padding

  DWORD n_total = 0;
  DWORD n_island[MAX_ISLAND_LEN+1] = {0};

  for(DWORD a=0; a<len; a++)
  if (flag[a] & FL_OPCODE)
  {
    disasm_struct diza;                           // if jmp/ret-alike
    ade32_disasm(&buf[a], &diza);                 //
    if (diza.disasm_flag & C_STOP)                //
    {
      while((flag[a] & FL_OPCODE_END)==0) a++;    // skip over last opcode
      a++;                                        //
      DWORD b = (a + 15) & 0xFFFFFFF0;            // assume align 16
      DWORD c = b - a;
      if ((c >= 2) && (c <= 15))       // need 5 bytes for jmp, or less
      if (flag[b] & FL_LABEL)          // in some special cases
      if (flag[b] & FL_OPCODE)
      {
        // verify its alignment
        int is_alignment = 1;
        for(DWORD i=a; i<b; i++)
        if (flag[i] & FL_CODE)
        {
          is_alignment = 0;
          break;
        }
        if (*(WORD*)&buf[b-2] != 0x0000)
        if (*(WORD*)&buf[b-2] != 0x9090)
          is_alignment = 0;
        if (is_alignment)
        {
          if (OPT_DUMP)
            printf("padd: %08X/.%08X  len=%d\n", a, offs2va(a), c);

          flag[a] |= FL_FREE_START;
          arg1[a] = c;
          for(DWORD t=a; t<b; t++)
            flag[t] |= FL_FREE;

          n_island[c]++;
          n_total += c;

          a += c - 1;
        }
      }
    }
  }//for a

  // analyze Exp$

  for(DWORD a=0; a<len-16; a+=4)        // ALIGN 4
  {
    if (flag[a] & FL_EXEC) // probably can be removed to use Exp$ in data
    if ( (memcmp(&buf[a], "$FreeBSD: ", 10)==0) ||
         (memcmp(&buf[a], "$NetBSD:  ", 9 )==0) )
    {
      DWORD c = (unsigned)strlen((char*)&buf[a])+1;
      if (c > MAX_ISLAND_LEN) c = MAX_ISLAND_LEN; // only for counting
      if (MaxIslandLen < c) MaxIslandLen = c;   // update MaxIslandLen

      if (OPT_DUMP)
        printf("Exp$: %08X/.%08X  len=%d\n", a, offs2va(a), c);

      flag[a] |= FL_FREE_START;
      arg1[a] = c;
      for(DWORD t=0; t<c; t++)
        flag[a+t] |= FL_FREE;

      n_island[c]++;
      n_total += c;
    }
  }

  // dump found "islands" statistics

  if (n_total != 0)
  {
    printf("isl.sz");
    for(DWORD n=2; n<=MaxIslandLen; n++)
      if (n_island[n])
        printf(" %4d", n);
    printf("\n");
    printf("isl.# ");
    for(DWORD n=2; n<=MaxIslandLen; n++)
      if (n_island[n])
        printf(" %4d", n_island[n]);
    printf("\n");
  }
  printf("total free space = %d bytes\n", n_total);

  // done

  /*
  FILE*f=fopen("_stat","wb");
  for(DWORD i=0; i<len; i++)
  if (flag[i] & FL_FREE_START)
  {
    fprintf(f, "%3d ", arg1[i]);
    for(DWORD j=0; j<arg1[i]; j++)
      fprintf(f," %02X", buf[i+j]);
    fprintf(f, "\n");
  }
  fclose(f);
  */

  return result = ERR_SUCCESS;
} // CElfHlp::Analyze
Exemple #7
0
int CElfHlp::DisasmELF(DWORD df_flags)
{
  // check file format

  if (len < 1024)
    return result = ERR_TOOSMALLFILE;

  hdr = (PELF32_HEADER) buf;

  if ( (hdr->e_ident[EI_MAG0]    != 0x7F       ) ||
       (hdr->e_ident[EI_MAG1]    != 'E'        ) ||
       (hdr->e_ident[EI_MAG2]    != 'L'        ) ||
       (hdr->e_ident[EI_MAG3]    != 'F'        ) ||
       (hdr->e_ident[EI_CLASS]   != ELFCLASS32 ) ||
       (hdr->e_ident[EI_DATA]    != ELFDATA2LSB) ||
       (hdr->e_ident[EI_VERSION] != EV_CURRENT ) ||
       (hdr->e_type              != ET_EXEC    ) ||
       (hdr->e_machine           != EM_386     ) ||
       (hdr->e_version           != EV_CURRENT ) ||
       (hdr->e_flags             != 0          ) )
    return result = ERR_BADFILEFORMAT;

  // mark entry point

  if (hdr->e_entry != 0)
  {
    DWORD entry_offs = va2offs(hdr->e_entry);
    if (entry_offs < len)
      flag[entry_offs] |= FL_LABEL | FL_NEXT;
  }

  // for each section

  for(int i=0; i<hdr->e_shnum; i++)
  {
    // make ptr to section header

    PELF32_SH sh = (PELF32_SH) &buf[ hdr->e_shoff + i * hdr->e_shentsize ];

    // mark section attribs

    if (sh->sh_offset != 0)
    if (sh->sh_size   != 0)
    if ((sh->sh_flags & (SHF_ALLOC|SHF_EXECINSTR)) == (SHF_ALLOC|SHF_EXECINSTR))
    for(DWORD t = sh->sh_offset; t < sh->sh_offset + sh->sh_size; t++)
      if ( (t >= 0) && (t < len) )
        flag[t] |= FL_EXEC;

    // check if symbols

    if (df_flags & DF_SYM)
    if ( (sh->sh_type == SHT_SYMTAB) ||
         (sh->sh_type == SHT_DYNSYM) )
    {

      // for each symbol entry

      for(DWORD j=0; j<sh->sh_size/sh->sh_entsize; j++)
      {
        PELF32_SYM st = (PELF32_SYM) &buf[ sh->sh_offset + j * sh->sh_entsize ];

        // mark functions

        if (ELF32_ST_TYPE(st->st_info) == STT_FUNC)
        {
          DWORD func_offs = va2offs(st->st_value);
          if (func_offs < len)
          {
            if (OPT_DUMP)
            if (OPT_DUMP)
              printf("offs/va=%08X/.%08X sect=[%s] symbol=[%s]\n",
                func_offs,
                st->st_value,
                IS_SPECIAL_SHN(st->st_shndx) ? "" : (char*)&buf[ ((PELF32_SH)&buf[ hdr->e_shoff + hdr->e_shstrndx * hdr->e_shentsize ])->sh_offset + ((PELF32_SH)&buf[ hdr->e_shoff + st->st_shndx * hdr->e_shentsize])->sh_name ],
                (char*)&buf[ ((PELF32_SH)&buf[ hdr->e_shoff + sh->sh_link     * hdr->e_shentsize ])->sh_offset + st->st_name ] );

            flag[func_offs] |= FL_LABEL | FL_NEXT;
          }
        }

      } // for j -- for each symbol

    } // SHT_SYMTAB || SHT_DYNSYM

    // check if .got

    if (df_flags & DF_GOT)
    if (strcmp((char*)&buf[ ((PELF32_SH) &buf[ hdr->e_shoff + hdr->e_shstrndx * hdr->e_shentsize ])->sh_offset + sh->sh_name ], ".got")==0)
    {
      // for each offset
      for(DWORD t = sh->sh_offset; t < sh->sh_offset + sh->sh_size; t += 4)
      if (t < len)
      {
        DWORD va = *(DWORD*)&buf[ t ];
        if ((va != 0) && ((va & 3)==0))
        {
          DWORD offs = va2offs(va);
          if (offs < len)
          if (flag[offs] & FL_EXEC)
          {
            if (OPT_DUMP)
              printf(".got entry: marked next at offs/va=%08X/.%08X\n", offs, va );
            flag[offs] |= FL_NEXT;
          }
        }
      } // for t -- for each offset

    } // .got

  } // for i -- for each section

  // find & mark subroutines

  if (df_flags & DF_FUNC)
  for(DWORD t=0; t<len; t+=4)
  {
    // push ebp
    // mov  ebp, esp
    // ~ to avoid fail on self
    if ( (~(*(DWORD*)&buf[t] & 0x00FFFFFF) == ~0x00EC8B55U) ||
         (~(*(DWORD*)&buf[t] & 0x00FFFFFF) == ~0x00E58955U) )
    {
      if (OPT_DUMP)
        printf("SUBROUTINE sign: marked next at offs/va=%08X/.%08X\n", t, offs2va(t) );
      flag[t] |= FL_NEXT;
    }
  } // for t

  // find & mark jmp tables

  if (df_flags & DF_JMPTAB)
  for(DWORD t = 0; t < len; t++)
  if (flag[t] & FL_EXEC)            // search within executable sections
  {
    // jmp dword ptr [reg32*4+imm32]
    if (*(WORD*)&buf[t+0] == 0x24FF)
    if ((buf[t+2]&0xC7)==0x85)
    if (buf[t+2]!=0xA5)             // reg32 != ESP -- special
    {
      DWORD jtab_va = *(DWORD*)&buf[t+3];
      for(DWORD jtab_offs = va2offs(jtab_va); jtab_offs < len; jtab_offs += 4)
      {
        DWORD f_va   = *(DWORD*)&buf[ jtab_offs ];
        DWORD f_offs = va2offs(f_va);
        if (f_offs >= len) break;
        if ((f_va & 3) == 0)
        if (flag[f_offs] & FL_EXEC)
        if ((flag[f_offs] & FL_ANALYZED) == 0)
        {
          if (OPT_DUMP)
            printf("JMPTAB: marked next at offs/va=%08X/.%08X\n", f_offs, f_va );
          flag[f_offs] |= FL_NEXT;
        }
      }
    }
  } // for t -- for each byte

  // disasm

  for(;;)       // main disasm cycle
  {

    // current instruction pointer
    DWORD ip = 0;

    // find FL_NEXT (code marked for future analysis)
    for(DWORD t = 0; t < len; t++)
    if (flag[t] & FL_NEXT)
    {
      ip = t;
      break;
    }

    // if FL_NEXT not found, search for relative-references to labels

    if (df_flags & DF_RELREF)
    if (ip == 0)
    {
      for(DWORD t = 0; t < len; t++)     // for each byte
      if (flag[t] & FL_EXEC)             // within executable section
      if ((flag[t] & FL_ANALYZED) == 0)  // which has not been analyzed yet
      {
        DWORD rel = NONE, arg = 0;
        BYTE o = buf[t];
        WORD w = *(WORD*)&buf[t];
        if ((w&0xF0FF)==0x800F)
        {
          arg = (long)(*(DWORD*)&buf[t + 2]);
          rel = OFFS_PLUS_REL(t, 6 + arg);
        }
        if ((o==0xE8)||(o==0xE9))
        {
          arg = (long)(*(DWORD*)&buf[t + 1]);
          rel = OFFS_PLUS_REL(t, 5 + arg);
        }
        if (arg & 0xFFFFFF00)
        if (rel < len)
        if ( (flag[rel] & (FL_LABEL|FL_EXEC))==(FL_LABEL|FL_EXEC) )
        {
          if (OPT_DUMP)
            printf("REL REF: marked next at offs/va=%08X/.%08X\n", t, offs2va(t) );
          flag[t] |= FL_NEXT;
          ip = t;
        }
      } // for t
    }

    if (ip == 0)
    {
      if (OPT_DUMP)
        printf("break: done\n");
      break;
    }

    // now we have FL_NEXT at ip

    if (OPT_DUMP)
      printf("NEXT at offs/va=%08X/.%08X\n", ip, offs2va(ip));

    for(;;)
    {
      flag[ip] &= ~FL_NEXT;             // remove FL_NEXT
      flag[ip] |= FL_ANALYZED;          // set FL_ANALYZED

      if (ip == 0) break;                       // troubl?

      // check typical situation on bsd elf's: call exit; db '...exp$...'
      if ((ip & 3) == 0)                // ALIGN 4
      if ( (memcmp(&buf[ip], "$FreeBSD: ", 10)==0) ||
           (memcmp(&buf[ip], "$NetBSD: " , 9 )==0) )
      {
        if (OPT_DUMP)
          printf("break: Exp$\n");
        break;
      }
      //

      if (OPT_DUMP)
        printf("  %08X/.%08X  ", ip, offs2va(ip));

      // disassemble opcode
      disasm_struct diza;
      DWORD op_len = ade32_disasm(&buf[ip], &diza);
      if (op_len == 0)
      {
        if (OPT_DUMP)
          printf("break: disasm error\n");
        break;                      // disasm error
      }

      if (OPT_DUMP)
      {
        for(DWORD t=0; t<op_len; t++)
          printf(" %02X", buf[ip+t]);
        printf("\n");
      }

      // C_BAD flag has been designed for win32 PE files, using PE_STAT.
      // todo: do the same for ELF files
      //if (diza.disasm_flag & C_BAD) break;

      // check if special flags are present within current opcode.
      for(DWORD t = 1; t < op_len; t++)
        if (flag[ip + t] & (FL_LABEL | FL_CODE | FL_OPCODE | FL_ANALYZED))
        {
          if (OPT_DUMP)
            printf("quit: ERR_DISASM (offs=%08X,flag=%08X)\n",
              ip+t, flag[ip+t]);
          return result = ERR_DISASM;
        }

      // after each opcode, flow can have 2 ways
      // (jmp/call tables are not processed yet)

      DWORD nxt = ip + op_len;    // normal way
      DWORD rel = NONE;           // jmp,call,jxx-way

      if (diza.disasm_flag & C_REL)  // have relative arg?
      {
        if (diza.disasm_datasize == 1) // jcc,jcxz,loop/z/nz,jmps
          rel = OFFS_PLUS_REL(nxt, diza.disasm_data_c[0]);
        if (diza.disasm_datasize == 4) // jcc near,call,jmp
          rel = OFFS_PLUS_REL(nxt, diza.disasm_data_l[0]);
      }

      // ret/ret#/retf/retf#/iret/jmp modrm ?
      if (diza.disasm_flag & C_STOP)
        nxt = NONE;

      // process both ways

      if (rel != NONE)
      {
        if (rel >= len)
        {
          if (OPT_DUMP)
            printf("break: rel out of range\n");
          break;          // out of range?
        }

        // ptr into the middle of the opcode?
        if ( (flag[rel] & FL_CODE) && (!(flag[rel] & FL_OPCODE)) )
        {
          if (OPT_DUMP)
            printf("break: ptr into the middle of the opcode\n");
          break;
        }

        flag[rel] |= FL_LABEL;
        if ((flag[rel] & FL_ANALYZED) == 0)
        {
          if (OPT_DUMP)
            printf("REL: marked next at offs/va=%08X/.%08X\n", rel, offs2va(rel) );
          flag[rel] |= FL_NEXT;
        }
      }

      // set flags for current opcode

      for(DWORD t = 0; t < op_len; t++)
      {
        flag[ip + t] |= FL_CODE | FL_ANALYZED;
        flag[ip + t] &= ~(FL_OPCODE | FL_NEXT);
      }
      flag[ip] |= FL_OPCODE;
      flag[ip + op_len - 1] |= FL_OPCODE_END;

      // if jmp-alike, swap nxt & rel, to follow jmp's label immediately

      if ((nxt == NONE) && (rel != NONE))
        nxt = rel;

      // go next opcode

      if (nxt == NONE)
      {
        if (OPT_DUMP)
          printf("break: STOP\n");
        break;
      }
      if (nxt >= len)
      {
        if (OPT_DUMP)
          printf("break: nxt out of range\n");
        break;                     // out of range?
      }

      ip = nxt;

      if (flag[ip] & FL_CODE)
      {
        if (OPT_DUMP)
          printf("break: already code\n");
        break;            // meet code ?
      }

    } // cycle until RET/troubl

  } // main disasm cycle

  return result = ERR_SUCCESS;
} // CElfHlp::DisasmELF
Exemple #8
0
void main()
{
  make_bin();

  DWORD ade32_flagtable[512];
  ade32_init(ade32_flagtable);

  for(DWORD i=0x401000; ; )
  {
    disasm_struct s = {4,4};

    DWORD c = ade32_disasm((BYTE*)i, &s, ade32_flagtable);
    if (c==0)
    {
      printf("(0) %08X  %02X %02X %02X %02X ...\n", i,*(BYTE*)(i+0),*(BYTE*)(i+1),*(BYTE*)(i+2),*(BYTE*)(i+3));
      break;
    }

    assert(c==s.disasm_len);

    printf("(%i) %08X ",c,i);
    for(DWORD j=0; j<c; j++) printf(" %02X",*(BYTE*)(i+j));

    for(DWORD j=c; j<8; j++) printf("   ");
    printf("[");
    if (s.disasm_flag&C_BAD)     printf(" ***C_BAD***");
    if (s.disasm_flag&C_SEG)     printf(" C_SEG");
    if (s.disasm_flag&C_LOCK)    printf(" C_LOCK");
    if (s.disasm_flag&C_REP)     printf(" C_REP");
    if (s.disasm_flag&C_67)      printf(" C_67");
    if (s.disasm_flag&C_66)      printf(" C_66");
    if (s.disasm_flag&C_OPCODE2) printf(" C_OPCODE2");
    if (s.disasm_flag&C_MODRM)   printf(" C_MODRM");
    if (s.disasm_flag&C_SIB)     printf(" C_SIB");
    if (s.disasm_flag&C_ADDR1)   printf(" C_ADDR1");
    if (s.disasm_flag&C_ADDR2)   printf(" C_ADDR2");
    if (s.disasm_flag&C_ADDR4)   printf(" C_ADDR4");
    if (s.disasm_flag&C_ADDR67)  printf(" C_ADDR67");
    if (s.disasm_flag&C_DATA1)   printf(" C_DATA1");
    if (s.disasm_flag&C_DATA2)   printf(" C_DATA2");
    if (s.disasm_flag&C_DATA4)   printf(" C_DATA4");
    if (s.disasm_flag&C_DATA66)  printf(" C_DATA66");
    if (s.disasm_flag&C_REL)     printf(" C_REL");
    if (s.disasm_flag&C_STOP)    printf(" C_STOP");
    printf(" ]\n");

    BYTE f**k[64]={0};
    DWORD f = ade32_asm(f**k, &s);

    if ( (f!=c)||( memcmp(f**k,(BYTE*)i,c)!=0 ) )
    {
      printf("(%i) %08X ",f,i);
      for(DWORD j=0; j<f; j++) printf(" %02X",f**k[j]);
      printf("  ; f**k[]\n");
      printf("flag=%08X\n", s.disasm_flag);
      exit(0);
    }

    i += c;
  }

}//main