刷攻防世界的最后一道二星题,记录一下,大佬请飘过


题目


分析过程

我很勇,我先双击看看这是什么

是一个扫雷游戏,第一下运气好没踩雷,发现无法继续输入了;如果运气不好,会输出“您踩雷啦!”

丢到PE里面

无壳,64位

丢到IDA里面,shif+F12查看字符串,追踪可疑字符串,发现main函数

  1 int __cdecl main(int argc, const char **argv, const char **envp)
2 {
3 unsigned int v3; // eax
4 std::ostream *v4; // rax
5 __int64 v5; // rax
6 _BYTE *v6; // rax
7 std::istream *v7; // rax
8 __int64 v8; // rax
9 std::ostream *v9; // rax
10 std::ostream *v10; // rax
11 __int64 v11; // rax
12 int v13; // [rsp+28h] [rbp-58h]
13 int v14; // [rsp+2Ch] [rbp-54h]
14 int v15; // [rsp+30h] [rbp-50h]
15 int v16; // [rsp+34h] [rbp-4Ch]
16 int v17; // [rsp+38h] [rbp-48h]
17 int v18; // [rsp+3Ch] [rbp-44h]
18 int v19; // [rsp+40h] [rbp-40h]
19 int i1; // [rsp+44h] [rbp-3Ch]
20 int nn; // [rsp+48h] [rbp-38h]
21 int mm; // [rsp+4Ch] [rbp-34h]
22 int ll; // [rsp+50h] [rbp-30h]
23 int i2; // [rsp+54h] [rbp-2Ch]
24 int kk; // [rsp+58h] [rbp-28h]
25 int jj; // [rsp+5Ch] [rbp-24h]
26 int ii; // [rsp+60h] [rbp-20h]
27 int n; // [rsp+64h] [rbp-1Ch]
28 int m; // [rsp+68h] [rbp-18h]
29 int l; // [rsp+6Ch] [rbp-14h]
30 int k; // [rsp+70h] [rbp-10h]
31 int v32; // [rsp+74h] [rbp-Ch]
32 int j; // [rsp+78h] [rbp-8h]
33 int i; // [rsp+7Ch] [rbp-4h]
34
35 _main();
36 memset(grid, 0, 0x190ui64);
37 memset(randMark, 0, 0x9C40ui64);
38 memset(vis, 0, sizeof(vis));
39 for ( i = 0; i <= 9; ++i ) // 第一个循环-------------------------------------------------------------------------------
40 {
41 for ( j = 0; j <= 9; ++j )
42 showUs[100 * i + j] = 42;
43 }
44 v3 = time(0i64);
45 srand(v3);
46 v32 = 0;
47 do
48 {
49 v19 = rand() % 10; // 随机一个0~9
50 v18 = rand() % 10;
51 if ( randMark[100 * v19 + v18] != 1 )
52 {
53 randMark[100 * v19 + v18] = 1; // v32不到mine_sum,就一直循环
54 // 我怀疑这里是布雷
55 // mine_sum是雷的数量
56 ++v32;
57 }
58 }
59 while ( v32 != mine_sum );
60 res = 0;
61 for ( k = 0; k <= 9; ++k ) // 第二个循环-------------------------------------------------------------------------------------------
62 {
63 for ( l = 0; l <= 9; ++l )
64 {
65 if ( randMark[100 * k + l] )
66 grid[10 * k + l] = -1;
67 }
68 }
69 for ( m = 0; m <= 9; ++m ) // 第三个循环-----------------------------------------------------------------------------------------------------
70 {
71 for ( n = 0; n <= 9; ++n )
72 {
73 if ( grid[10 * m + n] != -1 )
74 {
75 for ( ii = 0; ii <= 7; ++ii )
76 {
77 v17 = *((_DWORD *)&dir + 2 * ii) + m;
78 v16 = dword_475044[2 * ii] + n;
79 if ( v17 >= 0 && v17 <= 9 && v16 >= 0 && v16 <= 9 && grid[10 * v17 + v16] == -1 )
80 ++grid[10 * m + n];
81 }
82 }
83 }
84 }
85 for ( jj = 0; jj <= 9; ++jj ) // 第四个循环--------------------------------------------------------------------------------------------------------
86 {
87 for ( kk = 0; kk <= 9; ++kk )
88 {
89 v4 = (std::ostream *)std::operator<<<std::char_traits<char>>(
90 refptr__ZSt4cout,
91 (unsigned int)showUs[100 * jj + kk]);
92 std::operator<<<std::char_traits<char>>(v4, " ");
93 }
94 std::ostream::operator<<(refptr__ZSt4cout, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_);
95 }
96 LABEL_42:
97 v5 = std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, asc_48B002);// 请输入要翻开的位置的坐标
98 std::ostream::operator<<(v5, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_);
99 while ( 100 - mine_sum != res ) // res是没有雷的地方
100 {
101 v7 = (std::istream *)std::istream::operator>>(refptr__ZSt3cin);
102 std::istream::operator>>(v7);
103 if ( grid[10 * v14 + v13] == -1 ) // 第一个if---检查是否踩雷
104 {
105 v8 = std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, asc_48B01D);// 您中雷啦
106 std::ostream::operator<<(v8, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_);
107 goto LABEL_69; // pause
108 }
109 if ( !vis[100 * v14 + v13] && grid[10 * v14 + v13] > 0 )// 第二个if---
110 {
111 ++res;
112 vis[100 * v14 + v13] = 1;
113 showUs[100 * v14 + v13] = LOBYTE(grid[10 * v14 + v13]) + 48;
114 system("cls");
115 for ( ll = 0; ll <= 9; ++ll )
116 {
117 for ( mm = 0; mm <= 9; ++mm )
118 {
119 v9 = (std::ostream *)std::operator<<<std::char_traits<char>>(
120 refptr__ZSt4cout,
121 (unsigned int)showUs[100 * ll + mm]);
122 std::operator<<<std::char_traits<char>>(v9, " ");
123 }
124 std::ostream::operator<<(refptr__ZSt4cout, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_);
125 }
126 goto LABEL_42;
127 }
128 if ( !vis[100 * v14 + v13] && !grid[10 * v14 + v13] )// 第三个if---
129 {
130 bfs(v14, v13);
131 system("cls");
132 for ( nn = 0; nn <= 9; ++nn )
133 {
134 for ( i1 = 0; i1 <= 9; ++i1 )
135 {
136 v10 = (std::ostream *)std::operator<<<std::char_traits<char>>(
137 refptr__ZSt4cout,
138 (unsigned int)showUs[100 * nn + i1]);
139 std::operator<<<std::char_traits<char>>(v10, " ");
140 }
141 std::ostream::operator<<(refptr__ZSt4cout, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_);
142 }
143 v11 = std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, asc_48B002);// 请输入要翻开的位置的坐标
144 std::ostream::operator<<(v11, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_);
145 }
146 } // while结束的地方
147 v15 = std::string::length((std::string *)&ans);
148 for ( i2 = 0; i2 < v15; ++i2 )
149 {
150 v6 = (_BYTE *)std::string::operator[](&ans, i2);
151 std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, (unsigned int)(char)((v15 - i2) ^ *v6));// 异或操作!!!!注意!!!!
152 }
153 std::ostream::operator<<(refptr__ZSt4cout, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_);
154 LABEL_69:
155 system("pause");
156 return 0;
157 }

