[WUSTCTF2020]Cr0ssfun-学习笔记

前置知识

BUUCTF 新年快乐-学习笔记

正文

一、UPX脱壳

查过了,无壳。

二、IDA静态分析

1、main函数反编译,代码审计

IDA 进入后,左侧 Functions Window (函数窗口)可以看到所有函数。找到 main 函数并双击,然后按 F5 键反编译。

代码如下:

c 复制代码
int __fastcall main(int argc, const char **argv, const char **envp)
{
  _BYTE v4[48]; // 存储用户输入的 flag

  // 打印 ASCII 艺术字(忽略)
  puts(" _    _ _   _ _____ _____   _____           ");
  // ...(省略 banner)
  while ( 1 )
  {
    puts("Input the flag");
    __isoc99_scanf("%s", v4);    // 读取用户输入
    if ( (unsigned int)check(v4) == 1 )  // 调用 check() 验证
      break;
    puts("0ops, your flag seems fake.");
    rewind(__bss_start);
  }
  puts("Your flag is correct, go and submit it!");
  return 0;
}

逻辑很简单 :用户输入一个字符串 → 调用 check() 验证 → 正确则输出成功信息,错误则继续循环。

关键问题check() 函数到底检查了什么条件?

2、追踪 check() 函数链

check() 只有一行代码:

c 复制代码
__int64 __fastcall check(__int64 a1)
{
  return iven_is_handsome(a1);  // 调用 iven_is_handsome
}

iven_is_handsome 里面又调用了 iven_is_c0oliven_is_c0ol 调用了 iven_1s_educated...... 实际上,这些函数形成了一条调用链:

复制代码
check()
  → iven_is_handsome()
    → iven_is_c0ol()
      → iven_1s_educated()
        → iven_1s_brave()
          → iven_1s_great()
            → iven_and_grace()
              → finally_fun()

从后往前,逐一反编译每个函数,esc键往前退回,可以得到如下的位置→字符映射表:

finally_fun(最后一环):

c 复制代码
return a1[1] == 99 && a1[25] == 64 && a1[27] == 101;
//   索引1 = 'c'    索引25 = '@'    索引27 = 'e'

可以用随波逐流工具验证一下a1的值:

也可以用 Python 的 chr() 函数转换。

iven_and_grace:

c 复制代码
return a1[4] == 50 && a1[17] == 114 && a1[29] == 102 && a1[24] == 95 && finally_fun(a1);
//   索引4 = '2'    索引17 = 'r'    索引29 = 'f'    索引24 = '_'

iven_1s_great:

c 复制代码
return a1[2] == 116 && a1[9] == 99 && a1[32] == 125 && a1[19] == 118 && a1[5] == 48 && a1[14] == 110 && iven_and_grace(a1);
//   索引2 = 't'    索引9 = 'c'    索引32 = '}'    索引19 = 'v'    索引5 = '0'    索引14 = 'n'

iven_1s_brave:

c 复制代码
return a1[15] == 100 && a1[8] == 123 && a1[18] == 51 && a1[28] == 95 && a1[21] == 114 && iven_1s_great(a1);
//   索引15 = 'd'   索引8 = '{'    索引18 = '3'    索引28 = '_'    索引21 = 'r'

iven_1s_educated:

c 复制代码
return a1[0] == 119 && a1[6] == 50 && a1[22] == 115 && a1[31] == 110 && a1[12] == 95 && iven_1s_brave(a1);
//   索引0 = 'w'    索引6 = '2'    索引22 = 's'    索引31 = 'n'    索引12 = '_'

iven_is_c0ol:

c 复制代码
return a1[7] == 48 && a1[16] == 95 && a1[11] == 112 && a1[23] == 101 && a1[30] == 117 && iven_1s_educated(a1);
//   索引7 = '0'    索引16 = '_'   索引11 = 'p'    索引23 = 'e'    索引30 = 'u'

iven_is_handsome:

c 复制代码
return a1[10] == 112 && a1[13] == 64 && a1[3] == 102 && a1[26] == 114 && a1[20] == 101 && iven_is_c0ol(a1);
//   索引10 = 'p'   索引13 = '@'   索引3 = 'f'    索引26 = 'r'    索引20 = 'e'

每个函数都做同一件事:检查输入字符串的某些位置是否等于特定字符。

三、根据 check() 函数链调用链,编写有效 Flag

用AI 编写脚本:

python 复制代码
flag = [''] * 33

# finally_fun
flag[1] = chr(99)   # 'c'
flag[25] = chr(64)  # '@'
flag[27] = chr(101) # 'e'

# iven_and_grace
flag[4] = chr(50)   # '2'
flag[17] = chr(114) # 'r'
flag[29] = chr(102) # 'f'
flag[24] = chr(95)  # '_'

# iven_1s_great
flag[2] = chr(116)  # 't'
flag[9] = chr(99)   # 'c'
flag[32] = chr(125) # '}'
flag[19] = chr(118) # 'v'
flag[5] = chr(48)   # '0'
flag[14] = chr(110) # 'n'

# iven_1s_brave
flag[15] = chr(100) # 'd'
flag[8] = chr(123)  # '{'
flag[18] = chr(51)  # '3'
flag[28] = chr(95)  # '_'
flag[21] = chr(114) # 'r'

# iven_1s_educated
flag[0] = chr(119)  # 'w'
flag[6] = chr(50)   # '2'
flag[22] = chr(115) # 's'
flag[31] = chr(110) # 'n'
flag[12] = chr(95)  # '_'

# iven_is_c0ol
flag[7] = chr(48)   # '0'
flag[16] = chr(95)  # '_'
flag[11] = chr(112) # 'p'
flag[23] = chr(101) # 'e'
flag[30] = chr(117) # 'u'

# iven_is_handsome
flag[10] = chr(112) # 'p'
flag[13] = chr(64)  # '@'
flag[3] = chr(102)  # 'f'
flag[26] = chr(114) # 'r'
flag[20] = chr(101) # 'e'

print(''.join(flag))
相关推荐
蓝天下的守望者8 分钟前
ARM SOC architecture学习文档整理
arm开发·学习
志尊宝16 分钟前
Vue3 零基础每日笔记(004):模板语法初识——插值表达式、v-bind、v-on 一次学会
javascript·vue.js·笔记
SatanII1 小时前
OpenStack核心组件详解|Keystone+Glance+Nova+Cinder原理与实操笔记
网络·笔记·openstack
叶子野格1 小时前
《Verilog学习:前置知识》
学习·fpga开发
wuyk5551 小时前
从零吃透 MQTT 通信|第 6 章 MQTT 主题、过滤器、通配符、订阅管理、拒收机制详解与代码实现
c语言·stm32·学习
点心的游戏开发世界10 小时前
GDScript 入门笔记(十一):Lambda 与匿名函数
开发语言·笔记·游戏引擎·godot
摇滚侠10 小时前
《SpringBoot 3:入门与应用实战》第 12 章 JDBC 与事务 使用 JdbcTemplate 阅读笔记 32
spring boot·笔记·后端
sunshine22 girl11 小时前
Java学习一 环境配置2 安装和基本使用Idea
java·学习·intellij-idea
鱼子星_12 小时前
【C++】继承和多态(上)
c++·笔记
Kobebryant-Manba12 小时前
学习Bert微调
人工智能·学习·bert