void FunctionHook::correctRelativeAddresses()
{
    DISASM disassembler = {};
    disassembler.EIP = reinterpret_cast<uintptr_t>(m_trampoline.data());
    disassembler.VirtualAddr = m_info.originalAddr;

    RetSizeType bytesChecked = 0;

    while (bytesChecked < TRAMPOLINE_SIZE)
    {
        const int len = Disasm(&disassembler);

        if (len == OUT_OF_BLOCK || len == UNKNOWN_OPCODE)
        {
            break;
        }

        static constexpr uint8_t RELATIVE_CALL = 0xE8;
        static constexpr uint8_t RELATIVE_SHORT_JMP = 0xEB;
        static constexpr uint8_t RELATIVE_JMP = 0xE9;

        switch (disassembler.Instruction.Opcode)
        {
            case RELATIVE_CALL:
            case RELATIVE_JMP:
            {
                uint32_t* offset = reinterpret_cast<uint32_t*>(m_trampoline.data() + bytesChecked + 1);
                const uintptr_t originalOffset = *offset;
                const uintptr_t targetAddress = m_info.originalAddr + bytesChecked + len + originalOffset;
                const uintptr_t trampolineAddress = reinterpret_cast<uintptr_t>(m_trampoline.data() + bytesChecked + len);
                *offset = targetAddress + (0xFFFFFFFF - trampolineAddress) + 1;
                break;
            }

            case RELATIVE_SHORT_JMP:
            {
                assert(false); // No short jmp support yet!
                break;
            }
        }

        bytesChecked += len;
        disassembler.EIP += len;
        disassembler.VirtualAddr += len;
    }
}
Beispiel #2
0
static int disassemble(RAsm *a, RAsmOp *aop, const ut8 *buf, int len) {
	static DISASM disasm_obj;

	memset (&disasm_obj, '\0', sizeof (DISASM));
	disasm_obj.EIP = (long long)buf;
	disasm_obj.VirtualAddr = a->pc;
	disasm_obj.Archi = ((a->bits == 64) ? 64 : 0);
	disasm_obj.SecurityBlock = len;
	if (a->syntax == R_ASM_SYNTAX_ATT)
		disasm_obj.Options = 0x400;
	else disasm_obj.Options = 0;

	aop->size = Disasm (&disasm_obj);
	r_asm_op_set_asm (aop, disasm_obj.CompleteInstr);

	return aop->size;
}
Beispiel #3
0
void DisassembleCode(char *StartCodeSection, char *EndCodeSection, int (*Virtual_Address)(void))
{

	Error = 0;

	/* ============================= Init EIP */
	MyDisasm.EIP = (int) StartCodeSection;
	/* ============================= Init VirtualAddr */
	MyDisasm.VirtualAddr = (__int64) Virtual_Address;

	/* ============================= set IA-32 architecture */
	MyDisasm.Archi = 0;
	/* ============================= Loop for Disasm */
	while ( !Error){
		/* ============================= Fix SecurityBlock */
		MyDisasm.SecurityBlock = (long) EndCodeSection - MyDisasm.EIP;

		len = Disasm(&MyDisasm);
		if (len == OUT_OF_BLOCK) {
			(void) printf("disasm engine is not allowed to read more memory \n");
			Error = 1;
		}
		else if (len == UNKNOWN_OPCODE) {
			(void) printf("unknown opcode");
			Error = 1;
		}
		else {
			/* ============================= Make a filter on Instruction */
			if (MyDisasm.Instruction.BranchType != 0) {
				(void) printf("Branch-Instruction : ");
				(void) printf("%.8X %s\n",(int) MyDisasm.VirtualAddr, &MyDisasm.CompleteInstr);
			}
			else if ((MyDisasm.Argument1.AccessMode == READ) && (MyDisasm.Argument2.AccessMode == READ)) {
				(void) printf("CompareInstruction : ");
				(void) printf("%.8X %s\n",(int) MyDisasm.VirtualAddr, &MyDisasm.CompleteInstr);
			}
			MyDisasm.EIP = MyDisasm.EIP + len;
			MyDisasm.VirtualAddr = MyDisasm.VirtualAddr + len;
			if (MyDisasm.EIP >= (long) EndCodeSection) {
				(void) printf("End of buffer reached ! \n");
				Error = 1;
			}
		}
	};
	return;
}
Beispiel #4
0
bool disasmfast(unsigned char* data, uint addr, BASIC_INSTRUCTION_INFO* basicinfo)
{
    if(!data or !basicinfo)
        return false;
    DISASM disasm;
    memset(&disasm, 0, sizeof(disasm));
#ifdef _WIN64
    disasm.Archi = 64;
#endif // _WIN64
    disasm.EIP = (UIntPtr)data;
    disasm.VirtualAddr = (UInt64)addr;
    int len = Disasm(&disasm);
    if(len == UNKNOWN_OPCODE)
        return false;
    fillbasicinfo(&disasm, basicinfo);
    basicinfo->size = len;
    return true;
}
Beispiel #5
0
int main(int argc, char** argv)
{
	const char* usage = "usage: %s (-vX | -d) [dcpu-16 binary]";
	LAssert(argc >= 2, usage, argv[0]);

	logLevel = 2;
	
	const char* file = NULL;
	unsigned start = 0;
	int numFiles = 0;

	for(int i = 1; i < argc; i++){
		char* v = argv[i];
		if(v[0] == '-'){
			if(!strcmp(v, "-h")){
				LogI(usage, argv[0]);
				LogI(" ");
				LogI("Available flags:");
				LogI("  -vX   set log level, where X is [0-5] - default: 2");
				LogI("  -sX   start disassembly at address X - default 0");
				return 0;
			}
			else if(sscanf(v, "-v%d", &logLevel) == 1){}
			else if(sscanf(v, "-s0x%x", &start) || sscanf(v, "-s%d", &start) == 1){}
			else{
				LogF("No such flag: %s", v);
				return 1;
			}
		}else{
			numFiles++;
			file = v;
		}
	}
	
	LAssert(numFiles == 1, "Please specify one file to disassemble");

	// Allocate 16MB ROM/RAM
	uint8_t* ram = calloc(1, 1024 * 1024 * 16);

	ReadFile(ram, 1024 * 1024 * 16, file);
	Disasm(ram, start);

	free(ram);
}
Beispiel #6
0
static int disassemble(struct r_asm_t *a, struct r_asm_aop_t *aop, ut8 *buf, ut64 len)
{
	static DISASM disasm_obj;

	memset(&disasm_obj, '\0', sizeof(DISASM));
	disasm_obj.EIP = (long long)buf;
	disasm_obj.VirtualAddr = a->pc;
	disasm_obj.Archi = ((a->bits == 64) ? 64 : 0);
	disasm_obj.SecurityBlock = len;
	if (a->syntax == R_ASM_SYNTAX_ATT)
		disasm_obj.Options = 0x400;
	else disasm_obj.Options = 0;

	aop->inst_len = Disasm(&disasm_obj);

	snprintf(aop->buf_asm, R_ASM_BUFSIZE, disasm_obj.CompleteInstr);

	return aop->inst_len;
}
Beispiel #7
0
void CT_cbMagicJump()
{
    if(!patched_magic_jump)
    {
        BYTE eb[2]= {0xEB,0x90};
        WriteProcessMemory(fdProcessInfo->hProcess, (void*)(magic_byte+2), &eb, 1, 0); //patch JNZ->JMP
        eb[0]=0x90;
        WriteProcessMemory(fdProcessInfo->hProcess, (void*)noteax, &eb, 2, 0);
        SetBPX(tea_decrypt, UE_BREAKPOINT, (void*)CT_cbTeaDecrypt);
        SetBPX(end_big_loop, UE_BREAKPOINT, (void*)CT_cbEndBigLoop);
        DISASM MyDisasm= {0};
        MyDisasm.EIP=(UIntPtr)&cmp_data;
        Disasm(&MyDisasm);
        char register_retrieve[10]="";
        strncpy(register_retrieve, MyDisasm.Argument2.ArgMnemonic, 3);
        patched_magic_jump=true;
        register_magic_byte=DetermineRegisterFromText(register_retrieve);
    }
    magic_byte_cert=(unsigned char)GetContextData(register_magic_byte);
}
Beispiel #8
0
static void DisassembleCode(char *StartCodeSection, 
			    char *EndCodeSection, 
			    MainPtr Virtual_Address)
{

  Error = 0;

  /* ============================= Init EIP */
  MyDisasm.EIP = (UIntPtr) StartCodeSection;
  /* ============================= Init VirtualAddr */
  MyDisasm.VirtualAddr = (UIntPtr) Virtual_Address;

  /* ============================= set IA-32 architecture */
  MyDisasm.Archi = 0;
  /* ============================= Loop for Disasm */
  while (!Error){
    /* ============================= Fix SecurityBlock */
    MyDisasm.SecurityBlock = (UIntPtr)EndCodeSection - (UIntPtr)MyDisasm.EIP;

    len = Disasm(&MyDisasm);
    if (len == OUT_OF_BLOCK) {
      (void) printf("disasm engine is not allowed to read more memory \n");
      Error = 1;
    }
    else if (len == UNKNOWN_OPCODE) {
      (void) printf("unknown opcode");
      Error = 1;
    }
    else {
      (void) printf("%.8X %s\n",(int) MyDisasm.VirtualAddr, (char*)&MyDisasm.CompleteInstr);
      MyDisasm.EIP = MyDisasm.EIP + (UIntPtr)len;
      MyDisasm.VirtualAddr = MyDisasm.VirtualAddr + (UIntPtr)len;
      if (MyDisasm.EIP >=  (UIntPtr)EndCodeSection) {
	(void) printf("End of buffer reached ! \n");
	Error = 1;
      }
    }
  };
  return;
}
Beispiel #9
0
void DisassembleCode(char *StartCodeSection, char *EndCodeSection, int (*Virtual_Address)(void))
{

	/* ============================= Init the Disasm structure (important !)*/
	(void) memset (&MyDisasm, 0, sizeof(DISASM));

	/* ============================= Init EIP */
	MyDisasm.EIP = (long long) StartCodeSection;
	/* ============================= Init VirtualAddr */
	MyDisasm.VirtualAddr = (long long) Virtual_Address;

	/* ============================= set IA-32 architecture */
	MyDisasm.Archi = 0;
	/* ============================= Loop for Disasm */
	while (!Error){
		/* ============================= Fix SecurityBlock */
		MyDisasm.SecurityBlock = (int) EndCodeSection - MyDisasm.EIP;

		len = Disasm(&MyDisasm);
		if (len == OUT_OF_BLOCK) {
			(void) printf("disasm engine is not allowed to read more memory \n");
			Error = 1;
		}
		else if (len == UNKNOWN_OPCODE) {
			(void) printf("unknown opcode \n");
			Error = 1;
		}
		else {
            (void) printf("%.8X %s\n",(int) MyDisasm.VirtualAddr, (char*) &MyDisasm.CompleteInstr);
			MyDisasm.EIP = MyDisasm.EIP + len;
			MyDisasm.VirtualAddr = MyDisasm.VirtualAddr + len;
			if (MyDisasm.EIP >= (int) EndCodeSection) {
				(void) printf("End of buffer reached ! \n");
				Error = 1;
			}
		}
	};
	return;
}
Beispiel #10
0
void CT_RetrieveSaltValue()
{
    if(!salt_func_addr)
    {
        StopDebug();
        return;
    }
    DISASM MyDisasm= {0};
    MyDisasm.EIP=(UIntPtr)salt_code;
    int len=0;
    int xor_count=0;
    for(;;)
    {
        len=Disasm(&MyDisasm);
        if(len==UNKNOWN_OPCODE)
            break;
        if(MyDisasm.EIP!=(UIntPtr)salt_code and MyDisasm.Instruction.Mnemonic[0]=='x' and MyDisasm.Instruction.Mnemonic[1]=='o' and MyDisasm.Instruction.Mnemonic[2]=='r')
            xor_count++;
        if(xor_count==3)
            break;
        MyDisasm.EIP+=len;
        if(MyDisasm.EIP>=(unsigned int)salt_code+60)
            break;
    }
    if(xor_count!=3)
    {
        StopDebug();
        return;
    }
    salt_register=DetermineRegisterFromText(MyDisasm.Argument1.ArgMnemonic);
    unsigned int salt_breakpoint=MyDisasm.EIP-((unsigned int)salt_code)+salt_func_addr+len;
    if(!salt_register)
    {
        StopDebug();
        return;
    }
    SetContextData(UE_EIP, salt_func_addr);
    SetBPX(salt_breakpoint, UE_BREAKPOINT, (void*)CT_cbGetSalt);
}
int MalwareExtractor::FindNextAddress(ulong start)
{
	// At this point we have to analyze memory from current EIP
	// till the end of the current procedure and construct CFG. Then CFG
	// must be normalized in order to reduce number of breakpoints.
	// (up to first control flow change instruction, such as
	// jmp, ret, jcc (conditional jumps). If there are any calls)
	//
	//Error("%08x", m_thread->reg.ip);
	start = m_thread->reg.ip;
	ulong index = start - m_module->base;
	if (index < 0 || index > m_module->size) {
		m_error_code = ME_ERROR_OUTOFBOUNDS;
		return -1;
	}

	uchar *ptr = &m_imagecopy[index];
	ulong end_addr = (ulong)(&m_imagecopy + m_module->size);
	ulong cmd_size;
	ulong ip = start;//m_thread->reg.ip;
	t_disasm dasm = {0};

	// C_JMP = 0x50, C_JMC = 0x60, C_CAL = 0x70, C_RET = 0x80
	while ((dasm.cmdtype < C_JMP || dasm.cmdtype > C_RET) && (ulong)ptr < end_addr) {
		cmd_size = Disasm(ptr, MAXCMDSIZE, ip, NULL, &dasm, DISASM_ALL,
						  m_thread->threadid);
		ptr += cmd_size;
		ip += cmd_size;
	}

	if ((ulong)ptr > end_addr) {
		m_error_code = ME_ERROR_NOTFOUND;
		return -1;
	}

	m_next_address = ip - cmd_size;
	Error("%08X", m_next_address);
	return 0;
}
Beispiel #12
0
PyObject * wipe_Disasm(PyObject *self, PyObject *args)
{
	PULONG pulOffset;
	CHAR caBuf[BUFSIZE] = {0,};
	ULONG ulShowEffectiveAddress;

    if (!PyArg_ParseTuple(args, "kk", &pulOffset, &ulShowEffectiveAddress))
	{
        return NULL;
	}

	//FIXME
	caBuf[0] = "\x4d\x00";
    if (Disasm(&caBuf, caBuf, ulShowEffectiveAddress))
	{
		return Py_BuildValue("sk", caBuf);
	}
	else
	{
		Py_INCREF(Py_None);
		return Py_None;
	}
}
/// <summary>
/// Check if last instruction caused branching
/// </summary>
/// <param name="ctx">Current hook info</param>
/// <param name="ip">Instruction pointer</param>
/// <param name="sp">Stack pointer</param>
/// <returns>True if branching has occurred</returns>
bool TraceHook::CheckBranching( const HookContext& ctx, uintptr_t ip, uintptr_t sp )
{
    // Not yet initialized
    if (ctx.lastIP == 0 || ctx.lastSP == 0)
        return false;

    // Difference in instruction pointer more than possible 'call' length
    // Stack pointer changed
    if (ip - ctx.lastIP >= 8 && sp != ctx.lastSP)
    {
        DISASM info = { 0 };
        info.EIP = ctx.lastIP;

    #ifdef _M_AMD64
        info.Archi = 64;
    #endif  

        // Double-check call instruction using disasm
        if (Disasm( &info ) > 0 && info.Instruction.BranchType == CallType)
            return true;
    }

    return false;
}
Beispiel #14
0
/**
 * Sort CPU profile data addresses by call counts and show the results.
 * If symbols are requested and symbols are loaded, show (only) addresses
 * matching a symbol.
 */
