Adworld Re Writeups

Coast23

Reversing-x64Elf-100

下载附件得到.re文件.

先用DIE看看是什么文件:

DIE1

然后再扔进IDA:

IDA1

重点是这个sub_4006FD函数:

IDA2

根本不需要分析, 直接打印*(char *)(i + a1)就行.

exp:

#include <stdio.h>
#include <stdint.h>

__int64 __fastcall sub_4006FD(__int64 a1)
{
int i; // [rsp+14h] [rbp-24h]
__int64 v3[4]; // [rsp+18h] [rbp-20h]

v3[0] = (__int64)"Dufhbmf";
v3[1] = (__int64)"pG`imos";
v3[2] = (__int64)"ewUglpt";
for ( i = 0; i <= 11; ++i )
{
// if ( *(char *)(v3[i % 3] + 2 * (i / 3)) - *(char *)(i + a1) != 1 )
// return 1LL;
printf("%c", *(char *)(v3[i % 3] + 2 * (i / 3)) - 1);
}
return 0LL;
}

int main(){
sub_4006FD(0LL);
return 0^(0-0)^0;
}

Flag: Code_Talkers


666

解压附件得到666文件.

DIE:

DIE2

IDA:

  • main函数:

IDA3

  • encode函数:

IDA4

  • key = 18, enFlag = izwhroz""w"v.K".Ni

encode是线性的, 而且只涉及简单的加减和异或, 直接逆就行了.

exp:

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#define _BYTE char

#define key 18

int __fastcall encode(const char *a1, __int64 a2)
{
char v3[104]; // [rsp+10h] [rbp-70h]
int v4; // [rsp+78h] [rbp-8h]
int i; // [rsp+7Ch] [rbp-4h]

i = 0;
v4 = 0;
if ( strlen(a1) != key )
return puts("Your Length is Wrong");
for ( i = 0; i < key; i += 3 )
{
/* v3[i + 64] = key ^ (a1[i] + 6);
v3[i + 33] = (a1[i + 1] - 6) ^ key;
v3[i + 2] = a1[i + 2] ^ 6 ^ key;
*(_BYTE *)(a2 + i) = v3[i + 64];
*(_BYTE *)(a2 + i + 1LL) = v3[i + 33];
*(_BYTE *)(a2 + i + 2LL) = v3[i + 2];
*/
// 等价于如下代码
*(_BYTE *)(a2 + i) = key ^ (a1[i] + 6);
*(_BYTE *)(a2 + i + 1LL) = (a1[i + 1] - 6) ^ key;
*(_BYTE *)(a2 + i + 2LL) = a1[i + 2] ^ 6 ^ key;
}
return a2;
}

void decode(char *a2){
char flag[104] = {0};
for(int i = 0; i < key; i += 3){
flag[i] = (*(_BYTE *)(a2 + i) ^ key) - 6;
flag[i + 1] = (*(_BYTE *)(a2 + i + 1) ^ key) + 6;
flag[i + 2] = *(_BYTE *)(a2 + i + 2) ^ 6 ^ key;
}
printf("%s\n", flag);
}

int main(){
char s[] = "izwhroz\"\"w\"v.K\".Ni";
decode(s);
return 0^(0-0)^0;
}

Flag: unctf{b66_6b6_66b}


easyRE1

解压附件得到个文件: easy-32easy-64.

两个文件扔到IDA里是几乎一样的:

IDA5

直接提交db2f62a36a018bce28e46d976e3f9864, 错误.

db2f62a36a018bce28e46d976e3f9864进行解密无果, 直接搜这个字符串才知道答案要包上flag{}

显然这是个签到题.

Flag: flag{db2f62a36a018bce28e46d976e3f9864}


lucknum

解压附件得到lucknum文件.

DIE:

DIE3

IDA:

IDA6

也是一道搞笑签到题.

Flag: flag{c0ngr@tul@ti0n_f0r_luck_numb3r}


reverse_re3

reverse_re3题目描述

