NSSCTF [suctf 2019]hardcpp WP 控制流混淆

news2024/11/15 21:53:42

下载文件,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; // eax
  int v3; // eax
  char *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}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/505100.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《Linux 内核设计与实现》10. 内核同步方法

文章目录 原子操作原子整数操作64 位原子操作原子位操作 自旋锁读写自旋锁信号量计数信号量和二值信号量信号量方法列表 读写信号量互斥体信号量和互斥体自旋锁和互斥体 完成变量BLK&#xff1a;大内核锁顺序锁禁止抢占顺序和屏障 原子操作 原子操作&#xff1a;可以保证指令以…

人大金仓KFS全新升级,从容应对“名场面”

系统迁移升级过程中&#xff0c; 迁移停机时间长&#xff1f; 异构数据库迁移成本高&#xff1f; 数据一致性无法保证&#xff1f; 发生故障后缺乏回滚手段&#xff1f; 这些“名场面”您遇到过吗&#xff1f; KFS全新解决方案正式发布 针对用户不同应用场景出现的普遍痛点&…

C++基础之类、对象一(类的定义,作用域、this指针)

目录 面向对象的编程 类的引入 简介 类的定义 简介 访问限定符 命名规则 封装 简介 类的作用域 类的大小及存储模型 this指针 简介 面向对象的编程 C与C语言不同&#xff0c;C是面向对象的编程&#xff0c;那么什么是面向对象的编程呢&#xff1f; C语言编程&#xff0c;规定…

C++之多态与虚函数

文章目录 初识多态运行时多态的原理静态联编和动态联编 初识多态 多态性是面向对象程序设计的关键技术之一。若程序不支持多态&#xff0c;不能称为面向对象的语言编译时多态&#xff1a;通过函数重载实现&#xff0c;早期绑定运行时多态&#xff1a;在程序执行过成中&#xf…

神策微报告丨10 页速览「生成式 AI」能力边界与商业化!

以 ChatGPT 为代表的生成式 AI 投入规模化应用后&#xff0c;一场人工智能的军备竞赛正在上演&#xff0c;生成式 AI 成为科技领域关注的焦点。 基于此背景&#xff0c;神策数据正式发布微报告《关于生成式 AI&#xff0c;这 10 页 PPT 就够了&#xff01;》&#xff0c;从突破…

DIDCTF平台练习-2022暑假取证学习

文章目录 前言123456789101112131415161718 前言 挺适合新手的&#xff0c;平台地址https://forensics.didctf.com/challenges 1 直接看 WIN-49I0SNRJAMF 2 计算即可 4547A61A11064DF47B272A4803788597F9A5E9AC0F11A93ABE58C8B8588956CB 3 NoxPlayer&#xff0c;夜神…

记一次azkaban调度异常处理

一、背景 预发布环境使用的数据库性能比较低&#xff0c;根据业务测试的需求&#xff0c;需要将数据库更换成 稳定高性能的数据库。更换业务数据库后azkaban定时任务失败 二、数据库服务信息 说明&#xff1a;该部分使用代号来代替&#xff0c;非真实信息 该数据库存储了azka…

docker 搭建 Elasticsearch和Kibana 8.x版本

参考: docker入门&#xff1a;单机elasticsearch安装记录&#xff0c;保证无坑_8月日更_小鲍侃java_InfoQ写作社区 新建文件夹 同上文所述相同&#xff0c;需要在宿主机上挂载配置文件与数据文件。 mkdir -p /Users/louye/data/learn-data/elastic/config mkdir -p /Users/lo…

学系统集成项目管理工程师(中项)系列19a_成本管理(上)

1. 要确保在批准的预算内完成项目 2. 必须考虑项目决策对项目产品、服务或成果的使用成本、维护成本和支持成本的影响 3. 对成本的影响力在项目早期最大 4. 失控原因 4.1. 对工程项目认识不足 4.1.1. 对信息系统工程成本控制的特点认识不足&#xff0c;对难度估计不足 4.…

大数据|实验三:PageRank算法实现

