ida在调试android-arm app时不能解析调用栈,自己实现了一个简单的arm回溯栈 ida插件,会在实战中不断增强
#PUSH {LR}
#PUSH {R3,LR}
#PUSH {R4-R7,LR}
#PUSH {R0,R1,R4-R6,LR}
#STMFD SP!, {R3,LR}
#STMFD SP!, {R0-R7, LR}
#STMFD SP!, {R11,LR}
#
#SP=BEBBDBC0 BEBBDBD8 00000000
#R3=00000000
#LR=4003B0CD
#
#SP=BEBBDBB8 00000000 4003B0CD
# CallStack trace for arm x86
Rarr = ["R0","R1","R2","R3","R4","R5","R6","R7","R8","R9","R10","R11","R12"]
def __validate(addr):
instr = GetDisasm(addr -1)
if instr.find("BL") != -1:
return True
return False
def __getregnum(str):
pos1 = str.find("{")
pos2 = str.find("}")
num = 1
if pos1 != -1 and pos2 != -1:
str = str[pos1+1:pos2]
for i in str.split(','):
if i.find("LR") != -1:
num = num
elif i.find("-") != -1:
twoR = i.split("-")
first = 0
second = 0
for j in range(0, Rarr.__len__()):
index = Rarr.__len__() - j - 1
if twoR[0].find(Rarr[index]) != -1:
first = index
break
for j in range(0, Rarr.__len__()):
index = Rarr.__len__() - j - 1
if twoR[1].find(Rarr[index]) != -1:
second = index
break
num = num + second - first + 1
else:
num = num + 1
return num
else:
return 0
def __getsubnum(str):
pos1 = str.find("#")
if __name__ == "__main__":
curaddr = GetRegValue("PC")
cursp = GetRegValue("SP")
lastaddr = GetRegValue("LR") - 1
# print first layer call stack
print "%08x:%s"%(curaddr, GetFuncOffset(curaddr))
# validate and print second layer call stack
if -1 == GetFunctionAttr(lastaddr, FUNCATTR_START):
AnalyzeArea(addr - 0x1000, addr)
if __validate(lastaddr):
print "%08x:%s"%(lastaddr, GetFuncOffset(lastaddr))
else:
print "error"
# restore sp
funcstart = GetFunctionAttr(curaddr, FUNCATTR_START)
bingo = ""
offset = 0
if funcstart != -1:
for i in range(funcstart, curaddr):
instr = GetDisasm(i)
if instr.find("LR") != -1 and (instr.find("PUSH") != -1 or instr.find("STMFD") != -1):
offset = offset + __getregnum(instr) * 4
break
for i in range(funcstart, curaddr):
instr = GetDisasm(i)
if instr.find("SUB") != -1 and instr.find("SP") != -1:
offset = offset + __getsubnum(instr)
cursp = cursp + offset
for layer in range(0,9):
# get the function lastaddr belongs to
funcstart = GetFunctionAttr(lastaddr, FUNCATTR_START)
bingo = ""
offset = 0
if funcstart != -1:
for i in range(funcstart, lastaddr):
instr = GetDisasm(i)
if instr.find("LR") != -1 and (instr.find("PUSH") != -1 or instr.find("STMFD") != -1):
offset = offset + __getregnum(instr) * 4
break
for i in range(funcstart, lastaddr):
instr = GetDisasm(i)
if instr.find("SUB") != -1 and instr.find("SP") != -1:
offset = offset + __getsubnum(instr)
cursp = cursp + offset
lastLR = Dword(cursp - 4)
lastaddr = lastLR - 1
if __validate(lastaddr):
print "%08x:%s"%(lastaddr, GetFuncOffset(lastaddr))
else:
print "error"
#get the "sub sp" instruction
#1:PC GetFuncOffset(curaddr)
#2:LR GetFuncOffset(lastaddr)
#3: