IDApython学习笔记(一)

IDApython 简介

安装

需提前安装python2.7

ida pro7.0 百度网盘链接

链接:https://pan.baidu.com/s/1XQX1w8QgFGQMef6jSaCnBQ
提取码:xe1t

可直接下载使用,无需配置

测试

  1. 使用IDA打开任意二进制文件
  2. 在输出窗口,选择python,并打印任意字符

  1. 观察是否能正常运行

背景

IDApython创建于04年,是将IDA中的接口提供给python,用于完成一些自动化的任务。

IDApython由三个独立模块组成,第一个是idc,它是封装IDA的IDA函数的兼容性模块,现在已经很少使用。第二个模块是idautils,这是IDA里的一个高级实用函数。第三个模块是idaapi,它允许访问更多低级的数据,这些数据能够被类使用通过IDA。

基础

获取当前地址:

ea = here()
print "0x" + hex(ea)

获取该程序中的最小地址:

Python>hex(MinEA())
0x401000L
#结尾的L是指这是一个long类型

获取改程序中的最大地址:

Python>hex(MaxEA())
0x409000L

访问某个元素的一些属性:

ea = here()
#获取一个地址,以此为索引
print idc.SegName(ea)
#获取该地址所在段名称
print idc.GetDisasm(ea)
#获取该地址的反汇编字符串
print idc.GetMnem(ea)
#获取助记符
print idc.GetOpnd(ea, 0)
#获取操作数,其中0为操作数索引

输出结果:

扫描二维码关注公众号,回复: 10625682 查看本文章
.text
push    ebp
push
ebp

验证地址是否为有效地址:

Python>BADADDR
4294967295
Python>hex(BADADDR)
0xffffffffL
Python>idaapi.BADADDR
4294967295
ea = here()

if BADADDR != ea:
    print "valid address"

输出:

valid address

遍历所有段,输出段名称,段开始和结束的地址

import idautils

for seg in idautils.Segments():
    print idc.SegName(seg), hex(idc.SegStart(seg)), hex(idc.SegEnd(seg))

输出结果:

.text 0x401000L 0x402000L
.data 0x402000L 0x403000L
.rdata 0x403000L 0x404000L
.eh_frame 0x404000L 0x405000L
.bss 0x405000L 0x406000L
.idata 0x4060d0L 0x406164L
.CRT 0x407000L 0x408000L
.tls 0x408000L 0x409000L

获取下一节的起始地址:

ea = here()

print idc.SegName(ea)

eb = idc.NextSeg(ea)

输出结果:

.text
0x402000L

遍历所有已知函数:

import idautils

for func in idautils.Functions():
    print hex(func), idc.GetFunctionName(func)

获取当前地址所在函数:

Python>ea = here()
Python>hex(ea)
0x4013f9L
Python>func = idaapi.get_func(ea)
Python>dir(func)
['__class__', '__del__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__getattribute__', '__gt__', '__hash__', '__init__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__swig_destroy__', '__weakref__', '_print', 'analyzed_sp', 'argsize', 'clear', 'color', 'compare', 'contains', 'does_return', 'empty', 'endEA', 'end_ea', 'extend', 'flags', 'fpd', 'frame', 'frregs', 'frsize', 'intersect', 'is_far', 'llabelqty', 'llabels', 'overlaps', 'owner', 'pntqty', 'points', 'referers', 'refqty', 'regargqty', 'regargs', 'regvarqty', 'regvars', 'size', 'startEA', 'start_ea', 'tailqty', 'tails', 'this', 'thisown']
Python>hex(func.startEA)
0x4013c9L
Python>hex(func.endEA)
0x40145eL
  • dir(class)查询python中类的有效函数
  • 枚举函数的一个警告是,只有当IDA将代码块标识为函数时,他才起作用。
  • 在代码块被标记为一个函数之前,它将在函数枚举过程中跳过。
  • 未标记为函数的代码将在图例中标记为红色(顶部的颜色栏),可以通过手动方法进行固定。

输出一个函数的反汇编:

ea = here()

start = GetFunctionAttr(ea, FUNCATTR_START)

end = GetFunctionAttr(ea, FUNCATTR_END)

cur_addr = start

while cur_addr <= end:
    print hex(cur_addr),idc.GetDisasm(cur_addr)
    cur_addr = idc.NextHead(cur_addr, end)

输出:

