为了做出腾讯游戏安全竞赛初赛的这道安卓题,开始学习rwProcMem33 的使用来打硬件断点了
在juice4fun师傅做腾讯游戏安全竞赛初赛的安卓题的writeup时,使用了rwProcMem33来对安卓手机打下硬件断点分析反调试,我也对在安卓手机中打硬件断点的工具很感兴趣,所以就学习一下编译和使用的方法啦
要想使用rwProcMem33,编译环境(即AOSP安卓内核源码环境)的搭建过程是必不可少的,因为最终内核模块是运行在安卓手机的linux内核中,而非虚拟机的linux内核中,所以内核源码是有必要下载的
所以这篇文章不仅是硬件断点工具的编译和使用笔记,也是安卓内核的编译笔记,用来记录我在编译内核的过程中遇到的困难,以及如何克服的
为了更快的下载速度,可以选择配置代理,也可以手动切换下载源,只要不出现网络问题导致下载失败就行
docker的使用完全是因为我的虚拟机shell环境崩溃,从而导致无法编译,如果对自己虚拟机的shell环境足够自信,不使用docker也是可以的
我使用的虚拟机为Ubuntu22.04,虚拟机的参考配置如下

打开clash for windows,并打开Allow LAN的开关,随后点击network interfaces

请注意我的虚拟机使用的网络连接方式为NAT模式,所以需要关注VMnet8的地址,所以对于该虚拟机,代理地址为192.168.27.1,端口就是clash中Port选项所显示的端口

依次点击如下选项进入代理配置

输入代理地址保存即可

本人因为不小心运行了一个命令source _setup_env.sh,导致虚拟机的shell环境整个崩掉了,build.sh也屡屡运行失败,看了眼_setup_env.sh我真是只能苦涩的笑...

所以不得不用docker了,不过用下来发现竟然意外的好用
输入以下代理服务器内容
输入以下内容
替换为如下内容
随后将apt-get更新至最新版本
在末尾添加这三行并保存
如果使用python --version有打印python版本的话,那么这一步就不需要了,如果docker中没有安装python,在docker内使用如下命令安装
为了防止编译源码的过程中由于交换区不足而失败,所以我们需要去修改虚拟机的交换区的大小
这里我的pixel3的内核版本为Linux version 4.9.270-g862f51bac900-ab7613625
进入building-kernels中查看自己的源码分支,如图我的手机型号为pixel3,并且内核版本为4.9,于是就知道内核源码的代号是android-msm-crosshatch-4.9

之后进入安卓内核源码列表中,搜索内核源码代号android-msm-crosshatch-4.9

我的手机是安卓12,所以我下载的内核版本为android-msm-crosshatch-4.9-android12
这里的qpr1和qpr2,我们先看一下QPR的定义,简单来说就是QPR后面跟的数字越高,内核版本就越新
QPR, of course, is short for the Quarterly Platform Release, which Google first introduced with Android 12. These are not full system updates, but they bring a few select changes to the Pixels and other great high-end phones that opt to receive them.
注意一点就是例如你想要下载android-msm-crosshatch-4.9-android10,请先进入你想要下载的AOSP的地址,看看仓库中的default.xml文件,重点关注<project path="build" name="kernel/build" ,如果revision的值为main,请千万不要下载,否则你就会发现下载下来之后根本无法build!!,这是由于build仓库和内核源码仓库不同步导致的

当然你也可以选择进入kernel/build中找到适合你的build file,不过我还是建议能一键编译就一键编译,比如我下载的android-msm-crosshatch-4.9-android12,build和kernel source code就是同步的(惨痛的教训,头铁想要用安卓9的内核源码编译,结果根本无法build...最后还是妥协把手机刷成安卓12了)
我的手机的Linux内核版本为Linux version 4.9.270-g862f51bac900-ab7613625,g后面跟的是git分支,所以切换的分支为862f51bac900
首先下载android-image-kitchen
然后将boot.img放在工具的根目录下,这里的boot.img就是网上下载的刷机包解压之后其中的boot.img

然后运行unpackimg.bat,运行之后的窗口请不要关闭,因为输出中有需要后续使用到的参数,当然也可以将输出的内容复制下来到txt中
当unpackimg.bat运行完毕后,我们进入split_img/,然后解压其中的boot.img-ramdisk.cpio.gz,并将解压后的boot.img-ramdisk.cpio文件复制到内核源码根目录中
我们还需要下载mkbootimg.py,并将其复制到放到内核源码根目录
在内核源码根目录,进入build/build.sh,找到下方代码的位置
并在这两行代码之前加上下列命令

