【CTF Reverse】XCTF GFSJ1101 Mine- Writeup(反编译+动态调试+Base58编码)

news2024/9/20 12:24:39

Mine-

运气怎么这么差?


原理

Base58

Base58是用于比特币(Bitcoin)中使用的一种独特的编码方式,主要用于产生Bitcoin的钱包地址。

相比Base64,Base58不使用数字"0",字母大写"O",字母大写"I",和字母小写"l",以及"+“和”/"符号。

比特币的Base58字母表:

123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz

工具

  • Base58编码/解码:http://www.atoolbox.net/Tool.php?Id=932
  • Base58在线编码、Base58解码、在线Base58check编码、Base58check解码:http://web.chacuo.net/charsetbase58

解法

一个扫雷游戏,输入坐标翻开,坐标用空格隔开。

没走两步就爆了。

拉进 DIE 分析。无壳。

导入 IDA。

按 F5 反编译。

int __fastcall main(int argc, const char **argv, const char **envp)
{
  unsigned int v3; // eax
  std::ostream *v4; // rax
  std::ostream *v5; // rax
  _BYTE *v6; // rax
  std::istream *v7; // rax
  std::ostream *v8; // rax
  std::ostream *v9; // rax
  std::ostream *v10; // rax
  std::ostream *v11; // rax
  int v13; // [rsp+28h] [rbp-58h]
  int v14; // [rsp+2Ch] [rbp-54h]
  int v15; // [rsp+30h] [rbp-50h]
  unsigned int v16; // [rsp+34h] [rbp-4Ch]
  unsigned int v17; // [rsp+38h] [rbp-48h]
  int v18; // [rsp+3Ch] [rbp-44h]
  int v19; // [rsp+40h] [rbp-40h]
  int i3; // [rsp+44h] [rbp-3Ch]
  int i2; // [rsp+48h] [rbp-38h]
  int i1; // [rsp+4Ch] [rbp-34h]
  int nn; // [rsp+50h] [rbp-30h]
  int i4; // [rsp+54h] [rbp-2Ch]
  int mm; // [rsp+58h] [rbp-28h]
  int kk; // [rsp+5Ch] [rbp-24h]
  int jj; // [rsp+60h] [rbp-20h]
  int ii; // [rsp+64h] [rbp-1Ch]
  int n; // [rsp+68h] [rbp-18h]
  int m; // [rsp+6Ch] [rbp-14h]
  int k; // [rsp+70h] [rbp-10h]
  int v32; // [rsp+74h] [rbp-Ch]
  int j; // [rsp+78h] [rbp-8h]
  int i; // [rsp+7Ch] [rbp-4h]

  _main();
  memset(grid, 0, 0x190ui64);
  memset(randMark, 0, sizeof(randMark));
  memset(vis, 0, sizeof(vis));
  for ( i = 0; i <= 9; ++i )
  {
    for ( j = 0; j <= 9; ++j )
      showUs[100 * i + j] = 42;
  }
  v3 = time(0i64);
  srand(v3);
  v32 = 0;
  do
  {
    v19 = rand() % 10;
    v18 = rand() % 10;
    if ( randMark[100 * v19 + v18] != 1 )
    {
      randMark[100 * v19 + v18] = 1;
      ++v32;
    }
  }
  while ( v32 != mine_sum );
  res = 0;
  for ( k = 0; k <= 9; ++k )
  {
    for ( m = 0; m <= 9; ++m )
    {
      if ( randMark[100 * k + m] )
        grid[10 * k + m] = -1;
    }
  }
  for ( n = 0; n <= 9; ++n )
  {
    for ( ii = 0; ii <= 9; ++ii )
    {
      if ( grid[10 * n + ii] != -1 )
      {
        for ( jj = 0; jj <= 7; ++jj )
        {
          v17 = *((_DWORD *)&dir + 2 * jj) + n;
          v16 = dword_475044[2 * jj] + ii;
          if ( v17 <= 9 && v16 <= 9 && grid[10 * v17 + v16] == -1 )
            ++grid[10 * n + ii];
        }
      }
    }
  }
  for ( kk = 0; kk <= 9; ++kk )
  {
    for ( mm = 0; mm <= 9; ++mm )
    {
      v4 = (std::ostream *)std::operator<<<std::char_traits<char>>(
                             refptr__ZSt4cout,
                             (unsigned int)showUs[100 * kk + mm]);
      std::operator<<<std::char_traits<char>>(v4, " ");
    }
    refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_(refptr__ZSt4cout);
  }
LABEL_40:
  v5 = (std::ostream *)std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, asc_48B002);
  refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_(v5);
  while ( 100 - mine_sum != res )
  {
    v7 = (std::istream *)std::istream::operator>>(refptr__ZSt3cin);
    std::istream::operator>>(v7);
    if ( grid[10 * v14 + v13] == -1 )
    {
      v8 = (std::ostream *)std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, asc_48B01D);
      refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_(v8);
      goto LABEL_67;
    }
    if ( !vis[100 * v14 + v13] && grid[10 * v14 + v13] > 0 )
    {
      ++res;
      vis[100 * v14 + v13] = 1;
      showUs[100 * v14 + v13] = LOBYTE(grid[10 * v14 + v13]) + 48;
      system("cls");
      for ( nn = 0; nn <= 9; ++nn )
      {
        for ( i1 = 0; i1 <= 9; ++i1 )
        {
          v9 = (std::ostream *)std::operator<<<std::char_traits<char>>(
                                 refptr__ZSt4cout,
                                 (unsigned int)showUs[100 * nn + i1]);
          std::operator<<<std::char_traits<char>>(v9, " ");
        }
        refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_(refptr__ZSt4cout);
      }
      goto LABEL_40;
    }
    if ( !vis[100 * v14 + v13] && !grid[10 * v14 + v13] )
    {
      bfs(v14, v13);
      system("cls");
      for ( i2 = 0; i2 <= 9; ++i2 )
      {
        for ( i3 = 0; i3 <= 9; ++i3 )
        {
          v10 = (std::ostream *)std::operator<<<std::char_traits<char>>(
                                  refptr__ZSt4cout,
                                  (unsigned int)showUs[100 * i2 + i3]);
          std::operator<<<std::char_traits<char>>(v10, " ");
        }
        refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_(refptr__ZSt4cout);
      }
      v11 = (std::ostream *)std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, asc_48B002);
      refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_(v11);
    }
  }
  v15 = std::string::length((std::string *)&ans);
  for ( i4 = 0; i4 < v15; ++i4 )
  {
    v6 = (_BYTE *)std::string::operator[](&ans, i4);
    std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, (unsigned int)(char)((v15 - i4) ^ *v6));
  }
  refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_(refptr__ZSt4cout);