解压附件得到main2文件.

DIE:

DIE4

IDA:

IDA7

看到positive sp value has been detected.有点慌, 先切到main函数看看:

IDA8

重点是这个sub_940函数:

__int64 sub_940()
{
int v0; // eax
int v2; // [rsp+8h] [rbp-218h]
int v3; // [rsp+Ch] [rbp-214h]
char v4[520]; // [rsp+10h] [rbp-210h] BYREF
unsigned __int64 v5; // [rsp+218h] [rbp-8h]

v5 = __readfsqword(0x28u);
v3 = 0;
memset(v4, 0, 0x200uLL);
_isoc99_scanf(&unk_1278, v4, v4);
while ( 1 )
{
do
{
v2 = 0;
sub_86C();
v0 = v4[v3];
if ( v0 == 100 ) // Coast的注释: d
{
v2 = sub_E23();
}
else if ( v0 > 100 )
{
if ( v0 == 115 ) // Coast的注释: s
{
v2 = sub_C5A();
}
else if ( v0 == 119 ) // Coast的注释: w
{
v2 = sub_A92();
}
}
else
{
if ( v0 == 27 ) // Coast的注释: ESC
return 0xFFFFFFFFLL;
if ( v0 == 97 ) // Coast的注释: a
v2 = sub_FEC();
}
++v3;
}
while ( v2 != 1 );
if ( dword_202AB0 == 2 )
break;
++dword_202AB0;
}
puts("success! the flag is flag{md5(your input)}");
return 1LL;
}

可以看出, 这应该是一个走迷宫程序, 再来看看sub_86C, sub_E23, sub_C5A, sub_A92, sub_FEC:

unsigned __int64 sub_86C()
{
int i; // [rsp+0h] [rbp-10h]
int j; // [rsp+4h] [rbp-Ch]
unsigned __int64 v3; // [rsp+8h] [rbp-8h]

v3 = __readfsqword(0x28u);
for ( i = 0; i <= 14; ++i )
{
for ( j = 0; j <= 14; ++j )
{
if ( dword_202020[225 * dword_202AB0 + 15 * i + j] == 3 )
{
dword_202AB4 = i;
dword_202AB8 = j;
break;
}
}
}
return __readfsqword(0x28u) ^ v3;
}
__int64 sub_E23()
{
if ( dword_202AB8 != 14 )
{
if ( dword_202020[225 * dword_202AB0 + 1 + 15 * dword_202AB4 + dword_202AB8] == 1 )
{
dword_202020[225 * dword_202AB0 + 1 + 15 * dword_202AB4 + dword_202AB8] = 3;
dword_202020[225 * dword_202AB0 + 15 * dword_202AB4 + dword_202AB8] = 1;
}
else if ( dword_202020[225 * dword_202AB0 + 1 + 15 * dword_202AB4 + dword_202AB8] == 4 )
{
return 1LL;
}
}
return 0LL;
}
__int64 sub_C5A()
{
if ( dword_202AB4 != 14 )
{
if ( dword_202020[225 * dword_202AB0 + 15 + 15 * dword_202AB4 + dword_202AB8] == 1 )
{
dword_202020[225 * dword_202AB0 + 15 + 15 * dword_202AB4 + dword_202AB8] = 3;
dword_202020[225 * dword_202AB0 + 15 * dword_202AB4 + dword_202AB8] = 1;
}
else if ( dword_202020[225 * dword_202AB0 + 15 + 15 * dword_202AB4 + dword_202AB8] == 4 )
{
return 1LL;
}
}
return 0LL;
}
__int64 sub_A92()
{
if ( dword_202AB4 )
{
if ( dword_202020[225 * dword_202AB0 - 15 + 15 * dword_202AB4 + dword_202AB8] == 1 )
{
dword_202020[225 * dword_202AB0 - 15 + 15 * dword_202AB4 + dword_202AB8] = 3;
dword_202020[225 * dword_202AB0 + 15 * dword_202AB4 + dword_202AB8] = 1;
}
else if ( dword_202020[225 * dword_202AB0 - 15 + 15 * dword_202AB4 + dword_202AB8] == 4 )
{
return 1LL;
}
}
return 0LL;
}
__int64 sub_FEC()
{
if ( dword_202AB8 )
{
if ( dword_202020[225 * dword_202AB0 - 1 + 15 * dword_202AB4 + dword_202AB8] == 1 )
{
dword_202020[225 * dword_202AB0 - 1 + 15 * dword_202AB4 + dword_202AB8] = 3;
dword_202020[225 * dword_202AB0 + 15 * dword_202AB4 + dword_202AB8] = 1;
}
else if ( dword_202020[225 * dword_202AB0 - 1 + 15 * dword_202AB4 + dword_202AB8] == 4 )
{
return 1LL;
}
}
return 0LL;
}

