当前位置: 首页 > news >正文

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

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; // eaxstd::ostream *v4; // raxstd::ostream *v5; // rax_BYTE *v6; // raxstd::istream *v7; // raxstd::ostream *v8; // raxstd::ostream *v9; // raxstd::ostream *v10; // raxstd::ostream *v11; // raxint 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

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

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

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

参考资料

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

声明

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

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • go多线程
  • SysML图例-制药
  • 算法.图论-并查集上
  • 一款全看个人造化的Windows命令行软件下载安装管理器:Scoop
  • Revit学习记录-版本2018【持续补充】
  • python SQLAlchemy 数据库连接池
  • Robot Operating System——32 位浮点数表示的三维空间中一个点
  • 鸿蒙逐渐成为全球操作系统领域的重要一员
  • 为什么 Feign 要用 HTTP 而不是 RPC?
  • DEPLOT: One-shot visual language reasoning by plot-to-table translation论文阅读
  • 【车载以太网】【SOME/IP】Wireshark 解析
  • Google Gemini 与 OpenAI 激烈竞赛:语音 AI 与未来智能体的技术演进
  • 人工智能项目式综合实验教学平台,让教学实训更简单
  • CentOS5.2中安装并设置TFTP服务
  • 重修设计模式-概览
  • 《Java8实战》-第四章读书笔记(引入流Stream)
  • 【EOS】Cleos基础
  • Bootstrap JS插件Alert源码分析
  • es6要点
  • mysql常用命令汇总
  • 阿里云前端周刊 - 第 26 期
  • 创建一个Struts2项目maven 方式
  • 大整数乘法-表格法
  • 技术发展面试
  • 那些被忽略的 JavaScript 数组方法细节
  • ​1:1公有云能力整体输出,腾讯云“七剑”下云端
  • ​ubuntu下安装kvm虚拟机
  • # 计算机视觉入门
  • # 利刃出鞘_Tomcat 核心原理解析(八)-- Tomcat 集群
  • #如何使用 Qt 5.6 在 Android 上启用 NFC
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • (1/2)敏捷实践指南 Agile Practice Guide ([美] Project Management institute 著)
  • (23)Linux的软硬连接
  • (5)STL算法之复制
  • (c语言)strcpy函数用法
  • (Matalb时序预测)PSO-BP粒子群算法优化BP神经网络的多维时序回归预测
  • (poj1.3.2)1791(构造法模拟)
  • (ZT) 理解系统底层的概念是多么重要(by趋势科技邹飞)
  • (ZT)出版业改革:该死的死,该生的生
  • (编程语言界的丐帮 C#).NET MD5 HASH 哈希 加密 与JAVA 互通
  • (动手学习深度学习)第13章 计算机视觉---微调
  • (二)Pytorch快速搭建神经网络模型实现气温预测回归(代码+详细注解)
  • (二)windows配置JDK环境
  • (机器学习-深度学习快速入门)第三章机器学习-第二节:机器学习模型之线性回归
  • (剑指Offer)面试题34:丑数
  • (每日持续更新)jdk api之StringBufferInputStream基础、应用、实战
  • (七)Java对象在Hibernate持久化层的状态
  • (三)uboot源码分析
  • (使用vite搭建vue3项目(vite + vue3 + vue router + pinia + element plus))
  • (一)基于IDEA的JAVA基础1
  • (转)winform之ListView
  • (转载)Linux 多线程条件变量同步
  • ****三次握手和四次挥手
  • .Net IOC框架入门之一 Unity
  • .Net MVC + EF搭建学生管理系统