题目链接

https://buuoj.cn/challenges#%E5%88%AE%E5%BC%80%E6%9C%89%E5%A5%96

题解

用IDA打开,按F5反编译,双击进入DialogFunc函数。

代码如下:

  1 BOOL __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4)
2 {
3 const char *v4; // esi
4 const char *v5; // edi
5 int v7; // [esp+8h] [ebp-20030h]
6 int v8; // [esp+Ch] [ebp-2002Ch]
7 int v9; // [esp+10h] [ebp-20028h]
8 int v10; // [esp+14h] [ebp-20024h]
9 int v11; // [esp+18h] [ebp-20020h]
10 int v12; // [esp+1Ch] [ebp-2001Ch]
11 int v13; // [esp+20h] [ebp-20018h]
12 int v14; // [esp+24h] [ebp-20014h]
13 int v15; // [esp+28h] [ebp-20010h]
14 int v16; // [esp+2Ch] [ebp-2000Ch]
15 int v17; // [esp+30h] [ebp-20008h]
16 CHAR String; // [esp+34h] [ebp-20004h]
17 char v19; // [esp+35h] [ebp-20003h]
18 char v20; // [esp+36h] [ebp-20002h]
19 char v21; // [esp+37h] [ebp-20001h]
20 char v22; // [esp+38h] [ebp-20000h]
21 char v23; // [esp+39h] [ebp-1FFFFh]
22 char v24; // [esp+3Ah] [ebp-1FFFEh]
23 char v25; // [esp+3Bh] [ebp-1FFFDh]
24 char v26; // [esp+10034h] [ebp-10004h]
25 char v27; // [esp+10035h] [ebp-10003h]
26 char v28; // [esp+10036h] [ebp-10002h]
27
28 if ( a2 == 272 )
29 return 1;
30 if ( a2 != 273 )
31 return 0;
32 if ( (_WORD)a3 == 1001 )
33 {
34 memset(&String, 0, 0xFFFFu);
35 GetDlgItemTextA(hDlg, 1000, &String, 0xFFFF);
36 if ( strlen(&String) == 8 )
37 {
38 v7 = 90;
39 v8 = 74;
40 v9 = 83;
41 v10 = 69;
42 v11 = 67;
43 v12 = 97;
44 v13 = 78;
45 v14 = 72;
46 v15 = 51;
47 v16 = 110;
48 v17 = 103;
49 sub_4010F0((int)&v7, 0, 10);
50 memset(&v26, 0, 0xFFFFu);
51 v26 = v23;
52 v28 = v25;
53 v27 = v24;
54 v4 = sub_401000((int)&v26, strlen(&v26));
55 memset(&v26, 0, 0xFFFFu);
56 v27 = v21;
57 v26 = v20;
58 v28 = v22;
59 v5 = sub_401000((int)&v26, strlen(&v26));
60 if ( String == v7 + 34
61 && v19 == v11
62 && 4 * v20 - 141 == 3 * v9
63 && v21 / 4 == 2 * (v14 / 9)
64 && !strcmp(v4, "ak1w")
65 && !strcmp(v5, "V1Ax") )
66 {
67 MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
68 }
69 }
70 return 0;
71 }
72 if ( (_WORD)a3 != 1 && (_WORD)a3 != 2 )
73 return 0;
74 EndDialog(hDlg, (unsigned __int16)a3);
75 return 1;
76 }

35行读取输入,36行说明flag长度为8。

进入49行的sub_4010F0函数,并修改为可以运行的C语言格式。代码如下:

  1 #include<bits/stdc++.h>
2 using namespace std;
3 int __cdecl sub_4010F0(char *a1, int a2, int a3) // int a1
4 {
5 int result; // eax
6 int i; // esi
7 int v5; // ecx
8 int v6; // edx
9
10 result = a3;
11 for ( i = a2; i <= a3; a2 = i )
12 {
13 v5 = i; //v5 = 4 * i 这一行为什么要改?求大佬指教
14 v6 = a1[i]; //v6 = *(_DWORD *)(4 * i + a1)
15 if ( a2 < result && i < result )
16 {
17 do
18 {
19 if ( v6 > a1[result] ) //v6 > *(_DWORD *)(a1 + 4 * result)
20 {
21 if ( i >= result )
22 break;
23 ++i;
24 a1[v5] = a1[result]; //*(_DWORD *)(v5 + a1) = *(_DWORD *)(a1 + 4 * result)
25 if ( i >= result )
26 break;
27 while ( a1[i] <= v6 ) // *(_DWORD *)(a1 + 4 * i) <= v6
28 {
29 if ( ++i >= result )
30 goto LABEL_13;
31 }
32 if ( i >= result )
33 break;
34 v5 = i; //v5 = 4 * i 这一行为什么要改?求大佬指教
35 a1[result] = a1[i]; // *(_DWORD *)(a1 + 4 * result) = *(_DWORD *)(4 * i + a1)
36 }
37 --result;
38 }
39 while ( i < result );
40 }
41 LABEL_13:
42 a1[result] = v6; //*(_DWORD *)(a1 + 4 * result) = v6
43 sub_4010F0(a1, a2, i - 1);
44 result = a3;
45 ++i;
46 }
47 return result;
48 }
49
50 char str[20] = {90,74,83,69,67,97,78,72,51,110,103};
51
52 int main()
53 {
54 cout << str << endl;
55 sub_4010F0(str,0,10);
56 cout << str << endl;
57 }