0x4013c9L push    ebp
0x4013caL mov     ebp, esp
0x4013ccL sub     esp, 48h
0x4013cfL mov     dword ptr [ebp+flag], 'l`!H'
0x4013d6L mov     dword ptr [ebp+flag+4], 'i!`!'
0x4013ddL mov     dword ptr [ebp+flag+8], 'djb`'
0x4013e4L mov     dword ptr [ebp+flag+0Ch], 'e!-s'
0x4013ebL mov     dword ptr [ebp+flag+10h], 'u&on'
0x4013f2L mov     dword ptr [ebp+flag+14h], 'tnx!'
0x4013f9L mov     dword ptr [ebp+flag+18h], '`br!'
0x401400L mov     dword ptr [ebp+flag+1Ch], '>eds'
0x401407L mov     [ebp+flag+20h], 0
0x40140bL mov     [ebp+i], 0
0x401412L lea     eax, [ebp+flag]
0x401415L mov     [esp], eax; char *
0x401418L call    _strlen
0x40141dL cmp     eax, [ebp+i]
0x401420L jle     short loc_401442
0x401422L lea     edx, [ebp+flag]
0x401425L mov     eax, [ebp+i]
0x401428L add     eax, edx
0x40142aL movzx   eax, byte ptr [eax]
0x40142dL xor     eax, 1
0x401430L mov     ecx, eax
0x401432L lea     edx, [ebp+flag]
0x401435L mov     eax, [ebp+i]
0x401438L add     eax, edx
0x40143aL mov     [eax], cl
0x40143cL add     [ebp+i], 1
0x401440L jmp     short loc_401412
0x401442L lea     eax, [ebp+flag]
0x401445L mov     [esp+4], eax; buf
0x401449L mov     dword ptr [esp], offset filename; "hack"
0x401450L call    __Z10Write_FilePKcS0_; Write_File(char const*,char const*)
0x401455L mov     eax, 0
0x40145aL leave
0x40145bL retn    10h
  • 缺点:包含在开始和结束的功能边界。如果有一个跳转地址高于函数的末尾循环也将过早的退出

根据标志位检索函数信息

  • FUNC_NORET:用来标识一个函数没有执行返回指令,内部表示等于1
  • FUNC_FAR:很少出现,除非逆向软件使用分段内存,内部表示2
  • FUNC_LIB:用于查找库代码。标识库代码非常有用,因为是在执行分析时通常可忽略
  • FUNC_STATIC:用于标示作为静态函数编译的函数,如果作者定义了一个函数为静态只能访问内部文件等功能,在有限方式下,这可以用来帮助理解源代码是如何构造的
  • FUNC_FRAME:表明该函数使用栈指针ebp,使用栈指针的函数通常以设置堆栈框架的标准函数序言开始。
  • FUNC_USERFAR:罕见,非常小的文件,用户已指定远性功能,内部表示32
  • FUNC_HIDDEN:意味是隐藏的,需要扩展到视图
  • FUNC_THUNK:thunk函数,跳转到另一个函数
  • FUNC_BOTTOMBP:此标记用于跟踪栈指针

一个函数可以有多个标志;

import idautils



for func in idautils.Functions():
    flags = idc.GetFunctionFlags(func)
    if flags & FUNC_LIB:
        print hex(func), "FUNC_LIB", GetFunctionName(func)
    if flags & FUNC_FRAME:
        print hex(func), "FUNC_FRAME", GetFunctionName(func)
    if flags & FUNC_STATIC:
        print hex(func), "FUNC_STATIC", GetFunctionName(func)
    if flags & FUNC_HIDDEN:
        print hex(func), "FUNC_HIDDEN", GetFunctionName(func)
    if flags & FUNC_THUNK:
        print hex(func), "FUNC_THUNK", GetFunctionName(func)
    if flags & FUNC_BOTTOMBP:
        print hex(func), "FUNC_BOTTOMBP", GetFunctionName(func)
    if flags & FUNC_FAR:
        print hex(func), "FUNC_FAR", GetFunctionName(func)
    if flags & FUNC_USERFAR:
        print hex(func), "FUNC_USERFAR", GetFunctionName(func)
        

获取函数中的所有地址

import idautils

addr = 0x00401350

dism_addr = list(idautils.FuncItems(addr))
print dism_addr

for line in dism_addr:
    print hex(line), idc.GetDisasm(line)
发布了297 篇原创文章 · 获赞 124 · 访问量 30万+

猜你喜欢

转载自blog.csdn.net/AcSuccess/article/details/105174680
今日推荐