题目难度不大,毕竟是取证比赛,查查信息然后连蒙带猜也能做的差不多。
赛后从逆向的角度,对涉及到的几个程序再深入分析一下。
个人赛逆向部分#
exe#
- 在U盘中,你还发现了一个exe文件,但它被锁定,可能需要进行反编译以便进一步检查。参考
David_USB_8GB.e01
,使用x64dbg的字符串搜索(String Search)功能,在Bitlocker.exe
中查找哪个字符串最有可能与显示的登录状态有关?- 承上題,当找到控制登录成功的逻辑代码时,如何修改汇编代码来绕过检查,达到任意输入,都成功登录的效果?
Bitlocker.exe
的正确用户登录名称是?Bitlocker.exe
的正确登录密码是?- 当
Bitlocker.exe
程序尝试显示登录结果(成功或失败)时,使用了哪一种途径来决定显示的消息?- 决定能否解密
Bitlocker Key
的字节的内存偏移量(Memory Offset)(相对于基址"bitlocker.exe")是什么?- 决定能否解密
Bitlocker Key
的内存偏移量(Memory Offset)后,应该如何利用它来进行解密?- 解密后的
Bitlocker Key
是?
从U盘镜像中提取出这个Bitlocker.exe
,先用DIE查一下,无壳,但要留意是GUI程序。
利用DIE自带的字符串功能也可以搜索到相关的字符串。(比IDA中的多了PE头、.text
节、.rsrc
节的字符串)
程序的入口点恰好是WinMain
函数,IDA打开后看这个函数的反编译伪码,只有简单的几行,除去最后的消息处理,只调用了两个函数:
sub_140001620
:注册窗口类,这个窗口类在第二个函数中用于创建窗口。sub_140001700
:CreateWindowExA
创建主窗口,保持update。
在窗口类的定义中可以发现回调函数v2.lpfnWndProc = sub_1400017C0
,进入该函数分析
a2
是uMsg
参数,在windows.h
中可以找到如下的宏定义。结合switch-case
中的值可以推测功能
#define WM_CREATE 0x0001
#define WM_DESTROY 0x0002
#define WM_COMMAND 0x0111
主窗口创建时,产生WM_CREATE
消息,调用sub_140001850
创建一系列的子窗口句柄,体现为输入框,按钮等控件。退出主窗口时则产生WM_DESTROY
消息。
重点放在command
消息,也就是点击按钮时会调用sub_140001AE0
。查看这个函数,发现最后用MessageBoxA
来输出login结果,合理推测是对输入的用户名和密码进行检查。
伪码能直接看到两个字符串常量,分别对应Username
和Password
。代码部分类似memcmp
逐个字符检查。
结果最终保存到v9
中,通过if
判断登录是否成功。对应的汇编是test + jnz
,可以patch成jz
来绕过检查。
后面sub_7FF7CB6F22A0
函数还进行了hash,生成bitlocker key,通过MessageBox输出。但是如果直接运行的话输入正确只会显示Keep going
那段话。在最后可以看到这段代码由硬编码的byte_7FF7CB6F808C
常量控制跳转 (也就是题目中提到决定能否解密Bitlocker Key 的字节),必须要patch修改一下才能输出。
到这里已经梳理出程序的整个逻辑。由于程序会解密key,所以理想的做法就是两次patch来绕过拿key,和题目引导的整个流程一致,不太需要关心加解密的具体实现。否则可能还要分析加密的API及其参数来确定是何种加密方式。
团体赛逆向部分#
赛后检材直接删了,忘了把程序保存到本地。拿着当时的截图简单讲下思路吧
apk#
你现在査看Ben的笔记本电脑,并发现了APK文件。一般而言,APK的关键组成部分是什么?
参考
Ben_Laptop.zip
内的Joshe Investment.apk
,这个APK没有classes.dex
文件,而是有smali
文件,以下哪一个陈述是正确的?(A:这是一个經過反向工程製作的APK)Ben使用了哪个工具包生成恶意APK以控制受害者的设备?
确认哪个
.xml
文件被特别添加为主活动(activity_main)的布局文件?确认被指定为主活动层(activity main layer)
.xml
文件的公共ID?确认应用程序没有要求的权限?
ahmyth/mine/king/ahmyth/
文件夹下的b.smali
文件的主要功能是什么?在
ahmyth/mine/king/ahmyth/
文件夹下的b.smali
文件中,字节数组(Byte Array)在发送到服务器之前执行了哪一系列操作,最终的图像格式是?在
ahmyth/mine/king/ahmyth/
文件夹下的b.smali
文件中,图像在发送到服务器時的压缩比率是多少?在
ahmyth/mine/king/ahmyth/
文件夹下的ConnectionManager.smali
中,sendReq
method的目的是什么?承上题,参考
Ben Laptop.zip
内的Joshe Investment.apk
,C2服务器的IP地址及端口号?
ahmyth/mine/king/ahmyth/
文件夹下的g.smali
文件中,MediaRecorder
被初始化用于录音。如果setAudioSource()
方法使用了错误的参数,会发生什么,且这将如何影响录音过程的功能?
ahmyth/mine/king/ahmyth/
文件夹下的g.smali
文件中,TimerTask
用于在启动MediaRecorder
后调度动作。TimerTask
在这个过程中有什么作用?在
ahmyth/mine/king/ahmyth/
文件夹下的h.smali
文件中,methoda()
和methodb()
的主要功能有什么区别?在
ahmyth/mine/king/ahmyth/
文件夹下的h.smali
文件中,methodb()
需要哪些参数?
在Ben的Laptop的镜像中,Joshe Investment.apk
,jadx反编译后看到符号的混淆比较严重。
查看ahmyth
包,这个应该是远控工具,主活动和主服务也在这个包里面。
在MainActivity
中找SetContentView
对应的layout,可以确定使用的布局xml文件,其id保存在R
类中。
AndroidManifest.xml
可以查到要求的权限。
接下来对apk的反编译代码进行分析。由于代码量较大且程序被误删掉,只浅析一下题目ahmyth/mine/king/ahmyth
中提到的几个部分
b.smali
#
onPictureTaken
函数,推测与相机拍摄图像相关。先调用this.d
释放camera实例,紧接着调用this.e(bArr)
将字节数组解码成bitmap图像,再压缩成JEPG。压缩率是decodeByteArray.compress
的第二个参数。整个JPEG图像以字节流写入json对象并发送。
ConnectionManager
#
看到sendReq
声明了一个b.a.b.e
的实例对象,并用e.a().b()
进行初始化。
分别查看二者的代码实现,在b.a.b.e
中发现“connect”等关键词,推测与某个服务器建立连接。之后分析e.a.b
,找到一串Base64编码过的字符串,解码后即为C2服务器的ip和端口。
g.smali
#
TimerTask
h.smali
#
逆向分析,发现sms
分析sendTextMessage参数
着重分析方法a和方法b
python#
在分析Ben的笔记本电脑时,你从调查人员那里获得了以下信息:在对一名被捕的犯罪集团成员进行审问时获得的情报显示,Ben对John心怀怨恨,因为John扣留了Ben的犯罪收益份额。因此,Ben加密了John的机密文件夹,以限制他的访问。参考
Ben_Laptop.zip
,解密secretExcel.encrypted
的第一步应该是什么?在加密文件
secretExcel.encrypted
中,初始向量 (lnitial Vector)的值是什么?在加密文件
secretExcel.encrypted
中,盐值(SALT)是什么?查看
encrypt.py
代码,如果更改'PBKDF2'
的'count'
参数会产生什么影响?根据分析及计算后,解密
secrectExcel.encrypted
所用的key具体值是什么?
同样在Ben的Laptop。这个和逆向关联可能不是很大,直接给了python源码,但是毕竟涉及到加解密。
找到encrypt.py
,源代码如下:
import os
import sys
from Crypto.Cipher import AES
from Crypto.Protocol.KDF import PBKDF2
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad
def encrypt_file(file_path, password):
salt = get_random_bytes(32)
key = PBKDF2(password, salt, dkLen=32, count=100000000)
file_path = os.path.abspath(file_path)
output_dir = os.path.dirname(file_path)
folder_name = os.path.splitext(os.path.basename(file_path))[O]
encrypted_path = os.path.join(output_dir, f"{folder_name}.encrypted")
os.makedirs(os.path.dirname(encrypted_path), exist_ok=True)
with open(file_path, 'rb') as f_in, open (encrypted_path, 'wb') as f_out:
data f_in.read()
cipher = AES.new(key,AES.MODE_CBC)
f_out.write(cipher.iv)
f_out.write(salt)
encrypted_data = cipher.encrypt(pad(data,AES.block_size))
f_out.write(encrypted_data)
print(f"File encrypted successfully: {encrypted path}")
if __name__ == "__main__":
if len(sys.argv) != 3:
print("Usage: python encrypt.py <file_path> <password>")
sys.exit(1)
file_path = sys.argv[1]
password = sys.argv[2]
encrypt_file(file_path, password)
先基于PBKDF2算法生成伪随机密钥。查看crypto库的文档可以了解到该算法各个参数的作用,count参数代表迭代的次数,影响计算性能和安全性。
生成key之后进行AES-CBC加密。其中初始向量iv
(16 bytes)和加盐salt
(32 bytes)的值依次写入了加密文件的最前面。可以用十六进制编辑器提取出来。
反解出key再解密AES,恢复被加密的excel文件。