#获取一段汇编代码,以RET X指令作为终止信号
#CALL指令转换为push ret/jmp addr
#条件跳转默认成立
def GetAsm(StartAddr):
LstAsm = []
ObDis = Cs(CS_ARCH_X86, CS_MODE_32)
ObDis.detail = True
k = b'\x6A\x00'
asmm = ObDis.disasm(k, 0x401000)
for insn in asmm:
vcall = insn
state = True
while state:
code = ReadMemory(StartAddr, 30)
asmm = ObDis.disasm(code, StartAddr)
x = 0
for insn in asmm:
if insn.mnemonic == 'ret':
LstAsm.append(insn)
state = False
if x == 0:
if IsBranch(insn.mnemonic):
for i in insn.operands:
StartAddr = i.imm
break
elif insn.mnemonic == 'call':
for i in insn.operands:
LstAsm.append(vcall)
StartAddr = i.imm
break
else:
LstAsm.append(insn)
elif x == 1:
StartAddr = insn.address
break
x += 1
return LstAsm
因为要分析ret 0x10这条指令最终走向何处,所以我们要对程序运行时的栈进行模拟。
#获取一段汇编代码,以RET X指令作为终止信号
#CALL指令转换为push ret/jmp addr
#条件跳转默认成立
def GetAsm(StartAddr):
LstAsm = []
ObDis = Cs(CS_ARCH_X86, CS_MODE_32)
ObDis.detail = True
k = b'\x6A\x00'
asmm = ObDis.disasm(k, 0x401000)
for insn in asmm:
vcall = insn
state = True
while state:
code = ReadMemory(StartAddr, 30)
asmm = ObDis.disasm(code, StartAddr)
x = 0
for insn in asmm:
if insn.mnemonic == 'ret':
LstAsm.append(insn)
state = False
if x == 0:
if IsBranch(insn.mnemonic):
for i in insn.operands:
StartAddr = i.imm
break
elif insn.mnemonic == 'call':
for i in insn.operands:
LstAsm.append(vcall)
StartAddr = i.imm
break
else:
LstAsm.append(insn)
elif x == 1:
StartAddr = insn.address
break
x += 1
return LstAsm
#StackVar指定欲分析的栈变量
def AnalyzeStackVar(LstStackInfo, StackVar):
k = True
LstStackInfo.reverse()
for info in LstStackInfo:
info[StackVar] = k
if StackVar in info['write']:
k = False
if StackVar in info['read']:
k = True
LstStackInfo.reverse()
return
有了栈变量的在各指令上的活跃情况,我们就可以删除一些对死状态栈变量赋值的语句,具体代码如下。
#StackVar指定欲分析的栈变量
def AnalyzeStackVar(LstStackInfo, StackVar):
k = True
LstStackInfo.reverse()
for info in LstStackInfo:
info[StackVar] = k
if StackVar in info['write']:
k = False
if StackVar in info['read']:
k = True
LstStackInfo.reverse()
return
有了栈变量的在各指令上的活跃情况,我们就可以删除一些对死状态栈变量赋值的语句,具体代码如下。
def GetUnVar(info):
z = []
for x in range(0, MaxPtr + 1):
if not info[x]:
z.append(x)
return z
#默认在尾部时,所有栈变量都是活跃的
for i in range(0, MaxPtr + 1):
AnalyzeStackVar(LstStackInfo, i)
LstNewAsm = LstAsm[:]
LstNewStackInfo = LstStackInfo[:]
LstAsmInfo = []
for x, k in zip(LstNewAsm, LstNewStackInfo):
y = {}
y['Asm'] = x
y['Stack'] = k
LstAsmInfo.append(y)
LstNewAsmInfo = LstAsmInfo[:]
for asmi in LstAsmInfo:
#不涉及到栈指针调整的指令可以直接删除
if (len(asmi['Stack']['write']) != 0) and (IsListIn(asmi['Stack']['write'], GetUnVar(asmi['Stack']))) and (asmi['Asm'].mnemonic not in ['push', 'pushal', 'pushfd', 'pushad', 'pop', 'popfd', 'popal', 'popad']):
print('位于%X处的指令被清除了' % asmi['Asm'].address)
LstNewAsmInfo.remove(asmi)
输出情况并不是非常理想,仅删除了3条语句。
def GetUnVar(info):
z = []
for x in range(0, MaxPtr + 1):
if not info[x]:
z.append(x)
return z
#默认在尾部时,所有栈变量都是活跃的
for i in range(0, MaxPtr + 1):
AnalyzeStackVar(LstStackInfo, i)
LstNewAsm = LstAsm[:]
LstNewStackInfo = LstStackInfo[:]
LstAsmInfo = []
for x, k in zip(LstNewAsm, LstNewStackInfo):
y = {}
y['Asm'] = x
y['Stack'] = k
LstAsmInfo.append(y)
LstNewAsmInfo = LstAsmInfo[:]
for asmi in LstAsmInfo:
#不涉及到栈指针调整的指令可以直接删除
if (len(asmi['Stack']['write']) != 0) and (IsListIn(asmi['Stack']['write'], GetUnVar(asmi['Stack']))) and (asmi['Asm'].mnemonic not in ['push', 'pushal', 'pushfd', 'pushad', 'pop', 'popfd', 'popal', 'popad']):
print('位于%X处的指令被清除了' % asmi['Asm'].address)
LstNewAsmInfo.remove(asmi)