一堆循环与if,粗略看看,147行之前都没发现什么表明游戏通关的字符串或者跳转函数

一直到147行,突然出现一个ans,上来直接就是将它的长度赋给v15,做题有点经验的小伙伴应该会发现,一般能够单开一行赋长度的参数,很有可能是关键之一

特别是下面还有一个异或操作,简直就是重点怀疑对象


动态调试(X64dbg)

输出ans紧接着的是一个循环,我们看看地址与汇编

x64dbg的基址与IDA是一样的,不用改了——需要改地址的可以看看我之前的博客攻防世界 gametime 使用IDA pro+OD动调 - demo41 - 博客园 (cnblogs.com)

既然不用改地址,我们直接记下jmz的地址 0000000000401ED2 ,在x64dbg中跳转到

将jnz改成jz,运行直到出现字符串

输出结果: 7ii3VecVgof3r6ssiP2g7E3HqwqhM

直接拿去提交了,出错了,那应该是加密了

我试了很多,一直试不出来,还以为自己错了

后面看了wp,我解题没错,这是一个标准base58

大部分base58解密网站的字符序都是BTC-base58序列,顺序为123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz

标准base58的解密序列是123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ

这里提供一个解密网站:Base58编码/解码 - 一个工具箱 - 好用的在线工具都在这里! (atoolbox.net)


