[羊城杯 2020]easyre 1题解

news2024/11/16 14:38:34

一步一个脚印地耐心攀登,就是别去看顶峰,而要专注于在爬的路。

                                                                                        ——黑泽明

目录

1.查壳

2.IDA静态分析main函数

3.研究三重加密

第一重加密

第二重加密

第三重加密

4.解密


1.查壳

 64bit  exe文件

2.IDA静态分析main函数

拖入IDA,找到main函数

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // eax
  int v4; // eax
  int v5; // eax
  int result; // eax
  char Str; // [rsp+20h] [rbp-60h]
  char Str1; // [rsp+50h] [rbp-30h]
  char v9; // [rsp+90h] [rbp+10h]
  char v10; // [rsp+D0h] [rbp+50h]
  char Str2[8]; // [rsp+110h] [rbp+90h]
  int v12; // [rsp+14Ch] [rbp+CCh]

  _main();
  strcpy(Str2, "EmBmP5Pmn7QcPU4gLYKv5QcMmB3PWHcP5YkPq3=cT6QckkPckoRG");
  puts("Hello, please input your flag and I will tell you whether it is right or not.");
  scanf("%38s", &Str);
  if ( strlen(&Str) == 38
    && (v3 = strlen(&Str), (unsigned int)encode_one(&Str, v3, &v10, &v12) == 0)
    && (v4 = strlen(&v10), (unsigned int)encode_two(&v10, v4, &v9, &v12) == 0)
    && (v5 = strlen(&v9), (unsigned int)encode_three(&v9, v5, &Str1, &v12) == 0)
    && !strcmp(&Str1, Str2) )
  {
    puts("you are right!");
    result = 0;
  }
  else
  {
    printf("Something wrong. Keep going.");
    result = 0;
  }
  return result;
}

我们将flag输入到了str

if ( strlen(&Str) == 38
    && (v3 = strlen(&Str), (unsigned int)encode_one(&Str, v3, &v10, &v12) == 0)
    && (v4 = strlen(&v10), (unsigned int)encode_two(&v10, v4, &v9, &v12) == 0)
    && (v5 = strlen(&v9), (unsigned int)encode_three(&v9, v5, &Str1, &v12) == 0)
    && !strcmp(&Str1, Str2) )

可以看出正确的flag长度应该是38

根据函数名应该是有三次加密

看到第一次加密encode_one(&Str, v3, &v10, &v12) ,v10是引用的形式传参,v4 = strlen(&v10), (unsigned int)encode_two(&v10, v4, &v9, &v12) == 0,第二次在传str的地方传入了v10,第三次则是v9,可以猜测应该是对输入的str三重加密

最后对比str1,str2,相等,并且前面的条件都正确,就是正确的flag

str1,str2跟进

 

 dup即英文duplicate的缩写,重复的意思,用来定义重复的字节、字、双字、结构等内存缓冲区。

?表示值是未定义的  汇编语言

说明str1,str2最初没有什么内容

emmm,不对

在主函数开始的时候,给Str2赋值了,

重点研究三重加密是什么

3.研究三重加密

第一重加密

__int64 __fastcall encode_one(const char *a1, int a2, char *a3, int *a4)
{
  int v5; // esi
  int v6; // esi
  int v7; // esi
  int v8; // [rsp+34h] [rbp-1Ch]
  int v9; // [rsp+38h] [rbp-18h]
  char *v10; // [rsp+40h] [rbp-10h]
  int v11; // [rsp+48h] [rbp-8h]
  int i; // [rsp+4Ch] [rbp-4h]
  unsigned __int8 *v13; // [rsp+70h] [rbp+20h]
  int v14; // [rsp+78h] [rbp+28h]
  int *v15; // [rsp+88h] [rbp+38h]

  v13 = (unsigned __int8 *)a1;
  v14 = a2;
  v15 = a4;
  if ( !a1 || !a2 )
    return 0xFFFFFFFFi64;
  v11 = 0;
  if ( a2 % 3 )
    v11 = 3 - a2 % 3;
  v9 = a2 + v11;
  v8 = 8 * (a2 + v11) / 6;
  v10 = a3;
  for ( i = 0; i < v9; i += 3 )
  {
    *v10 = alphabet[(char)*v13 >> 2];
    if ( v14 + v11 - 3 == i && v11 )
    {
      if ( v11 == 1 )
      {
        v5 = (char)cmove_bits(*v13, 6u, 2u);
        v10[1] = alphabet[v5 + (char)cmove_bits(v13[1], 0, 4u)];
        v10[2] = alphabet[(char)cmove_bits(v13[1], 4u, 2u)];
        v10[3] = 61;
      }
      else if ( v11 == 2 )
      {
        v10[1] = alphabet[(char)cmove_bits(*v13, 6u, 2u)];
        v10[2] = 61;
        v10[3] = 61;
      }
    }
    else
    {
      v6 = (char)cmove_bits(*v13, 6u, 2u);
      v10[1] = alphabet[v6 + (char)cmove_bits(v13[1], 0, 4u)];
      v7 = (char)cmove_bits(v13[1], 4u, 2u);
      v10[2] = alphabet[v7 + (char)cmove_bits(v13[2], 0, 6u)];
      v10[3] = alphabet[v13[2] & 0x3F];
    }
    v10 += 4;
    v13 += 3;
  }
  if ( v15 )
    *v15 = v8;
  return 0i64;
}

