void WDbgArkUdis::Init(const unsigned __int8 mode) { std::memset(&m_udis_obj, 0, sizeof(m_udis_obj)); ud_init(&m_udis_obj); ud_set_mode(&m_udis_obj, mode); ud_set_syntax(&m_udis_obj, UD_SYN_INTEL); DEBUG_PROCESSOR_IDENTIFICATION_ALL processor_info; HRESULT result = g_Ext->m_Data->ReadProcessorSystemData(0, DEBUG_DATA_PROCESSOR_IDENTIFICATION, &processor_info, static_cast<unsigned __int32>(sizeof(processor_info)), nullptr); unsigned __int32 vendor = UD_VENDOR_ANY; if (SUCCEEDED(result) && (g_Ext->m_ActualMachine == IMAGE_FILE_MACHINE_I386 || g_Ext->m_ActualMachine == IMAGE_FILE_MACHINE_AMD64) ) { std::string vendor_string; if ( g_Ext->m_ActualMachine == IMAGE_FILE_MACHINE_I386 ) vendor_string = processor_info.X86.VendorString; else vendor_string = processor_info.Amd64.VendorString; if ( vendor_string == "GenuineIntel" ) vendor = UD_VENDOR_INTEL; else vendor = UD_VENDOR_AMD; } ud_set_vendor(&m_udis_obj, vendor); }
status_t DisassemblerX8664::Init(target_addr_t address, const void* code, size_t codeSize) { // unset old data delete fUdisData; fUdisData = NULL; // set new data fUdisData = new(std::nothrow) UdisData; if (fUdisData == NULL) return B_NO_MEMORY; fAddress = address; fCode = (const uint8*)code; fCodeSize = codeSize; // init udis ud_init(fUdisData); ud_set_input_buffer(fUdisData, (unsigned char*)fCode, fCodeSize); ud_set_mode(fUdisData, 64); ud_set_pc(fUdisData, (uint64_t)fAddress); ud_set_syntax(fUdisData, UD_SYN_ATT); ud_set_vendor(fUdisData, UD_VENDOR_INTEL); // TODO: Set the correct vendor! return B_OK; }
int ludis86_ud_set_vendor (lua_State * L) { ud_t * ud_obj; const char * vendor; ud_obj = ludis86_check_ud_t(L, 1); vendor = luaL_checkstring(L, 2); lua_pop(L, 2); if (strcmp(vendor, "UD_VENDOR_INTEL") == 0) ud_set_vendor(ud_obj, UD_VENDOR_INTEL); else if (strcmp(vendor, "UD_VENDOR_ATT") == 0) ud_set_vendor(ud_obj, UD_VENDOR_AMD); else luaL_error(L, "invalid vendor for ludis86"); return 0; }
/** HookEngine_Disassemble Obtain the minimum number of instruction bytes that need to be copied from the target function, in order to accomodate our jump instruction */ static DWORD HookEngine_Disassemble(DWORD cbRequired, LPVOID pTargetFunctionAddress, DISASSEMBLY_DATA& DisassemblyData ) { CONST SIZE_T Page = 4096; ud_t ud_obj = { 0 }; ud_init(&ud_obj); #if defined(_M_IX86) ud_set_mode(&ud_obj, 32); #elif defined(_M_X64) ud_set_mode(&ud_obj, 64); #else #error Unsuported platform #endif ud_set_pc(&ud_obj, uint64_t(pTargetFunctionAddress)); ud_set_vendor(&ud_obj, UD_VENDOR_INTEL); ud_set_input_buffer(&ud_obj, (unsigned char*)pTargetFunctionAddress, Page); DWORD instrlen = 0; DisassemblyData.Count = 0; DisassemblyData.Length = 0; HookEngine_Memset(DisassemblyData.Instructions, 0, sizeof(DisassemblyData.Instructions)); HookEngine_Memset(DisassemblyData.InstuctionBuffer, 0, sizeof(DisassemblyData.InstuctionBuffer)); HookEngine_Memset(DisassemblyData.InstructionLengths, 0, sizeof(DisassemblyData.InstructionLengths)); do { instrlen = ud_disassemble(&ud_obj); if (instrlen) { if ((DisassemblyData.Length + instrlen) < MAX_INSTRUCTION_BUFFER) { DisassemblyData.Instructions[DisassemblyData.Count] = ud_obj; DisassemblyData.InstructionLengths[DisassemblyData.Count] = instrlen; DisassemblyData.Count++; HookEngine_Memcpy(&DisassemblyData.InstuctionBuffer[DisassemblyData.Length], ((BYTE*)pTargetFunctionAddress) + DisassemblyData.Length, instrlen); DisassemblyData.Length += instrlen; } } } while (DisassemblyData.Length < cbRequired && DisassemblyData.Count < MAX_INSTRUCTIONS && instrlen != 0); return DisassemblyData.Length; }
int main(int argc, char* argv[]) { ud_t ud_obj; ud_init(&ud_obj); FILE* f = fopen(argv[1], "r"); ud_set_input_file(&ud_obj, f); ud_set_vendor(&ud_obj, UD_VENDOR_INTEL); ud_set_syntax(&ud_obj, UD_SYN_INTEL); ud_set_mode(&ud_obj, 32); while (ud_disassemble(&ud_obj)) { printf("\t%s\n", ud_insn_asm(&ud_obj)); } return 0; }
//-------------------------------------------------------------------------------------- PVOID Hook(PVOID Function, PVOID Handler, PULONG pBytesPatched) { #ifdef _X86_ #define SIZEOFJUMP 6 #elif _AMD64_ #define SIZEOFJUMP 14 #endif ULONG Size = 0, CollectedSpace = 0; PUCHAR pInst = (PUCHAR)Function; if (pBytesPatched) { *pBytesPatched = NULL; } // initialize disassembler engine ud_t ud_obj; ud_init(&ud_obj); // set mode, syntax and vendor ud_set_mode(&ud_obj, UD_MODE); ud_set_syntax(&ud_obj, UD_SYN_INTEL); ud_set_vendor(&ud_obj, UD_VENDOR_INTEL); while (CollectedSpace < SIZEOFJUMP) { ud_set_input_buffer(&ud_obj, pInst, MAX_INST_LEN); // get length of instruction ULONG dwInstLen = ud_disassemble(&ud_obj); if (dwInstLen == 0) { // error while disassembling instruction DbgMsg(__FILE__, __LINE__, __FUNCTION__"() ERROR: Can't disassemble instruction at "IFMT"\n", pInst); return NULL; } if (ud_obj.mnemonic == UD_Ijmp || ud_obj.mnemonic == UD_Icall) { // call/jmp with relative address DbgMsg(__FILE__, __LINE__, __FUNCTION__"() call/jmp/jxx instruction at "IFMT"\n", pInst); return NULL; } for (int i = 0; i < 3; i++) { if (ud_obj.operand[i].type == UD_OP_JIMM) { // jxx with relative address DbgMsg(__FILE__, __LINE__, __FUNCTION__"() jxx instruction at "IFMT"\n", pInst); return NULL; } } pInst += dwInstLen; CollectedSpace += dwInstLen; if (ud_obj.mnemonic == UD_Iret || ud_obj.mnemonic == UD_Iretf || ud_obj.mnemonic == UD_Iiretw || ud_obj.mnemonic == UD_Iiretq || ud_obj.mnemonic == UD_Iiretd) { // end of the function thunk? DbgMsg(__FILE__, __LINE__, __FUNCTION__"() ret/retn/iret instruction at "IFMT"\n", pInst); break; } } if (SIZEOFJUMP > CollectedSpace) { DbgMsg(__FILE__, __LINE__, __FUNCTION__"() ERROR: not enough memory for jump\n"); return NULL; } ULONG CallGateSize = CollectedSpace + SIZEOFJUMP; // allocate memory for callgate PVOID CallGate = M_ALLOC(CallGateSize); if (CallGate) { // generate callgate memset(CallGate, 0x90, CallGateSize); // save begining of the function memcpy(CallGate, Function, CollectedSpace); #ifdef _X86_ // jump from callgate to function body // push imm32 *(PUCHAR)((PUCHAR)CallGate + CollectedSpace) = 0x68; *(PUCHAR *)((PUCHAR)CallGate + CollectedSpace + 1) = (PUCHAR)Function + SIZEOFJUMP; // ret *(PUCHAR)((PUCHAR)CallGate + CollectedSpace + 5) = 0xC3; #elif _AMD64_ // jmp qword [addr] *(PUSHORT)((PUCHAR)CallGate + CollectedSpace) = 0x25FF; *(PULONG)((PUCHAR)CallGate + CollectedSpace + 2) = 0; // addr dq XXXh *(PULONGLONG)((PUCHAR)CallGate + CollectedSpace + 6) = (ULONGLONG)Function + SIZEOFJUMP; #endif // jump from the function to callgate memset(Function, 0x90, CollectedSpace); #ifdef _X86_ // push imm32 *(PUCHAR)Function = 0x68; *(PUCHAR *)((PUCHAR)Function + 1) = (PUCHAR)Handler; // ret *(PUCHAR)((PUCHAR)Function + 5) = 0xC3; #elif _AMD64_ // jmp qword [addr] *(PUSHORT)Function = 0x25FF; *(PULONG)((PUCHAR)Function + 2) = 0; // addr dq XXXh *(PULONGLONG)((PUCHAR)Function + 6) = (ULONGLONG)Handler; #endif *pBytesPatched = CollectedSpace; return CallGate; } else { DbgMsg(__FILE__, __LINE__, "M_ALLOC() fails\n"); } return NULL; }