LABEL_67:
  system("pause");
  return 0;
}

没看到有字符串常量。

按 Shift + F12 打开 Strings 窗口,发现中文字符串。

追踪其位置。发现这个字符数组的标识符为 asc_48B002。

回到 main 函数,搜索 asc_48B002 找到这行。推测这段是 C++ 的 cout。

      v11 = (std::ostream *)std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, asc_48B002);

这段找到变量 ans,可能是 flag。

  v15 = std::string::length((std::string *)&ans);
  for ( i4 = 0; i4 < v15; ++i4 )
  {
    v6 = (_BYTE *)std::string::operator[](&ans, i4);
    std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, (unsigned int)(char)((v15 - i4) ^ *v6));
  }
  refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_(refptr__ZSt4cout);

但是 ans 里面没有内容。

分析反编译伪代码可知,ans 在 while 循环结束后输出。找到 while 循环位置为 401ED2。

用 x64dbg 打开,Ctrl + G 跳转到 0000000000401ED2。

用 NOP 填充,跳出 while 循环。

运行程序,直接输出一段编码,应该是 ans。

7ii3VecVgof3r6ssiP2g7E3HqwqhM

提交 flag,错误。

可能是 base64 编码,用 base64 解码器解码,解码失败。

用 base58 解码器解码,解码失败。

看了大佬的 Writeup。因为有些解码器 base58 字母表的大写字母在小写字母前面:

123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz

另一些解码器 base58 字母表的大写字母在小写字母后面:

123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ

ans 采用的是大写字母在前面的字母表。换了另一个解码器,解码成功,得到 flag。

Flag

flag{h4pp4-M1n3-G4m3}

PS

我的理解是,标题可能一语双关。根据有道词典的解释:

mine

pron.
我的;<英,非正式>我的家
n.
矿,矿井;地雷,水雷;宝库,源泉;<>炸药坑道
v.
采(煤等矿物);布雷,用雷炸毁(车辆);寻找(某事物中)蕴含的价值;在(地下)挖洞(或坑道);挖掘(数据);挖矿(获取加密货币的勘探方式)

mine 有地雷的意思,指扫雷游戏,又有挖矿的意思,暗示了比特币钱包地址所使用的 base58 编码。

参考资料

  • https://dict.youdao.com/result?word=mine&lang=en

声明

本博客上发布的所有关于网络攻防技术的文章,仅用于教育和研究目的。所有涉及到的实验操作都在虚拟机或者专门设计的靶机上进行,并且严格遵守了相关法律法规

博主坚决反对任何形式的非法黑客行为,包括但不限于未经授权的访问、攻击或破坏他人的计算机系统。博主强烈建议每位读者在学习网络攻防技术时,必须遵守法律法规不得用于任何非法目的。对于因使用这些技术而导致的任何后果,博主不承担任何责任

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

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

相关文章

Linux 文件权限详解与管理

文章目录 前言一、文件权限概述1. 权限表示格式2. 权限组合值 二、查看文件权限三、修改文件所有者与所属组1. 使用 chown 修改文件所有者2. 使用 chgrp 修改文件所属组3. 添加所有者 四、修改文件权限1. 符号方式2. 八进制方式 总结 前言 在 Linux 系统中&#xff0c;文件权限…

React + Vite 多环境配置

1.根目录创建文件&#xff1a; .env.dev //测试环境 .env.development //本地环境 .env.production //正式环境 .env.uat //预发布环境 注&#xff1a;变量名必须使用 VITE_API 开头 2.package.json 配置&#xff1a; --mode 设置读取制定 .env文件 &#xff0c;默认读取.en…

Windows10安装cuda11.3.0+cudnn8.5.0,以及创建conda虚拟环境(pytorch)

1、检查电脑驱动版本为561.09&#xff0c;选择cuda版本&#xff0c;下图可知cuda版本<12.6。 nvidia-smi #查看驱动版本&#xff0c;以及最大可以安装的cuda版本 2、Anaconda3-2024.06-1-Windows-x86_64.exe下载&#xff1a; 官网&#xff1a;https://www.baidu.com/link?…

研究生存指南:必备Zotero插件,让你的文献管理更轻松

在读研阶段&#xff0c;我经常面临大量文献阅读和项目研究的任务。忽略文献整理会导致后续使用时非常不便&#xff0c;查找困难且混乱。导师向我们推荐了 Zotero&#xff0c;经过亲身试用&#xff0c;我发现它非常好用&#xff01;zotero有非常多的插件&#xff0c;能够一个就满…

了解Node开发基础知识

目录 定义架构应用场景安装版本工具代码执行REPL传递参数输出全局对象 定义 Node.js 是一个基于 V8 JavaScript 引擎构建的运行时环境&#xff0c;允许你在服务器端运行 JavaScript 代码。Node.js 允许开发者使用 JavaScript 编写服务器端代码&#xff0c;实现前后端代码的统一…

安全帽识别算法、安全帽智能识别、不戴安全帽检测算法

不戴安全帽检测算法是一种基于人工智能技术&#xff0c;用于实时监测和提醒工作人员是否正确佩戴安全帽的系统。以下是对不戴安全帽检测算法的详细介绍&#xff1a; 1. 技术原理 - 数据采集与预处理&#xff1a;通过安装在施工现场或工厂车间等场所的摄像头收集图像数据&#…

HTML 盒子标签、字符实体及废弃标签介绍

目录 HTML盒子标签 div标签 span标签 字符实体 HTML注释 HTML 废弃标签介绍 关注作者微信公众号&#xff0c;开启探索更多 HTML 知识的精彩之旅。在这里&#xff0c;你将收获丰富的 HTML 专业内容&#xff0c;深入了解这一网页开发语言的奥秘&#xff0c;不断拓展你的知识…

c语言面试字符串复制

1&#xff0c;下面这个函数的打印是什么&#xff1a; #include<stdio.h> #include<string.h>int main() {char str0[5], str1[] "welcome";strcpy(str0, str1);printf("str0:%s\r\n",str0);printf("str1:%s\r\n",str1); } larkla…

