BUUCTF中的[ACTF新生赛2020]rome
下载查成分,无壳32位
直接ida _main函数,没有东西,点进 func()函数查看
这里一眼看到凯撒加密,妥妥的送分题。先分析代码。
int func()
{
int result; // eax
int v1[4]; // [esp+14h] [ebp-44h]
unsigned __int8 input_str; // [esp+24h] [ebp-34h] BYREF
unsigned __int8 v3; // [esp+25h] [ebp-33h]
unsigned __int8 v4; // [esp+26h] [ebp-32h]
unsigned __int8 v5; // [esp+27h] [ebp-31h]
unsigned __int8 v6; // [esp+28h] [ebp-30h]
int v7; // [esp+29h] [ebp-2Fh]
int v8; // [esp+2Dh] [ebp-2Bh]
int v9; // [esp+31h] [ebp-27h]
int v10; // [esp+35h] [ebp-23h]
unsigned __int8 v11; // [esp+39h] [ebp-1Fh]
char v12[29]; // [esp+3Bh] [ebp-1Dh] BYREF
strcpy(v12, "Qsw3sj_lz4_Ujw@l"); // 原始密文
printf("Please input:");
scanf("%s", &input_str); // 用户输入flag位置
result = input_str;
if ( input_str == 65 )
{
result = v3;
if ( v3 == 'C' )
{
result = v4;
if ( v4 == 'T' )
{
result = v5;
if ( v5 == 'F' )
{
result = v6;
if ( v6 == '{' )
{
result = v11;
if ( v11 == '}' ) // 这几个if判断输入是不是CTF框架
{
v1[0] = v7;
v1[1] = v8; // 这里就是框架里面的内容,只不过用数组来存储
v1[2] = v9;
v1[3] = v10;
*(_DWORD *)&v12[17] = 0;
while ( *(int *)&v12[17] <= 15 )
{
if ( *((char *)v1 + *(_DWORD *)&v12[17]) > 64 && *((char *)v1 + *(_DWORD *)&v12[17]) <= 90 )// 大写字母偏移
*((_BYTE *)v1 + *(_DWORD *)&v12[17]) = (*((char *)v1 + *(_DWORD *)&v12[17]) - 51) % 26 + 65;
if ( *((char *)v1 + *(_DWORD *)&v12[17]) > 96 && *((char *)v1 + *(_DWORD *)&v12[17]) <= 122 )// 小写字母偏移
*((_BYTE *)v1 + *(_DWORD *)&v12[17]) = (*((char *)v1 + *(_DWORD *)&v12[17]) - 79) % 26 + 97;
++*(_DWORD *)&v12[17];
}
*(_DWORD *)&v12[17] = 0;
while ( *(int *)&v12[17] <= 15 )
{
result = (unsigned __int8)v12[*(_DWORD *)&v12[17]];
if ( *((_BYTE *)v1 + *(_DWORD *)&v12[17]) != (_BYTE)result )// 判断是否和我们输入的一样
return result;
++*(_DWORD *)&v12[17];
}
return printf("You are correct!");
}
}
}
}
}
}
return result;
}
然后这里就有两个思路了,第一种就是计算偏移量进行逆向倒推出flag。第二种就是暴力破解(这个是我一开始逆向没出来看了大佬的文章)。
这里先讲第一种方法。
先计算偏移量,看源码大写字母和小写字母的偏移量是不同的。
ASCII表
先写出正常凯撒加密的代码假设偏移量为先右偏移了4,W为输入的明文,E为加密后的密文
W=input("输入密文")
E=chr((ord(W)-64+4)%26+64)
print(E)
这里没有偏移就是:
W=input("输入密文")
E=chr((ord(W)-64)%26+64)
print(E)
分析大写字母的:
这里题目中的:
这里计算方法就是用题目中的-51减去-64加上题目中的65-64得出偏移量为14
偏移量=-51-(-64)+65-64
分析小写字母的同理:
这里计算方法就是用题目中的-79减去-64加上题目中的97-64得出偏移量为18
偏移量=-79-(-64)+97-64
然后可以编写exp了:
def reverse():
flag="Qsw3sj_lz4_Ujw@l"
result=[]
flag1=""
for i in flag:
if ord(i)>64 and ord(i)<=90:
result.append(chr(((ord(i)-64)-14)%26+64))
elif ord(i)>96 and ord(i)<=122:
result.append(chr(((ord(i)-97)-18)%26+97))
else:
result.append(i)
for i in range(len(result)):
flag1 += flag1.join(result[i])
print("flag{"+flag1+"}")
reverse()
运行结果flag{Cae3ar_th4_Gre@t}
第二种方法,暴力破解,就不需要分析出偏移量了。
a= 'ACTF{'
enc='Qsw3sj_lz4_Ujw@l'
s=''
for i in range(len(enc)):
for n in range(128):
j=n
if j >64 and j<=90:
j=(j-51)%26+65
if j>96 and j<=122:
j= (j-79)%26 +97
if j==ord(enc[i]):
a=a+chr(n)
print(a+'}')
ACTF{Cae3ar_th4_Gre@t}