IDA Python API: https://www.hex-rays.com/products/ida/support/idapython_docs/, 例子会持续更新补充

常用

patch_nop

def patch_nop(begin, end):
while(end>begin):
patch_byte(begin, 0x90)
begin=begin+1

patch jz/jnz

7.0

bg = 0
end = 0
addr = bg

def patch_nop(begin, end):
while(end>begin):
PatchByte(begin, 0x90)
begin=begin+1
def next_instr(addr):
return addr+ItemSize(addr)

while(addr<end):
next =next_instr(addr)
MakeCode(next)
if 'j' in GetMnem(addr) and 'j' in GetMnem(next) :
if GetOperandValue(addr, 0) == GetOperandValue(next, 0):
print 'jmp %08x'%addr
dest_addr = GetOperandValue(addr, 0)
patch_nop(addr, dest_addr)
addr=dest_addr
MakeCode(addr)
addr = next_instr(addr)
MakeCode(addr)

7.5

bg = 0
end = 0
addr = bg

def patch_nop(begin, end):
while(end>begin):
patch_byte(begin, 0x90)
begin=begin+1

def next_instr(addr):
return addr+get_item_size(addr)

while(addr<end):
next =next_instr(addr)
create_insn(next)
if 'j' in print_insn_mnem(addr) and 'j' in print_insn_mnem(next) :
if get_operand_value(addr, 0) == get_operand_value(next, 0):
print('jmp %08x'%addr)
dest_addr = get_operand_value(addr, 0)
patch_nop(addr, dest_addr)
addr=dest_addr
create_insn(addr)
addr = next_instr(addr)
create_insn(addr)

get_reg_value

get_reg_value("edx")

get_32bit/get_64bit

ida_bytes.get_32bit(ea)
ida_bytes.get_64bit(ea)

例子

Xman-2018-re0

import ida_bytes
buf = map(ord, ida_bytes.get_bytes(0x600B00, 182))
buf = map(lambda x: x ^ 0xC, buf)
ida_bytes.patch_bytes(0x600B00, str(bytearray(buf)))

KCTF 2019 Q1 第七题

bg = 0x00401000
end = 0x004BBE00
addr = bg

def patch_nop(begin, end):
while(end>begin):
PatchByte(begin, 0x90)
begin=begin+1
def next_instr(addr):
return addr+ItemSize(addr)
while(addr<end):
next =next_instr(addr)
MakeCode(next)
if 'j' in GetMnem(addr) and 'j' in GetMnem(next) :
if GetOperandValue(addr, 0) == GetOperandValue(next, 0):
print 'jmp %08x'%addr
dest_addr = GetOperandValue(addr, 0)
patch_nop(addr, dest_addr)
addr=dest_addr
MakeCode(addr)
if 'clc' == GetMnem(addr) and 'jnb' in GetMnem(next) :
print 'clc %08x'%addr
dest_addr = GetOperandValue(next, 0)
patch_nop(addr, dest_addr)
addr=dest_addr
MakeCode(addr)
if 'stc' == GetMnem(addr) and 'jb' in GetMnem(next) :
print 'clc %08x'%addr
dest_addr = GetOperandValue(next, 0)
patch_nop(addr, dest_addr)
addr=dest_addr
MakeCode(addr)
if 'call' in GetMnem(addr):
dest_addr = GetOperandValue(addr, 0)
idc.del_items(next_instr(addr))
MakeCode(dest_addr)
if "add esp, 4" == GetDisasm(dest_addr):
print 'call %08x'%addr
dest_addr=next_instr(dest_addr)
patch_nop(addr, dest_addr)
addr=dest_addr
MakeCode(addr)
addr = next_instr(addr)
MakeCode(addr)

*CTF 2019 Matr1x

题目:Matr1x

bg = 0x00002620
end = 0x00011320
addr = bg
index = 0


def patch_nop(begin, end):
while end > begin:
PatchByte(begin, 0x90)
begin += 1


def next_instr(addr):
return addr + ItemSize(addr)

def patch_global(addr, eax):
flag = GetMnem(addr)
ebx = GetOperandValue(addr, 1)
if flag == "xor":
eax ^= ebx
elif flag == "shl":
eax <<= ebx
elif flag == "sub":
eax -= ebx
elif flag == "add":
eax += ebx
elif flag == "and":
eax &= ebx
elif flag == "shr":
eax >>= ebx
elif flag == "or":
eax |= ebx

return eax & 0xFFFFFFFF

OperandValue = ['or', 'shr', 'and', 'add', 'sub', 'shl', 'xor']
Register = ['ebx', 'ecx', 'edx', 'eax']
Patch_jnz = ['xor', 'sub']

dest_addr = 0
_addr = 0
while addr < end:
next = next_instr(addr)
MakeCode(next)
if GetMnem(addr) in Patch_jnz and 'jnz' in GetMnem(next):
if GetOperandValue(addr, 0) == GetOperandValue(addr, 1):
print("sucess_patch_jnz: %x" % addr)
dest_addr = next_instr(next)
patch_nop(next, dest_addr)


if "call $+5" == GetDisasm(addr):
if "pop eax" == GetDisasm(next):
dest_addr = addr
for i in range(4):
dest_addr = next_instr(dest_addr)
MakeCode(dest_addr)
if "jmp" in GetMnem(dest_addr):
print("sucess_patch_call: %x" % addr)
patch_nop(addr, dest_addr)
PatchByte(dest_addr, 0xE8)

if "xchg" in GetMnem(addr):
if GetOperandValue(addr, 1) == GetOperandValue(addr, 0):
print("sucess_patch_xchg: %x" % addr)
patch_nop(addr, next)


if "jmp $+5" == GetDisasm(addr):
if "leave" in GetMnem(next):
patch_nop(addr, next)
print("sucess_patch_jmp: %x" % addr)
next = next_instr(next)
addr = next
next = next_instr(next)
next = next_instr(next)
patch_nop(addr, next)
PatchByte(addr, 0xC3)

if "[ebp" in GetDisasm(addr) and GetOperandValue(addr, 1) > 0x10000 and GetOperandValue(addr, 1) < (0xFFFFFFFF - 0x10000):
patch_nop(addr, next)
print("sucess_patch_ebp: %x" % addr)

if 0x0001329C >= GetOperandValue(addr, 1) >= 0x00013280:
print("sucess: %x" % addr)
eax = Dword(GetOperandValue(addr, 1))
_addr = addr
Reg = GetOperandValue(addr, 0)
while GetMnem(next) in OperandValue:
eax = patch_global(next, eax)
_addr = next
next = next_instr(next)
MakeCode(_addr)
MakeCode(next)
if GetOperandValue(_addr, 0) != GetOperandValue(next, 0):
break
elif GetOpnd(next, 1) in Register:
break
if GetOpnd(_addr, 0) == GetOpnd(_addr, 1):
Reg = -1
if Reg != -1:
addr = next_instr(addr)
patch_nop(addr, next)
if Reg == 3:
PatchByte(addr, 0xBB)
PatchDword(addr + 1, eax)
elif Reg == 2:
PatchByte(addr, 0xBA)
PatchDword(addr + 1, eax)
elif Reg == 1:
PatchByte(addr, 0xB9)
PatchDword(addr + 1, eax)
elif Reg == 0:
PatchByte(addr, 0xB8)
PatchDword(addr + 1, eax)
addr = next_instr(addr)
MakeCode(addr)