下载地址
然后将解压后的文件夹复制到docker中内核源码目录下的private/msm-google/drivers/中
将MY_LINUX_VERSION_CODE切换到对应的安卓内核版本,我们在下载内核源码阶段已经通过cat /proc/version知道了内核的版本号为Linux version 4.9.270-g862f51bac900-ab7613625,所以在private/msm-google/drivers/rwProcMem33/ver_control.h和private/msm-google/drivers/rwProcMem33/hwBreakpointProcModule/hwBreakpointProc/ver_control.h中我们也将内核切换到对应的4.9版本,选择MY_LINUX_VERSION_CODE的原则选这里出现的版本号中越接近自己手机内核版本的版本号

在Linux 4.11前,Linux内核把页表分为4级
所以对于Linux version 4.11以下的内核版本,并不支持五级页表,选择启用读取pagemap文件来计算物理内存的地址,同时注释掉启用页表计算物理内存的地址如图所示

Linux version 4.11版本把页表扩展到五级,在页全局目录和页上层目录之间增加了页四级目录(Page 4th Directory,P4D)
所以对于Linux version 4.11及以上的内核版本,选择启用页表计算物理内存的地址,同时注释掉启用读取pagemap文件来计算物理内存的地址如图所示

在rwProcMem33/linux_kernel_api文件夹中新建一个头文件linux_kernel_api.h

并写入如下内容
为了包含linux_kernel_api.h头文件,我们在api_proxy.h的前几行中加入#include "linux_kernel_api/linux_kernel_api.h"如图

在private/msm-google/drivers/Makefile的开头加入下列命令
在编译rwProcMem33内核模块时,由于内核编译时会将警告视为错误导致编译内核停止,所以我们要修改Makefile来忽视warning
在private/msm-google/Makefile找到如下位置,在-Wno-format-security后加上一个-w参数

在安卓内核源码的根目录打开终端使用如下命令开始编译
命令的参数为使用android-image-kitchen解包boot.img之后,控制台所打印的参数请务必替换为相对应的参数!!!
参数对应关系为
编译命令中的BUILD_CONFIG为AOSP源码根目录的build.config的软连接所指向的配置文件

所以最终的编译命令为
经过一段时间的等待,编译成功!

生成的boot.img的路径为/android-kernel/out/android-msm-pixel-4.9/dist/boot.img
安装Magisk 下载地址
将由内核源码编译出来的boot.img上传到手机上
然后在手机上打开Magisk,依次点击安装->选择并修补一个文件->/sdcard/boot.img->开始
待修补完成后,将修补后的boot.img传到电脑上
进入rwProcMem33\hwBreakpointProcModule\testHwBpClient文件夹,双击testHwBpClient.vcxproj在visual studio中打开
编译的程序位数应为64位
对于Windows平台编译的HwBpClient,并且需要在testHwBpClientDlg.cpp的这个位置进行修改,将这个位置的llX改为I64X,%zu改成I64d,否则将无法正确输入内容

原因在于C/C++输出64位数在window下和linux下是不一样的
linux
windows
修改完成后如图所示

接下来按下ctrl+B生成即可

编译HwBpServer服务端需要NDK,并将NDK引入环境变量中
NDK可以在android studio中进行安装,依次点击File->Project Structure->SDK Location,找到Android NDK location,点击Download即可开始安装,我这里使用的ndk的版本为ndk25.2.9519653
如果没有安装Android studio,NDK的安装方法可以在谷歌上找到
NDK安装完成后,进入到rwProcMem33\hwBreakpointProcModule\testHwBpServer\jni,打开cmd运行命令
即可完成编译,编译后的文件在rwProcMem33\hwBreakpointProcModule\testHwBpServer\libs中,选择对应手机架构的ELF,push到手机中运行即可
将电脑和我们的测试手机连接同一个手机热点,然后在测试手机中打开设置->WLAN点击我们连接的热点的高级选项,来查看手机的IP地址
将编译出来的程序复制到手机中并运行
查看打印出来的端口号3170

在电脑中运行编译完成的HwBpClient客户端,填入手机的IP地址以及由testHwBpServer.out打印出来的端口号

点击连接即可开始打硬件断点

