def add_context(self, data, library_onload=None): if self.columnCount() == 0: self.setColumnCount(3) self.setHorizontalHeaderLabels(['tid', 'pc', 'symbol']) row = self.rowCount() self.insertRow(row) q = ContextItem(data, str(data['tid'])) q.setForeground(Qt.darkCyan) self.setItem(row, 0, q) is_java = data['is_java'] if not is_java: q = MemoryAddressWidget(data['ptr']) else: parts = data['ptr'].split('.') q = NotEditableTableWidgetItem(parts[len(parts) - 1]) q.setForeground(Qt.red) q.setFlags(Qt.NoItemFlags) self.setItem(row, 1, q) if library_onload is None: if not is_java: q = NotEditableTableWidgetItem( '%s - %s' % (data['symbol']['moduleName'], data['symbol']['name'])) else: q = NotEditableTableWidgetItem('.'.join(parts[:len(parts) - 1])) else: q = NotEditableTableWidgetItem('loading %s' % library_onload) q.setFlags(Qt.NoItemFlags) q.setForeground(Qt.gray) self.setItem(row, 2, q) self.resizeRowsToContents() self.horizontalHeader().setStretchLastSection(True)
def set_ranges(self, ranges): self.setRowCount(0) i = 0 for range in ranges: self.insertRow(i) q = MemoryAddressWidget(range['base']) q.set_size(range['size']) self.setItem(i, 0, q) q = NotEditableTableWidgetItem(str(range['size'])) q.setFlags(Qt.NoItemFlags) self.setItem(i, 1, q) q = NotEditableTableWidgetItem(range['protection']) q.setFlags(Qt.NoItemFlags) q.setTextAlignment(Qt.AlignCenter) self.setItem(i, 2, q) if 'file' in range: q = NotEditableTableWidgetItem(range['file']['path']) q.setFlags(Qt.NoItemFlags) q.setForeground(Qt.lightGray) self.setItem(i, 3, q) else: self.setItem(i, 3, NotEditableTableWidgetItem('')) i += 1 self.resizeRowsToContents() self.horizontalHeader().setStretchLastSection(True) self.sortByColumn(0, 0)
def hook_onload(self, input=None): if input is None or not isinstance(input, str): input = InputDialog.input(hint='insert module name') if not input[0]: return input = input[1] if not input.endswith('.so'): input += '.so' if input in self.onloads: return self.insertRow(self.rowCount()) h = Hook() h.set_ptr(0) h.set_input(input) self.onloads[input] = h q = HookWidget(h.get_input()) q.set_hook_data(h) q.setForeground(Qt.darkGreen) self.setItem(self.rowCount() - 1, 0, q) q = NotEditableTableWidgetItem(hex(0)) q.setForeground(Qt.gray) self.setItem(self.rowCount() - 1, 1, q) q = NotEditableTableWidgetItem('-') q.setForeground(Qt.gray) self.setItem(self.rowCount() - 1, 2, q) self.app.get_script().exports.onload(input) self.resizeRowToContents(0) self.resizeRowToContents(1)
def hook_on_load(self): input = InputDialog.input(hint='insert module name') if input[0]: module = input[1] if not module.endswith('.so'): module += '.so' self.insertRow(self.rowCount()) h = Hook() h.set_ptr(0) h.set_input(module) h.set_widget_row(self.rowCount() - 1) self.onloads[module] = h q = HookWidget(h.get_input()) q.set_hook_data(h) q.setForeground(Qt.darkGreen) self.setItem(self.rowCount() - 1, 0, q) q = NotEditableTableWidgetItem(hex(0)) q.setForeground(Qt.gray) self.setItem(self.rowCount() - 1, 1, q) q = NotEditableTableWidgetItem('-') q.setForeground(Qt.gray) self.setItem(self.rowCount() - 1, 2, q) self.app.get_script().exports.onload(module)
def add_hook(self): input = InputDialog.input(hint='insert pointer') if input[0]: ptr = int(self.app.get_script().exports.getpt(input[1]), 16) if ptr > 0: hook = self.app.get_script().exports.hook(ptr) if hook: self.insertRow(self.rowCount()) h = Hook() h.set_ptr(ptr) h.set_input(input[1]) h.set_widget_row(self.rowCount() - 1) self.hooks[ptr] = h q = HookWidget(h.get_input()) q.set_hook_data(h) q.setForeground(Qt.gray) self.setItem(self.rowCount() - 1, 0, q) q = NotEditableTableWidgetItem(hex(ptr)) q.setForeground(Qt.red) self.setItem(self.rowCount() - 1, 1, q) q = NotEditableTableWidgetItem('0') self.setItem(self.rowCount() - 1, 2, q) self.resizeColumnsToContents()
def on_enumeration_complete(self, methods): for method in sorted(methods): row = self.rowCount() self.insertRow(row) q = NotEditableTableWidgetItem(method) q.setFlags(Qt.ItemIsEnabled) self.setItem(row, 0, q)
def add_context(self, data, library_onload=None): row = self.rowCount() self.insertRow(row) q = ContextItem(data, str(data['tid'])) q.setForeground(Qt.darkCyan) self.setItem(row, 0, q) is_java = data['is_java'] if not is_java: q = NotEditableTableWidgetItem(data['ptr']) else: parts = data['ptr'].split('.') q = NotEditableTableWidgetItem(parts[len(parts) - 1]) q.setForeground(Qt.red) self.setItem(row, 1, q) if library_onload is None: if not is_java: q = NotEditableTableWidgetItem( '%s - %s' % (data['symbol']['moduleName'], data['symbol']['name'])) else: q = NotEditableTableWidgetItem('.'.join(parts[:len(parts) - 1])) else: q = NotEditableTableWidgetItem('loading %s' % library_onload) q.setForeground(Qt.gray) self.setItem(row, 2, q) self.resizeRowToContents(0) self.resizeRowToContents(1)
def add(self, name, value, handle=None): row = self.rowCount() self.insertRow(row) if handle is not None: self.setItem(row, 0, HandleWidget(handle, name)) else: self.setItem(row, 0, NotEditableTableWidgetItem(name)) self.setItem(row, 1, NotEditableTableWidgetItem(str(value)))
def _finalize_asm_view(self): self.setRowCount(0) if self.app.get_arch() == 'arm64': arch = CS_ARCH_ARM64 self.cs_mode = CS_MODE_ARM else: arch = CS_ARCH_ARM md = Cs(arch, self.cs_mode) s_row = -1 for i in md.disasm(self.data['data'][self.asm_data_start:self.asm_data_start+64], self.asm_parse_start): row = self.rowCount() self.insertRow(row) if i.address == self.asm_parse_start: s_row = row w = NotEditableTableWidgetItem('0x%x' % i.address) w.setForeground(Qt.red) self.setItem(row, 0, w) w = NotEditableTableWidgetItem(i.mnemonic) self.setItem(row, 1, w) w = NotEditableTableWidgetItem(i.op_str) self.setItem(row, 2, w) self.resizeColumnsToContents() if s_row >= 0: self.setCurrentCell(s_row, 0) index = self.currentIndex() self.scrollTo(index, QAbstractItemView.PositionAtCenter) self.setCurrentCell(s_row, 0)
def add(self, name, ref): row = self.rowCount() self.insertRow(row) self.setItem(row, 0, NotEditableTableWidgetItem(name)) overloads = ref['overloads'] for i in range(0, len(overloads)): overload = overloads[i] if i > 0: row = self.rowCount() self.insertRow(row) args = [] for arg in overload['args']: args.append(arg['className']) self.setItem(row, 1, NotEditableTableWidgetItem(overload['return']['className'])) self.setItem(row, 2, NotEditableTableWidgetItem('(%s)' % ', '.join(args)))
def _set_memory_view(self): self.view = VIEW_HEX self.setRowCount(0) self.setColumnCount(18) s_row = -1 s_col = 0 for r in hexdump(self.data['data'], result='return').split('\n'): row = self.rowCount() self.insertRow(row) rr = r.split(':') offset = int(rr[0], 16) + self.data['start'] w = NotEditableTableWidgetItem(hex(offset)) w.setForeground(Qt.red) self.setItem(row, 0, w) rr = rr[1].split(' ') hex_line = rr[0][1:] + ' ' + rr[1] hex_line = hex_line.split(' ') for i in range(0, len(hex_line)): qq = ByteWidget(hex_line[i]) qq.set_value(int(hex_line[i], 16)) self.setItem(row, i + 1, qq) if -1 < self.data['jt'] == offset + i: qq.setSelected(True) s_row = row s_col = i + 1 self.setItem(row, 17, NotEditableTableWidgetItem(rr[2])) if s_row > -1: self.setCurrentCell(s_row, 0) index = self.currentIndex() self.scrollTo(index, QAbstractItemView.PositionAtCenter) self.setCurrentCell(s_row, s_col) self.horizontalHeader().show() h_labels = [ '' ] for i in range(0, 16): h_labels.append(hex(i)) h_labels.append('') self.setHorizontalHeaderLabels(h_labels) self.resizeColumnsToContents()
def add_context(self, data, library_onload=None): row = self.rowCount() self.insertRow(row) q = ContextItem(data, str(data['tid'])) q.setForeground(Qt.darkCyan) self.setItem(row, 0, q) q = NotEditableTableWidgetItem(data['context']['pc']) q.setForeground(Qt.red) self.setItem(row, 1, q) if library_onload is None: q = NotEditableTableWidgetItem('%s - %s' % ( data['symbol']['moduleName'], data['symbol']['name'])) else: q = NotEditableTableWidgetItem('loading %s' % library_onload) q.setForeground(Qt.gray) self.setItem(row, 2, q) self.resizeColumnsToContents()
def build_imports_row(table, item): row = table.rowCount() table.insertRow(row) q = NotEditableTableWidgetItem(item['name']) q.setForeground(Qt.gray) table.setItem(row, 0, q) q = MemoryAddressWidget(item['address']) table.setItem(row, 1, q) q = NotEditableTableWidgetItem(item['module']) table.setItem(row, 2, q) q = NotEditableTableWidgetItem(item['type']) table.setItem(row, 3, q)
def build_exports_table(self, table, exports): if len(exports) > 0: table.setMinimumWidth(int(self.app.width() / 3)) table.setColumnCount(3) table.setHorizontalHeaderLabels(['name', 'address', 'type']) for export in exports: row = table.rowCount() table.insertRow(row) q = NotEditableTableWidgetItem(export['name']) q.setForeground(Qt.gray) table.setItem(row, 0, q) q = NotEditableTableWidgetItem(export['address']) q.setForeground(Qt.red) table.setItem(row, 1, q) q = NotEditableTableWidgetItem(export['type']) table.setItem(row, 2, q) table.resizeColumnsToContents() table.horizontalHeader().setStretchLastSection(True)
def build_symbol_table(self, table, data): table.setMinimumWidth( int(self.app_window.get_app_instance().width() / 3)) table.setColumnCount(3) table.setHorizontalHeaderLabels(['name', 'address', 'module']) for sym in sorted(data, key=lambda x: x['name']): row = table.rowCount() table.insertRow(row) q = NotEditableTableWidgetItem(sym['name']) q.setForeground(Qt.gray) table.setItem(row, 0, q) q = NotEditableTableWidgetItem(sym['address']) q.setForeground(Qt.red) table.setItem(row, 1, q) q = NotEditableTableWidgetItem(sym['moduleName']) table.setItem(row, 2, q) table.resizeColumnToContents(1)
def hook_native_callback(self, ptr): self.insertRow(self.rowCount()) h = Hook() h.set_ptr(ptr) h.set_input(self.temporary_input) if self.native_pending_args: h.set_condition(self.native_pending_args['condition']) h.set_logic(self.native_pending_args['logic']) self.hooks[ptr] = h q = HookWidget(h.get_input()) q.set_hook_data(h) q.setForeground(Qt.gray) self.setItem(self.rowCount() - 1, 0, q) q = NotEditableTableWidgetItem(hex(ptr)) q.setForeground(Qt.red) self.setItem(self.rowCount() - 1, 1, q) q = NotEditableTableWidgetItem('0') q.setForeground(Qt.gray) self.setItem(self.rowCount() - 1, 2, q) self.resizeRowToContents(0) self.resizeRowToContents(1)
def hook_java_callback(self, class_method): self.insertRow(self.rowCount()) h = Hook() h.set_ptr(1) h.set_input(class_method) if self.java_pending_args: h.set_condition(self.java_pending_args['condition']) h.set_logic(self.java_pending_args['logic']) parts = class_method.split('.') self.java_hooks[class_method] = h q = HookWidget('.'.join(parts[:len(parts)-1])) q.set_hook_data(h) q.setForeground(Qt.darkYellow) self.setItem(self.rowCount() - 1, 0, q) q = NotEditableTableWidgetItem(parts[len(parts) - 1]) self.setItem(self.rowCount() - 1, 1, q) q = NotEditableTableWidgetItem('0') q.setForeground(Qt.gray) self.setItem(self.rowCount() - 1, 2, q) self.resizeRowToContents(0) self.resizeRowToContents(1)
def add_memory_hook(self, uc, access, address, value): res = None if access == UC_MEM_READ: if self._require_register_result is not None: res = '%s = %s' % (self._require_register_result[1], hex(value)) else: if self.item(self.rowCount() - 1, 4) is not None: res = '%s, %s = %s' % (self.item( self.rowCount() - 1, 4).text(), hex(address), hex(value)) else: res = '%s = %s' % (hex(address), hex(value)) if res is not None: # invalidate self._require_register_result = None self.setItem(self.rowCount() - 1, 4, NotEditableTableWidgetItem(res))
def hook_java_callback(self, hook): if self.columnCount() == 0: self.setColumnCount(2) self.setHorizontalHeaderLabels(['input', 'address']) self.insertRow(self.rowCount()) parts = hook.get_input().split('.') q = HookWidget('.'.join(parts[:len(parts) - 1])) q.set_hook_data(hook) q.setFlags(Qt.NoItemFlags) q.setForeground(Qt.darkYellow) self.setItem(self.rowCount() - 1, 0, q) q = NotEditableTableWidgetItem(parts[len(parts) - 1]) q.setFlags(Qt.NoItemFlags) q.setForeground(Qt.white) self.setItem(self.rowCount() - 1, 1, q) self.resizeRowsToContents() self.horizontalHeader().setStretchLastSection(True)
def hook_onload_callback(self, input=None): if self.columnCount() == 0: self.setColumnCount(2) self.setHorizontalHeaderLabels(['input', 'address']) h = self.app.get_dwarf().hook_onload(input) self.insertRow(self.rowCount()) q = HookWidget(h.get_input()) q.set_hook_data(h) q.setFlags(Qt.NoItemFlags) q.setForeground(Qt.darkGreen) self.setItem(self.rowCount() - 1, 0, q) q = NotEditableTableWidgetItem(hex(0)) q.setFlags(Qt.NoItemFlags) q.setForeground(Qt.gray) self.setItem(self.rowCount() - 1, 1, q) self.resizeRowsToContents() self.horizontalHeader().setStretchLastSection(True)
def _add_mem_address_item_if_needed(self, row): if not isinstance(self.memory_panel.item(row, 0), MemoryAddressWidget): address = self.memory_panel.range.base + (row * 16) q = MemoryAddressWidget(hex(address)) q.set_address(address) q.setFlags(Qt.NoItemFlags) q.setForeground(Qt.red) self.memory_panel.setItem(row, 0, q) col = 0 offset = address - self.memory_panel.range.base while col < 16: q = ByteWidget() if offset + col >= self.memory_panel.range.size: break try: q.set_value(self.memory_panel.range.data[offset + col]) except: self.work = False break q.set_ptr(address + col) q.set_offset(offset + col) self.memory_panel.setItem(row, col + 1, q) col += 1 tail = offset + 16 if tail > self.memory_panel.range.tail: tail = self.memory_panel.range.tail t = '' for byte in self.memory_panel.range.data[offset:tail]: if not PY3K: byte = ord(byte) if 0x20 <= byte <= 0x7E: t += chr(byte) else: t += '.' q = NotEditableTableWidgetItem(t) q.setFlags(Qt.NoItemFlags) q.setForeground(Qt.darkYellow) self.memory_panel.setItem(row, 17, q)
def hook_native_callback(self, ptr): self.insertRow(self.rowCount()) h = Hook(Hook.HOOK_NATIVE) h.set_ptr(ptr) h.set_input(self.temporary_input) self.temporary_input = '' if self.native_pending_args: h.set_condition(self.native_pending_args['condition']) h.set_logic(self.native_pending_args['logic']) self.native_pending_args = {} self.hooks[ptr] = h q = HookWidget(h.get_input()) q.set_hook_data(h) q.setFlags(Qt.NoItemFlags) q.setForeground(Qt.gray) self.setItem(self.rowCount() - 1, 0, q) q = NotEditableTableWidgetItem(hex(ptr)) q.setForeground(Qt.red) self.setItem(self.rowCount() - 1, 1, q) self.resizeRowsToContents() self.horizontalHeader().setStretchLastSection(True)
def hook_onload(self, input=None): if input is None or not isinstance(input, str): input = InputDialog.input(self.app, hint='insert module name', placeholder='libtarget.so') if not input[0]: return input = input[1] if len(input) == 0: return if not input.endswith('.so'): input += '.so' if input in self.app.get_dwarf().on_loads: return if self.columnCount() == 0: self.setColumnCount(2) self.setHorizontalHeaderLabels(['input', 'address']) h = self.app.get_dwarf().hook_onload(input) self.insertRow(self.rowCount()) q = HookWidget(h.get_input()) q.set_hook_data(h) q.setFlags(Qt.NoItemFlags) q.setForeground(Qt.darkGreen) self.setItem(self.rowCount() - 1, 0, q) q = NotEditableTableWidgetItem(hex(0)) q.setFlags(Qt.NoItemFlags) q.setForeground(Qt.gray) self.setItem(self.rowCount() - 1, 1, q) self.resizeRowsToContents() self.horizontalHeader().setStretchLastSection(True)
def hook_onload(self, input=None): if input is None or not isinstance(input, str): input = InputDialog.input(hint='insert module name') if not input[0]: return input = input[1] if len(input) == 0: return if not input.endswith('.so'): input += '.so' if input in self.onloads: return self.insertRow(self.rowCount()) h = Hook(Hook.HOOK_ONLOAD) h.set_ptr(0) h.set_input(input) self.onloads[input] = h q = HookWidget(h.get_input()) q.set_hook_data(h) q.setFlags(Qt.NoItemFlags) q.setForeground(Qt.darkGreen) self.setItem(self.rowCount() - 1, 0, q) q = NotEditableTableWidgetItem(hex(0)) q.setFlags(Qt.NoItemFlags) q.setForeground(Qt.gray) self.setItem(self.rowCount() - 1, 1, q) self.app.dwarf_api('hookOnLoad', input) self.resizeRowsToContents() self.horizontalHeader().setStretchLastSection(True)
def hook_java_callback(self, class_method): self.insertRow(self.rowCount()) h = Hook(Hook.HOOK_JAVA) h.set_ptr(1) h.set_input(class_method) if self.java_pending_args: h.set_condition(self.java_pending_args['condition']) h.set_logic(self.java_pending_args['logic']) parts = class_method.split('.') self.java_hooks[class_method] = h q = HookWidget('.'.join(parts[:len(parts) - 1])) q.set_hook_data(h) q.setFlags(Qt.NoItemFlags) q.setForeground(Qt.darkYellow) self.setItem(self.rowCount() - 1, 0, q) q = NotEditableTableWidgetItem(parts[len(parts) - 1]) q.setFlags(Qt.NoItemFlags) q.setForeground(Qt.white) self.setItem(self.rowCount() - 1, 1, q) self.resizeRowsToContents() self.horizontalHeader().setStretchLastSection(True)
def disasm(self, _range=None): self.setRowCount(0) if _range: self.range = _range if self.range is None: return 1 if len(self.history) == 0 or self.history[ len(self.history) - 1] != self.range.start_address: self.history.append(self.range.start_address) if len(self.history) > 25: self.history.pop(0) md = Cs(self.cs_arch, self.cs_mode) md.detail = True insts = 0 for i in md.disasm(self.range.data[self.range.start_offset:], self.range.start_address): if insts > 128: break instruction = Instruction(self.dwarf, i) row = self.rowCount() self.insertRow(row) w = MemoryAddressWidget('0x%x' % i.address) w.setFlags(Qt.NoItemFlags) w.setForeground(Qt.red) w.set_offset(self.range.base - i.address) self.setItem(row, 0, w) w = NotEditableTableWidgetItem( binascii.hexlify(instruction.bytes).decode('utf8')) w.setFlags(Qt.NoItemFlags) w.setForeground(Qt.darkYellow) self.setItem(row, 1, w) if instruction.is_jump and instruction.jump_address != 0: w = MemoryAddressWidget(instruction.op_str) w.set_address(instruction.jump_address) else: w = NotEditableTableWidgetItem(instruction.op_str) w.setFlags(Qt.NoItemFlags) w.setForeground(Qt.lightGray) self.setItem(row, 3, w) w = NotEditableTableWidgetItem(instruction.mnemonic.upper()) w.setFlags(Qt.NoItemFlags) w.setForeground(Qt.white) w.setTextAlignment(Qt.AlignCenter) w.setFont(QFont(None, 11, QFont.Bold)) self.setItem(row, 2, w) if instruction.symbol_name is not None: w = NotEditableTableWidgetItem( '%s (%s)' % (instruction.symbol_name, instruction.symbol_module)) w.setFlags(Qt.NoItemFlags) w.setForeground(Qt.lightGray) self.setItem(row, 4, w) insts += 1 self.scrollToTop() return 0
def append_var(self, key, var, type): row = self.rowCount() self.insertRow(row) q = NotEditableTableWidgetItem(key) q.setForeground(Qt.gray) self.setItem(row, 0, q) q = NotEditableTableWidgetItem(str(var)) if type == 0: q.setForeground(Qt.red) elif type == 1: q.setForeground(Qt.darkGreen) else: q.setForeground(Qt.darkCyan) self.setItem(row, 1, q) self.resizeColumnsToContents() return row
def set_backtrace(self, bt): self.setRowCount(0) if type(bt) is list: # native backtrace self.is_java_bt = False self.setHorizontalHeaderLabels(['symbol', 'address']) for a in bt: row = self.rowCount() self.insertRow(row) name = a['name'] if name is None: q = NotEditableTableWidgetItem('-') q.setFlags(Qt.NoItemFlags) q.setForeground(Qt.gray) self.setItem(row, 0, q) else: q = NotEditableTableWidgetItem(name) q.setFlags(Qt.NoItemFlags) q.setForeground(Qt.darkGreen) self.setItem(row, 0, q) q = MemoryAddressWidget(a['address']) self.setItem(row, 1, q) elif type(bt) is str: # Java backtrace self.is_java_bt = True self.setHorizontalHeaderLabels(['method', 'source']) parts = bt.split('\n') for i in range(0, len(parts)): if i == 0: continue p = parts[i].replace('\t', '') p = p.split('(') if len(p) != 2: continue row = self.rowCount() self.insertRow(row) q = NotEditableTableWidgetItem(p[0]) q.setFlags(Qt.NoItemFlags) q.setForeground(Qt.darkYellow) self.setItem(row, 0, q) q = NotEditableTableWidgetItem(p[1].replace(')', '')) q.setFlags(Qt.NoItemFlags) q.setForeground(Qt.gray) self.setItem(row, 1, q) self.resizeRowsToContents() self.horizontalHeader().setStretchLastSection(True)
def _work(): matches = app.dwarf_api('findSymbol', input) if len(matches) > 0: panel.setColumnCount(3) panel.setHorizontalHeaderLabels(['name', 'address', 'module']) for ptr in matches: sym = app.dwarf_api('getSymbolByAddress', ptr) if sym is None: continue if sym['name'] == '' or sym['name'] is None: sym['name'] = sym['address'] row = panel.rowCount() panel.insertRow(row) q = NotEditableTableWidgetItem(sym['name']) q.setFlags(Qt.NoItemFlags) q.setForeground(Qt.white) panel.setItem(row, 0, q) q = MemoryAddressWidget(sym['address']) panel.setItem(row, 1, q) q = NotEditableTableWidgetItem(sym['moduleName']) q.setFlags(Qt.NoItemFlags) q.setForeground(Qt.lightGray) panel.setItem(row, 2, q) panel.sortByColumn(0, 0) if row == 0: panel.resizeColumnsToContents() panel.horizontalHeader().setStretchLastSection(True)
def add_bytes_match_item(self, address, symbol): r = self.rowCount() if r == 0: self.setColumnCount(2) self.setHorizontalHeaderLabels(['address', 'symbol']) self.insertRow(r) self.setItem(r, 0, MemoryAddressWidget(address)) if symbol['moduleName'] is not None: sym = symbol['moduleName'] if symbol['name'] is not None: sym = '%s (%s)' % (symbol['name'], sym) q = NotEditableTableWidgetItem(sym) q.setFlags(Qt.NoItemFlags) q.setForeground(Qt.lightGray) else: q = NotEditableTableWidgetItem('-') q.setFlags(Qt.NoItemFlags) q.setForeground(Qt.gray) self.setItem(r, 1, q) if r == 0: self.resizeColumnsToContents() self.horizontalHeader().setStretchLastSection(True)