// Extract the immediate offset from the first "mov eax, dword [eax+imm]" or // "mov eax, dword [rax+imm]" instruction that occurs. static int32_t _native_fetch_mov_eax_imm_offset(const uint8_t *func) { for (uint32_t idx = 0; idx < 32; idx++) { if(memcmp(func, "\x8b\x80", 2) == 0) { return *(uint32_t *)(func + 2); } if(memcmp(func, "\x8b\x40", 2) == 0) { return func[2]; } func += lde(func); } return -1; }
static void _native_copy_function(uint8_t *dst, const uint8_t *src) { int len = 0; do { src += len, dst += len; len = lde(src); memcpy(dst, src, len); #if !__x86_64__ if(*dst == 0xe8) { *(uint32_t *)(dst + 1) += src - dst; } #endif } while (*src != 0xc2 && *src != 0xc3); }
void LabelDefinitions::editLabelDef(QListWidgetItem* lbitem) { if(lbitem) { QString originalName = lbitem->text(); LabelSizeInfo labelInfo = LabelSizeInfo::getByName(originalName); // run the editor dialog LabelDefinitionEditor lde(this); lde.init(labelInfo); if(lde.exec() == QDialog::Accepted) { LabelSizeInfo labelDef = lde.getLabelDefinition(); XSqlQuery xqry; xqry.prepare( "UPDATE labeldef SET labeldef_name=:name, labeldef_papersize=:papersize, labeldef_columns=:columns, labeldef_rows=:rows, labeldef_width=:width, labeldef_height=:height, labeldef_start_offset_x=:offsetx, labeldef_start_offset_y=:offsety, labeldef_horizontal_gap=:hgap, labeldef_vertical_gap=:vgap WHERE labeldef_name=:original_name"); xqry.bindValue(":name", labelDef.name()); xqry.bindValue(":papersize", labelDef.paper()); xqry.bindValue(":columns", labelDef.columns()); xqry.bindValue(":rows", labelDef.rows()); xqry.bindValue(":width", labelDef.width()); xqry.bindValue(":height", labelDef.height()); xqry.bindValue(":offsetx", labelDef.startX()); xqry.bindValue(":offsety", labelDef.startY()); xqry.bindValue(":hgap", labelDef.xGap()); xqry.bindValue(":vgap", labelDef.yGap()); xqry.bindValue(":original_name", originalName); xqry.exec(); if (xqry.lastError().type() == QSqlError::NoError) { init(); } else { QMessageBox::critical(NULL, QString("Database Error"), xqry.lastError().databaseText()); } } } }
void LabelDefinitions::btnAdd_clicked() { // add a new querySource item LabelSizeInfo labelInfo; // run the editor dialog LabelDefinitionEditor lde(this); lde.init(labelInfo); if(lde.exec() == QDialog::Accepted) { LabelSizeInfo labelDef = lde.getLabelDefinition(); XSqlQuery xqry; xqry.prepare( "INSERT INTO labeldef (labeldef_name, labeldef_papersize, labeldef_columns, labeldef_rows, labeldef_width, labeldef_height, labeldef_start_offset_x, labeldef_start_offset_y, labeldef_horizontal_gap, labeldef_vertical_gap) VALUES (:name, :papersize, :columns, :rows, :width, :height, :offsetx, :offsety, :hgap, :vgap )" ); xqry.bindValue(":name", labelDef.name()); xqry.bindValue(":papersize", labelDef.paper()); xqry.bindValue(":columns", labelDef.columns()); xqry.bindValue(":rows", labelDef.rows()); xqry.bindValue(":width", labelDef.width()); xqry.bindValue(":height", labelDef.height()); xqry.bindValue(":offsetx", labelDef.startX()); xqry.bindValue(":offsety", labelDef.startY()); xqry.bindValue(":hgap", labelDef.xGap()); xqry.bindValue(":vgap", labelDef.yGap()); xqry.exec(); if (xqry.lastError().type() == QSqlError::NoError) { init(); } else { QMessageBox::critical(NULL, QString("Database Error"), xqry.lastError().databaseText()); } } }
uint8_t *hook_addrcb_RtlDispatchException(hook_t *h, uint8_t *module_address, uint32_t module_size) { (void) h; (void) module_size; uint8_t *ki_user_exception_dispatcher = (uint8_t *) GetProcAddress((HMODULE) module_address, "KiUserExceptionDispatcher"); if(ki_user_exception_dispatcher == NULL) { pipe("WARNING:ntdll!RtlDispatchException unable to find " "KiUserExceptionDispatcher [aborting hook]"); return NULL; } // We are looking for the first relative call instruction. for (uint32_t idx = 0; idx < 32; idx++) { if(*ki_user_exception_dispatcher == 0xe8) { return ki_user_exception_dispatcher + *(int32_t *)(ki_user_exception_dispatcher + 1) + 5; } ki_user_exception_dispatcher += lde(ki_user_exception_dispatcher); } return NULL; }
int hook_create_stub(uint8_t *tramp, const uint8_t *addr, int len) { const uint8_t *base_addr = addr; while (len > 0) { int length = lde(addr); if(length == 0) return -1; // How many bytes left? len -= length; // Unconditional jump with 32-bit relative offset. if(*addr == 0xe9) { const uint8_t *target = addr + *(int32_t *)(addr + 1) + 5; tramp += asm_jump(tramp, target); addr += 5; } // Call with 32-bit relative offset. else if(*addr == 0xe8) { const uint8_t *target = addr + *(int32_t *)(addr + 1) + 5; tramp += asm_call(tramp, target); addr += 5; } // Conditional jump with 32bit relative offset. else if(*addr == 0x0f && addr[1] >= 0x80 && addr[1] < 0x90) { #if __x86_64__ pipe("CRITICAL:Conditional jump and calls in 64-bit are " "considered unstable!"); #endif // TODO This can be stabilized by creating a 8-bit conditional // jump with 32/64-bit jumps at each target. However, this is // only required for 64-bit support and then only when this // instruction occurs at all in the original function - which is // currently not the case. // Conditional jumps consist of two bytes. *tramp++ = addr[0]; *tramp++ = addr[1]; // When a jmp/call is performed, then the relative offset + // the instruction pointer + the size of the instruction is the // resulting address, so that's our target address. // As we have already written the first one or two bytes of the // instruction we only have the relative address left - four bytes // in total. const uint8_t *target = addr + *(int32_t *)(addr + 2) + 6; // We have already copied the instruction opcode(s) itself so we // just have to calculate the relative address now. *(uint32_t *) tramp = target - tramp - 4; tramp += 4; addr += 6; } // Unconditional jump with 8bit relative offset. else if(*addr == 0xeb) { const uint8_t *target = addr + *(int8_t *)(addr + 1) + 2; tramp += asm_jump(tramp, target); addr += 2; // TODO Check the remaining length. Also keep in mind that any // following nop's behind this short jump can be included in the // remaining available space. } // Conditional jump with 8bit relative offset. else if(*addr >= 0x70 && *addr < 0x80) { #if __x86_64__ pipe("CRITICAL:Conditional jumps in 64-bit are " "considered unstable!"); #endif // TODO The same as for the 32-bit conditional jumps. // Same rules apply as with the 32bit relative offsets, except // for the fact that both conditional and unconditional 8bit // relative jumps take only one byte for the opcode. // Hex representation of the two types of 32bit jumps; // 8bit relative conditional jumps: 70..80 // 32bit relative conditional jumps: 0f 80..90 // Thus we have to add 0x10 to the opcode of 8bit relative // offset jump to obtain the 32bit relative offset jump // opcode. *tramp++ = 0x0f; *tramp++ = addr[0] + 0x10; // 8bit relative offset - we have to sign-extend it, by casting it // as signed char, in order to calculate the correct address. const uint8_t *target = addr + *(int8_t *)(addr + 1) + 2; // Calculate the relative address. *(uint32_t *) tramp = (uint32_t)(target - tramp - 4); tramp += 4; addr += 2; } #if __x86_64__ // In 64-bit mode we have RIP-relative mov and lea instructions. These // have to be relocated properly. Handles "mov reg64, qword [offset]" // and "lea reg64, qword [offset]". else if((*addr == 0x48 || *addr == 0x4c) && (addr[1] == 0x8b || addr[1] == 0x8d) && (addr[2] & 0xc7) == 0x05) { // Register index and full address. uint32_t reg = ((addr[2] >> 3) & 7) + (*addr == 0x4c ? 8 : 0); const uint8_t *target = addr + *(int32_t *)(addr + 3) + 7; // mov reg64, address tramp[0] = 0x48 + (reg >= 8); tramp[1] = 0xb8 + (reg & 7); *(const uint8_t **)(tramp + 2) = target; tramp += 10; // If it was a mov instruction then also emit the pointer // dereference part. if(addr[1] == 0x8b) { // mov reg64, qword [reg64] tramp[0] = reg < 8 ? 0x48 : 0x4d; tramp[1] = 0x8b; tramp[2] = (reg & 7) | ((reg & 7) << 3); tramp += 3; } addr += 7; } #endif // Return instruction indicates the end of basic block as well so we // have to check if we already have enough space for our hook.. else if((*addr == 0xc3 || *addr == 0xc2) && len > 0) {