BUUCTF-[RoarCTF2019]polyre
创始人
2024-05-31 15:53:54
0

题目下载:下载

这道题目是一个关于控制流平坦化和虚假流程。

首先了解一下控制流平坦化:利用符号执行去除控制流平坦化 - 博客 - 腾讯安全应急响应中心https://www.cnblogs.com/zhwer/p/14081454.htmlbuuctf RoarCTF2019 polyre writeup - 『脱壳破解区』 - 吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

1.1控制流平坦化:

控制流平坦化(control flow flattening)的基本思想主要是通过一个主分发器来控制程序基本块的执行流程,例如下图是正常的执行流程 

 经过控制流平坦化后的执行流程就如下图

这样可以模糊基本块之间的前后关系,增加程序分析的难度

OLLVM 的控制流平坦化是一种常见的代码混淆方式,其基本原理是添加分发器来控制流程的执行。针对这种混淆方式的还原也有了许多研究和工具, 

简单来说,OLLVM会添加一个用于控制跳转的状态变量和分发器:当一个真实块执行完成后,会把状态变量的值进行更新,回到分发器进行检查,再根据状态变量的值跳转到下一个真实块执行;

如果原本的执行流程中存在条件跳转,则会在各条件下对状态变量设置不同的值,再回到分发器进行检查和跳转。

 知道了控制流平坦化的一些相关概念,做可以做题了。

查壳,无壳 (有的版本的查壳工具可以查出LLVM这个关键信息)载入IDA,找到主函数,看一下流程图,体会一下什么是控制流平坦化再看一下代码

发现是一堆while嵌套,发现真的很乱,真的是让代码之间关系混乱,经过查阅资料知道可以用deflat.py除去控制流平坦化。

下载deflat,百度网盘 请输入提取码 提取码u2g0

下载完后注意:deflat.py文件中的sys.path.append()后的地址是你下载的am_graph.py的地址,注意修改。

然后进行去除控制流平坦化操作:

python3 deflat.py attachment 0x400620   #python版本+脚本名+文件名+起始地址(main())

(注意在angr环境下运行)

如图

等待几分钟后就会出现下图

然后载入出现的attachment_recovered文件,看一下主函数流程图

 明显流程清晰很多,看一下主函数,发现有一堆while,do...while循环。并且变量在.bss区。

.bss区:存放未初始化的全局变量或者静态变量。值为0

所以可以进而判断这些循环只执行一次甚至不执行,所以可以把他们删去让代码更清晰。查阅资料发现都是用的官方wp的脚本,而在b站上看到了一个手动删除这些循环的方法。

反汇编窗口->右键->Synchronize with->Pseudocode-A,然后在伪代码中选中你要删除的,在返回反汇编窗口就会提醒你要删除的代码,nop掉它们操作就可以。

虚假流程消除后,代码如下:

void __fastcall main(int a1, char **a2, char **a3)
{signed __int64 v3; // [rsp+1E0h] [rbp-110h]int j; // [rsp+1E8h] [rbp-108h]int i; // [rsp+1ECh] [rbp-104h]int k; // [rsp+1ECh] [rbp-104h]char s1[48]; // [rsp+1F0h] [rbp-100h] BYREFchar input[60]; // [rsp+220h] [rbp-D0h] BYREFint v9; // [rsp+25Ch] [rbp-94h]char *v10; // [rsp+260h] [rbp-90h]int v11; // [rsp+26Ch] [rbp-84h]bool v12; // [rsp+272h] [rbp-7Eh]unsigned __int8 v13; // [rsp+273h] [rbp-7Dh]int v14; // [rsp+274h] [rbp-7Ch]char *v15; // [rsp+278h] [rbp-78h]int v16; // [rsp+284h] [rbp-6Ch]int v17; // [rsp+288h] [rbp-68h]bool v18; // [rsp+28Fh] [rbp-61h]char *v19; // [rsp+290h] [rbp-60h]int v20; // [rsp+298h] [rbp-58h]bool v21; // [rsp+29Fh] [rbp-51h]__int64 v22; // [rsp+2A0h] [rbp-50h]bool v23; // [rsp+2AFh] [rbp-41h]__int64 v24; // [rsp+2B0h] [rbp-40h]__int64 v25; // [rsp+2B8h] [rbp-38h]__int64 v26; // [rsp+2C0h] [rbp-30h]__int64 v27; // [rsp+2C8h] [rbp-28h]int v28; // [rsp+2D0h] [rbp-20h]int v29; // [rsp+2D4h] [rbp-1Ch]char *v30; // [rsp+2D8h] [rbp-18h]int v31; // [rsp+2E0h] [rbp-10h]int v32; // [rsp+2E4h] [rbp-Ch]bool v33; // [rsp+2EBh] [rbp-5h]v9 = 0;memset(input, 0, 0x30uLL);memset(s1, 0, sizeof(s1));printf("Input:");v10 = input;__isoc99_scanf("%s");for ( i = 0; ; ++i ){v11 = i;v12 = i < 64;if ( i >= 64 )break;v13 = input[i];v14 = v13;if ( v13 == '\n' )                          // 回车就break{v15 = &input[i];*v15 = 0;break;}v16 = i + 1;                                // 没用}for ( j = 0; ; ++j )                          // 每次循环6次{v17 = j;v18 = j < 6;if ( j >= 6 )break;v19 = input;v3 = *(_QWORD *)&input[8 * j];              // 每8个字符一组for ( k = 0; ; ++k )                        // 每次循环64次{v20 = k;v21 = k < 64;if ( k >= 64 )break;v22 = v3;                                 // 没用v23 = v3 < 0;                             // 没用if ( v3 >= 0 )                            // 非负数{v26 = v3;                               // 没用v27 = 2 * v3;                           // 没用v3 *= 2LL;                              // 相当于左移,最后一位是0}else                                      // 负数{v24 = 2 * v3;                           // 没用v25 = 2 * v3;                           // 没用v3 = (2 * v3) ^ 0xB0004B7679FA26B3LL;   // 计算后最后一位是1}v28 = k;}v29 = 8 * j;                                //flag长度 6*8==48v30 = &s1[8 * j];*(_QWORD *)v30 = v3;v31 = j + 1;}v32 = memcmp(s1, qword_402170, 0x30uLL);      // 变化结果给了s1v33 = v32 != 0;if ( v32 )puts("Wrong!");elseputs("Correct!");
}

然后代码流程:第一个for循环没用,从第二个看外循环6次,内循环64次,把flag看为8个字节一组,然后如果是非负数就乘2(相当左移),如果是负数就乘2(相当左移)在异或一个数。

这里的关键是如何判断是前一个数是正数还是负数,这里有个技巧,如果是正数就左移一位,所以最后一位是0,而要是负数就会左移并异或一个数,最后一位会是1,所以可以通过这个判断前一个数是正数还是负数,所以代码如下:

 flag:flag{6ff29390-6c20-4c56-ba70-a95758e3d1f8}

相关内容

热门资讯

【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
AsusVivobook无法开... 首先,我们可以尝试重置BIOS(Basic Input/Output System)来解决这个问题。...
ASM贪吃蛇游戏-解决错误的问... 要解决ASM贪吃蛇游戏中的错误问题,你可以按照以下步骤进行:首先,确定错误的具体表现和问题所在。在贪...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...