IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> xctf攻防世界 REVERSE 高手进阶区 流浪者 -> 正文阅读

[C++知识库]xctf攻防世界 REVERSE 高手进阶区 流浪者

0x01. 进入环境,下载附件

题目给出了一个exe注册机文件,我们双击打开,如图:
在这里插入图片描述
输入的crack不对,则会提示错了。推测可能让去寻找正确的口令即可。

0x02. 问题分析

使用IDA打开文件进行分析,如图:
在这里插入图片描述
在左侧找到main函数,F5反编译,如图,发现没有任何思路,没有其他有价值的信息:
在这里插入图片描述
我们将代码转成字符串(shift+f12),如图:
在这里插入图片描述
双击请输入pass,跳转到对应的位置,如图:
在这里插入图片描述
涉及到的函数段为:sub_401890,双击到对应的函数,如图:在这里插入图片描述
其次反编译查看反编译代码:

int __thiscall sub_401890(CWnd *this)
{
  struct CString *v1; // ST08_4
  CWnd *v2; // eax
  int v3; // eax
  int v5[26]; // [esp+4Ch] [ebp-74h]
  int i; // [esp+B4h] [ebp-Ch]
  char *Str; // [esp+B8h] [ebp-8h]
  CWnd *v8; // [esp+BCh] [ebp-4h]

  v8 = this;
  v1 = (CWnd *)((char *)this + 100);
  v2 = CWnd::GetDlgItem(this, 1002);   // 返回子窗口句柄
  CWnd::GetWindowTextA(v2, v1); // 将指定窗口的标题条文本拷贝到一个缓存区内
  v3 = sub_401A30((char *)v8 + 100); // 获取用户输入的长度
  Str = CString::GetBuffer((CWnd *)((char *)v8 + 100), v3);  // 将v3的内容用缓冲区方式保存,并用Str保存
  if ( !strlen(Str) )  // 长度为空提示请输入pass
    return CWnd::MessageBoxA(v8, "请输入pass!", 0, 0);
  for ( i = 0; Str[i]; ++i )
  {
    if ( Str[i] > '9' || Str[i] < '0' )
    {
      if ( Str[i] > 'z' || Str[i] < 'a' )
      {
        if ( Str[i] > 'Z' || Str[i] < 'A' )
          sub_4017B0();
        else
          v5[i] = Str[i] - 29;
      }
      else
      {
        v5[i] = Str[i] - 87;
      }
    }
    else
    {
      v5[i] = Str[i] - 48;
    }
  }
  return sub_4017F0((int)v5); 
}

基本的逻辑就是将输入的数据,经过一串的if处理,对每个字符进行变换,得到变换后的v5,送入函数sub_4017F0中进行后续操作。双击sub_4017F0函数查看内容,如下:

int __cdecl sub_4017F0(int a1)
{
  int result; // eax
  char Str1[28]; // [esp+D8h] [ebp-24h]
  int v3; // [esp+F4h] [ebp-8h]
  int v4; // [esp+F8h] [ebp-4h]

  v4 = 0;
  v3 = 0;
  while ( *(_DWORD *)(a1 + 4 * v4) < 62 && *(_DWORD *)(a1 + 4 * v4) >= 0 )
  {
    Str1[v4] = aAbcdefghiabcde[*(_DWORD *)(a1 + 4 * v4)];
    ++v4;
  }
  Str1[v4] = 0;
  if ( !strcmp(Str1, "KanXueCTF2019JustForhappy") )
    result = sub_401770();
  else
    result = sub_4017B0();
  return result;
}

a1为v5 数组的首地址。*(_DWORD *)(a1 + 4 * v4) 相当于是a1[v4]。因为这里是DWORD类型,也就是4个字节,每次循环+4,相当于是取数组的下一个元素。上述代码可以知道,要弹出pass,需要变换后的Str1和KanXueCTF2019JustForhappy相等。双击aAbcdefghiabcde可以查看到变量内容。
因此我们可以先求a1数组的内容:

src = "abcdefghiABCDEFGHIJKLMNjklmn0123456789opqrstuvwxyzOPQRSTUVWXYZ"
dst = "KanXueCTF2019JustForhappy"
data = []

for i in dst:
    data.append(src.index(i))

print(data)

输出后的data为:[19, 0, 27, 59, 44, 4, 11, 55, 14, 30, 28, 29, 37, 18, 44, 42, 43, 14, 38, 41, 7, 0, 39, 39, 48]

接着逆向处理if函数,还原值后再进行if判断:

flag = ''

for i in data:
    tmp1, tmp2, tmp3 = i + 29, i + 87, i + 48
    if 65 <= tmp1 <= 90:
        flag += chr(tmp1)
    elif 97 <= tmp2 <= 122:
        flag += chr(tmp2)
    elif 48 <= tmp3 <= 57:
        flag += chr(tmp3)
print("flag{{{}}}".format(flag))

因此,最终答案为:flag{j0rXI4bTeustBiIGHeCF70DDM}

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-07 22:27:40  更:2022-04-07 22:28:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 0:23:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码