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…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
[ACTF2020 新生赛]Include 1(php://filter伪协议)
题目 做法 启动靶机,点进去 点进去 查看URL,有 ?fileflag.php说明存在文件包含,原理是php://filter 协议 当它与包含函数结合时,php://filter流会被当作php文件执行。 用php://filter加编码,能让PHP把文件内容…...
永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器
一、原理介绍 传统滑模观测器采用如下结构: 传统SMO中LPF会带来相位延迟和幅值衰减,并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF),可以去除高次谐波,并且不用相位补偿就可以获得一个误差较小的转子位…...
Python竞赛环境搭建全攻略
Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型(算法、数据分析、机器学习等)不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...
02.运算符
目录 什么是运算符 算术运算符 1.基本四则运算符 2.增量运算符 3.自增/自减运算符 关系运算符 逻辑运算符 &&:逻辑与 ||:逻辑或 !:逻辑非 短路求值 位运算符 按位与&: 按位或 | 按位取反~ …...
Linux安全加固:从攻防视角构建系统免疫
Linux安全加固:从攻防视角构建系统免疫 构建坚不可摧的数字堡垒 引言:攻防对抗的新纪元 在日益复杂的网络威胁环境中,Linux系统安全已从被动防御转向主动免疫。2023年全球网络安全报告显示,高级持续性威胁(APT)攻击同比增长65%,平均入侵停留时间缩短至48小时。本章将从…...