合理猜测dword_202AB4是横坐标, dword_202AB8是纵坐标, dword_202020是地图, dword_202AB0目前还不知道是啥.

看看dword_202020:

IDA9

选中这个区段的数据, 按快捷键shift + E即可导出数据. 注意要选择initialized C variables: DWORD是双节, 相当于unsigned long.

dword_202020 (25行27列)
_DWORD dword_202020[675] = 
{
1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 3, 1, 1, 0,
0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 3, 1, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1,
0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0,
};

通过坐标的上下限, 很容易得知地图的大小是 , 可是为什么dword_202020的大小是呢?

上面这几个函数都能看到类似dword_202020[225 * dword_202AB0 + 15 * i + j]的语句, 可以大胆猜测: dword_202020其实是保存了的地图, 由dword_202AB0表示当前是第几个地图.

sub_940的循环终止条件: if(dword_202AB0 == 2) break; ++dword_202AB0;证实了这个猜测.

dword_202020 (3 * 15 * 15)
_DWORD dword_202020[3][15][15] = 
{
{
1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 0, 3, 1, 1, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
},
{
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 0, 3, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0,
1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0,
1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
},
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0,
},
};

显然, 3代表起点, 4代表终点. 这里可以直接走, 但我还是写了个脚本来输出路线.

反正不是比赛, 怎样优雅就怎样来.

exp:

#include <queue>
#include <cstdio>
#include <windef.h>

DWORD dword_202020[3][15][15] =
{
{
1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 0, 3, 1, 1, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
},
{
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 0, 3, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0,
1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0,
1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
},
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0,
},
};

char pre[3][15][15];

void get_start_pos(int maze, int* x, int* y){ // 找起点
for(int i = 0; i < 15; ++i){
for(int j = 0; j < 15; ++j){
if(dword_202020[maze][i][j] == 3){
*x = i, *y = j; return;
}
}
}
}

void print(int maze, int x, int y){ // 递归打印路径
if(pre[maze][x][y] == 'q') return;
if(pre[maze][x][y] == 'w') print(maze, x+1, y);
if(pre[maze][x][y] == 'a') print(maze, x, y+1);
if(pre[maze][x][y] =='s') print(maze, x-1, y);
if(pre[maze][x][y] == 'd') print(maze, x, y-1);
putchar(pre[maze][x][y]);
}

void bfs(int maze, int x, int y){
std::queue<std::pair<int, int>> q;
pre[maze][x][y] = 'q';
q.push({x, y});
while(q.size()){
int x = q.front().first, y = q.front().second; q.pop();
if(dword_202020[maze][x][y] == 4){print(maze, x, y); return;}
dword_202020[maze][x][y] = 0;
if(x > 0 and dword_202020[maze][x-1][y]){
q.push({x-1, y});
pre[maze][x-1][y] = 'w';
}
if(x < 14 and dword_202020[maze][x+1][y]){
q.push({x+1, y});
pre[maze][x+1][y] = 's';
}
if(y > 0 and dword_202020[maze][x][y-1]){
q.push({x, y-1});
pre[maze][x][y-1] = 'a';
}
if(y < 14 and dword_202020[maze][x][y+1]){
q.push({x, y+1});
pre[maze][x][y+1] = 'd';
}
}
}

