【总结】对大量函数进行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}

相关推荐
石小石Orz3 分钟前
因为没有使用路由懒加载,产生了一个难以寻找的bug
前端
Mintopia3 分钟前
Three.js 力导向图:让数据跳起优雅的华尔兹
前端·javascript·three.js
墨渊君19 分钟前
React Native 跨平台组件库实践: GlueStack UI 上手指南
前端
晓得迷路了26 分钟前
栗子前端技术周刊第 84 期 - Vite v7.0 beta、Vitest 3.2、Astro 5.9...
前端·javascript·vite
独立开阀者_FwtCoder29 分钟前
最全301/302重定向指南:从SEO到实战,一篇就够了
前端·javascript·vue.js
Moment38 分钟前
给大家推荐一个超好用的 Marsview 低代码平台 🤩🤩🤩
前端·javascript·github
小满zs42 分钟前
Zustand 第三章(状态简化)
前端·react.js
普宁彭于晏44 分钟前
元素水平垂直居中的方法
前端·css·笔记·css3
恋猫de小郭1 小时前
为什么跨平台框架可以适配鸿蒙,它们的技术原理是什么?
android·前端·flutter
云浪1 小时前
元素变形记:CSS 缩放函数全指南
前端·css