首页 > 其他分享 >【总结】对大量函数进行trace调用流程+国际AIS3题

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

时间:2024-02-28 16:11:47浏览次数:33  
标签:a1 调用 15 trace 16 AIS3 bpt 25

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

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

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

题目附件如下:

[stateful]

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

分析

打开题目,进入main函数

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

好家伙,一大坨

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

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

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

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

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

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

Trace

方法一:手动trace

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

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

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

 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];

其实手都快残了

【----帮助网安学习,以下所有学习资料免费领!加vx:dctintin,备注 “博客园” 获取!】

 ① 网安学习成长路径思维导图
 ② 60+网安经典常用工具包
 ③ 100+SRC漏洞分析报告
 ④ 150+网安攻防实战技术电子书
 ⑤ 最权威CISSP 认证考试指南+题库
 ⑥ 超1800页CTF实战技巧手册
 ⑦ 最新网安大厂面试题合集(含答案)
 ⑧ APP客户端安全检测指南(安卓+IOS)

方法二:IDA-trace

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

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

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

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

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

然后进一步提取和分析

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

  Go
  import idc
  
  bpt_addr = 0x5599F331ADA7
  bpt_size=1
  idaapi.add_bpt(bpt_addr,bpt_size)
  print("Final")

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

  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

https://github.com/Pr0214/trace_natives

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

解密

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

 #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}

更多网安技能的在线实操练习,请点击这里>>

  

标签:a1,调用,15,trace,16,AIS3,bpt,25
From: https://www.cnblogs.com/hetianlab/p/18040732

相关文章

  • Delphi调用BPL并显示窗体
    bplunitUnit2;interfaceusesWinapi.Windows,Winapi.Messages,System.SysUtils,System.Variants,System.Classes,Vcl.Graphics,Vcl.Controls,Vcl.Forms,Vcl.Dialogs,Vcl.StdCtrls;typeTForm2=class(TForm)Label1:TLabel;Button1:TBu......
  • 解决HttpServletRequest调用getInputStream()方法读取参数只能获取一次问题
    1、问题描述由于后端接口获取前端传过的参数是通过HttpServletRequest接收获取的。现有一需求需要在接口调用之前拦截接口进行业务处理。在拦截类中调用getInputStream()获取参数之后,在接口方法里获取参数为空。2、解决方法自定义一个过滤器过滤所有请求,使用HttpServletRequest......
  • js调用斑马打印机打印二维码
    斑马打印机打印二维码项目(Web项目)功能中存在生成并打印二维码的功能,需要借助打印机打印出二维码。由于业务需求二维码需要打印在不干胶的材料上并可以进行粘贴,所以借助斑马打印机通过热敏不干胶纸进行打印。需要结合所使用的的斑马打印机的型号,去官网下载相关的浏览器打印插件。(......
  • 如何在SpringBoot中优雅地重试调用第三方API?
    1引言在实际的应用中,我们经常需要调用第三方API来获取数据或执行某些操作。然而,由于网络不稳定、第三方服务异常等原因,API调用可能会失败。为了提高系统的稳定性和可靠性,我们通常会考虑实现重试机制。本文将深入探讨如何在SpringBoot项目中优雅地重试调用第三方API,并结合代码......
  • rn 调用webview组件调用h5传参
    webview组件调用html页面并实现互相传值的功能1.rn页面 html——> rnhtml页面传参 if(window.ReactNativeWebView){  window.ReactNativeWebView.postMessage('值');}接收html的数据使用接收onMessage={(event)=>this.onMessage(event)} 2.html页面......
  • SpringCloud系列之(六)服务调用
    服务调用完成微服务之间的分布式调用一、Ribbon1.概述1.1是什么​ SpringCloudRibbon是基于NetflixRibbon实现的一套客户端负载均衡【消费者侧80】的工具。​ 简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法和服务调用。Ribbon客户端组......
  • unigui 调用百度地图
    百度源代码如下:<styletype="text/css"> body,html,#allmap{width:100%;height:100%;overflow:hidden;margin:0;font-family:"微软雅黑";} #l-map{height:100%;width:78%;float:left;border-right:2pxsolid#bcbcbc;} #r-result{height:100%;width:......
  • 调用百度翻译api
    importrandomimporthashlibimporturllibimportrequestsimportjson#安装相应的库deftrans(word):src='en'#翻译的源语言obj='zh'......
  • java 通过 microsoft graph 调用outlook
    废话不多说一官方文档先看一下官方文档,https://learn.microsoft.com/zh-cn/graph/tutorials/java?context=outlook%2Fcontext&tabs=aad&tutorial-step=1其中的代码,可以通过地址下载:https://developer.microsoft.com/en-us/graph/quick-start 二授权方式microsoft登录授权......
  • Python 中动态调用函数或类的方法
    使用importlib#module.pyclassA:deffoo(self):print('thisisfoo.')@staticmethoddefstatic_method():print('thisisstatic.')defbar():print('bar……')defbaz():print('==......