void Profile_CpuShowCounts(int show, bool only_symbols)
{
	cpu_profile_item_t *data = cpu_profile.data;
	int symbols, matched, active;
	int oldcols[DISASM_COLUMNS];
	Uint32 *sort_arr, *end, addr, nextpc;
	const char *name;
	float percentage;
	Uint32 count;

	if (!data) {
		fprintf(stderr, "ERROR: no CPU profiling data available!\n");
		return;
	}
	active = cpu_profile.active;
	show = (show < active ? show : active);

	sort_arr = cpu_profile.sort_arr;
	qsort(sort_arr, active, sizeof(*sort_arr), cmp_cpu_count);

	if (!only_symbols) {
		leave_instruction_column(oldcols);
		printf("addr:\t\tcount:\n");
		for (end = sort_arr + show; sort_arr < end; sort_arr++) {
			addr = index2address(*sort_arr);
			count = data[*sort_arr].count;
			percentage = 100.0*count/cpu_profile.all.count;
			printf("0x%06x\t%5.2f%%\t%d%s\t",
			       addr, percentage, count,
			       count == MAX_CPU_PROFILE_VALUE ? " (OVERFLOW)" : "");
			Disasm(stdout, addr, &nextpc, 1);
		}
		printf("%d CPU addresses listed.\n", show);
		Disasm_SetColumns(oldcols);
		return;
	}

	symbols = Symbols_CpuCount();
	if (!symbols) {
		fprintf(stderr, "ERROR: no CPU symbols loaded!\n");
		return;
	}
	matched = 0;	

	leave_instruction_column(oldcols);

	printf("addr:\t\tcount:\t\tsymbol:\n");
	for (end = sort_arr + active; sort_arr < end; sort_arr++) {

		addr = index2address(*sort_arr);
		name = Symbols_GetByCpuAddress(addr);
		if (!name) {
			continue;
		}
		count = data[*sort_arr].count;
		percentage = 100.0*count/cpu_profile.all.count;
		printf("0x%06x\t%5.2f%%\t%d\t%s%s\t",
		       addr, percentage, count, name,
		       count == MAX_CPU_PROFILE_VALUE ? " (OVERFLOW)" : "");
		Disasm(stdout, addr, &nextpc, 1);

		matched++;
		if (matched >= show || matched >= symbols) {
			break;
		}
	}
	printf("%d CPU symbols listed.\n", matched);

	Disasm_SetColumns(oldcols);
}
Beispiel #15
0
/**
 * If call tracking is enabled (there are symbols), collect
 * information about subroutine and other calls, and their costs.
 * 
 * Like with profile data, caller info checks need to be for previous
 * instruction, that's why "pc" argument for this function actually
 * needs to be previous PC.
 */
