这道题比较经典,涉及三个知识点,所以记录一下。

首先给了一个文件,detect it easy看了下,是32位exe。

放入ida中,找下main函数,F5反编译看一下伪代码。

int __cdecl main(int argc, const char **argv, const char **envp)
{unsigned int v3; // edxunsigned int v4; // ecx__m128i si128; // xmm1unsigned int v6; // esiconst __m128i *v7; // eax__m128i v8; // xmm0int v9; // eaxchar v11[100]; // [esp+0h] [ebp-CCh] BYREFchar v12[100]; // [esp+64h] [ebp-68h] BYREFunsigned int v13; // [esp+C8h] [ebp-4h] BYREFprintf("please input your flah:");memset(v11, 0, sizeof(v11));scanf("%s", v11);memset(v12, 0, sizeof(v12));sub_A21000(v12, &v13, (unsigned __int8 *)v11, strlen(v11));v3 = v13;v4 = 0;if ( v13 ){if ( v13 >= 16 ){si128 = _mm_load_si128((const __m128i *)&xmmword_A34F20);v6 = v13 - (v13 & 0xF);v7 = (const __m128i *)v12;do{v8 = _mm_loadu_si128(v7);v4 += 16;++v7;v7[-1] = _mm_xor_si128(v8, si128);}while ( v4 < v6 );}for ( ; v4 < v3; ++v4 )v12[v4] ^= 0x25u;}v9 = strcmp(v12, "you_know_how_to_remove_junk_code");if ( v9 )v9 = v9 < 0 ? -1 : 1;if ( v9 )printf("wrong\n");elseprintf("correct\n");system("pause");return 0;
}

从后往前看,要得到correct结果,就需要v12和字符串you_know_how_to_remove_junk_code相等。

v12和v13先是和输入的v11进行了一个函数sub_A21000的处理,然后又做了一段包含异或0X25的处理。

先看第一个函数。

知识点1:这里其实是一个base64解密函数。

int __fastcall sub_A21000(_BYTE *a1, unsigned int *a2, unsigned __int8 *a3, unsigned int a4)     //a1是v12,a2是v13值,a3是输入数据,a4是输入数据长度。
{int v4; // ebxunsigned int v5; // eaxint v6; // ecxunsigned __int8 *v7; // ediint v8; // edxbool v9; // zfunsigned __int8 v10; // clchar v11; // cl_BYTE *v12; // esiunsigned int v13; // ecxint v14; // ebxunsigned __int8 v15; // clchar v16; // dlint v20; // [esp+14h] [ebp-4h]unsigned int v21; // [esp+14h] [ebp-4h]int i; // [esp+24h] [ebp+Ch]v4 = 0;       // 记录 '=' 出现的次数v5 = 0;// 当前输入索引(扫描位置)v6 = 0;  // 有效 Base64 数据字符数(不包括空格、换行、=)v20 = 0;// 同 v6,用于避免寄存器冲突(编译器优化痕迹)if ( !a4 )     //长度为0就退出return 0;v7 = a3;do{v8 = 0;v9 = v5 == a4;if ( v5 < a4 ){do{if ( a3[v5] != 32 )// 跳过前导空格break;++v5;++v8;}while ( v5 < a4 );v9 = v5 == a4;}if ( v9 )break;if ( a4 - v5 >= 2 && a3[v5] == 13 && a3[v5 + 1] == 10 || (v10 = a3[v5], v10 == 10) )// 遇到换行继续{v6 = v20;}else{if ( v8 )// Base64 中间不能有空格,返回错误return -44;if ( v10 == 61 && (unsigned int)++v4 > 2 )// 等于号的个数比2个多,非法return -44;if ( v10 > 0x7Fu )// 检查字符是否超出 ASCII 127return -44;v11 = byte_A34E40[v10];if ( v11 == 0x7F || (unsigned __int8)v11 < 0x40u && v4 )return -44;v6 = ++v20;}++v5;}while ( v5 < a4 );if ( !v6 )return 0;v12 = a1;v13 = ((unsigned int)(6 * v6 + 7) >> 3) - v4;  //这里用的是通用公式,取字节数减去填充 = 的数量if ( a1 && *a2 >= v13 ){v21 = 3;      // 每组 4 个 Base64 字符生成最多 3 字节v14 = 0;for ( i = 0; v5; --v5 ){v15 = *v7;if ( *v7 != '\r' && v15 != '\n' && v15 != ' ' ){v16 = byte_A34E40[v15];   //byte_A34E40是base64的字母表v21 -= v16 == 64;v14 = v16 & '?' | (v14 << 6);   //累加 6 位if ( ++i == 4 )   //每 4 个字符为一组{i = 0;if ( v21 )*v12++ = BYTE2(v14);   //高字节if ( v21 > 1 )*v12++ = BYTE1(v14);//中字节if ( v21 > 2 )*v12++ = v14;//低字节}}++v7;}*a2 = v12 - a1;return 0;}*a2 = v13;return -42;
}

