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; } }
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; }
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; }
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; }
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); }
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; }
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); }
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; }
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; }
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; }
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; }
/** * 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); }
/** * 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); } }
/// <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(); }
/** * 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; }
int desassemble(Desasembleur* desas){ int len = Disasm(desas->disasm); return len; }
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; }
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; }
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; } } } }
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); };
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); };
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; };
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; }
/** * 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 }
// 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); }
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 {
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); }