static void collect_calls(Uint32 pc, counters_t *counters)
{
	calltype_t flag;
	int idx, family;
	Uint32 prev_pc, caller_pc;

	family = cpu_profile.prev_family;
	cpu_profile.prev_family = OpcodeFamily;

	prev_pc = cpu_callinfo.prev_pc;
	cpu_callinfo.prev_pc = pc;
	caller_pc = PC_UNDEFINED;

	/* address is return address for last subroutine call? */
	if (unlikely(pc == cpu_callinfo.return_pc) && likely(cpu_callinfo.depth)) {

		flag = cpu_opcode_type(family, prev_pc, pc);
		/* previous address can be exception return (e.g. RTE) instead of RTS,
		 * if exception occurred right after returning from subroutine call.
		 */
		if (likely(flag == CALL_SUBRETURN || flag == CALL_EXCRETURN)) {
			caller_pc = Profile_CallEnd(&cpu_callinfo, counters);
		} else {
#if DEBUG
			/* although at return address, it didn't return yet,
			 * e.g. because there was a jsr or jump to return address
			 */
			Uint32 nextpc;
			fprintf(stderr, "WARNING: subroutine call returned 0x%x -> 0x%x, not through RTS!\n", prev_pc, pc);
			Disasm(stderr, prev_pc, &nextpc, 1);
#endif
		}
		/* next address might be another symbol, so need to fall through */
	}

	/* address is one which we're tracking? */
	idx = Symbols_GetCpuAddressIndex(pc);
	if (unlikely(idx >= 0)) {

		flag = cpu_opcode_type(family, prev_pc, pc);
		if (flag == CALL_SUBROUTINE || flag == CALL_EXCEPTION) {
			/* special HACK for for EmuTOS AES switcher which
			 * changes stack content to remove itself from call
			 * stack and uses RTS for subroutine *calls*, not
			 * for returning from them.
			 *
			 * It wouldn't be reliable to detect calls from it,
			 * so I'm making call *to* it show up as branch, to
			 * keep callstack depth correct.
			 */
			if (unlikely(pc == etos_switcher)) {
				flag = CALL_BRANCH;
			} else if (unlikely(prev_pc == PC_UNDEFINED)) {
				/* if first profiled instruction
				 * is subroutine call, it doesn't have
				 * valid prev_pc value stored
				 */
				cpu_callinfo.return_pc = PC_UNDEFINED;
				fprintf(stderr, "WARNING: previous PC from callinfo for 0x%d is undefined!\n", pc);
#if DEBUG
				skip_assert = true;
				DebugUI(REASON_CPU_EXCEPTION);
#endif
			} else {
				/* slow! */
				cpu_callinfo.return_pc = Disasm_GetNextPC(prev_pc);
			}
		} else if (caller_pc != PC_UNDEFINED) {
			/* returned from function to first instruction of another symbol:
			 *	0xf384	jsr some_function
			 *	other_symbol:
			 *	0f3x8a	some_instruction
			 * -> change return instruction address to
			 *    address of what did the returned call.
			 */
			prev_pc = caller_pc;
			assert(is_prev_instr(prev_pc, pc));
			flag = CALL_NEXT;
		}
		Profile_CallStart(idx, &cpu_callinfo, prev_pc, flag, pc, counters);
	}
}
Beispiel #16
0
/// <summary>
/// Capture stack frames
/// </summary>
/// <param name="ip">Current instruction pointer</param>
/// <param name="sp">Current stack pointer</param>
/// <param name="results">Found frames.</param>
/// <param name="depth">Frame depth limit</param>
/// <returns>Number of found frames</returns>
size_t TraceHook::StackBacktrace( uintptr_t ip, uintptr_t sp, vecStackFrames& results, uintptr_t depth /*= 10 */ )
{
    SYSTEM_INFO sysinfo = { { 0 } };
    uintptr_t stack_base = (uintptr_t)((PNT_TIB)NtCurrentTeb())->StackBase;

    GetNativeSystemInfo( &sysinfo );

    // Store exception address
    results.emplace_back( std::make_pair( 0, ip ) );

    // Walk stack
    for (uintptr_t stackPtr = sp; stackPtr < stack_base && results.size() <= depth; stackPtr += sizeof(void*))
    {
        uintptr_t stack_val = *(uintptr_t*)stackPtr;
        MEMORY_BASIC_INFORMATION meminfo = { 0 };

        // Decode value
        uintptr_t original = stack_val & HIGHEST_BIT_UNSET;

        // Invalid value
        if ( original < (uintptr_t)sysinfo.lpMinimumApplicationAddress ||
             original > (uintptr_t)sysinfo.lpMaximumApplicationAddress)
        {
            continue;
        }

        // Check if memory is executable
        if (VirtualQuery( (LPVOID)original, &meminfo, sizeof(meminfo) ) != sizeof(meminfo))
            continue;

        if ( meminfo.Protect != PAGE_EXECUTE_READ &&
             meminfo.Protect != PAGE_EXECUTE_WRITECOPY &&
             meminfo.Protect != PAGE_EXECUTE_READWRITE)
        {
            continue;
        }

        // Detect 'call' instruction
        for (uintptr_t j = 1; j < 8; j++)
        {
            DISASM info = { 0 };
            info.EIP = original - j;

        #ifdef USE64
            info.Archi = 64;
        #endif  

            // FIXME: Alternative for MinGW
#ifdef COMPILER_MSVC
            if (Disasm( &info ) > 0 && info.Instruction.BranchType == CallType)
            {
                results.emplace_back( std::make_pair( stackPtr, stack_val ) );
                break;
            }
#endif // COMPILER_MSVC
        }

    }

    return results.size();
}
Beispiel #17
0
/**
 * Show CPU instructions which execution was profiled, in the address order,
 * starting from the given address.  Return next disassembly address.
 */