确定好该函数后,右击rename函数为base64decode方便查看,继续看代码。

v3 = v13;v4 = 0;if ( v13 ){if ( v13 >= 16 ){si128 = _mm_load_si128((const __m128i *)&xmmword_A34F20);v6 = v13 - (v13 & 0xF);v7 = (const __m128i *)v12;do{v8 = _mm_loadu_si128(v7);v4 += 16;++v7;v7[-1] = _mm_xor_si128(v8, si128);}while ( v4 < v6 );}for ( ; v4 < v3; ++v4 )v12[v4] ^= 0x25u;}v9 = strcmp(v12, "you_know_how_to_remove_junk_code");

知识点2:这里是使用了SSE指令,即带 _mm_前缀,可以通过在一个控制器上同时处理多个数据流,从而提高运算速度。

_mm_load_si128函数表示从内存中加载一个128bits值到暂存器,也就是16字节,**注意:**p必须是一个16字节对齐的一个变量的地址。返回可以存放在代表寄存器的变量中的值。
_mm_loadu_si128函数和_mm_load_si128一样的,但是不要求地址p是16字节对齐。

v6 = v13 - (v13 & 0xF);

这个是先把v13进行对齐,否则无法使用SSE指令处理。

v4 += 16;

这里是取n个16位的v12和xmmword_A34F20进行异或,剩下的不足16位的就和0x25异或。

双击查看xmmword_A34F20,发现其就是16位的0x25。

.rdata:00A34F20 xmmword_A34F20  xmmword 25252525252525252525252525252525h

所以,就是输入值进行base64解密后,和0x25异或,最后和you_know_how_to_remove_junk_code字符串比较是否一致。

import base64
s=list("you_know_how_to_remove_junk_code")
encrypted_bytes = bytes(ord(c) ^ 0x25 for c in s)
decoded_bytes = base64.b64encode(encrypted_bytes).decode('ascii')
print(decoded_bytes)

这里还有一个我犯的错误点是把字符转ord异或后,应该转为byte字节,再进行base64加密,但是我转的是chr,这会导致一部分数据无法转为chr,从而导致错误。

知识点3:加密、解密、计算哈希、编码等都应该使用byte字节形式相互转化。

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

小白也能看懂,HTTP中的文件上传与下载到底发生了什么?

HTTP 文件传输协议解析&#xff1a;上传与下载 这份文档会用最简单的方式&#xff0c;带你了解 HTTP 协议是如何处理文件下载和上传的。我们会专注于协议本身&#xff0c;看看客户端&#xff08;比如你的浏览器&#xff09;和服务端&#xff08;网站服务器&#xff09;之间到底…

快速构建数据集-假数据(生成划分)

