MD5提取结果通常是32位,不受明文长度影响;
Base64编码结果末尾通常会出现一或二个等于符号,受明文长度影响;
一长串无规律数字与字母组合的字符大概率是AES、DES、SHA相关加密;
SHA1加密结果值为40位,不受明文长度影响;
SHA256加密结果值为64位,不受明文长度影响;
另外, AES、RSA等对称和非对称加密都喜欢将结果值用Base64进行编码,这样易于传递;
如果你看到一长串字符里出现+号、\号和末尾的=号,那大概率就是上一行描述的加密算法加密后又进行了Base64编码的结果;
但要注意的是32位的字符串不一定是MD5摘要结果, 64位的也不一定是SHA加密结果
NodeJs
var b64encode = new Buffer.from("JavaScript").toString("base64");
console.log(b64encode)
var b64decode = new Buffer.from(b64encode,'base64').toString();
console.log(b64decode)
刷机后时间错误、网络不可访问:
adb shell settings put global captive_portal_http_url https://www.google.cn/generate_204
adb shell settings put global captive_portal_https_url https://www.google.cn/generate_204
adb shell settings put global ntp_server 1.hk.pool.ntp.org
adb shell reboot
Android7以上安装证书:
openssl x509 -inform PEM -subject_hash_old -in cacert.pem
ren charles.pem 2e355b8b.0
adb push 2e355b8b.0 /sdcard/
adb shell
su
mount -o rw,remount /system
mv /sdcard/2e355b8b.0 /system/etc/security/cacerts/
chmod 644 /system/etc/security/cacerts/2e355b8b.0
reboot
计算cer证书hash值
openssl x509 -inform PEM -subject_hash_old -in /Users/wiliam/temp/FiddlerRoot.cer -inform der
“证书安装程序停止运行”解决方法:
手机关机后按电源键和音量- 选择recovery启动
adb root
adb remount
adb push 2e355b8b.0 sdcard/Download/
adb shell
cp sdcard/Download/2e355b8b.0 /data/adb/modules/movecert/system/etc/security/cacerts/
ls /data/adb/modules/movecert/system/etc/security/cacerts/
chown root:root /data/adb/modules/movecert/system/etc/security/cacerts/*
chmod 644 /data/adb/modules/movecert/system/etc/security/cacerts/*
chcon u:object_r:system_file:s0 /data/adb/modules/movecert/system/etc/security/cacerts/*
reboot
PC和手机需要安装版本一致的Frida版本,还要注意手机系统架构
查看手机系统架构:(adb shell中运行)
bullhead:/ # getprop ro.product.cpu.abi
arm64-v8a
pip install frida==12.8.0 frida_tools==5.3.0 objection==1.8.4
Kali 环境
frida 14.2.17
frida-tools 9.2.4
手机 /data/local/tmp/目录下
frida-server-14.2.17-android-arm64 re.frida.server
chmod 777 frida-server-12.11.17-android-arm64
./frida-server-12.11.17-android-arm64
确定frida已建立联系:
frida ps -U
查看手机进程
frida-ps -U
查询网址:https://github.com/frida/frida/releases
在对应版本Frida中查找Frida-tools版本即可
安装frida ide智能提示
(安装nvm,使用node 12的版本)
$ git clone git://github.com/oleavr/frida-agent-example.git
$ cd frida-agent-example/
$ npm install
$ frida -U -f com.example.android --no-pause -l _agent.js
在frida-agent-example/下新建文件夹编写frida脚本
hello world
frida -U -l hello_world.js com.android.bluetooth
(-U为USB, -l为脚本所在路径)
exit 或 Ctrl+D 退出
REPL(Read-Eval-Print Loop)“交互式解释器”或“交互式编程环境”
frida-ps -U | grep 'settings'
objection -g com.android.settings explore
JADX开启反混淆后类名并非原来的类名
方法分为静态方法和实例方法,应当分别从类和实例处重载
frida如何查看HashMap
var Map = Java.use('java.util.HashMap');
var args_map = Java.cast(m, Map);
console.log(args_map.toString());
wallbreaker的使用
7z x frida-server-12.8.0-android-arm64.xz
adb push frida-server-12.8.0-android-arm64 /data/local/tmp
git clone https://github.com/hluwa/Wallbreaker.git ~/.objection/plugins/Wallbreaker
objection -g com.qiyi.video.lite explore -P ~/.objection/plugins/
plugin wallbreaker objectsearch 类名 (每次运行句柄会变化)
plugin wallbreaker objectdump 0x31ba
objection日志文件是: ~/.objection/objection.log
, 可以删除, 方便查看下次的内容.
objection在APP启动时hook
objection -g 包名 explore -s "android hooking watch class 类 --dump-args --dump-backtrace --dump-return"
objection attach app
https://github.com/sensepost/objection/issues/335
╰─$ frida -Uf "cn.kuwo.player" -l anti_frida_detection.js
╰─$ frida-ps -Ua
PID Name Identifier
5 ------------ -----------------------
18833 酷我音乐 cn.kuwo.player
╰─$ objection -g 18833 explore -P ~/.objection/plugins/
或者
╰─$ objection -g `frida-ps -Ua | grep kuwo | awk '{print $1}'` explore -P ~/.objection/plugins/ -c objection_batch_hook.txt
frida在APP启动时hook------send()相当于console.log()
import frida # 导入frida模块
import sys # 导入sys模块
jscode = """
Java.perform(function(){
var c = Java.use("com.tencent.news.tad.common.e.d"); // 类的加载路径
c.ˆ.overload('java.lang.String').implementation = function(str){
send(str);
var r = this.ˆ(str);
send("success2");
send(r);
return r;
};
});
"""
def on_message(message, data): # js中执行send函数后要回调的函数
if message["type"] == "send":
print("[*] {0}".format(message["payload"]))
else:
print(message)
process = frida.get_usb_device()
pid = process.spawn(['com.tencent.news']) # spawn后app会进入空白页面卡住
session = process.attach(pid) # 依据进程号attach进程
script = session.create_script(jscode) # 创建js脚本
script.on('message', on_message) # 加载回调函数,也就是js中执行send函数规定要执行的python函数
script.load() # 加载脚本
process.resume(pid) # 从空白页面恢复运行
sys.stdin.read()
静态函数直接use class然后调用方法,非静态函数需要先choose实例然后调用
Frida疑问:
内部类
new Class() {
public int fun(){}
}
fun没有static为什么可以直接use class然后hook方法?继承
frida怎么实例化枚举类
使用Frida时,想要打印Java对象的内容,可以使用谷歌的gson包
https://bbs.pediy.com/thread-259186.htm
用wallbreaker找到想要查看属性的实例:
objection -g com.tencent.news explore -P ~/.objection/plugins/
com.tencent.news on (google: 8.1.0) [usb] # plugin wallbreaker objectsearch com.tencent.news.tad.business.manager.a
[0x5bda]: com.tencent.news.tad.business.manager.a@3b47eab
查看实例的属性:plugin wallbreaker objectdump 0x5bda
查找相关类,找到实例句柄
com.tencent.news on (google: 8.1.0) [usb] #
- [ ] android heap search instances com.tencent.news.utils.sp.f$b
Using exsiting matches for com.tencent.news.utils.sp.f$b. Use --fresh flag for new instances.
Handle Class toString()
------ -------------------------------------------- ----------------------
0x71e6 com.tencent.news.utils.sp.f$b com.tencent.news.utils.sp.f$b@714da6f
用Objection使用实例句柄调用带参数的方法
com.tencent.news on (google: 8.1.0) [usb] # android heap evaluate 0x71e6
(The handle at `0x71e6` will be available as the `clazz` variable.)
var r = clazz.getString("taid", "");
console.log(r);
JavaScript capture complete. Evaluating...
Handle 0x71e6 is to class com.tencent.news.utils.sp.f$b
0101869F9B239EB76E4D33C8D47D3D64B96FE17E74A91CC327CA1F452E8F00F2ECE8FB329612972826BF88AC
构造Context
var current_application = Java.use('android.app.ActivityThread').currentApplication();
var context = current_application.getApplicationContext();
构造Long类型
Java.use('java.lang.Long').parseLong.overload('java.lang.String').call(Java.use('java.lang.Long'), "3373342304")
查看Long类型的值
console.log(long.value);
打印调用栈
console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
打印字符串数组
// fastjson在大部分app中都有集成
var FastJson = Java.use('com.alibaba.fastjson.JSON');
console.log(FastJson.toJSONString(builder));
let arr_len = Java.vm.getEnv().getArrayLength(retval);
console.log("数组长度:", arr_len)
for (let i=0; i
import time
import frida # 导入frida模块
with open('test2.js') as f:
jscode = f.read()
process = frida.get_usb_device()
pid = process.spawn(['com.android.settings']) # spawn后app会进入空白页面卡住,
process.resume(pid) # resume恢复app的运行
time.sleep(1)
# pid = process.get_process('com.android.settings').pid # 不重启app
print('进程号:', pid)
session = process.attach(pid) # 加载进程号
script = session.create_script(jscode) # 创建js脚本
script.load() # 加载脚本
api = script.exports
r = api.get()
print(r)
function get(){
var base64;
Java.perform(function(){
var StringClass = Java.use("java.lang.String");
var byteArray = StringClass.$new("Hello World").getBytes();
// console.log(byteArray)
// console.log(JSON.stringify(byteArray))
var b = Java.use("java.util.Base64").$new().getEncoder();
base64 = b.encodeToString(byteArray)
// console.log(base64)
})
return base64
}
rpc.exports={
get:get
}
}
rpc.exports={
get:get
}
frida -Uf "air.tv.douyu.android" -l hook_all_map.js --runtime=v8 --debug --no-pause
//frida代码添加
//在chrome开发者工具打开node调试
//python脚本
script = process.create_script(f.read(), runtime='v8')
process.enable_debugger()
adb shell //adb进入命令行模式
su //切换至超级用户
magisk resetprop ro.debuggable 1 //设置debuggable
stop;start; //一定要通过该方式重启
查看效果 为1则正常
#adb shell "getprop ro.debuggable"
1
重启后会重置为0!
为Android Studio安装smalidea插件
https://bitbucket.org/JesusFreke/smali/downloads/
启动调试界面
adb shell am start -D -n 包名/.MainActivity
查找进程号
adb shell ps | grep 包名
使用 jdwp 转发端口:
adb forward tcp:端口 jdwp:进程号
创建remote调试
Android Studio打开apk, 直接Debug运行. 进入后打断点, 操作手机触发断点
如果断点不生效, 卸载app后再Debug (被玩坏了???)
高效学习smali:
Android Studio安装java2smali插件,
Build -> Compile to smali, 就能把java代码转成smali
Xpose不重启方案
mount -o rw,remount -t auto /
替换/system/framework/XposedBridge.jar
chmod 777 XposedBridge.jar
查看当前Activity
adb shell dumpsys activity top | grep ACTIVITY
非标准端口启用 frida-server和objection
/data/local/tmp/frida-server-12.8.0-android-arm64 -l 0.0.0.0:3353
objection -N -h 172.16.90.221 -p 3353 -g com.r0syue.nativetest explore
还原被名称粉碎机制破坏的函数名()
(一调用会报错app无法运行???)
# c++filt _Z54Java_com_r0syue_nativetest_MainActivity_stringFromJNI2P7_JNIEnvP8_jobject
Java_com_r0syue_nativetest_MainActivity_stringFromJNI2(_JNIEnv*, _jobject*)
查看静态注册的JNI函数在哪个so文件:
解压apk, 到lib目录下:
grep -ril "函数名" *
例: grep -ril "getQdsfWithTimestampJNI" *
(r 递归目录 i 忽略大小写 l 只输出文件名)
动态注册的JNI函数需要靠hook定位:
git clone https://github.com/lasting-yang/frida_hook_libart.git
frida -U -l hook_RegisterNatives.js -f com.qiyi.video.lite --no-pause
点击Run后AS会安装app-debug.apk.
手机应用的apk位置在/data/app/包名-base64字符串/base.apk
╰─$ adb shell pm list package | grep music
package:com.tencent.qqmusic
╰─$ adb shell pm path com.tencent.qqmusic
package:/data/app/~~741Xbz7-KBWlNG71ZIFGZQ==/com.tencent.qqmusic-PANj6LE3nCBuwNqarbWvtQ==/base.apk
╰─$ adb pull /data/app/~~741Xbz7-KBWlNG71ZIFGZQ==/com.tencent.qqmusic-PANj6LE3nCBuwNqarbWvtQ==/base.apk qqmusic.apk
/data/app/~~741Xbz7-KBWlNG71ZIFGZQ==/com.tencent.qqmusic-PANj6LE3...: 1 file pulled, 0 skipped. 35.2 MB/s (157805747 bytes in 4.280s)
AS Logcat日志过滤
点击“create New Logcat Filter”, 起个名字,在Log Tag输入
^(?!.*(libc|StudioTransport|GRPC|AudioTrack|SoundPool|Zygote|libprocessgroup)).*$
adb shell dumpsys meminfo -a com.tencent.reading
/data/app/包名***/base.apk
adb shell pm list packages
adb shell pm path com.xd.fp.ad
adb pull /data/app/~~MLGJJLICrscYTrNxIXdzdw==/com.xd.fp.ad-M2awbsAciEqDHes2KrfURg==/base.apk ~/Desktop/KUbuntu/派对之星/
/data/data/包名/databases/
Android Studio -> Build -> Generate signed Bundle/APK 可以生成证书.
apktool d app-release.apk -o outdir_rel 解包apk.
修改smali逻辑......
apktool b outdir_rel 重打包后apk在outdir_rel/dist/目录下面
jarsigner -verbose -keystore xxx.jks(证书) -signedjar xxx.apk(签名后的apk名字) xxx.apk(需要签名的apk) xxx(keystore别名)
https://mp.weixin.qq.com/s/xlgtU4xqoMqv2oXCMko7yQ
为什么用了久置的证书签名安装失败, 新生成的证书就可以呢??可能信息没填完整.
Jeb有内置工具可以修改生成debuggable:true的apk
jeb_wincon.bat -c --makeapkdebug -- file.apk
生成的apk需要重签名
apksigner.bat sign -ks SOME_KEYSTORE.JKS file_debuggable.apk
baksmali 的使用
下载 https://bitbucket.org/JesusFreke/smali/downloads/
java -jar /usr/local/bin/baksmali-2.5.2.jar d Main.dex
Android Studio SDK的dexdump
dexdump -d Main.dex
file xxx.so
或者
readelf -h xxx.so
so和ida的位数不一致就无法使用F5生成伪代码。
ARM 32位对应的是armv7架构、armv6架构、armv5架构
ARM 64位是armv8架构
常用的abi:
armeabi: armv5架构和armv6架构 (32位)
armeabi-v7a:armv7架构 (32位)
armeabi-v8a:armv8架构 (64位)
x86:x86架构 (32位)
x86_64:x86_64架构 (64位)
查看系统架构
# adb shell getprop ro.product.cpu.abi
arm64-v8a
查看手机支持的全部架构
# adb shell getprop ro.product.cpu.abilist
arm64-v8a,armeabi-v7a,armeabi
查看手机架构
# adb shell uname -a
Linux localhost 3.18.70-g91a2acf #1 SMP PREEMPT Fri May 11 01:06:35 UTC 2018 aarch64
aarch64架构的so文件存储在lib/arm64-v8a目录下.
一些apk只有arm架构的so文件, 无法运行在x86/64架构计算机中的模拟器上.
启动android_server
adb forward tcp:23946 tcp:23946
启动APP
IDA Attach
ndk clang编译c文件 64位可执行文件
$ANDROID_HOME/ndk/21.4.7075529/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang -target aarch64-linux-android21 md5.c -o md5aarch64
预处理
$ANDROID_HOME/ndk/21.4.7075529/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang -target arm-linux-android21 -E md5.c -o md5.i
编译
$ANDROID_HOME/ndk/21.4.7075529/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang -target arm-linux-android21 -S md5.i -o md5.s
汇编
$ANDROID_HOME/ndk/21.4.7075529/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang -target arm-linux-android21 -c md5.s -o md5.o
链接 (链接生成的文件才是可执行文件)
$ANDROID_HOME/ndk/21.4.7075529/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang -target arm-linux-android21 md5.o -o md5
汇编并链接
$ANDROID_HOME/ndk/21.4.7075529/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang -target armv7a-linux-android21 hello.s -o hello
查看段
$ANDROID_HOME/ndk/21.4.7075529/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readelf --sections md5
查看符号(符号==函数名?)
$ANDROID_HOME/ndk/21.4.7075529/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-nm md5$ANDROID_HOME/ndk/21.4.7075529/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-nm md5
objdump -T xxx.so 查看动态符号
objdump -t xxx.so 查看所有符号
gdb和gdbserver可以在编译的系统源码里找,也可以在android studio的ndk路径下找~/Library/Android/sdk/ndk/21.4.7075529/prebuilt
添加调试符号
编辑build.gradle(:app), android里添加
packagingOptions{
doNotStrip "*/armeabi/*.so"
doNotStrip "*/armeabi-v7a/*.so"
doNotStrip "*/x86/*.so"
}
gdbserver启动64还是32取决于app进程是64还是32位,
可以用object查看,或者查看app进程的父进程(ppid)是zygote还是zygote64
(PC)app进入debug页面
adb shell am start -D -n com.roysue.easyso1/.MainActivity
(PC)查看app进程
adb shell ps -e | grep -i roysue
(手机)手机gdb-server附加到对应进程,端口默认23946
./gdbserver 0.0.0.0:23946 --attach 5718
(PC)运行gdb进入gdb console
~/Documents/20210120/gdb/darwin-x86/bin/gdb
(gdb)连接手机
target remote 172.16.91.172:23946
(gdb)运行c
c
(PC)恢复App运行
/Applications/Android\ Studio.app/Contents/jre/Contents/Home/bin/jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700
直接运行app
查看进程是32/64和进程id启动gdbserver
/data/local/tmp/prebuilt/android-arm/gdbserver/gdbserver 0.0.0.0:23946 --attach 15631
hyper里启动gdb
(gdb) target remote 192.168.1.104:23946
继续程序的运行
(gdb) c
gdb命令
info shared 查看系统库(无调试信息)
c 运行到下个断点
nm -s libroysue.so | grep method (kali)
cat /proc/15631/status
frida注入器只有在注入so的阶段需要ptrace,注入完后即detach,所以TracerPid为0。
frida注入后可以再使用gdbserver,反过来则不行。
为什么android studio动态调试微信trackerpid为0呢?
(手机)
/data/local/tmp/prebuilt/android-arm/gdbserver/gdbserver 0.0.0.0:23946 ./hello
(hyper)
gdb
target remote 192.168.1.102:23946
b main
c
disassemble main
最简单的反编译器 objdump
“基地址” + “偏移地址”
因为三级流水线的关系,b main会断点在:
用算出来的地址b *0xaaaaa3d4则可以断在:
push {fp, lr} # 保存现场,讲fp(r11)和lr(r14)寄存器值入栈
info register 查看寄存器
ni 步过
Java层是unicode编码,C是ascii编码
使用Host-Only网络,确保虚拟机不联网
adb forward only bind localhost
adb forward tcp:23947 tcp:23946
nohup socat tcp:localhost:23947 tcp-listen:23946 > /dev/null 2>&1 &
adb logcat | fgrep -i intent
在Android中使用vi等linux命令
https://blog.csdn.net/cfy137000/article/details/115160014
cp /data/local/tmp/busybox-armv8l /system/xbin/busybox;chmod 755 /system/xbin/busybox;/system/xbin/busybox --install /system/xbin/
一个IDA小脚本,获取SO代码段中所有函数的偏移地址,再使用frida-trace 批量trace so函数的调用。
https://github.com/Pr0214/trace_natives