首页
社区
课程
招聘
[原创]伪·MSC解题报告
2015-1-26 21:44 33264

[原创]伪·MSC解题报告

2015-1-26 21:44
33264
唉唉~没办法,因为楼主是天秤座的,天生太懒了,所以这个帖子仅仅是简单说一下思路,截图什么的就肯定看不到了,而且我已经把题目的APK搞丢了。

补充一些题外话。如果参加过上次娜迦举办的沙龙,应该知道我现在也是从事apk保护工作的,所以限于工作原因,很多技巧都不应该公开的。但是这次比赛,还是公开了很多逆向技巧。
例如kill这东西,至少我没在别的公开场合见别人用过。只要合理利用kill,可以解决大部分反调试的附加问题(必要时需定制ROM)。
希望大家还是以学习为主,如果某天你利用这些技巧,破解了xx保护,xx加固,xx壳的话,只要偷着乐就好,还是不要拿出来炫耀了。毕竟很多人是靠这个吃饭的。
PS:还好我BOSS不上看雪,否则鸭梨山大啊。


第一题
就不说了,会点android逆向的都能很简单的搞定。
好吧,看到有人说jd-gui,有一部分看不到java代码。我只想说,根本就不需要看啊,看到那个Log.i就应该知道看log就行了。

第二题
把so拖到ida里面,找到native函数,按F5,就能看到一个很明显的比较循环,动态调试,在循环上下断点看内容就OK了。
看讨论,很多人说有反调试,过不了。对此貌似没有任何印象。
不过我的环境是自己改过的,有一些常规过反调试的措施。
根据后面几道题看到的内容,估计是读取了/proc/<pid>/status文件里面的状态和TracerId,这个自己想办法把读取的内容改了吧,一般是hook gets,之前有篇文章貌似说过。
一劳永逸的办法就是定制一个kernel,把调试信息全部去掉。

第三题
从这道题开始有点小麻烦。
就算有一些过反调试的措施,在我的环境下,ida一attach上去,程序就会退出。
看到有ptrace调用TRACEME,但返回结果都是-1,貌似是没影响。之前误以为是什么ptrace的高级用法,浪费了一些时间。事实上,在完成第三题的时候,我还是不能正常调试。
至于不调试怎么做呢。这里有个小技巧,就是利用kill指令,
kill -19 <pid>

可以让进程暂停,这个时候,使用IDA附加上去,程序就不会退出了。当时我没有运行,如果想运行的话,可以先
kill -18 <pid>

恢复之前暂停的状态,然后在ida里面运行。这个就是后面两道题的调试方法了。还有一些细节后两道题再说。
IDA附加上去之后,我是通过枚举gDvm->userDexFiles这个Hash表来查看加载的dex文件(实际上就两项),发现lib里面一个以y结尾的so被当作jar文件加载了。
(吐槽一下,发现很多人不知道userDexFiles这个东西,我觉得看过dalvik源码的话,对这个印象应该比较深刻才对)
解压缩so可以找到classes.dex文件,反编译发现所有函数内容都是什么RuntimeException。
这个问题请参照:
http://bbs.pediy.com/showthread.php?t=192836
实际就是运行时修改CodeOffset指向真正的代码内容。
这个问题我之前提出过一个简单的解决办法,就是dump大块内存,把真正代码对应的内容也dump出来(32位系统,最大也就4G,还要再去掉内核空间,所以完全能接受),然后baksmali再smali一下,原始dex就得到了。
具体操作,回到ida附加的进程上来,通过gDvm->userDexFiles可以找到DexOrJar结构,然后找so的JarFile结构体,再看DvmDex结构体的第二项,貌似是DexHeader*,指向的就是内存中dex文件首地址。得到地址之后,把dex文件和之前odex头一起dump出来,得到odex文件。然后上010Editor,查看得到的odex文件中class_def里面的类method的CodeOff项,值大概是0x2000+左右(或者0x12000+,根据环境不同也可能是其他值),总之是指向文件之外的内存。
之后对照/proc/<pid>/maps文件,查看从dex所在内存到CodeOff指向的内存,哪些可读,就直接dump,不能读或者没映射的就随便用字符填充。再次dump可以得到一个几M的odex。
然后修复此odex文件,就是用010Editor的DEX模板解析odex,遇到不能解析的值,进行修改。我是偷懒,直接把不能解析的置0了。
然后baksmali + smali可以得到正常的dex文件。

