题出自:2017年陕西省网络空间安全技术大赛——人民的名义-抓捕赵德汉2
打开题目,是一个.jar的文件
双击他运行看看:
点击,按提示给的xxxx-xxxx-xxxx-xxxx格式输入:
提示incorrect key,知道不对:
既然是jar文件,我们用Java Decompiler反编译工具打开:
看到关键的main(),点进去看反编译代码,不知道那个是关键地方可以看我们刚开始运行程序时的关键字符,找到他:
找到关键的地方了,只要₪₪₪₪₪₪₪₪₪₪₪₪.ℑℌℳ(str)返回1,就可以正确,由于反编译的原因,有些乱码,不要被她迷惑,保持清醒的头脑,知道逻辑就行了,我们下一步要找那个关键的函数了,在左边是函数列表,找到那个₪₪₪₪₪₪₪₪₪₪₪₪函数:
public class ₪₪₪₪₪₪₪₪₪₪₪₪
{
static String ªı_ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static String _ıª = "ZYXWVUTSRQPONMLKJIHGFEDCBA";
public static boolean ℑℌℳ(String 和咊)
{
if ((和咊 != null) && (和咊.length() == 19)) {
ªı_ = System.arraycopy(_ıª, 0, ªı_, 5, 5);
boolean keyGuessWrong = true;
int ȥ = 0;
for (int ƶ = 0; ƶ < 4; ƶ++) {
for (int ẓ = 0; ẓ < 4; ẓ++) {
if (和咊.charAt(ȥ + ẓ) != ªı_.charAt(Start.₪₪₪₪₪₪₪₪₪₪₪₪(ȥ + ẓ, ªı_))) {
keyGuessWrong = false;
}
}
ȥ += 5;
}
return keyGuessWrong;
}
return false;
}
依然有乱码的,但是整体不影响读代码,可以看到首先他验证了我们输入字符串的长度为19,然后做了一个System.arraycopy的操作,System.arraycopy函数在Java里是复制的函数,函数原型:
public static void arraycopy(Object src,
int srcPos,
Object dest,
int destPos,
int length)
其中:src表示源数组,srcPos表示源数组要复制的起始位置,desc表示目标数组,length表示要复制的长度。
网上看看了很多,没见此函数有返回值,很奇怪,就继续往下做了,没太在意,这里有一个很大的坑,一会说。
后面代码意思就是将输入的字符串的第ȥ + ẓ位和ªı.charAt(Start.₪₪₪₪₪₪₪₪₪₪₪₪(ȥ + ẓ, ªı))的比较,相同则继续比较继续,不同就返回false,charAt(ȥ + ẓ)函数是:
charAt(int index)方法是一个能够用来检索特定索引下的字符的String实例的方法.
charAt()方法返回指定索引位置的char值。索引范围为0~length()-1.
现在就明确了,只要求出ªı.charAt(Start.₪₪₪₪₪₪₪₪₪₪₪₪(ȥ + ẓ, ªı))就行了,而这个也是由start里面的₪₪₪₪₪₪₪₪₪₪₪₪(ȥ + ẓ, ªı_)函数的返回值做的索引,我们去看一下这个函数:
public static int ₪₪₪₪₪₪₪₪₪₪₪₪(int ৲, String ₢)
{
return ﷼௹૱(৲) % ₢.length();
}
private static int ﷼௹૱(int ৲) {
if (৲ > 2) return ﷼௹૱(৲ - 1) + ﷼௹૱(৲ - 2); return 1;
}
}
又是一堆乱码 不过没关系,大概意思还是能看懂,₪₪₪₪₪₪₪₪₪₪₪₪函数返回值是一个数值,干好作为charAt()的参数,为ªı_的索引值,下面我们就来复现这个函数
def h(a,s):
return k(a)%len(s)
def k(a):
if a>2:
return k(a-1)+k(a-2)
return 1
加上上面函数的逻辑,可以写出脚本:
a="ABCDEZYXWVKLMNOPQRSTUVWXYZ"
b="ZYXWVUTSRQPONMLKJIHGFEDCBA"
for i in c:
i=i>>1
d+=chr(i+15)
print(d,end='')
print()
def h(a,s):
return k(a)%len(s)
def k(a):
if a>2:
return k(a-1)+k(a-2)
return 1
z=0
for i in range(4):
for j in range(4):
print(a[h(z+j,a)],end='')
z+=5
但是发现求出来的key不对,百思不得其解,然后想起来开始那个拷贝函数有点问题,上网一搜也没发现他也没有返回值啊,这就是本题最大的坑点,这个arraycopy函数是出题者为了混淆视听,自己写的一个函数,而不是Java系统里那个同名的函数,而且进去那个函数发现,那几各参数根本没用,只是为了迷惑我们这些傻孩子:
他在这里就调用了start里面的main函数,进到mian()函数里面:
class Start
{
public static String main(String[] args)
{
String x = "";
for (int $ : "vȾ¤ÊʬÆÆÊv̤ʲʲÀΤ¨¸¬".toCharArray())
x = x + (char)(($ >> 1) + 15); return x;
}
懵了,怎么一串乱码,然后将$右移1位后+15,赋给x,最终返回字符串x,也就是说,我们起初的ªı字符串没卵用,这就可以理解arraycopy为什么会有返回值了,返回的x赋值给了ªı,但问题是,”vȾ¤ÊʬÆÆÊv̤ʲʲÀΤ¨¸¬”乱码是什么?很难想象他是Unicode转码转换得到的,网上有在线工具,我们用它转码一下:
得到一串字符,就是我们要找的数据,toCharArray()函数:将字符串转换为字符数组。
所以这时候的脚本可以写出来了:
#a="ABCDEZYXWVKLMNOPQRSTUVWXYZ" 幌子真坑,其实没用
#b="ZYXWVUTSRQPONMLKJIHGFEDCBA"
c=[118,200,190,164,202,202,172,198,198,202,118,204,164,202,178,202,178,192,206,164,168,184,172]#"vȾ¤ÊʬÆÆÊv̤ʲʲÀΤ¨¸¬" unicode转码
d=''
for i in c:
i=i>>1
d+=chr(i+15)
print(d,end='')
print()
def h(a,s):
return k(a)%len(s)
def k(a):
if a>2:
return k(a-1)+k(a-2)
return 1
z=0
for i in range(4):
for j in range(4):
print(d[h(z+j,d)],end='')
z+=5
最后得到key:sssntrtktceaakJr
不要忘了格式:sssn-trtk-tcea-akJr
测试一下:
真不容易啊!太坑