【总结】对大量函数进行trace调用流程+国际AIS3题

现在混淆的主要目的之一就有让逆向分析人员不清楚函数的调用流程,给你一堆函数,加了高强度的OLLVM,更不能看了。那么Trace跟踪技术就显得很重要的,如果清楚了函数调用流程,那么逐个分析,距离成功不就很快了。

万事开头难,逆向程序难在不知道从哪开始。

前几天做了一道AIS3的题目,内含50个加密函数,加密的流程很简单,关键是对这50个加密函数进行了ollvm控制流平坦化魔改(去除也很简单),主要是想抛砖引玉,锻炼和练习trace的技术。这样在以后遇到高强度的混淆干扰也能有一战的能力。

题目附件如下:

[stateful]

本文的重点在于总结trace技巧,题目本身不算很难。

分析

打开题目,进入main函数

发现逻辑不是很难,进入state_machine函数

好家伙,一大坨

尝试使用OBPO插件去除,发现直接卡死。使用D810也是卡死。

更高级的玩法使用Unicorn进行去除,类似deflat

本文的重点是在不去除平坦化的前提下去trace函数调用流程

发现有50多个state函数,并且每个函数的功能很简单,我们的目的是:

trace每一个函数,并在梳理调用流程的过程中,输出关键的加密流程,从而写出解密流程

注意调试的时候,记得传入参数

Trace

方法一:手动trace

最简单粗暴的方法,对每一个state函数下断点,然后运行程序,逐一拿到调用流程。

如果函数过多,这种方法就不太行了

最终笔者运行拿到了调用的流程

css 复制代码
 a1[14] += a1[35] + a1[8];  a1[9] -= a1[2] + a1[22];  *a1 -= a1[18] + a1[31];  a1[2] += a1[11] + a1[8];  a1[6] += a1[10] + a1[41];  a1[14] -= a1[32] + a1[6];  a1[16] += a1[25] + a1[11];  a1[31] += a1[34] + a1[16];  a1[9] += a1[11] + a1[3];  a1[17] += *a1 + a1[7];  a1[5] += a1[40] + a1[4];  a1[37] -= a1[29] + a1[3];  a1[23] += a1[7] + a1[34];  a1[39] -= a1[25] + a1[38];  a1[27] += a1[18] + a1[20];  a1[20] += a1[19] + a1[24];  a1[15] += a1[22] + a1[10];  a1[30] -= a1[33] + a1[8];  a1[1] -= a1[29] + a1[13];  a1[19] += a1[10] + a1[16];  *a1 += a1[33] + a1[16];  a1[36] += a1[11] + a1[15];  a1[24] += a1[20] + a1[5];  a1[7] += a1[21] + *a1;  a1[1] += a1[15] + a1[6];  a1[30] -= a1[13] + a1[2];  a1[1] += a1[16] + a1[40];  a1[31] += a1[1] + a1[16];  a1[32] += a1[5] + a1[25];  a1[13] += a1[25] + a1[28];  a1[7] += a1[10] + *a1;  a1[21] += a1[34] + a1[15];  a1[21] -= a1[13] + a1[42];  a1[18] += a1[29] + a1[15];  a1[4] += a1[7] + a1[25];  *a1 += a1[28] + a1[31];  a1[2] += a1[34] + a1[25];  a1[13] += a1[26] + a1[8];  a1[41] -= a1[3] + a1[34];  a1[37] += a1[27] + a1[18];  a1[4] += a1[27] + a1[25];  a1[23] += a1[30] + a1[39];  a1[18] += a1[26] + a1[31];  a1[10] -= a1[12] + a1[22];  a1[4] += a1[6] + a1[22];  a1[37] += a1[12] + a1[16];  a1[15] += a1[40] + a1[8];  a1[17] += a1[38] + a1[24];  a1[8] += a1[14] + a1[16];  a1[5] += a1[37] + a1[20];

其实手都快残了

帮助网安学习,全套资料S信领取:

① 网安学习成长路径思维导图

② 60+网安经典常用工具包

③ 100+SRC漏洞分析报告

④ 150+网安攻防实战技术电子书

⑤ 最权威CISSP 认证考试指南+题库

⑥ 超1800页CTF实战技巧手册

⑦ 最新网安大厂面试题合集(含答案)

⑧ APP客户端安全检测指南(安卓+IOS)

方法二:IDA-trace

程序动态调试的时候才可以使用trace功能

IDA自动进行trace跟踪,然后稍等片刻

可以发现成功的trace了调用了流程

但是有一点不方便的是,有了调用流程,但是我们还要进入每一个函数,提取加密的流程才行。

IDA快捷键Ctrl+F5可以导出整个程序的伪代码

然后进一步提取和分析

这里可以使用IDA-python自动下断点

go 复制代码
  Go  import idc    bpt_addr = 0x5599F331ADA7  bpt_size=1  idaapi.add_bpt(bpt_addr,bpt_size)  print("Final")

当然还不够,我们要达到的效果是,触发断点然后输出相关加密信息到output函数窗口,就是有断点回调函数