int main(){
int maze = 0, x = -1, y = -1;
while(maze <= 2){
get_start_pos(maze, &x, &y);
bfs(maze, x, y);
++maze;
}
return 0^(0-0)^0;
}

// Output: ddsssddddsssdssdddddsssddddsssaassssdddsddssddwddssssssdddssssdddss

flag格式在sub_940的最后面: flag{md5(your input)}.

Flag: flag{aeea66fcac7fa80ed8f79f38ad5bb953}


1000Click

解压附件得到1000Click.exe.

DIE:

DIE

似乎加壳了. 用IDA打开, 发现有个函数…

IDA

果断放弃.

先用DIE直接查字符串:

DIE

一堆假flag. 还是老老实实运行程序吧.

RUN

看样子, 只需要点击Click按钮次即可拿到flag.

DBCDC很快就点到次了.

当然, 也可以写一个AutoClicker.

#include <windows.h>
int main()
{
int cnt = 0;
while(cnt < 1000)
{
if(GetAsyncKeyState('S')) // 鼠标对准按钮, 按下S键开启连点.
{
while(cnt < 1000)
{
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
Sleep(3);
if(GetAsyncKeyState('B')) break; // 发生意外请按B键退出.
++cnt;
}
exit(0);
}
}
return 0^(0-0)^0;
}

上述代码可能需要以管理员身份运行.

点击次后会有一个弹窗:

FLAG

弹窗里的flag无法直接复制, 别傻呵呵地去辨认lI, 直接在DIE里搜.

DIE

Flag: flag{TIBntXVbdZ4Z9VRtoOQ2wRlvDNIjQ8Ra}


crypt

解压附件得到 crypt.exe.

没有壳, 直接扔进 IDA 反编译.

int __fastcall main(int argc, const char **argv, const char **envp)
{
unsigned int v3; // eax
unsigned int v4; // eax
__int64 v5; // rax
__int64 v7; // rax
int i; // [rsp+24h] [rbp-D4h]
void *v9; // [rsp+28h] [rbp-D0h]
char v10[32]; // [rsp+30h] [rbp-C8h] BYREF
char Str[32]; // [rsp+50h] [rbp-A8h] BYREF
char v12[96]; // [rsp+70h] [rbp-88h] BYREF

strcpy(Str, "12345678abcdefghijklmnopqrspxyz");
memset(v12, 0, sizeof(v12));
memset(v10, 0, 0x17ui64);
sub_1400054D0("%s", v10); // scanf
v9 = malloc(0x408ui64);
v3 = strlen(Str);
sub_140001120(v9, Str, v3); // 待分析
v4 = strlen(v10);
sub_140001240(v9, v10, v4); // 待分析
for ( i = 0; i < 22; ++i )
{
if ( ((unsigned __int8)v10[i] ^ 0x22) != (unsigned __int8)byte_14013B000[i] )
{
v5 = sub_1400015A0(&off_14013B020, "error");
_CallMemberFunction0(v5, sub_140001F10);
return 0;
}
}
v7 = sub_1400015A0(&off_14013B020, "nice job");
_CallMemberFunction0(v7, sub_140001F10);
return 0;
}