文章目录 &#x1f4da;PageRank概述&#x1f407;什么是PageRank&#x1f407;PageRank的简化模型&#x1f407;PageRank的随机浏览模型 &#x1f4da;实验目的&#x1f4da;实验平台&#x1f4da;实验内容&#x1f407;在本地编写程序和调试&#x1f407;在集群上提交作业并执…

【Linux脚本篇】流程控制语句-if

目录 &#x1f341;流程控制语句if &#x1f342;单分支语句 &#x1f342;双分支语句 &#x1f342;多分支语句 &#x1f341;流程控制语句&#xff1a;文件比较 &#x1f341;流程控制语句&#xff1a;整数比对 &#x1f341;流程控制语句&#xff1a;字符对比 &#x1f341;…

校园企业车辆维修报修管理系统设计与开发

本研究课题重点主要包括了下面几大模块&#xff1a;在本基于.net平台的车辆系统中分为管理员和用户2个模块&#xff0c;主要功能包括管理员信息管理&#xff0c;车辆信息管理&#xff0c;驾驶员信息管理&#xff0c;事故信息管理&#xff0c;维修信息管理&#xff0c;维修点管理…

【Leetcode -463.岛屿的周长 - 476.数字的补码】

Leetcode Leetcode -463.岛屿的周长Leetcode - 476.数字的补码 Leetcode -463.岛屿的周长 题目&#xff1a;给定一个 row x col 的二维网格地图 grid &#xff0c;其中&#xff1a;grid[i][j] 1 表示陆地&#xff0c; grid[i][j] 0 表示水域。 网格中的格子 水平和垂直 方向…

C/C++每日一练(20230509) 分割回文串II、盛水容器、Atoi

目录 1. 分割回文串 II &#x1f31f;&#x1f31f;&#x1f31f; 2. 盛最多水的容器 &#x1f31f;&#x1f31f; 3. 字符串转换整数 (atoi) &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/…

Springboot +Flowable,三种常见网关的使用(排他、并行、包容网关)(二)

一.简介 Flowable 中常用的网关主要有三种类型&#xff0c;分别是&#xff1a; 排他网关并行网关包容网关 下面来说下这三种的网关的概念和用法。 二.并行网关 并行网关&#xff0c;这种网关一般用在并行任务上&#xff0c;截图如下&#xff1a; 并行网关一般是成对出现的…

Vue学习笔记3 - Vue中 radio/select 如何设定初期值

使用 v-model 如何设定 radio的初期值呢&#xff1f; 使用v-model 绑定 value 属性&#xff0c;然后设置初始 value 属性的值即可。 比如 sexValue设置为 女&#xff0c;那么 女 那项就会被默认选中。 <!DOCTYPE html> <html lang"en"> <head>&…

数字孪生模型构建理论及应用

源自&#xff1a;计算机集成制造系统 作者&#xff1a;陶飞 张贺 戚庆林 徐 俊 孙铮 胡天亮 刘晓军 刘庭煜 关俊涛 陈畅宇 孟凡伟 张辰源 李志远 魏永利 朱铭浩 肖斌 摘 要 数字孪生作为实现数字化转型和促进智能化升级的重要使能途径&#xff0c;一直备受各…

Vue-01---初识Vue

一.搭建Vue开发环境 不建议初学者直接使用vue-cli脚手架 不建议初学者使用开发工具直接创建Vue工程 直接在html中用script引入 浏览器安装Vue Devtools插件 CDN链接引入&#xff08;不建议&#xff09;&#xff1a; <script src"h…

什么是电子负载?

1、简介 电子负载在硬件测试中是使用频率比较高的设备之一&#xff0c;是一种从电源吸收电流并消耗功率的测试仪器&#xff0c;基本都是通过控制内部功率器件&#xff08;Mosfet&#xff09;导通量&#xff0c;依靠功率管的耗散功率消耗电能。很多初入硬件或者硬件测试的小伙伴…

物联网安全工作梳理(0)

物联网相比互联网,设备更多,协议更多,标准不统一,安全更脆弱,因此相当于互联网的安全漏洞增量。物联网安全整改流程相比互联网在增量上工作更多些。本篇将从八个方面阐述物联网安全整改工作总结,每个面都是一项大工程。 物联网与互联网差异 物联网安全可分为8大类来说明…