快速构建数据集-假数据1、torch.randn&#xff08;✅&#xff09;2、HuggingFace Datasets&#xff08;✅&#xff09;&#x1f539;1. 从字典生成&#x1f539;2. 从 pandas.DataFrame 生成&#x1f539;3. 批量生成“业务型”假数据&#xff08;配合 Faker&#xff09;&#…

[修订版]Xenomai/IPIPE源代码情景解析

[修订版]Xenomai/IPIPE源代码情景解析 第一章&#xff1a;Interrupt Pipeline介绍 1.1 I-pipe与Xenomai1.2 I-pipe核心概念1.3 拉取I-pipe代码 第二章&#xff1a;I-pipe对ARM64异常的改造 2.1 ARM64中断机制与异常处理2.2 EL0_IRQ 中断改造之入口2.3 EL0_IRQ 中断改造之中断处…

【Qt开发】按钮类控件(三)-> QCheckBox

目录 1 -> 概述 2 -> 核心特性 2.1 -> 状态管理 2.2 -> 信号机制 2.3 -> 外观与文本 3 -> 应用场景 4 -> 代码示例 5 -> 总结 1 -> 概述 QCheckBox 是 Qt 框架中提供的一个基础控件&#xff0c;用于实现复选框功能。它允许用户在两种或三种…

在新发布的AI论文中 pytorch 和tensorflow 的使用比例

根据 2025 年最新的学术动态和行业报告&#xff0c;PyTorch 在 AI 论文中的使用比例已占据绝对主导地位&#xff0c;而 TensorFlow 的占比持续下降。以下是基于多个权威来源的综合分析&#xff1a; 一、顶级会议中的框架分布 在 NeurIPS、ICML、CVPR 等顶级学术会议中&#xff…

3DXML格式是什么?用什么软件可以打开?

3DXML 是一种开放标准的数据交换格式&#xff0c;主要用于三维 CAD&#xff08;计算机辅助设计&#xff09;模型的存储和交换。它是由 Dassault Systmes 开发的一种文件格式&#xff0c;常用于 CATIA V6 和其他支持该格式的应用程序中。3DXML 文件可以包含完整的 3D 模型数据&a…

9月8日星期一今日早报简报微语报早读

9月8日星期一&#xff0c;农历七月十七&#xff0c;早报#微语早读。1、中国火箭与月亮同框&#xff0c;遥感四十号03组卫星发射成功&#xff1b;2、湖南郴州开发区改革&#xff1a;编制数由815名减至680名&#xff0c;精简16.6%&#xff1b;3、水利部对广东、广西启动洪水防御Ⅳ…

windows系统搭建MQTT服务器

1、MQTT 协议 MQTT协议&#xff1a;实现MQTT协议需要客户端和服务器端通讯完成。 三种身份: 发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。 消息的发布者和订阅者都是客户端&#xff0c;消息代理是服务器&#xff0c;消息发布者可以同时是订阅者。 MQTT&am…

从 GPT 到 LLaMA:解密 LLM 的核心架构——Decoder-Only 模型

&#x1f525;从 GPT 到 LLaMA&#xff1a;解密 LLM 的核心架构——Decoder-Only 模型 “为什么所有大模型&#xff08;LLM&#xff09;都长一个样&#xff1f;” 因为它们都有一个共同的“基因”——Decoder-Only 架构。 在前面两节中&#xff0c;我们学习了&#xff1a; BER…

Codeforces Round 1047 (Div. 3)

由于最近这三天的数学建模&#xff0c;让我这个精力本来就不多的AI手更加力竭了&#xff0c;没注意到昨晚的cf&#xff0c;所以今天来补题了。 比赛连接&#xff1a;比赛传送门 A题&#xff1a; You are doing a research paper on the famous Collatz Conjecture. In your e…

C++经典的数据结构与算法之经典算法思想:贪心算法(Greedy)