// 补充:
_BYTE byte_14013B000[24] =
{
0x9E, 0xE7, 0x30, 0x5F, 0xA7, 0x01, 0xA6, 0x53, 0x59, 0x1B,
0x0A, 0x20, 0xF1, 0x73, 0xD1, 0x0E, 0xAB, 0x09, 0x84, 0x0E,
0x8D, 0x2B, 0x00, 0x00
};
__int64 __fastcall sub_140001120(_DWORD *a1, __int64 a2, int a3)
{
__int64 result; // rax
int i; // [rsp+0h] [rbp-28h]
int j; // [rsp+0h] [rbp-28h]
int v6; // [rsp+4h] [rbp-24h]
int v7; // [rsp+8h] [rbp-20h]
int v8; // [rsp+Ch] [rbp-1Ch]
_DWORD *v9; // [rsp+10h] [rbp-18h]

*a1 = 0;
a1[1] = 0;
v9 = a1 + 2;
for ( i = 0; i < 256; ++i )
v9[i] = i;
v6 = 0;
result = 0i64;
LOBYTE(v7) = 0;
for ( j = 0; j < 256; ++j )
{
v8 = v9[j];
v7 = (unsigned __int8)(*(_BYTE *)(a2 + v6) + v8 + v7);
v9[j] = v9[v7];
v9[v7] = v8;
if ( ++v6 >= a3 )
v6 = 0;
result = (unsigned int)(j + 1);
}
return result;
}
_DWORD *__fastcall sub_140001240(_DWORD *a1, __int64 a2, int a3)
{
_DWORD *result; // rax
int i; // [rsp+0h] [rbp-28h]
int v5; // [rsp+4h] [rbp-24h]
int v6; // [rsp+8h] [rbp-20h]
int v7; // [rsp+Ch] [rbp-1Ch]
int v8; // [rsp+10h] [rbp-18h]
_DWORD *v9; // [rsp+18h] [rbp-10h]

v5 = *a1;
v6 = a1[1];
v9 = a1 + 2;
for ( i = 0; i < a3; ++i )
{
v5 = (unsigned __int8)(v5 + 1);
v7 = v9[v5];
v6 = (unsigned __int8)(v7 + v6);
v8 = v9[v6];
v9[v5] = v8;
v9[v6] = v7;
*(_BYTE *)(a2 + i) ^= LOBYTE(v9[(unsigned __int8)(v8 + v7)]);
}
*a1 = v5;
result = a1;
a1[1] = v6;
return result;
}

分析了一下, 这是一个 RC4 加密.

Wiki: RC4

exp:

#include <cstdio>
#include <cstring>

unsigned char key[] = "12345678abcdefghijklmnopqrspxyz"; // 密钥
unsigned char text[] = {
0x9E, 0xE7, 0x30, 0x5F, 0xA7, 0x01, 0xA6, 0x53, 0x59, 0x1B,
0x0A, 0x20, 0xF1, 0x73, 0xD1, 0x0E, 0xAB, 0x09, 0x84, 0x0E,
0x8D, 0x2B
}; // 22 字节密文

template <typename T> void swap(T *a, T *b){T temp = *a; *a = *b; *b = temp;}

void rc4_init(unsigned char *S, unsigned char *key, int key_len){
// 初始化 S-box
for(int i = 0; i < 256; ++i) S[i] = i;

for(int i = 0, j = 0; i < 256; ++i){
j = (j + S[i] + key[i % key_len]) % 256;
swap(&S[i], &S[j]);
}
}

void rc4_crypt(unsigned char *S, unsigned char *text, int text_len){
// 加密
for(int i = 0, j = 0, k = 0; k < text_len; ++k){
i = (i + 1) % 256;
j = (j + S[i]) % 256;
swap(&S[i], &S[j]);
text[k] ^= S[(S[i] + S[j]) % 256];
}
}

void rc4_decrypt(unsigned char *S, unsigned char *text, int text_len){
rc4_crypt(S, text, text_len); // RC4 是对称加密算法.
}

int main(){
// 异或
for(int i = 0; i < sizeof(text); ++i) text[i] ^= 0x22;

// RC4 解密
unsigned char S[256];
rc4_init(S, key, strlen((char *)key));
rc4_decrypt(S, text, sizeof(text));

printf("%s\n", text);
return 0^(0-0)^0;
}

Flag: flag{nice_to_meet_you}

  • 标题: Adworld Re Writeups
  • 作者: Coast23
  • 创建于 : 2025-01-26 16:37:08
  • 更新于 : 2025-03-17 22:25:41
  • 链接: https://coast23.github.io/2025/01/26/Adworld-Re-Writeups/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论