scss 复制代码
  import idaapi    # 定义回调函数  def my_bpt_callback(bptno):  print("Breakpoint %d hit!" % bptno)    # 添加断点  bpt_addr = 0x5599F331ADA7  bpt_size=1  bpt = idaapi.add_bpt(bpt_addr,bpt_size)    # 设置断点回调  idaapi.add_bpt_chngev_cnd(bpt, idaapi.BPT_EXEC, my_bpt_callback)  #设置执行断点​-----------------------------------------------------------------------​idaapi.BPT_EXEC 表示执行事件

方法三:trace_natives

github.com/Pr0214/trac...

按照说明,进行输出,发现是这样的效果(IDA中,Edit-Plugins-traceNatives)

解密

有了调用流程,剩下的就很简单了

less 复制代码
 #define _CRT_SECURE_NO_WARNINGS  #include <stdio.h>  #include <iostream>    int main() {  unsigned char a1[] =  {  0x0F, 0x77, 0xEC, 0x33, 0x44, 0x16, 0x13, 0x59, 0x1D, 0x42,  0x84, 0x75, 0x5F, 0xE4, 0x83, 0xC0, 0x3B, 0xC1, 0x95, 0xCF,  0xDB, 0x33, 0x6C, 0xD2, 0xED, 0x72, 0x5F, 0x0D, 0x74, 0x41,  0x5B, 0x73, 0xA0, 0x33, 0x53, 0x24, 0x02, 0x59, 0x74, 0x60,  0x33, 0xCC, 0x7D  };      a1[5] -= a1[37] + a1[20];  a1[8] -= a1[14] + a1[16];  a1[17] -= a1[38] + a1[24];  a1[15] -= a1[40] + a1[8];  a1[37] -= a1[12] + a1[16];  a1[4] -= a1[6] + a1[22];  a1[10] += a1[12] + a1[22];  a1[18] -= a1[26] + a1[31];  a1[23] -= a1[30] + a1[39];  a1[4] -= a1[27] + a1[25];  a1[37] -= a1[27] + a1[18];  a1[41] += a1[3] + a1[34];  a1[13] -= a1[26] + a1[8];  a1[2] -= a1[34] + a1[25];  *a1 -= a1[28] + a1[31];  a1[4] -= a1[7] + a1[25];  a1[18] -= a1[29] + a1[15];  a1[21] += a1[13] + a1[42];  a1[21] -= a1[34] + a1[15];  a1[7] -= a1[10] + *a1;  a1[13] -= a1[25] + a1[28];  a1[32] -= a1[5] + a1[25];  a1[31] -= a1[1] + a1[16];  a1[1] -= a1[16] + a1[40];  a1[30] += a1[13] + a1[2];  a1[1] -= a1[15] + a1[6];  a1[7] -= a1[21] + *a1;  a1[24] -= a1[20] + a1[5];  a1[36] -= a1[11] + a1[15];  *a1 -= a1[33] + a1[16];  a1[19] -= a1[10] + a1[16];  a1[1] += a1[29] + a1[13];  a1[30] -= a1[33] + a1[8];  a1[15] -= a1[22] + a1[10];  a1[20] -= a1[19] + a1[24];  a1[27] -= a1[18] + a1[20];  a1[39] += a1[25] + a1[38];  a1[23] -= a1[7] + a1[34];  a1[37] += a1[29] + a1[3];  a1[5] -= a1[40] + a1[4];  a1[17] -= *a1 + a1[7];  a1[9] -= a1[11] + a1[3];  a1[31] -= a1[34] + a1[16];  a1[16] -= a1[25] + a1[11];  a1[14] += a1[32] + a1[6];  a1[6] -= a1[10] + a1[41];  a1[2] -= a1[11] + a1[8];  *a1 += a1[18] + a1[31];  a1[9] += a1[2] + a1[22];  a1[14] -= a1[35] + a1[8];    printf("%s", a1);  return 0;  }

得到flag

AIS3{4re_YOu@sTATEfUl_0r_StA03L3S$_ctF3R}

相关推荐
excel几秒前
WebGL 入门到进阶全解析:从 Canvas 上下文到 3D 绘制与 WebGL2 新特性
前端
掘金安东尼13 分钟前
用 WebGL + Solid.js 构建混合材质 Shader
前端·webgl
恋猫de小郭17 分钟前
Flutter 小技巧之有趣的 UI 骨架屏框架 skeletonizer
android·前端·flutter
江城开朗的豌豆17 分钟前
玩转React Hooks
前端·javascript·react.js
阿酷tony22 分钟前
教育场景下禁用html5播放器拖动进度条的例子
前端·html·html5·在线教育场景·禁止播放器拖动
前端小巷子43 分钟前
Vue3 响应式革命
前端·vue.js·面试
一狐九1 小时前
Flutter如何通过GlobalKey调用组件内的方法
前端·flutter
wyzqhhhh1 小时前
前端如何处理首屏优化问题
前端
杨荧1 小时前
基于Python的反诈知识科普平台 Python+Django+Vue.js
大数据·前端·vue.js·python·数据分析
22jimmy2 小时前
JavaWeb(二)CSS
java·开发语言·前端·css·入门·基础