前三部分已经验证了用IDAPython能够让工作变的更简单,这一部分让我们看看逆向工程师如何使用IDAPython的颜色和强大的脚本特性。

分析者经常需要面对越来越复杂的代码,而且有时候无法轻易看出动态执行的时候执行的代码。而通过IDAPython的强大功能,我们不但能静态的标识指令,并且能够统计出对应的指令被使用了多少次。

背景

在这一部分中,我用C语言写了一个简单的程序。下面的代码是为了这次的练习而编写和编译的:

#include "stdafx.h"
#include <stdlib.h>
#include <time.h> int _tmain(int argc, _TCHAR* argv[])
{
  char* start = "Running the program.";
  printf("[+] %s\n", start);
  char* loop_string = "Looping...";
 
  srand (time(NULL));
  int bool_value = rand() % 10 + 1;
  printf("[+] %d selected.\n", bool_value);
  if(bool_value > 5)
  {
    char* over_five = "Number over 5 selected. Looping 2 times.";
    printf("[+] %s\n", over_five);
    for(int x = 0; x < 2; x++)
      printf("[+] %s\n", loop_string);
  }
  else
  {
    char* under_five = "Number under 5 selected. Looping 5 times.";
    printf("[+] %s\n", under_five);
    for(int x = 0; x < 5; x++)
      printf("[+] %s\n", loop_string);
  }
  return 0;
}

当我们将这个二进制加载到IDA中时,我们可以看到预期的循环与代码重定向语句。如果我们在不知道源码的情况下来看这个例子,通过静态分析能够大概判断代码实现的功能。

然而,如果我们想知道运行的时候执行了哪个区块的代码呢?这个问题可以用IDAPython来解决哦!

编写IDAPYTHON脚本

我们第一个需要处理的难题是如何逐句遍历每一条指令,以下代码将可以帮助我们来解决:(调试信息会输出已经被执行的指令)

RunTo(BeginEA())
event = GetDebuggerEvent(WFNE_SUSP, -1) EnableTracing(TRACE_STEP, 1)
event = GetDebuggerEvent(WFNE_ANY|WFNE_CONT, -1) while True:
  event = GetDebuggerEvent(WFNE_ANY, -1)
  addr = GetEventEa()
  print "Debug: current address", hex(addr), "| debug event", hex(event)
  if event <= 1: break

在上面的代码中我们首先启动了调试器并且执行到函数的入口处,通过调用‘RunTo(BeginEA())’函数。接下来调用的GetDebuggerEvent()函数会等待直到断点到达。

接着我们调用EnableTracing()函数来打开IDA的跟踪功能,然后GetDebuggerEvent()函数调用会继续执行调试器,配置跟踪步骤。最后,我们会进入一个循环遍历每一个地址直到遇到结束条件。这个脚本在IDA中的输出如下所示:

下一个步骤是检索出执行的每一行并标识颜色。我们可以使用GetColor()和SetColor()函数来分别解决这两个问题。下面的代码会获取给定行数代码的当前颜色,并决定将代码设置成什么颜色,并进行设定。

在这个例子,我使用四种不同深浅的蓝色。深蓝色表示这一行被重复执行。(读者可以根据跟人喜好修改这部分代码)

def get_new_color(current_color):
  colors = [0xffe699, 0xffcc33, 0xe6ac00, 0xb38600]
  if current_color == 0xFFFFFF:
    return colors[0]
  if current_color in colors:
    pos = colors.index(current_color)
    if pos == len(colors)-1:
      return colors[pos]
    else:
      return colors[pos+1]
  return 0xFFFFFF
  
  
current_color = GetColor(addr, CIC_ITEM)
new_color = get_new_color(current_color)
SetColor(addr, CIC_ITEM, new_color)

运行上面的代码能够将无颜色的行数修改为高亮的蓝色。另外,如果同一行代码运行多次会变成深蓝色。

可以使用下面的代码来删除IDA文件中之前设置的所有颜色。将颜色设置成0XFFFFFF将会变成白色,或者高效的将之前设置的所有颜色删除。

heads = Heads(SegStart(ScreenEA()), SegEnd(ScreenEA()))
for i in heads:
  SetColor(i, CIC_ITEM, 0xFFFFFF)

将所有的代码合到一起,我们会得到如下结果:

heads = Heads(SegStart(ScreenEA()), SegEnd(ScreenEA()))
for i in heads:
  SetColor(i, CIC_ITEM, 0xFFFFFF)
  
def get_new_color(current_color):
  colors = [0xffe699, 0xffcc33, 0xe6ac00, 0xb38600]
  if current_color == 0xFFFFFF:
    return colors[0]
  if current_color in colors:
    pos = colors.index(current_color)
    if pos == len(colors)-1:
      return colors[pos]
    else:
      return colors[pos+1]
  return 0xFFFFFF
  
RunTo(BeginEA())
event = GetDebuggerEvent(WFNE_SUSP, -1) EnableTracing(TRACE_STEP, 1)
event = GetDebuggerEvent(WFNE_ANY|WFNE_CONT, -1)
while True:
  event = GetDebuggerEvent(WFNE_ANY, -1)
  addr = GetEventEa()
  current_color = GetColor(addr, CIC_ITEM)
  new_color = get_new_color(current_color)
  SetColor(addr, CIC_ITEM, new_color)
  if event <= 1: break

当我在程序用运行这段代码时,我们看到执行过的反汇编指令被高亮了。如下图所示,多次执行的指令被设置成了深蓝色,让我们能够更容易理解代码执行流程。

总结

