IDA工具类
Operand=操作数
ArmSpecialRegNameList = [
"SB",
"TR",
"XR",
"IP",
"IP0",
"IP1",
"PR",
"SP",
"FP",
"LR",
"PC",
]
class Operand:
o_void = 0
o_reg = 1
o_mem = 2
o_phrase = 3
o_displ = 4
o_imm = 5
o_far = 6
o_near = 7
o_idpspec0 = 8
o_idpspec1 = 9
o_idpspec2 = 10
o_idpspec3 = 11
o_idpspec4 = 12
o_idpspec5 = 13
o_trreg = o_idpspec0
o_dbreg = o_idpspec1
o_crreg = o_idpspec2
o_fpreg = o_idpspec3
o_mmxreg = o_idpspec4
o_xmmreg = o_idpspec5
o_reglist = o_idpspec1
o_creglist = o_idpspec2
o_creg = o_idpspec3
o_fpreglist = o_idpspec4
o_text = o_idpspec5
o_cond = o_idpspec5 + 1
o_spr = o_idpspec0
o_twofpr = o_idpspec1
o_shmbme = o_idpspec2
o_crf = o_idpspec3
o_crb = o_idpspec4
o_dcr = o_idpspec5
offStr = "Off"
valStr = "Val"
def __init__(self, operand, type, value):
self.operand = operand
self.type = type
self.value = value
self.baseReg = None
self.indexReg = None
self.displacement = None
self._postInit()
def _postInit(self):
if self.isDispl():
displMatch = re.search("\[(?P<baseReg>\w+)(,(?P<displacement>#[\w\-\.]+))?\]", self.operand)
if displMatch:
self.baseReg = displMatch.group("baseReg")
self.displacement = displMatch.group("displacement")
elif self.isPhrase():
phraseMatch = re.search("\[(?P<baseReg>\w+),(?P<indexReg>\w+)\]", self.operand)
if phraseMatch:
self.baseReg = phraseMatch.group("baseReg")
self.indexReg = phraseMatch.group("indexReg")
def __str__(self):
valStr = ""
if self.value <= 0:
valStr = "%s" % self.value
else:
valStr = "0x%X" % self.value
extraInfo = ""
if self.isDispl():
extraInfo = ",bsReg=%s,idxReg=%s,displ=%s" % (self.baseReg, self.indexReg, self.displacement)
elif self.isPhrase():
extraInfo = ",bsReg=%s,idxReg=%s" % (self.baseReg, self.indexReg)
curOpStr = "<Operand: op=%s,type=%d,val=%s%s>" % (self.operand, self.type, valStr, extraInfo)
return curOpStr
@staticmethod
def listToStr(operandList):
operandStrList = [str(eachOperand) for eachOperand in operandList]
operandListAllStr = ", ".join(operandStrList)
operandListAllStr = "[%s]" % operandListAllStr
return operandListAllStr
def isReg(self):
return self.type == Operand.o_reg
def isImm(self):
return self.type == Operand.o_imm
def isDispl(self):
return self.type == Operand.o_displ
def isPhrase(self):
return self.type == Operand.o_phrase
def isNear(self):
return self.type == Operand.o_near
def isIdpspec0(self):
return self.type == Operand.o_idpspec0
def isValid(self):
isDebug = False
isValidOperand = False
if isDebug:
print("self.operand=%s" % self.operand)
if self.operand:
if self.isImm():
isMatchImm = re.match("^#[\w\-\.]+$", self.operand)
if isDebug:
print("isMatchImm=%s" % isMatchImm)
isValidOperand = bool(isMatchImm)
if isDebug:
print("isValidOperand=%s" % isValidOperand)
elif self.isReg():
regNameUpper = self.operand.upper()
isMatchReg = re.match("^([XDW]\d+)|(XZR)|(WZR)$", regNameUpper)
if isDebug:
print("isMatchReg=%s" % isMatchReg)
isValidOperand = bool(isMatchReg)
if isDebug:
print("isValidOperand=%s" % isValidOperand)
if not isValidOperand:
isValidOperand = regNameUpper in ArmSpecialRegNameList
elif self.isDispl():
if isDebug:
print("self.baseReg=%s, self.indexReg=%s, self.displacement=%s" % (self.baseReg, self.indexReg, self.displacement))
if self.baseReg and (not self.indexReg):
isValidOperand = True
elif self.isPhrase():
if isDebug:
print("self.baseReg=%s, self.indexReg=%s" % (self.baseReg, self.indexReg))
if self.baseReg and self.indexReg:
isValidOperand = True
elif self.isNear():
if isDebug:
print("self.value=%s" % self.value)
if self.value:
isValidOperand = True
elif self.isIdpspec0():
isValidOperand = True
if self.isIdpspec0():
isValidTypeValue = self.value == -1
else:
isValidType = self.type != Operand.o_void
isValidValue = self.value >= 0
isValidTypeValue = isValidType and isValidValue
isValidAll = isValidOperand and isValidTypeValue
if isDebug:
print("Operand isValidAll=%s" % isValidAll)
return isValidAll
def isInvalid(self):
return not self.isValid()
@property
def immVal(self):
curImmVal = None
if self.isImm():
curImmVal = self.value
return curImmVal
@property
def immValHex(self):
curImmValHex = ""
if self.immVal != None:
curImmValHex = "0x%X" % self.immVal
return curImmValHex
@property
def regName(self):
curRegName = None
if self.isReg():
curRegName = self.operand
return curRegName
@property
def contentStr(self):
contentStr = ""
if self.isReg():
contentStr = self.regName
elif self.isImm():
if (self.immVal >= 0) and (self.immVal < 8):
contentStr = "%X" % self.immVal
else:
contentStr = self.immValHex
elif self.isIdpspec0():
contentStr = self.operand
elif self.isDispl():
if self.displacement:
displacementStr = ""
if self.value != None:
if (self.value >= 0) and (self.value < 8):
displacementStr = "%X" % self.value
else:
displacementStr = "0x%X" % self.value
contentStr = "%s%s%s%s" % (self.baseReg, Operand.offStr, displacementStr, Operand.valStr)
else:
contentStr = "%s%s" % (self.baseReg, Operand.valStr)
elif self.isPhrase():
contentStr = "%s%s%s%s" % (self.baseReg, Operand.offStr, self.indexReg, Operand.valStr)
contentStr = contentStr.replace(",", "")
contentStr = contentStr.replace("#", "")
return contentStr
@property
def regIdx(self):
curRegIdx = None
if self.isReg():
curRegIdx = 0
return curRegIdx
Instruction=指令
class Instruction:
toStr = "To"
addStr = "Add"
def __init__(self, addr, name, operands):
self.addr = addr
self.disAsmStr = ida_getDisasmStr(addr)
self.name = name
self.operands = operands
def __str__(self):
curInstStr = "<Instruction: 0x%X: %s>" % (self.addr, self.disAsmStr)
return curInstStr
@staticmethod
def listToStr(instList):
instContentStrList = [str(eachInst) for eachInst in instList]
instListAllStr = ", ".join(instContentStrList)
instListAllStr = "[%s]" % instListAllStr
return instListAllStr
@staticmethod
def parse(addr):
isDebug = False
if isDebug:
print("Instruction: parsing 0x%X" % addr)
parsedInst = None
instName = idc.print_insn_mnem(addr)
if isDebug:
print("instName=%s" % instName)
curOperandIdx = 0
curOperandVaild = True
operandList = []
while curOperandVaild:
if isDebug:
logSubSub("[%d]" % curOperandIdx)
curOperand = idc.print_operand(addr, curOperandIdx)
if isDebug:
print("curOperand=%s" % curOperand)
curOperandType = idc.get_operand_type(addr, curOperandIdx)
if isDebug:
print("curOperandType=%d" % curOperandType)
curOperandValue = idc.get_operand_value(addr, curOperandIdx)
if isDebug:
print("curOperandValue=%s=0x%X" % (curOperandValue, curOperandValue))
curOperand = Operand(curOperand, curOperandType, curOperandValue)
if isDebug:
print("curOperand=%s" % curOperand)
if curOperand.isValid():
operandList.append(curOperand)
else:
if isDebug:
print("End of operand for invalid %s" % curOperand)
curOperandVaild = False
if isDebug:
print("curOperandVaild=%s" % curOperandVaild)
curOperandIdx += 1
if operandList:
parsedInst = Instruction(addr=addr, name=instName, operands=operandList)
if isDebug:
print("parsedInst=%s" % parsedInst)
print("operandList=%s" % Operand.listToStr(operandList))
return parsedInst
def isInst(self, instName):
isMatchInst = False
if self.name:
if (instName.lower() == self.name.lower()):
isMatchInst = True
return isMatchInst
@property
def contentStr(self):
"""
convert to meaningful string of Instruction real action / content
"""
contentStr = ""
isDebug = False
if isDebug:
print("self=%s" % self)
operandNum = len(self.operands)
if isDebug:
print("operandNum=%s" % operandNum)
isPairInst = self.isStp() or self.isLdp()
if isDebug:
print("isPairInst=%s" % isPairInst)
if not isPairInst:
if operandNum >= 2:
srcOperand = self.operands[1]
if isDebug:
print("srcOperand=%s" % srcOperand)
srcOperandStr = srcOperand.contentStr
if isDebug:
print("srcOperandStr=%s" % srcOperandStr)
dstOperand = self.operands[0]
if isDebug:
print("dstOperand=%s" % dstOperand)
dstOperandStr = dstOperand.contentStr
if isDebug:
print("dstOperandStr=%s" % dstOperandStr)
if self.isMov() or self.isFmov():
if operandNum == 2:
contentStr = "%s%s%s" % (srcOperandStr, Instruction.toStr, dstOperandStr)
elif operandNum > 2:
print("TODO: add support operand > 2 of MOV/FMOV")
elif self.isAdd() or self.isFadd():
if operandNum == 3:
extracOperand = self.operands[2]
extraOperandStr = extracOperand.contentStr
contentStr = "%s%s%s%s%s" % (srcOperandStr, Instruction.addStr, extraOperandStr, Instruction.toStr, dstOperandStr)
elif self.isLdr():
if operandNum == 2:
contentStr = "%s%s%s" % (srcOperandStr, Instruction.toStr, dstOperandStr)
elif operandNum > 2:
print("TODO: add support operand > 2 of LDR")
elif self.isStr():
if operandNum == 2:
contentStr = "%s%s%s" % (dstOperandStr, Instruction.toStr, srcOperandStr)
elif operandNum > 2:
print("TODO: add support operand > 2 of STR")
elif self.isStp():
if operandNum == 3:
srcOperand1 = self.operands[0]
if isDebug:
print("srcOperand1=%s" % srcOperand1)
srcOperand1Str = srcOperand1.contentStr
if isDebug:
print("srcOperand1Str=%s" % srcOperand1Str)
srcOperand2 = self.operands[1]
if isDebug:
print("srcOperand2=%s" % srcOperand2)
srcOperand2Str = srcOperand2.contentStr
if isDebug:
print("srcOperand2Str=%s" % srcOperand2Str)
dstOperand = self.operands[2]
if isDebug:
print("dstOperand=%s" % dstOperand)
dstOperandStr = dstOperand.contentStr
if isDebug:
print("dstOperandStr=%s" % dstOperandStr)
contentStr = "%s%s%s%s" % (srcOperand1Str, srcOperand2Str, Instruction.toStr, dstOperandStr)
elif self.isLdp():
if operandNum == 3:
dstOperand1 = self.operands[0]
if isDebug:
print("dstOperand1=%s" % dstOperand1)
dstOperand1Str = dstOperand1.contentStr
if isDebug:
print("dstOperand1Str=%s" % dstOperand1Str)
dstOperand2 = self.operands[1]
if isDebug:
print("dstOperand2=%s" % dstOperand2)
dstOperand2Str = dstOperand2.contentStr
if isDebug:
print("dstOperand2Str=%s" % dstOperand2Str)
srcOperand = self.operands[2]
if isDebug:
print("srcOperand=%s" % srcOperand)
srcOperandStr = srcOperand.contentStr
if isDebug:
print("srcOperandStr=%s" % srcOperandStr)
contentStr = "%s%s%s%s" % (srcOperandStr, Instruction.toStr, dstOperand1Str, dstOperand2Str)
if isDebug:
print("contentStr=%s" % contentStr)
return contentStr
def isMov(self):
return self.isInst("MOV")
def isFmov(self):
return self.isInst("FMOV")
def isRet(self):
return self.isInst("RET")
def isB(self):
return self.isInst("B")
def isBr(self):
return self.isInst("BR")
def isBranch(self):
return self.isB() or self.isBr()
def isAdd(self):
return self.isInst("ADD")
def isFadd(self):
return self.isInst("FADD")
def isSub(self):
return self.isInst("SUB")
def isStr(self):
return self.isInst("STR")
def isStp(self):
return self.isInst("STP")
def isLdp(self):
return self.isInst("LDP")
def isLdr(self):
return self.isInst("LDR")