bool operator()(InputIterator& next, InputIterator end,Token& tok) { tok = Token(); // skip past all nonreturnable delims // skip past the returnable only if we are not returning delims for (;next!=end && ( is_nonret(*next) || (is_ret(*next) && !return_delims_ ) );++next) { } if (next == end) { return false; } // if we are to return delims and we are one a returnable one // move past it and stop if (is_ret(*next) && return_delims_) { tok+=*next; ++next; } else // append all the non delim characters for (;next!=end && !is_nonret(*next) && !is_ret(*next);++next) tok+=*next; return true; }
//------------------------------------------------------------------------------ // Name: on_tableWidgetCallStack_cellClicked // Desc: Enables the "Run To Return" button if the selected cell is in the // column for return addresses. Disables it, otherwise. //------------------------------------------------------------------------------ void DialogBacktrace::on_tableWidgetCallStack_cellClicked(int row, int column) { row = row; //Not used, and the warning is annoying. QPushButton *return_to = ui->pushButtonReturnTo; if (is_ret(column)) { return_to->setEnabled(true); } else { return_to->setDisabled(true); } }
//------------------------------------------------------------------------------ // Name: on_pushButtonReturnTo_clicked() // Desc: Ensures that the selected item is a return address. If so, sets a // breakpoint at that address and continues execution. //------------------------------------------------------------------------------ void DialogBacktrace::on_pushButtonReturnTo_clicked() { //Make sure our current item is in the RETURN_COLUMN QTableWidgetItem *item = table_->currentItem(); if (!is_ret(item)) { return; } bool ok; edb::address_t address = address_from_table(&ok, item); //If we didn't get a valid address, then fail. //TODO: Make sure "ok" actually signifies success of getting an address... if (!ok) { int base = 16; QString msg("Could not return to 0x%x" + QString().number(address, base)); QMessageBox::information( this, "Error", msg); return; } //Now that we got the address, we can run. First check if bp @ that address //already exists. IBreakpoint::pointer bp = edb::v1::debugger_core->find_breakpoint(address); if (bp) { edb::v1::debugger_core->resume(edb::DEBUG_CONTINUE); return; } //Using the non-debugger_core version ensures bp is set in a valid region edb::v1::create_breakpoint(address); bp = edb::v1::debugger_core->find_breakpoint(address); if (bp) { bp->set_internal(true); bp->set_one_time(true); edb::v1::debugger_core->resume(edb::DEBUG_CONTINUE); return; } }
//------------------------------------------------------------------------------ // Name: do_find // Desc: //------------------------------------------------------------------------------ void DialogROPTool::do_find() { const QItemSelectionModel *const selModel = ui->tableView->selectionModel(); const QModelIndexList sel = selModel->selectedRows(); if(sel.size() == 0) { QMessageBox::critical( this, tr("No Region Selected"), tr("You must select a region which is to be scanned for gadgets.")); } else { unique_results_.clear(); if(IProcess *process = edb::v1::debugger_core->process()) { for(const QModelIndex &selected_item: sel) { const QModelIndex index = filter_model_->mapToSource(selected_item); if(auto region = *reinterpret_cast<const IRegion::pointer *>(index.internalPointer())) { edb::address_t start_address = region->start(); const edb::address_t end_address = region->end(); const edb::address_t orig_start = start_address; ByteShiftArray bsa(32); while(start_address < end_address) { // read in the next byte quint8 byte; if(process->read_bytes(start_address, &byte, 1)) { bsa << byte; const quint8 *p = bsa.data(); const quint8 *const l = p + bsa.size(); edb::address_t rva = start_address - bsa.size() + 1; QList<edb::Instruction> instruction_list; // eat up any NOPs in front... Q_FOREVER { edb::Instruction inst(p, l, rva); if(!is_nop(inst)) { break; } instruction_list << inst; p += inst.size(); rva += inst.size(); } edb::Instruction inst1(p, l, rva); if(inst1) { instruction_list << inst1; if(inst1.operation() == edb::Instruction::Operation::X86_INS_INT && inst1.operands()[0].general_type() == edb::Operand::TYPE_IMMEDIATE && (inst1.operands()[0].immediate() & 0xff) == 0x80) { add_gadget(instruction_list); } else if(inst1.operation() == edb::Instruction::Operation::X86_INS_SYSENTER) { add_gadget(instruction_list); } else if(inst1.operation() == edb::Instruction::Operation::X86_INS_SYSCALL) { add_gadget(instruction_list); } else if(is_ret(inst1)) { ui->progressBar->setValue(util::percentage(start_address - orig_start, region->size())); ++start_address; continue; } else { p += inst1.size(); rva += inst1.size(); // eat up any NOPs in between... Q_FOREVER { edb::Instruction inst(p, l, rva); if(!is_nop(inst)) { break; } instruction_list << inst; p += inst.size(); rva += inst.size(); } edb::Instruction inst2(p, l, rva); if(is_ret(inst2)) { instruction_list << inst2; add_gadget(instruction_list); } else if(inst2 && inst2.operation() == edb::Instruction::Operation::X86_INS_POP) { instruction_list << inst2; p += inst2.size(); rva += inst2.size(); edb::Instruction inst3(p, l, rva); if(inst3 && inst3.operation() == edb::Instruction::Operation::X86_INS_JMP) { instruction_list << inst3; if(inst2.operand_count() == 1 && inst2.operands()[0].general_type() == edb::Operand::TYPE_REGISTER) { if(inst3.operand_count() == 1 && inst3.operands()[0].general_type() == edb::Operand::TYPE_REGISTER) { if(inst2.operands()[0].reg() == inst3.operands()[0].reg()) { add_gadget(instruction_list); } } } } } } // TODO(eteran): catch things like "add rsp, 8; jmp [rsp - 8]" and similar, it's rare, // but could happen } } ui->progressBar->setValue(util::percentage(start_address - orig_start, region->size())); ++start_address; } } } } }