xctf2020-高校战役
·500 words·3 mins
Table of Contents
xctf-cycle graph #
没有其他乱七八糟的东西,就是算法
int __usercall sub_401080@(char a1@)
{
void *Graph; // ecx@1
int v2; // edx@1
int v3; // eax@2
signed int t; // edx@3
char b; // al@3
signed int i; // edi@3
int a; // ecx@3
const char *v8; // eax@17
char v10; // [sp-Ch] [bp-30h]@3
int x; // [sp+0h] [bp-24h]@4
char flag; // [sp+8h] [bp-1Ch]@3
char v13; // [sp+9h] [bp-1Bh]@10
char v14; // [sp+Ah] [bp-1Ah]@11
char v15; // [sp+Bh] [bp-19h]@12
char v16; // [sp+Ch] [bp-18h]@13
char v17; // [sp+1Dh] [bp-7h]@14
::t = 0;
Graph = &unk_403384;
::b = 48;
v2 = 0;
::a = (int)&address;
do
{
v3 = root[v2];
++v2;
*((_DWORD *)Graph - 1) = v3;
*(_DWORD *)Graph = (char *)&address + 12 * branch1[v2];
*((_DWORD *)Graph + 1) = (char *)&address + 12 * branch2[v2];
Graph = (char *)Graph + 12;
}
while ( (signed int)Graph < (signed int)&end );//生成图
sub_401020("You need a flag to get out of this:\n", a1);
sub_401050("%s", (unsigned int)&flag);
t = ::t;
b = ::b;
i = 5;
a = ::a;
do
{
x = *(&flag + i);
if ( *(_DWORD *)a + b == x )//将根的信息与flag比较
{
a = *(_DWORD *)(a + 4);//走 branch1 、更新根的地址
}
else
{
if ( b - *(_DWORD *)a != x )
{
sub_401020("This is not flag~\n", v10);
system("pause");
exit(1);
}
a = *(_DWORD *)(a + 8);//走 branch2 、更新根的地址
}
b = *(&flag + i);
++t;
++i;
::b = b;
::a = a;
::t = t;
}
while ( i < 21 );
if ( flag != 102 || v13 != 108 || v14 != 97 || v15 != 103 || v16 != 123 || v17 != 125 )
{
v8 = "illegal input~\n";
}
else if ( t > 16 || (_UNKNOWN *)a != &end1 )//判断位置
{
v8 = "This is not flag~\n";
}
else
{
v8 = "Congratulations!!\n";
}
sub_401020(v8, x);
system("pause");
return 0;
}
这个图的结构还是有点意思,把一个大数组三个三个分开形成根节点和有向的路:
0 1 3 ......
root branch1 branch2 ......
拿到图的第一个反应就是该题不限步数的话一定有多解,完了还要还要检查ascii码的范围,最后我还是决定用寻路算法常用的递归
撸代码: #
#include <iostream>
#include <stdlib.h>
using namespace std;
int root[90] = {0x34, 0x2, 0x2c, 0x2a, 0x6, 0x2a, 0x2f, 0x2a, 0x33, 0x3, 0x2, 0x32, 0x32, 0x32, 0x30, 0x3, 0x1, 0x32, 0x2b, 0x2, 0x2e, 0x1, 0x2, 0x2d, 0x32, 0x4, 0x2d, 0x30, 0x31, 0x2f, 0x33, 0x5};
int b1[90] = {0x2, 0x2, 0x1, 0x12, 0x7, 0x2, 0x1a, 0xd, 0x4, 0xa, 0x4, 0x15, 0xe, 0x1, 0x0, 0xe, 0x5, 0x7, 0x1c, 0xc, 0x1c, 0xf, 0xf, 0x2, 0x10, 0x17, 0x1e, 0x17, 0x13, 0x9, 0x16, 0x1f};
int b2[90] = {0x1, 0x8, 0x7, 0x17, 0x9, 0x13, 0x1f, 0x17, 0x9, 0xd, 0xc, 0x1d, 0xa, 0x18, 0x9, 0x18, 0x19, 0x9, 0x1a, 0x3, 0x16, 0x6, 0x11, 0xd, 0x7, 0xf, 0x14, 0x1, 0x10, 0x4, 0xb, 0x1f};
int b[90];
int ans[90];
int dir[90];
int flag[90];
void cheak()
{
int a = 48;
int c;
for(int i=0;i<16;i++)
{
if(dir[i] == 1)
{
c = a + b[i];
if (c<33 || c>126)
return;
}
if(dir[i] == 2)
{
c = a - b[i];
if (c<33 || c>126)
return;
}
a = c;
flag[i]=c;
}
cout<<"flag{";
for(int i=0;i<16;i++)
{
printf("%c",flag[i]);
}
cout<<"}";
cout<
万万没想到终点的两个有向路居然指向自己,所以算出来确实有两个解,由于代码过于抽\象才过一天就已经快看不懂了。