RE | BUUCTF 刮开有奖1

本文详细解析了如何通过分析C函数和字符串操作来解密BUUCTF比赛中的一个挑战,包括理解魔改函数、构造满足条件的字符串(flag),以及应用Base64解码技术。
摘要由CSDN通过智能技术生成

题目:BUUCTF 刮开有奖1
参考:
BUUCTF 刮开有奖(特别详细了,尽自己全力理解所写)(这是主参考,写得很详细
BUUCTF_刮开有奖(主参考的参考,思路很清晰

我是大菜鸡…尽力写自己的理解了,哪里有不对的希望指正


主函数分析

首先查壳无壳32位,ida32打开,看字符串
有一个疑似u get it的东东
在这里插入图片描述点进去,看这个DialogFunc函数(好眼熟的函数名
在这里插入图片描述
分析一下
首先获取了一个string,并且string长度为8
一系列的赋值,后面是不知道干嘛的函数,疑似对v7这一串进行了魔改,而且v7以及后面一串赋值都在char范围内,后边又传参v7,怀疑是(隔开放的?)char数组
在这里插入图片描述然后把string的一部分赋给v18,然后v4、v5由v8魔改而来
在这里插入图片描述最后对string和v7进行一系列比较,对v4、v5加限制,条件全部满足就输出u get it
在这里插入图片描述现在就比较明朗了,我们要构造一个string满足最后的所有条件,就是flag(大概吧


把魔改后的v7搞出来

我一看这种函数就头疼…看不懂一点…看别人的题解才发觉,其实不用看懂啊,你c语言复现一下不就行了!!

注意点:

  1. v7 int数组改char,删掉所有DWORD
  2. *(a1 + 4 * i)这种要改成a1[i],因为ida中定义的是int数组,int占四个字节,而我们改成char数组了,char只占一个字节,还用*(a1 + 4 * i)就会变成a1[4*i]
  3. 见代码注释,有一个*(a1 + v5)要改成a1[v5 / 4](其实好像和i还是有关联的但是我懒得看了
#include <vector>
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

typedef long long ll;
const int N = 1e5 + 5;

int sub_4010F0(char *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 = a1[i];
    //v6 = i[a1];
    if ( a2 < result && i < result )
    {
      do
      {
        if ( v6 > a1[result] )
        {
          if ( i >= result )
            break;
          ++i;
          //特别注意这里,写a1[i] = a1[result]是不行的,因为v5和现在的i*4已经不相等了
          a1[v5 / 4] = a1[result];
          if ( i >= result )
            break;
          while ( a1[i] <= v6 )
          {
            if ( ++i >= result )
              goto LABEL_13;
          }
          if ( i >= result )
            break;
          v5 = 4 * i;
          a1[result] = a1[i];
        }
        --result;
      }
      while ( i < result );
    }
LABEL_13:
    a1[result] = v6;
    sub_4010F0(a1, a2, i - 1);
    result = a3;
    ++i;
  }
  return result;
}

int main()
{
	char v7[] = {90,74,83,69,67,97,78,72,51,110, 103};
	
    sub_4010F0(v7, 0, 10);
    cout << v7 << endl;
	return 0;
}

得到3CEHJNSZagn
在这里插入图片描述


拼出flag

(把string改名flag了)已知:

在这里插入图片描述前几行只涉及flag和v7数组,我们已经知道了,可以直接得到flag前几位
在之前求v7的代码后边加上几行:

str[0] = v7[0] + 34;
str[1] = v7[4];
str[2] = (char)((int)(3 * v7[2] + 141) / 4);
str[3] = 2 * (v7[7] / 9) * 4;
cout << str << endl;

得到flag[0-3] = UJWP在这里插入图片描述后两行要求v4=ak1w,v5=V1Ax
再看前面,v4v5都是从flag中截取一部分,再经过sub_401000函数得到
在这里插入图片描述看看这个函数
在这里插入图片描述看看这个byte_407830,char数组,大小写字幕数字和=
在这里插入图片描述再加上v4v5原本长度是4,处理完确只用了三个
合理怀疑是base64(?
找个网站解码
在这里插入图片描述得到

v4:ak1w <- jMp
v5:V1Ax <- WP1

再根据v18和flag的对应关系

//v18: jMp
v18[0] = flag[5];
v18[2] = flag[7];
v18[1] = flag[6];
//v18: WP1
v18[1] = flag[3];
v18[0] = flag[2];
v18[2] = flag[4];

得出flag[5-7] = jMpflag[2-4] = WP1
最终flag数组就是UJWP1jMp
(话说这里解出flag的2-7,跟前面与v7比较得到的flag0-3有重合啊怎么回事,虽然是一样的)

过了
在这里插入图片描述


感觉学会了很多又好像没学会…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值