静态调试(IDA+py脚本)

我之前查看字符串的时候,还有追踪asc_48B002和asc_48B01D的时候,都发现一个特别可疑的字符串

追进去看看

 1 int __fastcall __static_initialization_and_destruction_0(int a1, int a2)
2 {
3 int result; // eax
4 char v3[17]; // [rsp+2Fh] [rbp-51h] BYREF
5
6 if ( a1 == 1 && a2 == 0xFFFF )
7 {
8 std::ios_base::Init::Init((std::ios_base::Init *)&std::__ioinit);
9 atexit(_tcf_0);
10 std::allocator<char>::allocator(v3);
11 std::string::string(&ans, "*ur)O}t@r{u!c&|}d\\9m>M4NtsrjL", v3);// 放进去吗?
12 std::allocator<char>::~allocator(v3);
13 result = atexit(_tcf_1);
14 }
15 return result;
16 }

竟然和ans联系在一起了,花指令我没查具体意思,七分逆向三分猜,我感觉就是把字符串放进ans里面,反正异或操作不难,脚本很容易写,试试再说

py脚本

1 ans="*ur)O}t@r{u!c&|}d\\9m>M4NtsrjL"
2 v15=len(ans)
3 str=""
4
5 for i in range(len(ans)):
6 str+=chr((v15-i)^ord(ans[i]))
7
8 print(str)

输出结果: 7ii3VecVgof3r6ssiP2g7E3HqwqhM

直接拿去提交了,出错了,那应该是加密了

我试了很多,一直试不出来,还以为自己错了

后面看了wp,我解题没错,这是一个标准base58

大部分base58解密网站的字符序都是BTC-base58序列,顺序为123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz

标准base58的解密序列是123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ

这里提供一个解密网站:Base58编码/解码 - 一个工具箱 - 好用的在线工具都在这里! (atoolbox.net)


flag

flag{h4pp4-M1n3-G4m3}

攻防世界 Mine- IDA静调或x64dbg动调 两种方式的更多相关文章

  1. OpenCV4Android释疑: 透析Android以JNI调OpenCV的三种方式(让OpenCVManager永不困扰)

    OpenCV4Android释疑: 透析Android以JNI调OpenCV的三种方式(让OpenCVManager永不困扰) 前文曾详细探讨了关于OpenCV的使用,原本以为天下已太平.但不断有人反 ...

  2. 【攻防世界】 高手进阶区 Recho WP

    0x00 考察点 考察点有三个: ROP链构造 Got表劫持 pwntools的shutdown功能 0x01 程序分析 上来三板斧 file一下 checksec --file XXX chmod ...

  3. pwn篇:攻防世界进阶welpwn,LibcSearcher使用

    攻防世界welpwn (搬运一篇自己在CSDN写的帖子) 链接:https://blog.csdn.net/weixin_44644249/article/details/113781356 这题主要 ...

  4. 攻防世界(十三)unserialize3

    攻防世界系列 :unserialize3 1.打开题目,反序列化 2.代码审计 类xctf被调用时_weakeup()函数会被自动执行,但当序列化字符串中属性值个数大于属性个数,就会导致反序列化异常, ...

  5. 攻防世界pwn高手区——pwn1

    攻防世界 -- pwn1 攻防世界的一道pwn题,也有一段时间没有做pwn了,找了一道栈题热身,发现还是有些生疏了. 题目流程 拖入IDA中,题目流程如图所示,当v0为1时,存在栈溢出漏洞.在gdb中 ...

  6. 攻防世界逆向——game

    攻防世界逆向:game wp 攻防世界逆向新手区的一道题目. 是一道windows的creak,动态调试打开是这样的: 题目说明是让屏幕上所有的图像都亮之后,会出现flag,看来应该是可以玩出来的. ...

  7. 攻防世界PWN简单题 level0

    攻防世界PWN简单题 level0 开始考验栈溢出的相关知识了 Checksec 一下文件 看看都开了什么保护 和 是多少位的程序 发现是64位的程序, 扔进IDA64.IDA YYDS.. 进入主函 ...

  8. 攻防世界PWN简单题 level2

    攻防世界PWN简单题 level2 此题考验的是对ROP链攻击的基础 万事开头PWN第一步checksec 一下 32位的小端程序,扔进IDA 进入函数,找出栈溢出漏洞. 又是这个位置的栈溢出,rea ...

  9. 进阶区forgotg攻防世界

    攻防世界进阶区--forgot 前言,这题中看不中用啊宝友!!! 1.查看保护 第一反应就是蛮简单的,32位. 2.获取信息(先运行程序看看) 装的可以,蛮多的东西. 但是就是中看不中用 3.ida ...

  10. 【pwn】攻防世界 pwn新手区wp

    [pwn]攻防世界 pwn新手区wp 前言 这几天恶补pwn的各种知识点,然后看了看攻防世界的pwn新手区没有堆题(堆才刚刚开始看),所以就花了一晚上的时间把新手区的10题给写完了. 1.get_sh ...

