Jarvis OJ - Baby's Crack - Writeup
M4x原创,欢迎转载,转载请表明出处
这是我第一次用爆破的方法做reverse,值得记录一下
题目:
分析:
下载后解压有exe和flag.enc两个文件,初步推测flag.enc是用exe加密后的文件,我们只需要分析exe的加密算法,还原flag.enc的明文即可
-
exe无壳,拖到IDA中用F5大法,找到关键代码:
// local variable allocation has failed, the output may be wrong!
int __cdecl main(int argc, const char **argv, const char **envp)
{
int result; // eax@16
char Dest; // [sp+20h] [bp-80h]@16
FILE *v5; // [sp+88h] [bp-18h]@5
FILE *File; // [sp+90h] [bp-10h]@4
char v7; // [sp+9Fh] [bp-1h]@6
int v8; // [sp+B0h] [bp+10h]@1
const char **v9; // [sp+B8h] [bp+18h]@1 v8 = argc;
v9 = argv;
_main(*(_QWORD *)&argc, argv, envp);
if ( v8 <= )
{
printf("Usage: %s [FileName]\n", *v9);
printf("FileName是待加密的文件");
exit();
}
File = fopen(v9[], "rb+");
if ( File )
{
v5 = fopen("tmp", "wb+");
while ( feof(File) == )
{
v7 = fgetc(File);
if ( v7 != - && v7 )
{
if ( v7 > && v7 <= )
{
v7 += ;
}
else if ( v7 <= )
{
v7 += v7 % ;
}
else
{
v7 -= v7 % ;
}
fputc(v7, v5);
}
}
fclose(v5);
fclose(File);
sprintf(&Dest, "del %s", v9[]);
system(&Dest);
sprintf(&Dest, "ren tmp %s", v9[]);
system(&Dest);
result = ;
}
else
{
printf("无法打开文件%s\n", v9[]);
result = -;
}
return result;
} -
代码的逻辑很简单,exe读取文件中的每一个字符,经过加密存储到flag.enc中,加密的方式有三种:
if ( v7 != - && v7 )
{
if ( v7 > && v7 <= )
{
v7 += ;
}
else if ( v7 <= )
{
v7 += v7 % ;
}
else
{
v7 -= v7 % ;
}
fputc(v7, v5);
} 刚开始是想跟进加密的算法推出明文,但后来发现flag.enc中的字符只有52位,而三种加密的算法又很简单,因此完全可以爆破
附上爆破脚本
#coding:utf-8
import string #将密文转化为ascii码值便于处理,当然没有这一步也是可以的
cipher = 'jeihjiiklwjnk{ljj{kflghhj{ilk{k{kij{ihlgkfkhkwhhjgly'
l = map(ord, cipher)
#l = [106, 101, 105, 104, 106, 105, 105, 107, 108, 119, 106, 110, 107, 123, 108, 106, 106, 123, 107, 102, 108, 103, 104, 104, 106, 123, 105, 108, 107, 123, 107, 123, 107, 105, 106, 123, 105, 104, 108, 103, 107, 102, 107, 104, 107, 119, 104, 104, 106, 103, 108, 121] #爆破的范围为所有可打印字符
dic = string.printable #三种加密方式
f1 = lambda x: chr(x - 53)
def f2(x):
for i in dic:
if ord(i) + ord(i) % 11 == x:
return chr(i) def f3(x):
for i in dic:
if ord(i) - ord(i) % 61 == x:
return chr(i) #爆破函数,逐位对密文进行爆破
def crack():
ans = ''
for i in l:
try:
ans += f1(i)
except:
pass try:
ans += f2(i)
except:
pass try:
ans += f3(i)
except:
pass return ans #爆破出的明文是16进制的,还要进行解码
# print crack()
print crack().decode('hex')
-
运行得到flag