由于本人使用的是Mac来做开发,并且最近要做逆向相关,苦于网上多数教程都是Win的,没办法只有到处搜集资料和自己踩坑,摸着石头过河。这里分享一下Mac来做的整个过程。目标,IDA动态调试,dump dex脱壳。 脱壳的话,目前两种方法,一种动态调试,一种xposed,当前为动态调试学习
环境: macOS 10.14.1 root过后的手机 htc 4.4.2 IDA 7.0 附送地址 IDA mac 高版本崩溃解决适配 mprop 设置手机所有应用为可调试 下载地址
adb push xxx/mprop /data/local/tmp/mprop adb shell su chmod 755 /data/local/tmp/mprop data/local/tmp/mprop setprop ro.debuggable 1 /data/local/tmp/mprop -r
adb forward tcp:23946 tcp:23946 adb shell am start -D -n 包名/包名对应启动Activity
打开IDA设置好process options 地址127.0.0.1 端口23946 Ida -》debugger -》attach process 选择对应应用进程 选择libdvm.so 找到dvmDexFileOpenPartial 计算偏移量 下断点
连接jdb(两种方式) 1、通过ddms(如果占用8700 ps查看 kill杀掉 重来) 2、命令 adb shell ps | xxx 找到对应app的进程号 adb forward tcp:8700 jdwp:进程号 jdb -connect com.sun.jdi.SocketAttach:port=8700,hostname=localhost
启动ida F9 开始进行调试
通过IDA的动态调试系统库libdvm.so的dvmDexFileOpenPartial方法,来寻找内存中的dex段地址,然后进行dump,最终达到脱壳的目的。 (4.4前后的不同java虚拟机类型,所以这里用的是4.4.2的手机,系统库为libdvm,如果是之后的便是libart,调试方法为openMemory)
看似原理很简单,但是会遇到许多的问题和坑,每个都能卡你半天,所以这里分享给大家一些细节东西,望君莫要重蹈覆辙。
这里启动之后 可以看到IDA Android 32-bit remote debug server(ST) v1.22. Hex-Rays (c) 2004-2017 注意:这里32-bit的话,你打开IDA就用32位的打开 不然就是64位的
adb push xxx/mprop /data/local/tmp/mprop adb shell su chmod 755 /data/local/tmp/mprop data/local/tmp/mprop setprop ro.debuggable 1 /data/local/tmp/mprop -r
使用getprop ro.debuggable 就可以查看是否修改成功
有时候遇到
android_server Address already in use可以杀掉进程重来
进入adb shell ps | grep android_server kill -s 9 进程号 重新启动android_server
注意:手机每次重启都要重复此操作,都要重新设置debuggable为1,有时候手机会无意重启,注意。
adb forward tcp:23946 tcp:23946 adb shell am start -D -n 包名/包名对应启动Activity
这里转发了之后可以使用lsof -i:23946来查看如果有Listen则说明转发成功 接着调用adb 调试命令 填好对应包名和启动的Activity注入调试
这里提供一下 查询启动页的方法 adb shell dumpsys activity top 启动app之后查看现在的Activity信息可以拿到包名 然后 adb shell dumpsys package 包名 就可以查询一下有action MAIN的Activity,一般类似为SplashActivity
注入调试,手机上就有等待调试的弹框了。
打开IDA设置好process options 地址127.0.0.1 端口23946 Ida -》debugger -》attach process 选择对应应用进程 选择libdvm.so 找到dvmDexFileOpenPartial 计算偏移量 下断点
这里我们使用的是32位的IDA打开,一般要开两个,一个为了静态分析so(也就是找到libdvm.so的对应的dexFileOpen函数地址,后面要做寻找断点用);另外一个是拿来调试用的。
首先,需要获取libdvm.so,一般是在手机的/system/lib/ 下面
adb pull /system/lib/libdvm.so /users/jafir/desktop/ 直接pull到电脑上来,然后IDA打开
0004BB10这个地址就是dexFileOpen函数在libdvm.so中的偏移地址,后面我们打断点的时候,需要在整个内存中去寻找到真正的dexFileOpen的地址。 原理就是 找到libdvm.so在内存中的首地址,然后加上这里的偏移地址,就可以得到libdvm.so中的dexFileOpen的地址。 好,这就是静态分析获取地址。
然后,再打开一个,File->New Instance,选择 GO Debugger->Attach->Remote ArmLinux/Android
接下来就ctrl+s找到libdvm.so然后查看,它在内存中的首地址,计算偏移量
计算一下偏移量 4152D000+ 0004BB10 = 41578b10,按G,进行地址跳转
打上断点 ok
连接jdb(两种方式) 1、通过ddms(如果占用8700 ps查看 kill杀掉 重来) 2、命令 (-- adb shell ps | xxx 找到对应app的进程号 – adb forward tcp:8700 jdwp:进程号) jdb -connect com.sun.jdi.SocketAttach:port=8700,hostname=localhost
最简单的打开ddms,它是在你Android sdk/tools下面的monitor 然后jdb -connect com.sun.jdi.SocketAttach:port=8700,hostname=localhost
(base) Jafir:~ jafir$ jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=8700 设置未捕获的java.lang.Throwable 设置延迟的未捕获的java.lang.Throwable 正在初始化jdb... >如果打开DDMS报8700被占用了,lsof -i :端口号查看,然后kill -s 9 进程号杀掉,重来
(base) Jafir:~ jafir$ lsof -i:8700 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME monitor 31587 jafir 121u IPv6 0x8c41b253ec7cd357 0t0 TCP localhost:8700 (LISTEN) (base) Jafir:~ jafir$ kill -s 9 31587如果不用ddms,也可以用命令,来连接jdb
adb shell ps | xxx包名 找到对应app的进程号 adb forward tcp:8700 jdwp:进程号 jdb -connect com.sun.jdi.SocketAttach:port=8700,hostname=localhost启动ida F9 开始进行调试
点击绿色启动按钮,就可以了,这时候按道理,手机的debug等待框也消失了,进入调试状态。
ddms的灯变成绿色,然后断点断在了libc上头,就成功了 之后便是一路F9,回车。F9,回车 直到我们的断点处。 注意断点,向下执行,不要超过BL,过了PUSH就可以了
到断点处,如果成功的话,就可以从General registers里面看到变量值。
static main(void){ auto fp, dex_addr,end_addr; //打开或创建一个文件 fp = fopen("/users/jafir/desktop/dump.dex", "wb"); end_addr = r0+r1; for ( dex_addr = r0; dex_addr < end_addr; end_addr ++ ){ //按字节将其dump到本地文件中 fputc(Byte(dex_addr), fp); } }File->Script Command可以创建脚本命令
过一会就可以看到桌面上dump.dex文件了。
####进程相关: ps A 查看所有 ps a 显示同一终端下的所有程序 lsof -i:xxx 查看端口进程信息 kill -9 xxxx 杀死某个进程 #####逆向相关命令: cat 查看 cat /proc/xxxpid/maps 查看xxx进程的lib库文件(一般需要root才能查看) echo touch 写内容到文件中 echo 内容 >> 文件路径 (如果有文件就追加 没有就创建) echo 内容 >文件路径 (如果有文件就清空写入 没有就创建) adb shell dumpsys activity top adb shell dumpsys package [packagename] adb shell dumpsys meminfo xxxx com.cctv4g.cctvmobiletv adb shell dumpsys dainfo xxx adb shell screencap -p xxx路径 adb install -t xxx 以测试包的类型安装 #####查看当前的activity: 1、adb shell dumpsys activity activities | sed -En -e ‘/Running activities/,/Run #0/p’ 2、adb shell dumpsys activity | grep -i run #####查看权限的命令: ls -alf 查看文件及其权限 ls -a 可以查看包含隐藏文件 ls 查看 #####查看keystore的信息摘要 sha1 keytool -list -keystore keystore #####jadx-gui: jadx-gui xxx.jar/xxxx.dex/xxx.apk 配置好环境变量 #####Dx: dx --dex --output=HelloWorld.dex HelloWorld.class 把class文件编译成dex #####执行dex文件 1、生成dex文件(可以直接从apk中解压出来,也可以从jar利用dx命令生成) 2、然后adb push xxx.dex xxx到手机中去 3、adb shell 4、dalvikvm -cp xxx.dex com.jafir.signprotect.Main(主类)
本人也是刚入手,小白一个,摸索着石头过河,请教过很多大神,但是不管怎么说还是要自己动手,踩坑,尝试,无数次尝试。 这里只进行到dump dex,其实后面还有很多的操作,比如什么指令抽取的要还原啊,还要过滤反调试等的。
我只是用了自己的没有反调试的apk来过了一遍手,而后在想要脱壳的时候,却遇到了更多的问题,总之,初来乍到,还要继续学习和探索,有志同道合者,希望相互交流。