traditional
analysis
附件是一个无壳elf64和一个flag.enc文件,猜测是要对flag.enc文件进行解密。
main函数有一个call cs:off_564C6050EB00,猜测是rust、nim之类的语言,通过搜索字符串发现有.rs可以判断是rust的程序。
直接进入到sub_564C604BFA40分析,发现这个函数汇编层面比较复杂,F5也不是很清晰。
在Linux上尝试运行elf文件:
发现触发了rust的panic,其中'We lost the flag!: Os { code: 2, kind: NotFound, message: "No such file or directory" }'引起了我们的注意,应该是程序在读取文件时发现没有找到flag文件。
我们重新在ida搜索字符串,发现了flag.txt,由此可以推断:程序读取flag.txt,将其加密,然后将加密结果存入flag.enc。另外使用findcrypt发现程序里面有base64 table。
接下来就是动态调试,在sub_564C604BFA40开头下好断点,在开始之前我还在程序同级目录下创建了flag.txt文件,写入了helloworld123321。
此处在flag.txt文件不存在时会跳转到loc_555870DE126D,也就是文件不存在的情况。
此处执行完call cs:off_555870E2FF90后,会发现rsp+148h+flag_txt_data存储了文件内容的指针,即helloworld123321,说明该函数负责读取文件。
另外,call b64encode_564C604C19A0执行完之后在rsp+148h+src里发现了helloworld123321base64编码后的字符串aGVsbG93b3JsZDEyMzMyMTAw。
call cs:memcpy_ptr是将This is the flag:和aGVsbG93b3JsZDEyMzMyMTAw进行拼接,
接下来还将 Just decode it :P拼接到新字符串末尾,并将整体字符串进行逆序。
得到了字符串This is the flag: aGVsbG93b3JsZDEyMzMyMTAw Just decode it :P,逆序后就是P: ti edoced tsuJ wATMyMzMyEDZsJ3b39GbsVGa :galf eht si sihT。
接下来是一个循环,对字符串的每一个字符进行依次遍历,并根据各种情况对字符进行计算,将计算结果组成新的字符串。
大致的计算方法是:
1 | ' ' -> '/' |
循环结束后,就是本题思路最有意思的地方了,程序将上面循环计算得到的结果作为base64解码的输入,并将解码的结果写入flag.enc文件中。
script
1 | import base64 |
因为时间匆忙,这个脚本写的不是很好,最后需要自己手动补一个}。
Figole
analysis
一个apk文件,直接在手机上安装可以看到就是一个输入并检测。
使用jadx打开。
通过manifest文件发现入口在com.example.shctf.DActivity,手机点击check按钮之后会执行m210lambda$onCreate$0$comexampleshctfDActivity,另外secret、key通过l1、l2两个方法计算得到。
我们先看l1方法,cn通过base64解码得到,com.example.shctfdex.UT是很明显的java类,s是app的timesnewroman.ttf文件的路径,可以在jadx的资源文件/assets下发现。try代码块可以发现是利用java反射获取并调用com.example.shctfdex.UT的gf方法。
l2方法同理。
1 | public String l1(Context context) { |
我们把timesnewroman.ttf用jadx导出,可以发现是一个dex文件。那么我们直接用jadx打开:
com.example.shctfdex.UT的gf方法调用了gd方法,从数据库中读取数据,也就是apk里面的calibri.ttf文件。
1 | public String gd() { |
读取数据库的方法如下:(脑子抽了把calibri.ttf重命名成calibri.ttf.dex,可以忽略)
通过以上方法分析l1、l2可以找到secret和key的值,接下来分析加密部分。
m210lambda$onCreate$0$comexampleshctfDActivity里的result通过l3计算得到,里面调用了com.example.shctfdex.DX的ech方法。另外,l3的最后一个参数需要cdec方法计算得到,就是一个xor操作。
1 | public String ech(String message, String s) { |
可以看出就是AES加密,Mode为CBC,aes key和aes iv需要通过getK计算得到。
在动手之前先整理下程序的流程:
- secret 通过 l1 计算得到
- key 通过 l2 计算得到
- 将 secret、key传递给
m210lambda$onCreate$0$comexampleshctfDActivity - flag 就是我们的输入
- result 通过 l3 计算得到,将flag和
cdec(q)以参数传递,这里的q就是key- cdec函数的参数是一个hexstring,将参数转换成整数数组,并将每一个元素进行异或加密
- l3 调用了 ech 方法,AES的Key和IV需要getK方法进行计算
- 将 y (也就是secret)与result进行比较
script
1 | import base64 |