这些工具正常情况下只能工作于 linux/mac 系统之上,为个人常用功能的封装,并未特意考虑兼容 Windows 但是这不代表 lamda 不支持。如果你使用的是 Windows,以.sh
结尾的脚本应该无法正常工作。
开始之前,请确保已经启动设备上的 lamda 服务端。
注意:部分命令文档可能具有时效性随时更新,为了避免版本问题,继续前请务必先在手机上安装最新版本的 lamda 以及其 Python 库和依赖库。部分功能需要使用 adb,请务必确保安装的 adb 是最新版本。
# 如果没有安装,请 自行搜索 如何安装,这里提供的只是基础建议
# Windows
https://developer.android.com/studio/releases/platform-tools
# Mac
brew install android-platform-tools
#brew cask install android-platform-tools
# Debian/Ubuntu
apt install adb
克隆代码到本地
git clone https://github.com/rev1si0n/lamda.git
# 如果不会使用或未安装 git,下载此文件到本地并解压
# https://github.com/rev1si0n/lamda/archive/refs/heads/master.zip
进入 tools 目录并安装所需的依赖包
# 切换到 tools/ 目录并执行
pip3 install -r requirements.txt
如果你在服务端启用了通信加密(certificate),你需要在使用前设置环境变量 CERTIFICATE
# 对于 linux / Mac
export CERTIFICATE=/path/to/lamda.pem
# 对于 Windows(路径不能包含空格)
set CERTIFICATE=C:\Users\path\to\lamda.pem
如果你修改了 lamda 的默认端口 65000,也需要在使用前设置环境变量
# 对于 linux / Mac
export PORT=8123
# 对于 Windows(路径不能包含空格)
set PORT=8123
192.168.1.2 为示例IP,请自行获取设备的实际IP地址。
用来生成用于传输加密的证书
注:你有可能需要手动安装 pyOpenSSL 依赖库
pip install pyOpenSSL
python3 cert.py
如果你需要生成特定 CN 的证书
python3 cert.py device1.example.com
即可,当前目录下的 lamda.pem 或者 device1.example.com.pem 即为所需的证书。 在服务端应用该证书后,客户端也必须使用此证书来进行远程调用以及 ssh 连接。 应用此证书后,将会加密任何通过 client 库进行的操作,内置 SSH 将不再使用默认的秘钥。 同时,web 控制页面将需要使用 HTTPS 方式访问且需要登录(你可以在证书的第一行找到这个固定密码),
如果操作系统不方便使用此工具,当前目录下已经为你准备好了一个默认的 SSL 证书
test.pem # 用于加密客户端与服务端通信的证书
lamda 内置 ssh 使用的默认 ssh 私钥,此与 ssh.sh
、scp.sh
中硬编码的私钥相同。
启动中间人,这将会全自动的在设备上开启全局的中间人,你就可以截获应用的 http/s 流量,当然,也可以包括 DNS 请求(全局)。 它可以自动应用及撤销中间人,退出脚本后设备及网络也将恢复它原来的样子。
提示:有时在 Windows 上装这些东西是很烦的事情, 所以专门为 Windows 提供了 startmitm.exe,这是一个Windows 命令行程序,将其下载并放入系统 PATH 或者当前目录,在命令行执行即可。 它的参数与 startmitm.py 相同。这样你可以不用安装 Python 及任何相关环境,但是你也只能进行基本的中间人操作。你可以在每个版本的 release 中找到它。如果没有,可以翻看稍旧的 release。 对于 Linux/Mac 用户,如果你想生成/使用这种独立可执行程序,请自行使用
pyinstaller startmitm.spec
命令打包 (需要安装 pyinstaller)。
如果你需要对国际APP进行中间人,请转到 globalmitm
首先确保当前电脑与设备在同一个网段,192.168.1.2 为运行了 lamda 的手机设备。
其次,确保你已在命令行验证 mitmproxy 已安装成功(在命令行输入 mitmdump
进行验证)。
当然,电脑与设备不在同一网段或者是远程设备,你也可以轻松 mitm,请继续看下去。
注意:mitmweb 并不适合长时间多请求,其截获的请求均存储于内存之中。所以在长时间使用的情况下你的内存会被吃光(你可以不定期点击 mitmweb 界面的左上角 File->Clear All 来释放)。 对于长时间的中间人操作,请改用 mitmdump,请自行了解使用方法。
执行
# 注意,设备IP 必须在参数第一位
python3 -u startmitm.py 192.168.1.2
即可。
如果你想和局域网的小伙伴一起分析
python3 -u startmitm.py 192.168.1.2 --web-port 7890 --web-host 0.0.0.0
# 然后,让你的小伙伴用浏览器打开 http://你的IP地址:7890 即可
如果需要截获特定应用的流量而不是全局
# 这里的 com.some.package 是应用的 ID
python3 -u startmitm.py 192.168.1.2:com.some.package
即可。
如果你想使用特定的DNS,或者一些情况下,你可能出现DNS解析错误/无法解析的情况(可能出现于一些原生的系统),可以这样做
# 使用中国大陆 DNS
python3 -u startmitm.py 192.168.1.2 --nameserver 114.114.114.114
如果需要传递其他参数到 mitmproxy,例如 -s,则执行
关于如何编写
http_flow_hook.py
脚本,请参考 docs.mitmproxy.org/stable/addons-examples 以及 mitmproxy/examples/contrib
# 这样你就可以通过编写 http_flow_hook.py 实时修改请求或者响应
python3 -u startmitm.py 192.168.1.2 -s http_flow_hook.py
即可。
手机与当前电脑不在同一网络下,但是你可以物理接触设备,你仍然可以进行中间人,但是需要确保当前设备已通过USB 或者 adb connect
接入电脑且已ADB授权。
# localhost 代表使用 adb 设备
# 当前仅连接了一台 adb 设备
python3 -u startmitm.py localhost
# 电脑连接了多台 adb 设备,你需要指定 adb serial
# 这个 serial 请从命令 adb devices 的输出中寻找
python3 -u startmitm.py localhost --serial bfde362
即可。
手机与当前电脑不在同一网络下,也无法物理接触设备,但是只要你可以访问 lamda 的端口,你也可以进行中间人。 这种情况通常为:你使用了内置 frp 服务转发了 lamda 到远程服务器,或者你自行通过某种方式转发了 lamda 的 65000 端口到某个地方(例如 SSH、路由器端口转发等-注意安全性问题),这种情况下你和 lamda 之间 仅有这一个端口可以直接交流,其他端口是无法互相访问的。这种情况下,手机无法访问到本机的任何端口,本机也只能访问到手机的 lamda 端口(或者手机有公网IP,但本机在不互通的内网),这样需要通过以下方式来进行。(注意 OpenVPN 网络互通,并不属于这个情况)
这时,需要通过稍微繁琐的组合方式来进行,下面介绍如何操作。
首先,使用 adb_pubkey.py
或者自行调用接口将自身的 adb 公钥安装到设备上(请在本文档搜索)。
现在执行以下命令
adb kill-server
# 如果你使用了内置 frp 或者自行使用了 ssh 转发,
# 这里的 x.x.x.x 通常为 127.0.0.1,请依据事实修改
# 而这里的 65000 也非固定,依据你实际设置的目的转发端口做修改
adb connect x.x.x.x:65000
最后,按照和上文 通过USB 一样的方法操作
# localhost 代表使用 adb 设备
# 当前仅连接了一台 adb 设备
python3 -u startmitm.py localhost
# 电脑连接了多台 adb 设备,你需要指定 adb serial
python3 -u startmitm.py localhost --serial x.x.x.x:65000
即可。
注意:你可能需要完全结束APP并重新打开才会显示流量数据。
按下一次 CONTROL
+ C
退出脚本。
startmitm 本身也会启动 mitmproxy 作为代理服务,默认情况下流量都是 mitmproxy 从本机网卡发出的,如果你需要流量通过一个上游代理发出而不是本机,可以使用如下方式指定上游代理,仅支持 HTTP 作为上游代理。
DNS 流量不会经过上游代理
python3 -u startmitm.py 192.168.1.2 --mode upstream:http://example.com:8080
# 省略掉 http:// 开头也是可以的
python3 -u startmitm.py 192.168.1.2 --mode upstream:example.com:8080
如果上游代理需要登录认证
python3 -u startmitm.py 192.168.1.2 --mode upstream:example.com:8080 --upstream-auth USER:PASSWORD
这些选项是与 mitmproxy 兼容的。
截获 DNS 请求需要确保 mitmproxy 的版本 >= 9.0.0(且 Python>=3.9),且需要以管理员或者root身份运行脚本。
此选项与上方 --nameserver
意义不同,--dns
选项专指 dns 中间人
DNS 中间人,默认上游 DNS 服务器为 1.1.1.1
python3 -u startmitm.py 192.168.1.2 --dns
指定上游 DNS 为 114.114.114.114(如果在中国大陆,建议使用如下命令指定DNS)
python3 -u startmitm.py 192.168.1.2 --dns 114.114.114.114
如果上游 DNS 使用了非标准端口(例如 5353)
python3 -u startmitm.py 192.168.1.2 --dns 192.168.0.100:5353
hook 脚本的方法名称定义有一些变化,正常 http 请求为 response()
,截获 DNS 时需要使用 dns_response()
。
def response(flow):
print (flow, type(flow))
def dns_response(flow):
print (flow, type(flow))
具体请查看 mitmproxy 的文档。
用于安装本机的 adb pubkey 到 lamda 的脚本,否则 adb 连接将会显示未授权。
# 安装 adb pubkey
python3 -u adb_pubkey.py install 192.168.1.2
# 卸载 adb pubkey
python3 -u adb_pubkey.py uninstall 192.168.1.2
安装后,执行
adb kill-server
adb connect 192.168.1.2:65000
adb -s 192.168.1.2:65000 shell
来连接 lamda adb。
连接入手机上的 shell 终端。
执行
bash ssh.sh 192.168.1.2
即可。
使用 scp
复制设备上的文件到本地。
将 192.168.1.2 的 /sdcard/DCIM
目录复制到当前目录
bash scp.sh 192.168.1.2:/sdcard/DCIM .
将本地目录 test/
复制到设备 192.168.1.2 的 /sdcard/
bash scp.sh test/ 192.168.1.2:/sdcard
使用 rsync
增量上传或下载文件。
将 192.168.1.2 的 /sdcard/DCIM
下载当前目录
bash rsync.sh 192.168.1.2:/sdcard/DCIM .
将 192.168.1.2 的 /sdcard/DCIM
下载当前目录,并且保持本地与远程目录的同步。
这将删除在本地目录中存在但在远程目录不存在的文件,具有危险性,请三思后再执行。
bash rsync.sh 192.168.1.2:/sdcard/DCIM . --delete
关于其他可用的额外参数(例如 --delete),请参阅 rsync 的文档
将本地目录 test
上传到设备 192.168.1.2 的 /sdcard/
bash rsync.sh test 192.168.1.2:/sdcard
将本地目录 test
上传到设备 192.168.1.2 的 /sdcard/
,并且保持远程与本地目录的同步。
这将删除在远程目录中存在但在本地目录不存在的文件,具有危险性,请三思后再执行。
bash rsync.sh test 192.168.1.2:/sdcard --delete
将本地目录 test/
下的内容上传到设备 192.168.1.2 的 /sdcard/
bash rsync.sh test/ 192.168.1.2:/sdcard
列出本地网络中所有在线的设备(部分网络情况下可能一些设备没有列出,请多次尝试)
python3 discover.py
一个 fridarpc 功能的简单封装。
此功能需要你能熟练编写 frida 脚本。示例中使用的脚本请参照 test-fridarpc.js 文件,特别注意: frida 脚本中 rpc.exports 定义的函数返回值只能为 string/list/json 或者任意 js 中可以被 json 序列化的值。假设设备IP为 192.168.0.2。
执行以下命令注入 RPC 到 com.android.settings(注意查看是否有报错)
python3 fridarpc.py -f test-fridarpc.js -a com.android.settings -d 192.168.0.2
现在已经将接口拿出来了,只需要请求 http://192.168.0.2:65000/script/myRpcName/getMyString?args=["A","B"]
即可得到脚本内方法的返回结果,链接也可以用浏览器打开,接口同时支持 POST 以及 GET,参数列表也可以同时使用多个参数。
注意参数的提供形式,是双引号,建议使用 json.dumps(["A", "B"])
用 requests 调用
import json
import requests
url = "http://192.168.0.2:65000/script/myRpcName/getMyString"
data = requests.post(url, data={"args": json.dumps(["A", "B"])}).json()
print (data["result"])
#* 状态码 200 一切正常
#* 状态码 410 需要重新注入脚本或者脚本未注入(目前不支持自动重新注入)
#* 状态码 500 脚本或参数异常
#* 状态码 400 参数错误
响应结果的格式是固定的,可在浏览器打开查看。
仅适用于主流模拟器的服务端安装脚本,需要设备开启 WIFI adb,需要提前下载 对应架构服务端安装包到当前运行目录。
bash emu-install 192.168.1.2
如果你无法正常运行 LAMDA,可以使用此脚本来生成 issue 报告,重启设备并且确保 LAMDA 已经退出,将 statistics.sh
使用 adb push 到 /data/local/tmp,随后使用 root 身份执行。
# launch.sh 为启动 LAMDA 的脚本路径
sh /data/local/tmp/statistics.sh /data/server/bin/launch.sh
# 执行完毕后,会生成文件 /sdcard/statistics.txt,报告此文件即可
lamda 的 magisk 模块构架
所有镜像均为 x86 平台,在 ARM 处理器的 Linux/Mac 上使用你可能要自行做出修改并重新生成。
开箱即用的 OpenVPN 服务
用于分析需要透过代理才能连接的国外APP的流量
开箱即用的 frp 端口转发
开箱即用的 socks5 代理服务