剩下的就是看dex文件代码了。这道题直接看java代码就能得到答案,有几行关键代码
v5 = new e().a(this.c);

这个是把输入进行转换,在class e里面能看到对应关系
v0_6 = v5.substring(0, 2).hashCode();
    if(v0_6 == 3618) {
            if(v1_6[0] + v1_6[1] != 168) {

这里是用前两个字符得到hashCode。因为对Java不熟,所以枚举了一下hashCode可能的值。
之后两个if就是找到hashCode是3618,且字符ascii值和为168的,找出来貌似是"s5"(记不清了)
byte[] v5_1 = (e.class.getAnnotation(f.class).a() + a.class.getAnnotation(f.class).a()).getBytes();

之后就是读取class e和class a中f的注释(说不清楚,不理解的自己百度getAnnotation,反正我是自己百度的。
之后把得到的字符拼起来,就是最后答案了,当然,要用class e里面的'.'和'_'表示,用空格分隔

第四题
dump dex的方法同上题。不过此题要动态调试。之前说道通过kill暂停进程,可以让ida附加上去,但是一运行,就会收到各种信号,pass给程序,程序就会退出。
当时我采用的方法是,直接手工忽略产生的信号,然后看哪个线程产生的信号,就把哪个线程挂起。挂了几个之后,就能正常调试了。
然后回到dex上来,根据流程,找到是把输入框的内容,传给了M$j函数,这是一个native函数。
之后就要动态调试M$j,但是M$j的起始部分是动态生成(注1),然后跳转到SO的某处执行。
因为懒得从头开始调,所以我当时的做法是修改了一下ROM,在dvmCallJNIMethod里面,每调用一个method,就判断method->name是不是"M$j",是的话,就把method->insns输出出来(注2)。这样就能很容获得M$j的地址。
获得M$j的地址之后,就是在地址上下断点,然后动态调试了。调试的时候发现代码进行了混淆,瞬间就蛋疼了。不过还好这是功能函数,这种混淆之前就考虑过。应对办法就是,在该函数所有的BL和BLX指令上面下断点,然后F9运行就行了。当断下来之后,仔细看看BL和BLX调用了哪个函数,参数是什么,返回值是什么。这样M$j的做了什么事,就能猜到了。
结果就是M$j调用了dex里面的bh.a函数,然后把返回值跟某个字符串进行了比较。
然后就是看bh.a的内容,具体忘了,就是几个Java的编码函数,和两个native函数。Java编码函数因为有源码,可以很容易写出解码函数(函数本身也很简单),关键是两个native函数。
用同样的办法调试两个native函数。
第一函数是String操作,关注String的内容,可以发现是把String的第四个(Index=3)字符进行+8操作。
第二个函数内容不是太明显,不过可以看到两个Base64编码的字符串,一个是我们输入的值进行编码得到的,那另外一个就很可疑了。而且还看到了调用strlen获取字符串长度,所以猜测是有长度的比较,说不定就有内容的比较(内容比较看不到)。所以就尝试性地把第二个字符串进行逆操作(解码),惊喜地得到了通关答案。那么剩下的就不用继续分析。

第五题
这道题没有做。其实在做第四题的时候,我就猜到第五题肯定就是把代码混淆做到算法里面去了。
之前考虑过代码混淆,算法+代码混淆是最佳组合,反正我没想到什么巧妙的办法去解。所以看到native函数内容就直接放弃了,太伤脑细胞。
在此不得不说一下第一名的暴力枚举想法还是不错的。我有考虑到是比赛,但是没想到可以暴力破解,因为考虑到第二题的答案,如果还是那种的话,基本跑不出来。
在我考虑的比赛中,觉得如果肯花费一点时间,把那个native函数单步走上两三遍,肯定能有所发现的。毕竟通过第四题来看,这次的代码混淆主要都是一些跳转指令,并没有对中间数据(我猜的)进行混淆,这样就有分析的目的了,不管怎么跳,怎么修改值,盯住数据不放就行了。
假如有数据的混淆,例如输入值是a,进来就是a^b^c^d^e^f^g = x,然后在用到a的时候,预设一个值h=b^c^d^e^f^g,这个时候直接用x^h就是a了。当然,这只是简单的说明,实际上可以更复杂。
所以啊,虽然知道这道比赛题可以做,还是要放弃,为了我的脑细胞着想。

注1:DEBUG模式启动进程,在RegisterNativeMethod(貌似是这样写,不是做开发的,记不清楚了)函数下断点,就能看到起始地址,但是该地址内容全为0,F9之后,再次断在RegisterNativeMethod时,可以看到该地址被写了4个字节
注2:很多人不认为对于native函数,method->insns是指向函数地址的。实际上,在Android4.4(之前的好像不是,我没看过源码),native在调用过一次之后,insns会被置为函数的实际地址,如果想了解,请参看dvmResolveNativeMethod的实现。

OK,解题思路就说完了,剩下的就是吐吐槽
关于这次比赛,总觉得线上长时间比赛按照时间排名很不科学。例如以前参加某安全公司的线上竞赛,目测第一就被内定了,然后告诉我说什么你提交的晚啦什么的。尼玛,一个月的比赛,哥20号左右才知道,然后提交了卡着各种不给判题,出不了成绩,然后我就只能呵呵了。
当然啦,这次的第一,还是让我比较信服的。确实自叹不如,尤其还这么努力。
还有就是我所期待的ptrace的题目没有出现。总之ptrace也是纸老虎啊。

如果看过我以前的看雪文章的话,就应该知道,我本来是做漏洞分析的啊,顺便兼职程序猿。然后自从几个月前决心转移动安全,就开始找相关工作。一开始是要做Android的漏洞挖掘,结果面的公司都说我资历不够,让我做别的先练手,只有某某某安全大师给了非常好的职位和待遇,结果因为个人原因,没有选择去。之后就是选择了现在这份工作,做Android Apk加固的相关研究。从此就走上一条不归路啊!!!
之前发帖吐槽逆向,貌似对想入这行的人影响不好。但这些纯属个人观点吧。因为我的强项还是分析,逆向这种东西,纯属一种工具而已,需要的时候用用就好,专门当作职业的话,我还是觉得太累了。
尤其是现在Android代码混淆开始出现,真心觉得这行混不下去了。所以啊,诸位有谁是做移动端漏洞研究的,可以联系一下我哦,我们要多亲近亲近才是。

总之呢,说转行是认真的,但不是立刻,我还是要先做些准备,欢迎各位来讨论移动端漏洞相关的问题。
这次发帖呢,学学玩命个,跟大家混个脸熟,说不定以后还会共事呢。

OK,就这些吧,有啥问题请回帖说明,稍后我会尽量一一答复的。

阿里云助力开发者!2核2G 3M带宽不限流量!6.18限时价,开 发者可享99元/年,续费同价!

收藏
点赞1
打赏
分享
最新回复 (41)
雪    币: 85485
活跃值: (198795)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
linhanshi 2015-1-26 21:50
2
0
APK搞丢了?
雪    币: 18
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
uaien 2015-1-26 22:09
3
0
刚想求4 5题apk,就看到apk搞丢了几个字。求有程序的共享一下,谢谢!
雪    币: 18
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
uaien 2015-1-26 22:10
4
0
又仔细看了一下帖子,楼主 娜迦 的?
雪    币: 2015
活跃值: (902)
能力值: ( LV12,RANK:1000 )
在线值:
发帖
回帖
粉丝
天易love 18 2015-1-26 23:44
5
0
能把自己的调试技巧写出来真是学习了....非常的大公无私
雪    币: 188
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
JackJoker 2015-1-26 23:59
6
0
马克下,明天电脑上学习大牛总结
雪    币: 4608
活跃值: (2711)
能力值: ( LV5,RANK:75 )
在线值:
发帖
回帖
粉丝
jiavjiav 2015-1-27 00:18
7
0
大神环境怎么搭的,大概有那些反调试措施呢,想学习一下!
雪    币: 205
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
qihuan风云 2015-1-27 01:15
8
0
调试只是使用
kill -18 <pid>
就可以了吗
我这里使用了这个命令,还是附加失败,跟没使用一样。
雪    币: 185
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
whnet 2015-1-27 09:01
9
0
逆向真心是苦力活,舍得吃苦也不一定能吃的下来
雪    币: 3502
活跃值: (1433)
能力值: ( LV15,RANK:1045 )
在线值:
发帖
回帖
粉丝
kkHAIKE 10 2015-1-27 09:37
10
0
谁和我一样相求第四题第五题apk的
雪    币: 233
活跃值: (285)
能力值: ( LV12,RANK:270 )
在线值:
发帖
回帖
粉丝
QEver 5 2015-1-27 10:14
11
0
其实我是做完一个,然后就把所有东西清空,给下一题留空间了。
雪    币: 233
活跃值: (285)
能力值: ( LV12,RANK:270 )
在线值:
发帖
回帖
粉丝
QEver 5 2015-1-27 10:15
12
0
必须不是
雪    币: 233
活跃值: (285)
能力值: ( LV12,RANK:270 )
在线值:
发帖
回帖
粉丝
QEver 5 2015-1-27 10:16
13
0
我也觉得说的有点多了。
不过Android这种开源平台的软件保护,很多都只是防防小白而已。
雪    币: 233
活跃值: (285)
能力值: ( LV12,RANK:270 )
在线值:
发帖
回帖
粉丝
QEver 5 2015-1-27 10:18
14
0
反调试措施可以去找找上次娜迦的比赛一些相关分析。
娜迦的壳把常规的反调试都加上了。

怎么搭环境,就看你对源码的理解了。
雪    币: 233
活跃值: (285)
能力值: ( LV12,RANK:270 )
在线值:
发帖
回帖
粉丝
QEver 5 2015-1-27 10:19
15
0
是kill -19,18是恢复运行
具体数字代表什么意义,可以参考libc源码里面的signal.h文件

暂停之后有明显特征就是app进程卡住了,怎么操作都无效。
雪    币: 709
活跃值: (2270)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
sudami 25 2015-1-27 10:43
16
0
看不懂,只能学习了。
雪    币: 7474
活跃值: (2689)
能力值: (RANK:520 )
在线值:
发帖
回帖
粉丝
netwind 13 2015-1-27 10:49
17
0
谢谢QEver的分享!
雪    币: 141
活跃值: (39)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
習生 1 2015-1-27 11:02
18
0
Hi lz,问一下那个wbyang的DD大法是什么?能详细解释下吗
雪    币: 233
活跃值: (285)
能力值: ( LV12,RANK:270 )
在线值:
发帖
回帖
粉丝
QEver 5 2015-1-27 11:17
19
0
linux下有个命令叫dd,可以配合maps文件来做内存dump
雪    币: 141
活跃值: (39)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
習生 1 2015-1-27 12:36
20
0
那要是我要用这个命令,是写一个android的程序运行注入的方式吗?
雪    币: 18
活跃值: (41)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
deadxing 2015-1-27 13:01
21
0
感谢分享(*^__^*)
雪    币: 233
活跃值: (285)
能力值: ( LV12,RANK:270 )
在线值:
发帖
回帖
粉丝
QEver 5 2015-1-27 13:33
22
0
目测是
dd if=/proc/<pid>/mem of=xx.bin ......

反正我不习惯用dd
雪    币: 232
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
deryope 1 2015-1-27 13:46
23
0
感谢分享kill暂停的方法,回去试下这个思路对付反调试
雪    币: 141
活跃值: (39)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
習生 1 2015-1-27 13:55
24
0
[QUOTE=QEver;1349803]目测是
dd if=/proc/<pid>/mem of=xx.bin ......

反正我不习惯用dd[/QUOTE]

代码我知道,如何让它执行? adb shell su之后直接用?
雪    币: 59
活跃值: (185)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
heartbeast 2015-1-27 14:58
25
0
好帖留名
游客
登录 | 注册 方可回帖
返回