[攻防世界]re1 超详细题解(逆向CTF)

深入浅出,知无不答,言无不尽,力求详尽


老样子查壳

无壳, 可以直接IDA, 这还是windows控制台程序, 也可以od。

废话不多说, 直接F5

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // eax
  __m128i v5; // [esp+0h] [ebp-44h] BYREF
  __int64 v6; // [esp+10h] [ebp-34h]
  int v7; // [esp+18h] [ebp-2Ch]
  __int16 v8; // [esp+1Ch] [ebp-28h]
  char v9[32]; // [esp+20h] [ebp-24h] BYREF

  v5 = _mm_loadu_si128((const __m128i *)&xmmword_413E34);
  v7 = 0;
  v6 = 0x7D465443545544i64;
  v8 = 0;
  printf("欢迎来到DUTCTF呦\n");
  printf("这是一道很可爱很简单的逆向题呦\n");
  printf("输入flag吧:");
  scanf("%s", v9);
  v3 = strcmp(v5.m128i_i8, v9);
  if ( v3 )
    v3 = v3 < 0 ? -1 : 1;
  if ( v3 )
    printf(aFlag_0);
  else
    printf(aFlagGet);
  system("pause");
  return 0;
}

这段代码里有挺多SSE2中的指令集, __m128i类型变量, _mm_loadu_si128函数, __xmmword关键字...等等


1、开头的初始化, 第一行不再赘述了, 详细可以看过往两篇文章:

[攻防世界]Hello,CTF (逆向CTF) 包含 main函数中的参数 二级指针envp 说明

[攻防世界]Open-source(逆向Hack-you) 包含 main函数中的两个参数argc和argv 说明

3-8行初始化变量类型, 有两个例外要讲一下, 第4行的 __m128i 这个数据类型是个啥玩意, 它比较特别, 是一个联合体(union), 可以用不同的方式解释相同的128位数据, 既可以是16个8位整数、8个16位整数、也可以是4个32位整数或2个64位整数, 把它当成一个非常灵活的整数型变量就可以了。


2、一部分赋值解析

  v5 = _mm_loadu_si128((const __m128i *)&xmmword_413E34);
  v7 = 0;
  v6 = 0x7D465443545544i64;
  v8 = 0;

这个_mm_loadu_si128函数是直接加载128位值(si128表示signed 128 big interger), 无需16字节对齐, 返回寄存器中的值, 函数内参数const __m128i * 代表创建了一个常量指针, 指向xmmword_413E34。

还有v6赋值的16进制(这个大家应该看得懂吧), 后缀i64则是把占用的内存空间扩展到了64位。


3、主体部分

  printf("欢迎来到DUTCTF呦\n");
  printf("这是一道很可爱很简单的逆向题呦\n");
  printf("输入flag吧:");
  scanf("%s", v9);
  v3 = strcmp(v5.m128i_i8, v9);
  if ( v3 )
    v3 = v3 < 0 ? -1 : 1;
  if ( v3 )
    printf(aFlag_0);
  else
    printf(aFlagGet);
  system("pause");

前三行输出一些文字, scanf函数把我们输入的数据传给v9。

strcmp函数比较v5和v9, v5后缀的.m128i_i8 是取出v5的8位整数元素的意思, 并赋值给v3, strcmp函数的输出只有三种可能, 等于0、小于或者大于0, 在if判断中只要不是0值(布尔类型), 都是1值, 会执行下面的语句。


进入判断

如果v3的值不是0就执行下面的语句:

       v3 = v3 < 0 ? -1 : 1;

(注意加粗)这里用了一个三元运算符 "?", 这玩意初见很难理解。

"?" 的前面是条件, 后面一个条件为真执行的, 一个为假执行的, 我简单表述一下:

条件 ? (条件True时执行) : (条件False时执行)

回到题目, 这里v3小于0, 那么v3就会赋值成-1, 反之则赋值为1


第二个判断

v3不是0

输出aFlag_0

错了

v3是0

获得flag, 对了


我们总结一下条件:

v3的值决定了我们能不能获得flag, 而v3的值取决于v5和v9, v9是我们输入的值, v5是程序自带的, 所以我们溯源v5, v5指向xmmword_413E34, 双击跳转

发现两串十六进制数据, IDA中选中这条数据右键就可以将其转换成各种编码。

我们会发现这串东西好像反过来了一样, 确实, 你想的没错。

为什么呢?

这个原理在王克义教授所著的《微机原理》第2版的194页, 第二点提到了: (里面还提了一嘴为啥要叫大端和小端)

其实在《汇编语言》王爽写的那本里也提到了, 不过我很久没看了, 具体在哪记不清了...

好了, 今天就这样结束吧, 累了😩

把flag倒过来就行了:

flag:

DUTCTF{We1c0met0DUTCTF}

### 关于BUUCTF RE1类型题目 #### BUUCTF平台简介 BUUCTF是一个专注于网络安全竞赛训练的在线平台,提供多种类型的挑战题供参赛者练习。其中RE1Reverse Engineering Level 1)类别主要涉及逆向工程的基础知识和技术应用。 #### 题目实例:Simple_RE1 在BUUCTF平台上存在一道名为`Simple_RE1`的经典入门级逆向题目[^2]。该题目的目标是从给定的可执行文件中提取出隐藏的信息或者理解其内部逻辑流程来获取flag。 #### 解题思路概述 对于这类基础性的逆向题目来说,通常会考察以下几个方面: - **工具使用**:掌握基本调试器(如IDA Pro, Ghidra)以及十六进制编辑器(HxD等)的操作方法。 - **程序分析**:能够阅读并解析编译后的机器码或字节码,识别常见的算法结构和字符串处理方式。 - **漏洞挖掘**:了解常见软件缺陷模式及其利用手法,在此案例中可能涉及到简单的缓冲区溢出等问题。 具体到这道`Simple_RE1`题目上,解法可以概括如下: 1. 使用反汇编工具加载二进制文件; 2. 寻找main函数入口点,并跟踪调用链直至发现关键操作区域; 3. 对比输入参数与预期输出之间的差异,推测加密/编码机制; 4. 尝试修改特定条件分支语句以绕过验证过程从而获得正确答案; ```python from pwn import * context.arch = 'amd64' elf = ELF('./simple_re') p = elf.process() payload = b'A' * offset + pack(flag_address) p.sendline(payload) print(p.recvall().decode()) ``` 上述代码片段展示了如何通过构造特殊的数据包发送至目标进程实现对内存地址的有效控制,进而读取或篡改指定位置的内容。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值