首页
社区
课程
招聘
[原创]解题思路(fXXl)
发表于: 2015-1-25 22:38 2289

[原创]解题思路(fXXl)

2015-1-25 22:38
2289
题目1
使用dex2jar和jd-gui来反编译apk:
$ dex2jar AliCrackme_1.apk
$ jd-gui AliCrackme_1-dex2jar.jar

在onClick方法中可以看到程序将用户的输入和一个字符串的表使用bytesToAliSmsCode这个方法进行了转换,并且将转换所用的表、转换后的密码、转换后的输入使用log输出。
MainActivity类不仅包含了bytesToAliSmsCode这个加密的方法,而且还有其相应的解密方法:bytesToAliSmsCode。
第一个想法是通过smali注入来调用bytesToAliSmsCode,后来想到可以直接把函数拷贝出来,写到个Java程序调用就行了,参数可以在log中找到。
public class Ali1 {
  private static String table = "一乙二十丁厂七卜人入八九几儿了力乃刀又三于干亏士工土才寸下大丈与万上小口巾山千乞川亿个勺久凡及夕丸么广亡门义之尸弓己已子卫也女飞刃习叉马乡丰王井开夫天无元专云扎艺木五支厅不太犬区历尤友匹车巨牙屯比互切瓦止少日中冈贝内水见午牛手毛气升长仁什片仆化仇币仍仅斤爪反介父从今凶分乏公仓月氏勿欠风丹匀乌凤勾文六方火为斗忆订计户认心尺引丑巴孔队办以允予劝双书幻玉刊示末未击打巧正扑扒功扔去甘世古节本术可丙左厉右石布龙平灭轧东卡北占业旧帅归且旦目叶甲申叮电号田由史只央兄叼叫另叨叹四生失禾丘付仗代仙们仪白仔他斥瓜乎丛令用甩印乐";

  private static String pw = "义弓么丸广之";
  private static byte[] aliCodeToBytes(String paramString1, String paramString2) {
    byte[] arrayOfByte = new byte[paramString2.length()];
    for (int i = 0; ; i++)
    {
      if (i >= paramString2.length())
      return arrayOfByte;
      arrayOfByte[i] = ((byte)paramString1.indexOf(paramString2.charAt(i)));
    }
  }

  public static void main(String[] args) {
    byte[] pass = aliCodeToBytes(table, pw);
    System.out.println(new String(pass));
  }
}

答案:581026

题目2
直接对apk使用dex2jar会报错,将classes.dex从apk中解压。使用jd-gui可以看到程序使用securityCheck这个方法对输入做验证。
使用ida逆向动态链接库,发现是直接将输入与 off_628C的字符串进行比对, off_628C的字符串是wojiushidaan,但是提交提示答案不正确。应该是在某个时候做了改动。
既然是普通的字符串对比,那么动态调试一下就行了。但是我是安卓新手。。。暂时不会动态调native程序。。。
既然动态调还得找资料,就先来个简单的方法,直接patch程序,在对比之前将key输出就行了。Patch好的链接库见附件。下面红色是patch的代码。
.text:0000129C                 BLX     R3
.text:000012A0                 LDR     R1, =(off_628C - 0x5FBC)
.text:000012A4                 LDR     R2, [R1,R7] ; off_628C
.text:000012A8
.text:000012A8 loc_12A8                                ; CODE XREF: Java_com_yaotong_crackme_MainActivity_securityCheck+12j
.text:000012A8                 MOV     R1, R2
.text:000012AC                 MOV     R0, #4
.text:000012B0                 BL      __android_log_print

.text:000012B4                 BNE     loc_12D0
.text:000012B8                 ADD     R2, R2, #1
.text:000012BC                 ADD     R0, R0, #1
.text:000012C0                 MOV     R1, #1
.text:000012C4                 CMP     R3, #0
重新打包运行,使用logcat就可以看到答案:aiyou,bucuoo

题目3
程序保护的思想是使用native代码来还原加密的delvik字节码,然后再使用加载dalvik虚拟机加载。libmobisec.so是动态链接库,libmobisecy.so是剔去了code的空壳dex文件,libmobisecx.so猜想是加密后的code代码(看代码貌似阿里还有一个libmobisecx.so的文件,应该是x86下的动态链接库)。程序还加了包的完整性验证,重新打包运行崩溃。
既然最终dex文件会被还原,可以在程序加载之后dump一下内存,然后找到解密的dex文件。
使用gdb附加到crackme.a3上,发现程序崩溃。搜索了一些资料成功在jni_OnLoad函数下断,动态跟了跟,发现程序应该是使用一个新线程来检测主线程是否被ptrace,如果是的话就修改程序的代码来反调试。
一个app运行有好几个线程,既然不能直接附加到主线程上,可以尝试附加到其它线程上。成功利用gdb附加之后输入gcore来dump内存。直接拷贝之前某次ctf中别人的代码来提取:

from zio import *
f = open('dump')
data = f.read()
f.close()

start = 0
while 1:
    i = data.find('dex\x0a035', start)
    if i == -1:
        break
    start = i + 1
    l = l32(data[i + 32: i + 36])
    open(str(i) + '.dex', 'w').write(data[i:])

提取出来很多dex,使用grep StubRuntimeException *来过滤一下得到解密的dex包。(libmobisecy.so中有一个StubRuntimeException包)
之后用baksmali反编译得到smali代码,可以再通过smali程序打包回dex再通过dex2jar和jd-gui来分析,但是jd-gui貌似对异常处理代码的反编译有点问题,对代码阅读造成很大困难。我直接读了smali代码,当中有一些混淆的代码,程序的基本流程就是对输入的字符串做摩斯电码的转换,然后再做一些运算来验证。
答案:... _____ ____. . ..___ .__.

题目4
题目4没有做出来,贴一下分析的思路。
题目4与题目3类似,相同的文件,一个libmobisec.so来加解密,libmobisecy.so空壳,libmobisecz.so加密数据。
程序做了反调试
刚开始直接上gdb dump内存,发现gdb报了一个错,但是仍然得到了dump,使用脚本提取,发现提取的dex文件用baksmali反编译报错,以为是加强了限制,没能提取到解密的dex。
后来想既然在用户空间不好提取,那么在内核空间应该没有问题。找了个破中兴手机,刷了一晚上recovery死活刷不上。。。
既然提取不成就直接分析libmobisec.so,将它拖进ida,ida报错。使用objdump等工具同样不行。这个应该是修改了elf结构的某些与加载无关的内容,这样仍然能够运行,但是静态工具无法分析。重新翻阅elf specification,对着看了看,无果。
后来突然想到既然elf能这样防止静态工具反编译,那么dex会不会用同样的方式处理了?
查了一下dex文件格式,对比发现确实是dex格式某些字段被更改了,这样手工分析有点困难,我下载了baksmali的源码,对它进行调试跟踪发现更改了insns_size字段,这个字段存储的是字节码的长度,但是这个难以恢复。
最后两小时突然想到了那个空壳dex文件,那个文件可以使用baksmali反编译,那么说明它的字段是未经修改的,可以提取合并到dump出来的dex文件上。没有时间做了,等过几天再试试。

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//