Android逆向零基础到入坟
一、JNI开发
Java native interface:是一种java和c\c++交互的通道;这个是java的一种语言特性,与android无关。
1、创建项目
普通项目:Empty Activity(Java)
jni项目:Native C++(Java + C)
通项目也可以手动配置成jni项目,但是比较
Project选择Native C++。
其他选项无所谓,next就行。
2、编码实例
项目创建完毕后,可以在MainActivity.java中看到有一个native修饰stringFromJNI函数。
并且可以在左边的项目结构中看到有cpp文件夹,展开后可以看到有一个native-lib.cpp文件,双进进入可以看到有一个函数实现。
默认会对函数名折叠,单击灰色的函数名即可看到完整的函数名。
jni类型的函数名为:Java_包名_1static_类名_函数名,其中头文件jni.h为必须引入。回到MainActivity.java中自己添加两个函数。
首先可以看到报错了,鼠标放上去。
根据提示点击Create JNI function for add会自动生成对应函数体。
编写下列代码。
add函数直接正常编写即可。getName由于是c语言实现的函数,自身并没有java的String类,无法直接返回,但可以通过调用env→NewStringUTF(const char*)函数进行转换后返回。
回到MainActivity中调用,并输出查看。
3、JNI注册
创建Native C++项目后会发现多了一个CMakeList.txt,打开查看内容。
cmake_minimum_required:cmake的最低版本。project:项目名。add_library:欲添加的c库。在默认配置中含义为添加名为${CMAKE_PROJECT_NAME},src为native-lib.cpp这个库(编译产出为so文件,为linux动态链接库文件。)target_link_libraries:要链接的库,默认配置添加了${CMAKE_PROJECT_NAME}
一旦工程编译,则会生成对应so文件在build/intermadiates/cxx/Debug/{xxxxx}/obj/{arch}/下,例如项目默认的so为libnative_static.so。
3.1 静态注册
手动创建一个enc.java、enc.cpp文件。
enc.java:用来声明native函数。enc.cpp:用来定义native函数实现。
java代码如下:
System.loadLibrary("enc");表示要加载这个库文件。然后按照相同的方法创建对象体,并实现代码。
由于此时并没有对CMakeList.txt修改,因此会出现很多报错。按照下列方式进行修改。
最后Build→Refresh Links C++ Projects刷新一下cmake即可。入口函数调用。
3.2 动态注册
动态注册只是c/c++代码实现不同,其他设置还是一样。但需要一个注册格式,生成步骤如下:
1、获取enc类名路径。
2、终端跳转到项目java路径下。
3、输入javah path。
会生成一个.h文件,打开即可看到格式。
编写如下代码:
二、进程内存读写
CLion+NDK环境,具体搭建见官方链接:https://developer.android.google.cn/ndk/guides/ndk-build?hl=zh-cn
这里贴一下项目结构和mk文件。
打开说明一下最后一行,官方给的说明有很多个。这里因为是生成可执行文件,因此这里是$(BUILD_EXCUTEABLE)。
2.1 ptrace
man文档:https://man7.org/linux/man-pages/man2/ptrace.2.html
实际上就是个调试命令,可以对进程附加、读写等操作。
1 | |
由于开发环境在mac上,因此宏可能和linux上不太一样,linux(PTRACE_)mac(PT_)
2.2 proc读写
linux中执行的进程被管理在/proc中,每个进程以目录的形式管理,目录名为进程id。
随便进入一个进程中。
其他目录不做解释,mem代表为进程内存,因此可以通过linux的io命令打开以为文件形式读写。
1 | |
2.3 process_vm
man手册:https://man7.org/linux/man-pages/man2/process_vm_readv.2.html
说白了就是两个进程间测内存数据传输,然后这里提一下官方最后一句:两个数据直接相互传输,不会经过内核空间。指的是不会将数据从一个进程的用户空间复制到内核空间,再从内核空间复制到目标进程的用户空间。这样提高了效率,而且三个内存读写中,这个方法也是效率最高的。
1 | |
这里可以直接调用process_vm_readv、process_vm_writev,但是部分环境上不会有这个函数,所以也可以syscall
三、Charles抓包
首先说明,一定要去官方下载正版,盗版一定别用,踩坑了,呜呜呜呜!!!!!!
官方链接:https://www.charlesproxy.com/
在线注册机:https://zzzmode.com/mytools/charles/
charles下载后开启,第一个设置是把电脑代理关闭(默认是开启的),不关闭,电脑无法上网。
关闭方式:Proxy→ macOSA Proxy。macOS是我电脑系统,这个根据你系统来显示。
然后是关闭启动时自动开启:Proxy→Proxy Settings,取消勾选Enable macOS proxy on launch。
3.1 设置代理端口(可默认)
Proxy→Proxy Settings
设置完毕后实际上已经可以抓包了,但是只能抓http的包。下一步设置ssl证书后就可以抓https的包了。
3.2 设置ssl
Proxy→SSL Proxy Settings
点击Add后host和port全部填*,代表对所有的https请求捕获,这个后续可以自己优化,比如只对指定host的https进行抓包。
3.3 Android安装证书
这一步,千万,一定,必须,用的是官方的Charles,不然证书有问题(安装成功了依然没法抓https包)。问就是踩坑了。
Help→SSL Proxying,然后这里可以选择Save Charle Root Certificate,也可以选择第四个install charles root ..... remote browser(这个具体操作就不说了)。
将导出的证书用adb拉进手机后先不忙安装证书,需要安装一个模块。
在Android 8.0设备上root设备只需要将上面生成的
xxx.0文件直接拷贝到/system/etc/security/cacerts目录下即可导入成功。但是在再高版本的系统上,即使是获取了root权限,也难以修改系统分区文件属性来进行读写。经常会出现一下错误提示:
- Read-only file system
- mount: '/system' not in /proc/mounts
- 等等。
使用KernelSU或者面具安装这个模块,这个模块主要作用就是把用户证书自动移动到系统证书中(安装证书后,需要重启手机生效)。
首先安装证书后,重启手机,然后到系统级证书查看。
可以看到最后一个证书为Charles,没有这一步操作前,这个证书可以在用户级中看到,现在移动过来后就看不到了。
3.4 手机设置代理
首先获取charles的ip,Help→Local IP Address。
这里有两个方法。
3.4.1 手动设置网络代理
ip填写上边获取到的内容,端口填第一步设置的HTTP Proxy端口。点击确定后即可抓包。
3.4.2 socksDroid
手机安装这个apk,打开后
Server IP依旧填写上边获取到的IP,Server Port则填写第一步中SOCKS Proxy中设置的端口。然后点击右上角的开关,开启即可。
开启成功时,右上角状态栏会有一个钥匙状态图标,表示生效。
3.5 抓包
上边设置完毕后,直接可以抓包了。