Description of the Exercise:
Imagine that you have just implemented a Java version of a console application called “Password Vault” that helps computer users create and manage their passwords in a secure and convenient way. Before releasing a limited trial version of the application on your company’s Web site, you would like to understand how difficult it would be for a reverse engineer to circumvent a limitation in the trial version that exists to encourage purchases of the full version; the trial version of the application limits the number of password records a user may create to five. The Java version of the Password Vault application was developed to provide a non-trivial application for reversing exercises without the myriad of legal concerns involved with reverse engineering software owned by others. The Java version of the Password Vault application employs 128-bit AES encryption, using Sun’s Java Cryptography Extensions (JCE), to securely store passwords for multiple users—each in separate, encrypted XML files.
Software for the Exercise:
Password Vault Java Windows installer
FrontEnd Plus (java bytecode decompiler)
Jad (java bytecode decompiler) (if you prefer to work at the command-line)
Step1:安装并试用密码管理器
完成安装后,我们首先尝试一下这个密码管理器。可以明显看到选项1是显示当前所有储存的账户密码;选项2是添加新的账户密码。如下图所示,当存储数量达到试用存储的上限后,再尝试添加的话就会显示:"Thank you for trying Password Vault! You have reached the maximum number of records allowed in this trial version."
Step2:解压PasswordVault.jar
明显的,程序的java源程序在PasswordVault.jar中。我们将PasswordVault.jar直接解压,可以看到如下的class文件:
Step3:用FrontEnd Plus反编译PasswordVault.class
反编译PasswordVault.class,用之前得到的“Thank you……”字符串作为关键词搜索,我们不难找到存储数量是否到上限的判断处,如下图:
Step4:用IDA反编译PasswordVault.class
再用IDA反编译PasswordVault.class,按照之前得到的信息,可以找到:
Step5:修改PasswordVault.class文件的十六进制码
现在我们来思考一下,如果判断条件是存储数量>5则不允许再添加,那么如果我们想无限制地使用仅仅加大5是不够的,因为这样仅仅只是加大上限,而不是无限制。我们可以这样更改:存储数量<0则不允许再添加,而存储数量总是>=0的,所以此判断条件是永远不会成立的,这就达到了破解此软件的目的。
那么我们该如何修改class的16进制文件呢?查询资料得知以下原理:
0xa1 if_icmplt 比较栈顶两int型数值大小,当结果小于0时跳转
0xa2 if_icmpge 比较栈顶两int型数值大小,当结果大于等于0时跳转
0xa3 if_icmpgt 比较栈顶两int型数值大小,当结果大于0时跳转
0xa4 if_icmple 比较栈顶两int型数值大小,当结果小于等于0时跳转
0x03 iconst_0 将int型0推送至栈顶
0x04 iconst_1 将int型1推送至栈顶
0x05 iconst_2 将int型2推送至栈顶
0x06 iconst_3 将int型3推送至栈顶
0x07 iconst_4 将int型4推送至栈顶
0x08 iconst_5 将int型5推送至栈顶
我们查看16进制文件,发现上面内容正好得到了验证:
所以,我们按照之前的分析把0x08换成0x03,把0xA1换成0xA3:
Step6:替换原PasswordVault.class文件
用修改后的PasswordVault.class文件替换原jar包中文件:
Step7:验证修改结果
这时候再尝试添加新的账户密码,发现不会受到阻碍:
可以看到,破解成功!
Step1:用FrontEnd Plus反编译原文件
反编译结果如下:
漏洞就在于程序用simpledateformat1去格式化当前时间。这里simpledateformat1为yyyyMM,所以格式化当前时间的结果依然是当前时间,只是形式发生变化。但当simpledateformat1为具体值时,格式化当前时间的结果,就不是当前时间了,而是那个simpledateformat1的值。所以,我们只要将yyyyMM改为201807,即可使当前时间失效,程序中的s4就由201807变化过来,在调用hexStr2Str会输出Welcome。
Step2:通过十六进制编辑器修改
将yyyyMM改为201807:
Step3:运行修改后程序
运行结果如下:
这里我们时间是2019年,但依然输出了Welcome。
Step1:用FrontEnd Plus反编译原文件
反编译结果如下:
分析可知:这题的思路和上一题完全一样,只要我们将yyyy-MM改为2018-07,就可以输出Welcome了。
Step2:通过十六进制编辑器修改
将yyyy-MM改为2018-07:
Step3:运行修改后程序
运行结果如下:
成功输出Welcome对话框。
https://www.mysterytwisterc3.org/en/challenges/level-ii/brute-force-attack-on-triple-des-with-reduced-key-space
由题意,密钥的前几个字符为06年建造用于攻击DES的机器名称。百度一下,就可知道机器名称为COPACOBANA,如下图。
密钥的后六位是6个数字,这里就需要暴力破解了。因为这有106即一百万种可能,程序破解比较慢,我们也不可能去人工观察如此众多的破解结果到底哪个是正确的。所以,在这里,我们认定解密结果中,字母、空格总数最多的那个,即为明文。代码如下:
代码如下:
#coding:utf-8
from Crypto.Cipher import DES3
import re
from binascii import unhexlify
with open('3.txt', 'r') as fp :
data = "".join(fp.read().split()) #split消除一切空格和回车
max1 = 0
for k in range(0, 999999 + 1) :
tmp = str(k).zfill(6) #将k转为字符串,并填充至6位
key ='COPACOBANA' + tmp
cipher = DES3.new(key.encode('utf-8'), DES3.MODE_CBC, "00000000".encode('utf-8'))
mtext = cipher.decrypt(unhexlify(data))# 16进制解码字符串
num = len(re.findall('[a-zA-Z ]'.encode('utf-8'), mtext)) #得到解密后的字母、空格数
if num > max1: #这里认为字母、空格数最多的那个,即为明文
max1 = num
Mtext = mtext
Key = key
print("key:%s" % Key)
print("Mtext:")
print(Mtext)
运行结果:
密钥为COPACOBANA008880。解出的明文,除了第一行有乱码,其他都是可读的。百度一下,即可发现这是How to Break DES for 8,980 Euro这篇论文。
Flag是第一行,通过部分可识别的字符,我们可以判断Flag就是How to Break DES for 8,980 Euro。提交至网站,显示成功通过
Android逆向:
不管是通过反编译由.class文件得到java源代码还是通过反汇编由apk文件生成smali代码来分析程序,我们的最终目的都是找到关键点代码的位置,得到程序运行的基本思路,进而对关键点进行修改或是代码注入。在分析android程序时,我们需要做的是通过程序的AndroidMainfest.xml对程序使用的activity、权限、服务有所了解、关注Application类以及最终定位关键代码。在具体的Android逆向实例中,作者通过采用代码注入得到注册码的方法进行破解,读取程序对应的文件,编写注册机,最后获得破解结果。