这里50行我们定义的字符串见DialogFunc函数中第38到48行。运行结果:

我们再回到DialogFuc函数。

通过观察变量v7到v25定义时的地址(或者双击变量名),我们知道它们在地址中是相邻的,实际上如下图:

那么可以理解,DialogFunc函数中第51~54行,是把经过sub_4010F0处理后的字符串的倒数第3~倒数第1位赋给v4,而第56~59行,是将倒数第6~倒数第4位赋给v5。

接下来我们研究sub_401000函数。代码如下:

  1 _BYTE *__cdecl sub_401000(int a1, int a2)
2 {
3 int v2; // eax
4 int v3; // esi
5 size_t v4; // ebx
6 _BYTE *v5; // eax
7 _BYTE *v6; // edi
8 int v7; // eax
9 _BYTE *v8; // ebx
10 int v9; // edi
11 signed int v10; // edx
12 int v11; // edi
13 signed int v12; // eax
14 signed int v13; // esi
15 _BYTE *result; // eax
16 _BYTE *v15; // [esp+Ch] [ebp-10h]
17 _BYTE *v16; // [esp+10h] [ebp-Ch]
18 int v17; // [esp+14h] [ebp-8h]
19 int v18; // [esp+18h] [ebp-4h]
20
21 v2 = a2 / 3;
22 v3 = 0;
23 if ( a2 % 3 > 0 )
24 ++v2;
25 v4 = 4 * v2 + 1;
26 v5 = malloc(v4);
27 v6 = v5;
28 v15 = v5;
29 if ( !v5 )
30 exit(0);
31 memset(v5, 0, v4);
32 v7 = a2;
33 v8 = v6;
34 v16 = v6;
35 if ( a2 > 0 )
36 {
37 while ( 1 )
38 {
39 v9 = 0;
40 v10 = 0;
41 v18 = 0;
42 do
43 {
44 if ( v3 >= v7 )
45 break;
46 ++v10;
47 v9 = *(unsigned __int8 *)(v3++ + a1) | (v9 << 8);
48 }
49 while ( v10 < 3 );
50 v11 = v9 << 8 * (3 - v10);
51 v12 = 0;
52 v17 = v3;
53 v13 = 18;
54 do
55 {
56 if ( v10 >= v12 )
57 {
58 *((_BYTE *)&v18 + v12) = (v11 >> v13) & 0x3F;
59 v8 = v16;
60 }
61 else
62 {
63 *((_BYTE *)&v18 + v12) = 64;
64 }
65 *v8++ = byte_407830[*((char *)&v18 + v12)];
66 v13 -= 6;
67 ++v12;
68 v16 = v8;
69 }
70 while ( v13 > -6 );
71 v3 = v17;
72 if ( v17 >= a2 )
73 break;
74 v7 = a2;
75 }
76 v6 = v15;
77 }
78 result = v6;
79 *v8 = 0;
80 return result;
81 }

进入第65行的byte_407830

怀疑sub_401000是base64加密。

再回到DialogFuc函数,研究flag的格式:

  if ( String == v7 + 34                    // 第一位等于经过sub_4010F0处理后的字符串的第一位('3')51+34=85('U')
&& v19 == v11 // 第二位等于v11,即经过sub_4010F00处理后的字符串的第5位'J'
&& 4 * v20 - 141 == 3 * v9 // 经过计算,第三位等于(3 * 69('E') + 141) / 4 = 87('W')
&& v21 / 4 == 2 * (v14 / 9) // 第四位等于2 * ( 90('Z') / 9 ) * 4 = 80('P')
&& !strcmp(v4, "ak1w") // 第六、七、八位经过base64加密后等于'ak1w'
&& !strcmp( // 第三、四、五位经过base64加密后等于'V1Ax'
v5,
"V1Ax") )
{
MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
}

将’ak1w’、’V1Ax’进行base64解密,再连上前两位拼接起来,加上flag{}格式,即可得到flag:

flag{UJWP1jMp}


参考

BUUCTF--刮开有奖

Open Live Writer 安装

open live writer 安装 markdown 插件

博客高亮代码及使用OpenLiveWriter修改之前博客

其他

一开始用openlivewriter插入markdown代码总是报错

解决办法是取消勾选语言。

