BUUCTF 刮开有奖 1

这题使用IDA反汇编的话有windows编程基础会好些,看不懂跟着思路来也行

一、基本分析

在这里插入图片描述
运行后
在这里插入图片描述
然后就什么都没有了

IDA反汇编
在这里插入图片描述
紫色颜色的函数就是windows系统的内置函数,这里是一个对话框函数,主要的就是第四个参数(DialogFunc),这是一个自定义函数,对话框的所有操作都在这里执行了
点进去这个函数

在这里插入图片描述

可以直接跳转到代码分析处
a2是窗口消息,可以看到是自定义函数中传递的,该消息由用户的动作产生,比如鼠标的点击,移动等,对话框的初始化都会产生一个对应的唯一的消息ID,前面消息ID的判断我们就不看了,直接浏览全部代码发现一处弹出框
在这里插入图片描述
这个也是windows的系统函数,用于弹出信息,所以我们猜测,执行到这里,flag就有了(一般出题的套路都是如此好吧,而且就这个if判断的内容最长,也只有你了)
所以我们需要让上一个if判断成立
在这里插入图片描述

所以直接看看如何让判断成立

二、代码分析

第一处判断

String[0] == v7[0] + 34

首先就是String[0]要等于v7[0] + 34, 这里v7我们并不知道,所以向上判断
在这里插入图片描述
你们那里的v7最开始的赋值可能是数字,点击数字然后按r就可以转字符
最开始是Z,后面经过sub_4010F0函数后不知道变成啥了,进去看看
在这里插入图片描述
看着就炸裂有没有,不过这个代码可以直接复制到本地运行一下,将_DWORD换成DWORD就好了,因为DWORD就是4字节大小,也就是32位下指针的大小,也就是c语言中的long类型(也可以换成long类型),DWORD定义在windows.h中,所以我们需要包含下 #include<windows.h>
需要在windows平台下运行

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

int __cdecl sub_4010F0(int a1, int a2, int a3)
{
    int result; // eax
    int i;      // esi
    int v5;     // ecx
    int v6;     // edx

    result = a3;
    for (i = a2; i <= a3; a2 = i)
    {
        v5 = 4 * i;
        v6 = *(DWORD *)(4 * i + a1);
        if (a2 < result && i < result)
        {
            do
            {
                if (v6 > *(DWORD *)(a1 + 4 * result))
                {
                    if (i >= result)
                        break;
                    ++i;
                    *(DWORD *)(v5 + a1) = *(DWORD *)(a1 + 4 * result);
                    if (i >= result)
                        break;
                    while (*(DWORD *)(a1 + 4 * i) <= v6)
                    {
                        if (++i >= result)
                            goto LABEL_13;
                    }
                    if (i >= result)
                        break;
                    v5 = 4 * i;
                    *(DWORD *)(a1 + 4 * result) = *(DWORD *)(4 * i + a1);
                }
                --result;
            } while (i < result);
        }
    LABEL_13:
        *(DWORD *)(a1 + 4 * result) = v6;
        sub_4010F0(a1, a2, i - 1);
        result = a3;
        ++i;
    }
    return result;
}

int main()
{
    int v7[11];
    v7[0] = 'Z';
    v7[1] = 'J';
    v7[2] = 'S';    // v8 = 'S';
    v7[3] = 'E';    // v9 = 'E';
    v7[4] = 'C';    // v10 = 'C';
    v7[5] = 'a';    // v11 = 'a';
    v7[6] = 'N';    // v12 = 'N';
    v7[7] = 'H';    // v13 = 'H';
    v7[8] = '3';    // v14 = '3';
    v7[9] = 'n';    // v15 = 'n';
    v7[10] = 'g';   // v16 = 'g';
    sub_4010F0((int)v7, 0, 10);
    printf("%c", v7[0] + 34);
    return 0;
}

最后输出为 U

疑问

这里看了代码的小伙伴可能会发现我将其他变量的值写在了v7中(这里将其他变量的值转成了字符)
在这里插入图片描述
其实我们在定义变量处就可以发现变量的定义在内存中是连续的,也就是说原本可能是数组,但是IDA识别成了变量,从sub_4010F0函数中也可以发现这一点
在这里插入图片描述
在这里插入图片描述
传递的第一个参数是指针,而第二个参数为0,第三个为10, 这个函数的代码里有一个for循环

a2=0
a3=10
for(i=0; i <= 10;...)`

这个for循环一共循环11次,而我们将变量加上v7数组后一共11个int大小的单元,也就是说明对其他变量进行了操作,再看这行代码

v6 = *(_DWORD *)(4 * i + a1);

少见这种代码的小伙伴可能会懵逼,这是IDA寻址的一种表示,可以看成

a1[i]

为什么这样看?
首先a1是指针,4就是int类型占用的内存大小,i是数组的下标,里面计算出地址

(4 * i + a1)

然后转成32位下的地址

(_DWORD *)(4 * i + a1)

地址解引用

int* p = (_DWORD *)(4 * i + a1)
*p

此时的*p不就等于 *(_DWORD *)(4 * i + a1)


第二个判断

继续看第二个判断

String[1] == v10

在这里插入图片描述

看起来v10似乎没有变化,但是不要忘了我前面说的,这些变量就是一个int数组,v7被作为指针传递v10在v7的下标也就是4
我们稍微改变我们上一步输出的源代码

在这里插入图片描述

最后输出J


第三处判断

4 * String[2] - 141 == 3 * v8

大概公式推导出

String[2] = (3*v8+141) / 4

直接上代码
在这里插入图片描述

结果 W


第四处判断

String[3] / 4 == 2 * (v13 / 9)

推导

String[3] == 2 * (v13 / 9) * 4

在这里插入图片描述

结果 P


第五处判断

!strcmp(v4, "ak1w")

需要v4ak1w相等
让我们看看v4在何处
在这里插入图片描述
很明显,跟v18扯上了关系
在这里插入图片描述

这里我排个序

v18[0] = String[5];
v18[1] = String[6];
v18[2] = String[7];
v4 = (const char *)sub_401000((int)v18, strlen(v18));

进入函数看看
在这里插入图片描述
这里看到一个比较特殊的变量好吧
点进去看
在这里插入图片描述
一眼盯真,base64编码表
也就是说v4可能是三个字符的编码后的结果
这里对 ak1wbase解码 jMp


第五处判断

!strcmp(v5,"V1Ax"))

这里函数用的都是同一个

在这里插入图片描述

v18[0] = String[2];
v18[1] = String[3];
v18[2] = String[4];

V1Ax解码 WP1

三、flag

至此全部判断都解出来了,可以发现,所有判断都是围绕着String进行的,最后解得的String就是flag

首先是最后两处判断得到的 String[2] - String[7] 等于 WP1jMp
还有第一处得到的 String[0] 等于 U
第二处得到的 String[1] 等于 J

最后得到flag

flag{UJWP1jMp}

在这里插入图片描述

四、最后

我们发现我们解出的其他两处似乎没用上,这个故事告诉我们
捷径总是到成功时才发现,但是一切都不再有回头路。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电子信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值