我们只需要看这个加密算法的核心部分,根据加密算法的特征,识别出什么加密算法

move_bit字面意思和使用这个函数的次数很像是base64,看一下加密算法中很显眼的这个alphabet数组

h是十六进制的意思,hex,按下快捷键a转换成字符看一下 

 发现确实应该是一个base64加密表

第二重加密

__int64 __fastcall encode_two(const char *a1, int a2, char *a3, int *a4)
{
  char *Source; // [rsp+40h] [rbp+10h]
  char *v6; // [rsp+50h] [rbp+20h]

  Source = (char *)a1;
  v6 = a3;
  if ( !a1 || !a2 )
    return 0xFFFFFFFFi64;
  strncpy(a3, a1 + 26, 0xDui64);
  strncpy(v6 + 13, Source, 0xDui64);
  strncpy(v6 + 26, Source + 39, 0xDui64);
  strncpy(v6 + 39, Source + 13, 0xDui64);
  return 0i64;
}

encode_two(&v10, v4, &v9, &v12) == 0

根据前面的推断,第三个参数应该是加密后的密文,用一个Source指针指向原来的明文,然后进行strncpy操作

strncpy(a3, a1 + 26, 0xDui64);
  strncpy(v6 + 13, Source, 0xDui64);
  strncpy(v6 + 26, Source + 39, 0xDui64);
  strncpy(v6 + 39, Source + 13, 0xDui64);

就是一个简单的替换加密

第三重加密

__int64 __fastcall encode_three(const char *a1, int a2, char *a3, int *a4)
{
  char v5; // [rsp+Fh] [rbp-11h]
  int i; // [rsp+14h] [rbp-Ch]
  char *v7; // [rsp+18h] [rbp-8h]
  const char *v8; // [rsp+30h] [rbp+10h]

  v8 = a1;
  if ( !a1 || !a2 )
    return 0xFFFFFFFFi64;
  v7 = a3;
  for ( i = 0; i < a2; ++i )
  {
    v5 = *v8;
    if ( *v8 <= 64 || v5 > 90 )
    {
      if ( v5 <= 96 || v5 > 122 )
      {
        if ( v5 <= 47 || v5 > 57 )
          *v7 = v5;
        else
          *v7 = (v5 - 48 + 3) % 10 + 48;
      }
      else
      {
        *v7 = (v5 - 97 + 3) % 26 + 97;
      }
    }
    else
    {
      *v7 = (v5 - 65 + 3) % 26 + 65;
    }
    ++v7;
    ++v8;
  }
  return 0i64;
}

第三重加密是凯撒加密

*v7 = (v5 - 48 + 3) % 10 + 48;这是典型的凯撒加密的特征

不了解凯撒加密阅读 凯撒加密

需要简单熟悉一下ASCLL码表,便于阅读

使用快捷键r改为字符,可以看出分别对于大小写字母和数字进行了移动三位的凯撒加密

 分析完毕,开始爆破

4.解密

!strcmp(&Str1, Str2) 

三重加密之后的字符串是Str1,Str2是一直的,当Str1等于Str2的时候会输出"you are right!"

我们就需要将Str2的值逆向三重解密,得到正确的flag

需要解密的密文EmBmP5Pmn7QcPU4gLYKv5QcMmB3PWHcP5YkPq3=cT6QckkPckoRG

第一重解密(凯撒加密的解密)

def decrypt_caesar(str, key=3):  # 解密函数
    text = ""
    for i in str:
        if ord(i) >= 65 and ord(i) <= 90:
            text += chr(65 + ((ord(i) - 65) - key) % 26)
        elif ord(i) >= 97 and ord(i) <= 122:
            text += chr(97 + ((ord(i) - 97) - key) % 26)
        elif ord(i) >= 48 and ord(i) <= 57:
            text += chr(48 + ((ord(i) - 48) - key) % 10)
        else:
            text+=i
    return text

