NDK汇编(开发)
基础配置
https://www.jianshu.com/p/c546783ad284
idea安装cmake和NDK
1、ubuntu自动加进环境变量
2、windows要自己添加
source ~/.bashrc
1
| ndk-build NDK_PROJECT_PATH=. NDK_APPLICATION_MK=Application.mk
|
IDA远程调试:
1 2
| 1、把 IDA dbgsrv目录下的文件在手机执行 android_server 2、用32位IDA Debugger调试程序
|
elf文件
arm 模式:定长指令集,四个字节
thumb 模式:不定长
T标志位
clang 开发
https://developer.android.com/ndk/guides/other_build_systems?hl=zh-cn
https://www.cnblogs.com/burner/p/clang-fen-si-bu-bian-yimainc.html
clang路径在SDK/NDK下
1 2
| C:\Users\admin\AppData\Local\Android\Sdk\ndk\28.0.12674087\toolchains\llvm\prebuilt\windows-x86_64\bin C:\Users\admin\AppData\Local\Android\Sdk\ndk\28.0.12674087\toolchains\llvm\prebuilt\linux-x86_64\bin
|
GDB
安装GEF
GDB multiarch 远程调试,原理同IDA远程调试,需上传服务端文件
1 2 3 4 5 6 7 8
| Sdk/ndk/23.1.7779620/prebuilt/android-arm/gdbserver ./gdbserver :1234 hello.o
gdb-multiarch target remote ip:port
gdb-multiarch gef-remote -p 3929 ip:port #雷电需要用x86_64版本,提示权限不足
|
ARM 案例
案例一
在 .o文件里用汇编代替原有函数(print、getchar)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #printf #只有return 0的汇编 main: .fnstart @ %bb.0: .pad #4 sub sp, sp, #4 movw r0, #0 str r0, [sp] movw r0, #0 add sp, sp, #4 bx lr
main: .fnstart push {lr}
ldr r0,[r1,#4] bl printf
movw r0, #0 pop {lr} bx lr
|
案例二
根据汇编还原为C代码
1、IDA打开v7a的 SO文件
2、找到导出 check
3、修改第一个默认参数为 JNIEnv,这样就能关联到内置的函数
4、算法还原
这些R0 、R1指代第一第二个参数吗
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| TestDec ; CODE XREF: j_TestDec+8↑j .text:00001062 ; DATA XREF: LOAD:00000250↑o ... .text:00001062 ; __unwind { .text:00001062 PUSH {R4,R5,R7,LR} .text:00001064 ADD R7, SP, #8 .text:00001066 MOV R4, R0 .text:00001068 BLX strlen .text:0000106C CMP R0, #2 .text:0000106E BCC loc_108A .text:00001070 MOVS R5, #0 .text:00001072 .text:00001072 loc_1072 ; CODE XREF: TestDec+26↓j .text:00001072 ADDS R1, R4, R5 .text:00001074 LDRB R0, [R4,R5] .text:00001076 LDRB R2, [R1,#0x10] .text:00001078 STRB R2, [R4,R5] .text:0000107A ADDS R5, #1 .text:0000107C STRB R0, [R1,#0x10] .text:0000107E MOV R0, R4 ; s .text:00001080 BLX strlen .text:00001084 CMP.W R5, R0,LSR#1 .text:00001088 BCC loc_1072 .text:0000108A .text:0000108A loc_108A ; CODE XREF: TestDec+C↑j .text:0000108A LDRB R0, [R4] .text:0000108C CBZ R0, locret_10B8 .text:0000108E LDRB R1, [R4,#1] .text:00001090 STRB R1, [R4] .text:00001092 STRB R0, [R4,#1] .text:00001094 MOV R0, R4 ; s .text:00001096 BLX strlen .text:0000109A CMP R0, #3 .text:0000109C BCC locret_10B8 .text:0000109E MOVS R5, #0 .text:000010A0 .text:000010A0 loc_10A0 ; CODE XREF: TestDec+54↓j .text:000010A0 ADDS R0, R4, R5 .text:000010A2 LDRB R1, [R0,#2] .text:000010A4 LDRB R2, [R0,#3] .text:000010A6 STRB R2, [R0,#2] .text:000010A8 STRB R1, [R0,#3] .text:000010AA MOV R0, R4 ; s .text:000010AC BLX strlen .text:000010B0 ADDS R1, R5, #4 .text:000010B2 ADDS R5, #2 .text:000010B4 CMP R1, R0 .text:000010B6 BCC loc_10A0 .text:000010B8 .text:000010B8 locret_10B8 ; CODE XREF: TestDec+2A↑j .text:000010B8 ; TestDec+3A↑j .text:000010B8 POP {R4,R5,R7,PC} .text:000010B8 ; End of function TestDec
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| #include <stdio.h> #include <string.h> #include <stdlib.h> int TestDec(char *str){ char *r4 = str; int lenstr = strlen(str); if(lenstr>=2){ for(int r5=0;r5< lenstr>>1;r5++){ char * r1 = r4+r5; char r0 = *(r4+r5); char r2 = *(r1+16); *(r4+r5) = r2; *(r1+16) = r0; } } char r0 = *(r4); if(r0){ char r1 = *(r4+1); *(r4) = r1; *(r4+1) = r0; if(lenstr >= 3){ for(int r5=0; r5+4 < lenstr;r5+=2){ char *rr0 = r4+r5; char rr1 = *(rr0+2); char rr2 = *(rr0+3); *(rr0+2) = rr2; *(rr0+3) = rr1; } } } printf("%s\n",r4); return 0; }
int main(){ char *s = "9007b55be5bf95adf72c5a365694182a"; int lenstr = strlen(s); char *arg = (char*)malloc(lenstr+1); memset(arg,0,lenstr+1); memcpy(arg,s,lenstr); TestDec(arg); return 0; }
|
可引入IDA 提供的 defs.h 后直接运行伪代码
https://www.52pojie.cn/forum.php?mod=viewthread&tid=1584115&highlight=ida
IDA快捷键&常用方法
- 汇编 & 伪代码的跳转(空格、Tab)
- 强制当做代码/数据(C、D)
- 数据 convert
- 重命名
- 查找调用链,Xref graph to
- 插件使用
https://blog.csdn.net/qq_41028985/article/details/119407917
熟悉算法
用于识别魔改算法或分析算法
输入信息/输出信息要hex编码
md5算法
SHA1算法
SHA2/256/512等后续一堆
HMAC(salt)
https://space.bilibili.com/253413704
1 2 3
| message:加密消息 key:加密密钥(需要补充) opad 和 ipad 都是固定
|
DES
1 2 3 4 5
| https://www.bilibili.com/video/BV1134y1Y71j https://www.bilibili.com/video/BV1QW411B7A4 https://www.bilibili.com/video/BV1KQ4y127AT https://juejin.cn/post/7084242293816983589 https://cloud.tencent.com/developer/article/1497864
|
https://www.cnblogs.com/jikexianfeng/p/10192024.html
CLion
分组加密
https://blog.csdn.net/a745233700/article/details/102311776
https://segmentfault.com/a/1190000040964999
https://www.bilibili.com/video/BV1U8411f74f/
AES
https://www.bilibili.com/video/BV1824y1y7gc
12345678,8个字节,64个位
APK未抹去符号表,MD5算法是否魔改分析
1、提取 so,用IDA分析
2、根据原MD5的几个关键步骤,分析汇编。搜索固定的表内容,没被魔改可以搜到
3、Hook SO地址
MD5常见魔改点:
1、明文加盐或填充
2、初始魔数的修改
3、常量表K
4、左移次数
5、F,G,H,I四个非线性变换函数等的逻辑
unidbg
IDA快捷键:H、Y、Tab
IDA 动态调试之反调试
遗留问题:虚拟机debuggable=1
1、getprop ro.debuggable = 0 的话 IDA 动态调试看不到进程名,部分功能被屏蔽
真机用:agiskHide Props Config 修改成功
虚拟机暂未成功
2、查看线程名要用新版的IDA,实测7.0的看不到,7.7的就看得到
1 2 3 4 5 6
| 1.Attach模式 附加 so动态调试。过掉反调试的方法 2.Spwan模式 过掉反调试的方法:这里讲原理
1. nop掉 2. 挂起线程 3. frida hook
|
IDA调试tips:
1 2 3 4 5 6
| 1、真机无网络通过USB调试,需配置端口转发才能IDA远程调试 adb forward tcp:23946 tcp:23946 本机->设备 adb reverse tcp:23946 tcp:23946 设备->本机 adb forward --remove tcp:<port>
2、静态调试和动态调试,IDA自动化分析的注释不同
|
步骤:
1 2 3 4
| 1、进入IDA动态调试,点击运行崩溃 2、在Threads窗口,找和包名一样的线程,Suspended 挂起运行正常 3、在Modules窗口,搜索包名/运行关键词/check/security,找到检测/校验模块,双击进入对应代码,下断点 4、点击触发,Tab切换伪代码
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| var ByPassTracerPid = function () { var fgetsPtr = Module.findExportByName("libc.so", "fgets"); var fgets = new NativeFunction(fgetsPtr, 'pointer', ['pointer', 'int', 'pointer']); Interceptor.replace(fgetsPtr, new NativeCallback(function (buffer, size, fp) { var retval = fgets(buffer, size, fp); var bufstr = Memory.readUtf8String(buffer); if (bufstr.indexOf("TracerPid:") > -1) { Memory.writeUtf8String(buffer, "TracerPid:\t0"); console.log("tracerpid replaced: " + Memory.readUtf8String(buffer)); } return retval; }, 'pointer', ['pointer', 'int', 'pointer'])); }; setImmediate(ByPassTracerPid);
|
参考文章:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| Android修改ro.debuggable 的四种方法 https://blog.csdn.net/jinmie0193/article/details/111355867
IDA动态调试破解AliCrackme与反调试对抗 https://blog.csdn.net/weixin_39190897/article/details/120808079
[原创]2015年AliCrackMe第二题的分析之人肉过反调试 https://bbs.pediy.com/thread-258595.htm
常用命令: adb shell am start -D -n com.yaotong.crackme/.MainActivity adb shell ps | findstr crackme jdwp协议端口转发:adb forward tcp:8700 jdwp:2494 jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700
|
APP过ROOT检测
安装面具:
https://www.bilibili.com/video/BV1UN4y137Z5/?vd_source=43c2c404de6d798650d44c856ee1e992
https://bbs.kanxue.com/thread-263203.htm
修改固有面具(修改源码)
https://blog.csdn.net/qq_41155858/article/details/127885048
root检测:
1.在代码中检测 -> hook/修改重打包(代码固有API检测是否root?)
2.检测系统属性(检测app安装的系统环境参数)
3.查找字符串(查找root关键词,比如su)
对抗方法:
1.hook
2.最新版magisk(配置排除列表、随机文件名) + shamiko(可有可无)+随机magisk
3.需要重新编译面具 改su名称(这个有点麻烦,最新版gsyh过不去就这个)
1 2 3 4
| 小米6重装最新版Magisk就可以了,直接过三个(新版的gs只开还是过不了) adb reboot bootloader https://magiskcn.com/ https://blog.csdn.net/qq_42663692/article/details/135704736
|
绕过的具体操作
1、最新版面具
2、修改面具名称
3、用自带的隐藏root模块
4、修改su名称
Tips:
1、面具安装在真机,需要提取真机boot,通过面具修复后生成.img文件,再重新刷回手机
2、面具安装在模拟器,要安装修改的magisk-delta版本,有直接刷在系统选项(https://magisk-delta.com/)
自编译面具
环境:win10
1 2 3 4 5 6 7 8
| 1、用AS自带的 java11,设置为环境变量 2、全程挂梯子 3、windows 用旧版 python,如python3.8
git clone --recurse-submodules https://github.com/topjohnwu/Magisk.git python build.py ndk python build.py clean python build.py -v all
|
需要修改成自定义指令的地方
1 2
| val isActive = versionCode > 0 追踪逻辑 "su","--mount-master"
|
Apktoolbox 重打包
windwos坑太多,用ubuntu试试,用ubuntu挂梯子
参考链接:
1 2
| https://blog.csdn.net/qq_41155858/article/details/127885048?spm=1001.2014.3001.5506 https://zhuanlan.zhihu.com/p/385255256
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| https://www.jianshu.com/p/c546783ad284 https://developer.android.com/ndk/guides/other_build_systems?hl=zh-cn https://www.cnblogs.com/burner/p/clang-fen-si-bu-bian-yimainc.html 编译博客也不错 https://blog.csdn.net/qq_31865983/article/details/89402100 这个更加完整一点 https://github.com/hugsy/gef https://www.likecs.com/show-204245381.html#sc=400 Cortex-A7 常用汇编指令资料: https://www.cnblogs.com/iron2222/p/15640269.html
gdb调试器快速上手教程 https://blog.csdn.net/qq_45953886/article/details/127678876
ARM官方汇编指令 https://blog.csdn.net/oqqHuTu12345678/article/details/125683244
ARM汇编基础 https://www.cnblogs.com/hilfloser/p/10516610.html
ARM关于标志位影响详解 https://blog.csdn.net/tabactivity/article/details/90407858
ARM的九种寻址方式 https://blog.csdn.net/qq_43743762/article/details/105056991
### 5.编写第一个汇编程序
> https://www.w3cschool.cn/c/c-file-io.html
参考资料:https://softool.cn/read/arm_assembly_basic_aye/21010203.html
https://blog.csdn.net/qq_41028985/article/details/119407917
### 6.逆向C程序-数据类型
> 计算器: > https://www.bangnishouji.com/tools/224457.html
##### 1.32位浮点数表示方法:
> 二进制数怎么转化为浮点数?阶码又是怎么算出来的? > https://zhidao.baidu.com/question/750285508423217012.html
算法篇:ios和安卓通用
参考连接: https://www.cnblogs.com/xiaxveliang/p/15004954.html https://blog.csdn.net/sinat_27933301/article/details/79538169 https://www.cnblogs.com/DeeLMind/p/7581423.html https://www.bilibili.com/video/BV1aP411M7ug:强推
https://www.bilibili.com/video/BV1V14y1T7LM https://blog.csdn.net/ZCShouCSDN/article/details/84675235
|