这一部分演示的例子确实很简单,结合了IDA调试功能与颜色相关API的使用。这项技术能够让分析者在复杂应用代码分析中节省大量的时间。

*原文:Paloaltone,东二门陈冠希/编译,转载请注明来自FreeBuf黑客与极客(FreeBuf.COM)

IDApython教程(四)的更多相关文章

  1. CRL快速开发框架系列教程四(删除数据)

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  2. 手把手教从零开始在GitHub上使用Hexo搭建博客教程(四)-使用Travis自动部署Hexo(2)

    前言 前面一篇文章介绍了Travis自动部署Hexo的常规使用教程,也是个人比较推荐的方法. 前文最后也提到了在Windows系统中可能会有一些小问题,为了在Windows系统中也可以实现使用Trav ...

  3. C#微信公众号开发系列教程四(接收普通消息)

    微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南) C#微信公众号开发系列教程三(消息体签名及加解密) C ...

  4. 无废话ExtJs 入门教程四[表单:FormPanel]

    无废话ExtJs 入门教程四[表单:FormPanel] extjs技术交流,欢迎加群(201926085) 继上一节内容,我们在窗体里加了个表单.如下所示代码区的第28行位置,items:form. ...

  5. TFS(Team Foundation Server)敏捷使用教程(四):工作项跟踪(1)

    工作项跟踪(1) 可跟踪性是软件过程的重要能力,TFS主要是以工作项来实现过程的可跟踪性.曾有人问:"你们实际项目里的工作项是怎么样的?能不能让我们看看?"我也一直很好奇别的公司T ...

  6. Android Studio系列教程四--Gradle基础

    Android Studio系列教程四--Gradle基础 2014 年 12 月 18 日 DevTools 本文为个人原创,欢迎转载,但请务必在明显位置注明出处!http://stormzhang ...

  7. Laravel教程 四:数据库和Eloquent

    Laravel教程 四:数据库和Eloquent 此文章为原创文章,未经同意,禁止转载. Eloquent Database 上一篇写了一些Laravel Blade的基本用法和给视图传递变量的几种方 ...

  8. NGUI系列教程四(自定义Atlas,Font)

    今天我们来看一下怎么自定义NGUIAtlas,制作属于自己风格的UI.第一部分:自定义 Atlas1 . 首先我们要准备一些图标素材,也就是我们的UI素材,将其导入到unity工程中.2. 全选我们需 ...

  9. Qt零基础教程(四) QWidget详解篇

    在博客园里面转载我自己写的关于Qt的基础教程,没次写一篇我会在这里更新一下目录: Qt零基础教程(四) QWidget详解(1):创建一个窗口 Qt零基础教程(四) QWidget详解(2):QWid ...

  10. Qt零基础教程(四)QWidget详解(3):QWidget的几何结构

    Qt零基础教程(四)  QWidget详解(3):QWidget的几何结构 这篇文章里面分析了QWidget中常用的几种几何结构 下图是Qt提供的分析QWidget几何结构的一幅图,在帮助的 Wind ...

随机推荐

  1. python爬虫解析库学习

    一.xpath库使用: 1.基本规则: 2.将文件转为HTML对象: html = etree.parse('./test.html', etree.HTMLParser()) result = et ...

  2. redux源码解析-函数式编程

    提到redux,会想到函数式编程.什么是函数式编程?是一种很奇妙的函数式的编程方法.你会感觉函数式编程这么简单,但是用起来却很方便很神奇. 在<functional javascript> ...

  3. Building real-time dashboard applications with Apache Flink, Elasticsearch, and Kibana

    https://www.elastic.co/cn/blog/building-real-time-dashboard-applications-with-apache-flink-elasticse ...

  4. Spring 整合 Hibernate 时启用二级缓存实例详解

    写在前面: 1. 本例使用 Hibernate3 + Spring3: 2. 本例的查询使用了 HibernateTemplate: 1. 导入 ehcache-x.x.x.jar 包: 2. 在 a ...

  5. 百度地图API,展示地图和添加控件

    1.申请百度账号和AK 点我申请 2.准备页面 根据HTML标准,每一份HTML文档都应该声明正确的文档类型,我们建议您使用最新的符合HTML5规范的文档声明: <!DOCTYPE html&g ...

  6. MySQL排序函数field()详解

    在日常开发过程中,排序是经常用到的,有时候有这样的需求. 比如,需要在查询结果中根据某个字段的具体值来排序.如下面例子 上面是一张个人信息 表,假如我们想按照'seiki','iris','xut'来 ...

  7. jquery.form.js ajax提交上传文件

    项目中最近有用到表单提交,是带有图片上传的表单录入,需要ajax异步提交,网上找了好多例子都是只能提交上传字段一个信息的,这里整理一下.表单里有普通文本信息字段也有图片上传字段. 1.jsp代码--引 ...

  8. RAND_MAX

    RAND_MAX 指的是 C 语言标准库 <stdlib.h> 中定义的一个宏.经预编译阶段处理后, 它展开为一个整数类型的常量表达式.RAND_MAX 是 <stdlib.h> ...

  9. JS事件(五)内存与性能

    1.减少代码中事件处理程序的数量,是减少内存开销,提升网页速度的有效手段 事件委托: <ul id="ul"> <li id="goSomewhere& ...

  10. python之OpenCv(二)---保存图像

    1.使用opencv保存图像 cv2.imwrite(存储路径,图像变量[,存盘标识]) 存盘标识: cv2.CV_IMWRITE_JPEG_QUALITY  设置图片格式为.jpeg或者.jpg的图 ...