Uint32 Profile_CpuShowAddresses(Uint32 lower, Uint32 upper, FILE *out)
{
	int oldcols[DISASM_COLUMNS], newcols[DISASM_COLUMNS];
	int show, shown, active;
	const char *symbol;
	cpu_profile_item_t *data;
	Uint32 idx, end, size;
	uaecptr nextpc, addr;

	data = cpu_profile.data;
	if (!data) {
		fprintf(stderr, "ERROR: no CPU profiling data available!\n");
		return 0;
	}

	size = cpu_profile.size;
	active = cpu_profile.active;
	if (upper) {
		end = address2index(upper);
		show = active;
		if (end > size) {
			end = size;
		}
	} else {
		end = size;
		show = ConfigureParams.Debugger.nDisasmLines;
		if (!show || show > active) {
			show = active;
		}
	}

	/* get/change columns */
	Disasm_GetColumns(oldcols);
	Disasm_DisableColumn(DISASM_COLUMN_HEXDUMP, oldcols, newcols);
	Disasm_SetColumns(newcols);

	fputs("# disassembly with profile data: <instructions percentage>% (<sum of instructions>, <sum of cycles>, <sum of i-cache misses>)\n", out);

	nextpc = 0;
	idx = address2index(lower);
	for (shown = 0; shown < show && idx < end; idx++) {
		if (!data[idx].count) {
			continue;
		}
		addr = index2address(idx);
		if (addr != nextpc && nextpc) {
			fprintf(out, "[...]\n");
		}
		symbol = Symbols_GetByCpuAddress(addr);
		if (symbol) {
			fprintf(out, "%s:\n", symbol);
		}
		/* NOTE: column setup works only with 68kDisass disasm engine! */
		Disasm(out, addr, &nextpc, 1);
		shown++;
	}
	printf("Disassembled %d (of active %d) CPU addresses.\n", shown, active);

	/* restore disassembly columns */
	Disasm_SetColumns(oldcols);
	return nextpc;
}
DWORD Virtualize(CodeChunk *code, void *addr, DWORD maxBytes) {
	srand(time(0)); // TODO: flytta in i separat funktion, använd WinAPI istället

	DISASM disasm;
	ZeroMemory(&disasm, sizeof(disasm));

	disasm.EIP = (UIntPtr)addr;

	disasm.VirtualAddr = code->getBaseVa();

	// Stats
	unsigned int virtualizedCount = 0;
	unsigned int nativeCount = 0;
	unsigned int totalInstructions = 0;

	unsigned int totalLen = 0;
	while (1) {
		disasm.SecurityBlock = 0;
		int instrLen = Disasm(&disasm);

		if (instrLen == -1) {
			logger.write(LOG_ERROR, "Disassembling failed\n");
			break;
		}

		// temp, break on NOP
		//if (disasm.Instruction.Opcode == 0x90) {
		//	break;
		//}

		
		if (maxBytes != 0 && (totalLen + instrLen > maxBytes)) {
			break;
		}

		totalInstructions++;
		disasm.SecurityBlock = instrLen; // TEMP

		//
		if (g_Settings.displayDisasm) {
			char hex[32];
			Utils::hexStr((BYTE*)disasm.EIP, instrLen, hex, sizeof(hex), 16, ' ');
			logger.write(LOG_MSG, "%08x %s | %s\n", (DWORD)disasm.VirtualAddr, hex, disasm.CompleteInstr);
		}
		// Attempt to virtualize
		if (virtualizers.virtualize(code, &disasm)) {
			virtualizedCount++;
		} else {
			// Create native handler for it
			//logger.write(LOG_MSG, "TEMP Native: [%s]\n", disasm.CompleteInstr);
			doNativeHandler(code, &disasm, (BYTE*)disasm.EIP, instrLen);
			nativeCount++;
		}
		//

		totalLen += instrLen;
		disasm.VirtualAddr += instrLen;
		disasm.EIP += instrLen;
	}

	logger.write(LOG_MSG,"%d bytes disassembled\n", totalLen);
	logger.write(LOG_MSG, "%d of %d instructions were virtualized (~%d%%)\n", virtualizedCount, totalInstructions, (int)(100 * (virtualizedCount / (float)totalInstructions)));

	return totalLen;
}
Beispiel #19
0
int desassemble(Desasembleur* desas){
    int len = Disasm(desas->disasm);
    
    return len;
}
Beispiel #20
0
int dbg_console()
{
	char *p;
loop:
	p = readline("k> ");
	switch (*p++)
	{
	case 'b': /* break point */
		if (*p == '-') /* delete */
		{
			int n;
			p = _eat_white_char(++p);
			if (*p == '#')
			{
				n = strtol(++p, NULL, 10);
			}
			else
			{
				if ((n = _get_bpidx_by_addr(strtol(p, NULL, 16))) == MAX_DEBUGGER_BPS)
					cprintf("no breakpoint @ %s\n", p);
			}
			*(uint8_t *)dbg.bps[n].addr = dbg.bps[n].origin;
			dbg.bps[n].valid = 0;
		}
		else if (*p == '?') /* query */
		{
			p = _eat_white_char(++p);
			if (*p == '#') /* specific breakpoint */
			{
				_dbg_print_bp(strtol(++p, NULL, 10), 1);
			}
			else /* find breakpoint on address */
			{
				int i;
				for (i = 0; i < MAX_DEBUGGER_BPS; ++i)
					_dbg_print_bp(i, 0);
			}
		}
		else /* add */
		{
			int n;
			p = _eat_white_char(p);
			n = _dbg_add_bp(strtol(p, NULL, 16));
			if (n >= MAX_DEBUGGER_BPS)
			{
				cprintf("breakpoint slot run out!\n");
			}
			else
			{
				*(uint8_t *)dbg.bps[n].addr = 0xCC;
				cprintf("breakpoint #%d set to %s\n", n, p);
			}
		}
		break;
	case 'g': /* go */
		if (dbg.ctx == NULL)
			goto out_ret;
		if (dbg.ctx->tf_trapno != 3)
			dbg.ctx->tf_eflags &= ~FL_TF; /* clear eeflag.tp */
		//asm volatile {rdmsr } // TODO
		//asm volatile {wrmsr }; /* clear msr.btf */
		goto out_ret;
	case 's': /* step */
		if (dbg.ctx == NULL)
		{
			cprintf("no debugging context!\n");
			break;
		}
		dbg.step_trap = 1;
		dbg.ctx->tf_eflags |= FL_TF; /* set eeflag.tp */
		if (*p == 'o') /* over */
		{
			// TODO set msr
		}
		goto out_ret;
	case '$': /* stack */
		if (dbg.ctx == NULL)
		{
			cprintf("no debugging context!\n");
			break;
		}
		p = _eat_white_char(p);
		_dump_addr((void *)(_get_seg_base(dbg.ctx->tf_ss) + dbg.ctx->tf_esp), p); // TODO ctx.ss+esp
		break;
	case 'r': /* register */
		if (dbg.ctx == NULL)
		{
			cprintf("no debugging context!\n");
			break;
		}
		if (*p == 's')
		{
			_print_sregs(dbg.ctx);
		}
		else
		{
			_print_cregs(dbg.ctx);
		}
		break;
	/* context free operations */
	case 'd': /* disasm(memory) */
		do
		{
			int i;
			char *addr = (char *)strtol(_eat_white_char(p), NULL, 16), *t = addr;
			t_disasm da;
			ideal=0; lowercase=1; putdefseg=0;
			for (i = 0; i < 16; ++i)
			{
				t += Disasm(addr, (unsigned long)addr, 0, &da, DISASM_CODE);
				cprintf("%08x  %-24s  %-24s\n", addr, da.dump, da.result);
				addr = t;
			}
		} while (0);
		break;
	case 'l': /* looking */
		do
		{
			uint8_t buffer[128] = {0};
			char *addr_begin = (char *)strtol(_eat_white_char(p), &p, 16);
			char *addr_end = (char *)strtol(_eat_white_char(p), &p, 16);
			_parse_data(buffer, p);
			// TODO
		} while(0);
		break;
	case 'x': /* check memory */
		do
		{
			void *addr = (void *)strtol(_eat_white_char(p), &p, 16);
			_dump_addr(addr, _eat_white_char(p));
		} while(0);
		break;
	case 'w': /* write memory */
		do
		{
			uint8_t buffer[128];
			char *addr = (char *)strtol(_eat_white_char(p), &p, 16);
			int len = _parse_data(buffer, p);
			memcpy(addr, buffer, len);
		} while(0);
		break;
	default:
		cprintf("invalid debugge command!\n");
		break;
	}
	goto loop;
out_ret:
	dbg.ctx = NULL;
	return 0;
}
Beispiel #21
0
int _InstallHook(char* real, char* hook, char* thunk){

	t_disasm disasm;
	t_asmmodel am;

	char myAsm[TEXTLEN] , errtext[TEXTLEN];
	char *pointer = real;
	
	int length=0, l=0, asmLen=0, wasJMP=0, oldPerm = 0;;

	if(!EnableWrite(thunk,20)){
		sprintf(lastError,"Could not set writable memory perm on thunk?");
		return 0;
	}

	while(length<5){ //copy min space of first instructions of real fx to our thunk
		l = Disasm(pointer,10, (unsigned long)pointer, &disasm, DISASM_CODE);
		if(l<1){ 
			sprintf(lastError,"Disasm Error?");
			return 0;
		}
		switch(disasm.cmdtype){
			case C_JMP:
			case C_JMC:
			case C_CAL: 
				
				if(length==0){ //first instruction only				
					//printf("Your target fx address first inst is a jmp or call %s\n", disasm.result );
					if(l<5){
						sprintf(lastError,"Not enough space to embed our patch?");
						return 0;
					}
					//printf("Ok Trying to reasm for new thunk address...\n");
					l = Assemble(disasm.result,((unsigned long)thunk+length),&am,0,0,errtext);
					if(l<1){
						sprintf(lastError,"Asm Length failed? %d %s %s", asmLen, &disasm.result ,errtext);
						return 0;
					}
					wasJMP=1;
					memcpy( (void*)&thunk[length],am.code ,l);
					break;
				}

			default:
				memcpy( (void*)&thunk[length], pointer ,l);
				break;

		}

		length+=l;
		pointer+=l;
	}

	if(!wasJMP){
		sprintf(myAsm,"jmp 0%X", pointer); //where we will hop back into real api + x
		asmLen = Assemble(myAsm,((unsigned long)thunk+length),&am,0,0,errtext);
		
		if(asmLen<1){
			sprintf(lastError,"Asm Length failed? %d %s", asmLen,errtext);
			return 0;
		}

		memcpy( (void*)&thunk[length], am.code, asmLen); 
	}

	//printf("Ok i think the thunk is built! final size: %d\n", (length+asmLen) );

	
	//now we replace the first bytes of the real function with a 
	//rdirection to our hook replacement	
	sprintf(myAsm,"jmp 0%X", (int)hook);                //jmp hook
	asmLen = Assemble(myAsm,(int)real,&am,0,0,errtext); //asm to embed at real fx start
	
	if(asmLen<1){
		sprintf(lastError,"Asm Length failed? %d %s", asmLen,errtext);
		return 0;
	}

	oldPerm = EnableWrite(real,asmLen);
	
	if(!oldPerm){
		sprintf(lastError,"Could not enable write on real function address? %x", real);
		return 0 ;
	}

	while(length--) real[length] = 0xCC; //be tidy for debugging sake
	memcpy(real, am.code, asmLen);       //embed our patch at beginning of real function
	
	RestorePerm(real,asmLen,oldPerm);

	return 1;

}
Beispiel #22
0
void BasicBlock::disasm()
{
    if (isDisasmed())
        return;
    setDisasmed(true);

    DISASM MyDisasm = insts[0];
    insts.pop_back();
    //printf("\t\tStart BasicBlock::disasm 0x%llx\n", (ADDR)this);
    while (1){
        // Fix SecurityBlock 
        MyDisasm.SecurityBlock = func->getEnd() - MyDisasm.EIP;
        // disasm
        int len = Disasm(&MyDisasm);
        if (len == OUT_OF_BLOCK) {
            puts("\t\t\tOUT_OF_BLOCK : Disasm finished");
            return;
        }else if (len == UNKNOWN_OPCODE) {
            fprintf(stderr, "unknown opcode\n");
            return;
        }else {
            if((MyDisasm.Instruction.Category&0xffff)==CONTROL_TRANSFER && MyDisasm.Instruction.BranchType) {
                switch (MyDisasm.Instruction.BranchType) {
                    case CallType:
                        break;
                    case JO:
                    case JC:
                    case JE:
                    case JA:
                    case JS:
                    case JP:
                    case JL:
                    case JG:
                    //case JB:
                    case JECXZ:
                    case JNO:
                    case JNC:
                    case JNE:
                    case JNA:
                    case JNS:
                    case JNP:
                    case JNL:
                    case JNG:
                    //case JNB:
                        {
                            ADDR mAddr = MyDisasm.EIP + len;
                            if ((ADDR)-1 != func->getVirAddr(mAddr)) {
                                BasicBlock *succ = func->findBasicBlock(mAddr);
                                addSuccessor(succ);
                                succ->addPredecessor(this);
                            }
                        }
                    case JmpType:
                        if (MyDisasm.Instruction.AddrValue != 0) {
                            ADDR mAddr = func->getMapAddr(MyDisasm.Instruction.AddrValue);
                            if ((ADDR)-1 != mAddr) {
                                BasicBlock *succ = func->findBasicBlock(mAddr);
                                addSuccessor(succ);
                                succ->addPredecessor(this);
                            }
                        }
                    case RetType:
                        //puts("\t\t\tCONTROL_TRANSFER : Disasm finished");
                        //char buf[1024];
                        //printf("\t\t%s\n\n", toString(buf, sizeof(buf)));
                        insts.push_back(MyDisasm);
                        return;
                    default:
                        fprintf(stderr, "unknown branchtype %d (0x%llx) in Basic Block 0x%llx\n", MyDisasm.Instruction.BranchType, (ADDR)MyDisasm.VirtualAddr, getFirstInstAddr());
                        return;
                }
            }

            insts.push_back(MyDisasm);
            MyDisasm.EIP = MyDisasm.EIP + len;
            MyDisasm.VirtualAddr = MyDisasm.VirtualAddr + len;
	
            if(MyDisasm.EIP >= func->getEnd()){
                //puts("\t\t\tFUNCTION END : Disasm finished");
                char buf[1024];
                //printf("\t\t%s\n\n", toString(buf, sizeof(buf)));
                return;
            }
        }
    }
}
Beispiel #23
0
void main(void) {                      // Old form. So what?
  int i,j,n;
  ulong l;
  char *pasm;
  t_disasm da;
  t_asmmodel am;
  char s[TEXTLEN],errtext[TEXTLEN];

  // Demonstration of Disassembler.
  printf("Disassembler:\n");

  // Quickly determine size of command.
  l=Disasm("\x81\x05\xE0\x5A\x47\x00\x01\x00\x00\x00\x11\x22\x33\x44\x55\x66",
    10,0x400000,&da,DISASM_SIZE);
  printf("Size of command = %i bytes\n",l);

  // ADD [475AE0],1 MASM mode, lowercase, don't show default segment
  ideal=0; lowercase=1; putdefseg=0;
  l=Disasm("\x81\x05\xE0\x5A\x47\x00\x01\x00\x00\x00",
    10,0x400000,&da,DISASM_CODE);
  printf("%3i  %-24s  %-24s   (MASM)\n",l,da.dump,da.result);

  // ADD [475AE0],1 IDEAL mode, uppercase, show default segment
  ideal=1; lowercase=0; putdefseg=1;
  l=Disasm("\x81\x05\xE0\x5A\x47\x00\x01\x00\x00\x00",
    10,0x400000,&da,DISASM_CODE);
  printf("%3i  %-24s  %-24s   (IDEAL)\n",l,da.dump,da.result);

  // CALL 45187C
  l=Disasm("\xE8\x1F\x14\x00\x00",
    5,0x450458,&da,DISASM_CODE);
  printf("%3i  %-24s  %-24s   jmpconst=%08X\n",l,da.dump,da.result,da.jmpconst);

  // JNZ 450517
  l=Disasm("\x75\x72",
    2,0x4504A3,&da,DISASM_CODE);
  printf("%3i  %-24s  %-24s   jmpconst=%08X\n",l,da.dump,da.result,da.jmpconst);

  // Demonstration of Assembler.
  printf("\nAssembler:\n");

  // Assemble one of the commands above. First try form with 32-bit immediate.
  pasm="ADD [DWORD 475AE0],1";
  printf("%s:\n",pasm);
  j=Assemble(pasm,0x400000,&am,0,0,errtext);
  n=sprintf(s,"%3i  ",j);
  for (i=0; i<j; i++) n+=sprintf(s+n,"%02X ",am.code[i]);
  if (j<=0) sprintf(s+n,"  error=\"%s\"",errtext);
  printf("%s\n",s);

  // Then variant with 8-bit immediate constant.
  j=Assemble(pasm,0x400000,&am,0,2,errtext);
  n=sprintf(s,"%3i  ",j);
  for (i=0; i<j; i++) n+=sprintf(s+n,"%02X ",am.code[i]);
  if (j<=0) sprintf(s+n,"  error=\"%s\"",errtext);
  printf("%s\n",s);

  // Error, unable to determine size of operands.
  pasm="MOV [475AE0],1";
  printf("%s:\n",pasm);
  j=Assemble(pasm,0x400000,&am,0,4,errtext);
  n=sprintf(s,"%3i  ",j);
  for (i=0; i<j; i++) n+=sprintf(s+n,"%02X ",am.code[i]);
  if (j<=0) sprintf(s+n,"  error=\"%s\"",errtext);
  printf("%s\n",s);

  // Show results.
  Sleep(10000);
};
Beispiel #24
0
Datei: main.c Projekt: dzzie/libs
void main(void) {                      // Old form. So what?
  int i,j,n;
  ulong l;
  char *pasm;
  t_disasm da;
  t_asmmodel am;
  char s[TEXTLEN],errtext[TEXTLEN];


  //display default char type is unsigned 	
  char ch = -10;
  int iConverted = ch;
  printf("char=%d, conv =%d\n\n", ch, iConverted);
  
  memset(&da,0,sizeof(da));

  // Demonstration of Disassembler.
  printf("Disassembler:\n");

  /*Quickly determine size of command.
  l=Disasm("\x81\x05\xE0\x5A\x47\x00\x01\x00\x00\x00\x11\x22\x33\x44\x55\x66",
    10,0x400000,&da,DISASM_SIZE);
  printf("Size of command = %i bytes\n",l);
 */

  //8B4440 41      MOV EAX,DWORD PTR DS:[EAX+EAX*2+41]
  l=Disasm("\x8B\x44\x40\x41", 4, 0x450458,&da,DISASM_CODE);
  printf("%3i  %-24s  %-24s   jmpconst=%08X\n",l,da.dump,da.result,da.jmpconst);
 
  // CALL 45187C
  l=Disasm("\xE8\x1F\x14\x00\x00",
    5,0x450458,&da,DISASM_CODE);
  printf("%3i  %-24s  %-24s   jmpconst=%08X\n",l,da.dump,da.result,da.jmpconst);

  // JNZ 450517
  l=Disasm("\x75\x72",
    2,0x4504A3,&da,DISASM_CODE);
  printf("%3i  %-24s  %-24s   jmpconst=%08X\n",l,da.dump,da.result,da.jmpconst);

  // Demonstration of Assembler.
  printf("\nAssembler:\n");

  // Assemble one of the commands above. First try form with 32-bit immediate.
  pasm="ADD [DWORD 475AE0],1";
  printf("%s:\n",pasm);
  j=Assemble(pasm,0x400000,&am,0,0,errtext);
  n=sprintf(s,"%3i  ",j);
  for (i=0; i<j; i++) n+=sprintf(s+n,"%02X ",am.code[i]);
  if (j<=0) sprintf(s+n,"  error=\"%s\"",errtext);
  printf("%s\n",s);

  // Then variant with 8-bit immediate constant.
  j=Assemble(pasm,0x400000,&am,0,2,errtext);
  n=sprintf(s,"%3i  ",j);
  for (i=0; i<j; i++) n+=sprintf(s+n,"%02X ",am.code[i]);
  if (j<=0) sprintf(s+n,"  error=\"%s\"",errtext);
  printf("%s\n\n",s);


  printf("Test operand error mechanism\n");

  // Error, unable to determine size of operands.
  pasm="MOV [475AE0],1";
  printf("%s:\n",pasm);
  j=Assemble(pasm,0x400000,&am,0,4,errtext);
  n=sprintf(s,"%3i  ",j);
  for (i=0; i<j; i++) n+=sprintf(s+n,"%02X ",am.code[i]);
  if (j<=0) sprintf(s+n,"  error=\"%s\"",errtext);
  printf("%s\n",s);

  // Show results.
  Sleep(10000);


};
Beispiel #25
0
static int MCompareTrace(t_table *pt,wchar_t *name,ulong index,int mode) {
  wchar_t buffer[100];
  uchar * codeline;
  ulong codelinesize;

  if (mode==MENU_VERIFY)
    return MENU_NORMAL;                // Always available
  else if (mode==MENU_EXECUTE) {
    ulong i,j,length, declength;
    uchar cmd[MAXCMDSIZE],*decode;
	t_disasm da;
    t_reg *reg;
	void * result;
	t_memory *pmem;
    t_hitlist hitlistitem;
    Deletesorteddatarange(&(hitlisttable.sorted),0,0xFFFFFFFF);
	for ( i=0; i<memory.sorted.n; i++) {
      pmem=(t_memory *)Getsortedbyindex(&memory.sorted,i);    // Get next memory block.
	  if ((pmem->type & MEM_GAP)!=0)
        continue;                        // Unallocated memory
      // Check whether it contains executable code.
      if ((pmem->type & (MEM_CODE|MEM_SFX))==0)
        continue;                        // Not a code   	  
	  // iterate through code
      for ( j=pmem->base; j<=pmem->base +pmem->size; j++) {
	    codeline = Finddecode(j,&codelinesize);
		if (codeline)
			if (((*codeline)&DEC_TRACED)==DEC_TRACED){
				result = Findsorteddata(&baselist,j,0);
				//Addtolist(result,DRAW_NORMAL,L"sorted");
				if(!result){
                  length=Readmemory(cmd,j,MAXCMDSIZE,MM_SILENT|MM_PARTIAL);
                  if (length==0) Addtolist(j,DRAW_NORMAL,L"Readmemory returned zero!");
                  decode=Finddecode(j,&declength);
                  if (decode!=NULL && declength<length) 
                     decode=NULL;
                  length=Disasm(cmd,length,j,decode,&da,DA_TEXT|DA_OPCOMM|DA_MEMORY,NULL,NULL);
                  if (length==0) Addtolist(j,DRAW_NORMAL,L"Disasm returned zero!");
                  StrcopyW(hitlistitem.decodedinstruction,TEXTLEN,da.result);
			      hitlistitem.index=j;
                  hitlistitem.size=1;
                  hitlistitem.type=0;
                  Addsorteddata(&(hitlisttable.sorted),&hitlistitem);
				}
			}
		}
	  }
	if (hitlisttable.hw==NULL){
      // Create table window. Third parameter (ncolumn) is the number of
      // visible columns in the newly created window (ignored if appearance is
      // restored from the initialization file). If it's lower than the total
      // number of columns, remaining columns are initially invisible. Fourth
      // parameter is the name of icon - as OllyDbg resource.
      Createtablewindow(&hitlisttable,0,hitlisttable.bar.nbar,NULL, L"ICO_PLUGIN",PLUGINNAME);
	}
    else
      Activatetablewindow(&hitlisttable);
	return MENU_REDRAW;
	}
  return MENU_ABSENT;
};
Beispiel #26
0
std::multiset<Gadget*> BeaRopGadgetFinder::find_all_gadget_from_ret(const unsigned char* data, unsigned long long vaddr, const DISASM* ending_instr_disasm, unsigned int len_ending_instr)
{
    std::multiset<Gadget*> gadgets;
    DISASM dis;

    init_disasm_struct(&dis);

    /*
        We go back, trying to create the longuest gadget possible with the longuest instructions
        "On INTEL processors, (in IA-32 or intel 64 modes), instruction never exceeds 15 bytes." -- beaengine.org
    */
    dis.EIP         = (UIntPtr)(ending_instr_disasm->EIP - m_depth*15); // /!\ Warning to pointer arith
    dis.VirtualAddr = ending_instr_disasm->VirtualAddr - m_depth*15;

    /* going back yeah, but not too much :)) */
    if(dis.EIP < (UIntPtr)data)
    {
        dis.EIP = (UIntPtr)data;
        dis.VirtualAddr = vaddr;
    }

    while(dis.EIP < ending_instr_disasm->EIP)
    {
        std::list<Instruction> list_of_instr;

        /* save where we were in memory */
        UIntPtr saved_eip  = dis.EIP;
        UInt64 saved_vaddr = dis.VirtualAddr;

        bool is_a_valid_gadget = false;

        /* now we'll try to find suitable sequence */
        for(unsigned int nb_ins = 0; nb_ins < m_depth; nb_ins++)
        {
            int len_instr = Disasm(&dis);

            /* if the instruction isn't valid, let's try the process one byte after */
            if(len_instr == UNKNOWN_OPCODE || is_valid_instruction(&dis) == false)
                break;

            list_of_instr.push_back(Instruction(
                std::string(dis.CompleteInstr),
                std::string(dis.Instruction.Mnemonic),
                dis.EIP - (UIntPtr)data,
                len_instr
            ));
            
            dis.EIP += len_instr;
            dis.VirtualAddr += len_instr;

            /* if the address of the latest instruction found points on the ending one, we have a winner */
            if(dis.EIP == ending_instr_disasm->EIP)
            {
                is_a_valid_gadget = true;
                /* NB: I reach the ending instruction without depth instruction */
                break;
            }

            /* if we point after the ending one, it's not a valid sequence */
            if(dis.EIP > ending_instr_disasm->EIP)
                break;
        }

        if(is_a_valid_gadget)
        {
            /* we have a valid gadget, time to build it ; add the instructions found & finally add the ending instruction */
            
            /* Don't forget to include the ending instruction in the chain of instruction */
            list_of_instr.push_back(Instruction(
                std::string(ending_instr_disasm->CompleteInstr),
                std::string(ending_instr_disasm->Instruction.Mnemonic),
                ending_instr_disasm->EIP - (UIntPtr)data,
                len_ending_instr
            ));


            Gadget *gadget = new (std::nothrow) Gadget();
            if(gadget == NULL)
                RAISE_EXCEPTION("Cannot allocate gadget");

            /* Now we populate our gadget with the instructions previously found.. */
            gadget->add_instructions(list_of_instr, vaddr);

            gadgets.insert(gadget);
        }

        /* goto the next byte */
        dis.EIP = saved_eip + 1;
        dis.VirtualAddr = saved_vaddr + 1;
    }

    return gadgets;
}
Beispiel #27
0
/**
 * Update CPU cycle and count statistics for PC address.
 *
 * This gets called after instruction has executed and PC
 * has advanced to next instruction.
 */
