[BUUOJ] [RE] [ACTF新生赛2020] rome1

news2024/12/23 9:08:59

IDA

好久没写博客了,最近在刷re,这道题是我觉得十分有意义的一道题。故AC后总结分享给大家。不足之处请指正

分析

直接导入IDA shift +F12
请添加图片描述

双击后按 ctrl + x跳转到被调用的函数中,按F5反编译,源代码如下

int func()
{
  int result; // eax
  int v1[4]; // [esp+14h] [ebp-44h]
  unsigned __int8 v2; // [esp+24h] [ebp-34h] BYREF
  unsigned __int8 v3; // [esp+25h] [ebp-33h]
  unsigned __int8 v4; // [esp+26h] [ebp-32h]
  unsigned __int8 v5; // [esp+27h] [ebp-31h]
  unsigned __int8 v6; // [esp+28h] [ebp-30h]
  int v7; // [esp+29h] [ebp-2Fh]
  int v8; // [esp+2Dh] [ebp-2Bh]
  int v9; // [esp+31h] [ebp-27h]
  int v10; // [esp+35h] [ebp-23h]
  unsigned __int8 v11; // [esp+39h] [ebp-1Fh]
  char v12[29]; // [esp+3Bh] [ebp-1Dh] BYREF

  strcpy(v12, "Qsw3sj_lz4_Ujw@l");
  printf("Please input:");
  scanf("%s", &v2);
  result = v2;
  if ( v2 == 65 )
  {
    result = v3;
    if ( v3 == 67 )
    {
      result = v4;
      if ( v4 == 84 )
      {
        result = v5;
        if ( v5 == 70 )
        {
          result = v6;
          if ( v6 == 123 )
          {
            result = v11;
            if ( v11 == 125 )
            {
              v1[0] = v7;
              v1[1] = v8;
              v1[2] = v9;
              v1[3] = v10;
              *(_DWORD *)&v12[17] = 0;
              while ( *(int *)&v12[17] <= 15 )
              {
                if ( *((char *)v1 + *(_DWORD *)&v12[17]) > 64 && *((char *)v1 + *(_DWORD *)&v12[17]) <= 90 )
                  *((_BYTE *)v1 + *(_DWORD *)&v12[17]) = (*((char *)v1 + *(_DWORD *)&v12[17]) - 51) % 26 + 65;
                if ( *((char *)v1 + *(_DWORD *)&v12[17]) > 96 && *((char *)v1 + *(_DWORD *)&v12[17]) <= 122 )
                  *((_BYTE *)v1 + *(_DWORD *)&v12[17]) = (*((char *)v1 + *(_DWORD *)&v12[17]) - 79) % 26 + 97;
                ++*(_DWORD *)&v12[17];
              }
              *(_DWORD *)&v12[17] = 0;
              while ( *(int *)&v12[17] <= 15 )
              {
                result = (unsigned __int8)v12[*(_DWORD *)&v12[17]];
                if ( *((_BYTE *)v1 + *(_DWORD *)&v12[17]) != (_BYTE)result )
                  return result;
                ++*(_DWORD *)&v12[17];
              }
              result = printf("You are correct!");
            }
          }
        }
      }
    }
  }
  return result;
}

