CyberTruck Challenge 2019 challenge 1
总结
1.此题不像之前的题会用一个Toast弹出FLAG,flag是静态的或者用Frida动态获取的 。
2.学会使用Frida对程序进行hook和注入,动态获取程序中函数的返回值。
参考:CyberTruck Challenge 2019 — Android CTF
challenge1
- to unlock car1. “DES key: Completely Keyless. Completely safe”
- 50pts: There is a secret used to create a DES key. Can you tell me which one?
- 100pts: There is a token generated at runtime to unlock the carid=1. Can you get it? (flag must be submitted in hexa all lowercase)
- 题目链接
- 简而言之就是说要找到DES加密的密钥以及产生的Token
测试APP
- 安装App后打开,发现主要有三个可交互的控件,两个switch一个button:
- 因为题目中说token是解锁时产生的,所以点击下UNLOCK按钮出现一个toast:
- 没啥可用信息,开始反编译
静态flag
- 首先用apktool反编译生成smali文件并用dex2jar生成整个APK的jar文件用jd-gui打开。
- 从Manifest文件中找到启动的Activity
- 在jd-gui中查看其反编译代码,发现定义了三个组件的功能,分析按钮的功能,找到调用的函数:
- 其中一个函数名字正是chanllenge1,进入该函数,发现依次调用了generateKey,以及使用DES进行加密的generateDynamicKey函数:
- 而字符串
s3cr3t$_n3veR_mUst_bE_h4rdc0d3d_m4t3!
用来生成DES密钥加密字符串CyB3r_tRucK_Ch4113ng3
- 所以chanllenge1的静态flag为
s3cr3t$_n3veR_mUst_bE_h4rdc0d3d_m4t3!
动态flag
- 这里使用frida进行hook获取点击按钮后generateDynamicKey函数的返回值。
- 编写脚本如下:
import frida, sys
#因为一个字节是8位转换为16进制至少由两个数字。所以有一个数字的话加一个0
def append_zero(hex):
if len(hex) == 1:
return '0'+hex
return hex
#将数字转换为16进制,负数转为正数
def on_message(message, data):
if message['type'] == 'send':
byte_array = message['payload']
flag = ""
for byte in byte_array:
if byte < 0:
flag += append_zero(str(hex(byte & 0xff))[2:])
else:
flag += append_zero(str(hex(byte))[2:])
print("[*] {}".format(flag))
else:
print(message)
#js 脚本
jscode = """
#frida的main,注意:所有的脚本必须放在这里面
Java.perform(function(){
#Java.use:动态获取一个类的对象,为以后改变对象方法的实现(此时类为org.nowsecure.cybertruck.keygenerators.Challenge1)
var Challenge1 = Java.use('org.nowsecure.cybertruck.keygenerators.Challenge1');
#修改函数名为generateDynamicKey,参数为byte[]类型的函数的实现
Challenge1.generateDynamicKey.overload('[B').implementation = function(b){
#获取函数返回值
var result = this.generateDynamicKey(b);
console.log("[->] Flag1 Captured...");
send(result);
return result
};
});
"""
#通过调用frida.get_usb_device()方法来得到一个连接中的USB设备(Device类)实例然后获取一个session
process = frida.get_usb_device().attach('org.nowsecure.cybertruck')
script = process.create_script(jscode)
#调用Script类的on()方法添加一个消息回调,第一个参数是信号名,乖乖传入message就行,第二个是回调函数
script.on('message', on_message)
#加载创建好的javascript脚本
script.load()
# 读取系统输入
sys.stdin.read()
- 在安卓端打开执行frida-server,执行脚本后点击按钮。生成最后的动态flag为: