re学习(31)BUUCTF-xx(多层加密)
参考文章:
【BUUCTF逆向 [2019红帽杯]xx】_nb_What_DG的博客-CSDN博客
re学习笔记(26)BUUCTF-re-[2019红帽杯]xx_Forgo7ten的博客-CSDN博客
还有B站 水番正文
IDA64位载入
shift+F12查看字符串
交叉引用找到关键代码
使用findcrypt插件找到加密算法为tea系列,进函数内部查看知道为xxtea
// 代码审计(正向开发经验)
int __cdecl main(int argc, const char **argv, const char **envp)
{__int64 flaglen2; // rbx__int64 flaglen1; // rax__int128 *malloc5; // rax__int64 data; // r11__int128 *malloc7; // r14int v8; // edi__int128 *malloc9; // rsichar tmp; // r10int v11; // edx__int64 v12; // r8unsigned __int64 datalen; // rcx__int64 v14; // rcxunsigned __int64 v15; // raxunsigned __int64 i; // rax__int64 encodeflag; // raxsize_t encodeflaglen; // rsi_BYTE *enflag; // rbx_BYTE *v20; // r9int I; // r11dchar *data1; // r8__int64 n; // rcxchar v24; // al__int64 v25; // r9__int64 v26; // rdx__int64 v27; // raxsize_t Size; // [rsp+20h] [rbp-48h] BYREF__int128 v30; // [rsp+28h] [rbp-40h] BYREFint v31; // [rsp+38h] [rbp-30h]int v32; // [rsp+3Ch] [rbp-2Ch]int flag[4]; // [rsp+40h] [rbp-28h] BYREFint v34; // [rsp+50h] [rbp-18h]*(_OWORD *)flag = 0i64;v34 = 0;sub_1400018C0(std::cin, argv, flag); // 在C++中,std其实就是standard标准的意思。// 例如std::cin就是标准输入,std::cout就是标准输出的意思。flaglen2 = -1i64;flaglen1 = -1i64;do++flaglen1;while ( *((_BYTE *)flag + flaglen1) );if ( flaglen1 != 19 ) // flag 为 19位{sub_140001620((__int64 *)std::cout, (__int64)"error\n");_exit((int)flag);}malloc5 = (__int128 *)operator new(5ui64); // operator new申请内存(operator new后面将进行详细说明,这里理解为C语言中的malloc)data = *(_QWORD *)&Code; // 将Code数据给data,// Code为"qwertyuiopasdfghjklzxcvbnm1234567890"malloc7 = malloc5;v8 = 0;malloc9 = malloc5;do{tmp = *((_BYTE *)malloc9 + (char *)flag - (char *)malloc5);v11 = 0;*(_BYTE *)malloc9 = tmp;v12 = 0i64;datalen = -1i64;do++datalen;while ( *(_BYTE *)(data + datalen) );if ( datalen ){do{if ( tmp == *(_BYTE *)(data + v12) )break;++v11;++v12;}while ( v11 < datalen );}v14 = -1i64;do++v14;while ( *(_BYTE *)(data + v14) );if ( v11 == v14 )_exit(data);malloc9 = (__int128 *)((char *)malloc9 + 1);// 下一位}while ( (char *)malloc9 - (char *)malloc5 < 4 );*((_BYTE *)malloc5 + 4) = 0;do++flaglen2;while ( *((_BYTE *)flag + flaglen2) );v15 = 0i64;v30 = *malloc7;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; // 全部赋值为0encodeflag = (__int64)sub_140001AB0((__int64)flag, flaglen2, (unsigned __int8 *)&v30, &Size);encodeflaglen = Size;enflag = (_BYTE *)encodeflag;v20 = operator new(Size); // v20开辟一块内存区域I = 1;*v20 = enflag[2];data1 = v20 + 1; // v22与v20指向了同一片内存区域v20[1] = *enflag;v20[2] = enflag[3];v20[3] = enflag[1];v20[4] = enflag[6];v20[5] = enflag[4];v20[6] = enflag[7];v20[7] = enflag[5];v20[8] = enflag[10];v20[9] = enflag[8];v20[10] = enflag[11];v20[11] = enflag[9];v20[12] = enflag[14];v20[13] = enflag[12];v20[14] = enflag[15];v20[15] = enflag[13];v20[16] = enflag[18];v20[17] = enflag[16];v20[18] = enflag[19];v20[19] = enflag[17];v20[20] = enflag[22];v20[21] = enflag[20];v20[22] = enflag[23];for ( v20[23] = enflag[21]; I < encodeflaglen; ++data1 )// 异或操作{n = 0i64;if ( I / 3 > 0 ) // I从3开始{v24 = *data1;do{v24 ^= v20[n++]; // v22^v20*data1 = v24;}while ( n < I / 3 ); // I/3是跟前多少位...}++I;}*(_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 );v27 = (__int64)sub_140001620((__int64 *)std::cout, (__int64)"You win!");std::ostream::operator<<(v27, sub_1400017F0);return 0;
}
流程为
- 先判断输入的字符串是否都在程序实现存储的数据Code中
- 然后取前四个字符作为xxtea的密钥,(不满位数右端补零)
- 然后对输入的字符串进行加密
- 之后对加密的字符串打乱顺序
- 之后异或操作
- 再与存储的数据进行比对
其中第6部存储的数据为
v30,v30+1,v31,v32在栈上存放的位置相连。小端序存放,需将其反过来写。
开始写脚本:
一.逆异或 二.正序
data0 = "CEBC406B7C3A95C0EF9B202091F70235231802C8E75656FA"#为提取出来的v29,v29+1,v30,v31
data = []
for i in range(0,len(data0),2):data.append(int(data0[i]+data0[i+1],16))#每两位为整体,将16进制转换为10进制
print(data)
for i in range(len(data)-1,-1,-1):for j in range(i//3):data[i] ^= data[j]#1.进行的异或操作
print(data)
biao = [2,0,3,1,6,4,7,5,10,8,11,9,14,12,15,13,18,16,19,17,22,20,23,21]#置换表
shuju = [1]*24
for i in range(24):shuju[biao[i]] = data[i]#2.将其按照一定顺序置换
print(shuju)
print(len(shuju))
三.得到加密数据 密钥key xxtea解密
因为用户输入的为19位字符,也就是38位十六进制字符串,而上面生成了40位,所以要去掉最后两位,也就是去掉13。
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "encode.h"
int main()
{int i,j,data[] = { 188, 165, 206, 64, 244, 178, 178, 231, 169, 18, 157, 18, 174, 16, 200, 91, 61, 215, 6, 29, 220, 112, 248, 220 };for (i = 1; i <= 6; i++)//3.导出加密的数据,将其转换为十六进制并用小端序来表示{printf("0x");for (j = i * 4 - 1; j > (i - 1) * 4 - 1; j--)printf("%x", data[j]);printf(",");}printf("\n0x");int key[] = { 'f','l','a','g' };//导出密钥,将其转换为十六进制并用小端序来表示for (i = 3; i >= 0; i--)printf("%x", key[i]);printf(",");for (i = 0; i < 3; i++)//密钥为4个32位的数,1个字符4bit,4个字符为32bit,还差3个32bit的数printf("0x0,");
}
图片展示
#include <stdio.h>
#include <stdint.h>
#define DELTA 0x9e3779b9
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))
void btea(uint32_t *v, int n, uint32_t const key[4])
{uint32_t y, z, sum;unsigned p, rounds, e;if (n > 1) /* Coding Part */{rounds = 6 + 52/n;sum = 0;z = v[n-1];do{sum += DELTA;e = (sum >> 2) & 3;for (p=0; p<n-1; p++){y = v[p+1];z = v[p] += MX;}y = v[0];z = v[n-1] += MX;}while (--rounds);}else if (n < -1) /* Decoding Part */{n = -n;rounds = 6 + 52/n;sum = rounds*DELTA;y = v[0];do{e = (sum >> 2) & 3;for (p=n-1; p>0; p--){z = v[p-1];y = v[p] -= MX;}z = v[n-1];y = v[0] -= MX;sum -= DELTA;}while (--rounds);}
}int main()
{uint32_t v[6]= {0x40cea5bc,0xe7b2b2f4,0x129d12a9,0x5bc810ae,0x1d06d73d,0xdcf870dc};uint32_t const k[4]= {0x67616c66,0,0,0};int n= 6; //n的绝对值表示v的长度,取正表示加密,取负表示解密// v为要加密的数据是两个32位无符号整数// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位//printf("加密前原始数据:%u %u\n",v[0],v[1]);//btea(v, n, k);//printf("加密后的数据:%u %u\n",v[0],v[1]);btea(v, -n, k);for (int i = 0 ; i < 6;i++){printf("%x",v[i]);printf(" ");}return 0;
}m = [0x67616c66,0x5858437b,0x646e615f,0x742b2b5f,0x7d6165]
四.最后将生成的十六进制数用小端序表示
m = [0x67616c66,0x5858437b,0x646e615f,0x742b2b5f,0x7d6165]
flag = ''
for i in m:flag += libnum.n2s(i).decode()[::-1]print(flag)
#flag{CXX_and_++tea}
总结:
1.如果涉及多字节了,应该考虑字节的顺序,比如这个题,就应该将处理的数据都转换为小端序2.这个题的加密步骤有多步(3步:xxtea/乱序/异或)
3.要增强python工具,提高代码能力
相关文章:

re学习(31)BUUCTF-xx(多层加密)
参考文章:【BUUCTF逆向 [2019红帽杯]xx】_nb_What_DG的博客-CSDN博客 re学习笔记(26)BUUCTF-re-[2019红帽杯]xx_Forgo7ten的博客-CSDN博客 还有B站 水番正文 IDA64位载入 shiftF12查看字符串 交叉引用找到关键代码 使用findcrypt插件找到…...
HDFS的小文件影响及解决办法
Hadoop Distributed File System (HDFS) 是用于存储和处理大规模数据的分布式文件系统。然而,HDFS 中的小文件可能会对系统性能和资源利用产生一些影响。下面是小文件对HDFS的影响以及处理方法的一些信息: 影响: 元数据开销: HDFS中的每个文件和目录都有相关的元数据(文件…...
【前端】husky 的使用
husky 是一个优化 git hooks 的 npm 库 Modern native Git hooks made easy 安装和使用 1.安装 npm install husky --save-dev 2. 初始化 npx husky install;官方文档的写法是在 package.json 中初始化,本质上还是执行了 npx husky install 指令 3. 添加…...

Spring系列篇 -- Bean的生命周期
目录 经典面试题目: 一,Bean的生命周期图 二,关于Bean的生命周期流程介绍: 三,Bean的单例与多例模式 总结: 前言:今天小编给大家带来的是关于Spring系列篇中的Bean的生命周期讲解。在了解B…...

分类预测 | MATLAB实现BO-BiGRU贝叶斯优化双向门控循环单元多输入分类预测
分类预测 | MATLAB实现BO-BiGRU贝叶斯优化双向门控循环单元多输入分类预测 目录 分类预测 | MATLAB实现BO-BiGRU贝叶斯优化双向门控循环单元多输入分类预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 1.Matlab实现BO-BiGRU贝叶斯优化双向门控循环单元多特征分…...

Linux权限系列--给普通用户添加某个命令的sudo权限
原文网址:Linux权限系列--给普通用户添加某个命令的sudo权限_IT利刃出鞘的博客-CSDN博客 简介 说明 本文介绍Linux系统如何给普通用户添加某个命令的sudo权限。 使用场景 普通开发者可能需要sudo的命令: apt-get(经常要安装软件&#x…...

11-数据结构-栈和队列的应用(C语言)
栈和队列的应用 目录 栈和队列的应用 一、括号匹配(栈) 二、表达式的各种转换 (1)中缀转后缀(手工) (2)后缀转中缀表达式(手工) (3)中缀转后缀(栈) (4)中缀转后缀(树) (5)后缀表达式求值 (6)中缀表达式求值(栈…...

uni-app自定义多环境配置,动态修改appid
背景 在企业级项目开发中,一般都会分为开发、测试、预发布、生产等多个环境,在工程化中使用不同的打包命令改变环境变量解决不同环境各种变量需要手动修改的问题,比如接口请求地址,不同环境的请求路径前缀都是不同的。在使用uni-…...

04 - 分离头指针情况、理解HEAD和branch
查看所有文章链接:(更新中)GIT常用场景- 目录 文章目录 1. 分离头指针2. HEAD和branch2.1 branch的一些操作2.2 HEAD 1. 分离头指针 分离头指针detached HEAD是一种HEAD指针指向了某一个具体的 commit id,而不是分支的情况。 切换…...

C#__基本特性和使用
// 特性(attribute): // 一种允许我们向程序集添加元数据的语言结构 // 用于保存程序结构信息的某种特殊类型的类 // 类似“批注”,用于解释说明 #define IsShowMessage // 宏定义,在开头定义࿰…...
mysql(3)
分库分表 分库:将数据库中的数据分散到不同数据库上,可以垂直分库和水平分库。 1.垂直分库:把单一的数据按照业务进行划分,不同的业务使用不同的数据库,进而将一个数据库的压力分散到多个数据库。 2.水平分库&#…...
阿里巴巴常用的12个后端开发工具
1 阿尔萨斯Java在线诊断工具 Arthas是一款用于Java应用程序的在线诊断工具,由阿里巴巴于2018年9月开源。 典型场景: 您不知道从中加载类的特定JAR包。 您想弄清楚为什么您的系统会抛出各种与类相关的异常。 您不知道为什么修改后的代码无法执行。您不…...

php base64转图片保存本地
调用函数 public function base64(){$img $this->request->param(img);$img data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAkACQAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIy…...

unity物体移动至指定位置
物体坐标与物体移动 世界坐标与局部坐标之间的转换物体移动至指定位置需求思路注意 世界坐标与局部坐标之间的转换 在Unity中,物体的坐标分为局部坐标和世界坐标。 局部坐标是相对于物体的父对象的坐标系,而世界坐标是相对于场景的整体坐标系。 使用tr…...

详解C#-static void Main(string[] args)
目录 简介: 举例: 输出结果:编辑 总结: 简介: 在C#中static void Main(string[] args)这个句话有什么作用,分别代表什么意思!! 这句话是入口函数的声明,指定了C#程序的入口点,并定义了一个名为”Mai…...

中大许少辉博士《乡村振兴战略下传统村落文化旅游设计》中国建筑工业出版社八一付梓。
中大许少辉博士《乡村振兴战略下传统村落文化旅游设计》中国建筑工业出版社八一付梓。...

Matplotlib数据可视化(五)
目录 1.绘制折线图 2.绘制散点图 3.绘制直方图 4.绘制饼图 5.绘制箱线图 1.绘制折线图 import matplotlib.pyplot as plt import numpy as np %matplotlib inline x np.arange(9) y np.sin(x) z np.cos(x) # marker数据点样式,linewidth线宽,li…...
Python爬虫——requests_post请求
import requests import jsonurl https://fanyi.baidu.com/sugheaders {User-Agent: ,Cookie: }data {kw: hello }response requests.post(url, data, headersheaders)content response.textobj json.loads(content.encode(utf-8)) print(obj)总结: post请求…...

excel 下载方法封装
1.首先需要拿到后端返回的URL下载地址 2.写个下载方法 // url 接口返回的下载地址。例如:https://cancer-research.oss-cn-beijing.aliyuncs.com/yuance-platform-permission/校内共享数据导入模板.xlsx // name 文件名称 例如: 校内共享数据导入模板 /…...
按日,周,月,季,年统计;获取对应的时间段
按日,周,月,季,年统计;获取对应的时间段 1.周实体类:WeekEntity.java package com.test.common.entity;import java.time.LocalDate;public class WeekEntity {private String day;/*** 开始日期**/privat…...

Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...

网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...

短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...

算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...