贪心算法&#xff08;Greedy Algorithm&#xff09;&#xff1a;通过局部最优达成全局最优的决策策略 贪心算法是一种通过每次选择局部最优解来期望全局最优解的算法思想。它不考虑未来的影响&#xff0c;仅根据当前信息做出最优选择&#xff0c;适用于具有贪心选择性质和最优子…

LangChain实战(二十一):构建自动化AI客服系统

本文是《LangChain实战课》系列的第二十一篇,将带领您构建一个完整的自动化AI客服系统。通过结合对话记忆、工具调用和业务知识库,我们将创建一个能够处理复杂客户查询的智能客服解决方案。 前言 在现代商业环境中,客户服务是企业成功的关键因素之一。传统客服系统往往面临…

一人公司智能管理系统概述

系统概述 项目结构 Al_Compny系统采用前后端分离的全栈架构&#xff0c;项目根目录下包含两个主要子目录&#xff1a;Al_Compny_backend&#xff08;后端服务&#xff09;和Al_Compny_frontend&#xff08;前端应用&#xff09;。核心功能模块 Al_Compny系统是一个面向"一…

OpenWrt | 在 PPP 拨号模式下启用 IPv6 功能

文章目录一、WAN 口配置二、LAN 口配置三、IPv6 测试本文将详细介绍 将光猫的网络模式改成桥接之后使用路由器拨号的上网方式的情况下&#xff0c;在 OpenWrt 上使用 PPP 拨号模式上网时&#xff0c;启用 IPv6 功能的方法。 一、WAN 口配置 首先&#xff0c;我们需要在 网络 …

Java如何实现一个安全的登录功能?

安全登录系统完整教程 &#x1f4cb; 目录 项目概述技术栈安全特性项目结构核心组件详解安全实现原理部署和运行安全最佳实践常见问题解答进阶扩展 &#x1f3af; 项目概述 这是一个基于Spring Boot和Spring Security的完整安全登录系统&#xff0c;专为初学者设计&#xff…

星辰诞愿——生日快乐

前言 今天这篇博客并非技术文章&#xff0c;而是庆祝我可爱的妹妹18岁生日以及介绍我半年以来的学习经历 祝生网站&#xff1a;星辰诞愿(用户列表里第一位就是我妹妹&#xff0c;希望大家能献上自己的祝福&#xff0c;能分享转发更好&#xff0c;我在此感谢大家。如果使用手机&…

基于STM32单片机的智能粮仓温湿度检测蓝牙手机APP设计

基于STM32单片机的智能粮仓温湿度检测蓝牙手机APP设计 1 系统功能介绍 本系统是一款基于STM32单片机的智能粮仓环境监测与控制装置&#xff0c;核心目标是通过传感器实时采集粮仓内的温度和湿度信息&#xff0c;并结合蓝牙通信模块将数据传输至手机端&#xff0c;实现对粮仓环境…

简单视频转换器 avi转mp4

直接上代码package com.example.videoconverter;import ws.schild.jave.Encoder; import ws.schild.jave.EncoderException; import ws.schild.jave.MultimediaObject; import ws.schild.jave.encode.AudioAttributes; import ws.schild.jave.encode.EncodingAttributes; impor…

Kafka 与 RocketMQ 核心概念与架构对比

Kafka 与 RocketMQ 核心概念与架构对比DeepSeek生成&#xff0c;便于记忆大概逻辑核心概念对比图 #mermaid-svg-dEbo1XpAjfzOjvUW {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-dEbo1XpAjfzOjvUW .error-icon{fill…

30分钟深度压测cuBLAS:从FP64到INT8全精度性能剖析

在深度学习和高性能计算领域&#xff0c;GPU的矩阵运算性能是衡量系统算力的核心指标之一。NVIDIA的cuBLAS库作为CUDA平台上最基础的线性代数计算库&#xff0c;其性能表现直接影响着上层应用的运行效率。本文将详细介绍如何使用cublasmatmulbench工具对多GPU进行全面的性能基准…