m1="EmBmP5Pmn7QcPU4gLYKv5QcMmB3PWHcP5YkPq3=cT6QckkPckoRG"
m2=decrypt_caesar(m1)
print(m2)

脚本运行结果

BjYjM2Mjk4NzMR1dIVHs2NzJjY0MTEzM2VhMn0=zQ3NzhhMzhlOD

第二重解密(替换加密)

就是一个四部分替换一下顺序,不写脚本了,简单手推

BjYjM2Mjk4NzM 3
R1dIVHs2NzJjY 1
0MTEzM2VhMn0= 4
zQ3NzhhMzhlOD 2
R1dIVHs2NzJjYzQ3NzhhMzhlODBjYjM2Mjk4NzM0MTEzM2VhMn0=

破解结果

R1dIVHs2NzJjYzQ3NzhhMzhlODBjYjM2Mjk4NzM0MTEzM2VhMn0=

第三重解密(base64解密)

import base64
a="R1dIVHs2NzJjYzQ3NzhhMzhlODBjYjM2Mjk4NzM0MTEzM2VhMn0="
b=base64.b64decode(a.encode());
print(b.decode())

也可以使用在线解密网站

GWHT{672cc4778a38e80cb362987341133ea2}

flag{672cc4778a38e80cb362987341133ea2}

边解题编写题解,别的buuctf逆向题解可以关注我的专栏reverse

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

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

相关文章

芯片验证系列——Checker

在产生了有效的激励后&#xff0c;需要判断出不符合功能描述的行为。Checker就是用于查看DUT是否按照功能描述做出期望的行为&#xff0c;识别出所有的设计缺陷。 按照激励的生成方式和检查的功能点分布可以将验证划分为三种方式&#xff1a; 黑盒验证&#xff1a;验证环境不…

【Vue】前端工程化与 webpack

一、前端工程化前端开发1.1 小白眼中的前端开发会写 HTML CSS JavaScript 就会前端开发需要美化页面样式&#xff0c;就拽一个 bootstrap 过来需要操作 DOM 或发起 Ajax 请求&#xff0c;再拽一个 jQuery 过来需要快速实现网页布局效果&#xff0c;就拽一个 Layui 过来1.2 实…

redis事务详解

事务是逻辑上对数据的一组操作&#xff0c;这操作要么一次全部成功或者这操作全部失败&#xff0c;是不可分割的单位 四大特性 原子性&#xff0c;一致性&#xff0c;隔离性&#xff0c;持久性(ACID) redis的事务 redis是弱事务型数据库&#xff0c;并不具备ACID的全部特性 re…

python情感分析:基于jieba的分词及snownlp的情感分析!

情感分析&#xff08;sentiment analysis&#xff09;是2018年公布的计算机科学技术名词。 它可以根据文本内容判断出所代表的含义是积极的还是负面的&#xff0c;也可以用来分析文本中的意思是褒义还是贬义。 一般应用场景就是能用来做电商的大量评论数据的分析&#xff0c;…

【Linux】基础IO文件操作

目录 基础IO 重谈文件 重谈C语言的文件操作 系统文件IO 理解文件 文件描述符fd 0 & 1 & 2 文件描述符的分配规则 重定向 使用 dup2 系统调用 在minishell中添加重定向功能 缓冲区 理解缓冲区 再次理解缓冲区 基础IO 重谈文件 1、空文件&#xff0c;也要…

C++STL入门:string的基本使用小笔记

目录 一.string类简介 二.string类的常用成员接口 1.string类对象的构造函数接口 2. string类对象的容量操作接口 std::string::size std::string::length std::string::empty std::string::clear std::string::resize std::string::reserve 3.string类对象的访问及遍历操作…

【精品】k8s的CKA考题17道解析

目标一:记住命令关键单词 第4道题:scale replicas 第5道题:cordon、uncordon、drain 第8道题:target-port 目标二:完成操作要求 NoSchedule 查看工作节点的健康状态 ,确定集群中有多少节点为 Ready 状态,并且去除包含 NoSchedule 污点的节点。之后将数字写到/opt/repl…

Mybatis-Plus使用指南

1、了解Mybatis-Plus 1.1、Mybatis-Plus介绍 MyBatis-Plus&#xff08;简称 MP&#xff09;是一个 MyBatis 的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。 官网&#xff1a;https://mybatis.plus/ 或 https://mp.baomi…

基础IO详解

目录 一、系统文件IO 1.1 open 1.1.1 open的第一个参数 1.1.2 open的第二个参数 1.1.3 open的第三个参数 1.1.4 open的返回值 1.2 close 1.3 write 1.4 read 二、文件描述符 2.1 进程与文件描述符 2.2 文件描述符的分配规则 三、重定向 3.1 自实现重定向原理 3.…

