void addDir32NBReloc(COFFBaseDefinedAtom *atom, const Atom *target, llvm::COFF::MachineTypes machine, size_t offsetInAtom) { switch (machine) { case llvm::COFF::IMAGE_FILE_MACHINE_I386: addReloc(atom, target, offsetInAtom, Reference::KindArch::x86, llvm::COFF::IMAGE_REL_I386_DIR32NB); return; case llvm::COFF::IMAGE_FILE_MACHINE_AMD64: addReloc(atom, target, offsetInAtom, Reference::KindArch::x86_64, llvm::COFF::IMAGE_REL_AMD64_ADDR32NB); return; default: llvm_unreachable("unsupported machine type"); } }
static void doReloc( asm_reloc *reloc, ins_operand *op, owl_reloc_type rtype, uint_32 *offset ) { //*********************************************************************************************** if( op == NULL ) return; if( !( OP_HAS_RELOC( op ) ) ) return; addReloc( reloc, op->reloc.target, relocType( op->reloc.type, rtype ), (unsigned)( (char *)offset - (char *)result ), ( op->flags & RELOC ) ); }
HOOKINFO *hookAPIFunction(const char *lib, const char *func, unsigned char *hookFunction) { HOOKINFO *hook = NULL; int routineCodeSize = 0; unsigned char *originalProc = NULL; unsigned char *codeBytePtr = NULL; HMODULE hlib = NULL; DWORD oldProtection = 0; int maxCodeLength = 1024; unsigned char opCode; void *newFunc = NULL; void *requiredFunctionAddress = NULL; if (!hookInit) is64BitProcess(); hlib = LoadLibraryA(lib); originalProc = (unsigned char *)GetProcAddress(hlib, func); codeBytePtr = originalProc; int off; hook = allocStructMem(HOOKINFO); if (!hook) return NULL; while (routineCodeSize == 0) { if (maxCodeLength-- <= 0) return NULL; switch (*codeBytePtr) { case OC_RET: { opCode = *(codeBytePtr + 1); //bak bakalim gercekten rutin sonunda miyiz? if (opCode == 0x90 || opCode == 0xcc || opCode == 0x00) { routineCodeSize = ((codeBytePtr + 1) - originalProc); if (verbose) xprintf("+ RET\n\n"); } } break; case OC_RET_N: { opCode = *(codeBytePtr + 2); if (opCode == 0x90 || opCode == 0xcc || opCode == 0x00) { routineCodeSize = ((codeBytePtr + 3) - originalProc); //ret + 2 byte rel16 byte ret val if (verbose) xprintf("+ RET X\n\n"); } } break; case OC_CALL_REL: { if (isMov(*(codeBytePtr - 1))) break; off = *((int *)(codeBytePtr + 1)); addReloc(hook,codeBytePtr + 1, off,4); if (verbose) xprintf("CALL_R8 found at 0x%p -> RELOFFSET: %x (%d)\n\n", codeBytePtr, off,off); codeBytePtr += 4; } break; case OC_CALL_MODRM: { //check previous opcode is one of the MOV opcode. //0xFF is EDI,EDI operand for MOV if (isMov(*(codeBytePtr - 1))) break; if (getInstrByModrm(*(codeBytePtr + 1)) == OCX_CALL) { off = *((int *)(codeBytePtr + 2)); addReloc(hook,codeBytePtr + 2, off, 4); if (verbose) xprintf("MODRM based CALL found at 0x%p -> RELOFFSET: %x (%d)\n\n", codeBytePtr, off,off); //detect size } } break; case OC_JCC_NEAR: //two byte len { //0x80 - 0x8F kosullu dallanma komutlari opCode = *(codeBytePtr + 1); if (opCode >= OC_JCC_BEGIN && opCode <= OC_JCC_END) { off = *((int *)(codeBytePtr + 1 + 1)); addReloc(hook,codeBytePtr + 2, off, 4); if (verbose) xprintf("REL_JCC found at 0x%p -> RELOFFSET: %x (%d)\n\n", codeBytePtr, off, off); codeBytePtr += 6; } } break; } codeBytePtr++; } requiredFunctionAddress = originalProc - routineCodeSize - 1024; newFunc = NULL; while (newFunc == NULL) { //nop alani icin ekstradan 32 byte bellek iste newFunc = VirtualAlloc(requiredFunctionAddress, routineCodeSize + 32, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); requiredFunctionAddress = ((unsigned char *)requiredFunctionAddress) - 0x1000; } //Yeni kod bellek bolgesini Nop ile dolduralim cop opcode kalmasin. memset(newFunc, 0x90, routineCodeSize + 32); //orjinal fonksiyon kodunu yeni alana tasiyoruz. memcpy(newFunc, originalProc, routineCodeSize); //orjinal kod bellek bolgesinin readonly modunu readwrite yapiyoruz. if (!VirtualProtect(originalProc, routineCodeSize, PAGE_EXECUTE_READWRITE, &oldProtection)) { xprintf("original code page could not switch to r/w mode"); VirtualFree(newFunc, routineCodeSize + 32, MEM_RELEASE); return NULL; } //orjinal bellek bolgesini nopluyoruz. guvenli olmasi icin memset(originalProc, 0x90, routineCodeSize); //x64 //64 bit ise hook fonksiyonumuzun yeri 64 bit araligina giren bir noktada //olabilir. o yuzden 64 bit bir registera adresi alip oraya zipliyoruz if (is64bit) { //64 bit trambolin fonksiyon cagrisi //mov rax, 64BIT_FUNCTION_ADDRESS //jmp rax *originalProc = (unsigned char)0x48; *(originalProc + 1) = (unsigned char)0xB8; *((long long int *)(originalProc + 2)) = (long long int)hookFunction; *((unsigned short *)(originalProc + 10)) = 0xe0ff; } else { //32 bit tramboline cagri //32 bit ise normal bir jump ile bolgeye ziplayabiliriz. //JMP NEW_RELATIVE_OFFSET int jmpOffset = ((unsigned char *)originalProc) - hookFunction; jmpOffset = -jmpOffset; jmpOffset -= 5; //our jmp instruction size *originalProc = (unsigned char)0xE9; *((int *)(originalProc + 1)) = jmpOffset; } VirtualProtect(originalProc, routineCodeSize, oldProtection, &oldProtection); xprintf("Original Function Location: 0x%p\n", originalProc); xprintf("New Function Location: 0x%p\n", newFunc); for (relocBranchList *beg = hook->relocList->head; beg != NULL; beg = beg->next) { recalculateAndPatch(originalProc, (unsigned char *)newFunc, beg->rbi); } hook->originalApi = newFunc; hook->hookFunction = hookFunction; return hook; }