NSSCTF [suctf 2019]hardcpp WP 控制流混淆
下载文件,64位主函数非常多循环
去控制流混淆,脚本下载deflat
用法
python 脚本名 文件名 起始地址
例如主函数地址是0x4007E0
python deflat.py hardCpp 0x4007E0
然后就生成了去混淆的文件
主函数非常大,开始分析逻辑
puts("func(?)=\"01abfc750a0c942167651c40d088531d\"?");
输出01abfc750a0c942167651c40d088531d"?
s = getchar();
fgets(v24, 21, stdin);
然后输入字符串,其中第一个值给s,然后再给v24。
if ( y >= 10 && ((((_BYTE)x - 1) * (_BYTE)x) & 1) != 0 )goto LABEL_13;while ( 1 ){v20 = strlen(&s);v34 = v20 != 21;if ( y < 10 || ((((_BYTE)x - 1) * (_BYTE)x) & 1) == 0 )break;
LABEL_13:v20 = strlen(&s);}
这里是个混淆,无论if跳不跳转,v20都等于s长度,注意s前面加了地址符&,
说明是地址,而s和v24的地址是连续的。所以v20本来应该为1,其实为21,不过v20的作用不大。,v34作用不大忽略
while ( 1 ){v19 = 1;if ( y < 10 || ((((_BYTE)x - 1) * (_BYTE)x) & 1) == 0 )break;v19 = 1;}
这里也有混淆,v19就是1
hile ( v19 < 21 ){if ( y >= 10 && ((((_BYTE)x - 1) * (_BYTE)x) & 1) != 0 ){v18 = v21 ^ v24[v19 - 1];v17[0] = main::$_0::operator()(v27, (unsigned int)v18);v16[0] = main::$_1::operator()(v25, (unsigned int)*(&s + v21 + v19 - 1));v8 = main::$_1::operator() const(char)::{lambda(int)#1}::operator()(v16, 7LL);v18 = main::$_0::operator() const(char)::{lambda(char)#1}::operator()(v17, (unsigned int)v8);v15[0] = main::$_2::operator()(v28, (unsigned int)v18);v14[0] = main::$_2::operator()(v28, (unsigned int)*(&s + v21 + v19 - 1));v9 = main::$_2::operator() const(char)::{lambda(char)#1}::operator()(v14, 18LL);v13[0] = main::$_3::operator()(v26, (unsigned int)v9);v10 = main::$_3::operator() const(char)::{lambda(char)#1}::operator()(v13, 3LL);v12[0] = main::$_0::operator()(v27, (unsigned int)v10);v11 = main::$_0::operator() const(char)::{lambda(char)#1}::operator()(v12, 2LL);v18 = main::$_2::operator() const(char)::{lambda(char)#1}::operator()(v15, (unsigned int)v11);}do{v18 = v21 ^ v24[v19 - 1];v17[0] = main::$_0::operator()(v27, (unsigned int)v18);v16[0] = main::$_1::operator()(v25, (unsigned int)*(&s + v21 + v19 - 1));v3 = main::$_1::operator() const(char)::{lambda(int)#1}::operator()(v16, 7LL);v18 = main::$_0::operator() const(char)::{lambda(char)#1}::operator()(v17, (unsigned int)v3);v15[0] = main::$_2::operator()(v28, (unsigned int)v18);v14[0] = main::$_2::operator()(v28, (unsigned int)*(&s + v21 + v19 - 1));v4 = main::$_2::operator() const(char)::{lambda(char)#1}::operator()(v14, 18LL);v13[0] = main::$_3::operator()(v26, (unsigned int)v4);v5 = main::$_3::operator() const(char)::{lambda(char)#1}::operator()(v13, 3LL);v12[0] = main::$_0::operator()(v27, (unsigned int)v5);v6 = main::$_0::operator() const(char)::{lambda(char)#1}::operator()(v12, 2LL);v18 = main::$_2::operator() const(char)::{lambda(char)#1}::operator()(v15, (unsigned int)v6);}while ( enc[v19 - 1] != v18 );while ( y >= 10 && ((((_BYTE)x - 1) * (_BYTE)x) & 1) != 0 );++v19;}
接下来来到了重头戏了,共六个函数一个一个分析
main::$_0::operator()
char __fastcall main::$_0::operator()(__int64 a1, char a2)
{return a2;
}
就是返回a2,我们把函数重命名为return_a2
方便后续分析
main::$_1::operator() const(char)::{lambda(int)#1}::operator()
__int64 __fastcall main::$_1::operator() const(char)::{lambda(int)#1}::operator()(char *a1, int a2)
{return (unsigned int)(*a1 % a2);
}
返回a1%a2,这里a2是常数7,命名为return_a1_mod_7
main::$_0::operator() const(char)::{lambda(char)#1}::operator()
__int64 __fastcall main::$_0::operator() const(char)::{lambda(char)#1}::operator()(__int64 a1, char a2)
{int v2; // eaxint v3; // eaxchar *v5; // [rsp+0h] [rbp-40h]int v6; // [rsp+8h] [rbp-38h]int v7; // [rsp+Ch] [rbp-34h]int v8; // [rsp+10h] [rbp-30h]int v9; // [rsp+14h] [rbp-2Ch]char *v10; // [rsp+18h] [rbp-28h]char v11; // [rsp+23h] [rbp-1Dh]int v12; // [rsp+24h] [rbp-1Ch]bool v13; // [rsp+2Ah] [rbp-16h]bool v14; // [rsp+2Bh] [rbp-15h]unsigned int v15; // [rsp+2Ch] [rbp-14h]v13 = ((((_BYTE)x_5 - 1) * (_BYTE)x_5) & 1) == 0;v14 = y_6 < 10;v12 = 1023500310;v11 = a2;v10 = (char *)a1;do{while ( 1 ){while ( 1 ){while ( 1 ){v9 = v12;v8 = v12 + 2037067308;if ( v12 != -2037067308 )break;v5 = v10;*((_BYTE *)&v5 - 16) = v11;v12 = -1418698808;}v7 = v9 + 1418698808;if ( v9 != -1418698808 )break;v3 = -2037067308;v5 = v10;*((_BYTE *)&v5 - 16) = v11;v15 = *((char *)&v5 - 16) + *v5;if ( y_6 < 10 || ((((_BYTE)x_5 - 1) * (_BYTE)x_5) & 1) == 0 )v3 = 1456142001;v12 = v3;}v6 = v9 - 1023500310;if ( v9 != 1023500310 )break;v2 = -2037067308;if ( v14 || v13 )v2 = -1418698808;v12 = v2;}HIDWORD(v5) = v9 - 1456142001;}while ( v9 != 1456142001 );return v15;
核心部分
v11 = a2;v10 = (char *)a1;
v5 = v10;
*((_BYTE *)&v5 - 16) = v11;
v15 = *((char *)&v5 - 16) + *v5;
return v15;
就是返回a1+a2,命名return_a1_add_a2
main::$_2::operator()
核心部分
v12 = a2;
*((_BYTE *)&v5 - 16) = v12;
LOBYTE(v5) = *((_BYTE *)&v5 - 16);
v16 = v5;
return v16;
就是返回v5低位,就是a2re_a22
main::$_2::operator() const(char)::{lambda(char)#1}::operator()
return (unsigned int)(char)(a2 ^ *a1);
命名return_a1_XOR_a2
main::$_3::operator()
v12 = a2;
*((_BYTE *)&v5 - 16) = v12;
LOBYTE(v5) = *((_BYTE *)&v5 - 16);
v16 = v5;
return v16;
命名re_a2222
main::$_3::operator() const(char)::{lambda(char)#1}::operator()
return (unsigned int)(a2 * *a1);
return_a1_x_a2
六个大爹干完了,然后再对逻辑进行分析,就是一直变换,就是解方程
v18=v24[v19-1];v17[0]=v18;//v17[0]=v24[v19-1];v16[0]=s[v19-1];v8=v16%7;//v8=s[v19-1]%7;v18=v17+v8;//v18=v24[v19-1]+s[v19-1]%7;v15[0]=v18;//v15[0]=v24[v19-1]+(s[v19-1]%7);v14[0]=s[v19-1];v9=v14^18;//v9=s[v19-1]^18;v13[0]=v9;//v13[0]=s[v19-1]^18;v10=v13*3;//v10=s[v19-1]^18*3;v12[0]=v10;v11=v12+2;//v11=s[v19-1]^18*3+2;v18=v15^v11;//v18={v24[v19-1]+(s[v19-1]%7)}^{s[v19-1]^18*3+2}
一层一层代入就得到了v18={v24[v19-1]+(s[v19-1]%7)}^{(s[v19-1]^18)*3+2}
然后再与enc[v19 - 1]比较,然后v19加1。继续上述循环。
然后逆过去解方程
v24[v19-1]+(s[v19-1]%7)=v18^(s[v19-1]^18*3+2)
v24[v19-1]=(v18^(s[v19-1]^18*3+2))-(s[v19-1]%7)
这样就能得到每一位了。现在看开头
puts("func(?)=\"01abfc750a0c942167651c40d088531d\"?");
32位,盲猜md5加密,去进行解密,得到符号#,说明第一个字符是#,即知道了s[v19-1],v19=1;.又知道了v18即enc,我们就可以求出第二位,同理得到所有,脚本如下
enc=[0xF3, 0x2E, 0x18, 0x36, 0xE1, 0x4C, 0x22, 0xD1, 0xF9, 0x8C,0x40, 0x76, 0xF4, 0x0E, 0x00, 0x05, 0xA3, 0x90, 0x0E, 0xA5]
lst=[35]
for i in range(len(enc)):lst.append((((enc[i]^((lst[i]^18)*3+2)))-((lst[i]%7)))&0xff)print(lst)
for i in lst:print(chr(i),end='')
这里有个&0xff运算,防止数字溢出
得到flag
#flag{mY-CurR1ed_Fns}
相关文章:

NSSCTF [suctf 2019]hardcpp WP 控制流混淆
下载文件,64位主函数非常多循环 去控制流混淆,脚本下载deflat 用法 python 脚本名 文件名 起始地址例如主函数地址是0x4007E0 python deflat.py hardCpp 0x4007E0然后就生成了去混淆的文件 主函数非常大,开始分析逻辑 puts("func(?…...

计算机毕业论文内容参考|基于神经网络的网络安全态势感知技术研究
文章目录 导文文章重点摘要前言绪论课题背景国内外现状与趋势课题内容相关技术与方法介绍技术分析技术设计技术实现总结与展望导文 基于神经网络的网络安全态势感知技术研究 文章重点 摘要 随着互联网的快速发展,网络攻击的频率和复杂度也在逐年增加。为了更好地保护信息系统…...
Flask框架之Request、Response、Cookies、Session等对象的使用
Request、Response、Cookies、Session等对象的使用 Request对象基本使用参数的获取转换器内置转换器自定义转换器 Response对象基本使用返回模板重定向返回JSON Cookies对象设置cookie获取cookie删除cookie Session会话对象设置SECRET_KEY设置会话获取会话释放会话 Request对象…...

信号与槽机制一
一、信号与槽 1、什么是信号与槽? 信号和槽是用于对象之间的通信,它是Qt的核心机制,在Qt编程中有着广泛的应用。如果想学好Qt,一定要充分掌握信号的槽的概念与使用。 2、信号和槽的代码实例 在Qt中,发送对象、发送的信…...
nodejs 复制文件到指定目录
var fs require(fs), path require(path), exec require(child_process).exec, sourcePath, targetPath; //获取命令行中的路径 process.argv.forEach(function (val, index, array) { if (index 2) { sourcePath val; } if (index 3) { targetPath val; } }); // 定义…...

第八章 使用Apache服务部署静态网站
文章目录 第八章 使用Apache服务部署静态网站一、网站服务程序1、网站服务介绍2、Apache程序介绍 二、配置服务文件参数1、Linux系统中的配置文件2、配置httpd服务程序时最常用的参数以及用途描述 三、SELinux安全子系统1、SELinux介绍2、SELinux服务配置模式3、Semanage命令4、…...

Three——四、几何体、高光网络材质、锯齿模糊以及GUI库的使用
文章: Three——一、初识Three以及基础的前端场景搭建(结尾含源码)Three——二、加强对三维空间的认识Three——三、动画执行、画布大小、渲染帧率和相机适配体验Three——四、几何体、高光网络材质、锯齿模糊以及GUI库的使用Three——五、点线模型对象、三角形概念…...

盲目自学网络安全只会成为脚本小子?
前言:我们来看看怎么学才不会成为脚本小子 目录: 一,怎么入门? 1、Web 安全相关概念(2 周)2、熟悉渗透相关工具(3 周)3、渗透实战操作(5 周)4、关注安全圈动…...
文从字顺|程序员须知,如何编写高质量代码
高质量代码是软件开发中至关重要的一部分。高质量的代码不仅可以提高软件的可维护性和可复用性,还可以增强软件的安全性和稳定性。同时,可以降低软件维护成本,提升开发效率,为用户提供更好的使用体验。 写出高质量代码是每个程序…...

PCIe物理层弹性缓存机制(详细)解析-PCIe专题知识(四)
目录 前言一、简介二、详细解析2.1 实例解析2.2 具体实现过程 三、总结四、其他相关链接1、PCI总线及发展历程总结2、PCIe物理层总结-PCIE专题知识(一)3、PCIe数据链路层图文总结-PCIe专题知识(二)4、PCIe物理层链路训练和初始化总…...
分片上传和断点续传的区别?实现思路是什么?
相同: 分片上传和断点续传都是网络传输中常用的重要技术 不同: 分片上传:将一个大文件切分为多个小文件进行上传。这种方式能够加快上传速度,降低服务器压力,特别适用于大型文件的上传。例如,在云存储系统…...

微前端 qiankun@2.10.5 源码分析(二)
微前端 qiankun2.10.5 源码分析(二) 我们继续上一节的内容。 loadApp 方法 找到 src/loader.ts 文件的第 244 行: export async function loadApp<T extends ObjectType>(app: LoadableApp<T>,configuration: FrameworkConfi…...
08异步请求:何种场景下应该使用异步请求?
异步在计算机科学中早就是一个比较常用的词汇,从操作系统的特性( 并发、共享、虚拟、异步)开始,异步就在处理并发操作中起到很大的作用,不仅如此,在软件层面,异步同样也是解决并发请求的一个关键过程,它可以将瞬时激增的请求进行更加灵活的处理,通过异步请求,客户端可…...
【深度学习 | Transformer】Transformers 教程:pipeline一键预测
文章目录 一、前言二、Computer vision2.1 Image classification2.2 Object detection2.3 Image segmentation2.4 Depth estimation 三、NLP3.1 Text classification3.2 Token classification3.3 Question answering3.4 Summarization3.5 Translation3.6 Language modeling3.6.…...

HTMLCSS
1、HTML 1.1 介绍 HTML 是一门语言,所有的网页都是用HTML 这门语言编写出来的,也就是HTML是用来写网页的,像京东,12306等网站有很多网页。 这些都是网页展示出来的效果。而HTML也有专业的解释 HTML(HyperText Markup Language)…...

【安装Nginx】
Linux上安装Nginx 文章目录 Linux上安装NginxUbuntuCentOS查看已安装的软件 Ubuntu 在 Ubuntu 上安装 Nginx 非常简单。只需按照以下步骤操作: 打开终端,更新软件包索引: sudo apt update安装 Nginx: sudo apt install nginx安…...

VSCode作业1:猜数字游戏和简单计数器(包含完整代码)
目录 猜数字游戏 一、使用‘random’函数获取随机数 二、 分情况讨论输入值大小情况 三、HTML代码 四、CSS样式及运行效果 简单计数器(计时器) 一、使用‘setInterval’函数实现计数效果 二、使用’clearInterval‘函数实现暂停计数和重新计数效果 …...

NANK OE骨传导开放式蓝牙耳机发布,极致体验拉满!
近日,中国专业音频品牌NANK南卡发布了全新一代——骨传导开放式蓝牙耳机NANK OE,耳机采用了传统真无线和骨传导的结合方式,带来更加舒适的佩戴体验和音质升级,同时还支持单双耳自由切换,全新的设计收获了市场的喜爱和认…...

看完这篇文章你就彻底懂啦{保姆级讲解}-----(I.MX6U驱动GPIO中断《包括时钟讲解》) 2023.5.9
目录 前言整体文件结构源码分析(保姆级讲解)中断初始化部分初始化GIC控制器初始化中断向量表设置中断向量表偏移 系统时钟初始化部分使能所有的时钟部分led初始化部分beep初始化部分key初始化部分按键中断初始化部分按键中断服务函数部分 while循环部分 …...

MySql -- 事务
目录 1.概念 2.事务的运用场景 3.事务的四大特点 4.执行事务带来的问题 4.1 脏读 4.2 不可重复度 4.3 幻读 5. MySQL中事务的隔离级别 1.概念 事务就是把若干个独立操作打包成一个整体而诞生的一种功能. 2.事务的运用场景 比如:A——>B 转账500 A的余额-500…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...
【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error
在前端开发中,JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作(如 Promise、async/await 等),开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝(r…...

消防一体化安全管控平台:构建消防“一张图”和APP统一管理
在城市的某个角落,一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延,滚滚浓烟弥漫开来,周围群众的生命财产安全受到严重威胁。就在这千钧一发之际,消防救援队伍迅速行动,而豪越科技消防一体化安全管控平台构建的消防“…...

基于江科大stm32屏幕驱动,实现OLED多级菜单(动画效果),结构体链表实现(独创源码)
引言 在嵌入式系统中,用户界面的设计往往直接影响到用户体验。本文将以STM32微控制器和OLED显示屏为例,介绍如何实现一个多级菜单系统。该系统支持用户通过按键导航菜单,执行相应操作,并提供平滑的滚动动画效果。 本文设计了一个…...
Spring事务传播机制有哪些?
导语: Spring事务传播机制是后端面试中的必考知识点,特别容易出现在“项目细节挖掘”阶段。面试官通过它来判断你是否真正理解事务控制的本质与异常传播机制。本文将从实战与源码角度出发,全面剖析Spring事务传播机制,帮助你答得有…...
MySQL基本操作(续)
第3章:MySQL基本操作(续) 3.3 表操作 表是关系型数据库中存储数据的基本结构,由行和列组成。在MySQL中,表操作包括创建表、查看表结构、修改表和删除表等。本节将详细介绍这些操作。 3.3.1 创建表 在MySQL中&#…...