import struct start = 0x140001000 #起始位置 end = 0x14001C694 #结束位置 address_m = [0 for x in range(11)] address_target = ['push rax','push rax','pushfq','call $+5','pop rax','add rax,','mov ','popfq','pop rax','retn'] # 第一种花指令的特征 注意这个里面的每一条指令中间的空格数都要和ida之中展示的汇编代码相同,所以最好是进行复制粘贴
def check1(): cnt = 0 for i in range(9): if i == 5 or i == 6: cnt += GetDisasm(address_m[i]).find(address_target[i]) != -1 # GetDisasm:获得对应位置的汇编地址 因为'add rax,','mov '这两个指令中有数据,每个部分的代码就会不一样,所以使用find函数来判断是否存在 else: cnt += GetDisasm(address_m[i]) == address_target[i] # 除了那两个语句以外就需要判断剩下的这些语句是否相等就可以了 return cnt == 9 # 如果9条语句都和目标类型已知 就认为是第一种花指令 def check2(x,y): cnt = 0 cnt += print_insn_mnem(x) == "push" # idc.print_insn_mnem()获取操作符 判断操作符是否是push指令 cnt += print_insn_mnem(y) == "pop" # idc.print_insn_mnem(y)获取操作符 判断操作符是否是 pop 指令 cnt += print_operand(x,0) == print_operand(y,0) # idc.print_operand(x, 0) 获取第一个操作数 判断这两个指令的操作数是否相等 return cnt == 3 # 当以上的三个条件都满足的时候就是第二种花指令 def check3(): cnt = 0 cnt += print_insn_mnem(address_m[0]) == "push" # print_insn_mnem获取操作符 判断操作符是否是push cnt += get_operand_type(address_m[0], 0) == o_imm # 如果操作数是一个确定的数值的话,那么返回类型,值为 5 return cnt == 2 def nop(u,v): # u是指令的起始地址 v是结束的地址,但是v地址的指令不会被nop patch_add = u while(patch_add < v): patch_byte(patch_add,0x90) patch_add += 1 p = start while p <= end: address_m[0] = p p = next_head(p) # 利用了 idc.next_head()使当前地址不断增长
# 将第二种花指令进行nop while print_insn_mnem(p) == "nop": # 如果是nop语句就跳过 p = next_head(p) if check2(address_m[0], p) == 1: # 判断这两个连续的语句是否是满足第二种花指令的要求 p = next_head(p) # p定位到第二种花指令结束之后那个地址 nop(address_m[0], p) # address_m[0]是nop的起始位置 p是nop的结束位置 else: p = address_m[0] # 如果不是花指令起点又回到最初的那个地方
# 将第一种花指令nop address_m[0] = p # 将起始的地址放入到数组的第一项之中 for i in range(1, 11): # 判断这个地方连续的10条指令是否满足第一种花指令的要求,取出这10条指令的地址放入到数组之中 address_m[i] = next_head(address_m[i - 1])