Created
March 30, 2017 06:27
-
-
Save sdasgup3/d79874b749e04f355a231cb4f162c404 to your computer and use it in GitHub Desktop.
recover stack resident "scalar variables" and "structures"
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import idaapi | |
import idc | |
import idautils | |
def _get_flags_from_bits(flag): | |
if -1 == flag: | |
return "" | |
cls = { | |
'MASK':1536, | |
1536:'FF_CODE', | |
1024:'FF_DATA', | |
512:'FF_TAIL', | |
0:'FF_UNK', | |
} | |
comm = { | |
'MASK':1046528, | |
2048:'FF_COMM', | |
4096:'FF_REF', | |
8192:'FF_LINE', | |
16384:'FF_NAME', | |
32768:'FF_LABL', | |
65536:'FF_FLOW', | |
524288:'FF_VAR', | |
49152:'FF_ANYNAME', | |
} | |
_0type = { | |
'MASK':15728640, | |
1048576:'FF_0NUMH', | |
2097152:'FF_0NUMD', | |
3145728:'FF_0CHAR', | |
4194304:'FF_0SEG', | |
5242880:'FF_0OFF', | |
6291456:'FF_0NUMB', | |
7340032:'FF_0NUMO', | |
8388608:'FF_0ENUM', | |
9437184:'FF_0FOP', | |
10485760:'FF_0STRO', | |
11534336:'FF_0STK', | |
} | |
_1type = { | |
'MASK':251658240, | |
16777216:'FF_1NUMH', | |
33554432:'FF_1NUMD', | |
50331648:'FF_1CHAR', | |
67108864:'FF_1SEG', | |
83886080:'FF_1OFF', | |
100663296:'FF_1NUMB', | |
117440512:'FF_1NUMO', | |
134217728:'FF_1ENUM', | |
150994944:'FF_1FOP', | |
167772160:'FF_1STRO', | |
184549376:'FF_1STK', | |
} | |
datatype = { | |
'MASK':4026531840, | |
0:'FF_BYTE', | |
268435456:'FF_WORD', | |
536870912:'FF_DWRD', | |
805306368:'FF_QWRD', | |
1073741824:'FF_TBYT', | |
1342177280:'FF_ASCI', | |
1610612736:'FF_STRU', | |
1879048192:'FF_OWRD', | |
2147483648:'FF_FLOAT', | |
2415919104:'FF_DOUBLE', | |
2684354560:'FF_PACKREAL', | |
2952790016:'FF_ALIGN', | |
} | |
flags = set() | |
flags.add(cls[cls['MASK']&flag]) | |
for category in [comm, _0type, _1type, datatype]: | |
val = category.get(category['MASK']&flag, None) | |
if val: | |
flags.add(val) | |
return flags | |
def _signed_from_unsigned64(val): | |
if val & 0x8000000000000000: | |
return -0x10000000000000000 + val | |
return val | |
def _explore_struct(idx): | |
if ( idx == -1 ): | |
print("Internal IDA error, GetStrucId returned -1!") | |
name = GetStrucName(idx) | |
size = GetStrucSize(idx) | |
members = GetMemberQty(idx) | |
print "\tName {0} Size {1} Qnty {2}\n".format(name, size, members) | |
member_off = 0 | |
while member_off != size : | |
mname = GetMemberName(idx,member_off); | |
if mname == "": | |
print " Hole ( {0} bytes)\n".format(GetStrucNextOff(idx,member_off)-member_off) | |
else : | |
msize = GetMemberSize(idx,member_off); | |
mtype = GetMemberFlag(idx,member_off) & DT_TYPE; | |
if mtype == FF_BYTE : mtype = "Byte" | |
elif mtype == FF_WORD : mtype = "Word" | |
elif mtype == FF_DWRD : mtype = "Double word" | |
elif mtype == FF_QWRD : mtype = "Quadro word" | |
elif mtype == FF_TBYT : mtype = "Ten bytes" | |
elif mtype == FF_ASCI : mtype = "ASCII string" | |
elif mtype == FF_STRU : mtype = "Structure {0}".format(GetStrucName(GetMemberStrId(idx,member_off))) | |
#elif mtype == FF_XTRN : mtype = "Unknown external?!" | |
elif mtype == FF_FLOAT : mtype = "Float" | |
elif mtype == FF_DOUBLE : mtype = "Double" | |
elif mtype == FF_PACKREAL : mtype = "Packed Real" | |
else : mtype = "Unknown Type {0:x}".format(mtype) | |
print "MName {0} Size {1} Type {2}".format(mname, msize, mtype) | |
mtype = GetMemberFlag(idx,member_off); | |
if isOff0(mtype): print(" Offset") | |
elif isChar0(mtype) :print(" Character") | |
elif isSeg0(mtype) : print(" Segment") | |
elif isDec0(mtype) : print(" Decimal") | |
elif isHex0(mtype) : print(" Hex") | |
elif isOct0(mtype) : print(" Octal") | |
elif isBin0(mtype) : print(" Binary") | |
member_off = GetStrucNextOff(idx,member_off) | |
def recover_stack_arg(base='ebp'): | |
funcs = idautils.Functions() | |
for f in funcs: | |
print "\nRecover stack args of {0}".format(idc.Name(f)); | |
# find the stack frame | |
frame = idc.GetFrame(f) | |
if frame is None: | |
print "None." | |
return | |
_uses_bp = 0 != (idc.GetFunctionFlags(f) & idc.FUNC_FRAME) | |
size = idc.GetStrucSize(frame) | |
delta = idc.GetMemberOffset(frame, " s") | |
if -1 == delta: | |
return "base pointer cannot be located." | |
else: | |
print "base pointer offset {0:x}".format(delta) | |
# figure out all of the variable names | |
offset = idc.GetFirstMember(frame) | |
while -1 != _signed_from_unsigned64(offset): | |
memberName = idc.GetMemberName(frame, offset) | |
if memberName is None: | |
memberName = "gap" | |
offset = idc.GetStrucNextOff(frame, offset) | |
continue | |
memberSize = idc.GetMemberSize(frame, offset) | |
memberFlag = idc.GetMemberFlag(frame, offset) | |
flag_str = _get_flags_from_bits(memberFlag) | |
print "Offset {0:x} Name {1} Size {2} Flags {3}".format(offset - delta, memberName, memberSize, flag_str) | |
if 'FF_STRU' in flag_str: | |
idx = GetStrucIdByName('biff') | |
_explore_struct(idx) | |
offset = idc.GetStrucNextOff(frame, offset) | |
if __name__ == "__main__": | |
#idaapi.autoWait() | |
recover_stack_arg() | |
#idc.Exit(0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment