Flash Encrypt
第一次做flash逆向的题目,不过这个题目还是比较简单的,简单搜集了一下得到了一个工具:https://github.com/jindrapetrik/jpexs-decompiler
跑起来之后大概这样
翻了下几个目录,得到几个主要的信息:
- 这个swf有7帧,前六帧都需要输入一个数字然后摁按钮确认
- 第七帧是答案,猜想是前六帧输对了调到第七帧出答案
- 前六帧的按钮都有对应的处理脚本,
Action Script
,可读性很高
简单读了下发现是这样一个逻辑:
在第1帧里面:
所以第1帧输入1456
,跳到第3帧
然后跟进第3帧:
所以第3帧输入25
,跳到第4帧,
然后跟进第4帧:
所以第4帧输入44
,跳到第2帧,
然后跟进第2帧:
所以第4帧输入8
,跳到第6帧,关于这个spw和spwd是算最后的key的,所以可以不用管具体怎么算的,因为最后会打印答案的。
然后跟进第6帧:
所以第6帧输入88
,跳到第5帧,
然后跟进第5帧:
最后输入20546
,跳到最后一帧打印答案
MetroApp
做题之前先说一下环境安装过程吧,好歹折腾了快俩小时,头疼。题目的readme提示了要win8。
首先在MSDN上下镜像,我用的是这个:
起一个管理员权限的powershell,先设定可以执行ps脚本,再设定运行不受信任的用户发布的软件
set-executionpolicy remotesigned
Set-ExecutionPolicy -ExecutionPolicy Unrestricted
然后证书有效期注意
调整系统时间为2013年,之后用powershell
运行ps1脚本,然后就会弹出一个框要链接服务器获取win8开发者许可证,这个时候先别点我同意
,因为要连接服务器,需要把系统时间恢复回来,然后再点我同意,之后登录Microsoft账户,然后很快就弹出一个框:
然后关闭之后可能会失败,这个时候不慌,因为win8开发者许可证已经拿到了,我们把系统时间重新回到2013年,然后重新跑一次ps1脚本,然后就安装成功了:
然后查了下,这个appx后缀其实就是个皮包的zip,直接按zip解压就行了,然后看到一个MetroApp.exe
,放进ida里面,搜字符串找到了判断的关键位置:
然后想着动态调试,很迷很迷,没有调过类似的,并没有经验,每次调试器附加上去之后,只要暂停,一般不过10多秒钟,程序就自动退出了,非常头疼,而且经过调试之后发现上述找到的关键位置应该是个还不够:
即便开头以MERONG
开头也是wrong,说明后面还有进一步的判断,
这里用的各种windowsxxxx
的api都是对HSTRING
结构体操作,从多次调试来看,如下下图的前20字节:
第4-7代表HSTRING
长度,第16-19字节代表实际的UTF-16
的字符串的地址。
然后继续往下看代码,整个代码量太大了,而且动态调试应该是我没有掌握到方法,最多只能暂停住进程10来秒的样子,一旦超了进程就退出了。
这里要注意调试的线程是主线程,通过调用堆栈可以定位到用户空间的代码,然后搜索关键字符串例如
wrong
就能找到具体的代码位置,然后下断点就能调试
进过一番调试测试,终于定位到了一个奇怪的地方:
对应的反编译代码如下:
这三个都是对应的我们输入的字符串,再看看接下来这个递归式子,
v80是个计数器,在while之前被置为0,每一轮循环自加一,v50,v51,v52
都是输入。考虑到其中的字符串编码是UTF-16,每一个字符对应两个字节,所以换算一下,递归式如下:
input[i+1] = byte_4307A8[i] ^ rol(input[i] , input[i] & 7)
Readme.txt
提示了说答案是大写字母+数字
那就很简单了,写个深搜直接爆破所有答案,由于不知道长度,暂时用15来爆破:
byte_4307A8=[0x77,0xAD,0x07,0x02,0xA5,0x00,0x29,0x99,0x28,0x29,0x24,0x5E,0x2E,0x2A,0x2B,0x3F,0x5B,0x5D,0x7C,0x5C,0x2D,0x7B,0x7D,0x2C,0x3A,0x3D,0x21]
v80=0
stringtable="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
ans=""
length=15
def rol(lst_int, k):
lst=list('{:0>8}'.format(bin(lst_int)[2:]))
tmp= lst[k:] + lst[:k]
tmp2=int("0b"+"".join(i for i in tmp),2)
return tmp2
def search(char,i,ans):
print(char,i,ans)
if i==length:
print(ans)
input("")
return
else:
for j in stringtable:
if ord(j) == byte_4307A8[i&7]^rol(ord(char),ord(char)&7):
search(j,i+1,ans+j)
return
for i in stringtable:
search(i,0,i)
结果如下:
答案也就是D34DF4C3
虽然乱七八糟把答案整出来了,但是几个地方还是没弄懂
- 为什么附加到MetroAPP上一定时间之后程序会自动退出?
- 从结果来看,最开始的初始化
Correct
和Wrong
的HSTRING
明显就是幌子,但是真实的判断点及输出点哪儿?
- 从结果来看,最开始的初始化
- 如何正常调试
MetroAPP
?
- 如何正常调试
CRC1
最近时间实在太碎了,这类型的题先留坑,有整块时间再来看。
Multiplicative
一个2kb不到的jar文件,直接放到jd里面一看,空空如也。。。
不知道是版本还是混淆的原因,那就换一个在线反编译网站java Decompilers online
六种反编译器,JDCore出不来,但是CFR出来了,代码如下:
/*
* Decompiled with CFR 0.139.
*/
import java.io.PrintStream;
public class JavaCrackMe {
public static final synchronized /* bridge */ /* varargs */ strictfp /* synthetic */ void main(String ... arrstring) {
try {
System.out.println("Reversing.Kr CrackMe!!");
System.out.println("-----------------------------");
System.out.println("The idea came out of the warsaw's crackme");
System.out.println("-----------------------------\n");
long l = Long.decode(arrstring[0]);
if ((l *= 26729L) == -1536092243306511225L) {
System.out.println("Correct!");
} else {
System.out.println("Wrong");
}
}
catch (Exception exception) {
System.out.println("Please enter a 64bit signed int");
}
}
}
那就很简单了,-1536092243306511225=2**64-1536092243306511225=16910651830403040391
但是16910651830403040391/26729
不能整除,考虑到无符号long
型的数据最大为2**64-1
,那就多叠加几个2**64
如下:
for i in range(10000000):
if (-1536092243306511225+2**64+i*2**64)%26729==0:
print((-1536092243306511225+2**64+i*2**64)//26729)
print(2**64-(-1536092243306511225+2**64+i*2**64)//26729)
exit()
得到结果9468659231510783855
,但是被说不是64bit signed int
,那就转换成负数-(2**64-9468659231510783855)=8978084842198767761
,
最终答案就是-8978084842198767761
CRC2
同留坑