BUUCTF Reverse/[2019红帽杯]xx

news2025/1/20 3:41:48

BUUCTF Reverse/[2019红帽杯]xx

在这里插入图片描述

先看下文件信息:没有加壳、64位程序

在这里插入图片描述

看别人wp时候发现个好东东,就是这个findcrypt插件,可以看加密算法的,具体安装可以看这个IDA7.5安装findcrypt3插件

在这里插入图片描述

可以看到这是tea加密

在这里插入图片描述

先一点点分析代码,输入flag,flag的长度必须为19

 sub_7FF7A98718C0(std::cin, argv, flag);       // 输入flag
  v3 = -1i64;
  v4 = -1i64;
  do
    ++v4;
  while ( *((_BYTE *)flag + v4) );
  if ( v4 != 19 )                               // 长度为19
  {
    sub_7FF7A9871620(std::cout, "error\n");
    _exit((int)flag);

这里给v6赋值为qwertyuiopasdfghjklzxcvbnm1234567890

这行代码看上去挺麻烦的,一眼唬住,但是仔细看下,前面有个v9 = v5,后面又减去了个v5,所以这行代码就变成了v10 = *flag
v10 = *((_BYTE *)v9 + (char *)flag - (char *)v5);

这段代码比较的是输入的flag的前四个字符是否在qwertyuiopasdfghjklzxcvbnm1234567890之间,顺便把flag的前四个字符赋值给v5

 v5 = (__int128 *)operator new(5ui64);
  v6 = *(_QWORD *)&Code;
  v7 = v5;
  v8 = 0;
  v9 = v5;
  do
  {
    v10 = *((_BYTE *)v9 + (char *)flag - (char *)v5);
    v11 = 0;
    *(_BYTE *)v9 = v10;
    v12 = 0i64;
    v13 = -1i64;
    do
      ++v13;
    while ( *(_BYTE *)(v6 + v13) );
    if ( v13 )
    {
      do
      {
        if ( v10 == *(_BYTE *)(v6 + v12) )
          break;
        ++v11;
        ++v12;
      }
      while ( v11 < v13 );
    }
    v14 = -1i64;
    do
      ++v14;
    while ( *(_BYTE *)(v6 + v14) );
    if ( v11 == v14 )
      _exit(v6);
    v9 = (__int128 *)((char *)v9 + 1);
  }
  while ( (char *)v9 - (char *)v5 < 4 );

将v5扩展成16位,不足补0,前四位应该是 ‘flag’,补完后就是 ‘flag000000000000’

 v30 = *v7;
  while ( *((_BYTE *)&v30 + v15) )
  {
    if ( !*((_BYTE *)&v30 + v15 + 1) )
    {
      ++v15;
      break;
    }
    if ( !*((_BYTE *)&v30 + v15 + 2) )
    {
      v15 += 2i64;
      break;
    }
    if ( !*((_BYTE *)&v30 + v15 + 3) )
    {
      v15 += 3i64;
      break;
    }
    v15 += 4i64;
    if ( v15 >= 0x10 )
      break;
  }
  for ( i = v15 + 1; i < 0x10; ++i )
    *((_BYTE *)&v30 + i) = 0;

这一段就是给输入的flag进行xxtea加密,前面扩展的v5就是它的秘钥,然后再变换位置

 v17 = sub_7FF7A9871AB0((__int64)flag, v3, (unsigned __int8 *)&v30, &Size);// tea加密
  v18 = Size;
  v19 = v17;
  v20 = operator new(Size);
  v21 = 1;
  *v20 = v19[2];
  v22 = v20 + 1;
  v20[1] = *v19;
  v20[2] = v19[3];
  v20[3] = v19[1];
  v20[4] = v19[6];
  v20[5] = v19[4];
  v20[6] = v19[7];
  v20[7] = v19[5];
  v20[8] = v19[10];
  v20[9] = v19[8];
  v20[10] = v19[11];
  v20[11] = v19[9];
  v20[12] = v19[14];
  v20[13] = v19[12];
  v20[14] = v19[15];
  v20[15] = v19[13];
  v20[16] = v19[18];
  v20[17] = v19[16];
  v20[18] = v19[19];
  v20[19] = v19[17];
  v20[20] = v19[22];
  v20[21] = v19[20];
  v20[22] = v19[23];

xxtea里面还有一段拆分的代码,将32位的数拆分成4个8位的数

    if ( v40 )
    {
      do
      {
        v42[v13] = v11[v13 >> 2] >> (8 * (v13 & 3));
        ++v13;
      }
      while ( v13 < v40 );
    }

异或

  for ( v20[23] = v19[21]; v21 < v18; ++v22 )
  {
    v23 = 0i64;
    if ( v21 / 3 > 0 )
    {
      v24 = *v22;
      do
      {
        v24 ^= v20[v23++];                      // 与前面的数异或
        *v22 = v24;
      }
      while ( v23 < v21 / 3 );
    }
    ++v21;
  }

变换后的字符串要等于v30中的字符串

 *(_QWORD *)&v30 = 0xC0953A7C6B40BCCEui64;
  v25 = v20 - (_BYTE *)&v30;
  *((_QWORD *)&v30 + 1) = 0x3502F79120209BEFi64;
  v26 = 0i64;
  v31 = 0xC8021823;
  v32 = 0xFA5656E7;
  do
  {
    if ( *((_BYTE *)&v30 + v26) != *((_BYTE *)&v30 + v26 + v25) )
      _exit(v8 * v8);
    ++v8;
    ++v26;
  }
  while ( v26 < 24 );

梳理下:
输入flag->取前四位扩展成16位作秘钥-> xxtea加密->拆分 ->移位 ->异或

然后写脚本挨个逆就行,先异或

int v20[] = {  0xCE, 0xBC, 0x40, 0x6B, 0x7C, 0x3A, 0x95, 0xC0, 0xEF, 0x9B,
                        0x20, 0x20, 0x91, 0xF7, 0x02, 0x35, 0x23, 0x18, 0x02, 0xC8,
                        0xE7, 0x56, 0x56, 0xFA};

   for(int v22 = 23,v21 = 23; v21 >= 1; v22--)
   {
       int v23 = 0;
       if( v21 / 3 > 0)
       {
           //int v24 = v20[v22];
           do
           {
               //v24 ^= v20[v23 ++];
               //v20[v22] = v24;
               v20[v22] ^= v20[v23++];
           }
           while(v23 < v21 / 3);
       }
       --v21;
   }

移位

int v19[25] = {0};

   v19[0] = v20[1];
   v19[2] = v20[0];
   v19[3] = v20[2];
   v19[1] = v20[3];
   v19[6] = v20[4];
   v19[4] = v20[5];
   v19[7] = v20[6];
   v19[5] = v20[7];
   v19[10] = v20[8];
   v19[8] = v20[9];
   v19[11] = v20[10];
   v19[9] = v20[11];
   v19[14] = v20[12];
   v19[12] = v20[13];
   v19[15] = v20[14];
   v19[13] = v20[15];
   v19[18] = v20[16];
   v19[16] = v20[17];
   v19[19] = v20[18];
   v19[17] = v20[19];
   v19[22] = v20[20];
   v19[20] = v20[21];
   v19[23] = v20[22];
   v19[21] = v20[23];

合并

    unsigned int flag[10] = {0};
    for(int i = 0 ; i < 0x18 ; i++)
    {
        //printf("%d, %d\n",i , 4 * (i / 4 + 1) - (i %  4) - 1);
        flag[i >>2] <<= 8;
        flag[i >> 2] += v19[4 * (i / 4 + 1) - i % 4 - 1];

    }

xxtea解密

xxtea秘钥是4个32位数,小端排序

#define MX ((y ^ sum) + (z ^ key[e ^ (p & 3)])) ^ (((4 * y) ^ (z >> 5)) + ((y >> 3) ^ (16 * z)))
#define DELTA 0x61C88647

int key[5] = {0x67616c66,0x00,0x00,0x00};

 unsigned int sum = 0 , n = 6;
  int rounds = 52 / n + 6;
  int i,j,k;
  unsigned int z,y,e,p;


    rounds = 6 + 52/n;
    sum = rounds * DELTA * (-1);
    y = flag[0];
    do
    {
       // if(rounds < 0) break;
        e = (sum >> 2) & 3;
        for (p=n-1; p>0; p--)
        {
            z = flag[p-1];
                //y = v2[p] -= ((y ^ sum) + (z ^ key[e ^ (p & 3)])) ^ (((4 * y) ^ (z >> 5)) + ((y >> 3) ^ (16 * z)));
            y = flag[p] -= MX;
            printf("p = %d\n",p);
        }
        z = flag[n-1];
            //y = v2[0] -= ((v2[0] ^ sum) + (z ^ key[e ^ (p & 3)])) ^ (((4 * v2[0]) ^ (z >> 5)) + ((v2[0] >> 3) ^ (16 * z)));
        y = flag[0] -= MX;
        sum += DELTA;
        printf("rounds = %d\n",rounds);

    }
    while(--rounds);


总代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define MX ((y ^ sum) + (z ^ key[e ^ (p & 3)])) ^ (((4 * y) ^ (z >> 5)) + ((y >> 3) ^ (16 * z)))
#define DELTA 0x61C88647

int main()
{

   int v20[] = {  0xCE, 0xBC, 0x40, 0x6B, 0x7C, 0x3A, 0x95, 0xC0, 0xEF, 0x9B,
                        0x20, 0x20, 0x91, 0xF7, 0x02, 0x35, 0x23, 0x18, 0x02, 0xC8,
                        0xE7, 0x56, 0x56, 0xFA};

   int key[5] = {0x67616c66,0x00,0x00,0x00};

      for(int v22 = 23,v21 = 23; v21 >= 1; v22--)
   {
       int v23 = 0;
       if( v21 / 3 > 0)
       {
    
           do
           {
               v20[v22] ^= v20[v23++];
           }
           while(v23 < v21 / 3);
       }
       --v21;
   }

   int v19[25] = {0};

   v19[0] = v20[1];
   v19[2] = v20[0];
   v19[3] = v20[2];
   v19[1] = v20[3];
   v19[6] = v20[4];
   v19[4] = v20[5];
   v19[7] = v20[6];
   v19[5] = v20[7];
   v19[10] = v20[8];
   v19[8] = v20[9];
   v19[11] = v20[10];
   v19[9] = v20[11];
   v19[14] = v20[12];
   v19[12] = v20[13];
   v19[15] = v20[14];
   v19[13] = v20[15];
   v19[18] = v20[16];
   v19[16] = v20[17];
   v19[19] = v20[18];
   v19[17] = v20[19];
   v19[22] = v20[20];
   v19[20] = v20[21];
   v19[23] = v20[22];
   v19[21] = v20[23];

    unsigned int flag[10] = {0};
    for(int i = 0 ; i < 0x18 ; i++)
    {
        //printf("%d, %d\n",i , 4 * (i / 4 + 1) - (i %  4) - 1);
        flag[i >>2] <<= 8;
        flag[i >> 2] += v19[4 * (i / 4 + 1) - i % 4 - 1];

    }

unsigned int sum = 0 , n = 6;
  int rounds = 52 / n + 6;
  int i,j,k;
  unsigned int z,y,e,p;

//xxtea

    rounds = 6 + 52/n;
    sum = rounds * DELTA * (-1);
    y = flag[0];
    do
    {
       // if(rounds < 0) break;
        e = (sum >> 2) & 3;
        for (p=n-1; p>0; p--)
        {
            z = flag[p-1];
     
            y = flag[p] -= MX;
        }
        z = flag[n-1];
        y = flag[0] -= MX;
        sum += DELTA;

    }
    while(--rounds);
    //输出
   char *tmp = flag;
   for(int i = 0 ; i < 19 ; i++)
   {
       printf("%c",*tmp++);
   }
   return 0;
}


输出

在这里插入图片描述

最终flag:flag{CXX_and_++tea}

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

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

相关文章

48.标准输入输出流

标准输入流对象cin&#xff0c;重点掌握的函数&#xff1a; 1.cin.get() //一次只能读取一个字符 2.cin.get(一个参数) //读一个字符 3.cin.get(两个参数) //可以读字符串 这种情况下不会读取换行符&#xff0c;换行符始终留在缓冲区当中 4.cin.getline() 此函数在读取数据的…

跳出打工圈!程序员要如何走上创业逆袭路,获得财富自由

前言 采访了一位创业人物&#xff0c;创业即是人生&#xff0c;生命精彩待续 人生的每一种经历都是一门功课&#xff0c;我们无法跳跃过去&#xff0c;所以必须要逐个地去完成它。无论遇到什么样的困难&#xff0c;自己想通了、走出来了&#xff0c;才会有不一样的自己。 大…

rt-thread通过spi连接W25Q32后无法读取ID

注意&#xff0c;cs引脚必须由rtt控制&#xff0c;但是我这个cs引脚用的是PA15&#xff0c;它默认是jlink的引脚&#xff0c;所以首先要将jlink禁用&#xff0c;如下&#xff1a; rcu_periph_clock_enable(RCU_AF);rcu_periph_clock_enable(RCU_GPIOA);rcu_periph_clock_enable…

开课通知 | 《AISHELL-3语音合成实战》课程

语音合成技术 在多个智能语音技术的学习方向中&#xff0c;语音合成又称文本转换&#xff08;Text To Speech, 简称TTS&#xff09;即将文字信息转换成为人类可以听得懂、流利的语音技术。在人机语音交互系统中&#xff0c;语音合成作为最后机器将内容转化为语音的输出环节&…

线程可重复使用,程序开发是如何使用线程池的呢?

大家都知道多线程开发对于程序开发的重要性&#xff0c;今天大连九哥来给大家聊一聊线程池的使用过程。 一、为什么要使用线程池&#xff1f; 大家都知道java支持多线程开发&#xff0c;也就是支持多个任务并行运行&#xff0c;我们也知道线程的生命周期中包括创建、就绪、运…

maltose-Transferrin 麦芽糖-转铁蛋白

maltose-Transferrin 麦芽糖-转铁蛋白 中文名称&#xff1a;麦芽糖-转铁蛋白 英文名称&#xff1a;maltose-Transferrin 别称&#xff1a;转铁蛋白修饰麦芽糖&#xff0c;Tf-麦芽糖 可以提供PEG接枝修饰麦芽糖&#xff0c;麦芽糖-聚乙二醇-转铁蛋白,Transferrin-PEG-maltos…

17.Http__Linux

目录 1.为什么要学Linux 2.我们要学什么 3.Linux命令操作 1.常用快捷键&#xff1a; 2.文件的操作 4.管道pipe 5.重定向redirect 5.查看系统指标&#xff08;任务管理器&#xff09; 7.安装软件(maven、包) 8.部署博客系统 1.首先对tomcat进行安装和调配 HTTPS:出现…

山西青年杂志山西青年杂志社山西青年编辑部2022年第22期目录

本刊专稿《山西青年》投稿&#xff1a;cn7kantougao163.com 基于学生激励机制的考核方案研究 聂晶晶; 1-4 当前我国大学生网络心理障碍分析及引导机制研究 陈宁;王佳玮; 5-8 教育教学研究 百万扩招背景下高职院校“三教”改革探究 郭庆秋; 9-11 “百万扩招”背…

linux统计目录文件数量

1、当前文件夹及子文件夹的数量&#xff1a; ls -lR | grep "^d" | wc -l 2、当前文件及子目录文件夹的数量&#xff1a; ls -lR | grep "^-" | wc -l 3、当前目录某文件的数量&#xff1a; find . -name filename | wc -l 4、当前目录所有目录和文件罗…

SpringCloud服务治理介绍Nacos安装及实现负载均衡

目录 一、服务治理简介 二、nacos简介 三、nacos下载&安装 四、nacos实现负载均衡 一、服务治理简介 通过上一章的操作&#xff0c;我们已经可以实现微服务之间的调用。但是我们把服务提供者的网络地址 &#xff08;ip&#xff0c;端口&#xff09;等硬编码到了代码中…

基于PHP+MySQL大连真爱果汁厂管理系统的设计与实现

果汁是以水果为原料经过物理方法如压榨、离心、萃取等得到的汁液产品。长期的饮用果汁不仅可以让我们大饱口福而且能够增加免疫力,减少生病,延缓衰老,甚至一些果汁还有美容养颜的功效,果汁中富含多种矿物质和有机酸为此深受各类人群的喜欢,随着人们健康意识的增加,人们对果汁的…

双十二投影仪推荐 三分钟告诉你怎么挑选到称心如意的投影仪

作为家庭沉浸式观影的必备神器&#xff0c;投影仪越来越受大众的喜爱&#xff0c;今天就让我们一起来看看双十二投影仪推荐&#xff0c;双十二高性价比投影仪选购指南&#xff0c;双十二卧室投影怎么选&#xff1f;2022双十二热门投影仪推荐&#xff0c;这8款投影仪总有一款适合…

华为云会议,轻松实现远程智能办公

说到云会议&#xff0c;很多人首先想到的应该就是华为云会议&#xff01;华为云会议基于华为近30年的音视频技术&#xff0c;结合华为IdeaHub等全系列智能协作终端&#xff0c;为客户提供全场景端云协同视频会议解决方案&#xff0c;满足跨地区、跨企业、跨终端的智能沟通协作需…

聚L-精氨酸/纳米金/石墨烯/聚苯胺复合膜/铝粉/稀土粒子修饰多巴胺的制备

小编这里给大家分享的科研内容是聚L-精氨酸/纳米金/石墨烯/聚苯胺复合膜/铝粉/稀土粒子修饰多巴胺的制备&#xff0c;和小编一起来看! 聚L-精氨酸/纳米金修饰多巴胺的制备&#xff1a; 利用多电位脉冲沉积法制备纳米金修饰电极 (AuNPs/GCE),再将L-精氨酸电聚合在AuNPs/GCE表面…

Kotlin高仿微信-项目实践58篇

Kotlin高仿微信项目实践主要包含5大模块&#xff1a; 1、Web服务器 2、Kotlin客户端 3、Xmpp即时通讯服务器 4、视频通话服务器 5、腾讯云服务器 另外也有Flutter版本高仿微信功能&#xff0c;Flutter版本跟Kotlin同时开发&#xff0c;调用的是同一个服务器接口。 每天只…

【原创】关于表结构更改的大量数据的迁移方案

前言 由于公司要求做产品之间的对接&#xff0c;需要统一表结构和字段名&#xff0c;但是有些表有上亿条数据&#xff0c;如果直接修改表字段名和加字段每一条SQL都要执行大量时间&#xff0c;大概时间为加一个字段1.5小时/1亿条数据&#xff0c;这耗时实在太长了&#xff0c;…

GitHub价值1w的Java最新面试宝典(附答案解析)被我弄到手了

为了能够帮助更多Java岗位同学就业&#xff0c;小编淘来了GitHub上最新Java面试宝典&#xff0c;本套题库均来自海量真实校招面试题目大数据进行的整理&#xff0c;学完这个题库&#xff0c;把此题库都理解透彻应对各家企业面试完全没有问题。&#xff08;当然要加上好的项目以…

Hosmer-Lemeshow检验(HL检验)

Hosmer-Lemeshow检验&#xff08;HL检验&#xff09;为模型拟合指标&#xff0c;其原理在于判断预测值与真实值之间的gap情况&#xff0c;如果p值大于0.05&#xff0c;则说明通过HL检验&#xff0c;即说明预测值与真实值之间并无非常明显的差异。反之如果p值小于0.05&#xff0…

操作系统:处理机调度与死锁 练习题(带有解析和答案)

文章目录1.处理机调度的层次和调度算法的目标1.1.处理机调度的层次1.2.处理机调度算法的目标求解周转时间和带权周转时间例题2.作业与作业调度2.1.批处理系统中的作业2.2.作业调度的主要任务2.3.先来先服务和短作业优先调度算法2.4.优先级调度算法和高响应比调度算法3.进程调度…

基于ASPNET+SQL的医院在线预约平台系统的设计与开发

本论文介绍的主要内容是从武警警官医院在线预约平台系统的需求分析到详细设计,最后到测试部分的整个过程。其实现主要功能有患者信息、医务人员、科室信息的管理和在线咨询、在线预约信息管理等五个主要模块。系统实现了用户信息在线管理、浏览以及在线咨询与预约信息的交互和数…