8月份课时1
- 虚拟机安装
- 下载kali-linux:https://github.com/r0ysue/AndroidSecurityStudy/tree/master/FART
- wifi adb:https://www.apkmirror.com/apk/metactrl/wifi-adb-debug-over-air/wifi-adb-debug-over-air-3-0-6-release/wifi-adb-debug-over-air-3-0-6-android-apk-download/download/
- vmware配置kali-linux
解压
vmware打开解压后的文件
编辑虚拟机-》内存4096,显示器3d加速不选,其他不改
开机-》账号root,密码toor
如果虚拟机时间不对改时区:终端-》dpkg-reconfigure tzdata-》Asia/shanghai-》apt update
显示中文字符(系统不要切换成中文):apt install xfonts-intl-chinese、apt install ttf-wqy-microhei
如果上面的命令执行失败就执行apt update,如果还失败:https://wochinijiamile.blog.csdn.net/article/details/79275944?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_paycolumn_v3&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_paycolumn_v3&utm_relevant_index=1
分别运行命令安装软件:apt install htop、apt-get install tmux jnettop
apt install neofetch:用来看系统的工具
- 软件安装
(1)as:
下载:wget https://redirector.gvt1.com/edgedl/android/studio/ide-zips/4.0.1.0/android-studio-ide-193.6626763-linux.tar.gz
解压:tar -zxvf 文件名
运行:./studio.sh
一路next和finish完成下载
(2) genymotion
https://www.genymotion.com/download/选大的
安装genymotion,安装时不要改genymotion和virtualBox默认安装路径,不然可能启动不了
注册账号
加虚拟机-》搜索5x-》选择8.0
配置其他不变,最后选bridge
模拟器配置:adb shell-》uname -a查看架构,i686代表是x86,arm是手机
有些app是arm会导致模拟器无法安装,要搭arm桥:把压缩包直接拖入模拟器
模拟器wifi有×,root下执行:
settings put global captive_portal_http_url https://www.google.cn/generate_204
settings put global captive_portal_https_url https://www.google.cn/generate_204
settings put global ntp_server 1.hk.pool.ntp.org
reboot重启×消失
8月份课时5
- jeb,java反编译工具,根jadx作用差不多
下载地址:http://www.itmop.com/downinfo/214119.html
8月份课时6
apktool下载地址:https://www.jb51.net/softs/644481.html
- objection
objection安装:pip3 install objection
objection -g 包名 explore:打开应用,如objection -g com.android.settings explore打开设置
如果运行objection报(Pygments 2.11.2 (d:\python\python3.7\lib\site-packages), Requirement.parse(‘Pygments<=2.11.1,>=1.6’)类似的错误,那就是版本问题,要降objection版本
android hooking list classes:列出所有的类
- 内存漫游
获取内存中的对象、调用栈等
env:常用命令,显示包的缓存、主要文件、源app位置
memory list modules:显示当前在内存中的so
memory list exports so名:hook指定so
memory list exports so名 —json c:/Users/hw/Desktop/1.json:把hook结果输出到文件
android hooking list activities:列出所有activity
android intent launch_activity activity名:跳到指定的activity
android hooking watch class 类的全限定类名:hook监视类,可以查看那些方法有没有执行
android hooking search classes 类名:搜索一个类
jobs list:查看监视的对象
jobs kill 对象id:解除监视
android hooking watch class_method 类的全限定类名.方法名 —dump
-args —dump-backtrace —dump-return:监视方法的参数和返回值,并且打印调用栈。java加密常用类java.security.MessageDigest
8月份课时7
- 去升级
升级弹窗常用方法:activity、Dialog、PopupWindow
activity:可以直接用activity跳转直接绕过
dialog:Android dialog常用实例https://www.jianshu.com/p/4712652fb313
8月份课时9
安卓常用反爬
代码混淆:把类名、常量、参数变成没有意义的字符串
类动态加载:运行时加载类
云加载:核心逻辑放到服务器上
类动态加载
hook安卓的DexClassLoader
9月份课时1
xpose安装
原版xpose已经停止更新,最高支持安卓7,可使用衍生版本:太极、virtualxpose等
模块安装
GravityBox[N]:调整手机设置
9月份课时2
jeb3.0
smail调试(类似于直接调试程序)
https://down.52pojie.cn/Tools/Android_Tools/
tab:切换代码显示
双击:进入方法
调试:装xdebug插件,手机打开app,jeb调试器-》开始-》选择进程,app必须要支持调试(Manileft下有android:debuggable=”true”)
DDMS动态调试
android studio的sdk安装目录下有monitor.exe
手机运行app-》找到对应的包名-》点上面的dump
Hierarchy View:DDMS旁边的图标点一下出来,可以查看继承关系图
mothod Profiling:查看运行的方法,可以搜关键方法进行定位
9月份课时3
frida
frida-ps -U:查看本机连的手机的进程
frida -U -F:查看前台应用
开发环境搭建
git clone https://github.com/oleavr/frida-agent-example.git
cd frida-agent-example
npm install
用vscode等软件打开工程会有代码提示
npm run watch:监控代码修改自动编译成js文件
frida -U -f com.android.settings —no-pause -l_agent.js
9月份课时4
常用抓包方式
设置代理抓包:手机设置wifi,电脑用fiddler、charles
vpn抓包:有些app会有检测,导致app抓不到包或app无网络,这时要手机配置vpn抓包
9月份课时6
基于hook的抓包
安卓网络请求常用框架:com.android.okhttp、java.net.HttpURLConnection、org.apache.http
用objection来hook网络请求常用框架看调用栈,反编译软件直接定位方法,如果包的子包多用*
混淆
1.app有混淆无法用直接搜索
2.apktool d app名:解包app,如果有加固就不能解
3.搜索被混淆的类,如okhttpclient,可以用工具:https://www.greenxf.com/soft/270951.html
4.找到可疑文件,打开可疑文件找.source就可以看到混淆前的类
网上脚本
git clone https://github.com/siyujie/OkHttpLogger-Frida.git
push文件:adb push okhttpfind.dex /data/local/tmp
赋权
运行脚本:frida -U -l okhttp_poker.js -f 包名 —no-pause
9月份课时7
两种方法:命令行、RPC
- 命令行
frida -UF -l js脚本:获取最前台的app并加载脚本
-U:获取usb,-F:获取最前台app,-l:加载脚本
- RPC
Java.perform(function(){console.log('2222222222222222')})
```python import osimport frida# 连接手机device=frida.get_remote_device()# 获取最前的appprint(device.get_frontmost_application())# 获取所有进程print(device.enumerate_applications())# 获取pidpid=device.get_frontmost_application().pid# 根据pid获取进程session=device.attach(pid)with open('hello world\helloworld.js') as f:script=session.create_script(f.read())# 执行脚本script.load()
import frida, sys
def on_message(message, data): if message[‘type’] == ‘send’: print(“[*] {0}”.format(message[‘payload’])) else: print(message)
jscode = ‘’’ Java.perform(function () { Java.use(‘tencent.go.c’).c.implementation = function() { send(1) var res=this.c() return res; } }); ‘’’
jscode=open(‘./test.js’,encoding=’utf-8’).read()
process = frida.get_remote_device().attach(‘com.example.seccon2015.rock_paper_scissors’)
os.system(“adb forward tcp:27042 tcp:27042”) os.system(“adb forward tcp:27043 tcp:27043”)
session = frida.get_remote_device()
根据包名启动app,用于启动时hook
pid=session.spawn([‘com.wzyk.zgyjb’]) session.resume(pid) session=session.attach(pid)
script = session.create_script(jscode) script.on(‘message’, on_message) print(‘[*] Running CTF’) script.load() sys.stdin.read()
3. frida两种操作app方式spawn:应用加载时就hook,有壳就不行<br />attach:运行时hook,有壳也可以<a name="TUgxi"></a>### 9月份课时81. 壳的分类一代壳:脱壳之后拿到完整源码<br />二代壳:脱壳后源码不全,比如函数体没有,只有函数名<br />frida-dexdump github:[https://github.com/hluwa/FRIDA-DEXDump](https://github.com/hluwa/FRIDA-DEXDump)<br />脱壳:frida-dexdump -U -f com.app.pkgname2. 跳过升级案例启动时hook类:objection -g 包名 --startup-command "android hooking watch class 类全限定名"<br />如:objection -g com.wzyk.zgyjb explore --startup-command "android hooking watch class android.view.Window"<br />常用类:android.view.Window、android.app.Dialog、android.widget.PopupWindow、android.app.AlertDialog<br />如果弹框使用android.app.Dialog:hook方法android.app.Dialog.setCancelable查看调用栈,查看调用此方法的方法<a name="SLKRK"></a>### 9月份课时91. frida主动调用类静态变量可以直接访问:对象.变量名.value<br />成员变量不能直接访问,需要使用choose```javascriptJava.choose("com.wzyk.zgyjb.bean.PageInfo",{// instance:固定,current_page_num:变量名,value:获取值onMatch:function(instance){// 操作执行函数console.log(instance);console.log(instance.current_page_num.value);// 直接修改instance.current_page_num.value=5},onComplete:function(){// 操作完成函数send("完成")}})
调用构造方法创建对象:Java.use(类全限定类名).$new(参数),如Java.use(“java.lang.String”).$new(“2”)
调用静态方法:对象.方法名(参数)
调用普通方法:跟调用成员变量同理,instance.方法名(参数)
- nps
内网穿透工具,github:https://github.com/ehang-io/nps
10月份课时1
案例项目:https://github.com/aqi00/android2,模块network
hooking类java.net.URL和它的构造函数
hooking构造函数:java.net.URL.$init
import frida, sys,osdef on_message(message, data):if message['type'] == 'send':print("{0}".format(message['payload']))else:print(message)jscode = open('10月份/01.js',encoding="UTF-8").read()os.system("adb forward tcp:27042 tcp:27042")os.system("adb forward tcp:27043 tcp:27043")# 获取最前的appdevice=frida.get_remote_device()# 获取pidpid=device.get_frontmost_application().pid# 根据pid获取进程session=device.attach(pid)# 加载脚本script = session.create_script(jscode)# 打印日志script.on('message', on_message)# 执行脚本script.load()# 脚本执行完不直接结束sys.stdin.read()
Java.perform(function(){var u=Java.use("java.net.URL");u.$init.overload('java.net.URL', 'java.lang.String').implementation=function(s1,s2){send(s1)send(s2)this.$init(s1,s2);}})
Wallbreaker插件:https://www.cnblogs.com/Fightingbirds/p/13995950.html,windows下路径~改成自定义
查看内存中的源码:plugin wallbreaker classdump —fullname 类的全限定类名
10月份课时2
plugin wallbreaker classsearch OkHttp:搜索名字包含OkHttp的类
plugin wallbreaker objectsearch okhttp3.OkHttpClient:根据搜索到的类查看相关类的内存
android hooking watch class okhttp3.OkHttpClient:hook okhttp3框架查看调用栈
11月课时1
创建c++项目报错:Failed to install the following Android SDK pac…
https://www.jianshu.com/p/560bcb5d2034
sdk:java层开发
ndk:c++层开发
- JNI
java本地接口,是java调用native一种特性
c++静态绑定:Java全限定类名(用分开)_方法名,如Java_com_lyf.demo_MainActivity_getSignJNI
JNI对应Java数据类型
一般是前面加一个j,jstring-》String
https://blog.csdn.net/chunleixiahe/article/details/51388577
so文件对应cpu
ARMv5-》armeabi,一般是以前32位手机
ARMv7-》armeabi-v7a,一般是以前32位手机
ARMv8-》arm64-v8a,一般是手机
x86-》x86,一般是模拟器
x86_64-》x86_64,一般是模拟器
逆向框架地址:https://pan.baidu.com/s/1dIjN3mCqL3lr7ZjkIjL_ug,提取码ytdj
启动时hook方法:objection -f 包名 explore -s “hook方法的命令”,跟命令行一致
方法静态注册和动态注册
memory list modules:查看所有内存中deso
静态注册:memory list exports so名,直接查看注册的方法
动态注册:无法直接搜索,https://github.com/lasting-yang/frida_hook_libart
11月课时7
getObjClassName(args):输出args的全限定类名
Frida JavaScript 常用 API:https://www.jianshu.com/p/2475cb4532c8
- 多classloader的hook
反编译可以找到类,但是用java.use的时候就报错找不到,这是该APP本身有多个classloader
Java.use的类并不在frida的默认的classFactory.loader的classloader里面
解决办法:找到类在哪个classloader,然后把classloader改成默认的
Java.enumerateClassLoaders({onMatch:function(loader){try{// 查找类在哪个classloaderif(loader.findClass('com.wzyk.zgyjb.api.param.ParamFactory')){console.log('找到loader:'+loader)// 把对应的classloader设置成默认Java.classFactory.loader=loader}}catch(error){console.log('error:'+error)}},onComplete:function(loader){}})// 切换后use就可以找到了Java.use('com.wzyk.zgyjb.api.param.ParamFactory')
11月课时9
- frida hook抓包
通杀脚本:https://github.com/r0ysue/r0capture
运行如果出现adb server version (32) doesn’t match this client (41):需要升级版本, https://blog.csdn.net/weixin_38515203/article/details/104985570
Spawn 模式:python r0capture.py -U -f app进程名
Attach 模式:python r0capture.py -U app进程名 -p zhuabao.txt,将抓包结果保存到文件
C语言简单入门
- 指针入门

int p:定义int类型的指针,里面只能存放地址,p=100是错误写法
p=&a:把a的地址给p
p:取出p地址的数据
int p和int p是一样
- 指针应用
在逆向中c函数一般不写返回值,一般加密函数是传明文和返回值的地址,然后把加密结果给传入的地址
md5(‘12345678’,接收加密结果的地址),如何根据地址去数据
- 指针运算

数组的内存地址是连续的,数组的地址是根据第一个元素的地址
*(p+1):在数组原地址的基础上偏移1,取到第二个元素,如果是int类型就是加4个字节,根据类型占的字节
- 字符串

c语言没有直接的字符串,字符串是一个字符数组
- 多极指针

多级指针:第二个指针指向第一个指针的地址,第三个指针指向第二个指针的地址
- 结构体

- 函数指针
so层逆向网上视频笔记
案例app:川观新闻
- 分析
hook发现前两个参数都是空的,第三个参数是时间戳
主动调用发现传入固定时间戳返回值也是固定
可以判断时间戳是和固定字符串进行操作然后返回
- so分析
ide打开对应so文件找到getSign
getMD5String:c实现md5加密方法
hook可疑函数MD5Digest
import frida, sys,osdef on_message(message, data):if message['type'] == 'send':print("{0}".format(message['payload']))else:print(message)jscode = '''Java.perform(function () {// so文件地址,夜神模拟器可能获取不到,谷歌原生模拟器模拟器或真机可以获取到var soaddress=Module.findBaseAddress('libwtf.so');// 函数地址,CF0:ide分析的地址var funaddress=soaddress.add(0xCF0+1);// 方法2,根据注册名找地址// var funaddress=Module.findExportByName('libwtf.so','Java_com_sichuanol_cbgc_util_SignManager_getSign');Interceptor.attach(funaddress,{// 进函数前执行的方法,args:参数,hexdump:查看16进制数据,每一个16进制数对应一个字符onEnter:function(args){console.log('args1'+hexdump(args[1]));console.log('args1'+args[1].toInt32());},onLeave:function(retval){// 函数离开调用方法console.log('retval'+hexdump(retval[0]));}})})'''os.system("adb forward tcp:27042 tcp:27042")os.system("adb forward tcp:27043 tcp:27043")# 获取最前的appdevice=frida.get_remote_device()# 获取pidpid=device.get_frontmost_application().pid# 根据pid获取进程session=device.attach(pid)# 加载脚本script = session.create_script(jscode)print('开始')# 打印日志script.on('message', on_message)# 执行脚本script.load()# 脚本执行完不直接结束sys.stdin.read()
- ida动态调试
(1)汇编转伪c代码后出现很多如v10+33类似的偏移值或函数显示错乱
选中入参-》y键-》把值改成JNIEnv*,可以显示一些函数出来
工具栏view-》的一个选项-》string:查看so的字符串
(2)
把安装目录下的dbgsrv下的android_server推送到手机里,改名字可以规避一定的检测
赋权-》chmod 777 as-》./as执行
Genymotion模拟器不支持、其他如夜神模拟器会找不到so,调试一般用真机
如果执行报错可能是版本不匹配,更换其他版本的,
(3)端口转发
adb forward tcp:23946 tcp:23946:一般用默认端口23946,app有反调试就要更换
(4)调试配置
新开ida窗口不打开任何文件下-》debugger-》选项2-》Android debugger-》配置ip和端口-》找到包名-》
进入一个全新界面-》找到modules-》点击对应so-》点击函数名就会定位到对应汇编代码
general registers对应:
PC:运行到哪行就指向哪行地址
LR:保存函数返回地址
如果f9无限循环并且出现got SIGTRAP signal (Trace trap) (exc.code 5, tid 12245)类似的错误,说明有检测
(5)断点
右键-》break point
ida动态调试不会把函数名解析出来,需要开两个ida,一个动态调试,一个静态分析
方法1:工具函数前面的关键字数位置,可能是blx或call
方法2:点击可疑sub_Fxxx-》快捷键c可疑看到对应代码
(6)代码查看
hex view-1窗口右键synchronize with,r0-r2分别对应不同参数
so层逆向网上视频笔记2
案例app:喜马拉雅
- 程序附加
有时候程序附加找不到对应so,可能是代码执行才加载so,只加载一次,需要做对应操作再附加
附加找到对应函数方法2:
同一so同一平台下的动态调试和静态调试函数偏移是一样的
找到函数选中-》tab转到汇编看地址-》根据地址找到动态调试的函数-》双击可以看函数名-》
快捷的c转成代码
debugger-》step over:下一行代码
调试
- 常见反调试
(1)检测文件名,默认名字是android_server
解决办法:改文件名
(2)检测端口号,默认端口号是23946
解决办法:改端口号,./as -p23947
(3)进程名检测,进程Tracerpid不为0说明被调试
解决办法:手动值0
(4)fork一个子进程调试自己,程序只能被一个进程调试
解决办法:直接调试父进程也能达到调试子进程的效果
- 查看是否被调试
过滤进程:ps | grep 包名,第二栏就是pid
查看状态:cat /proc/pid(进程ID)/status,TracerPid为0代表没有被调试,不为0代表在被调试
绕过腾讯加固反调试
- 解壳程序入口点
AndroidManifest.xml下的application标签的android:name属性
- 调试分析
注入后勾选debugger下的debugger setup的library load/unload选项
