Beispiel #1
0
size_t 
VtableScanner::getVtableMethodsCount (
    ea_t curAddress
) {
    ea_t startTable = BADADDR;
    ea_t curEntry = 0;

    // Iterate until we find a result
    for (; ; curAddress += 4) 
    {
        flags_t flags = IDAUtils::GetFlags (curAddress);

        // First iteration
        if (startTable == BADADDR) {
            startTable = curAddress;
            if (!(hasRef (flags) && (has_name (flags) || (flags & FF_LABL)))) {
                // Start of vtable should have a xref and a name (auto or manual)
                return 0;
            }
        }
        else if (hasRef (flags)) {
            // Might mean start of next vtable
            break;
        }
        
        if (!hasValue (flags) || !isData (flags)) {
            break;
        }
        
        if ((curEntry = get_long (curAddress))) {
            flags = IDAUtils::GetFlags (curEntry);
            
            if (!hasValue (flags) || !isCode (flags) || get_long (curEntry) == 0) {
                break;
            }
        }
    }

    
    if (startTable != BADADDR) {
        return (curAddress - startTable) / 4;
    }
    
    else {
        // No vtable at this EA
        return 0;
    }
}
Beispiel #2
0
// check and create a flat 32 bit jump table -- the most common case
static void check_and_create_flat32(
        jump_table_type_t /*jtt*/,
        switch_info_ex_t &si)
{
  // check the table contents
  ea_t table = si.jumps;
  segment_t *s = getseg(table);
  if ( s == NULL )
    return;
  size_t maxsize = size_t(s->endEA - table);
  int size = si.ncases;
  if ( size > maxsize )
    size = (int)maxsize;

  int i;
  insn_t saved = cmd;
  for ( i=0; i < size; i++ )
  {
    ea_t ea = table + 4*i;
    flags_t F = getFlags(ea);
    if ( !hasValue(F) )
      break;
    if ( i && (has_any_name(F) || hasRef(F)) )
      break;
    ea_t target = segm_adjust_ea(getseg(table), si.elbase + get_long(ea));
    if ( !isLoaded(target) )
      break;
    flags_t F2 = get_flags_novalue(target);
    if ( isTail(F2) || isData(F2) )
      break;
    if ( !isCode(F2) && !decode_insn(target) )
      break;
  }
  cmd = saved;
  size = i;
  // create the table
  for ( i=0; i < size; i++ )
  {
    ea_t ea = table + 4*i;
    doDwrd(ea, 4);
    op_offset(ea, 0, REF_OFF32, BADADDR, si.elbase);
    ea_t target = si.elbase + segm_adjust_diff(getseg(table), get_long(ea));
    ua_add_cref(0, target, fl_JN);
  }
  si.flags  |= SWI_J32;
  if ( si.defjump != BADADDR )
    si.flags |= SWI_DEFAULT;
  si.ncases  = (uint16)size;
  si.startea = cmd.ea;
  set_switch_info_ex(cmd.ea, &si);
}
BOOL get_vtbl_info(ea_t ea_address, VTBL_info_t &vtbl_info)
{
	flags_t flags = getFlags(ea_address);
	if (!(hasRef(flags) || has_any_name(flags) && (isDwrd(flags) || isUnknown(flags))))
		return(FALSE);
	else
	{
		BOOL is_move_xref = FALSE;
		ea_t ea_code_ref = get_first_dref_to(ea_address);
		if (ea_code_ref && (ea_code_ref != BADADDR))
		{
			do
			{
				if (isCode(getFlags(ea_code_ref)))
				{
					LPCTSTR disasm_line = get_text_disasm(ea_code_ref);
#ifndef __EA64__
					if ((*((PUINT)disasm_line) == 0x20766F6D /*"mov "*/) && (strstr(disasm_line + 4, " offset ") != NULL))
#else
					if ((*((PUINT)disasm_line) == 0x2061656c /*"lea "*/) && (strstr(disasm_line + 4, "rcx") != NULL) && (strstr(disasm_line + 4, "const") != NULL))
#endif
					{
						is_move_xref = TRUE;
						break;
					}
				}

				ea_code_ref = get_next_dref_to(ea_address, ea_code_ref);

			} while (ea_code_ref && (ea_code_ref != BADADDR));
		}
		if (!is_move_xref)
			return(FALSE);

		ZeroMemory(&vtbl_info, sizeof(VTBL_info_t));

		// get_name(BADADDR, ea_address, vtbl_info.vtbl_name, (MAXSTR - 1));
		f_get_ea_name(&vtbl_info.vtbl_name, ea_address);
		ea_t ea_start = vtbl_info.ea_begin = ea_address;
		while (TRUE)
		{
			flags_t index_flags = getFlags(ea_address);
#ifndef __EA64__
			if (!(hasValue(index_flags) && (isDwrd(index_flags) || isUnknown(index_flags))))
#else
			if (!(hasValue(index_flags) && (isQwrd(index_flags) || isUnknown(index_flags)))) 
#endif
				break;
#ifndef __EA64__
			ea_t ea_index_value = get_32bit(ea_address);
#else
			ea_t ea_index_value = get_64bit(ea_address);
#endif

			if (!(ea_index_value && (ea_index_value != BADADDR)))
				break;

			if (ea_address != ea_start)
				if (hasRef(index_flags))
					break;

			flags_t value_flags = getFlags(ea_index_value);
			if (!isCode(value_flags))
				break;
			else
				if (isUnknown(index_flags))
#ifndef __EA64__
					doDwrd(ea_address, sizeof(DWORD));
			ea_address += sizeof(UINT);
#else
					doQwrd(ea_address, sizeof(UINT64));
			ea_address += sizeof(UINT64);
#endif
		};
#ifndef __EA64__
		if ((vtbl_info.methods = ((ea_address - ea_start) / sizeof(UINT))) > 0)
#else
		if((vtbl_info.methods = ((ea_address - ea_start) / sizeof(UINT64))) > 0)
#endif
		{
			vtbl_info.ea_end = ea_address;
			return(TRUE);
		}
		else
			return(FALSE);
	}
}
Beispiel #4
0
static bool check_for_table_jump(void)
{
  ea_t base = BADADDR, table = BADADDR, defea = BADADDR;
  int size = 0, elsize = 0;

  int i;
  bool ok = false;
  insn_t saved = cmd;
  for ( i=0; !ok && i < qnumber(patterns); i++ )
  {
    ok = patterns[i](&base, &table, &defea, &size, &elsize);
    cmd = saved;
  }
  if ( !ok ) return false;

  if ( table != BADADDR ) table = toEA(cmd.cs, table);
  if ( base  != BADADDR ) base  = toEA(cmd.cs, base);
  if ( defea != BADADDR ) defea = toEA(cmd.cs, defea);

  // check the table contents
  int oldsize = size;
  segment_t *s = getseg(table);
  if ( s == NULL ) return false;
  int maxsize = int(s->endEA - table);
  if ( size > maxsize ) size = maxsize;

  for ( i=0; i < size; i++ )
  {
    ea_t ea = table+i*elsize;
    flags_t F = getFlags(ea);
    if ( !hasValue(F)
      || (i && (has_any_name(F) || hasRef(F))) ) break;
    int el = elsize == 1 ? get_byte(ea) : get_word(ea);
    flags_t F2 = get_flags_novalue(base+el);
    if ( isTail(F2)
      || isData(F2)
      || (!isCode(F2) && !decode_insn(base+el)) ) break;
  }
  cmd = saved;
  size = i;
  if ( size != oldsize )
    msg("Warning: jpt_%04a calculated size of %d forced to %d!\n",
                                      cmd.ip, oldsize, size);

  // create the table
  if ( size == 0 ) return false;
  for ( i=0; i < size; i++ )
  {
    ea_t ea = table + i*elsize;
    (elsize == 1 ? doByte : doWord)(ea, elsize);
    op_offset(ea, 0, elsize == 1 ? REF_OFF8 : REF_OFF16, BADADDR, base);
    ua_add_cref(0, base + (elsize==1?get_byte(ea):get_word(ea)), fl_JN);
  }
  char buf[MAXSTR];
  qsnprintf(buf, sizeof(buf), "def_%a", cmd.ip);
//  set_name(defea, buf, SN_NOWARN|SN_LOCAL);         // temporary kernel bug workaround
  set_name(defea, buf, SN_NOWARN);
  qsnprintf(buf, sizeof(buf), "jpt_%a", cmd.ip);
  set_name(table, buf, SN_NOWARN);
  return true;
}
Beispiel #5
0
// Attempt to get information of and fix vftable at address
// Return TRUE along with info if valid vftable parsed at address
BOOL vftable::getTableInfo(ea_t ea, vtinfo &info)
{
    ZeroMemory(&info, sizeof(vtinfo));

	// Start of a vft should have an xref and a name (auto, or user, etc).
    // Ideal flags 32bit: FF_DWRD, FF_0OFF, FF_REF, FF_NAME, FF_DATA, FF_IVL
    //dumpFlags(ea);
    flags_t flags = get_flags_novalue(ea);
	if(hasRef(flags) && has_any_name(flags) && (isEa(flags) || isUnknown(flags)))
    {
        // Get raw (auto-generated mangled, or user named) vft name
        //if (!get_name(BADADDR, ea, info.name, SIZESTR(info.name)))
        //    msg(EAFORMAT" ** vftable::getTableInfo(): failed to get raw name!\n", ea);

        // Determine the vft's method count
        ea_t start = info.start = ea;
        while (TRUE)
        {
            // Should be an ea_t offset to a function here (could be unknown if dirty IDB)
            // Ideal flags for 32bit: FF_DWRD, FF_0OFF, FF_REF, FF_NAME, FF_DATA, FF_IVL
            //dumpFlags(ea);
            flags_t indexFlags = get_flags_novalue(ea);
            if (!(isEa(indexFlags) || isUnknown(indexFlags)))
            {
                //msg(" ******* 1\n");
                break;
            }

            // Look at what this (assumed vftable index) points too
            ea_t memberPtr = getEa(ea);
            if (!(memberPtr && (memberPtr != BADADDR)))
            {
                // vft's often have a zero ea_t (NULL pointer?) following, fix it
                if (memberPtr == 0)
                    fixEa(ea);

                //msg(" ******* 2\n");
                break;
            }

            // Should see code for a good vft method here, but it could be dirty
            flags_t flags = get_flags_novalue(memberPtr);
            if (!(isCode(flags) || isUnknown(flags)))
            {
                //msg(" ******* 3\n");
                break;
            }

            if (ea != start)
            {
                // If we see a ref after first index it's probably the beginning of the next vft or something else
                if (hasRef(indexFlags))
                {
                    //msg(" ******* 4\n");
                    break;
                }

                // If we see a COL here it must be the start of another vftable
                if (RTTI::_RTTICompleteObjectLocator::isValid(memberPtr))
                {
                    //msg(" ******* 5\n");
                    break;
                }
            }

            // As needed fix ea_t pointer, and, or, missing code and function def here
            fixEa(ea);
            fixFunction(memberPtr);

            ea += sizeof(ea_t);
        };

        // Reached the presumed end of it
        if ((info.methodCount = ((ea - start) / sizeof(ea_t))) > 0)
        {
            info.end = ea;
            //msg(" vftable: "EAFORMAT"-"EAFORMAT", methods: %d\n", rtInfo.eaStart, rtInfo.eaEnd, rtInfo.uMethods);
            return(TRUE);
        }
    }

    //dumpFlags(ea);
    return(FALSE);
}
int idaapi emu()
{
    char szLabel[MAXSTR];
    insn_t saved;
    segment_t* pSegment;
    ea_t ea, length, offset;
    flags_t flags;
    uint32 dwFeature, i;

    dwFeature = cmd.get_canon_feature();
    fFlow = !(dwFeature & CF_STOP);

    if (dwFeature & CF_USE1) op_emu(cmd.Op1, 1);
    if (dwFeature & CF_USE2) op_emu(cmd.Op2, 1);

    if (dwFeature & CF_CHG1) op_emu(cmd.Op1, 0);
    if (dwFeature & CF_CHG2) op_emu(cmd.Op2, 0);

    saved = cmd;
    switch (cmd.itype)
    {
    case M8B_MOV:
        if (!cmd.Op1.is_reg(rPSP))
            break;
    case M8B_SWAP:
        if (cmd.itype == M8B_SWAP && !cmd.Op2.is_reg(rDSP))
            break;

        for (i = 0; i < 5; ++i)
        {
            ea = decode_prev_insn(cmd.ea);
            if (ea == BADADDR) break;
            if (cmd.itype == M8B_MOV && cmd.Op1.is_reg(rA) && cmd.Op2.type == o_imm)
            {
                ea = toRAM(cmd.Op2.value);
                if (ea != BADADDR)
                {
                    qsnprintf(szLabel, sizeof(szLabel), "%s_%0.2X", cmd.itype == M8B_MOV ? "psp" : "dsp", cmd.Op2.value);
                    ua_add_dref(cmd.Op2.offb, ea, dr_O);
                    set_name(ea, szLabel, SN_NOWARN);
                }
                break;
            }
        }
        break;
    case M8B_JACC:
        pSegment = getseg(cmd.ea);
        if (!pSegment) break;
        length = pSegment->endEA - cmd.ea;
        if (length > 256) length = 256;
        for (offset = 2; offset < length; offset += 2)
        {
            ea = toROM(saved.Op1.addr + offset);
            if (ea == BADADDR) break;
            flags = getFlags(ea);
            if (!hasValue(flags) || (has_any_name(flags) || hasRef(flags)) || !create_insn(ea)) break;
            switch (cmd.itype)
            {
            case M8B_JMP:
            case M8B_RET:
            case M8B_RETI:
            case M8B_IPRET:
                add_cref(saved.ea, ea, fl_JN);
                break;
            default:
                offset = length;
            }
        }
        break;
    case M8B_IORD:
    case M8B_IOWR:
    case M8B_IOWX:
        for (i = 0; i < 5; ++i)
        {
            ea = (saved.itype == M8B_IORD) ? decode_insn(cmd.ea + cmd.size) : decode_prev_insn(cmd.ea);
            if (ea == BADADDR) break;
            if (cmd.Op1.is_reg(rA) && cmd.Op2.type == o_imm)
            {
                qsnprintf(szLabel, sizeof(szLabel), "[A=%0.2Xh] ", cmd.Op2.value);
                if (get_portbits_sym(szLabel + qstrlen(szLabel), saved.Op1.addr, cmd.Op2.value))
                    set_cmt(saved.ea, szLabel, false);
                break;
            }
        }
    }
    cmd = saved;

    if ((cmd.ea & 0xFF) == 0xFF)
    {
        switch (cmd.itype)
        {
        case M8B_RET:
        case M8B_RETI:
        case M8B_XPAGE:
            break;
        default:
            QueueMark(Q_noValid, cmd.ea);
        }
    }

    if (fFlow) ua_add_cref(0, cmd.ea + cmd.size, fl_F);

    return 1;
}
Beispiel #7
0
// Process function
void processFunction(func_t *f)
{
	// Skip tiny functions
	if(f->size() >= 5)
	{
		// Don't add comments to API wrappers
        char name[MAXNAMELEN]; name[0] = name[SIZESTR(name)] = 0;
		if(!apiMap.empty())
		{
			if(get_short_name(BADADDR, f->startEA, name, SIZESTR(name)))
			{
				if(apiMap.find(name) != apiMap.end())
					return;
			}
		}

		// Iterate function body
        STRLIST importLstTmp;
        LPSTR commentPtr = NULL;
		char comment[MAXSTR]; comment[0] = comment[SIZESTR(comment)] = 0;
        UINT commentLen = 0;

        #define ADDNM(_str) { UINT l = strlen(_str); memcpy(comment + commentLen, _str, l); commentLen += l; _ASSERT(commentLen < MAXSTR); }

        func_item_iterator_t it(f);
		do
		{
            ea_t currentEA = it.current();

			// Will be a "to" xref
			xrefblk_t xb;
			if(xb.first_from(currentEA, XREF_FAR))
			{
				BOOL isImpFunc = FALSE;
                name[0] = 0;

				// If in import segment
				// ============================================================================================
				ea_t refAdrEa = xb.to;
				if(isInImportSeg(refAdrEa))
				{
					flags_t flags = get_flags_novalue(refAdrEa);
					if(has_name(flags) && hasRef(flags) && isDwrd(flags))
					{
						if(get_short_name(BADADDR, refAdrEa, name, SIZESTR(name)))
						{
							// Nix the imp prefix if there is one
							if(strncmp(name, "__imp_", SIZESTR("__imp_")) == 0)
								memmove(name, name + SIZESTR("__imp_"), ((strlen(name) - SIZESTR("__imp_")) + 1));

							isImpFunc = TRUE;
						}
						else
							msg(EAFORMAT" *** Failed to get import name! ***\n", refAdrEa);
					}
				}
				// Else, check for import wrapper
				// ============================================================================================
				else
				if(!apiMap.empty())
				{
					// Reference is a function entry?
					flags_t flags = get_flags_novalue(refAdrEa);
					if(isCode(flags) && has_name(flags) && hasRef(flags))
					{
						if(func_t *refFuncPtr = get_func(refAdrEa))
						{
							if(refFuncPtr->startEA == refAdrEa)
							{
								if(get_short_name(BADADDR, refAdrEa, name, SIZESTR(name)))
								{
									// Skip common unwanted types "sub_.." or "unknown_libname_.."
									if(
										// not "sub_..
										/*"sub_"*/ (*((PUINT) name) != 0x5F627573) &&

										// not "unknown_libname_..
										/*"unknown_"*/ ((*((PUINT64) name) != 0x5F6E776F6E6B6E75) && (*((PUINT64) (name + 8)) != /*"libname_"*/ 0x5F656D616E62696C)) &&

										// not nullsub_..
										/*"nullsub_"*/ (*((PUINT64) name) != 0x5F6275736C6C756E)
										)
									{
										// Nix the import prefixes
										if(strncmp(name, "__imp_", SIZESTR("__imp_")) == 0)
											memmove(name, name + SIZESTR("__imp_"), ((strlen(name) - SIZESTR("__imp_")) + 1));

										// Assumed to be a wrapped import if it's in the list
										isImpFunc = (apiMap.find(name) != apiMap.end());
									}
								}
								else
									msg(EAFORMAT" *** Failed to get function name! ***\n", refAdrEa);
							}
						}
					}
				}

				// Found import function to add list
				if(isImpFunc)
				{
					// Skip those large common STL names
					if(strncmp(name, "std::", SIZESTR("std::")) != 0)
					{
						// Skip if already seen in this function
						BOOL known = FALSE;
						for(STRLIST::iterator ji = importLstTmp.begin(); ji != importLstTmp.end(); ji++)
						{
							if(strcmp(ji->c_str(), name) == 0)
							{
								known = TRUE;
								break;
							}
						}

						// Not seen
						if(!known)
						{
							importLstTmp.push_front(name);

                            // Append to existing comments w/line feed
                            if(!commentLen && !commentPtr)
                            {
                                commentPtr = get_func_cmt(f, true);
                                if(!commentPtr)
                                    get_func_cmt(f, false);

                                if(commentPtr)
                                {
                                    commentLen = strlen(commentPtr);
                                    // Bail out not enough comment space
                                    if(commentLen >= (MAXSTR - 20))
                                    {
                                        qfree(commentPtr);
                                        return;
                                    }

                                    memcpy(comment, commentPtr, commentLen);
                                    ADDNM("\n"MYTAG);
                                }
                            }

                            if(!commentLen)
                                ADDNM(MYTAG);

							// Append a "..." (continuation) and bail out if name hits max comment length
							if((commentLen + strlen(name) + SIZESTR("()") + sizeof(", ")) >= (MAXSTR - sizeof("...")))
							{
                                ADDNM(" ...");
								break;
							}
							// Append this function name
							else
							{
								if(importLstTmp.size() != 1)
                                    ADDNM(", ");
                                ADDNM(name); ADDNM("()");
							}
						}
					}
					else
					{
						//msg("%s\n", szName);
					}
				}
			}

		}while(it.next_addr());

		if(!importLstTmp.empty() && commentLen)
		{
            // Add comment
            comment[commentLen] = 0;
			set_func_cmt(f, comment, true);
			commentCount++;
		}

        if(commentPtr)
            qfree(commentPtr);
	}
}