Example #1
0
// 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;
}
Example #2
0
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) {