关于电流互感器电流以及采集电路理解

今天看了下零序电流互感器的作用&#xff0c;跟电路互感器的相似&#xff0c;这个相似是对于二次侧的电路检测功能相似&#xff1b;下面来记录下零序电流互感器以及二次侧采样电路&#xff08;1&#xff09;零序电流互感器&#xff0c;主要用于漏电检测从图中我们看到从断路器到…

L1、L2正则化的原理及适用场景

1. L1正则化&#xff0c;也称Lasso回归 1.1 含义 权值向量 中各元素的绝对值之和&#xff0c;一般记作 。 1.2 公式表示 添加了L1正则化的损失函数一般可表示为&#xff1a; 1.3 作用 L1正则常被用来解决过拟合问题&#xff1b; L1正则化容易产生稀疏权值矩阵&#x…

RK3568 LVDS G121EAN01.3屏幕及触摸ILI2511 调试

1: 屏幕的规格书2&#xff1a;RK3568中DTS的配置// SPDX-License-Identifier: (GPL-2.0 OR MIT) /** Copyright (c) 2020 Rockchip Electronics Co., Ltd.https://www.cnblogs.com/chenfulin5/p/12918924.htmlhttps://blog.csdn.net/qq_28515331/article/details/90763875?spm…

[架构之路-93]:《软件架构设计:程序员向架构师转型必备》-3-软件架构设计中的视图View

前言&#xff1a;同一个软件系统&#xff0c;从不同的视角View&#xff0c;得到不同的视觉和感受。所有的视角得到的视觉感受综合而成了整个系统的架构。有些视角是用眼睛看&#xff0c;有些视角是耳朵听&#xff0c;有些视角用探测器探。不同的人&#xff0c;视角不同&#xf…

【算法】冒泡排序算法原理及实现

1.什么是冒泡排序 冒泡排序&#xff08;Bubble Sort&#xff09;&#xff0c;它是一种最为基础的交换排序。之所以叫冒泡排序&#xff0c;是因为这一种排序算法的每一个元素可以根据自身的大小&#xff0c;一点点的向着一侧来移动。每一轮都会找到一个最大的数字冒泡到数组数组…

一文探索预训练的奥秘

2022年下半年开始&#xff0c;涌现出一大批大模型的应用&#xff0c;其中比较出圈的当属AI作画与ChatGPT&#xff0c;刷爆了各类社交平台&#xff0c;其让人惊艳的效果&#xff0c;让AI以一个鲜明的姿态**&#xff0c;站到了广大民众面前&#xff0c;让不懂AI的人也能直观地体会…

一刷代码随想录——哈希表

1 理论基础常见的三种哈希结构当我们想使用哈希法来解决问题的时候&#xff0c;我们一般会选择如下三种数据结构。数组set &#xff08;集合&#xff09;map(映射)这里数组就没啥可说的了&#xff0c;我们来看一下set。在C中&#xff0c;set 和 map 分别提供以下三种数据结构&a…

Node.js+Vue.js全栈开发王者荣耀手机端官网和管理后台(三) | 前台页面part

文章目录工具样式概念和SASS样式重置网站色彩和字体定义&#xff08;colors text&#xff09;通用flex布局样式定义常用边距定义&#xff08;margin padding&#xff09;主页框架和顶部菜单首页顶部轮播图片&#xff08;vue swiper&#xff09;使用精灵图片&#xff08;sprite&…

【ThreeJs 初学习】基本API的使用方式

基本API的使用方式 根据官网的文档整理出一份API文档, 地址是&#xff1a;ThreeJs 官网文档&#xff0c;其目的还是为了方便查阅 下列代码源码地址 // 此处表示导入three import * as THREE from three;// 1. 创建一个场景 const scene new THREE.Scene();// 2. 创建一个相机…

文献阅读:Language Models are Unsupervised Multitask Learners

文献阅读&#xff1a;Language Models are Unsupervised Multitask Learners 1. 内容介绍2. 模型介绍3. 实验结果 1. 语言模型2. QA & 常识推断3. 生成任务 4. 总结 & 思考 文献链接&#xff1a;https://cdn.openai.com/better-language-models/language_models_are_u…

python-布隆过滤器

在学习redis过程中提到一个缓存穿透的问题&#xff0c; 书中参考的解决方案之一是使用布隆过滤器&#xff0c; 那么就有必要来了解一下什么是布隆过滤器。在参考了许多博客之后&#xff0c; 写个总结记录一下。 一、布隆过滤器简介 什么是布隆过滤器&#xff1f; 本质上布隆…