BUUCTF 刮开有奖 WriteUp的更多相关文章

  1. [BUUCTF]REVERSE——刮开有奖

    刮开有奖 附件 步骤: 例行检查,无壳,32位程序 32位ida载入,shift+f12检索程序里的字符串,看到了一个base64加密的特征字符串,猜想这题用到了base64加密 从main函数开始看 ...

  2. BUUOJ reverse 刮开有奖

    刮开有奖 这是一个赌博程序,快去赚钱吧!!!!!!!!!!!!!!!!!!!!!!!!!!!(在编辑框中的输入值,即为flag,提交即可) 注意:得到的 flag 请包上 flag{} 提交 拖到id ...

  3. [BUUOJ]刮开有奖reverse

    刮开有奖 这是一个赌博程序,快去赚钱吧!!!!!!!!!!!!!!!!!!!!!!!!!!!(在编辑框中的输入值,即为flag,提交即可) 注意:得到的 flag 请包上 flag{} 提交 1.查壳 ...

  4. buu 刮开有奖

    一.查壳, 二.拖入ida,分析 直接搜字符串完全没头绪,在看了大佬的wp才找到了,关键函数. 明显那个String就是我们要求的flag,要开始分析程序. 字符串长度为8,同时这个函数对字符串进行了 ...

  5. BUUCTF--刮开有奖

    文件链接:https://buuoj.cn/files/abe6e2152471e1e1cbd9e5c0cae95d29/8f80610b-8701-4c7f-ad60-63861a558a5b.ex ...

  6. 服务端性能测试工具校验v1.1

    服务端性能测试工具校验v1.1 更新说明: 1.精简CRT运行库支持. 2.添加响应模拟测试,校验压力测试工具的响应时间统计准确性. 3.大并发请求请降低延迟时间 WEIMJSAM原创,转载请注明出处 ...

  7. 服务端性能测试工具校验v1.0

    性能测试工具对服务端进行并发测试时,如果工具本身问题或异常就会造成真实并发与实际并发有差距,要测试10000/S并发的性能结果实际到达服务端的并发达不到95%,这样的测试无效. 所以给大家共享,我做的 ...

  8. Visual.Studio.2013.IDE+visual.studio.15.preview5 编译器

    硬盘版Visual.Studio.2013.IDE + visual.studio.15.preview5 编译器 使用前注意以下事项: 1.右键-管理员权限安装,VS15补丁.exe,补丁是VS15 ...

  9. 测试工具之Charles视频教程(更新中。。。)

    应群里小伙伴学习需求,录制新版 Charles V4 系列教程,后续内容抽空更新,测试工具系列带你上王者...(ノ°ο°)ノ前方高能预警 链接:http://pan.baidu.com/s/1c16P ...

随机推荐

  1. 吉他自学用Guitar Pro好不好?

    很多人心中都有一个吉他梦,可苦于没有坚持下来.其实一个人自学吉他过程是非常枯燥的.经常手上被磨得都是茧,但是也不清楚自己弹的到底对不对. 如果不跟着老师练习,那很有可能就走了歪路或者是无法长期坚持.所 ...

  2. FL studio系列教程(十五):FL Studio文件菜单功能详讲

    在FL Studio主控面板上的是其主菜单.主菜单包括:文件.编辑.添加.样式.查看.选项.工具和帮助.如下图所示: 为了帮助初学者快速的了解并能使用它制作出作品,今天小编将详细地为大家讲解下这些菜单 ...

  3. 移动自动化测试框架--openatx

    之前学习并使用appium进行移动端测试,对于使用appium的一些体会与感受是否与我相似 1. appium启动服务和app程序非常慢 2. appium搭建环境较复杂 3. appium必须连接u ...

  4. img标签到底是行内元素还是块级元素

    面试官问你<img>是什么元素时你怎么回答 写这篇文章源自我之前的一次面试,题目便是问img标签属于块级元素还是行内元素,当时想都没想就说了是行内(inline)元素,面试官追问为什么能够 ...

  5. 项目、地铁/公交、游戏签到、项目上线后发现新bug该怎么处理

    项目:1.提前分配好业务(每个人该干什么 )2.提前召开会议3.提前挑好人4.准备项目思维导图5.提前审阅项目6.为确保项目按期交付 把控好时间7.给员工提前打好招呼 (提醒加班)8.建立好安全机制9 ...

  6. Dotnet Core下的Channel, 你用了吗?

    今天给大家分享一个微软官方的好东西:Channel.   前言 今天给大家分享一个微软官方的生产者/消费者方案的特性解决:Channel. Channel在System.Threading.Chann ...

  7. 大厂是如何用DevCloud流水线实现自动化部署Web应用的?

    DevUI是一支兼具设计视角和工程视角的团队,服务于华为云DevCloud平台和华为内部数个中后台系统,服务于设计师和前端工程师. 官方网站:devui.design Ng组件库:ng-devui(欢 ...

  8. JDK8日期类入门

    关于jdk8的时间类的用法,网上有很多教程教你如何用,比如: System.out.println(LocalDateTime.now()); 可以获取当前的时间, 2020-12-06T18:02: ...

  9. 第9.13节 Python文件操作总结

    本章老猿重点介绍了Python io模块的文件操作相关功能,包括文件打开.读.写.文件定位.文件关闭,并介绍了二进制文件和文本文件处理的差异,以及相关文件编码的一些知识,最后简单提及了Python中与 ...

  10. PyQt(Python+Qt)学习随笔:QAbstractScrollArea的viewPort(视口)理解

    老猿Python博文目录 老猿Python博客地址 在学习Designer中ItemViews类部件时,这些部件都有个父类QAbstractScrollArea,该父类是Qt滚动区域的低级抽象.该区域 ...