比赛网址
https://ctf.unctf.com/#/match
官方wp
ezlogin
简单签到题,IDA32位打开,flag就在login()中
跟进查看
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
```c
int login(void)
{
double v0; // st7
signed int v1; // eax
signed int v2; // ecx
int v3; // edi
int v4; // eax
int v5; // ebx
int v6; // edi
char *v7; // edx
int i; // ecx
char v9; // al
float v11; // [esp+10h] [ebp-C8h]
float v12; // [esp+24h] [ebp-B4h]
double v13; // [esp+28h] [ebp-B0h]
double v14; // [esp+30h] [ebp-A8h]
float v15; // [esp+3Ch] [ebp-9Ch]
char Text[16]; // [esp+40h] [ebp-98h] BYREF
char v17[44]; // [esp+50h] [ebp-88h] BYREF
float v18; // [esp+7Ch] [ebp-5Ch]
char v19[32]; // [esp+80h] [ebp-58h] BYREF
char Str[56]; // [esp+A0h] [ebp-38h] BYREF
system("cls");
v14 = 1.3;
v15 = 1.3;
do
{
v13 = -1.2;
v0 = -1.2;
do
{
v11 = v0 * v0;
v12 = v15 * v15;
if ( pow(v12 + v0 * v0 - 1.0, 3.0) - v11 * v15 * v15 * v15 <= 0.0 )
putchar(42);
else
putchar(32);
v18 = v13 + 0.05;
v13 = v18;
v0 = v18;
}
while ( v18 <= 1.2 );
Sleep(0x28u);
putchar(10);
v15 = v14 - 0.1;
v14 = v15;
}
while ( v15 >= -1.1 );
puts("-----Welcome to the landing page-----");
printf("------Enter your name:");
scanf("%s", Str);
printf("------Enter your password:");
scanf("%s", v19);
v1 = strlen(Str);
v2 = 0;
if ( v1 <= 0 )
{
LABEL_12:
v4 = MessageBoxA(0, "Login Successfully!", "UNCTF2021", 0x24u);
if ( v4 == 1 || v4 == 6 )
{
v5 = 0;
qmemcpy(v17, "pqsd`fl{zmpZsag}wdYVkUNC", 24); //flag对这串字符串进行变换得到
v6 = 0;
do
{
v7 = &v17[v5];
for ( i = 2; i >= 0; --i )
{
v9 = *v7;
v7 += 8;
Text[v6++] = v9 ^ 0x16;
}
++v5;
}
while ( v5 <= 4 );
Text[v6] = 0;
MessageBoxA(0, Text, "UNCTF2021", 0x40u);
}
}
else
{
v3 = 0;
while ( v19[v2] == v3 + Str[v2] ) //这里Str中是输入的账号,v19是输入的密码,要满足这样一种关系才能够登录成功
{
++v2;
v3 += 2;
if ( v2 >= v1 )
goto LABEL_12;
}
MessageBoxA(0, "Longin Failed!", "UNCTF2021", 0x40u);
}
return system("pause");
}
写个简单小脚本或者根据上面的账号和密码关系输入相应账号密码
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
int main()
{
char s[] = "pqsd`fl{zmpZsag}wdYVkUNC";
char flag[99];
int i,j;
int v5 = 0,v6=0;
char v9;
do
{
int v7 = v5;
for(i = 2; i>=0; --i)
{
v9 = s[v7];
v7 += 8;
flag[v6++] = v9 ^ 0x16;
}
++v5;
}
while(v5 <= 4);
printf("%s",flag);
return 0;
}
最终flag:flag{refOrL@ve}
rejunk
代码混淆,就只有这两行关键代码
一个小脚本就行
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
int main()
{
char s[] = "WQGULxb>2:ooh95=''twk";
int i,j;
for(i = 0 ; i < strlen(s) ; i++)
{
s[i] ^= i;
s[i] -= 2;
}
printf("%s",s);
return 0;
}
最终flag: UNCTF{b781cbb29054db}
py_trade
手动逆向,可以参考这个[原创]死磕python字节码-手工还原python源码和dis — Python 字节码反汇编器
逆向出来的代码
flag=""
num=[]
k=0
for i in range(len(flag)):
num[i]=(ord(flag[i]) + i) ^ (k % 3 + 1)
num[len(flag) -i - 1] = ((( ord(flag[len(flag) - i - 1]) + len(flag) )- i) - 1 ) ^ (k % 3 + 1)
k+=1
print(num)
#
[115, 120, 96, 84, 116, 103, 105, 56, 102, 59, 127, 105, 115, 128, 95, 124, 139, 49]
然后搞个逆向脚本
out = [115, 120, 96, 84, 116, 103, 105, 56, 102, 59, 127, 105, 115, 128, 95, 124, 139, 49]
flag = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
k = 0
for i in range(18):
flag[i] = (out[i] ^ (k % 3 + 1)) - i
flag[17 - i] = (out[17 - i] ^ (k % 3 + 1) ) + i - 17
k+=1
for j in flag:
print(chr(j),end='')
py_Trad3_1s_fuNny! ,结果加上flag{}提交就行
ezMaze
一个地图题,要注意点的是,他可以斜着跳,,比如左下,右下
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 v3; // rax
char *v4; // rdi
unsigned __int64 v5; // rbx
const char *v6; // rdx
int v7; // eax
int v8; // er9
int v9; // er8
int v10; // edx
char v11; // cl
int v12; // ecx
int v13; // ecx
__int64 v14; // rax
((void (__fastcall *)(int, const char **, const char **))sub_1400011A0)(argc, argv, envp);
dword_140006790[0] = 1; //这里定义了一张地图,可以用win64debug执行完这一段后在内存中查看
dword_140006794 = 1;
dword_1400067B4 = 1;
dword_1400067CC = 1;
dword_1400067EC = 1;
dword_1400067F0 = 1;
dword_1400067D4 = 1;
dword_1400067D8 = 1;
dword_1400067F8 = 1;
dword_140006810 = 1;
dword_14000682C = 1;
dword_140006844 = 1;
dword_140006840 = 1;
dword_140006864 = 1;
dword_140006868 = 1;
dword_140006884 = 1;
dword_1400068A0 = 1;
dword_1400068BC = 1;
dword_1400068DC = 1;
dword_14000689C = 1;
v3 = sub_140001800(std::cout, "Plz inpu7 the P4th :");
std::ostream::operator<<(v3, sub_1400019D0);
v4 = byte_140006720;
v5 = -1i64;
sub_140001AA0(std::cin, -1i64, byte_140006720);
do
++v5;
while ( byte_140006720[v5] );
if ( v5 > 17 ) // flag长度为17
//
{
v6 = "to0 lon9!t0o long!";
goto LABEL_26;
}
if ( v5 < 17 )
{
v6 = (const char *)&unk_140003770;
goto LABEL_26;
}
v7 = dword_140006710;
v8 = 0;
v9 = dword_140006714;
v10 = dword_140006710;
do
{
v11 = *v4;
if ( *v4 == 'A' )
goto LABEL_21;
if ( v11 == 'W' )
{
++v10;
v12 = v7 % 2;
++v7;
goto LABEL_20;
}
if ( v11 == 'E' )
{
++v10;
v13 = v7 % 2;
++v7;
LABEL_16:
dword_140006710 = v7;
if ( v13 )
goto LABEL_23;
goto LABEL_17;
}
if ( v11 != 'D' )
{
if ( v11 != 'X' )
{
if ( v11 != 'Z' )
{
v6 = "What the fuck did you give me?";
goto LABEL_26;
}
--v10;
v12 = v7 % 2;
--v7;
LABEL_20:
dword_140006710 = v7;
if ( !v12 )
goto LABEL_23;
LABEL_21:
--v9;
goto LABEL_22;
}
--v10;
v13 = v7 % 2;
--v7;
goto LABEL_16;
}
LABEL_17:
++v9;
LABEL_22:
dword_140006714 = v9;
LABEL_23:
++v8;
++v4;
}
while ( v8 < v5 );
v6 = "Congratulations on this forced to get the right flag, you entered is the correct answer!";
if ( dword_140006790[7 * v7 + v9] != 1 ) //这里地图7个一行
v6 = "Try it again little unlucky!";
LABEL_26:
v14 = sub_140001800(std::cout, v6);
std::ostream::operator<<(v14, sub_1400019D0);
return 0;
}
画出来的地图,1是可以走的路径,从左上角开始
1100000
0010000
0101100
0011010
0000100
0000100
0011000
0000110
0000010
0001110
0000010
0000001
看了官方wp才知道这是个六边形的迷宫,我当成普通迷宫写了。。。不过问题不大,写出来就行。。
比如W是往下走,但如果再满足v12 == 1 就除了会往下走一格,还会往左走一格
DEWEDXDEWWWEDEWEE
ezDriver
变种tea加密
上半部分是加密,下半部分是解密,这里解题代码已经给你了,只要改改就行
解题脚本
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdbool.h>
#define MX \
((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z))
void btea(unsigned int *a1, int a2, unsigned int *a3) { //解密
unsigned int v3;
int v15;
unsigned int v16;
unsigned int v17;
int v18;
int v19;
int v20;
unsigned int v21;
int v22;
int v23;
int v24;
int v25;
v3 = a1[0];
v15 = -a2; //v15 = 10
v16 = -1640531527 * (52 / v15 + 6); //v16 = 0xcc623af3
//printf("v16 = %x\n",v16);
v17 = v15; //v17 = 10 作为从数组最后开始的下标
do
{
v18 = v15 - 1; //v18 = 9
v19 = (v16 >> 2) & 3;
if ( v15 - 1 > 0 )
{
v20 = a1[v17 - 1]; //v20 = a1[9]
printf("v20 = %X , v17 = %X \n",v20,v17);
v21 = v17 - 1; //v21 = 9从最后一位开始
do
{
v22 = ((16 * a1[v21 - 1]) ^ (v3 >> 3)) + ((a1[v21 - 1] >> 5) ^ (4 * v3));
v23 = v19 ^ (v18--) & 3;
v24 = a3[v23] ^ a1[v21 - 1];
v23 = v3 ^ v16;
v25 = v20;
v20 = a1[v21 - 1];
v3 = v25 - ((v23 + v24) ^ v22);
a1[v21--] = v3;
}
while ( v18 > 0 );
}
*a1 -= ((v3 ^ v16) + (a3[v19 ^ v18 & 3] ^ a1[v17 - 1])) ^ (((16 * a1[v17 - 1]) ^ (v3 >> 3)) + ((a1[v17 - 1] >> 5) ^ (4 * v3)));
v3 = *a1;
v16 += 1640531527;
}
while ( v16 );
}
//xxtea
int main()
{
// test
int i,j;
/*unsigned int v[] = {0x18,0x4E,0x8E,0x7F,
0x2E,0x69,0xB7,0x02,
0xEE,0xAA,0x50,0x39,
0x90,0xDE,0xE5,0x9F,
0xAE,0x4C,0x4D,0x06,
0x93,0x71,0x64,0x20,
0x8B,0x02,0x34,0xB8,
0x3C,0xA1,0x88,0x4A,
0x21,0x67,0x1A,0x37,
0x83,0xD1,0xF2,0xB1};*/
unsigned int v[] = {0x7F8E4E18,0x02B7692E,0x3950AAEE,0x9FE5DE90,0x064D4CAE,
0x20647193,0xB834028B,0x4A88A13C,0x371A6721,0xB1F2D183};
//unsigned key[] = {1, 0,0,0,2,0,0,0, 3,0,0,0, 4,0,0,0};
unsigned key[] = {1,2,3,4};
for(i = 0 ; i < 10; i++)
{
printf("%X \n",v[i]);
}
btea(v, -10, key);
for(i = 0 ; i < 10; i++)
{
printf("%X",v[i]);
}
return 0;
}
我这里输出的是16进制,然候要转成字符串形式74636E756F447B66756F795F6E61775F6F745F74635F615F6F5F707565745F667D3F610
得到tcnuoD{fuoy_naw_ot_tc_a_o_puet_f}?a,
然后每四个字符倒一下就行:unctf{Do_you_want_to_a_cup_of_tea?}
chall
秘钥是2021
codemaker是明文
然后RC4加密一下就得到flag
最终flag:UNCTF{Ts/l3pXiG0Fw}
ezPuzzle
这个想了两天没想出来,只是有些思路