【Verilog学习日常】—牛客网刷题—Verilog快速入门—VL21

根据状态转移表实现时序电路 描述 某同步时序电路转换表如下&#xff0c;请使用D触发器和必要的逻辑门实现此同步时序电路&#xff0c;用Verilog语言描述。 电路的接口如下图所示。 输入描述&#xff1a; input A , input clk , …

uniapp+renderJS+google map开发安卓版APP非小程序

背景需求 需要在uniapp中接入google地图,研究了一番,都没有找到合适的,现在说一下教程。 效果图 前期工作 这两点缺一不可,否则你啥也看不到。 1、电脑安装L-O-U梯 用于访问G-OO-G-LE的API或者创建google map key。 2、手机安装L-O-U梯 用于显示google地图。我就是手…

SpringCloud从零开始简单搭建 - JDK17

文章目录 SpringCloud Nacos从零开始简单搭建 - JDK17一、创建父项目二、创建子项目三、集成Nacos四、集成nacos配置中心 SpringCloud Nacos从零开始简单搭建 - JDK17 环境要求&#xff1a;JDK17、Spring Boot3、maven。 那么&#xff0c;如何从零开始搭建一个 SpringCloud …

DNS攻击频发,打造防劫持DNS需强化“数据治理”理念

数字化转型时代&#xff0c;“一物多址&#xff0c;万物互联”正依托于DNS&#xff08;域名系统&#xff09;实现&#xff0c;DNS的重要性不言而喻。然而传统DNS协议存在诸多安全隐患&#xff0c;整个明文传输过程几乎没有认证与保护&#xff0c;导致DNS报文易被篡改&#xff0…

VSCode调试Unity准备工作

一.Unity设置VSCode为默认编辑器 Unity编辑器中Edit-Preferences-External Tools中选择VSCode 二.VSCode安装Unity插件 三.Unity的Visual Studio Editor升至最新 Window->Package Manager->Visual Studio Editor 四.下载配置.Net 8.0 安装之前VSCode会提示你下载.Net …

maxwell 输出消息到 redis

文章目录 1、maxwell 输出消息到 redis1.1、启动一个Maxwell容器&#xff0c;它会连接到指定的MySQL数据库&#xff0c;捕获变更事件&#xff0c;并将这些事件以Redis发布/订阅的形式发送到指定的Redis服务器1.2、在已运行的 Redis 容器中执行 Redis 命令行界面&#xff08;CLI…

【2023工业异常检测文献】SimpleNet

SimpleNet:ASimpleNetworkforImageAnomalyDetectionandLocalization 1、Background 图像异常检测和定位主要任务是识别并定位图像中异常区域。 工业异常检测最大的难题在于异常样本少&#xff0c;一般采用无监督方法&#xff0c;在训练过程中只使用正常样本。 解决工业异常检…

【uni-app】小兔鲜项目-基础架构-请求和上传文件拦截器

注意事项 uni.request 请求封装 请求和上传文件拦截器 uniapp 拦截器&#xff1a; uni.addInterceptor 接口说明&#xff1a;接口文档 实现需求 拼接基础地址设置超时时间添加请求头标识添加 token 参考代码 // src/utils/http.ts// 请求基地址 const baseURL https://pca…

IM项目-----语音识别子服务

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、搭建思想二、服务器搭建1.继承speechService类,重写业务代码2.编写语音识别服务器类3.建造者类编写 三.测试 前言 语音转换子服务&#xff0c;用于调用语音…

字节跳动算法岗面试亲历:高效流程大公开,通关诀窍全掌握

最近这一两周看到不少互联网公司都已经开始秋招提前批了。 不同以往的是&#xff0c;当前职场环境已不再是那个双向奔赴时代了。求职者在变多&#xff0c;HC 在变少&#xff0c;岗位要求还更高了。 个人情况 985 本硕项目一个论文一篇无实习经历 时间节点 7.2 技术面一面 …

探索Python的聊天机器人世界:errbot库的神秘面纱

文章目录 探索Python的聊天机器人世界&#xff1a;errbot库的神秘面纱背景&#xff1a;为何选择errbot&#xff1f;errbot是什么&#xff1f;如何安装errbot&#xff1f;简单库函数使用方法1. 创建机器人2. 响应消息3. 处理私聊4. 定时任务5. 错误处理 场景应用1. 会议提醒2. 天…