吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 18225|回复: 50
收起左侧

[Android CTF] 以Xp0intCTF的so fun为例利用Zjdroid安卓脱壳步骤(以及排查出错问题)

  [复制链接]
whklhh 发表于 2017-10-25 03:45
本帖最后由 whklhh 于 2017-10-26 21:55 编辑

在最后补上了linux通过srand48和lrand48得到genstr的值,从而得到flag的过程,以及附加模拟器(失败,得用真机
==========================更新10.26======================================

首先,也许zjdroid这个工具的确已经很老了,不过作为学习、脱一些简单的壳应该还是可以的
(主要是官方Wp中说的这个工具,那肯定它是可以的嘛。当然优先复现它咯~)

遇到了很多坑,换了俩模拟器最后在真机上搞定,折腾了数个小时才搞定,感觉自己的排错能力真的提升了不少OTZ

Xposed和Zjdroid这命令,debug得我都轻车熟路了……

使用Zjdroid这个工具需要先安装Xposed框架,注意【安装框架】和【安装模块】完后都需要重启
(不注意看提示会掉坑撒)

重启后开启两个命令行,一个命令行查看log中的返回数据,另一个命令行来执行命令
Zjdroid的命令结果全都是通过broadcast返回的,因此需要logcat来接收
第一步:
[Shell] 纯文本查看 复制代码
adb shell dumpsys activity top


这个命令可以显示当前显示程序的包名和pid
有了这个包名以后我们就可以筛选log了(否则太多啦)

在一个命令行使用
[Shell] 纯文本查看 复制代码
adb logcat -s zjdroid-shell-com.jnu.ctf2017


意思是从log中筛选zjdroid-shell-com.jnu.ctf2017

当发现程序在运行以后就会显示hook到的数据:

  
然后另一个命令行进入shell中开始执行zjdroid的命令就好了:

首先得到内存中dex的信息
[Shell] 纯文本查看 复制代码
root@x86:/ # am broadcast -a com.zjdroid.invoke --ei target 2102  --es cmd '{"action":"dump_dexinfo"}'
 -a com.zjdroid.invoke --ei target 【目标程序PID】  --es cmd '{"action":"dump_dexinfo"}'



注意要在shell中输入哦

我刚开始用adb shell am xxxxxx的方式输入时无限报错,最后去掉单引号就能成功dump出dex信息了,但是后一步就没办法了╮(╯_╰)╭试了好久好久
【搜索的时候发现有不少人问log中显示the cmd is valid,都没有查到结果;除了命令确实输错以外,就可能是这个原因,请仔细检查单引号、cmd后的空格、以及是否在shell中和是否具有root权限(在Shell中输入su一下即可)】
这样在另一边的Log窗口就能看到信息啦:


两个filepath就是内存中的文件了,壳解密出的东西就是它们了
我们只需要把它们dump下来就OK咯!
(注意mCookie:-1,这是第一个大坑)

dump命令:
[Shell] 纯文本查看 复制代码
root@x86:/ # am broadcast -a com.zjdroid.invoke --ei target 【目标程序PID】  --es cmd '{"action":"backsmali",dexpath:"/data/app/com.jnu.ctf2017-1/base.apk"}'

结果:
  
嗯?!咋回事儿?
试了几遍都是这样
按照提示去源码中查了一下:



我知道mCookie=-1肯定不对劲儿,可是这Cookie是你给的啊(╯‵□′)╯︵┻━┻
权限也都是最高的了,没道理出错啊

那我们乖乖看log呗:

  
我选中的部分就是核心出错点,上半部分是正常的log,加载了backsmali命令
下半部分是出错位置的调用堆栈,可以看到,位置在backsmaliDexFile方法中的getCookie中出错了
又去翻译了一下,这个错误似乎是long到int的类型转换出错了……
估计是程序返回的cookie太大,超过了int的范围;而Zjdroid中的变量是int类型,导致溢出直接转换报错,返回-1了……

说到这我想起来,所用模拟器(雷电模拟器)是安卓5.1版本,似乎应用了64位系统。
我用它也正是因为上一次做的某个CM要求64位系统。也许是这个原因吧。

当时也差不多猜到可能这个系统太新了的缘故,于是换回以前使用的夜神模拟器。

值得一说的是,Xposed的APK我是从官网下的最新版,结果拖进夜神直接报错
查了一波发现有旧版的可以给夜神用,遂安装成功

同样步骤进行下来,返回的mCookie终于正常了:
  
看到这个巨大的负数简直让我兴奋的不行,暗想幸亏我还留着这个以前跟着我的模拟器……

没想到这是另外一个坑

继续下一步,dump:
好嘛,这次更恐怖,直接结束运行了……
  

又试了一次,换别的app dump也一样,说明还是Zjdroid和系统的适配问题……
这次不猜了,乖乖看Log吧:

  

同样的位置,从开始向下看一下就找到了
这次Cookie对了,但是找不到框架中的libdvmnative.so库了
我查了一下,似乎有人说这个库是闭源的啊,有人说是安装过程的问题啊等等
报错的进程是davikvm虚拟机,我感觉跟模拟器是x86处理器架构,而真机是ARM处理器架构有关

于是我就掏出尘封已久的价值一百块的二手中兴真机,再来一遍
(别问我为啥不一开始就上真机,太菜了不好意思掏出来(而且懒得充电 没电关机落灰很久了
再值得一说的是,那个适用于夜神的老版Xposed居然不适用于辣鸡中兴
我本来以为脱壳无望了,查了一波发现有人修改出了努比亚专用的Xposed……

安装竟然成功了,自此一帆风顺这次终于没问题了……


以上是脱壳和查错教程
(其实一开始就上真机就一点问题都没了啊(╯‵□′)╯︵┻━┻)


下面开始本题的WP

这一题来自前两天的Xp0int(暨南大学校赛)的re,题名为so fun


查壳的时候发现有两个文件,apk和secData.jar
这个jar其实我比赛的时候就看到了,感觉有点问题但是反编译不出来,就没太在意
原来这个就是关键的加密dex啊!
dump下来以后拖入jeb反编译,查看MainActivity:
  
过程太简单了好感动

取到输入字符串以后传入checkstr方法,这个方法是native导出的,要去so库中找
IDA反编译以后找到checkstr导出函数


checkstr调用的时候实际上送入了一个参数,就是这里的v0了
v1来自于genstr生成
然后cmpstr比对genstr里还算简单,不过随机数有点麻烦,需要模拟环境
今天太晚了我就不开虚拟机搞了,明天再说吧
  

另外strcmp函数并不是简单的字符串对比,里面还有一个处理:

再异或一下0x6a,内部生成flag

官方WP的方法是直接新建一个工程调用so库文件,动态调试cmpstr,找到v2的值后脚本跑出v3
我觉得其实直接IDA附加到这个库上应该也可以
再不济通过linux还原genstr应该也行吧;不过不知道linux的x86处理器和安卓的ARM处理器会不会对随机数算法有什么影响……应该没有吧,只要库文件相同,算法就相同的
明天尝试一下几个解决方案

总体来说Zjdroid的步骤其实很简单,hook以后得到pid,再查看dexinfo,最后dump出来即可;这么多步骤主要都是各个模拟器下的问题,如果一开始就用真机就半小时解决了……

不过也算锻炼了一下纠错查错的能力,玄学,玄学

想起来去年的CTF国赛也有一个带壳安卓,当时看的WP用的是另外一个通用脱壳程序,明天有空再翻出来试试吧(还有AndroidHunter,虽然现在估计对付新时代的壳已经没用了……)

这个题目不脱壳其实也能做来着,直接反编译这个库然后研究返回值就行……虽然不脱壳也不知道APK里有没有对JNI方法返回的值再做变换就是了……
感觉好可惜~

题目链接: https://pan.baidu.com/s/1boGHz0z 密码: hxwq


===============================================更新====================================================================
补上昨天的遗漏和测试

首先是代码纠正:

之前想的太简单了,if判断内部其实是进一步的校验,而不是我以为的flag生成(估计太晚了脑子有坑了吧,输入的就是flag还生成个鸡毛哟)
if判断第一个值,通过以后在循环中判断其余13个值,注意i的初值为1,也就是说实际上就是连续判断,写成这种结构纯粹多此一举……又不是在服务器上节省资源233
虽然看起来有点像DO..WHILE结构,不知道是不是IDA反编译差了

不过不影响效果╮(╯_╰)╭
我们知道这玩意儿是将genstr的结果+下标i以后异或一个数组中的对应值后,与input比较就够了

用同样的种子和算法就能生成相同的伪随机数序列,由此得到genstr,进而算出flag


验证代码的时候顺便查了一下,srand48是指一个线性同余法和48位整数运算的生成算法,windows下没有这个函数,但是可以自己参考linux的库文档,手动写一个函数(貌似很短,百度一下就有)


我直接在linux上进行了,注意头文件stdlib.h

代码(Linux C):
[C++] 纯文本查看 复制代码
#include <stdio.h>[/size]
#include <stdlib.h>

int main()
{
    char s[] = "_0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";
    int key[]={106, 124, 104, 31, 16, 39, 43, 6, 62, 39, 8, 70, 56, 20};
    char flag[15];
    int j;
    srand48(0);
    for(j=0;j<14;j++)
    {
        flag[j] = s[lrand48() / 0x1FFFFFF] + j;
        flag[j] ^= key[j];

    }
    puts(flag);
    return 0;
}

PS:用[j]应该就不会被吃了吧



然后确认了IDA附加:


将/dbgsrv下的android_server 通过adb push进安卓端以后进入shell执行:
[Shell] 纯文本查看 复制代码
C:\Users\hasee>adb push E:\ctf\IDA_Pro_v6.8_and_Hex-Rays_Decompiler_(ARM,x64,x86)_Green\dbgsrv\android_server /data/[/size]
941 KB/s (523480 bytes in 0.543s)

C:\Users\hasee>adb shell
root@x86:/ # su
su
root@x86:/ # cd /data
cd /data
root@x86:/data # ./android_server
./android_server
IDA Android 32-bit remote debug server(ST) v1.19. Hex-Rays (c) 2004-2015


Listening on port #23946...



这样就在23946端口进行监听了,然后在端口转发以后就可以用IDA附加上去啦


[Shell] 纯文本查看 复制代码
C:\Users\hasee>adb forward tcp:23946 tcp:23946[/size]



附加上以后只要运行到断点就报错:


FFFFFFFF: got SIGILL signal (Illegal instruction) (exc.code 4, tid 2240)

查了一下应该是模拟器为x86架构,而so程序是ARM架构的原因只能附加真机咯~出来玩没带那货╮(╯_╰)╭回去再补上下文~






免费评分

参与人数 13吾爱币 +13 热心值 +13 收起 理由
oranges + 1 + 1 我很赞同!
helloword121 + 1 + 1 用心讨论,共获提升!
Ravey + 1 + 1 谢谢@Thanks!
MXWXZ + 2 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
XhyEax + 1 + 1 我很赞同!
DevinCc + 1 + 1 我很赞同!
GG0 + 1 + 1 我很赞同!
lies2014 + 1 + 1 用心讨论,共获提升!
Three_fish + 1 + 1 谢谢@Thanks!
海底总动员 + 1 我很赞同!
superzhangxue + 1 + 1 谢谢@Thanks!
时光不老时 + 1 + 1 热心回复!
SomnusXZY + 1 + 1 热心回复!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| whklhh 发表于 2017-10-25 12:27
时光不老时 发表于 2017-10-25 12:19
大神,请问一下,我新手刚入门应该从哪方面开始

我也还很菜呢
单纯APK入门的话,从Android Killer或APK改之理、jd-gui或jeb2等工具的使用开始学咯
(当然最好还是先学正向写APK)
论坛里有很多教程,搜索一下就能找到的
感冒的猪baby 发表于 2017-11-29 18:05
root@x86:/ # am broadcast -a com.zjdroid.invoke --ei target 【目标程序PID】  --es cmd '{"action":"backsmali",dexpath:"/data/app/com.jnu.ctf2017-1/base.apk"}'

这一步,只要一执行,手机上app就奔溃了
plasd 发表于 2017-10-25 06:31
夏雨微凉 发表于 2017-10-25 07:58 来自手机
厉害厉害
一人游弋 发表于 2017-10-25 08:29
厉害厉害
canmeng 发表于 2017-10-25 08:39
厉害学习了
星星当空照 发表于 2017-10-25 09:52
支持以下。。。
mayl8822 发表于 2017-10-25 09:54
感谢分享, 学习了
yycmd 发表于 2017-10-25 09:56
不明觉厉
pxhb 发表于 2017-10-25 10:20
收藏,感谢分享
微笑的高圆圆 发表于 2017-10-25 10:23
慢慢来就好了了
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-20 06:10

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表