随机推荐

  1. 【Azure Function App】Java Function部署到Azure后出现中文显示乱码问题

    问题描述 Java Function在Azure上遇见中文显示乱码问题?如何解决呢? 问题解答 中文字符显示为乱码,这个情况就是服务实例上设置的编码格式不是统一的UTF-8所导致的. 在查看Azure ...

  2. 【Azure 应用服务】Azure Function App在部署时候遇见 503 ServiceUnavailable

    问题描述 在VS Code中编写好 Azure Function App代码后,通过  func azure functionapp publish 部署失败,抛出 503 Service Unava ...

  3. 【Azure Fabric Service】Service Fabric 托管群集通过 Connect-ServiceFabricCluster 连接时候报错 CertificatedNotMatched

    问题描述 Service Fabric 托管群集, 使用Key Vault中证书,把证书导入到本地安装后,使用该证书的 Thumbprint 作为指令 Connect-ServiceFabricClu ...

  4. 【Azure 应用服务】部署Azure Web App时,是否可以替换hostingstart.html文件呢?

    问题描述 当成功创建一个Web App时,通过高级工具(Kudu)可以查看 Web App的根目录(wwwroot)中有一个默认的文件(hostingstart.html).它就是应用服务的默认页面. ...

  5. 十一: 数据库缓冲池(buffer pool)

    数据库缓冲池(buffer pool) InnoDB 存储引擎是以页为单位来管理存储空间的,我们进行的增删改查操作其实本质上都是在访问页 面(包括读页面.写页面.创建新页面等操作).而磁盘 I/O 需 ...

  6. shell脚本的基本使用

    本文是对菜鸟教程 shell编程原文 的总结并记录 如有侵权 联系删除 简介 说明: Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁.这个应用程序提供了一个界面,用户通过这 ...

  7. SQL之 逻辑库,数据表

    SQL语言三大类 创建逻辑库 创建数据表 例子 数据表其他操作 ps:desc仅仅查看表的结构,不能查看内容 添加字段 ps: 修改字段类型和约束 修改字段名称 删除字段

  8. 1. zookeeper简介与应用场景

    1.1 zookeeper介绍   zookeeper是一个高可用的分布式管理与协调框架,基于ZAB算法(原子消息广播协议)的实现. 能够很好保证分布式环境中数据的一致性.正是基于这样的特性,使得zo ...

  9. Codeforces Round 260 (Div. 1)A. Boredom(dp)

    最开始写了一发贪心wa了,然后这种选和不选的组合优化问题,一般是考虑动态规划 \(dp[i][0]:\)表示第i个数不选的最大值 \(dp[i][1]:\)表示第i个数选的最大值 考虑转移: \(dp ...

  10. day07-IO流应用02

    Java坦克大战07 8.IO流应用02 8.3记录退出游戏时敌人坦克坐标/方向,存盘退出 8.3.1思路分析 在Recorder类中,增加一个Vector集合,用来接收从MyPanel类中传入的en ...