可以使用命令来查询
也可以使用下面的frida脚本查询so的基址
接下来就可以愉快的打硬件断点啦~
[原创]开源一个Linux内核里进程内存管理模块源码
万字长文教你使用安卓内核驱动进行内存读写
安卓内核驱动编译
AOSP Android 10内核编译刷入Pixel3
kernel编译的哪些坑
eBPF on Android之打补丁和编译内核修正版
Android10 内核编译笔记
sudo apt install docker.io
sudo apt install docker.io
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo gedit /etc/systemd/system/docker.service.d/proxy.conf
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo gedit /etc/systemd/system/docker.service.d/proxy.conf
[Service]
Environment="HTTP_PROXY=58aK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8U0p5&6x3W2)9J5k6e0p5$3z5q4)9J5k6e0t1%4i4K6u0W2x3g2)9K6b7e0M7^5z5e0m8Q4x3V1j5`."
Environment="HTTPS_PROXY=fc2K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8U0p5&6x3W2)9J5k6e0p5$3z5q4)9J5k6e0t1%4i4K6u0W2x3g2)9K6b7e0M7^5z5e0m8Q4x3V1j5`."
Environment="NO_PROXY=localhost,127.0.0.1"
[Service]
Environment="HTTP_PROXY=5e7K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8U0p5&6x3W2)9J5k6e0p5$3z5q4)9J5k6e0t1%4i4K6u0W2x3g2)9K6b7e0M7^5z5e0m8Q4x3V1j5`."
Environment="HTTPS_PROXY=863K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8U0p5&6x3W2)9J5k6e0p5$3z5q4)9J5k6e0t1%4i4K6u0W2x3g2)9K6b7e0M7^5z5e0m8Q4x3V1j5`."
Environment="NO_PROXY=localhost,127.0.0.1"
sudo systemctl daemon-reload
sudo systemctl restart docker
sudo systemctl daemon-reload
sudo systemctl restart docker
sudo mkdir -p ~/.docker/
sudo gedit ~/.docker/config.json
sudo mkdir -p ~/.docker/
sudo gedit ~/.docker/config.json
{
"proxies":
{
"default":
{
"httpProxy": "9e0K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8U0p5&6x3W2)9J5k6e0p5$3z5q4)9J5k6e0t1%4i4K6u0W2x3g2)9K6b7e0M7^5z5e0m8Q4x3V1j5`.",
"httpsProxy": "12bK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8U0p5&6x3W2)9J5k6e0p5$3z5q4)9J5k6e0t1%4i4K6u0W2x3g2)9K6b7e0M7^5z5e0m8Q4x3V1j5`.",
"noProxy": "localhost,127.0.0.1"
}
}
}
{
"proxies":
{
"default":
{
"httpProxy": "b0dK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8U0p5&6x3W2)9J5k6e0p5$3z5q4)9J5k6e0t1%4i4K6u0W2x3g2)9K6b7e0M7^5z5e0m8Q4x3V1j5`.",
"httpsProxy": "170K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8U0p5&6x3W2)9J5k6e0p5$3z5q4)9J5k6e0t1%4i4K6u0W2x3g2)9K6b7e0M7^5z5e0m8Q4x3V1j5`.",
"noProxy": "localhost,127.0.0.1"
}
}
}
docker pull ubuntu
docker run -it --net host --name Akernel ubuntu /bin/bash
docker run -it --net host --name Akernel ubuntu /bin/bash
apt-get update
apt-get install vim
apt-get install sudo
apt-get update
apt-get install vim
apt-get install sudo
sudo cp /etc/apt/sources.list /etc/apt/sources.list_backup
sudo vim /etc/apt/sources.list
sudo cp /etc/apt/sources.list /etc/apt/sources.list_backup
sudo vim /etc/apt/sources.list
deb 7d5K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3#2A6M7Y4u0G2M7Y4y4Q4x3X3g2S2L8r3W2&6N6h3&6Q4x3X3g2U0L8$3#2Q4x3V1k6#2j5Y4g2F1N6s2g2Q4x3V1j5`. jammy main restricted universe multiverse
deb-src 57cK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3#2A6M7Y4u0G2M7Y4y4Q4x3X3g2S2L8r3W2&6N6h3&6Q4x3X3g2U0L8$3#2Q4x3V1k6#2j5Y4g2F1N6s2g2Q4x3V1j5`. jammy main restricted universe multiverse
deb 7d1K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3#2A6M7Y4u0G2M7Y4y4Q4x3X3g2S2L8r3W2&6N6h3&6Q4x3X3g2U0L8$3#2Q4x3V1k6#2j5Y4g2F1N6s2g2Q4x3V1j5`. jammy-security main restricted universe multiverse
deb-src e01K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3#2A6M7Y4u0G2M7Y4y4Q4x3X3g2S2L8r3W2&6N6h3&6Q4x3X3g2U0L8$3#2Q4x3V1k6#2j5Y4g2F1N6s2g2Q4x3V1j5`. jammy-security main restricted universe multiverse
deb 5bbK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3#2A6M7Y4u0G2M7Y4y4Q4x3X3g2S2L8r3W2&6N6h3&6Q4x3X3g2U0L8$3#2Q4x3V1k6#2j5Y4g2F1N6s2g2Q4x3V1j5`. jammy-updates main restricted universe multiverse
deb-src eeeK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3#2A6M7Y4u0G2M7Y4y4Q4x3X3g2S2L8r3W2&6N6h3&6Q4x3X3g2U0L8$3#2Q4x3V1k6#2j5Y4g2F1N6s2g2Q4x3V1j5`. jammy-updates main restricted universe multiverse
# deb d33K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3#2A6M7Y4u0G2M7Y4y4Q4x3X3g2S2L8r3W2&6N6h3&6Q4x3X3g2U0L8$3#2Q4x3V1k6#2j5Y4g2F1N6s2g2Q4x3V1j5`. jammy-proposed main restricted universe multiverse
# deb-src 0c0K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3#2A6M7Y4u0G2M7Y4y4Q4x3X3g2S2L8r3W2&6N6h3&6Q4x3X3g2U0L8$3#2Q4x3V1k6#2j5Y4g2F1N6s2g2Q4x3V1j5`. jammy-proposed main restricted universe multiverse
deb e8aK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3#2A6M7Y4u0G2M7Y4y4Q4x3X3g2S2L8r3W2&6N6h3&6Q4x3X3g2U0L8$3#2Q4x3V1k6#2j5Y4g2F1N6s2g2Q4x3V1j5`. jammy-backports main restricted universe multiverse
deb-src 19cK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3#2A6M7Y4u0G2M7Y4y4Q4x3X3g2S2L8r3W2&6N6h3&6Q4x3X3g2U0L8$3#2Q4x3V1k6#2j5Y4g2F1N6s2g2Q4x3V1j5`. jammy-backports main restricted universe multiverse
deb ec8K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3#2A6M7Y4u0G2M7Y4y4Q4x3X3g2S2L8r3W2&6N6h3&6Q4x3X3g2U0L8$3#2Q4x3V1k6#2j5Y4g2F1N6s2g2Q4x3V1j5`. jammy main restricted universe multiverse
deb-src 28eK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3#2A6M7Y4u0G2M7Y4y4Q4x3X3g2S2L8r3W2&6N6h3&6Q4x3X3g2U0L8$3#2Q4x3V1k6#2j5Y4g2F1N6s2g2Q4x3V1j5`. jammy main restricted universe multiverse
deb 9fcK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3#2A6M7Y4u0G2M7Y4y4Q4x3X3g2S2L8r3W2&6N6h3&6Q4x3X3g2U0L8$3#2Q4x3V1k6#2j5Y4g2F1N6s2g2Q4x3V1j5`. jammy-security main restricted universe multiverse
deb-src 672K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3#2A6M7Y4u0G2M7Y4y4Q4x3X3g2S2L8r3W2&6N6h3&6Q4x3X3g2U0L8$3#2Q4x3V1k6#2j5Y4g2F1N6s2g2Q4x3V1j5`. jammy-security main restricted universe multiverse
deb 60cK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3#2A6M7Y4u0G2M7Y4y4Q4x3X3g2S2L8r3W2&6N6h3&6Q4x3X3g2U0L8$3#2Q4x3V1k6#2j5Y4g2F1N6s2g2Q4x3V1j5`. jammy-updates main restricted universe multiverse
deb-src db2K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3#2A6M7Y4u0G2M7Y4y4Q4x3X3g2S2L8r3W2&6N6h3&6Q4x3X3g2U0L8$3#2Q4x3V1k6#2j5Y4g2F1N6s2g2Q4x3V1j5`. jammy-updates main restricted universe multiverse
# deb cb9K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3#2A6M7Y4u0G2M7Y4y4Q4x3X3g2S2L8r3W2&6N6h3&6Q4x3X3g2U0L8$3#2Q4x3V1k6#2j5Y4g2F1N6s2g2Q4x3V1j5`. jammy-proposed main restricted universe multiverse
# deb-src abcK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3#2A6M7Y4u0G2M7Y4y4Q4x3X3g2S2L8r3W2&6N6h3&6Q4x3X3g2U0L8$3#2Q4x3V1k6#2j5Y4g2F1N6s2g2Q4x3V1j5`. jammy-proposed main restricted universe multiverse
deb 4feK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3#2A6M7Y4u0G2M7Y4y4Q4x3X3g2S2L8r3W2&6N6h3&6Q4x3X3g2U0L8$3#2Q4x3V1k6#2j5Y4g2F1N6s2g2Q4x3V1j5`. jammy-backports main restricted universe multiverse
deb-src 7d9K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3#2A6M7Y4u0G2M7Y4y4Q4x3X3g2S2L8r3W2&6N6h3&6Q4x3X3g2U0L8$3#2Q4x3V1k6#2j5Y4g2F1N6s2g2Q4x3V1j5`. jammy-backports main restricted universe multiverse
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install build-essential
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install build-essential
sudo apt-get install git-core gnupg flex bison build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 libncurses5 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z1-dev libgl1-mesa-dev libxml2-utils xsltproc unzip fontconfig libssl-dev bc kmod cpio git curl
sudo apt-get install git-core gnupg flex bison build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 libncurses5 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z1-dev libgl1-mesa-dev libxml2-utils xsltproc unzip fontconfig libssl-dev bc kmod cpio git curl
git config --global user.email "xxx@gmail.com"
git config --global user.name "xxx"
git config --global http.proxy 192.168.27.1:7890
git config --global user.email "xxx@gmail.com"
git config --global user.name "xxx"
git config --global http.proxy 192.168.27.1:7890
mkdir ~/bin
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
mkdir ~/bin
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
sudo vim ~/.bashrc
export REPO_URL='cb7K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6E0K9i4u0J5L8%4u0K6i4K6u0W2N6s2g2F1j5g2)9J5k6i4c8K6K9h3&6Y4K9s2g2S2i4K6u0W2k6h3c8#2i4K6u0W2j5$3&6Q4x3V1k6Y4K9i4c8Q4x3V1k6Y4K9i4c8Q4x3X3c8J5k6i4m8G2i4K6u0r3i4K6t1%4
export PATH="~/bin:$PATH"
export REPO_URL='8dcK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6E0K9i4u0J5L8%4u0K6i4K6u0W2N6s2g2F1j5g2)9J5k6i4c8K6K9h3&6Y4K9s2g2S2i4K6u0W2k6h3c8#2i4K6u0W2j5$3&6Q4x3V1k6Y4K9i4c8Q4x3V1k6Y4K9i4c8Q4x3X3c8J5k6i4m8G2i4K6u0r3i4K6t1%4
export PATH="~/bin:$PATH"
source ~/.bashrc
sudo apt-get install software-properties-common
add-apt-repository ppa:deadsnakes/ppa
sudo apt install python3.9
sudo ln -s /usr/bin/python3 /usr/bin/python
sudo apt-get install software-properties-common
add-apt-repository ppa:deadsnakes/ppa
sudo apt install python3.9
sudo ln -s /usr/bin/python3 /usr/bin/python
sudo swapoff /swapfile
sudo rm /swapfile
sudo dd if=/dev/zero of=/swapfile bs=1GB count=32
sudo chmod 600 /swapfile
sudo mkswap -f /swapfile
sudo swapon /swapfile
sudo swapoff /swapfile
sudo rm /swapfile
sudo dd if=/dev/zero of=/swapfile bs=1GB count=32
sudo chmod 600 /swapfile
sudo mkswap -f /swapfile
sudo swapon /swapfile
adb shell cat /proc/version
Linux version 4.9.270-g862f51bac900-ab7613625 (android-build@abfarm-east4-101) (Android (7284624, based on r416183b) clang version 12.0.5 (https://android.googlesource.com/toolchain/llvm-project c935d99d7cf2016289302412d708641d52d2f7ee))
adb shell cat /proc/version
Linux version 4.9.270-g862f51bac900-ab7613625 (android-build@abfarm-east4-101) (Android (7284624, based on r416183b) clang version 12.0.5 (https://android.googlesource.com/toolchain/llvm-project c935d99d7cf2016289302412d708641d52d2f7ee))
mkdir android-kernel && cd android-kernel
repo init -u https://android.googlesource.com/kernel/manifest -b android-msm-crosshatch-4.9-android12
repo sync -j4