看着眼花,慢慢来讲
int8的v2-v6本质上就是字符,因为int8就是一个字节和char长度相等,
int32才是我们常说的四个字节
v2-v6和v11其实就是 ACTF{},中间的字符才是关键,也就是v7 v8 v9 v10这四个int32的变量,也就是4*4=16 个ascii字符
v7-v10赋值给了v1[0-3],后面其实就是v1和v12之间的比较,但是这个*((char *) 等指针看的眼花缭乱,下面慢慢理。

记住以下几点:
*((char *) 一个字节
*((_BYTE *) 一个字节
*(_DWORD *) 四个字节 相当于int32

我们分别看看 v1 和 v12的内存视图
v1 : 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00
v12 : Qsw3sj_lz4_Ujw@l 0 | 0000 0000 0000
先看v1因为 int v1[4],所以v1有4个int32,分开来看,一个00代表了1字节数据(4个字节正好 1 int)
v1数组可以存4个int32位的整型,也可以看作4*4=16 个ascii字符。把如上反编译代码简化以下得到

int func()
{
  int result; // eax
  int v1[4]; // [esp+14h] [ebp-44h]
  unsigned __int8 v2; // [esp+24h] [ebp-34h] BYREF
  unsigned __int8 v3; // [esp+25h] [ebp-33h]
  unsigned __int8 v4; // [esp+26h] [ebp-32h]
  unsigned __int8 v5; // [esp+27h] [ebp-31h]
  unsigned __int8 v6; // [esp+28h] [ebp-30h]
  int v7; // [esp+29h] [ebp-2Fh]
  int v8; // [esp+2Dh] [ebp-2Bh]
  int v9; // [esp+31h] [ebp-27h]
  int v10; // [esp+35h] [ebp-23h]
  unsigned __int8 v11; // [esp+39h] [ebp-1Fh]
  char v12[29]; // [esp+3Bh] [ebp-1Dh] BYREF

  strcpy(v12, "Qsw3sj_lz4_Ujw@l");
  printf("Please input:");
  scanf("%s", &v2);
  result = v2;
  if ( v2 == 65 )
  {
    result = v3;
    if ( v3 == 67 )
    {
      result = v4;
      if ( v4 == 84 )
      {
        result = v5;
        if ( v5 == 70 )
        {
          result = v6;
          if ( v6 == 123 )
          {
            result = v11;
            if ( v11 == 125 )
            {
              v1[0] = v7;
              v1[1] = v8;
              v1[2] = v9;
              v1[3] = v10;
              point = 0; // \*(&v12+17) int point
              //char v12[29] = "Qsw3sj_lz4_Ujw@l";
              while ( point <= 15 )
              {
                if ( *((char *)v1 + point) > 65 && *((char *)v1 + point) <= 90 )
                  *((_BYTE *)v1 + point) = (*((char *)v1 + point) - 51) % 26 + 65;
                /*
                  如果为大写字母
                  a = (a - 51) % 26 + 65
                */

                if ( *((char *)v1 + point) > 96 && *((char *)v1 + point) <= 122 )
                  *((_BYTE *)v1 + point) = (*((char *)v1 + point) - 79) % 26 + 97;
                /*
                  如果为小写字母
                  a = (a - 79) % 26 + 97
                */
                ++point;
              }
              point = 0;
              while ( point <= 15 )
              {
                result = (unsigned __int8)v12[point];
                if ( *((_BYTE *)v1 + point) != (_BYTE)result )
                  return result;
                ++point;
              }
              result = printf("You are correct!");
}

说明一:题目把v12后面没有用到的空间作为一个int整型存数字(虽然不够4个字节?这部分不是很懂,但不影响做题)即上面加粗的部分。

说明二:v1明明是一个int类型的数组,但是题目却使用了char类型指针,说明其实v1数字存放的是ascii字符。我们就应该把v1的内存分开来看,所以我在上面分开了。正好v12字符串的长度和v1的长度相等,v1其实就是我们要找的flag{}中间的那16个未知字符。每一个00 对应了一个字母。

说明三:*(_DWORD *)&v12[17]可以把他看成一个int整型的point,就是计算地址用的,就像数组中a[114]或者*a+114 这个形式

说明四:_BYTE就是char,无需在意。为什么留着这个没有简化?是因为让读者知道这时的v1不能简单地看作int类型数组。

说明五:point 从0到15长度为16,正好与v12字符串长度相等,也和我们flag长度相等。

解题

由简化后的代码可知:输入的字符经过了变换 -> 大小写字母有一个位移变换,其他字符不变。
那么我们把密码本反向构造好flag就直接出来了。

#[ACTF新生赛2020]rome1
# Author me 2023.6.6 22:03
dic = {}
'''
分别构造大小写密码本
'''
for key in range(65,90+1):
    value = ( key - 51) % 26 + 65
    dic[chr(value)] = chr(key)

for key in range(97,122+1):
    value = ( key - 79) % 26 + 97
    dic[chr(value)] = chr(key)

s = 'Qsw3sj_lz4_Ujw@l'
ans = ""
for i in s:
    if i in dic: # 是字母直接转换
        ans += dic[i]
    else:        # 不是字母的照旧
        ans += i
print(ans) # Cae3ar_th4_Gre@t
# 加上ACTF{}就得到 You are correct!

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

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

相关文章

数据结构-线性表-链表

目录 线性表的链式存储结构&#xff1a;一、单向链表的ADT定义二、链表的优缺点 线性表的链式存储结构&#xff1a; 为了表示数据元素ai和其后继元素ai1之间的逻辑关系&#xff0c;对ai来说需存储其本身信息和后继元素的信息&#xff08;存储位置&#xff09;。这两部分组成ai…

Android系统(AOSP)--编译指令篇

目录 一、编译Android系统 二、普通编译指令 三、快速编译指令 四、新建lunch项和编译类型说明 五、Android编译系统的整体架构 六、编译后的输出目录和生成文件 七、Android常用编译命令总结 一、编译Android系统 1.Android系统全编译(Android5.1以后mtk都是这种方式…

裸辞3个月没工作,害怕面试,害怕HR问我的问题,怎么办?

其实裸辞最大的伤害就是很容易导致自己的不自信。 现在可能就是你的低谷期&#xff0c;你需要做的是什么呢&#xff0c;丰富自己。 你要相信&#xff0c;你只是太久没有面试过&#xff0c;生疏了而已。 今天小月带你回到面试场&#xff0c;找回面试最纯正的感觉&#xff01; 面…

火龙果MM32F3273G8P开发板MindSDK开发教程1 - 点亮LED

火龙果MM32F3273G8P-MindSDK开发教程1-点亮LED 1、登录官网下载对应的MindSDK固件 https://mindsdk.mindmotion.com.cn/&#xff0c;然后注册下载mm32F3270的固件即可。 下载完的文件为 plus-f3270_mdk.zip 解压后的文件路径如图&#xff1a; 2、新建LED工程 将下载的plu…

基于张量补全的交通数据复原文献汇总(最新)

由于传感器故障和通信故障等因素导致的交通数据缺失严重制约了ITS的发展与应用。如何准确、高效地恢复缺失数据已成为ITS的一个关键问题。近年来&#xff0c;LRTC&#xff08;低秩张量补全&#xff09;的方法已被广泛应用于交通数据补全。本文将介绍几篇最新的关于交通数据补全…

python3 爬虫相关学习7:初步摸索使用 BeautifulSoup

1 一个爬图片pic的代码的例子 下面这段是爬一些图片pic的代码学写了一段bs的代码&#xff0c;但是马上报错 #E:\work\FangCloudV2\personal_space\2learn\python3\py0001.txtimport requests from bs4 import BeautifulSoupurl"https://movie.douban.com/celebrity/10115…

搭建个人博客

个人网站用处有很多&#xff0c;可以写博客来记录学习过程中的各种事&#xff0c;不管是新知识还是踩坑记录&#xff0c;写完就丢在网站上&#xff0c;方便日后复习&#xff0c;也可以共享给他人&#xff0c;让其他人避免踩雷。 当然也不仅限于技术性的文章&#xff0c;生活中有…

隐马尔可夫模型在数学建模中的应用及MATLAB实现

2023年9月数学建模国赛期间提供ABCDE题思路加Matlab代码,专栏链接(赛前一个月恢复源码199,欢迎大家订阅):http://t.csdn.cn/Um9Zd 目录 2023年9月数学建模国赛期间提供ABCDE题思路加Matlab代码,专栏链接(赛前一个月恢复源码199,欢迎大家订阅):http://t.csdn.cn/Um9Zd 隐马尔可…

(二)CSharp-数据类型

一、数据类型 1、C#程序是一组类型声明 C 程序是一组函数和数据类型C 程序是一组函数和类C# 程序是一组类型声明 2、类型是一种模板 类型由下面的元素定义&#xff1a; 名称用于保存数据成员的数据结构一些行为及约束条件 3、实例化类型 从某个类型模板创建实际的对象&am…

完败!资深码农 VS 新手+AI;阿里云AI黑客松千万奖金池;手把手教你用AI写小说;微软AI入门课 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f916; 阿里云首届AI黑客马拉松&#xff0c;共享 1000 万美元风投资金池 阿里云官方宣布&#xff0c;将以国内最大AI模型社区「Model Scope 魔…

基于双视角图表示算法的双向人职匹配偏好建模推荐系统构建

基于双视角图表示算法的双向人职匹配偏好建模推荐系统构建 文章目录 基于双视角图表示算法的双向人职匹配偏好建模推荐系统构建1. 传统推荐系统模型2. 协同过滤算法3. 基于双视角图表示学习算法的模型构建3.1 数据输入3.2 双视角交互图的构建3.3 混合偏好传播策略3.4 对于双向意…

H5项目怎么打包成APP

文章目录 前言一、新建5APP项目二、删除不需要的文件三、将H5打包的文件拷贝到当前目录下四、配置APP五、发行-云打包六、安装apk总结 前言 开发uni-app的编辑器HBuilderX可以将H5项目打包成APP&#xff0c;相信很多小伙伴还不知道这个功能&#xff0c;下面将介绍下如何将H5打…

linux MMU内存管理单元

本篇文章简要阐述MMU的概念&#xff0c;以及以段地址的转换过程为例&#xff0c;简单说明MMU将虚拟地址转换成物理地址的过程。更多详细内容请查看《ARM-MMU(中文手册).pdf》。 1、MMU概述 在ARM存储系统中&#xff0c;使用MMU实现虚拟地址到实际物理地址的映射。为何要实现这…

人工智能学习07--pytorch21--目标检测:YOLO系列理论合集(YOLOv1~v3)

如果直接看yolov3论文的话&#xff0c;会发现有好多知识点没见过&#xff0c;所以跟着视频从头学一下。 学习up主霹雳吧啦Wz大佬的学习方法&#xff1a; 想学某个网络的代码时&#xff1a;到网上搜这个网络的讲解 → 对这个网络大概有了印象 → 读论文原文&#xff08; 很多细…

Django实现接口自动化平台(五)httprunner(4.x)介绍【持续更新中】

上一章&#xff1a; Django实现接口自动化平台&#xff08;四&#xff09;解决跨域问题【持续更新中】_做测试的喵酱的博客-CSDN博客 下一章&#xff1a; 一、httpruner介绍 1.1 背景&#xff1a; 之所以学习httpruner的用法&#xff0c;是要把httpruner嵌入我们的自动化平…

全网最全、最新MyBatis框架核心知识

MyBatis框架 1. 软件开发常用结构 MyBatis是操作数据库的&#xff0c;相当于是一个增强的JDBC 1.1 三层架构 三层架构包括&#xff1a; 界面层&#xff08;User Interface layer&#xff09;业务逻辑层&#xff08;Business Logic Layer&#xff09;数据访问层&#xff08;Dat…

Window搭建IOS App自动化测试环境

平台搭建&#xff1a;tidevice&#xff08;Windows逆向通信iOS工具&#xff09;WebDriverAgent&#xff08;iOS通信服务&#xff09;facebook-wda&#xff08;iOS测试框架&#xff09; macOSXcode&#xff1a;在手机上安装WebDriverAgent的时候需要用到&#xff0c;必须要Xcod…

HDFS概述及其优缺点

什么是HDFS&#xff1f; HDFS的全称是hadoop distributed file system&#xff0c;即hadoop的分布式文件系统。 见名知意&#xff0c;它就是用来进行文件存储的。毕竟它是大数据的一个组件&#xff0c;用来存储这种海量的数据。 它是基于03年10月份&#xff0c;谷歌发表的GFS…

Hadoop 怎么委任和解除节点?

前言 本文隶属于专栏《大数据技术体系》&#xff0c;该专栏为笔者原创&#xff0c;引用请注明来源&#xff0c;不足和错误之处请在评论区帮忙指出&#xff0c;谢谢&#xff01; 本专栏目录结构和参考文献请见大数据技术体系 正文 Hadoop 集群的管理员经常需要向集群中添加节点…

Android Studio引用第三方库的方式

title: 大小端详解 date: 2023-06-06 21:01:24 comments: true #是否可评论 toc: true #是否显示文章目录 categories: #分类 - gradle - android studio tags: #标签 - gradle - android studio summary: android stduio 导入第三方库方式 Android Studio引用第三方库的方式 …