目录
不一样的flag_迷宫
SimpleRev_小端序
Java逆向解密
luck_guy
JustRE
刮开有奖_特殊加密
简单注册器
pyre
觉得这篇文章不错的话就收藏、点赞、评论、关注我吧~
相关推荐:
1-8题详解博客 看这里→ BUUCTF逆向1-8题wp
逆向工具下载 点这里→ 爱盘 - 在线破解工具包
逆向入门博客 看这里→ 逆向入门规划
分析代码
11:给出字符长度为25的字符串
14-19:打印提示信息。由此可知字符为迷宫,25个字符可以构造成边长为5的字符迷宫
20-48:完善程序逻辑,可不用分析
49-56:按r键将数字转换为字符,可知在此迷宫中,移动到“1”处会中断游戏,移动到“#”处则通关游戏,同时可知其他字符时可为通关路径
根据所给字符进行换行排列,构成迷宫,移动路径如下:
*1111
01000
01010
00010
1111#
下下下右右上上右右下下下
即为:222441144222。此为flag
此文件为elf文件,是小端序存储(wlf文件一般无后缀名)
小端序存储时的字符串需要逆序:
当早已存储在变量中,或代码中的函数中,此时无需逆序;
当对声明的变量赋值,且为小端序时,需要逆序(如下方代码情况)
分析代码,每行函数及变量处理结果见注释中标识。有字符串变量key、text,以及输入字符串变量v1经过处理最终存入str2中。即v1与key相运算后存入str2中,将str2与text对比相同即为正确输入,而其中所需要输入的v1即为flag。
编写程序爆破出flag。通过for循环遍历ASCII码与key运算,将每次处理后的值与text的字符逐个对比,相同后则输出字符串,即可得到flag的值
#include
int main()
{
char text[10] = "killshadow";
char key[10] = "adsfkndcls";
int v3 = 10;
int v5 = 10;
int i, j;
for (i = 0; i < 10; i++)
{
for (j = 0; j < 128; j++)
{
if (j <= '`' || j > 'z')
{
if (j > '@' && j <= 'Z')
{
if ((j - 39 - key[v3 % v5] + 97) % 26 + 97 == text[i])
{
printf("%c", j);
v3++;
break;
}
}
}
else
if ((j - 39 - key[v3 % v5] + 97) % 26 + 97 == text[i])
{
printf("%c", j);
v3++;
break;
}
}
}
}
KLDQCUDFZO
使用recaf工具打开
编写脚本
KEY = [180, 136, 137, 147, 191, 137, 147, 191, 148,
136, 133, 191, 134, 140, 129, 135, 191, 65]
s = ""
for i in range(len(KEY)):
s += chr(KEY[i] - 64 ^ 0x20)
print(s)
分析代码
10-14行是先获取时间戳,然后获得随机数,这是伪随机,与flag处理代码关联不大
代码主要内容为处理字符串,可以推测出,主要步骤顺序是:
case 4:将待处理的字符串初始化
case 5:处理相应的字符串
case 1:输出已知字符串f1与处理后的f2即为flag
编写程序
方法一:用python写
f1 = "GXY{do_not_"
f2 = "icug`of\x7F"
f2 = list(f2)
for j in range(8):
if ( j % 2 == 1 ):
f2[j] = chr(ord(f2[j]) - 2 )
else:
f2[j] = chr(ord(f2[j]) - 1 )
f2 = ''.join(f2)
print(f1,f2)
方法二:用C写
#include
int main()
{
char f1[] = "GXY{do_not_";
char f2[] = "icug`of\x7F";
int j;
for (j = 0; j <= 7; ++j)
{
if (j % 2 == 1)
f2[j] -= 2;
else
--f2[j];
}
printf("%s%s",f1,f2);
}
GXY{do_not_hate_me}
不言而喻
分析代码
首先输入字符串string
首先使用sub_4010F0对10个字节的字符进行加密(由于这10字节大小的变量连续存储存储,所以只需以第一个变量v7为操作数即可)-> v7~v16
分两次获取v18。
第一次v18被string索引为5、6、7的字符分别赋值,最终被sub_40100加密后传给v4。第二次v18被string索引为2,、3、4的字符分别赋值,最终被sub_40100加密后传给v5。
点击sub_40100函数可以推测为base64加密(Base64编码使用了一个由64个字符组成的字符集,通常包括A-Z、a-z、0-9和+/。这些字符被赋予了对应的数值,用于表示字节的值。 Base64编码字符串的长度不为4的倍数,需要使用=填充。)
随后进入if判断语句,与输入字段进行对比。
前三个字符与加密的字符相关,加密后进行相关运算即可(运算脚本建议使用C语言编写,因为对于ASCII码运算更方便,Python需要使用函数)。
后六个字符串为base64加密后的,两组分别解密即可。
sub_4010F0未知加密方式,但可根据点开的伪代码编写C语言脚本
int占四个字节,所以伪代码有 i*4,转换C语言代码可以视为是i
#include
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 = i;
v6 = i[a1];
if ( a2 < result && i < result )
{
do
{
if ( v6 > a1[result])
{
if ( i >= result )
break;
++i;
a1[v5] = a1[result];
if ( i >= result )
break;
while ( a1[i] <= v6 )
{
if ( ++i >= result )
goto LABEL_13;
}
if ( i >= result )
break;
v5 = 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 str[] = "ZJSECaNH3ng";
sub_4010F0(str,0,10);
printf("%s", str);
return 0;
}
使用jadx打开apk文件,分析源码
flag为处理后的bbb字符串
截取源码在java环境中运行,得到flag
public class test {
public static void main(String[] args){
char[] x = "dd2940c04462b4dd7c450528835cca15".toCharArray();
x[2] = (char) ((x[2] + x[3]) - 50);
x[4] = (char) ((x[2] + x[5]) - 48);
x[30] = (char) ((x[31] + x[9]) - 48);
x[14] = (char) ((x[27] + x[28]) - 97);
for (int i = 0; i < 16; i++) {
char a = x[31 - i];
x[31 - i] = x[i];
x[i] = a;
}
String bbb = String.valueOf(x);
System.out.print(bbb);
}
}
59acc538825054c7de4b26440c0999dd
可以在在线网站反编译pyc文件为py文件:pyc反编译
也可以使用(python3.8) uncompyle6 库 工具:
pip3 install uncompyle6 -i https://pypi.tuna.tsinghua.edu.cn/simple
uncompyle6 -o attachment.py attachment.pyc
分析代码
源代码通过逐字符遍历,使用先加法后取余的方式做了第一次加密,又通过逐字符遍历,使用顺序相邻异或运算的方式做了第二次加密。
编写脚本
code = ['\x1f', '\x12', '\x1d', '(', '0', '4', '\x01', '\x06', '\x14', '4', ',', '\x1b', 'U', '?', 'o', '6', '*', ':', '\x01', 'D', ';', '%', '\x13']
flag = ''
for i in range(len(code) - 2, -1, -1):
code[i] = chr(ord(code[i]) ^ ord(code[i + 1]))
for i in range(len(code)):
code[i] = chr((ord(code[i]) - i) % 128)
flag += code[i]
print(flag)
首先对第二次加密进行解密,因为两次异或运算等于本身,所以解密是对code语句进行一次逆序异或运算,这里注意索引范围(索引i最大为lenth-1,但是运算的方程中需要引用i+1,所以索引i最大需变为为lenth-2)。
然后再对第二次加密进行解密,直接将其中的加号换为减号即可(此处还对反编译中的冗余部分做了化简)。最终运行代码,即可得到flag。
GWHT{Just_Re_1s_Ha66y!}