题目: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语言复现一下不就行了!!
注意点:
- v7 int数组改char,删掉所有DWORD
*(a1 + 4 * i)
这种要改成a1[i]
,因为ida中定义的是int数组,int占四个字节,而我们改成char数组了,char只占一个字节,还用*(a1 + 4 * i)
就会变成a1[4*i]
- 见代码注释,有一个
*(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] = jMp
,flag[2-4] = WP1
最终flag数组就是UJWP1jMp
(话说这里解出flag的2-7,跟前面与v7比较得到的flag0-3有重合啊怎么回事,虽然是一样的)
过了
感觉学会了很多又好像没学会…