void Profile_CpuUpdate(void)
{
	counters_t *counters = &(cpu_profile.all);
	Uint32 pc, prev_pc, idx, cycles, misses;
	cpu_profile_item_t *prev;

	prev_pc = cpu_profile.prev_pc;
	/* PC may have extra bits, they need to be masked away as
	 * emulation itself does that too when PC value is used
	 */
	cpu_profile.prev_pc = pc = M68000_GetPC() & 0xffffff;

	if (unlikely(profile_loop.fp)) {
		if (pc < prev_pc) {
			if (pc == cpu_profile.loop_start && prev_pc == cpu_profile.loop_end) {
				cpu_profile.loop_count++;
			} else {
				cpu_profile.loop_start = pc;
				cpu_profile.loop_end = prev_pc;
				cpu_profile.loop_count = 1;
			}
		} else {
			if (pc > cpu_profile.loop_end) {
				log_last_loop();
				cpu_profile.loop_end = 0xffffffff;			
				cpu_profile.loop_count = 0;
			}
		}
	}

	idx = address2index(prev_pc);
	assert(idx <= cpu_profile.size);
	prev = cpu_profile.data + idx;

	if (likely(prev->count < MAX_CPU_PROFILE_VALUE)) {
		prev->count++;
	}

#if USE_CYCLES_COUNTER
	/* Confusingly, with DSP enabled, cycle counter is for this instruction,
	 * without DSP enabled, it's a monotonically increasing counter.
	 */
	if (bDspEnabled) {
		cycles = Cycles_GetCounter(CYCLES_COUNTER_CPU);
	} else {
		Uint32 newcycles = Cycles_GetCounter(CYCLES_COUNTER_CPU);
		cycles = newcycles - cpu_profile.prev_cycles;
		cpu_profile.prev_cycles = newcycles;
	}
#else
	cycles = CurrentInstrCycles + nWaitStateCycles;
#endif
	/* cycles are based on 8Mhz clock, change them to correct one */
	cycles <<= nCpuFreqShift;

	if (likely(prev->cycles < MAX_CPU_PROFILE_VALUE - cycles)) {
		prev->cycles += cycles;
	} else {
		prev->cycles = MAX_CPU_PROFILE_VALUE;
	}

#if ENABLE_WINUAE_CPU
	misses = CpuInstruction.iCacheMisses;
	assert(misses < MAX_MISS);
	cpu_profile.miss_counts[misses]++;
	if (likely(prev->misses < MAX_CPU_PROFILE_VALUE - misses)) {
		prev->misses += misses;
	} else {
		prev->misses = MAX_CPU_PROFILE_VALUE;
	}
#else
	misses = 0;
#endif
	if (cpu_callinfo.sites) {
		collect_calls(prev_pc, counters);
	}
	/* counters are increased after caller info is processed,
	 * otherwise cost for the instruction calling the callee
	 * doesn't get accounted to caller (but callee).
	 */
	counters->misses += misses;
	counters->cycles += cycles;
	counters->count++;

#if DEBUG
	if (unlikely(OpcodeFamily == 0)) {
		Uint32 nextpc;
		fputs("WARNING: instruction opcode family is zero (=i_ILLG) for instruction:\n", stderr);
		Disasm(stderr, prev_pc, &nextpc, 1);
	}
	/* catch too large (and negative) cycles for other than STOP instruction */
	if (unlikely(cycles > 512 && OpcodeFamily != i_STOP)) {
		Uint32 nextpc;
		fprintf(stderr, "WARNING: cycles %d > 512:\n", cycles);
		Disasm(stderr, prev_pc, &nextpc, 1);
	}
	if (unlikely(cycles == 0)) {
		Uint32 nextpc;
		fputs("WARNING: Zero cycles for an opcode:\n", stderr);
		Disasm(stderr, prev_pc, &nextpc, 1);
	}
#endif
}
Beispiel #28
0
// CString object causes crashes here sometimes for some unknown reason. Using STL std::string in lieu of CString.
stdstring DisassembleCode(unsigned char** StartCodeSection, unsigned char** EndCodeSection, size_t Virtual_Address, int* textHeight)
{
	char szOut[8192] = { '\0' };

	DISASM MyDisasm;
	memset(&MyDisasm, 0, sizeof(DISASM));

	MyDisasm.EIP = (UIntPtr)StartCodeSection;

	MyDisasm.VirtualAddr = (UInt64)Virtual_Address;
#ifdef _WIN64
	MyDisasm.Archi = 64;
#else
	MyDisasm.Archi = 0;
#endif
	MyDisasm.Options = PrefixedNumeral;

#ifdef _WIN64
	int securityCount = 0;
#endif

	bool Error = 0;
	while (!Error)
	{
#ifdef _WIN64
		securityCount++;
		if (securityCount >= 100)
			break;
#endif

		MyDisasm.SecurityBlock = (UInt32)(EndCodeSection - (UIntPtr)MyDisasm.EIP);

		int len = Disasm(&MyDisasm);
		if (len == OUT_OF_BLOCK)
		{
			Error = 1;
		}
		else if (len == UNKNOWN_OPCODE)
		{
			Error = 1;
		}
		else
		{
			char szInstruction[96];
			sprintf_s(szInstruction, "%p  ", (void*)MyDisasm.VirtualAddr);
			strcat_s(szInstruction, MyDisasm.CompleteInstr);
			strcat_s(szInstruction, "\r\n");

			strcat_s(szOut, szInstruction);

			MyDisasm.EIP = MyDisasm.EIP + len;
			MyDisasm.VirtualAddr = MyDisasm.VirtualAddr + len;
			if (MyDisasm.EIP >= (UIntPtr)EndCodeSection)
				break;

			unsigned char opcode;
			ReadMemory((LPVOID)(MyDisasm.VirtualAddr - 1), &opcode, sizeof(unsigned char));
			if (opcode == 0xCC) // INT 3 instruction
				break;

			*textHeight += 16;
		}
	}

	*textHeight += 4;

#ifdef UNICODE
	wchar_t Ret[8192];
	size_t converted = 0;
	mbstowcs_s(&converted, Ret, &szOut[0], 8192);
#else
	char* Ret = &szOut[0];
#endif

	return stdstring(Ret);
}
Beispiel #29
0
static void cbVirtualProtect()
{
    DeleteAPIBreakPoint((char*)"kernel32.dll", (char*)"VirtualProtect", UE_APISTART);
    MEMORY_BASIC_INFORMATION mbi= {0};

    unsigned int sec_addr=0;
    unsigned int sec_size=0;
    unsigned int esp_addr=0;
    BYTE* sec_data=0;
    esp_addr=(long)GetContextData(UE_ESP);
    if(!ReadProcessMemory(g_fdProcessInfo->hProcess, (const void*)((esp_addr)+4), &sec_addr, 4, 0))
    {
        VF_FatalError(rpmerror(), g_ErrorMessageCallback);
        return;
    }
    sec_addr-=0x1000;
    VirtualQueryEx(g_fdProcessInfo->hProcess, (void*)sec_addr, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
    sec_size=mbi.RegionSize;
    sec_data=(BYTE*)malloc2(sec_size);
    if(!ReadProcessMemory(g_fdProcessInfo->hProcess, (const void*)sec_addr, sec_data, sec_size, 0))
    {
        VF_FatalError(rpmerror(), g_ErrorMessageCallback);
        return;
    }

    unsigned int usbdevice=VF_FindUsbPattern(sec_data, sec_size);
    if(usbdevice)
    {
        usbdevice+=sec_addr;
        unsigned int usb_push=VF_FindPushAddr(sec_data, sec_size, usbdevice);
        if(!usb_push)
            VF_FatalError("Could not find reference to 'USB Device'", g_ErrorMessageCallback);
        unsigned int invalidkey=0;
        for(int i=usb_push; i>0; i--)
        {
            if(sec_data[i]==0x68 and (sec_data[i+5]>>4)==0x0B and sec_data[i+10]==0xE8)
                //if(sec_data[i]==0x6A and(sec_data[i+1]>>4)==0x00 and sec_data[i+2]==0x6A and(sec_data[i+3]>>4)==0x00 and sec_data[i+4]==0x68)
            {
                invalidkey=i;
                break;
            }
        }
        if(!invalidkey)
            VF_FatalError("Could not find InvalidKey pushes", g_ErrorMessageCallback);

        unsigned int extradw_call=0;
        unsigned int dw_extracall=0;

        DISASM MyDisasm;
        memset(&MyDisasm, 0, sizeof(DISASM));
        MyDisasm.EIP=(UIntPtr)sec_data+invalidkey;
        int len=0;
        int call_count=0;
        for(;;)
        {
            len=Disasm(&MyDisasm);
            if(len!=UNKNOWN_OPCODE)
            {
                if(!strncasecmp(MyDisasm.Instruction.Mnemonic, "call", 4))
                    call_count++;
                if(call_count==2)
                    break;
                MyDisasm.EIP=MyDisasm.EIP+(UIntPtr)len;
                if(MyDisasm.EIP>=(unsigned int)sec_data+invalidkey+0x1000) //Safe number (make bigger when needed)
                    break;
            }
            else
                break;
        }
        extradw_call=MyDisasm.EIP-((unsigned int)sec_data);
        memcpy(&dw_extracall, sec_data+extradw_call+1, 4);
        unsigned int extradw_call_dest=(extradw_call+sec_addr)+dw_extracall+5;
        SetBPX(extradw_call_dest, UE_BREAKPOINT, (void*)cbDw);
    }
    else
    {
Beispiel #30
0
void disassemble(disasmRequest_t req)
{
	address_t address = req.target;
	std::cout << "disassemble " << std::hex << address << std::endl;

	address_t blockStart = address;
	Block block;
	block.start = blockStart;

	do
	{
		char* memory = bytesAtVA(address, 15);
		DISASM disasm = {0, };
		disasm.Archi = 0;
		disasm.Options = Tabulation | MasmSyntax | PrefixedNumeral;
		disasm.SecurityBlock = 0;
		disasm.EIP = reinterpret_cast<UIntPtr>(memory);
		disasm.VirtualAddr = address;

		int length = Disasm(&disasm);
		if (length <= 0)
		{
			std::cerr << "omg fail" << std::endl;
			break;
		}

		describe(address, Description(disasm, blockStart));

		address_t nextAddress = address + length;

		if ((disasm.Instruction.Category & CONTROL_TRANSFER) == CONTROL_TRANSFER)
		{
			switch (disasm.Instruction.BranchType)
			{
				case RetType:
					break;

				case CallType:
					block.exitEdges.push_back(std::make_pair(nextAddress, Fallthrough));
					queueDisasmRequest(DisasmRequest(address, Fallthrough, nextAddress));

					if ((disasm.Argument1.ArgType & CONSTANT_TYPE) == CONSTANT_TYPE)
					{
						block.exitEdges.push_back(std::make_pair(disasm.Instruction.AddrValue, Call));
						queueDisasmRequest(DisasmRequest(address, Call, disasm.Instruction.AddrValue));
					}
					break;

				case JmpType:
					if ((disasm.Argument1.ArgType & CONSTANT_TYPE) == CONSTANT_TYPE)
					{
						block.exitEdges.push_back(std::make_pair(disasm.Instruction.AddrValue, Jump));
						queueDisasmRequest(DisasmRequest(address, Jump, disasm.Instruction.AddrValue));
					}
					break;

				default:
					block.exitEdges.push_back(std::make_pair(nextAddress, Fallthrough));
					queueDisasmRequest(DisasmRequest(address, Fallthrough, nextAddress));

					if ((disasm.Argument1.ArgType & CONSTANT_TYPE) == CONSTANT_TYPE)
					{
						block.exitEdges.push_back(std::make_pair(disasm.Instruction.AddrValue, Jump));
						queueDisasmRequest(DisasmRequest(address, Jump, disasm.Instruction.AddrValue));
					}
					break;
			}

			block.end = address;
			blocks.insert(std::make_pair(block.start, block));
			break;
			
		}

		address = nextAddress;
	} while (true);
}