├── .gitignore ├── CHANGELOG.txt ├── DISCLAIMER.TXT ├── README.md ├── SECURITY.md ├── examples ├── README.md ├── activity_jump.py └── search_in_taobao.py ├── extensions ├── README.md ├── example_http_extension.py ├── example_mcp_extension.py └── firerpa.py ├── image ├── claude.gif ├── demo.gif ├── inspect.png └── logo.svg ├── lamda ├── __init__.py ├── bcast.proto ├── client.py ├── const.py ├── exceptions.py ├── google │ └── protobuf │ │ ├── any.proto │ │ ├── api.proto │ │ ├── compiler │ │ └── plugin.proto │ │ ├── descriptor.proto │ │ ├── duration.proto │ │ ├── empty.proto │ │ ├── field_mask.proto │ │ ├── source_context.proto │ │ ├── struct.proto │ │ ├── timestamp.proto │ │ ├── type.proto │ │ └── wrappers.proto ├── rpc │ ├── application.proto │ ├── debug.proto │ ├── file.proto │ ├── policy.proto │ ├── proxy.proto │ ├── services.proto │ ├── settings.proto │ ├── shell.proto │ ├── status.proto │ ├── storage.proto │ ├── types.proto │ ├── uiautomator.proto │ ├── util.proto │ └── wifi.proto └── types.py ├── properties.local.example ├── scripts ├── disable_flag_secure.yaml └── disable_ssl_pinning_simple.yaml ├── setup.py └── tools ├── README.md ├── adb_pubkey.py ├── cert.py ├── debugimage.py ├── discover.py ├── firerpa.yml ├── fridarpc.py ├── globalmitm ├── DNS2SOCKS.c ├── Dockerfile └── entry ├── id_rsa ├── ida.py ├── magisk ├── META-INF │ └── com │ │ └── google │ │ └── android │ │ ├── update-binary │ │ └── updater-script ├── common │ ├── server │ │ └── .keep │ └── service.sh ├── install.sh ├── module.prop └── uninstall.sh ├── objection-1.11.0-command-patch.diff ├── openvpn ├── Dockerfile ├── config.ovpn ├── entry ├── ovpn-client-new ├── ovpn-client-profile ├── ovpn-client-renew ├── ovpn-client-revoke ├── ovpn-server-new └── vars ├── paddle_ocr_http_api.py ├── requirements.txt ├── root.crt ├── root.key ├── rsync.sh ├── scp.sh ├── socks5 ├── Dockerfile └── entry ├── ssh.sh ├── startmitm.ico ├── startmitm.py ├── startmitm.spec ├── test-fridarpc.js └── test.pem /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .nox/ 42 | .coverage 43 | .coverage.* 44 | .cache 45 | nosetests.xml 46 | coverage.xml 47 | *.cover 48 | *.py,cover 49 | .hypothesis/ 50 | .pytest_cache/ 51 | cover/ 52 | 53 | # Translations 54 | *.mo 55 | *.pot 56 | 57 | # Django stuff: 58 | *.log 59 | local_settings.py 60 | db.sqlite3 61 | db.sqlite3-journal 62 | 63 | # Flask stuff: 64 | instance/ 65 | .webassets-cache 66 | 67 | # Scrapy stuff: 68 | .scrapy 69 | 70 | # Sphinx documentation 71 | docs/_build/ 72 | 73 | # PyBuilder 74 | .pybuilder/ 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | # For a library or package, you might want to ignore these files since the code is 86 | # intended to run in multiple environments; otherwise, check them in: 87 | # .python-version 88 | 89 | # pipenv 90 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 91 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 92 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 93 | # install all needed dependencies. 94 | #Pipfile.lock 95 | 96 | # poetry 97 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 98 | # This is especially recommended for binary packages to ensure reproducibility, and is more 99 | # commonly ignored for libraries. 100 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 101 | #poetry.lock 102 | 103 | # pdm 104 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 105 | #pdm.lock 106 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 107 | # in version control. 108 | # https://pdm.fming.dev/#use-with-ide 109 | .pdm.toml 110 | 111 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 112 | __pypackages__/ 113 | 114 | # Celery stuff 115 | celerybeat-schedule 116 | celerybeat.pid 117 | 118 | # SageMath parsed files 119 | *.sage.py 120 | 121 | # Environments 122 | .env 123 | .venv 124 | env/ 125 | venv/ 126 | ENV/ 127 | env.bak/ 128 | venv.bak/ 129 | 130 | # Spyder project settings 131 | .spyderproject 132 | .spyproject 133 | 134 | # Rope project settings 135 | .ropeproject 136 | 137 | # mkdocs documentation 138 | /site 139 | 140 | # mypy 141 | .mypy_cache/ 142 | .dmypy.json 143 | dmypy.json 144 | 145 | # Pyre type checker 146 | .pyre/ 147 | 148 | # pytype static type analyzer 149 | .pytype/ 150 | 151 | # Cython debug symbols 152 | cython_debug/ 153 | 154 | # PyCharm 155 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 156 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 157 | # and can be added to the global gitignore or merged into this file. For a more nuclear 158 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 159 | #.idea/ 160 | -------------------------------------------------------------------------------- /CHANGELOG.txt: -------------------------------------------------------------------------------- 1 | 8.35 2 | * 远程桌面支持实时音频推送 3 | * 修复 hex_patch 段错误 4 | 5 | 8.30 6 | * 新增二进制补丁接口 7 | * 支持在 Selector 使用 child、sibling 8 | * 支持在远程桌面查看界面 XML 树状布局 9 | * 更新 frida 修复部分问题 10 | 11 | 8.28 12 | * 修复 install_local_file 13 | * 修复 frida 上报 ID 递增 14 | * 提升内置 tf 推理性能 15 | * 更新部分第三方模块 16 | 17 | 8.25 18 | * 新增 hexedit 命令 19 | * 彻底修复 Permission Loophole (maybe) 20 | * 新增设备端 AI 框架 (tflite-runtime) 21 | * 更新 frida 提升隐藏性 22 | 23 | 8.22 24 | * 使用全新 sqlite 25 | * 远程桌面检视显示当前坐标及RGB 26 | * 增加插件 setup 逻辑 27 | 28 | 8.20 29 | * 新增官方 MCP 插件 30 | * 优化 frida 兼容性 31 | * 优化 MCP 协议实现 32 | * 修复自恢复逻辑 33 | 34 | 8.18 35 | * 回退存在 BUG 的 Frida 36 | * MCP、HTTP 扩展插件支持 37 | 38 | 8.15 39 | * 修复服务不可用的问题 40 | * 支持使用 jsonrpc 调用导出脚本 41 | * 修复 ssh 用户目录 42 | * 更新部分子模块 43 | 44 | 8.12 45 | * 修复触控异常 46 | * 添加部分工具脚本 47 | * 增强稳定性 48 | 49 | 8.10 50 | * 优化自恢复逻辑 51 | * 优化触控兼容性 52 | 53 | 8.9 54 | * 修复解析错误 55 | 56 | 8.8 57 | * Frida 数据上报支持 AMQP 58 | * 修复 cert.py 上游库变更导致的证书问题 59 | * 修复服务重启资源释放的问题 60 | 61 | 8.5 62 | * 优化剪切板共享逻辑 63 | * 新增 Frida 脚本崩溃日志 64 | * 已支持安卓 15 65 | 66 | 8.0 67 | * 接口全面支持多开应用 68 | * 远程桌面支持共享剪切板 69 | * 新增部分机型无法打开APP的修复配置 70 | * 新增 Yaml frida 脚本持久化 71 | * 修复 6.0 等低版本系统兼容性 72 | * 修复高版本系统自动化相关功能异常 73 | * 移除/重命名部分方法 74 | * 更新底层实现 75 | 76 | 7.90 77 | * 持久化脚本支持 spawn 模式 78 | * 支持持久化脚本输出日志 79 | * 修复 dump_window_hierarchy 80 | * 修复 frida 实例获取逻辑错误 81 | 82 | 7.85 83 | * 支持 mDNS 广播服务 84 | * 支持枚举选择器选中的所有元素 85 | * 客户端添加自动重试机制 86 | * 修复 Bound 比较逻辑错误 87 | * 允许从远程加载证书 88 | 89 | 7.80 90 | * 优化实时投屏流畅度 91 | * 新增持久化 Hook 脚本支持 92 | * 新增 Hook RPC 支持 93 | * 新增数据上报支持 94 | 95 | 7.76 96 | * 修复工具版本依赖 97 | * 修复 Python 版本匹配问题 98 | * 更新部分子模块 99 | 100 | 7.75 101 | * 新增 OCR识别接口 102 | * 新增 get_application_by_name 103 | * 更新部分子模块及依赖版本 104 | 105 | 7.73 106 | * 修复部分应用白屏的问题 107 | 108 | 7.72 109 | * 更新部分子模块 110 | * 已知问题修复 111 | 112 | 7.71 113 | * 修复 Permission Loophole #95 114 | * 修复 enumerate_all_pkg_names 115 | 116 | 7.70 117 | * 更新部分子模块 118 | * 已知问题修复 119 | 120 | 7.68 121 | * 优化 h264 实时屏幕 122 | 123 | 7.67 124 | * 精简掉部分无效的程序逻辑 125 | * 修复自动恢复时间过长的问题 126 | * 其他一些优化及问题修复 127 | 128 | 7.65 129 | * 移除 IDA 相关工具及接口 130 | * 修复部分情况下启动失败的问题 131 | * 其他一些优化及问题修复 132 | * 新增增强隐身模式 133 | 134 | 7.60 135 | * 优化以图找图查找速度 136 | * 支持在远程桌面进行区域截图 137 | * 修复远程桌面的一些问题 138 | 139 | 7.57 140 | * 新增特征及模板找图客户端接口 141 | * 其他一些优化及问题修复 142 | 143 | 7.55 144 | * 修复屏幕旋转显示不正常的问题 145 | * 修复远程桌面初次连接断开的问题 146 | * 修复元素存在判断 147 | * 加入 Meta 按键定义 148 | * 其他一些优化及问题修复 149 | 150 | 7.52 151 | * 修复 magisk 版雷电兼容性 152 | * 修复无法正常退出服务的问题 153 | 154 | 7.50 155 | * 彻底修复夜神模拟器兼容性问题 156 | * 修复逻辑错误导致的僵尸进程 157 | * 新的组网订阅服务,无需 Frp、OpenVPN 即可实现组网 158 | * 修复系统多分辨率的问题 159 | * 优化安卓13, 14的系统证书注入逻辑 160 | * 新增对多开应用的支持 (user) 161 | * OpenVPN 已支持 IPv6 162 | 163 | 7.30 164 | * 修复雷电/夜神兼容性问题 165 | * 一些小调整 166 | 167 | 7.28 168 | * 新增 show_toast 接口 169 | * 内置代理现已支持代理 DNS 流量 170 | * startmitm 现已支持 DNS 通过上游代理 171 | * 修复安卓 10+ frida spwan 172 | 173 | 7.25 174 | * 修复定时任务运行失败的问题 175 | * 修复从 termux 启动失败的问题 176 | * 更新内置 Frida 版本 177 | 178 | 7.22 179 | * 自动同步系统时间 180 | * 更新部分内置模块 181 | * 一些小修复 182 | 183 | 7.20 184 | * 减少被检测的可能性 185 | * 优化锁机制,可对所有API资源加锁 186 | * 修复模拟器兼容性 187 | * 其他小修改及修复 188 | 189 | 7.15 190 | * 支持安卓 14 (SDK 34) 191 | * 修复注册监视器异常的问题 192 | * 提高远程桌面兼容性(理论支持所有设备) 193 | * 修复 scroll_from_bottom_to_top_to_end 异常。感谢 ThanhPham 194 | * 修复 drag_to、long_click 代码错误 195 | * 内置 OpenVPN 支持 userpass 登录 196 | * 远程桌面支持设置最高60帧 197 | * 更新 DISCLAIMER.TXT 198 | * 其他小修改及修复 199 | 200 | 5.6 201 | * 修复布局导出不全的问题。感谢 ThanhPham 202 | 203 | 5.5 204 | * 修复 adb push 文件损坏问题 205 | * 添加 install_local_file 接口 206 | * 代码结构优化 207 | 208 | 5.3 209 | * 支持使用证书后自定义远程桌面登录密码 210 | * 修复部分设备不支持端口复用的问题。感谢 alex han 211 | * 修复 Magisk 安装脚本的一些问题 212 | * 修复 Debian 启动器的兼容性问题 213 | 214 | 5.2 215 | * 修复 Selector 包含的 False 值时无效的问题。感谢 ThanhPham 216 | * 使用 LAMDA 时可同时使用其他无障碍服务(仅限安卓 >= 8.0) 217 | 218 | 5.0 219 | 版本 5.0 和 3.0 没有太大的本质区别,修复了一个较为严重的漏洞以及一些小问题, 220 | 这个漏洞可能会在任意情况下导致设备被入侵。在服务内部权限上也做了一些调整, 221 | 将系统非特权用户入侵的风险降到了最低。客户端现已经支持 Python 3.11。 222 | ================================================================= 223 | 注意:5.0 与 3.0 的客户端不完全兼容,请注意同时更新。 224 | 225 | * 修复登录证书导致的一系列问题 226 | * 修复 Magisk 模块配置读取策略 227 | * 现在远程桌面,RPC 已全部支持 TLS 化 228 | * 内置 debian 模块可启动 debian 子系统 229 | * 远程桌面BUG修复以及简单的布局调整 230 | * 服务内部权限以及相关目录调整 231 | * 提升服务端的稳定性 232 | * 调整服务的安装方式 233 | * 代理服务的 nameserver 支持指定端口 234 | * 添加内部存储(内存配置)读写接口 235 | * 等一系列更新及修复 236 | 237 | 3.157 238 | * 界面检视元素高亮 239 | * 支持系统崩溃计数 240 | 241 | 3.155 242 | * 支持 tab 键遍历界面元素 243 | * 支持在远程桌面输入英文字符 244 | * 支持远程桌面触摸 245 | 246 | 3.153 247 | * 修复部分场景截图失败的问题 248 | * 次要更改 249 | 250 | 3.152 251 | * 次要界面样式调整 252 | 253 | 3.151 254 | * 高分屏投屏被拉伸的问题 #41 255 | 256 | 3.150 257 | * 修改定时任务重载时的逻辑 258 | * 修复 scapy 路由的问题 259 | * 兼容部分小米设备 260 | * 修复安卓11接口兼容性问题(感谢 Kate Swan) 261 | * 支持连接 WIFI 的情况下使用 4G 作为代理 262 | * 新增部分界面控件 263 | 264 | 3.138 265 | * 修复 gRPC 依赖的问题 266 | * 获取系统最后一个 toast 267 | 268 | 3.135 269 | * 修复远程桌面加载中的问题 270 | * 彻底修复协议中的竞争条件问题 271 | * 修复 Windows Python310 兼容性问题 272 | * 允许 HTTP 接口跨站调用 273 | * 添加部分丢失的模块 274 | * 远程桌面加入服务状态指示 275 | * 远程桌面响应式布局 276 | * 预发 next 版本 277 | 278 | 3.123 279 | * 修复获取最近活动不全的问题 280 | 281 | 3.120-1 282 | * 现 LAMDA 已支持本身作为代理 283 | * 新增获取系统最近 Activity 的接口 284 | * 修复一个协议中的 race condition (maybe) 285 | * 增加部分命令,移除 SQLite db view 286 | * 实验性的 H.264 投屏 287 | 288 | 3.108 289 | * 优化网络断连处理逻辑 290 | * 增加 Redroid (remote android) 支持 291 | * 部分兼容 uiautomator2 292 | * 支持文件夹上传 293 | 294 | 3.102 295 | * 修复文件描述符泄漏的问题 296 | * 支持从远程文件服务器加载启动配置 297 | * 现在已上传 armeabi-v7a 的服务端 298 | * 修复 magisk 下安装根证书失败的问题 299 | * 修复配置解析错误的问题 300 | * 轻微的UI调整 301 | 302 | 3.98 303 | * 加入 crontab, vi 命令 304 | 305 | 3.95 306 | * 修复构建流程存在的问题 307 | * 次要更改 308 | 309 | 3.93 310 | * 增加安卓常量定义 311 | 312 | 3.90 313 | * 移除未使用的库,减小体积 314 | * 移除 client 中不兼容 MacOS 的命令行历史功能 315 | * 更新 DISCLAIMER.TXT 316 | * 更新部分依赖库版本 317 | 318 | 3.83 319 | * 支持 WSA #24 @aimardcr 320 | * 修复 note7pro MIUI10 黑屏 @yu1chaofan 321 | * 次要更改 322 | 323 | 3.80 324 | * 修复 ssh 断连的问题 325 | * 减小包体积 326 | 327 | 3.78 328 | * 修复 #21 @yu1chaofan 329 | * 更新 frida-server 330 | 331 | 3.76 332 | * 默认内置 shell 使用 bash 333 | * 修复断网后远程桌面触摸无法使用的问题 334 | * 修复 OpenVPN 僵尸进程的问题 335 | * startmitm.py 支持指定 adb 串号 336 | * 支持 magisk 自启动 337 | 338 | 3.0.59 339 | * 所有界面提示使用英文 340 | * 修复一个 web 接口未认证的问题 341 | * 修复旧版本兼容性 342 | 343 | 3.0.55 344 | * 修复宽字符请求头导致的崩溃 345 | * 合并 mitmweb 到 startmitm 进程 346 | * docker 镜像小修改 347 | * 支持布局检视 348 | 349 | 3.0.50 350 | * 支持 child, sibling 选择器 351 | 352 | 3.0.48 353 | ----------------------- 354 | * 免安装的 windows startmitm 命令 355 | * 支持从内存上传/下载文件到内存 356 | * 添加 screenshot() 别名 357 | 358 | 3.0.47 359 | ----------------------- 360 | * 简化 globalmitm,支持 HTTP,SOCKS5 代理 361 | * 增强 webview 节点查找 362 | 363 | 3.0.46 364 | ----------------------- 365 | * 支持双指缩放 366 | * 简化 startmitm DNS 中间人操作 367 | 368 | 3.0.45 369 | ----------------------- 370 | * 支持自定义 server 端口 (--port) 371 | * 目录索引检测文件类型时在特殊文件上卡住 372 | * globalmitm 检查 DNS 服务可用性 373 | * startmitm.py 当存在多个网络时获取了错误的网络接口 374 | * client 通信不再自动使用系统代理 375 | 376 | 3.0.35 377 | ----------------------- 378 | * 提高内置 ADB 性能 379 | * openvpn 服务支持 auth 参数 (默认为 SHA1) 380 | * 通过内置 ADB 使用 scrcpy 异常的问题 381 | -------------------------------------------------------------------------------- /DISCLAIMER.TXT: -------------------------------------------------------------------------------- 1 | 若您需要获得本服务,您(以下称"用户")应当同意本协议的全部条款并按照页面上的提示完成全部申请使用程序。您可以在源码或者发布程序中找到 DISCLAIMER.TXT,或者查看以下副本。 2 | 3 | 为了下载和使用由 firerpa(地址:github.com/firerpa,邮箱:lamda.devel@gmail.com,以下简称“开发者”)开发的 LAMDA 软件(以下简称“本服务”),您必须仔细阅读并同意本协议中的所有条款。请确保您在下载、安装或使用本软件前,已充分理解并同意以下内容。 4 | 在未完全阅读并接受本协议条款之前,您无权下载、安装或使用本软件及其相关服务。一旦您进行下载、安装或使用本软件的操作,即视为您已阅读并同意本协议的全部条款,并愿意遵守其约束。 5 | 6 | 风险告知: 7 | 本服务需要设备获取 root 权限才能运行,且默认的通讯协议及相关证书文件均为开放信息,这可能会增加您设备被入侵的风险。 8 | 本服务可能存在未知的逻辑错误,可能会导致潜在的风险如数据丢失、系统崩溃等,由用户自行决定是否下载、使用本服务。 9 | 10 | 11 | 1、本服务设计目的为提高安全分析及测试人员工作效率,应用行为、应用合规分析等。提供的相关工具均为合法合规的APP测试分析、Mock 场景提供。 12 | 本服务本身不提供任何侵入、修改、抓取其他应用内存及网络数据的功能,整合了各大开源框架提供的服务供用户自行选择,方便安全分析人员使用,减少用户的重复性劳动以及管理成本。 13 | 本服务本身不存在盈利性,用户可根据自己需求自行通过下载获取使用,下载及使用过程中不会收取任何费用。 14 | 15 | 2、本服务尊重并保护用户的个人隐私,不会窃取任何用户设备中的信息。本服务的启动及任何对设备数据读取、存储、传输等权利均在用户自己手中。 16 | 17 | 3、用户必须在无隐私数据的虚拟设备或者专用设备中使用本服务。在使用本服务时,必须遵守中华人民共和国或者用户所属国家或地区的法律法规, 18 | 不得为任何非法目的而使用本服务,不得利用本服务进行任何不利于他人的行为。 19 | 20 | 4、用户只可使用本服务进行正规的学习研究或是经过合法授权的应用分析、测试等行为,若用户在使用该软件服务的过程中违背以上原则对第三方造成损失,一切责任由该用户自行承担。 21 | 22 | 5、任何单位或个人因下载使用本服务而产生的任何意外、疏忽、合约毁坏、诽谤、版权或知识产权侵犯及其造成的损失 (包括但不限于直接、间接、附带或衍生的损失等),开发者不承担任何法律责任。 23 | 24 | 6、您可以将本服务用于商业用途,但仅限于通过本服务提供的功能、接口或相关服务进行衍生功能扩展或产品开发。您同意,不得将本服务及其相关服务或接口用于任何违反当地法律法规,或从事损害他人利益的行为。 25 | 26 | 7、用户明确并同意本协议条款列举的全部内容,对使用本服务过程中可能存在的风险和后果由用户自行承担,开发者不承担任何法律责任。 27 | 28 | 8、开发者有权随时对本声明条款及附件内容进行单方面的变更、中断或终止部分或全部本服务的权利。并以消息推送、网页公告等方式予以公布, 29 | 公布后立即自动生效,无需另行单独通知;若您在本声明内容公告变更后继续使用的,表示您已充分阅读、理解并接受修改后的声明内容。 30 | 31 | 9、如果本声明的任何部分被认为无效或不可执行,则该部分应以符合相关法律的方式予以修正,以尽可能地反映出开发者的原始意图, 32 | 其余部分仍具有完全效力。不可执行的部分声明,并不构成开发者放弃执行该声明的权利。 33 | 34 | 10、保留权利:未明示授权的其他一切权利均由开发者所有。 35 | 36 | 37 | 请确认您已阅读并接受本协议所有条款,否则您将无权下载、安装或使用本软件及相关服务。 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | FIRERPA 3 |

4 | 5 |

Android AI Robot Framework, Next-Generation Mobile Data Automation Robot

6 | 7 |

8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 |

16 | 17 |

Document (English) | 中文文档 | TELEGRAM | QQ Group

18 | 19 |

Most powerful Android automation framework built for the mobile-first era.

20 |

面向移动优先时代的强大 Android 自动化框架。

21 | 22 | With the decline of traditional web interfaces and the rise of intelligent devices, automation and data technologies must adapt to the mobile shift. FIRERPA embraces this trend, offering a modern solution purpose-built for Android automation. Lightweight, with no external dependencies, and compatible with any version of the Android operating system. Low-latency remote desktop and audio transmission (under 80ms). Over 160 programming interfaces, covering automation, file I/O, script injection, proxy support, and more. Exceptionally stable, supports distributed deployment, and is easy to monitor and manage. 随着传统网页的式微与智能设备的崛起,自动化与数据技术迫切需要适应移动化转型。FIRERPA 正是顺应这一趋势而生,为 Android 自动化带来现代化解决方案。轻量,无任何外部依赖,可运行于任何版本的安卓系统。低延迟的远程桌面及远程音频传输(小于 80ms)。160+ 编程接口,涵盖自动化及文件读写、脚本注入、代理等等。极致稳定,支持分布式部署,易监控管理。 23 | 24 |

25 | Claude 26 |

27 | 28 |

Reliable across Android 6.0 to 15, from emulators to cloud.

29 |

兼容 Android 6.0–15,适用于模拟器、真机与云平台。

30 | 31 | FIRERPA delivers commercial-grade automation capabilities across a wide range of Android versions and devices. It requires only root access, simplifies security analysis and testing, and is already widely used in scenarios such as digital forensics and compliance monitoring. FIRERPA 提供稳定且达到商用级的自动化能力,兼容众多 Android 系统与设备,仅需 Root 权限即可轻松完成安全分析与测试,广泛应用于数字取证与合规监测等场景。 32 | 33 |

Zero-Intrusion Design.

34 |

零侵入式设计。

35 | 36 | FIRERPA ensures complete non-intrusiveness during operation—it does not alter system settings or write to system files, preserving the original environment and ensuring device integrity. 37 | FIRERPA 保证运行过程完全无侵入,不修改系统设置、不改写系统文件,保留原始环境,设备完整性不受影响。 38 | 39 |

Designed from the ground up for flexible deployment.

40 |

从零设计,专为灵活性与大规模部署而生。

41 | 42 | FIRERPA was built from the ground up to run non-intrusively on most Android devices. It requires no third-party dependencies, no complex configuration, and is ready to use out of the box. Compared to other solutions, it avoids common issues like instability and poor compatibility, making it ideal for large-scale business applications. FIRERPA 从设计之初就面向多样化环境,几乎兼容所有 Android 设备,无侵入式运行,无需依赖与额外配置,即开即用。相较于其他方案常见的不稳定、兼容差、维护难等问题,FIRERPA 在大规模部署中的表现尤为出色。 43 | 44 |

160+ APIs and full Python SDK for rapid development.

45 |

160+ API 配套完整 Python SDK,助力高效开发。

46 | 47 | FIRERPA offers over 160 categorized, stable APIs that cover command execution, system configuration, automation flows, and app-level controls. It also provides a full-featured Python SDK for rapid development and seamless AI integration. Developers can easily build intelligent workflows with precise control over Android systems. FIRERPA 提供超 160 个分类清晰、稳定可靠的接口,涵盖命令执行、系统设置、自动化流程与应用控制等,并包含完整的 Python SDK,帮助开发者高效实现与 AI 的无缝集成,构建具备精细控制能力的智能化任务流。 48 | 49 |

50 | demo 51 |

52 | 53 |

Remote desktop and device control, made simple.

54 |

远程桌面与设备控制,简单直观。

55 | 56 | FIRERPA comes with a clean, intuitive remote desktop interface, allowing users to monitor and control Android devices visually and interactively. Whether for testing, automation validation, or system diagnostics, it provides a powerful control layer with minimal setup. FIRERPA 内置简洁直观的远程桌面功能,帮助用户以可视化方式监控和操作 Android 设备。无论用于测试、任务验证还是系统诊断,都能提供高效、轻量的控制体验。 57 | 58 |

59 | demo 60 |

61 | 62 |

Check out real usage examples and developer guides in the documentation.

63 |

欢迎查阅 FIRERPA 使用文档,了解更多实际案例与开发指南。

-------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | | Version | Supported | 6 | | ------- | ------------------ | 7 | | 8.x | :white_check_mark: | 8 | 9 | ## Reporting a Vulnerability 10 | 11 | mailto:lamda.devel@gmail.com 12 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | We’re not targeting any specific application; we’re just using it as a convenient example for the demo. 2 | 3 | API Document: https://device-farm.com/doc/ -------------------------------------------------------------------------------- /examples/activity_jump.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025 rev1si0n (lamda.devel@gmail.com). All rights reserved. 2 | #encoding=utf-8 3 | from lamda.client import * 4 | import time 5 | 6 | d = Device("localhost") 7 | 8 | app = d.application("com.taobao.taobao") 9 | app.start() 10 | 11 | while True: 12 | goodsid = input("Please input a taobao goods id (item_id) (eg. 123456): ") 13 | if goodsid.isdigit(): 14 | intent["package"] = "com.taobao.taobao" 15 | intent["action"] = "android.intent.action.VIEW" 16 | intent["component"] = "com.taobao.taobao/com.taobao.android.detail.alittdetail.TTDetailActivity" 17 | intent["data"] = f"http://internal.tt.detail.taobao.com/detail/index.html?id={goodsid}" 18 | d.start_activity(**intent) 19 | time.sleep(2) -------------------------------------------------------------------------------- /examples/search_in_taobao.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025 rev1si0n (lamda.devel@gmail.com). All rights reserved. 2 | #encoding=utf-8 3 | from lamda.client import * 4 | import time 5 | 6 | """ 7 | This is a simple demo for performing keyword searches on Taobao. 8 | """ 9 | 10 | d = Device("localhost") 11 | 12 | app = d.application("com.taobao.taobao") 13 | 14 | if not app.is_installed(): 15 | print ("taobao app is not installed") 16 | exit (1) 17 | 18 | if app.info().versionName != "10.48.0": 19 | print ("please intall taaobao 10.48.0") 20 | exit (1) 21 | 22 | # ensure the app is stopped 23 | app.stop() 24 | time.sleep(1.5) 25 | 26 | app.start() 27 | time.sleep(10) # wait for app fully started 28 | 29 | if not d(description="我的淘宝").exists(): 30 | print ("is taobao home page?") 31 | exit (1) 32 | 33 | # click to activate input 34 | d(description="搜索栏").click() 35 | 36 | # wait for search input activated 37 | d(resourceId="com.taobao.taobao:id/searchbtn").wait_for_exists(15*1000) 38 | 39 | # input search keyword: 苹果手机 40 | d(resourceId="com.taobao.taobao:id/searchEdit").set_text("苹果手机") 41 | 42 | # click "Search" 43 | d(resourceId="com.taobao.taobao:id/searchbtn").click() 44 | 45 | # wait for goods showsup 46 | d(description="筛选").wait_for_exists(15*1000) 47 | 48 | # do a simple swipe 49 | d().swipe() 50 | 51 | # ... -------------------------------------------------------------------------------- /extensions/README.md: -------------------------------------------------------------------------------- 1 | API Document: https://device-farm.com/doc/ -------------------------------------------------------------------------------- /extensions/example_http_extension.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025 rev1si0n (lamda.devel@gmail.com). All rights reserved. 2 | # 3 | # Distributed under MIT license. 4 | # See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 5 | from lamda.extensions import * 6 | 7 | 8 | class ExampleHttpExtension(BaseHttpExtension): 9 | route = "/api/v1/hello-world" # API route 10 | def http_get(self, *args, **kwargs): 11 | """ GET Method Handler """ 12 | self.write("Hello World") 13 | def http_post(self, *args, **kwargs): 14 | """ POST Method Handler """ 15 | self.write("Hello World") 16 | def http_put(self, *args, **kwargs): 17 | """ PUT Method Handler """ 18 | self.write("Hello World") 19 | def http_delete(self, *args, **kwargs): 20 | """ DELETE Method Handler """ 21 | self.write("Hello World") 22 | def http_patch(self, *args, **kwargs): 23 | """ PATCH Method Handler """ 24 | self.write("Hello World") -------------------------------------------------------------------------------- /extensions/example_mcp_extension.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025 rev1si0n (lamda.devel@gmail.com). All rights reserved. 2 | # 3 | # Distributed under MIT license. 4 | # See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 5 | import base64 6 | 7 | from lamda.mcp import * 8 | from lamda.utils import getprop 9 | from lamda.extensions import * 10 | 11 | 12 | class ExampleMcpExtension(BaseMcpExtension): 13 | route = "/model-context-protocol/sse/" 14 | name = "example-mcp-extension" 15 | version = "1.0.0" 16 | @mcp("tool", description="Send a greeting to others.") 17 | def greeting(self, ctx, msg: Annotated[str, "Greeting message"], 18 | to: Annotated[str, "Greeting to who"] = "John"): 19 | return TextContent(text=f"mcp greeting! {msg}, {to}!") 20 | @mcp("tool", description="Read android system property by name.") 21 | def getprop(self, ctx, name: Annotated[str, "Android system property name."]): 22 | return TextContent(text=getprop(name) or "") 23 | @mcp("resource", uri="file://{absolute_path}") 24 | def get_file(self, ctx, absolute_path: Annotated[str, "Absolute file path"]): 25 | """ Read file content on the device by full path """ 26 | blob = base64.b64encode(open(absolute_path, "rb").read()).decode() 27 | return BlobResourceContents(blob=blob, uri=f"file://{absolute_path}", 28 | mimeType="text/plain") -------------------------------------------------------------------------------- /image/claude.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firerpa/lamda/fbd5e6e0ec602df622130c53abb4e87bd783e442/image/claude.gif -------------------------------------------------------------------------------- /image/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firerpa/lamda/fbd5e6e0ec602df622130c53abb4e87bd783e442/image/demo.gif -------------------------------------------------------------------------------- /image/inspect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firerpa/lamda/fbd5e6e0ec602df622130c53abb4e87bd783e442/image/inspect.png -------------------------------------------------------------------------------- /image/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | background 4 | 5 | 6 | 7 | Layer 1 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 | LAMDA 33 | 34 | -------------------------------------------------------------------------------- /lamda/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 rev1si0n (lamda.devel@gmail.com). All rights reserved. 2 | # 3 | # Distributed under MIT license. 4 | # See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 5 | __version__ = "8.35" 6 | -------------------------------------------------------------------------------- /lamda/bcast.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2022 rev1si0n (lamda.devel@gmail.com). All rights reserved. 2 | // 3 | // Distributed under MIT license. 4 | // See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 5 | syntax = "proto3"; 6 | package lamda; 7 | 8 | message BcastHeader { 9 | // magic always 0x54534143 ("CAST") 10 | uint32 magic = 1; 11 | // protocol version 12 | string version = 2; 13 | } 14 | 15 | message BcastDiscoverInfo { 16 | string ID = 1; 17 | uint64 uptime = 2; 18 | string device = 3; 19 | string abi = 4; 20 | uint32 sdk = 5; 21 | string version = 6; 22 | } 23 | 24 | message BcastResponse { 25 | BcastHeader header = 1; 26 | oneof body { 27 | BcastDiscoverInfo discoverinfo = 10; 28 | int32 errno = 11; 29 | bytes data = 12; 30 | } 31 | } 32 | 33 | message BcastRequest { 34 | BcastHeader header = 1; 35 | string method = 2; 36 | } 37 | -------------------------------------------------------------------------------- /lamda/const.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 rev1si0n (https://github.com/rev1si0n). All rights reserved. 2 | # 3 | # Distributed under MIT license. 4 | # See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 5 | 6 | # Android runtime permissions 7 | PERMISSION_READ_SMS = "android.permission.READ_SMS" 8 | PERMISSION_READ_CALENDAR = "android.permission.READ_CALENDAR" 9 | PERMISSION_READ_CALL_LOG = "android.permission.READ_CALL_LOG" 10 | PERMISSION_ACCESS_FINE_LOCATION = "android.permission.ACCESS_FINE_LOCATION" 11 | PERMISSION_ANSWER_PHONE_CALLS = "android.permission.ANSWER_PHONE_CALLS" 12 | PERMISSION_RECEIVE_WAP_PUSH = "android.permission.RECEIVE_WAP_PUSH" 13 | PERMISSION_BODY_SENSORS = "android.permission.BODY_SENSORS" 14 | PERMISSION_READ_PHONE_NUMBERS = "android.permission.READ_PHONE_NUMBERS" 15 | PERMISSION_RECEIVE_MMS = "android.permission.RECEIVE_MMS" 16 | PERMISSION_RECEIVE_SMS = "android.permission.RECEIVE_SMS" 17 | PERMISSION_READ_EXTERNAL_STORAGE = "android.permission.READ_EXTERNAL_STORAGE" 18 | PERMISSION_ACCESS_COARSE_LOCATION = "android.permission.ACCESS_COARSE_LOCATION" 19 | PERMISSION_READ_PHONE_STATE = "android.permission.READ_PHONE_STATE" 20 | PERMISSION_SEND_SMS = "android.permission.SEND_SMS" 21 | PERMISSION_CALL_PHONE = "android.permission.CALL_PHONE" 22 | PERMISSION_WRITE_CONTACTS = "android.permission.WRITE_CONTACTS" 23 | PERMISSION_ACCEPT_HANDOVER = "android.permission.ACCEPT_HANDOVER" 24 | PERMISSION_CAMERA = "android.permission.CAMERA" 25 | PERMISSION_WRITE_CALENDAR = "android.permission.WRITE_CALENDAR" 26 | PERMISSION_WRITE_CALL_LOG = "android.permission.WRITE_CALL_LOG" 27 | PERMISSION_USE_SIP = "android.permission.USE_SIP" 28 | PERMISSION_PROCESS_OUTGOING_CALLS = "android.permission.PROCESS_OUTGOING_CALLS" 29 | PERMISSION_READ_CELL_BROADCASTS = "android.permission.READ_CELL_BROADCASTS" 30 | PERMISSION_GET_ACCOUNTS = "android.permission.GET_ACCOUNTS" 31 | PERMISSION_WRITE_EXTERNAL_STORAGE = "android.permission.WRITE_EXTERNAL_STORAGE" 32 | PERMISSION_ACTIVITY_RECOGNITION = "android.permission.ACTIVITY_RECOGNITION" 33 | PERMISSION_RECORD_AUDIO = "android.permission.RECORD_AUDIO" 34 | PERMISSION_READ_CONTACTS = "android.permission.READ_CONTACTS" 35 | PERMISSION_ACCESS_BACKGROUND_LOCATION = "android.permission.ACCESS_BACKGROUND_LOCATION" 36 | PERMISSION_ACCESS_MEDIA_LOCATION = "android.permission.ACCESS_MEDIA_LOCATION" 37 | 38 | # Android activity flags 39 | FLAG_ACTIVITY_BROUGHT_TO_FRONT = 0x00400000 40 | FLAG_ACTIVITY_CLEAR_TASK = 0x00008000 41 | FLAG_ACTIVITY_CLEAR_TOP = 0x04000000 42 | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS = 0x00800000 43 | FLAG_ACTIVITY_FORWARD_RESULT = 0x02000000 44 | FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY = 0x00100000 45 | FLAG_ACTIVITY_LAUNCH_ADJACENT = 0x00001000 46 | FLAG_ACTIVITY_MATCH_EXTERNAL = 0x00000800 47 | 48 | FLAG_ACTIVITY_MULTIPLE_TASK = 0x08000000 49 | FLAG_ACTIVITY_NEW_DOCUMENT = 0x00080000 50 | FLAG_ACTIVITY_NEW_TASK = 0x10000000 51 | FLAG_ACTIVITY_NO_ANIMATION = 0x00010000 52 | FLAG_ACTIVITY_NO_HISTORY = 0x40000000 53 | FLAG_ACTIVITY_NO_USER_ACTION = 0x00040000 54 | 55 | FLAG_ACTIVITY_PREVIOUS_IS_TOP = 0x01000000 56 | FLAG_ACTIVITY_REORDER_TO_FRONT = 0x00020000 57 | FLAG_ACTIVITY_REQUIRE_DEFAULT = 0x00000200 58 | FLAG_ACTIVITY_REQUIRE_NON_BROWSER = 0x00000400 59 | 60 | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED = 0x00200000 61 | FLAG_ACTIVITY_RETAIN_IN_RECENTS = 0x00002000 62 | FLAG_ACTIVITY_SINGLE_TOP = 0x20000000 63 | FLAG_ACTIVITY_TASK_ON_HOME = 0x00004000 -------------------------------------------------------------------------------- /lamda/exceptions.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 rev1si0n (https://github.com/rev1si0n). All rights reserved. 2 | # 3 | # Distributed under MIT license. 4 | # See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 5 | class CompatibilityException(Exception): 6 | """ Exception """ 7 | class DeadSystemException(Exception): 8 | """ Exception """ 9 | class DeviceUnavailable(Exception): 10 | """ Exception """ 11 | class DuplicateEntryError(Exception): 12 | """ Exception """ 13 | class IllegalArgumentException(Exception): 14 | """ Exception """ 15 | class IllegalStateException(Exception): 16 | """ Exception """ 17 | class InstallPackageFailed(Exception): 18 | """ Exception """ 19 | class InternalRpcException(Exception): 20 | """ Exception """ 21 | class InvalidAndroidPackage(Exception): 22 | """ Exception """ 23 | class InvalidArgumentError(Exception): 24 | """ Exception """ 25 | class InvalidOperationError(Exception): 26 | """ Exception """ 27 | class InvalidRootCertificate(Exception): 28 | """ Exception """ 29 | class MethodNotFoundException(Exception): 30 | """ Exception """ 31 | class NameNotFoundException(Exception): 32 | """ Exception """ 33 | class NotImplementedException(Exception): 34 | """ Exception """ 35 | class NullPointerException(Exception): 36 | """ Exception """ 37 | class SecurityException(Exception): 38 | """ Exception """ 39 | class ServiceUnavailable(Exception): 40 | """ Exception """ 41 | class StaleObjectException(Exception): 42 | """ Exception """ 43 | class StartupActivityNotFound(Exception): 44 | """ Exception """ 45 | class StorageOutOfMemory(Exception): 46 | """ Exception """ 47 | class UiAutomatorException(Exception): 48 | """ Exception """ 49 | class UiObjectNotFoundException(Exception): 50 | """ Exception """ 51 | class UnHandledException(Exception): 52 | """ Exception """ -------------------------------------------------------------------------------- /lamda/google/protobuf/any.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option go_package = "google.golang.org/protobuf/types/known/anypb"; 37 | option java_package = "com.google.protobuf"; 38 | option java_outer_classname = "AnyProto"; 39 | option java_multiple_files = true; 40 | option objc_class_prefix = "GPB"; 41 | 42 | // `Any` contains an arbitrary serialized protocol buffer message along with a 43 | // URL that describes the type of the serialized message. 44 | // 45 | // Protobuf library provides support to pack/unpack Any values in the form 46 | // of utility functions or additional generated methods of the Any type. 47 | // 48 | // Example 1: Pack and unpack a message in C++. 49 | // 50 | // Foo foo = ...; 51 | // Any any; 52 | // any.PackFrom(foo); 53 | // ... 54 | // if (any.UnpackTo(&foo)) { 55 | // ... 56 | // } 57 | // 58 | // Example 2: Pack and unpack a message in Java. 59 | // 60 | // Foo foo = ...; 61 | // Any any = Any.pack(foo); 62 | // ... 63 | // if (any.is(Foo.class)) { 64 | // foo = any.unpack(Foo.class); 65 | // } 66 | // 67 | // Example 3: Pack and unpack a message in Python. 68 | // 69 | // foo = Foo(...) 70 | // any = Any() 71 | // any.Pack(foo) 72 | // ... 73 | // if any.Is(Foo.DESCRIPTOR): 74 | // any.Unpack(foo) 75 | // ... 76 | // 77 | // Example 4: Pack and unpack a message in Go 78 | // 79 | // foo := &pb.Foo{...} 80 | // any, err := anypb.New(foo) 81 | // if err != nil { 82 | // ... 83 | // } 84 | // ... 85 | // foo := &pb.Foo{} 86 | // if err := any.UnmarshalTo(foo); err != nil { 87 | // ... 88 | // } 89 | // 90 | // The pack methods provided by protobuf library will by default use 91 | // 'type.googleapis.com/full.type.name' as the type URL and the unpack 92 | // methods only use the fully qualified type name after the last '/' 93 | // in the type URL, for example "foo.bar.com/x/y.z" will yield type 94 | // name "y.z". 95 | // 96 | // 97 | // JSON 98 | // ==== 99 | // The JSON representation of an `Any` value uses the regular 100 | // representation of the deserialized, embedded message, with an 101 | // additional field `@type` which contains the type URL. Example: 102 | // 103 | // package google.profile; 104 | // message Person { 105 | // string first_name = 1; 106 | // string last_name = 2; 107 | // } 108 | // 109 | // { 110 | // "@type": "type.googleapis.com/google.profile.Person", 111 | // "firstName": , 112 | // "lastName": 113 | // } 114 | // 115 | // If the embedded message type is well-known and has a custom JSON 116 | // representation, that representation will be embedded adding a field 117 | // `value` which holds the custom JSON in addition to the `@type` 118 | // field. Example (for message [google.protobuf.Duration][]): 119 | // 120 | // { 121 | // "@type": "type.googleapis.com/google.protobuf.Duration", 122 | // "value": "1.212s" 123 | // } 124 | // 125 | message Any { 126 | // A URL/resource name that uniquely identifies the type of the serialized 127 | // protocol buffer message. This string must contain at least 128 | // one "/" character. The last segment of the URL's path must represent 129 | // the fully qualified name of the type (as in 130 | // `path/google.protobuf.Duration`). The name should be in a canonical form 131 | // (e.g., leading "." is not accepted). 132 | // 133 | // In practice, teams usually precompile into the binary all types that they 134 | // expect it to use in the context of Any. However, for URLs which use the 135 | // scheme `http`, `https`, or no scheme, one can optionally set up a type 136 | // server that maps type URLs to message definitions as follows: 137 | // 138 | // * If no scheme is provided, `https` is assumed. 139 | // * An HTTP GET on the URL must yield a [google.protobuf.Type][] 140 | // value in binary format, or produce an error. 141 | // * Applications are allowed to cache lookup results based on the 142 | // URL, or have them precompiled into a binary to avoid any 143 | // lookup. Therefore, binary compatibility needs to be preserved 144 | // on changes to types. (Use versioned type names to manage 145 | // breaking changes.) 146 | // 147 | // Note: this functionality is not currently available in the official 148 | // protobuf release, and it is not used for type URLs beginning with 149 | // type.googleapis.com. 150 | // 151 | // Schemes other than `http`, `https` (or the empty scheme) might be 152 | // used with implementation specific semantics. 153 | // 154 | string type_url = 1; 155 | 156 | // Must be a valid serialized protocol buffer of the above specified type. 157 | bytes value = 2; 158 | } 159 | -------------------------------------------------------------------------------- /lamda/google/protobuf/api.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | import "google/protobuf/source_context.proto"; 36 | import "google/protobuf/type.proto"; 37 | 38 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 39 | option java_package = "com.google.protobuf"; 40 | option java_outer_classname = "ApiProto"; 41 | option java_multiple_files = true; 42 | option objc_class_prefix = "GPB"; 43 | option go_package = "google.golang.org/protobuf/types/known/apipb"; 44 | 45 | // Api is a light-weight descriptor for an API Interface. 46 | // 47 | // Interfaces are also described as "protocol buffer services" in some contexts, 48 | // such as by the "service" keyword in a .proto file, but they are different 49 | // from API Services, which represent a concrete implementation of an interface 50 | // as opposed to simply a description of methods and bindings. They are also 51 | // sometimes simply referred to as "APIs" in other contexts, such as the name of 52 | // this message itself. See https://cloud.google.com/apis/design/glossary for 53 | // detailed terminology. 54 | message Api { 55 | // The fully qualified name of this interface, including package name 56 | // followed by the interface's simple name. 57 | string name = 1; 58 | 59 | // The methods of this interface, in unspecified order. 60 | repeated Method methods = 2; 61 | 62 | // Any metadata attached to the interface. 63 | repeated Option options = 3; 64 | 65 | // A version string for this interface. If specified, must have the form 66 | // `major-version.minor-version`, as in `1.10`. If the minor version is 67 | // omitted, it defaults to zero. If the entire version field is empty, the 68 | // major version is derived from the package name, as outlined below. If the 69 | // field is not empty, the version in the package name will be verified to be 70 | // consistent with what is provided here. 71 | // 72 | // The versioning schema uses [semantic 73 | // versioning](http://semver.org) where the major version number 74 | // indicates a breaking change and the minor version an additive, 75 | // non-breaking change. Both version numbers are signals to users 76 | // what to expect from different versions, and should be carefully 77 | // chosen based on the product plan. 78 | // 79 | // The major version is also reflected in the package name of the 80 | // interface, which must end in `v`, as in 81 | // `google.feature.v1`. For major versions 0 and 1, the suffix can 82 | // be omitted. Zero major versions must only be used for 83 | // experimental, non-GA interfaces. 84 | // 85 | // 86 | string version = 4; 87 | 88 | // Source context for the protocol buffer service represented by this 89 | // message. 90 | SourceContext source_context = 5; 91 | 92 | // Included interfaces. See [Mixin][]. 93 | repeated Mixin mixins = 6; 94 | 95 | // The source syntax of the service. 96 | Syntax syntax = 7; 97 | } 98 | 99 | // Method represents a method of an API interface. 100 | message Method { 101 | // The simple name of this method. 102 | string name = 1; 103 | 104 | // A URL of the input message type. 105 | string request_type_url = 2; 106 | 107 | // If true, the request is streamed. 108 | bool request_streaming = 3; 109 | 110 | // The URL of the output message type. 111 | string response_type_url = 4; 112 | 113 | // If true, the response is streamed. 114 | bool response_streaming = 5; 115 | 116 | // Any metadata attached to the method. 117 | repeated Option options = 6; 118 | 119 | // The source syntax of this method. 120 | Syntax syntax = 7; 121 | } 122 | 123 | // Declares an API Interface to be included in this interface. The including 124 | // interface must redeclare all the methods from the included interface, but 125 | // documentation and options are inherited as follows: 126 | // 127 | // - If after comment and whitespace stripping, the documentation 128 | // string of the redeclared method is empty, it will be inherited 129 | // from the original method. 130 | // 131 | // - Each annotation belonging to the service config (http, 132 | // visibility) which is not set in the redeclared method will be 133 | // inherited. 134 | // 135 | // - If an http annotation is inherited, the path pattern will be 136 | // modified as follows. Any version prefix will be replaced by the 137 | // version of the including interface plus the [root][] path if 138 | // specified. 139 | // 140 | // Example of a simple mixin: 141 | // 142 | // package google.acl.v1; 143 | // service AccessControl { 144 | // // Get the underlying ACL object. 145 | // rpc GetAcl(GetAclRequest) returns (Acl) { 146 | // option (google.api.http).get = "/v1/{resource=**}:getAcl"; 147 | // } 148 | // } 149 | // 150 | // package google.storage.v2; 151 | // service Storage { 152 | // rpc GetAcl(GetAclRequest) returns (Acl); 153 | // 154 | // // Get a data record. 155 | // rpc GetData(GetDataRequest) returns (Data) { 156 | // option (google.api.http).get = "/v2/{resource=**}"; 157 | // } 158 | // } 159 | // 160 | // Example of a mixin configuration: 161 | // 162 | // apis: 163 | // - name: google.storage.v2.Storage 164 | // mixins: 165 | // - name: google.acl.v1.AccessControl 166 | // 167 | // The mixin construct implies that all methods in `AccessControl` are 168 | // also declared with same name and request/response types in 169 | // `Storage`. A documentation generator or annotation processor will 170 | // see the effective `Storage.GetAcl` method after inheriting 171 | // documentation and annotations as follows: 172 | // 173 | // service Storage { 174 | // // Get the underlying ACL object. 175 | // rpc GetAcl(GetAclRequest) returns (Acl) { 176 | // option (google.api.http).get = "/v2/{resource=**}:getAcl"; 177 | // } 178 | // ... 179 | // } 180 | // 181 | // Note how the version in the path pattern changed from `v1` to `v2`. 182 | // 183 | // If the `root` field in the mixin is specified, it should be a 184 | // relative path under which inherited HTTP paths are placed. Example: 185 | // 186 | // apis: 187 | // - name: google.storage.v2.Storage 188 | // mixins: 189 | // - name: google.acl.v1.AccessControl 190 | // root: acls 191 | // 192 | // This implies the following inherited HTTP annotation: 193 | // 194 | // service Storage { 195 | // // Get the underlying ACL object. 196 | // rpc GetAcl(GetAclRequest) returns (Acl) { 197 | // option (google.api.http).get = "/v2/acls/{resource=**}:getAcl"; 198 | // } 199 | // ... 200 | // } 201 | message Mixin { 202 | // The fully qualified name of the interface which is included. 203 | string name = 1; 204 | 205 | // If non-empty specifies a path under which inherited HTTP paths 206 | // are rooted. 207 | string root = 2; 208 | } 209 | -------------------------------------------------------------------------------- /lamda/google/protobuf/compiler/plugin.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | // Author: kenton@google.com (Kenton Varda) 32 | // 33 | // WARNING: The plugin interface is currently EXPERIMENTAL and is subject to 34 | // change. 35 | // 36 | // protoc (aka the Protocol Compiler) can be extended via plugins. A plugin is 37 | // just a program that reads a CodeGeneratorRequest from stdin and writes a 38 | // CodeGeneratorResponse to stdout. 39 | // 40 | // Plugins written using C++ can use google/protobuf/compiler/plugin.h instead 41 | // of dealing with the raw protocol defined here. 42 | // 43 | // A plugin executable needs only to be placed somewhere in the path. The 44 | // plugin should be named "protoc-gen-$NAME", and will then be used when the 45 | // flag "--${NAME}_out" is passed to protoc. 46 | 47 | syntax = "proto2"; 48 | 49 | package google.protobuf.compiler; 50 | option java_package = "com.google.protobuf.compiler"; 51 | option java_outer_classname = "PluginProtos"; 52 | 53 | option go_package = "google.golang.org/protobuf/types/pluginpb"; 54 | 55 | import "google/protobuf/descriptor.proto"; 56 | 57 | // The version number of protocol compiler. 58 | message Version { 59 | optional int32 major = 1; 60 | optional int32 minor = 2; 61 | optional int32 patch = 3; 62 | // A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should 63 | // be empty for mainline stable releases. 64 | optional string suffix = 4; 65 | } 66 | 67 | // An encoded CodeGeneratorRequest is written to the plugin's stdin. 68 | message CodeGeneratorRequest { 69 | // The .proto files that were explicitly listed on the command-line. The 70 | // code generator should generate code only for these files. Each file's 71 | // descriptor will be included in proto_file, below. 72 | repeated string file_to_generate = 1; 73 | 74 | // The generator parameter passed on the command-line. 75 | optional string parameter = 2; 76 | 77 | // FileDescriptorProtos for all files in files_to_generate and everything 78 | // they import. The files will appear in topological order, so each file 79 | // appears before any file that imports it. 80 | // 81 | // protoc guarantees that all proto_files will be written after 82 | // the fields above, even though this is not technically guaranteed by the 83 | // protobuf wire format. This theoretically could allow a plugin to stream 84 | // in the FileDescriptorProtos and handle them one by one rather than read 85 | // the entire set into memory at once. However, as of this writing, this 86 | // is not similarly optimized on protoc's end -- it will store all fields in 87 | // memory at once before sending them to the plugin. 88 | // 89 | // Type names of fields and extensions in the FileDescriptorProto are always 90 | // fully qualified. 91 | repeated FileDescriptorProto proto_file = 15; 92 | 93 | // The version number of protocol compiler. 94 | optional Version compiler_version = 3; 95 | 96 | } 97 | 98 | // The plugin writes an encoded CodeGeneratorResponse to stdout. 99 | message CodeGeneratorResponse { 100 | // Error message. If non-empty, code generation failed. The plugin process 101 | // should exit with status code zero even if it reports an error in this way. 102 | // 103 | // This should be used to indicate errors in .proto files which prevent the 104 | // code generator from generating correct code. Errors which indicate a 105 | // problem in protoc itself -- such as the input CodeGeneratorRequest being 106 | // unparseable -- should be reported by writing a message to stderr and 107 | // exiting with a non-zero status code. 108 | optional string error = 1; 109 | 110 | // A bitmask of supported features that the code generator supports. 111 | // This is a bitwise "or" of values from the Feature enum. 112 | optional uint64 supported_features = 2; 113 | 114 | // Sync with code_generator.h. 115 | enum Feature { 116 | FEATURE_NONE = 0; 117 | FEATURE_PROTO3_OPTIONAL = 1; 118 | } 119 | 120 | // Represents a single generated file. 121 | message File { 122 | // The file name, relative to the output directory. The name must not 123 | // contain "." or ".." components and must be relative, not be absolute (so, 124 | // the file cannot lie outside the output directory). "/" must be used as 125 | // the path separator, not "\". 126 | // 127 | // If the name is omitted, the content will be appended to the previous 128 | // file. This allows the generator to break large files into small chunks, 129 | // and allows the generated text to be streamed back to protoc so that large 130 | // files need not reside completely in memory at one time. Note that as of 131 | // this writing protoc does not optimize for this -- it will read the entire 132 | // CodeGeneratorResponse before writing files to disk. 133 | optional string name = 1; 134 | 135 | // If non-empty, indicates that the named file should already exist, and the 136 | // content here is to be inserted into that file at a defined insertion 137 | // point. This feature allows a code generator to extend the output 138 | // produced by another code generator. The original generator may provide 139 | // insertion points by placing special annotations in the file that look 140 | // like: 141 | // @@protoc_insertion_point(NAME) 142 | // The annotation can have arbitrary text before and after it on the line, 143 | // which allows it to be placed in a comment. NAME should be replaced with 144 | // an identifier naming the point -- this is what other generators will use 145 | // as the insertion_point. Code inserted at this point will be placed 146 | // immediately above the line containing the insertion point (thus multiple 147 | // insertions to the same point will come out in the order they were added). 148 | // The double-@ is intended to make it unlikely that the generated code 149 | // could contain things that look like insertion points by accident. 150 | // 151 | // For example, the C++ code generator places the following line in the 152 | // .pb.h files that it generates: 153 | // // @@protoc_insertion_point(namespace_scope) 154 | // This line appears within the scope of the file's package namespace, but 155 | // outside of any particular class. Another plugin can then specify the 156 | // insertion_point "namespace_scope" to generate additional classes or 157 | // other declarations that should be placed in this scope. 158 | // 159 | // Note that if the line containing the insertion point begins with 160 | // whitespace, the same whitespace will be added to every line of the 161 | // inserted text. This is useful for languages like Python, where 162 | // indentation matters. In these languages, the insertion point comment 163 | // should be indented the same amount as any inserted code will need to be 164 | // in order to work correctly in that context. 165 | // 166 | // The code generator that generates the initial file and the one which 167 | // inserts into it must both run as part of a single invocation of protoc. 168 | // Code generators are executed in the order in which they appear on the 169 | // command line. 170 | // 171 | // If |insertion_point| is present, |name| must also be present. 172 | optional string insertion_point = 2; 173 | 174 | // The file contents. 175 | optional string content = 15; 176 | 177 | // Information describing the file content being inserted. If an insertion 178 | // point is used, this information will be appropriately offset and inserted 179 | // into the code generation metadata for the generated files. 180 | optional GeneratedCodeInfo generated_code_info = 16; 181 | } 182 | repeated File file = 15; 183 | } 184 | -------------------------------------------------------------------------------- /lamda/google/protobuf/duration.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option cc_enable_arenas = true; 37 | option go_package = "google.golang.org/protobuf/types/known/durationpb"; 38 | option java_package = "com.google.protobuf"; 39 | option java_outer_classname = "DurationProto"; 40 | option java_multiple_files = true; 41 | option objc_class_prefix = "GPB"; 42 | 43 | // A Duration represents a signed, fixed-length span of time represented 44 | // as a count of seconds and fractions of seconds at nanosecond 45 | // resolution. It is independent of any calendar and concepts like "day" 46 | // or "month". It is related to Timestamp in that the difference between 47 | // two Timestamp values is a Duration and it can be added or subtracted 48 | // from a Timestamp. Range is approximately +-10,000 years. 49 | // 50 | // # Examples 51 | // 52 | // Example 1: Compute Duration from two Timestamps in pseudo code. 53 | // 54 | // Timestamp start = ...; 55 | // Timestamp end = ...; 56 | // Duration duration = ...; 57 | // 58 | // duration.seconds = end.seconds - start.seconds; 59 | // duration.nanos = end.nanos - start.nanos; 60 | // 61 | // if (duration.seconds < 0 && duration.nanos > 0) { 62 | // duration.seconds += 1; 63 | // duration.nanos -= 1000000000; 64 | // } else if (duration.seconds > 0 && duration.nanos < 0) { 65 | // duration.seconds -= 1; 66 | // duration.nanos += 1000000000; 67 | // } 68 | // 69 | // Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. 70 | // 71 | // Timestamp start = ...; 72 | // Duration duration = ...; 73 | // Timestamp end = ...; 74 | // 75 | // end.seconds = start.seconds + duration.seconds; 76 | // end.nanos = start.nanos + duration.nanos; 77 | // 78 | // if (end.nanos < 0) { 79 | // end.seconds -= 1; 80 | // end.nanos += 1000000000; 81 | // } else if (end.nanos >= 1000000000) { 82 | // end.seconds += 1; 83 | // end.nanos -= 1000000000; 84 | // } 85 | // 86 | // Example 3: Compute Duration from datetime.timedelta in Python. 87 | // 88 | // td = datetime.timedelta(days=3, minutes=10) 89 | // duration = Duration() 90 | // duration.FromTimedelta(td) 91 | // 92 | // # JSON Mapping 93 | // 94 | // In JSON format, the Duration type is encoded as a string rather than an 95 | // object, where the string ends in the suffix "s" (indicating seconds) and 96 | // is preceded by the number of seconds, with nanoseconds expressed as 97 | // fractional seconds. For example, 3 seconds with 0 nanoseconds should be 98 | // encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should 99 | // be expressed in JSON format as "3.000000001s", and 3 seconds and 1 100 | // microsecond should be expressed in JSON format as "3.000001s". 101 | // 102 | // 103 | message Duration { 104 | // Signed seconds of the span of time. Must be from -315,576,000,000 105 | // to +315,576,000,000 inclusive. Note: these bounds are computed from: 106 | // 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years 107 | int64 seconds = 1; 108 | 109 | // Signed fractions of a second at nanosecond resolution of the span 110 | // of time. Durations less than one second are represented with a 0 111 | // `seconds` field and a positive or negative `nanos` field. For durations 112 | // of one second or more, a non-zero value for the `nanos` field must be 113 | // of the same sign as the `seconds` field. Must be from -999,999,999 114 | // to +999,999,999 inclusive. 115 | int32 nanos = 2; 116 | } 117 | -------------------------------------------------------------------------------- /lamda/google/protobuf/empty.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option go_package = "google.golang.org/protobuf/types/known/emptypb"; 37 | option java_package = "com.google.protobuf"; 38 | option java_outer_classname = "EmptyProto"; 39 | option java_multiple_files = true; 40 | option objc_class_prefix = "GPB"; 41 | option cc_enable_arenas = true; 42 | 43 | // A generic empty message that you can re-use to avoid defining duplicated 44 | // empty messages in your APIs. A typical example is to use it as the request 45 | // or the response type of an API method. For instance: 46 | // 47 | // service Foo { 48 | // rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); 49 | // } 50 | // 51 | // The JSON representation for `Empty` is empty JSON object `{}`. 52 | message Empty {} 53 | -------------------------------------------------------------------------------- /lamda/google/protobuf/field_mask.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option java_package = "com.google.protobuf"; 37 | option java_outer_classname = "FieldMaskProto"; 38 | option java_multiple_files = true; 39 | option objc_class_prefix = "GPB"; 40 | option go_package = "google.golang.org/protobuf/types/known/fieldmaskpb"; 41 | option cc_enable_arenas = true; 42 | 43 | // `FieldMask` represents a set of symbolic field paths, for example: 44 | // 45 | // paths: "f.a" 46 | // paths: "f.b.d" 47 | // 48 | // Here `f` represents a field in some root message, `a` and `b` 49 | // fields in the message found in `f`, and `d` a field found in the 50 | // message in `f.b`. 51 | // 52 | // Field masks are used to specify a subset of fields that should be 53 | // returned by a get operation or modified by an update operation. 54 | // Field masks also have a custom JSON encoding (see below). 55 | // 56 | // # Field Masks in Projections 57 | // 58 | // When used in the context of a projection, a response message or 59 | // sub-message is filtered by the API to only contain those fields as 60 | // specified in the mask. For example, if the mask in the previous 61 | // example is applied to a response message as follows: 62 | // 63 | // f { 64 | // a : 22 65 | // b { 66 | // d : 1 67 | // x : 2 68 | // } 69 | // y : 13 70 | // } 71 | // z: 8 72 | // 73 | // The result will not contain specific values for fields x,y and z 74 | // (their value will be set to the default, and omitted in proto text 75 | // output): 76 | // 77 | // 78 | // f { 79 | // a : 22 80 | // b { 81 | // d : 1 82 | // } 83 | // } 84 | // 85 | // A repeated field is not allowed except at the last position of a 86 | // paths string. 87 | // 88 | // If a FieldMask object is not present in a get operation, the 89 | // operation applies to all fields (as if a FieldMask of all fields 90 | // had been specified). 91 | // 92 | // Note that a field mask does not necessarily apply to the 93 | // top-level response message. In case of a REST get operation, the 94 | // field mask applies directly to the response, but in case of a REST 95 | // list operation, the mask instead applies to each individual message 96 | // in the returned resource list. In case of a REST custom method, 97 | // other definitions may be used. Where the mask applies will be 98 | // clearly documented together with its declaration in the API. In 99 | // any case, the effect on the returned resource/resources is required 100 | // behavior for APIs. 101 | // 102 | // # Field Masks in Update Operations 103 | // 104 | // A field mask in update operations specifies which fields of the 105 | // targeted resource are going to be updated. The API is required 106 | // to only change the values of the fields as specified in the mask 107 | // and leave the others untouched. If a resource is passed in to 108 | // describe the updated values, the API ignores the values of all 109 | // fields not covered by the mask. 110 | // 111 | // If a repeated field is specified for an update operation, new values will 112 | // be appended to the existing repeated field in the target resource. Note that 113 | // a repeated field is only allowed in the last position of a `paths` string. 114 | // 115 | // If a sub-message is specified in the last position of the field mask for an 116 | // update operation, then new value will be merged into the existing sub-message 117 | // in the target resource. 118 | // 119 | // For example, given the target message: 120 | // 121 | // f { 122 | // b { 123 | // d: 1 124 | // x: 2 125 | // } 126 | // c: [1] 127 | // } 128 | // 129 | // And an update message: 130 | // 131 | // f { 132 | // b { 133 | // d: 10 134 | // } 135 | // c: [2] 136 | // } 137 | // 138 | // then if the field mask is: 139 | // 140 | // paths: ["f.b", "f.c"] 141 | // 142 | // then the result will be: 143 | // 144 | // f { 145 | // b { 146 | // d: 10 147 | // x: 2 148 | // } 149 | // c: [1, 2] 150 | // } 151 | // 152 | // An implementation may provide options to override this default behavior for 153 | // repeated and message fields. 154 | // 155 | // In order to reset a field's value to the default, the field must 156 | // be in the mask and set to the default value in the provided resource. 157 | // Hence, in order to reset all fields of a resource, provide a default 158 | // instance of the resource and set all fields in the mask, or do 159 | // not provide a mask as described below. 160 | // 161 | // If a field mask is not present on update, the operation applies to 162 | // all fields (as if a field mask of all fields has been specified). 163 | // Note that in the presence of schema evolution, this may mean that 164 | // fields the client does not know and has therefore not filled into 165 | // the request will be reset to their default. If this is unwanted 166 | // behavior, a specific service may require a client to always specify 167 | // a field mask, producing an error if not. 168 | // 169 | // As with get operations, the location of the resource which 170 | // describes the updated values in the request message depends on the 171 | // operation kind. In any case, the effect of the field mask is 172 | // required to be honored by the API. 173 | // 174 | // ## Considerations for HTTP REST 175 | // 176 | // The HTTP kind of an update operation which uses a field mask must 177 | // be set to PATCH instead of PUT in order to satisfy HTTP semantics 178 | // (PUT must only be used for full updates). 179 | // 180 | // # JSON Encoding of Field Masks 181 | // 182 | // In JSON, a field mask is encoded as a single string where paths are 183 | // separated by a comma. Fields name in each path are converted 184 | // to/from lower-camel naming conventions. 185 | // 186 | // As an example, consider the following message declarations: 187 | // 188 | // message Profile { 189 | // User user = 1; 190 | // Photo photo = 2; 191 | // } 192 | // message User { 193 | // string display_name = 1; 194 | // string address = 2; 195 | // } 196 | // 197 | // In proto a field mask for `Profile` may look as such: 198 | // 199 | // mask { 200 | // paths: "user.display_name" 201 | // paths: "photo" 202 | // } 203 | // 204 | // In JSON, the same mask is represented as below: 205 | // 206 | // { 207 | // mask: "user.displayName,photo" 208 | // } 209 | // 210 | // # Field Masks and Oneof Fields 211 | // 212 | // Field masks treat fields in oneofs just as regular fields. Consider the 213 | // following message: 214 | // 215 | // message SampleMessage { 216 | // oneof test_oneof { 217 | // string name = 4; 218 | // SubMessage sub_message = 9; 219 | // } 220 | // } 221 | // 222 | // The field mask can be: 223 | // 224 | // mask { 225 | // paths: "name" 226 | // } 227 | // 228 | // Or: 229 | // 230 | // mask { 231 | // paths: "sub_message" 232 | // } 233 | // 234 | // Note that oneof type names ("test_oneof" in this case) cannot be used in 235 | // paths. 236 | // 237 | // ## Field Mask Verification 238 | // 239 | // The implementation of any API method which has a FieldMask type field in the 240 | // request should verify the included field paths, and return an 241 | // `INVALID_ARGUMENT` error if any path is unmappable. 242 | message FieldMask { 243 | // The set of field mask paths. 244 | repeated string paths = 1; 245 | } 246 | -------------------------------------------------------------------------------- /lamda/google/protobuf/source_context.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option java_package = "com.google.protobuf"; 37 | option java_outer_classname = "SourceContextProto"; 38 | option java_multiple_files = true; 39 | option objc_class_prefix = "GPB"; 40 | option go_package = "google.golang.org/protobuf/types/known/sourcecontextpb"; 41 | 42 | // `SourceContext` represents information about the source of a 43 | // protobuf element, like the file in which it is defined. 44 | message SourceContext { 45 | // The path-qualified name of the .proto file that contained the associated 46 | // protobuf element. For example: `"google/protobuf/source_context.proto"`. 47 | string file_name = 1; 48 | } 49 | -------------------------------------------------------------------------------- /lamda/google/protobuf/struct.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option cc_enable_arenas = true; 37 | option go_package = "google.golang.org/protobuf/types/known/structpb"; 38 | option java_package = "com.google.protobuf"; 39 | option java_outer_classname = "StructProto"; 40 | option java_multiple_files = true; 41 | option objc_class_prefix = "GPB"; 42 | 43 | // `Struct` represents a structured data value, consisting of fields 44 | // which map to dynamically typed values. In some languages, `Struct` 45 | // might be supported by a native representation. For example, in 46 | // scripting languages like JS a struct is represented as an 47 | // object. The details of that representation are described together 48 | // with the proto support for the language. 49 | // 50 | // The JSON representation for `Struct` is JSON object. 51 | message Struct { 52 | // Unordered map of dynamically typed values. 53 | map fields = 1; 54 | } 55 | 56 | // `Value` represents a dynamically typed value which can be either 57 | // null, a number, a string, a boolean, a recursive struct value, or a 58 | // list of values. A producer of value is expected to set one of that 59 | // variants, absence of any variant indicates an error. 60 | // 61 | // The JSON representation for `Value` is JSON value. 62 | message Value { 63 | // The kind of value. 64 | oneof kind { 65 | // Represents a null value. 66 | NullValue null_value = 1; 67 | // Represents a double value. 68 | double number_value = 2; 69 | // Represents a string value. 70 | string string_value = 3; 71 | // Represents a boolean value. 72 | bool bool_value = 4; 73 | // Represents a structured value. 74 | Struct struct_value = 5; 75 | // Represents a repeated `Value`. 76 | ListValue list_value = 6; 77 | } 78 | } 79 | 80 | // `NullValue` is a singleton enumeration to represent the null value for the 81 | // `Value` type union. 82 | // 83 | // The JSON representation for `NullValue` is JSON `null`. 84 | enum NullValue { 85 | // Null value. 86 | NULL_VALUE = 0; 87 | } 88 | 89 | // `ListValue` is a wrapper around a repeated field of values. 90 | // 91 | // The JSON representation for `ListValue` is JSON array. 92 | message ListValue { 93 | // Repeated field of dynamically typed values. 94 | repeated Value values = 1; 95 | } 96 | -------------------------------------------------------------------------------- /lamda/google/protobuf/timestamp.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option cc_enable_arenas = true; 37 | option go_package = "google.golang.org/protobuf/types/known/timestamppb"; 38 | option java_package = "com.google.protobuf"; 39 | option java_outer_classname = "TimestampProto"; 40 | option java_multiple_files = true; 41 | option objc_class_prefix = "GPB"; 42 | 43 | // A Timestamp represents a point in time independent of any time zone or local 44 | // calendar, encoded as a count of seconds and fractions of seconds at 45 | // nanosecond resolution. The count is relative to an epoch at UTC midnight on 46 | // January 1, 1970, in the proleptic Gregorian calendar which extends the 47 | // Gregorian calendar backwards to year one. 48 | // 49 | // All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap 50 | // second table is needed for interpretation, using a [24-hour linear 51 | // smear](https://developers.google.com/time/smear). 52 | // 53 | // The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By 54 | // restricting to that range, we ensure that we can convert to and from [RFC 55 | // 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. 56 | // 57 | // # Examples 58 | // 59 | // Example 1: Compute Timestamp from POSIX `time()`. 60 | // 61 | // Timestamp timestamp; 62 | // timestamp.set_seconds(time(NULL)); 63 | // timestamp.set_nanos(0); 64 | // 65 | // Example 2: Compute Timestamp from POSIX `gettimeofday()`. 66 | // 67 | // struct timeval tv; 68 | // gettimeofday(&tv, NULL); 69 | // 70 | // Timestamp timestamp; 71 | // timestamp.set_seconds(tv.tv_sec); 72 | // timestamp.set_nanos(tv.tv_usec * 1000); 73 | // 74 | // Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. 75 | // 76 | // FILETIME ft; 77 | // GetSystemTimeAsFileTime(&ft); 78 | // UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; 79 | // 80 | // // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z 81 | // // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. 82 | // Timestamp timestamp; 83 | // timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); 84 | // timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); 85 | // 86 | // Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. 87 | // 88 | // long millis = System.currentTimeMillis(); 89 | // 90 | // Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) 91 | // .setNanos((int) ((millis % 1000) * 1000000)).build(); 92 | // 93 | // 94 | // Example 5: Compute Timestamp from Java `Instant.now()`. 95 | // 96 | // Instant now = Instant.now(); 97 | // 98 | // Timestamp timestamp = 99 | // Timestamp.newBuilder().setSeconds(now.getEpochSecond()) 100 | // .setNanos(now.getNano()).build(); 101 | // 102 | // 103 | // Example 6: Compute Timestamp from current time in Python. 104 | // 105 | // timestamp = Timestamp() 106 | // timestamp.GetCurrentTime() 107 | // 108 | // # JSON Mapping 109 | // 110 | // In JSON format, the Timestamp type is encoded as a string in the 111 | // [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the 112 | // format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" 113 | // where {year} is always expressed using four digits while {month}, {day}, 114 | // {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional 115 | // seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), 116 | // are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone 117 | // is required. A proto3 JSON serializer should always use UTC (as indicated by 118 | // "Z") when printing the Timestamp type and a proto3 JSON parser should be 119 | // able to accept both UTC and other timezones (as indicated by an offset). 120 | // 121 | // For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past 122 | // 01:30 UTC on January 15, 2017. 123 | // 124 | // In JavaScript, one can convert a Date object to this format using the 125 | // standard 126 | // [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) 127 | // method. In Python, a standard `datetime.datetime` object can be converted 128 | // to this format using 129 | // [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with 130 | // the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use 131 | // the Joda Time's [`ISODateTimeFormat.dateTime()`]( 132 | // http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D 133 | // ) to obtain a formatter capable of generating timestamps in this format. 134 | // 135 | // 136 | message Timestamp { 137 | // Represents seconds of UTC time since Unix epoch 138 | // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to 139 | // 9999-12-31T23:59:59Z inclusive. 140 | int64 seconds = 1; 141 | 142 | // Non-negative fractions of a second at nanosecond resolution. Negative 143 | // second values with fractions must still have non-negative nanos values 144 | // that count forward in time. Must be from 0 to 999,999,999 145 | // inclusive. 146 | int32 nanos = 2; 147 | } 148 | -------------------------------------------------------------------------------- /lamda/google/protobuf/type.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | import "google/protobuf/any.proto"; 36 | import "google/protobuf/source_context.proto"; 37 | 38 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 39 | option cc_enable_arenas = true; 40 | option java_package = "com.google.protobuf"; 41 | option java_outer_classname = "TypeProto"; 42 | option java_multiple_files = true; 43 | option objc_class_prefix = "GPB"; 44 | option go_package = "google.golang.org/protobuf/types/known/typepb"; 45 | 46 | // A protocol buffer message type. 47 | message Type { 48 | // The fully qualified message name. 49 | string name = 1; 50 | // The list of fields. 51 | repeated Field fields = 2; 52 | // The list of types appearing in `oneof` definitions in this type. 53 | repeated string oneofs = 3; 54 | // The protocol buffer options. 55 | repeated Option options = 4; 56 | // The source context. 57 | SourceContext source_context = 5; 58 | // The source syntax. 59 | Syntax syntax = 6; 60 | } 61 | 62 | // A single field of a message type. 63 | message Field { 64 | // Basic field types. 65 | enum Kind { 66 | // Field type unknown. 67 | TYPE_UNKNOWN = 0; 68 | // Field type double. 69 | TYPE_DOUBLE = 1; 70 | // Field type float. 71 | TYPE_FLOAT = 2; 72 | // Field type int64. 73 | TYPE_INT64 = 3; 74 | // Field type uint64. 75 | TYPE_UINT64 = 4; 76 | // Field type int32. 77 | TYPE_INT32 = 5; 78 | // Field type fixed64. 79 | TYPE_FIXED64 = 6; 80 | // Field type fixed32. 81 | TYPE_FIXED32 = 7; 82 | // Field type bool. 83 | TYPE_BOOL = 8; 84 | // Field type string. 85 | TYPE_STRING = 9; 86 | // Field type group. Proto2 syntax only, and deprecated. 87 | TYPE_GROUP = 10; 88 | // Field type message. 89 | TYPE_MESSAGE = 11; 90 | // Field type bytes. 91 | TYPE_BYTES = 12; 92 | // Field type uint32. 93 | TYPE_UINT32 = 13; 94 | // Field type enum. 95 | TYPE_ENUM = 14; 96 | // Field type sfixed32. 97 | TYPE_SFIXED32 = 15; 98 | // Field type sfixed64. 99 | TYPE_SFIXED64 = 16; 100 | // Field type sint32. 101 | TYPE_SINT32 = 17; 102 | // Field type sint64. 103 | TYPE_SINT64 = 18; 104 | } 105 | 106 | // Whether a field is optional, required, or repeated. 107 | enum Cardinality { 108 | // For fields with unknown cardinality. 109 | CARDINALITY_UNKNOWN = 0; 110 | // For optional fields. 111 | CARDINALITY_OPTIONAL = 1; 112 | // For required fields. Proto2 syntax only. 113 | CARDINALITY_REQUIRED = 2; 114 | // For repeated fields. 115 | CARDINALITY_REPEATED = 3; 116 | } 117 | 118 | // The field type. 119 | Kind kind = 1; 120 | // The field cardinality. 121 | Cardinality cardinality = 2; 122 | // The field number. 123 | int32 number = 3; 124 | // The field name. 125 | string name = 4; 126 | // The field type URL, without the scheme, for message or enumeration 127 | // types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`. 128 | string type_url = 6; 129 | // The index of the field type in `Type.oneofs`, for message or enumeration 130 | // types. The first type has index 1; zero means the type is not in the list. 131 | int32 oneof_index = 7; 132 | // Whether to use alternative packed wire representation. 133 | bool packed = 8; 134 | // The protocol buffer options. 135 | repeated Option options = 9; 136 | // The field JSON name. 137 | string json_name = 10; 138 | // The string value of the default value of this field. Proto2 syntax only. 139 | string default_value = 11; 140 | } 141 | 142 | // Enum type definition. 143 | message Enum { 144 | // Enum type name. 145 | string name = 1; 146 | // Enum value definitions. 147 | repeated EnumValue enumvalue = 2; 148 | // Protocol buffer options. 149 | repeated Option options = 3; 150 | // The source context. 151 | SourceContext source_context = 4; 152 | // The source syntax. 153 | Syntax syntax = 5; 154 | } 155 | 156 | // Enum value definition. 157 | message EnumValue { 158 | // Enum value name. 159 | string name = 1; 160 | // Enum value number. 161 | int32 number = 2; 162 | // Protocol buffer options. 163 | repeated Option options = 3; 164 | } 165 | 166 | // A protocol buffer option, which can be attached to a message, field, 167 | // enumeration, etc. 168 | message Option { 169 | // The option's name. For protobuf built-in options (options defined in 170 | // descriptor.proto), this is the short name. For example, `"map_entry"`. 171 | // For custom options, it should be the fully-qualified name. For example, 172 | // `"google.api.http"`. 173 | string name = 1; 174 | // The option's value packed in an Any message. If the value is a primitive, 175 | // the corresponding wrapper type defined in google/protobuf/wrappers.proto 176 | // should be used. If the value is an enum, it should be stored as an int32 177 | // value using the google.protobuf.Int32Value type. 178 | Any value = 2; 179 | } 180 | 181 | // The syntax in which a protocol buffer element is defined. 182 | enum Syntax { 183 | // Syntax `proto2`. 184 | SYNTAX_PROTO2 = 0; 185 | // Syntax `proto3`. 186 | SYNTAX_PROTO3 = 1; 187 | } 188 | -------------------------------------------------------------------------------- /lamda/google/protobuf/wrappers.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | // Wrappers for primitive (non-message) types. These types are useful 32 | // for embedding primitives in the `google.protobuf.Any` type and for places 33 | // where we need to distinguish between the absence of a primitive 34 | // typed field and its default value. 35 | // 36 | // These wrappers have no meaningful use within repeated fields as they lack 37 | // the ability to detect presence on individual elements. 38 | // These wrappers have no meaningful use within a map or a oneof since 39 | // individual entries of a map or fields of a oneof can already detect presence. 40 | 41 | syntax = "proto3"; 42 | 43 | package google.protobuf; 44 | 45 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 46 | option cc_enable_arenas = true; 47 | option go_package = "google.golang.org/protobuf/types/known/wrapperspb"; 48 | option java_package = "com.google.protobuf"; 49 | option java_outer_classname = "WrappersProto"; 50 | option java_multiple_files = true; 51 | option objc_class_prefix = "GPB"; 52 | 53 | // Wrapper message for `double`. 54 | // 55 | // The JSON representation for `DoubleValue` is JSON number. 56 | message DoubleValue { 57 | // The double value. 58 | double value = 1; 59 | } 60 | 61 | // Wrapper message for `float`. 62 | // 63 | // The JSON representation for `FloatValue` is JSON number. 64 | message FloatValue { 65 | // The float value. 66 | float value = 1; 67 | } 68 | 69 | // Wrapper message for `int64`. 70 | // 71 | // The JSON representation for `Int64Value` is JSON string. 72 | message Int64Value { 73 | // The int64 value. 74 | int64 value = 1; 75 | } 76 | 77 | // Wrapper message for `uint64`. 78 | // 79 | // The JSON representation for `UInt64Value` is JSON string. 80 | message UInt64Value { 81 | // The uint64 value. 82 | uint64 value = 1; 83 | } 84 | 85 | // Wrapper message for `int32`. 86 | // 87 | // The JSON representation for `Int32Value` is JSON number. 88 | message Int32Value { 89 | // The int32 value. 90 | int32 value = 1; 91 | } 92 | 93 | // Wrapper message for `uint32`. 94 | // 95 | // The JSON representation for `UInt32Value` is JSON number. 96 | message UInt32Value { 97 | // The uint32 value. 98 | uint32 value = 1; 99 | } 100 | 101 | // Wrapper message for `bool`. 102 | // 103 | // The JSON representation for `BoolValue` is JSON `true` and `false`. 104 | message BoolValue { 105 | // The bool value. 106 | bool value = 1; 107 | } 108 | 109 | // Wrapper message for `string`. 110 | // 111 | // The JSON representation for `StringValue` is JSON string. 112 | message StringValue { 113 | // The string value. 114 | string value = 1; 115 | } 116 | 117 | // Wrapper message for `bytes`. 118 | // 119 | // The JSON representation for `BytesValue` is JSON string. 120 | message BytesValue { 121 | // The bytes value. 122 | bytes value = 1; 123 | } 124 | -------------------------------------------------------------------------------- /lamda/rpc/application.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2022 rev1si0n (lamda.devel@gmail.com). All rights reserved. 2 | // 3 | // Distributed under MIT license. 4 | // See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 5 | syntax = "proto3"; 6 | package lamda.rpc; 7 | 8 | import "google/protobuf/struct.proto"; 9 | 10 | enum GrantType { 11 | GRANT_ALLOW = 0; 12 | GRANT_DENY = 1; 13 | GRANT_IGNORE = 2; 14 | } 15 | 16 | enum DataEncode { 17 | DATA_ENCODE_NONE = 0; 18 | DATA_ENCODE_ZLIB = 1; 19 | } 20 | 21 | enum ScriptRuntime { 22 | RUNTIME_QJS = 0; 23 | RUNTIME_V8 = 1; 24 | } 25 | 26 | message ApplicationRequest { 27 | string name = 1; 28 | string permission = 2; 29 | GrantType mode = 3; 30 | string path = 4; 31 | uint32 user = 5; 32 | } 33 | 34 | message ApplicationActivityRequest { 35 | string package = 1; 36 | string action = 2; 37 | string category = 3; 38 | string component = 4; 39 | google.protobuf.Struct extras = 5; 40 | repeated string categories = 6; 41 | int64 flags = 7; 42 | bool debug = 8; 43 | string data = 9; 44 | uint32 user = 10; 45 | } 46 | 47 | message ApplicationActivityInfo { 48 | string package = 1; 49 | string action = 2; 50 | string category = 3; 51 | string component = 4; 52 | google.protobuf.Struct extras = 5; 53 | repeated string categories = 6; 54 | int64 flags = 7; 55 | bool debug = 8; 56 | string data = 9; 57 | uint32 user = 10; 58 | } 59 | 60 | message ApplicationActivityInfoList { 61 | repeated ApplicationActivityInfo activities = 1; 62 | } 63 | 64 | message ApplicationPermissions { 65 | repeated string permissions = 1; 66 | } 67 | 68 | message ApplicationInfo { 69 | string packageName = 1; 70 | uint32 uid = 2; 71 | bool enabled = 3; 72 | string processName = 4; 73 | string sourceDir = 5; 74 | string dataDir = 6; 75 | uint32 baseRevisionCode = 7; 76 | int64 firstInstallTime = 8; 77 | int64 lastUpdateTime = 9; 78 | uint32 versionCode = 10; 79 | string versionName = 11; 80 | string activity = 12; 81 | uint32 user = 13; 82 | } 83 | 84 | message ApplicationProcess { 85 | repeated string packages = 1; 86 | string processName = 2; 87 | int64 uid = 3; 88 | int64 pid = 4; 89 | } 90 | 91 | message ApplicationProcesses { 92 | repeated ApplicationProcess processes = 1; 93 | } 94 | 95 | message ApplicationPkgNames { 96 | repeated string names = 1; 97 | } 98 | 99 | message HookRequest { 100 | string package = 1; 101 | bytes script = 2; 102 | ScriptRuntime runtime = 3; 103 | string destination = 4; 104 | DataEncode encode = 5; 105 | uint32 standup = 6; 106 | bool spawn = 7; 107 | uint32 user = 8; 108 | } 109 | 110 | message HookRpcRequest { 111 | string package = 1; 112 | string callinfo = 2; 113 | uint32 user = 3; 114 | } 115 | 116 | message HookRpcResponse { 117 | string package = 1; 118 | string callresult = 2; 119 | } -------------------------------------------------------------------------------- /lamda/rpc/debug.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2022 rev1si0n (lamda.devel@gmail.com). All rights reserved. 2 | // 3 | // Distributed under MIT license. 4 | // See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 5 | syntax = "proto3"; 6 | package lamda.rpc; 7 | 8 | import "google/protobuf/struct.proto"; 9 | 10 | message ADBDConfigRequest { 11 | string adb_pubkey = 1; 12 | } -------------------------------------------------------------------------------- /lamda/rpc/file.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2022 rev1si0n (lamda.devel@gmail.com). All rights reserved. 2 | // 3 | // Distributed under MIT license. 4 | // See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 5 | syntax = "proto3"; 6 | package lamda.rpc; 7 | 8 | message FileStat { 9 | string name = 1; 10 | string path = 2; 11 | bool directory = 3; 12 | int64 st_mode = 4; 13 | int64 st_atime = 5; 14 | int64 st_mtime = 6; 15 | int64 st_ctime = 7; 16 | int32 st_uid = 8; 17 | int32 st_gid = 9; 18 | int64 st_size = 10; 19 | } 20 | 21 | message FileRequest { 22 | string path = 1; 23 | uint64 mode = 2; 24 | bytes payload = 3; 25 | } 26 | 27 | message FileDataResponse { 28 | bytes payload = 1; 29 | } 30 | -------------------------------------------------------------------------------- /lamda/rpc/policy.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2022 rev1si0n (lamda.devel@gmail.com). All rights reserved. 2 | // 3 | // Distributed under MIT license. 4 | // See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 5 | syntax = "proto3"; 6 | package lamda.rpc; 7 | 8 | message SelinuxPolicyRequest { 9 | string source = 1; 10 | string target = 2; 11 | string tclass = 3; 12 | string action = 4; 13 | } -------------------------------------------------------------------------------- /lamda/rpc/proxy.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2022 rev1si0n (lamda.devel@gmail.com). All rights reserved. 2 | // 3 | // Distributed under MIT license. 4 | // See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 5 | syntax = "proto3"; 6 | package lamda.rpc; 7 | 8 | import "application.proto"; 9 | 10 | enum GproxyType { 11 | SOCKS5 = 0; 12 | HTTP_CONNECT = 1; 13 | HTTP_RELAY = 2; 14 | } 15 | 16 | message GproxyConfigRequest { 17 | ApplicationInfo application = 1; 18 | GproxyType type = 2; 19 | string nameserver = 3; 20 | string login = 4; 21 | string password = 5; 22 | string host = 6; 23 | uint32 port = 7; 24 | bool bypass_local_subnet = 8; 25 | bool drop_udp = 9; 26 | bool udp_proxy = 10; 27 | bool dns_proxy = 11; 28 | } 29 | 30 | enum OpenVPNProto { 31 | TCP = 0; 32 | UDP = 1; 33 | } 34 | 35 | enum OpenVPNAuth { 36 | SHA1 = 0; 37 | SHA224 = 1; 38 | SHA256 = 2; 39 | SHA384 = 3; 40 | SHA512 = 4; 41 | RIPEMD160 = 5; 42 | RSA_SHA1 = 6; 43 | RSA_SHA224 = 7; 44 | RSA_SHA256 = 8; 45 | RSA_SHA384 = 9; 46 | RSA_SHA512 = 10; 47 | RSA_RIPEMD160 = 11; 48 | } 49 | 50 | enum OpenVPNCipher { 51 | AES_128_GCM = 0; 52 | AES_256_GCM = 1; 53 | CHACHA20_POLY1305= 2; 54 | AES_128_CBC = 3; 55 | AES_256_CBC = 4; 56 | } 57 | 58 | enum OpenVPNKeyDirection { 59 | // because 0 is a default value 60 | // so we use 1 as key-direction 0 61 | KEY_DIRECTION_NONE = 0; 62 | KEY_DIRECTION_0 = 1; 63 | KEY_DIRECTION_1 = 2; 64 | } 65 | 66 | enum OpenVPNEncryption { 67 | TLS_NONE = 0; 68 | TLS_AUTH = 1; 69 | TLS_CRYPT = 2; 70 | TLS_CRYPT_V2 = 3; 71 | } 72 | 73 | message OpenVPNConfigRequest { 74 | bool all_traffic = 1; 75 | OpenVPNProto proto = 2; 76 | string host = 3; 77 | uint32 port = 4; 78 | OpenVPNCipher cipher = 5; 79 | string ca = 6; 80 | string cert = 7; 81 | string key = 8; 82 | OpenVPNEncryption tls_encryption = 9; 83 | OpenVPNKeyDirection tls_key_direction = 10; 84 | string tls_key = 11; 85 | OpenVPNAuth auth = 12; 86 | string login = 13; 87 | string password = 14; 88 | } 89 | -------------------------------------------------------------------------------- /lamda/rpc/services.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2022 rev1si0n (lamda.devel@gmail.com). All rights reserved. 2 | // 3 | // Distributed under MIT license. 4 | // See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 5 | syntax = "proto3"; 6 | package lamda.rpc; 7 | 8 | import public "google/protobuf/empty.proto"; 9 | import public "google/protobuf/any.proto"; 10 | 11 | import public "types.proto"; 12 | 13 | import public "util.proto"; 14 | import public "shell.proto"; 15 | import public "policy.proto"; 16 | import public "debug.proto"; 17 | import public "settings.proto"; 18 | import public "status.proto"; 19 | import public "application.proto"; 20 | import public "uiautomator.proto"; 21 | import public "storage.proto"; 22 | import public "proxy.proto"; 23 | import public "file.proto"; 24 | import public "wifi.proto"; 25 | 26 | 27 | service Application { 28 | rpc isForeground(ApplicationRequest) returns (Boolean) {} 29 | rpc currentApplication(google.protobuf.Empty) returns (ApplicationInfo) {} 30 | rpc enumerateAllPkgNames(google.protobuf.Empty) returns (ApplicationPkgNames) {} 31 | rpc enumerateRunningProcesses(google.protobuf.Empty) returns (ApplicationProcesses) {} 32 | rpc queryLaunchActivity(ApplicationRequest) returns (ApplicationActivityInfo) {} 33 | rpc getPermissions(ApplicationRequest) returns (ApplicationPermissions) {} 34 | rpc resetApplicationData(ApplicationRequest) returns (Boolean) {} 35 | rpc deleteApplicationCache(ApplicationRequest) returns (Boolean) {} 36 | rpc getLastActivities(Integer) returns (ApplicationActivityInfoList) {} 37 | rpc startActivity(ApplicationActivityRequest) returns (Boolean) {} 38 | rpc applicationInfo(ApplicationRequest) returns (ApplicationInfo) {} 39 | rpc startApplication(ApplicationRequest) returns (Boolean) {} 40 | rpc stopApplication(ApplicationRequest) returns (Boolean) {} 41 | rpc uninstallApplication(ApplicationRequest) returns (Boolean) {} 42 | rpc installFromLocalFile(ApplicationRequest) returns (ApplicationInfo) {} 43 | rpc enableApplication(ApplicationRequest) returns (Boolean) {} 44 | rpc disableApplication(ApplicationRequest) returns (Boolean) {} 45 | rpc grantPermission(ApplicationRequest) returns (Boolean) {} 46 | rpc revokePermission(ApplicationRequest) returns (Boolean) {} 47 | rpc isPermissionGranted(ApplicationRequest) returns (Boolean) {} 48 | rpc isInstalled(ApplicationRequest) returns (Boolean) {} 49 | 50 | rpc addToDozeModeWhiteList(ApplicationRequest) returns (Boolean) {} 51 | rpc removeFromDozeModeWhiteList(ApplicationRequest) returns (Boolean) {} 52 | rpc getIdentifierByLabel(String) returns (String) {} 53 | 54 | rpc callScript(HookRpcRequest) returns (HookRpcResponse) {} 55 | rpc isScriptAlive(HookRequest) returns (Boolean) {} 56 | rpc isScriptAttached(HookRequest) returns (Boolean) {} 57 | rpc attachScript(HookRequest) returns (Boolean) {} 58 | rpc detachScript(HookRequest) returns (Boolean) {} 59 | } 60 | 61 | service Debug { 62 | rpc isAndroidDebugBridgeRunning(google.protobuf.Empty) returns (Boolean) {} 63 | 64 | rpc installADBPubKey(ADBDConfigRequest) returns (Boolean) {} 65 | rpc uninstallADBPubKey(ADBDConfigRequest) returns (Boolean) {} 66 | 67 | rpc startAndroidDebugBridge(google.protobuf.Empty) returns (Boolean) {} 68 | rpc stopAndroidDebugBridge(google.protobuf.Empty) returns (Boolean) {} 69 | } 70 | 71 | service Proxy { 72 | rpc isOpenVPNRunning(google.protobuf.Empty) returns (Boolean) {} 73 | rpc isGproxyRunning(google.protobuf.Empty) returns (Boolean) {} 74 | rpc stopOpenVPN(google.protobuf.Empty) returns (Boolean) {} 75 | rpc stopGproxy(google.protobuf.Empty) returns (Boolean) {} 76 | rpc startOpenVPN(OpenVPNConfigRequest) returns (Boolean) {} 77 | rpc startGproxy(GproxyConfigRequest) returns (Boolean) {} 78 | } 79 | 80 | service SelinuxPolicy { 81 | rpc setEnforce(Boolean) returns (Integer) {} 82 | rpc getEnforce(google.protobuf.Empty) returns (Integer) {} 83 | rpc isEnabled(google.protobuf.Empty) returns (Boolean) {} 84 | 85 | rpc policySetEnforce(String) returns (Boolean) {} 86 | rpc policySetPermissive(String) returns (Boolean) {} 87 | rpc policySetAllow(SelinuxPolicyRequest) returns (Boolean) {} 88 | rpc policySetDisallow(SelinuxPolicyRequest) returns (Boolean) {} 89 | rpc policyCreateDomain(String) returns (Boolean) {} 90 | } 91 | 92 | service Settings { 93 | rpc putSettings(SettingsRequest) returns (Boolean) {} 94 | rpc getSettings(SettingsRequest) returns (String) {} 95 | } 96 | 97 | service Shell { 98 | rpc executeForeground(ShellRequest) returns (ShellResult) {} 99 | rpc executeBackground(ShellRequest) returns (ShellTask) {} 100 | rpc isBackgroundFinished(ShellTask) returns (Boolean) {} 101 | rpc killBackground(ShellTask) returns (Boolean) {} 102 | } 103 | 104 | service Status { 105 | rpc getBootTime(google.protobuf.Empty) returns (Integer) {} 106 | rpc getDiskUsage(String) returns (DiskUsage) {} 107 | rpc getBatteryInfo(google.protobuf.Empty) returns (BatteryInfo) {} 108 | rpc getCpuInfo(google.protobuf.Empty) returns (CpuInfo) {} 109 | rpc getOverallDiskIOInfo(google.protobuf.Empty) returns (DiskIOInfo) {} 110 | rpc getOverallNetIOInfo(google.protobuf.Empty) returns (NetIOInfo) {} 111 | rpc getMemInfo(google.protobuf.Empty) returns (MemInfo) {} 112 | rpc getUserDataDiskIOInfo(google.protobuf.Empty) returns (DiskIOInfo) {} 113 | rpc getNetIOInfo(String) returns (NetIOInfo) {} 114 | } 115 | 116 | service UiAutomator { 117 | rpc click(ClickPointRequest) returns (Boolean) {} 118 | rpc drag(DragPointRequest) returns (Boolean) {} 119 | rpc swipe(SwipePointRequest) returns (Boolean) {} 120 | rpc swipePoints(SwipePointsRequest) returns (Boolean) {} 121 | rpc openNotification(google.protobuf.Empty) returns (Boolean) {} 122 | rpc openQuickSettings(google.protobuf.Empty) returns (Boolean) {} 123 | rpc wakeUp(google.protobuf.Empty) returns (Boolean) {} 124 | rpc sleep(google.protobuf.Empty) returns (Boolean) {} 125 | rpc isScreenOn(google.protobuf.Empty) returns (Boolean) {} 126 | rpc isScreenLocked(google.protobuf.Empty) returns (Boolean) {} 127 | rpc setClipboard(ClipboardRequest) returns (Boolean) {} 128 | rpc getClipboard(google.protobuf.Empty) returns (String) {} 129 | rpc freezeRotation(Boolean) returns (Boolean) {} 130 | rpc setOrientation(OrientationRequest) returns (Boolean) {} 131 | rpc pressKey(PressKeyRequest) returns (Boolean) {} 132 | rpc pressKeyCode(PressKeyRequest) returns (Boolean) {} 133 | 134 | rpc deviceInfo(google.protobuf.Empty) returns (DeviceInfo) {} 135 | 136 | rpc takeScreenshot(TakeScreenshotRequest) returns (Bytes) {} 137 | rpc dumpWindowHierarchy(Boolean) returns (Bytes) {} 138 | rpc waitForIdle(Integer) returns (Boolean) {} 139 | 140 | rpc selectorTakeScreenshot(SelectorTakeScreenshotRequest) returns (Bytes) {} 141 | 142 | rpc selectorGetText(SelectorOnlyRequest) returns (String) {} 143 | rpc selectorClearTextField(SelectorOnlyRequest) returns (Boolean) {} 144 | rpc selectorSetText(SelectorSetTextRequest) returns (Boolean) {} 145 | 146 | rpc selectorClick(SelectorClickRequest) returns (Boolean) {} 147 | rpc selectorClickExists(SelectorClickRequest) returns (Boolean) {} 148 | rpc selectorLongClick(SelectorClickRequest) returns (Boolean) {} 149 | 150 | rpc selectorExists(SelectorOnlyRequest) returns (Boolean) {} 151 | rpc getLastToast(google.protobuf.Empty) returns (ToastInfo) {} 152 | 153 | rpc selectorObjInfo(SelectorOnlyRequest) returns (ObjInfo) {} 154 | rpc selectorObjInfoOfAllInstances(SelectorOnlyRequest) returns (ObjInfoList) {} 155 | rpc selectorCount(SelectorOnlyRequest) returns (Integer) {} 156 | 157 | rpc selectorDragTo(SelectorDragToRequest) returns (Boolean) {} 158 | 159 | rpc selectorWaitForExists(SelectorWaitRequest) returns (Boolean) {} 160 | rpc selectorWaitUntilGone(SelectorWaitRequest) returns (Boolean) {} 161 | rpc selectorSwipe(SelectorSwipeRequest) returns (Boolean) {} 162 | 163 | rpc selectorFlingToBeginning(SelectorFlingRequest) returns (Boolean) {} 164 | rpc selectorFlingToEnd(SelectorFlingRequest) returns (Boolean) {} 165 | rpc selectorFlingBackward(SelectorFlingRequest) returns (Boolean) {} 166 | rpc selectorFlingForward(SelectorFlingRequest) returns (Boolean) {} 167 | 168 | rpc selectorScrollToBeginning(SelectorScrollRequest) returns (Boolean) {} 169 | rpc selectorScrollToEnd(SelectorScrollRequest) returns (Boolean) {} 170 | rpc selectorScrollBackward(SelectorScrollRequest) returns (Boolean) {} 171 | rpc selectorScrollForward(SelectorScrollRequest) returns (Boolean) {} 172 | rpc selectorScrollTo(SelectorScrollRequest) returns (Boolean) {} 173 | 174 | rpc selectorPinchOut(SelectorPinchRequest) returns (Boolean) {} 175 | rpc selectorPinchIn(SelectorPinchRequest) returns (Boolean) {} 176 | 177 | rpc setWatcherLoopEnabled(Boolean) returns (Boolean) {} 178 | rpc getWatcherLoopEnabled(google.protobuf.Empty) returns (Boolean) {} 179 | rpc getWatcherTriggeredCount(String) returns (Integer) {} 180 | rpc resetWatcherTriggeredCount(String) returns (Boolean) {} 181 | 182 | rpc removeWatcher(String) returns (Boolean) {} 183 | rpc getAppliedWatchers(google.protobuf.Empty) returns (WatcherNameList) {} 184 | 185 | rpc registerClickUiObjectWatcher(WatcherRegistRequest) returns (Boolean) {} 186 | rpc registerPressKeysWatcher(WatcherRegistRequest) returns (Boolean) {} 187 | rpc registerNoneOpWatcher(WatcherRegistRequest) returns (Boolean) {} 188 | rpc findSimilarImage(FindImageRequest) returns (FindImageResponse) {} 189 | } 190 | 191 | service Wifi { 192 | rpc status(google.protobuf.Empty) returns (WifiStatus) {} 193 | rpc blacklistAdd(String) returns (Boolean) {} 194 | rpc blacklistClear(google.protobuf.Empty) returns (Boolean) {} 195 | rpc blacklistAll(google.protobuf.Empty) returns (WifiBlacklist) {} 196 | rpc scan(Boolean) returns (Boolean) {} 197 | rpc scanResults(google.protobuf.Empty) returns (ScanResult) {} 198 | rpc listNetworks(google.protobuf.Empty) returns (NetworkList) {} 199 | rpc selectNetwork(Network) returns (Boolean) {} 200 | rpc enableNetwork(Network) returns (Boolean) {} 201 | rpc disableNetwork(Network) returns (Boolean) {} 202 | rpc addNetwork(google.protobuf.Empty) returns (Network) {} 203 | rpc removeNetwork(Network) returns (Boolean) {} 204 | rpc setNetworkConfig(NetworkConfig) returns (Boolean) {} 205 | rpc getNetworkConfig(NetworkConfig) returns (NetworkConfig) {} 206 | rpc disconnect(google.protobuf.Empty) returns (Boolean) {} 207 | rpc reconnect(google.protobuf.Empty) returns (Boolean) {} 208 | rpc setConfig(WifiConfig) returns (Boolean) {} 209 | rpc setAutoConnect(Boolean) returns (Boolean) {} 210 | rpc saveConfig(google.protobuf.Empty) returns (Boolean) {} 211 | rpc getMacAddr(google.protobuf.Empty) returns (String) {} 212 | rpc signalPoll(google.protobuf.Empty) returns (SignalPoll) {} 213 | } 214 | 215 | service Util { 216 | rpc recordTouch(google.protobuf.Empty) returns (TouchSequence) {} 217 | rpc performTouch(PerformTouchRequest) returns (Boolean) {} 218 | 219 | rpc serverInfo(google.protobuf.Empty) returns (ServerInfoResponse) {} 220 | 221 | rpc reboot(google.protobuf.Empty) returns (Boolean) {} 222 | rpc beepBeep(google.protobuf.Empty) returns (Boolean) {} 223 | rpc isCACertificateInstalled(CertifiRequest) returns (Boolean) {} 224 | rpc installCACertificate(CertifiRequest) returns (Boolean) {} 225 | rpc uninstallCACertificate(CertifiRequest) returns (Boolean) {} 226 | rpc shutdown(google.protobuf.Empty) returns (Boolean) {} 227 | rpc showToast(ShowToastRequest) returns (Boolean) {} 228 | rpc reload(Boolean) returns (Boolean) {} 229 | rpc exit(google.protobuf.Empty) returns (Boolean) {} 230 | rpc setProp(SetPropRequest) returns (Boolean) {} 231 | rpc getProp(String) returns (String) {} 232 | rpc hexPatch(HexPatchRequest) returns (HexPatchResponse) {} 233 | } 234 | 235 | service File { 236 | rpc uploadFile(stream FileRequest) returns (FileStat) {} 237 | rpc downloadFile(FileRequest) returns (stream FileDataResponse) {} 238 | rpc deleteFile(FileRequest) returns (Boolean) {} 239 | rpc fileChmod(FileRequest) returns (FileStat) {} 240 | rpc fileStat(FileRequest) returns (FileStat) {} 241 | } 242 | 243 | service Lock { 244 | rpc releaseLock(google.protobuf.Empty) returns (Boolean) {} 245 | rpc getSessionToken(google.protobuf.Empty) returns (String) {} 246 | rpc acquireLock(Integer) returns (Boolean) {} 247 | rpc refreshLock(Integer) returns (Boolean) {} 248 | } 249 | 250 | service Storage { 251 | rpc clearAll(StorageRequest) returns (Boolean) {} 252 | rpc clearContainer(StorageRequest) returns (Boolean) {} 253 | rpc exists(StorageRequest) returns (Boolean) {} 254 | rpc delete(StorageRequest) returns (Boolean) {} 255 | rpc expire(StorageRequest) returns (Boolean) {} 256 | rpc ttl(StorageRequest) returns (Integer) {} 257 | rpc set(StorageRequest) returns (Boolean) {} 258 | rpc setnx(StorageRequest) returns (Boolean) {} 259 | rpc setex(StorageRequest) returns (Boolean) {} 260 | rpc get(StorageRequest) returns (Bytes) {} 261 | } -------------------------------------------------------------------------------- /lamda/rpc/settings.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2022 rev1si0n (lamda.devel@gmail.com). All rights reserved. 2 | // 3 | // Distributed under MIT license. 4 | // See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 5 | syntax = "proto3"; 6 | package lamda.rpc; 7 | 8 | enum Group { 9 | GROUP_SYSTEM = 0; 10 | GROUP_SECURE = 1; 11 | GROUP_GLOBAL = 2; 12 | } 13 | 14 | message SettingsRequest { 15 | Group group = 1; 16 | string name = 2; 17 | string value = 3; 18 | } 19 | -------------------------------------------------------------------------------- /lamda/rpc/shell.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2022 rev1si0n (lamda.devel@gmail.com). All rights reserved. 2 | // 3 | // Distributed under MIT license. 4 | // See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 5 | syntax = "proto3"; 6 | package lamda.rpc; 7 | 8 | message ShellRequest { 9 | string tid = 1; 10 | string name = 2; 11 | string script = 3; 12 | int32 timeout = 4; 13 | } 14 | 15 | message ShellResult { 16 | int32 exitstatus = 1; 17 | bytes stdout = 2; 18 | bytes stderr = 3; 19 | } 20 | 21 | message ShellTask { 22 | string tid = 1; 23 | string name = 2; 24 | int32 pid = 3; 25 | } -------------------------------------------------------------------------------- /lamda/rpc/status.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2022 rev1si0n (lamda.devel@gmail.com). All rights reserved. 2 | // 3 | // Distributed under MIT license. 4 | // See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 5 | syntax = "proto3"; 6 | package lamda.rpc; 7 | 8 | message BatteryInfo { 9 | bool batt_charging = 1; 10 | int32 batt_percent = 2; 11 | float batt_temperature = 3; 12 | } 13 | 14 | message CpuInfo { 15 | float cpu_percent = 1; 16 | int32 cpu_count = 2; 17 | float cpu_freq_current = 3; 18 | float cpu_freq_max = 4; 19 | float cpu_freq_min = 5; 20 | float cpu_times_user = 6; 21 | float cpu_times_system = 7; 22 | float cpu_times_idle = 8; 23 | } 24 | 25 | message DiskUsage { 26 | int64 disk_total = 1; 27 | int64 disk_used = 2; 28 | int64 disk_free = 3; 29 | float disk_percent = 4; 30 | } 31 | 32 | message DiskIOInfo { 33 | int64 disk_io_read_bytes = 1; 34 | int64 disk_io_read_count = 2; 35 | int64 disk_io_write_bytes = 3; 36 | int64 disk_io_write_count = 4; 37 | int64 disk_io_read_time = 5; 38 | int64 disk_io_write_time = 6; 39 | int64 disk_io_busy_time = 7; 40 | } 41 | 42 | message NetIOInfo { 43 | int64 net_io_bytes_sent = 1; 44 | int64 net_io_packets_sent = 2; 45 | int64 net_io_bytes_recv = 3; 46 | int64 net_io_packets_recv = 4; 47 | int64 net_io_dropin = 5; 48 | int64 net_io_dropout = 6; 49 | int64 net_io_errin = 7; 50 | int64 net_io_errout = 8; 51 | } 52 | 53 | message MemInfo { 54 | int64 mem_total = 1; 55 | int64 mem_available = 2; 56 | float mem_percent = 3; 57 | int64 mem_used = 4; 58 | int64 mem_free = 5; 59 | int64 mem_active = 6; 60 | int64 mem_inactive = 7; 61 | int64 mem_buffers = 8; 62 | int64 mem_cached = 9; 63 | int64 mem_shared = 10; 64 | int64 mem_slab = 11; 65 | } 66 | -------------------------------------------------------------------------------- /lamda/rpc/storage.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2022 rev1si0n (lamda.devel@gmail.com). All rights reserved. 2 | // 3 | // Distributed under MIT license. 4 | // See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 5 | syntax = "proto3"; 6 | package lamda.rpc; 7 | 8 | message StorageRequest { 9 | string container = 1; 10 | string key = 2; 11 | bytes value = 3; 12 | uint32 ttl = 4; 13 | } -------------------------------------------------------------------------------- /lamda/rpc/types.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2022 rev1si0n (lamda.devel@gmail.com). All rights reserved. 2 | // 3 | // Distributed under MIT license. 4 | // See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 5 | syntax = "proto3"; 6 | package lamda.rpc; 7 | 8 | message Boolean { 9 | bool value = 1; 10 | } 11 | 12 | message Integer { 13 | int64 value = 1; 14 | } 15 | 16 | message String { 17 | string value = 1; 18 | } 19 | 20 | message Bytes { 21 | bytes value = 1; 22 | } 23 | 24 | message Empty { 25 | } 26 | -------------------------------------------------------------------------------- /lamda/rpc/util.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2022 rev1si0n (lamda.devel@gmail.com). All rights reserved. 2 | // 3 | // Distributed under MIT license. 4 | // See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 5 | syntax = "proto3"; 6 | package lamda.rpc; 7 | 8 | enum ToastDuration { 9 | TD_SHORT = 0; 10 | TD_LONG = 1; 11 | } 12 | 13 | message TouchDown { 14 | int32 tid = 1; 15 | int32 x = 2; 16 | int32 y = 3; 17 | int32 pressure = 4; 18 | } 19 | 20 | message TouchUp { 21 | int32 tid = 1; 22 | } 23 | 24 | message TouchMove { 25 | int32 tid = 1; 26 | int32 x = 2; 27 | int32 y = 3; 28 | int32 pressure = 4; 29 | } 30 | 31 | message TouchWait { 32 | uint32 wait = 1; 33 | } 34 | 35 | message TouchAction { 36 | oneof action { 37 | TouchDown down = 1; 38 | TouchMove move = 2; 39 | TouchWait wait = 3; 40 | TouchUp up = 4; 41 | } 42 | } 43 | 44 | message TouchSequence { 45 | repeated TouchAction sequence = 1; 46 | } 47 | 48 | message PerformTouchRequest { 49 | TouchSequence sequence = 1; 50 | bool wait = 2; 51 | } 52 | 53 | message SetPropRequest { 54 | string name = 1; 55 | string value = 2; 56 | } 57 | 58 | message CertifiRequest { 59 | bytes cert = 1; 60 | } 61 | 62 | message ShowToastRequest { 63 | string text = 1; 64 | ToastDuration duration = 2; 65 | } 66 | 67 | message ServerInfoResponse { 68 | string uniqueId = 1; 69 | string version = 2; 70 | string architecture = 3; 71 | uint64 uptime = 4; 72 | bool secure = 5; 73 | } 74 | 75 | message HexPatchRequest { 76 | string pattern = 1; 77 | string replacement = 2; 78 | string path = 3; 79 | int32 maxreplace = 4; 80 | bool dryrun = 5; 81 | } 82 | 83 | message HexPatchItem { 84 | string path = 1; 85 | int32 index = 2; 86 | uint64 offset = 3; 87 | } 88 | 89 | message HexPatchResponse { 90 | int32 count = 1; 91 | repeated HexPatchItem replaces = 2; 92 | } -------------------------------------------------------------------------------- /lamda/rpc/wifi.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2022 rev1si0n (lamda.devel@gmail.com). All rights reserved. 2 | // 3 | // Distributed under MIT license. 4 | // See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 5 | syntax = "proto3"; 6 | package lamda.rpc; 7 | 8 | message WifiStatus { 9 | string id = 1; 10 | string address = 2; 11 | string bssid = 3; 12 | string freq = 4; 13 | string group_cipher = 5; 14 | string ip_address = 6; 15 | string key_mgmt = 7; 16 | string mode = 8; 17 | string pairwise_cipher = 9; 18 | string ssid = 10; 19 | string wifi_generation = 11; 20 | string wpa_state = 12; 21 | } 22 | 23 | message SignalPoll { 24 | string RSSI = 1; 25 | string LINKSPEED = 2; 26 | string NOISE = 3; 27 | string FREQUENCY = 4; 28 | string WIDTH = 5; 29 | string AVG_RSSI = 6; 30 | string AVG_BEACON_RSSI = 7; 31 | string CENTER_FRQ1 = 8; 32 | } 33 | 34 | message WifiInfo { 35 | string id = 1; 36 | string bssid = 2; 37 | string ssid = 3; 38 | string freq = 4; 39 | string noise = 5; 40 | string level = 6; 41 | string tsf = 7; 42 | string flags = 8; 43 | } 44 | 45 | message ScanResult { 46 | repeated WifiInfo stations = 1; 47 | } 48 | 49 | message Network { 50 | int32 nid = 1; 51 | string bssid = 2; 52 | string ssid = 3; 53 | string flags = 4; 54 | } 55 | 56 | message NetworkList { 57 | repeated Network networks = 1; 58 | } 59 | 60 | message NetworkConfig { 61 | Network network = 1; 62 | string name = 2; 63 | string value = 3; 64 | } 65 | 66 | message WifiConfig { 67 | string name = 1; 68 | string value = 2; 69 | } 70 | 71 | message WifiBlacklist { 72 | repeated string bssids = 1; 73 | } -------------------------------------------------------------------------------- /lamda/types.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 rev1si0n (lamda.devel@gmail.com). All rights reserved. 2 | # 3 | # Distributed under MIT license. 4 | # See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 5 | import io 6 | import codecs 7 | 8 | __all__ = ["AttributeDict", "BytesIO"] 9 | 10 | 11 | class AttributeDict(dict): 12 | def __getattr__(self, attr): 13 | return self[attr] 14 | def __setattr__(self, attr, value): 15 | self[attr] = value 16 | def remove(self, key): 17 | key in self and self.pop(key) 18 | 19 | 20 | class BytesIO(io.BytesIO): 21 | @classmethod 22 | def decode_from(cls, data, encoding): 23 | return cls(codecs.decode(data, encoding)) 24 | def encode(self, encoding): 25 | return codecs.encode(self.getvalue(), encoding) 26 | def decode(self, encoding): 27 | return codecs.decode(self.getvalue(), encoding) 28 | def save(self, fpath): 29 | with open(fpath, "wb") as fd: 30 | return fd.write(self.getvalue()) 31 | @classmethod 32 | def load(cls, fpath): 33 | with open(fpath, "rb") as fd: 34 | return cls(fd.read()) 35 | -------------------------------------------------------------------------------- /properties.local.example: -------------------------------------------------------------------------------- 1 | # properties.local configuration file 2 | # 3 | # DO NOT DIRECTLY COPY THIS FILE, PLEASE SELECT THE NECESSARY CONFIGURATION LINES TO CREATE A NEW FILE 4 | # 5 | # This file is the LAMDA service configuration file. You can use 6 | # it to automatically start some services when LAMDA starts. 7 | # The file should be located in /data or /data/usr (this directory 8 | # will not exist before the first startup, please create it if it does not exist). 9 | # Lines starting with # and ; are comment lines and will be ignored. 10 | # Please ensure that each line follows the format a=b and does not contain spaces. 11 | # If there are duplicate configuration items across multiple files, 12 | # the last duplicate will be used. 13 | 14 | # Set the default listening port for LAMDA. 15 | port=65000 16 | 17 | # You can change the name displayed on the remote desktop for 18 | # LAMDA to any name you prefer (up to 10 characters). 19 | brandname=FIRERPA 20 | 21 | # Set the LAMDA certificate. It will encrypt your remote desktop 22 | # and API traffic, and enable password authentication. You can obtain 23 | # the following configuration value by running 'base64 -w0 lamda.pem'. 24 | # It is the base64-encoded certificate. 25 | cert=TEFNREEgU1NMIENFUlRJRklDQVRFIChDTj10ZXN0LFBBU1NXRD1hMWMwZTNlYTcwN2E1NGRlN2EwZjk1KQotLS0tLUJFR0lOIFBSSVZBVEUgS0VZLS0tLS0KTUlJRXZnSUJBREFOQmdrcWhraUc5dzBCQVFFRkFBU0NCS2d3Z2dTa0FnRUFBb0lCQVFEVmNMWlA5b0xRWkRIRgp5V0pTa2U0Z0crSUpmSCtMWlk0cXUzdS9OckRwSHZCN2k5V01rMWxRL2FMSGI0V3ZqelBLK1RITm9rRzc2MENRClhBTUpWS0dmYXRwcmNLUXdvMGhvWDZ2NlhsTVlZUlNRbW9wN3pSaUtnN3ZxKzV2S09DQ2RKcDFlSVNiZXcyTEgKTmYxL3JZelpwa1Q1bHoxTGZkem00eXJBS3VNa0tyZ3pnTzJRcE9CQVdYdmdiWG9BMDdidDdOODZZOGdNZFUwdAp6Ui9EcmhLTi9JMVdYSk11MU4wQW5UbDJRdEhEb0dCN0UyS0xpdmwybDZJdnRrYWJ4RE55Y2lHbUxOUGlMRklrCllPSHlnMUg3MUJ2NU04NE5TWDc1c2xuOXVNUGUzOVNFVlJoU0ptNHcvT2tXZnA5dGpZRUx3dHphdFhoSWJoS3MKaC9OZU1lOWRBZ01CQUFFQ2dnRUFCYlFuWUdlcFdKYjAydURtSnhLNGx2OFNhL0o1dzJpSldMYjk0dW1SUExRKwpTa1E5c1Zpc0JiQU1JNHc2dWFyNEFBVTh3WGxaTndPekMvM2V6dWNHRXFreEFReXM0VDB4SXRPUkF2WExxVlowCkl1WnpxNW53Si9OeFFzeEtmaWhBZkRLYlRmZjdmcG5MWlV0dlpNbG5LWUhQVExtRlFua3drckwyRE5YdDVVOTYKYXJUUDVOY0x1aDQ2dU93alJUOWhaNytYQi9ubU9LeTV4V3hoNWVMQmJJUTJrS0UvdWViUlVYRGZNdG5tbTh2aApRSG9VM3N5dzlZcE1xRDlWQWppcGlqQXRwbUlwa2w1emRWSE52Q1dCSGk2NjZxKzF6cUpHeFVUODBseHo1N2R1ClRvRFFQc1l0OFFEL3ZjNGkxajd0bDZyRzNQWkJNM05LNVR5ZFYyRnlnUUtCZ1FEYUcycnV3aWxyYUdZRzZNQWwKNEF2WW1BY0hHQWUwQjR0ZmtkdS9QandlRWQyWUF2TjJIQWV1Z1ZUSWg1eFplUlIwNFE4ZVNGenBTaEpwREpkNAp1TEhHcXJ2cmpXL1greEVIc081NnNjNjRiem1weWJWQXBlQnA4NlFGSTk4V3FmZkFyN3FzbzhweFJjNmdTRU1uCk5TcXV1Z2psYU05TlJmcUo4ci82RklmQkxRS0JnUUQ2aGJ0Z2dIdVJoTHhHYWNNaERvOVppcXJlNi9HN1dvZnQKR2FGZmFQM2xZNTNmM0hPdSsyNTZMWDY1ZWFYRTdrbXlQOGRDM2VWL24xT3dvTHdBYm1BZ2pEWVd1N09KdGk4QQpPbG9VNmtnTkVwNWcwOHpVWlBaR3NSMkZMd2VpUkgrQ3ZOdFBZakJydmFIQUtVU2lLa3BKdEpWeFpIdUl6SlpGCjVUZkM2VjNrOFFLQmdEeWp0TlpPKzA4V2hvOVROT0VTNnBnOHBHK1BlY3pPOEN3UkZJU1dYQWFNTnd6bGZTVVEKWS81YmpPUDMrRHRVRTZEdlZkRzRrc1IxeUtxV1NxTFF6dlNLVVpjTEN0YUV3bFplRmQvZEFibDdpdyt1dWdzUQpVMVdCM005bENzaDFWeUdtZWdNM3dyZzlqVlk0NFJyTWlHSnQ3TDFEcDZjM1ZwSDJBUFFac3lpOUFvR0JBTk9pCmpmeWtEYitNNXBDRllEWlkybmpHVURzcUQzZzZyb0Y2R1gxRWNOaU1JeDZ1V1h3RkkvdEsyN2RNTU9JQWUzbDkKcjVPcGFPczdhYlBZMVhsM3hQVTUvYWVPd2NrZ2d1d3FYMWN6NDlKSFhFeG9JSzE4N1NBakY5RWZQYyt6RmhVWAovaDA5MGJIeTdPWXM5cklZRDlIY0lETStzNjJKUjVtY1hsTG1Xay9CQW9HQkFKRVhQV05IWEwra1l6My91R1c3CnRKd0hUQzFlbEJjclcvaHpJMWt4ZEhXem5VaXNTWlcyVnA5b0wwSWNrQXVWQkx6eGUvR1h6OGJRTjZkOWwyZDAKdGtmUmo1TmpDOTUzS2N1cTNSekRmVU40cTcyUlVWTWlFOHVvSTBkVVZpalczN0tVMEhLcm1pbDBocU01eW9iNQpVZlhPQ2Q5SlRRSWx5Y2dNWER6Tm00S3oKLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0KTUlJQ3FEQ0NBWkNnQXdJQkFnSVJBUHNjMVBRNXBuSDNhNk1GZkdVTXA2WXdEUVlKS29aSWh2Y05BUUVMQlFBdwpFREVPTUF3R0ExVUVDZ3dGVEVGTlJFRXdIaGNOTWpBd01UQXhNREF3TURBeFdoY05Namt4TWpJNU1EQXdNREF4CldqQVBNUTB3Q3dZRFZRUUREQVIwWlhOME1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0MKQVFFQTFYQzJUL2FDMEdReHhjbGlVcEh1SUJ2aUNYeC9pMldPS3J0N3Z6YXc2Ujd3ZTR2VmpKTlpVUDJpeDIrRgpyNDh6eXZreHphSkJ1K3RBa0Z3RENWU2huMnJhYTNDa01LTklhRityK2w1VEdHRVVrSnFLZTgwWWlvTzc2dnViCnlqZ2duU2FkWGlFbTNzTml4elg5ZjYyTTJhWkUrWmM5UzMzYzV1TXF3Q3JqSkNxNE00RHRrS1RnUUZsNzRHMTYKQU5PMjdlemZPbVBJREhWTkxjMGZ3NjRTamZ5TlZseVRMdFRkQUowNWRrTFJ3NkJnZXhOaWk0cjVkcGVpTDdaRwptOFF6Y25JaHBpelQ0aXhTSkdEaDhvTlIrOVFiK1RQT0RVbCsrYkpaL2JqRDN0L1VoRlVZVWladU1QenBGbjZmCmJZMkJDOExjMnJWNFNHNFNySWZ6WGpIdlhRSURBUUFCTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFBWEQ0L1cKQjBhSW1aWGpQbTRxUnBOazJmUnpjU1g4MGw2TlZaWWxJV3ZYalFxUXdXZnMvSGczZDVzYUpickFmcWVPa1lQdQpjeXJEWFZPdC9RTEVDOTFBSGtjRWJ1R0dPMGNFU2YyOHdUM1UzRnJJb2cxS1VyTURqWFFIb09vZEJpOGdNaVBmCmROcWhMSTdkNDJBTXJKU3dZUTlSUG9vWG9UZ2xDa0d3R291RDhuS0V5MmNHeVMxM3lQcDRseC9TWTR1QkRFU0sKRlErR0ZRTExGQktQZHZNc2x0cHYyQWFMWmR3clF4aFQ2aTU1U1puNStLb3c1TGxYL0RHdUw5UnRPdmZ2T0tzZQpRZ3pOQUg3QkYzbGdvQmJjYk9yZkVQazY1ZEZRN0NXYi91aDZjVmlmSjdxQzkvL0xhdElmb1VQVnJiRXdZL2dRCk5BRXFYclduMGZuYUc0cUEKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0KTUlJQ2xEQ0NBWHdDQVFBd0RRWUpLb1pJaHZjTkFRRUxCUUF3RURFT01Bd0dBMVVFQ2d3RlRFRk5SRUV3SGhjTgpNakF3TVRBeE1EQXdNREF4V2hjTk1qa3hNakk1TURBd01EQXhXakFRTVE0d0RBWURWUVFLREFWTVFVMUVRVENDCkFTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTG5xZkJadnJHWmFxZ2s1bXNDUlJwUHoKcC8rNDY0akJrbmxtVEtldE9ja0RUVXE4VjZmSC8yR2ZiNkhqam9ENXBrQ3RENW1TS2thSE5odXhMWHNGZkVmYwpLbG1ubjNacGp5Tk9IRUEvaUFPMkR5RVlhMDh4U2V2TTdXb2piRjdjTmo1L0RZZzdlYjBpMCsvL2JCbGg4bmxPCmdoU1VoQ1RNNVBDb2ZMRFU4c1ZYdVlBaUdVNlV6QnJJQzB2SEVsdERraUpWTHBjQ3RzS2pFWk9za1BkQWM3dTYKL2FBMFA1R29uWjVVa1JEWXBhK2plSlVhYnFXWlFRRWd0bXZqbG1VVWlYd3UwalJuajFuMFQzZlBRRDNnQStMSQp2QUU5dmd2cFk1WFFqNm90cEJ2c1ozTUpKTktjVU1RdTF6T0FOVHpPMThUbEE4S29CTnNCeThaOURRWktYRjhDCkF3RUFBVEFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBZUduL055cUlSSS8wQUdxdkhQOTdLdFE3NlRqNmFjaGIKMzBMSVhXcCtZSFVhTWVBVmpkMlo3alNRcDVtWlpGbCtrMWZiMzM3SWVhR1hvZlZJMjFlSzUyUVgydGVOb0JrQQovVi9PMUh1MzUvK2FpejB4c2RENndXdndvNEZ5MWpsbWFlSmh3ZFFhY0JsREdGQTJqRkp4dUVwYWhmeFp2VXNiCjNqNXpVMFdLVFVDZkVEZ1hGd0J3MTJ4a3UvN1RNZENFYlJzWWFaM3pGVEMyMjZsUWJVRE43d2VxRndTRCt0QjYKUnVoSXhlOCtjRndBc0FXSENsZXJLZ1pucjN0NVFGMDc4cFcyR0h5OENzSjdWM01aVDVsWjQzbFM1TklCOUp6WgpTWXhaL2l6aFJ5aDVxUjczdUFnc0phTDU2QmorY1Fxbm9UcWhMWlZsN0orTTZXaFdLem9qc0E9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== 26 | 27 | # Set the remote desktop login password for LAMDA, 6-32 characters. 28 | # This password will only take effect if a certificate (--certificate) 29 | # is used. It serves as a backup password to the one generated in 30 | # the certificate (for easier memorization). 31 | ssl-web-credential=password123 32 | 33 | # Set Access-Control-Allow-Origin header of firerpa webui 34 | # and it's apis to allow you embed firerpa's features 35 | # see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin 36 | allow_origin=https://example.com 37 | 38 | # Setting this option will also disable the LAMDA Python client API. 39 | # This option should be set only if the device crashes after starting LAMDA, 40 | # or if you do not need to use the API. This option will also disable 41 | # any components that might impact system stability. 42 | disable-client-api=false 43 | 44 | # Enhanced stealth mode, designed to protect LAMDA and its associated 45 | # components from detection in cases where there is a risk of damaging 46 | # itself or third-party components. 47 | # Use only if necessary (introduced in version 7.65). 48 | enhanced-stealth-mode=false 49 | 50 | # Remote Desktop Touch Fix 51 | # If there is an offset or no response when you touch the screen on 52 | # the remote desktop, please set the following configuration: 53 | touch.backend=system 54 | 55 | # The switch for get_last_activities, default is false and does not intercept. 56 | # introduced in 8.20 57 | intercept-intent=false 58 | 59 | # Set the log file location (directory must exists) 60 | logfile=/data/local/tmp/server.log 61 | 62 | # ---------- OpenVPN Configuration ---------- 63 | # Do not manually write the following configuration. You should use 64 | # our accompanying OpenVPN server setup solution to set it up and 65 | # generate this configuration using its built-in commands. 66 | openvpn.proto=udp 67 | openvpn.cipher=AES-256-GCM 68 | openvpn.host=123.123.123.123 69 | openvpn.port=1190 70 | openvpn.ca=LS0tLS1CRU... 71 | openvpn.cert=LS0tLS1CRU... 72 | openvpn.key=LS0tLS1CRU... 73 | openvpn.tls_encryption= 74 | openvpn.tls_key_direction= 75 | openvpn.tls_key= 76 | # ONLY THE FOLLOWING CONFIGURATION ITEMS CAN BE MANUALLY CONFIGURED. 77 | # Whether to enable global VPN. 78 | openvpn.global=false 79 | # Whether to enable the service true | false 80 | openvpn.enable=true 81 | 82 | # ---------- Proxy Configuration ---------- 83 | # This configuration is used to make LAMDA automatically connect 84 | # to the proxy server at startup. 85 | # 86 | # Whether to enable the service true | false 87 | gproxy.enable=true 88 | # The proxy type can be either http-connect or socks5. 89 | gproxy.type=http-connect 90 | # Proxy server address 91 | gproxy.host=172.1.1.1 92 | # Proxy server port 93 | gproxy.port=8080 94 | # Proxy server login password (leave empty for no authentication) 95 | gproxy.password= 96 | # Proxy server login username (leave empty for no authentication) 97 | gproxy.login= 98 | 99 | # ---------- CRONTAB Scheduled Task Service ---------- 100 | # If you do not need scheduled tasks, you can disable this service. 101 | # Whether to enable the service true | false 102 | cron.enable=true 103 | 104 | # ---------- SSHD Service ---------- 105 | # If you do not need to connect to the device via SSH, you can disable this service. 106 | # Whether to enable the service true | false 107 | sshd.enable=true 108 | 109 | # ---------- Port Forwarding (frp) Service ---------- 110 | # Whether to enable the service true | false 111 | fwd.enable=true 112 | # Port to forward to the remote (0 means randomly allocated) 113 | fwd.rport=0 114 | # FRP server address 115 | fwd.host=123.123.123.123 116 | # FRP server port 117 | fwd.port=9911 118 | # FRP protocol 119 | fwd.protocol=tcp 120 | # FRP login authentication 121 | fwd.token=abc123 122 | 123 | # ---------- ADB Service ---------- 124 | # Whether to enable the service true | false 125 | adb.enable=true 126 | # Default working directory for built-in ADB (adb shell working directory) 127 | adb.directory=/data/local/tmp 128 | # If set to true, the ADB connection will have root privileges, 129 | # otherwise it will have shell privileges. When this option is set to false, 130 | # you will be using a native-like adb shell, and you will not be able to use 131 | # LAMDA's built-in commands. Please note that since ADB does not use TLS connections, 132 | # traffic may be monitored. For security reasons, when the LAMDA service is 133 | # started with a certificate, this value will be set to false by default. 134 | # However, if you specify it in the properties.local file, the configuration 135 | # in the file will take precedence. 136 | # You are responsible for ensuring security. 137 | adb.privileged=true 138 | 139 | # ---------- Bridge Proxy Service ---------- 140 | # Whether to enable the service true | false 141 | tunnel2.enable=true 142 | # The bridge proxy will require login authentication only if both login and password 143 | # are set. If either one is left empty, no login authentication will be required. 144 | tunnel2.login=lamda 145 | # Login password for the bridge proxy 146 | tunnel2.password=1234 147 | # Outbound interface (rmnet|wlan) 148 | # When the outbound interface is rmnet, the proxy will attempt to forward your requests through mobile data. 149 | # When the outbound interface is wlan, requests will be forwarded through the wlan interface. 150 | # If the configuration is empty, the default network will be used to forward the requests. 151 | tunnel2.iface=rmnet 152 | 153 | # ---------- mDNS Broadcast Service ---------- 154 | # Enable or disable true | false 155 | mdns.enable=true 156 | # Add TXT metadata for mDNS. When enabled, it will support querying device information 157 | # such as model, ABI, and device ID using tools like python-zeroconf. Disabled by default. 158 | mdns.meta=false 159 | # Set the broadcast domain name using a locally unique ID, default is {DEVICEID-UNIQUE}.lamda. 160 | # If the name duplicates in the local network, a suffix ID will be automatically added. 161 | mdns.name=DEVICEID-UNIQUE.lamda 162 | # Set the broadcast service name, default is lamda, i.e., _lamda._tcp.local. 163 | mdns.service=lamda 164 | -------------------------------------------------------------------------------- /scripts/disable_flag_secure.yaml: -------------------------------------------------------------------------------- 1 | # EXAMPLE EXTENSION OF FIRERPA (https://github.com/firerpa/lamda) 2 | # This script is used to disable the android FLAG_SECURE flag. 3 | # Replace YOUR_APP_ID with the ID (eg. com.android.settings) of your target application. 4 | enable: true 5 | application: "YOUR_APP_ID" 6 | version: "N/A" 7 | script: !!binary "SmF2YS5wZXJmb3JtKGZ1bmN0aW9uICgpIHsKICAgICAgICB2YXIgRkxBR19TRUNVUkUgPSAweDIwMDA7CiAgICAgICAgdmFyIFdpbmRvdyA9IEphdmEudXNlKCJhbmRyb2lkLnZpZXcuV2luZG93Iik7CiAgICAgICAgdmFyIHNldEZsYWdzID0gV2luZG93LnNldEZsYWdzOwoKICAgICAgICBzZXRGbGFncy5pbXBsZW1lbnRhdGlvbiA9IGZ1bmN0aW9uIChmbGFncywgbWFzaykgewogICAgICAgICAgICBjb25zb2xlLmxvZygiRGlzYWJsaW5nIEZMQUdfU0VDVVJFLi4uIik7CiAgICAgICAgICAgIGZsYWdzICY9IH5GTEFHX1NFQ1VSRTsKICAgICAgICAgICAgc2V0RmxhZ3MuY2FsbCh0aGlzLCBmbGFncywgbWFzayk7CiAgICAgICAgfTsKfSk7Cg==" 8 | standup: 0 9 | spawn: false -------------------------------------------------------------------------------- /scripts/disable_ssl_pinning_simple.yaml: -------------------------------------------------------------------------------- 1 | # EXAMPLE EXTENSION OF FIRERPA (https://github.com/firerpa/lamda) 2 | # This script is used to disable simple ssl pinning (checkServerTrusted). 3 | # Replace YOUR_APP_ID with the ID (eg. com.android.settings) of your target application. 4 | enable: true 5 | application: "YOUR_APP_ID" 6 | version: "N/A" 7 | script: !!binary "SmF2YS5wZXJmb3JtKGZ1bmN0aW9uKCkgewpKYXZhLnVzZSgiYW5kcm9pZC5zZWN1cml0eS5uZXQuY29uZmlnLlJvb3RUcnVzdE1hbmFnZXIiKS5jaGVja1NlcnZlclRydXN0ZWQub3ZlcmxvYWQoIltMamF2YS5zZWN1cml0eS5jZXJ0Llg1MDlDZXJ0aWZpY2F0ZTsiLCAiamF2YS5sYW5nLlN0cmluZyIsICJqYXZhLm5ldC5Tb2NrZXQiKS5pbXBsZW1lbnRhdGlvbiA9IGZ1bmN0aW9uIChhLCBiLCBjKSB7CiAgICAgICAgcmV0dXJuCn0KfSkK" 8 | standup: 0 9 | spawn: false -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # Copyright 2022 rev1si0n (lamda.devel@gmail.com). All rights reserved. 3 | import setuptools 4 | 5 | exec(open("lamda/__init__.py", "rt").read()) 6 | 7 | setuptools.setup( 8 | name = "lamda", 9 | version = "{}".format(__version__), 10 | description = "Android reverse engineering & automation framework (Client API)", 11 | url = "https://github.com/firerpa/lamda", 12 | author = "rev1si0n", 13 | python_requires = ">=3.6,<3.13", 14 | zip_safe = False, 15 | extras_require = { 16 | "full": ["frida>=16.0.0,<17.0.0"], 17 | ":sys_platform == \"win32\"": [ 18 | "pyreadline==2.1", 19 | ], 20 | }, 21 | install_requires= [ 22 | "grpcio-tools>=1.35.0,<=1.68.0", 23 | "grpc-interceptor>=0.13.0,<=0.15.4", 24 | "grpcio>=1.35.0,<=1.68.0", 25 | "cryptography>=35.0.0", 26 | "msgpack>=1.0.0", 27 | "asn1crypto>=1.0.0,<2", 28 | "pem==23.1.0", 29 | ], 30 | classifiers = [ 31 | "Environment :: Console", 32 | "Intended Audience :: Developers", 33 | "Development Status :: 5 - Production/Stable", 34 | "Intended Audience :: Information Technology", 35 | "Intended Audience :: Science/Research", 36 | "Programming Language :: Python :: 3", 37 | "Operating System :: Android", 38 | "Topic :: Security", 39 | ], 40 | package_data = { 41 | "lamda": ["*.py", "*.proto"], 42 | "lamda.google.protobuf.compiler": ["*.proto"], 43 | "lamda.google.protobuf": ["*.proto"], 44 | "lamda.rpc": ["*.proto"], 45 | }, 46 | packages = [ 47 | "lamda.google.protobuf.compiler", 48 | "lamda.google.protobuf", 49 | "lamda.rpc", 50 | "lamda", 51 | ], 52 | ) 53 | -------------------------------------------------------------------------------- /tools/README.md: -------------------------------------------------------------------------------- 1 | Document: https://device-farm.com/doc/ -------------------------------------------------------------------------------- /tools/adb_pubkey.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | #encoding=utf-8 3 | import os 4 | import argparse 5 | 6 | from os.path import isfile 7 | from lamda.client import * 8 | 9 | certfile = os.environ.get("CERTIFICATE", None) 10 | port = int(os.environ.get("PORT", 65000)) 11 | 12 | android_path = os.path.join("~", ".android") 13 | abs_android_path = os.path.expanduser(android_path) 14 | f = "adbkey.pub" 15 | 16 | argp = argparse.ArgumentParser() 17 | 18 | argp.add_argument("action", nargs=1) 19 | argp.add_argument("device", nargs=1) 20 | 21 | args = argp.parse_args() 22 | 23 | d = Device(args.device[0], port=port, 24 | certificate=certfile) 25 | cmd = args.action[0] 26 | 27 | os.chdir(abs_android_path) 28 | 29 | # try generate pubkey 30 | pubkey = os.popen("adb pubkey adbkey").read() 31 | open("adbkey.lamda", "w").write(pubkey) 32 | 33 | f = ("adbkey.lamda", f)[isfile(f)] 34 | 35 | call = getattr(d, "%s_adb_pubkey" % cmd) 36 | exit(not call(f)) -------------------------------------------------------------------------------- /tools/cert.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import os 3 | import sys 4 | import random 5 | import datetime 6 | 7 | from hashlib import sha256 8 | from cryptography.hazmat.primitives.asymmetric import rsa 9 | from cryptography.hazmat.primitives import hashes, serialization 10 | from cryptography.hazmat.backends import default_backend 11 | from cryptography.x509 import ( 12 | Name, 13 | NameAttribute, 14 | CertificateBuilder, 15 | CertificateSigningRequestBuilder, 16 | DNSName, 17 | SubjectAlternativeName, 18 | load_pem_x509_certificate, 19 | BasicConstraints, 20 | KeyUsage, 21 | ) 22 | from cryptography.x509.oid import NameOID 23 | 24 | CN = "lamda" 25 | if len(sys.argv) == 2: 26 | CN = sys.argv[1] 27 | 28 | if os.path.isfile("root.key"): 29 | with open("root.key", "rb") as f: 30 | rk = serialization.load_pem_private_key( 31 | f.read(), password=None, backend=default_backend() 32 | ) 33 | else: 34 | rk = rsa.generate_private_key( 35 | public_exponent=65537, key_size=2048, backend=default_backend() 36 | ) 37 | with open("root.key", "wb") as f: 38 | f.write( 39 | rk.private_bytes( 40 | encoding=serialization.Encoding.PEM, 41 | format=serialization.PrivateFormat.TraditionalOpenSSL, 42 | encryption_algorithm=serialization.NoEncryption(), 43 | ) 44 | ) 45 | 46 | if os.path.isfile("root.crt"): 47 | with open("root.crt", "rb") as f: 48 | root = load_pem_x509_certificate(f.read(), default_backend()) 49 | else: 50 | subject = issuer = Name( 51 | [ 52 | NameAttribute(NameOID.ORGANIZATION_NAME, "LAMDA"), 53 | NameAttribute(NameOID.COMMON_NAME, "FireRPA LAMDA Root Trust"), 54 | ] 55 | ) 56 | root = ( 57 | CertificateBuilder() 58 | .subject_name(subject) 59 | .issuer_name(issuer) 60 | .not_valid_before(datetime.datetime.utcnow()) 61 | .not_valid_after(datetime.datetime.utcnow() + datetime.timedelta(days=3650)) 62 | .public_key(rk.public_key()) 63 | .serial_number(random.randint(1, 2**128)) 64 | .add_extension(BasicConstraints(ca=True, path_length=None), critical=True) 65 | .sign(rk, hashes.SHA256(), default_backend()) 66 | ) 67 | with open("root.crt", "wb") as f: 68 | f.write(root.public_bytes(serialization.Encoding.PEM)) 69 | 70 | 71 | if not os.path.isfile(f"{CN}.pem"): 72 | pk = rsa.generate_private_key( 73 | public_exponent=65537, key_size=2048, backend=default_backend() 74 | ) 75 | csr = ( 76 | CertificateSigningRequestBuilder() 77 | .subject_name(Name([NameAttribute(NameOID.COMMON_NAME, CN)])) 78 | .sign(pk, hashes.SHA256(), default_backend()) 79 | ) 80 | 81 | cert = ( 82 | CertificateBuilder() 83 | .subject_name(csr.subject) 84 | .issuer_name(root.subject) 85 | .not_valid_before(datetime.datetime.utcnow()) 86 | .not_valid_after(datetime.datetime.utcnow() + datetime.timedelta(days=3650)) 87 | .public_key(csr.public_key()) 88 | .serial_number(random.randint(1, 2**128)) 89 | .sign(rk, hashes.SHA256(), default_backend()) 90 | ) 91 | 92 | with open(f"{CN}.pem", "wb") as output: 93 | pem_private_key = pk.private_bytes( 94 | encoding=serialization.Encoding.PEM, 95 | format=serialization.PrivateFormat.TraditionalOpenSSL, 96 | encryption_algorithm=serialization.NoEncryption(), 97 | ) 98 | pem_cert = cert.public_bytes(serialization.Encoding.PEM) 99 | pem_root = root.public_bytes(serialization.Encoding.PEM) 100 | 101 | d = pk.private_numbers().d 102 | pd = d.to_bytes((d.bit_length() + 7) // 8, "little") 103 | cred = sha256(pd).hexdigest()[::3] 104 | 105 | header = f"LAMDA SSL CERTIFICATE (CN={CN},PASSWD={cred})\n" 106 | output.write(header.encode()) 107 | output.write(pem_private_key.strip()) 108 | output.write(b"\n") 109 | output.write(pem_cert.strip()) 110 | output.write(b"\n") 111 | output.write(pem_root.strip()) 112 | output.write(b"\n") 113 | -------------------------------------------------------------------------------- /tools/debugimage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import os 3 | import argparse 4 | 5 | from PIL import Image, ImageDraw 6 | from lamda.client import * 7 | 8 | cert = os.environ.get("CERTIFICATE", None) 9 | port = int(os.environ.get("PORT", 65000)) 10 | 11 | parser = argparse.ArgumentParser() 12 | parser.add_argument("-d", type=str, dest="device", 13 | help="service ip address", required=True) 14 | parser.add_argument("-p", "--port", type=str, 15 | default=port, help="service port") 16 | parser.add_argument("-f", "--method", type=str, 17 | help="find method", default="0") 18 | parser.add_argument("-i", "--image", type=argparse.FileType("rb"), 19 | help="find image path", required=True) 20 | parser.add_argument("-a", "--area", type=str, 21 | help="area", default="0") 22 | parser.add_argument("-s", "--scale", type=float, 23 | help="scale", default=1.0) 24 | parser.add_argument("-t", "--threshold", type=float, 25 | help="threshold", default=0) 26 | parser.add_argument("-m", "--distance", type=int, 27 | help="max distance", default=0) 28 | parser.add_argument("-cert", type=str, default=cert, 29 | help="ssl cert") 30 | args = parser.parse_args() 31 | 32 | 33 | d = Device(args.device, port=args.port, 34 | certificate=args.cert) 35 | image = Image.open(d.screenshot(95)) 36 | 37 | draw = ImageDraw.Draw(image) 38 | for r in d.find_similar_image(args.image.read(), 39 | area=eval(args.area), 40 | method=eval(args.method), 41 | distance=args.distance, 42 | threshold=args.threshold, 43 | scale=args.scale): 44 | p1 = r.corner("top-left") 45 | p2 = r.corner("bottom-right") 46 | draw.rectangle(((p1.x, p1.y), (p2.x, p2.y)), 47 | outline="#00ff00", width=3) 48 | image.show() -------------------------------------------------------------------------------- /tools/discover.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import os 3 | import struct 4 | from socket import * 5 | 6 | from lamda import __version__ 7 | from lamda.client import load_proto 8 | 9 | protos, services = load_proto("bcast.proto") 10 | 11 | BcastHeader = protos.BcastHeader 12 | BcastDiscoverInfo = protos.BcastDiscoverInfo 13 | BcastResponse = protos.BcastResponse 14 | BcastRequest = protos.BcastRequest 15 | 16 | port = int(os.environ.get("PORT", 65000)) 17 | 18 | 19 | def BcastCallMethod(method): 20 | req = BcastRequest(method=method) 21 | # ASTBCAST + length (body,4byte) + body + feeedeed 22 | hdr = BcastHeader(magic=0x54534143, 23 | version=__version__) 24 | req.header.CopyFrom(hdr) 25 | body = req.SerializeToString() 26 | buffer = [] 27 | r = struct.pack("QH", 0x5453414342545341, len(body)) 28 | buffer.append(r) 29 | r = struct.pack("{}s".format(len(body)), body) 30 | buffer.append(r) 31 | r = struct.pack("I", 0xeedeeefe) 32 | buffer.append(r) 33 | r = bytes().join(buffer) 34 | return r 35 | 36 | 37 | sock = socket(AF_INET, SOCK_DGRAM) 38 | sock.setsockopt(SOL_SOCKET, SO_BROADCAST, 1) 39 | message = BcastCallMethod("DISCOVER") 40 | sock.sendto(message, ("255.255.255.255", port)) 41 | sock.settimeout(3.0) 42 | 43 | while True: 44 | try: 45 | data, remote = sock.recvfrom(4096) 46 | except timeout: 47 | break 48 | fmt = " ${BINDIR}/gost 16 | 17 | COPY startmitm.py ${BINDIR} 18 | COPY globalmitm/entry ${BINDIR} 19 | COPY globalmitm/DNS2SOCKS.c /tmp 20 | COPY requirements.txt /tmp 21 | 22 | RUN gcc -pthread DNS2SOCKS.c -o ${BINDIR}/DNS2SOCKS 23 | RUN pip3 install -i ${PYPIMIRROR} --no-cache-dir -r requirements.txt 24 | 25 | RUN chmod 755 ${BINDIR}/* 26 | ENV PATH=${BINDIR}:${PATH} 27 | 28 | WORKDIR /root 29 | EXPOSE 53/udp 8118/tcp 1234/tcp 30 | ENTRYPOINT [ "entry" ] -------------------------------------------------------------------------------- /tools/globalmitm/entry: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | export GRPC_DNS_RESOLVER=native 4 | export PROXYPORT=${PROXYPORT:-8118} 5 | 6 | die () { 7 | echo $@; exit 1 8 | } 9 | 10 | IP=${1:-} 11 | if [ -z "${IP}" ]; then 12 | die "no device provided" 13 | fi 14 | 15 | DNS=${DNS:-8.8.8.8} 16 | PDNS=$(((RANDOM % 10000) + 10000)) 17 | 18 | if [ ! -z "${SOCKS5}" ] || [ ! -z "${HTTP}" ]; then 19 | PIDS= 20 | 21 | if [ ! -z "${SOCKS5}" ]; then 22 | PHTTP=$(((RANDOM % 10000) + 10000)) 23 | UPSTREAM=http://127.0.0.1:${PHTTP} 24 | gost -L=${UPSTREAM} -F=socks5://${SOCKS5} >/dev/null 2>&1 & 25 | PIDS="$PIDS $!" 26 | DNS2SOCKS ${SOCKS5} ${DNS} 127.0.0.1:${PDNS} /q & 27 | PIDS="$PIDS $!" 28 | 29 | elif [ ! -z "${HTTP}" ]; then 30 | UPSTREAM=http://${HTTP} 31 | DNS2SOCKS ${HTTP} ${DNS} 127.0.0.1:${PDNS} /t /q & 32 | PIDS="$PIDS $!" 33 | 34 | else 35 | die 36 | fi 37 | 38 | trap "kill -9 ${PIDS} 2>/dev/null" SIGINT 39 | if ! dig +time=3 google.com @127.0.0.1 -p ${PDNS}; then 40 | die "BAD PROXY (CANNOT RESOLVE THROUGH PROXY)" 41 | fi 42 | 43 | set -- "$@" --dns 127.0.0.1:${PDNS} 44 | set -- "$@" --mode upstream:${UPSTREAM} 45 | fi 46 | 47 | # common arguments 48 | set -- "$@" --web-host=0.0.0.0 49 | set -- "$@" --web-port=${WEBPORT:-1234} 50 | set -- "$@" --set block_global=false 51 | 52 | startmitm.py $@ -------------------------------------------------------------------------------- /tools/id_rsa: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEogIBAAKCAQEA4QHmY32OT+F+maERMn1cvBRuIOIXH9yOALG+GMCngtjRJzSR 3 | n09dInmXE+PjiAqNRWvknVEjFywv0v1v/H2qSRJKR/togPgySjiABhigqDHdirNd 4 | Dh63oN2e+d0yythoLzsQrH5BSVtw05Atpkr7bW4KdfMveWuddvDACnQ3mvCXq50X 5 | IK3cOlmHXwcJrX55BhEXxgHIqw0upf0A7DC3Afz5xjOA6+K/O2EzZIIJ+sWw7/Ko 6 | 5+3m98Et0zwcxe20uNxzYf7JSMu3490YNckLiQcDrZVRUXNS70HO9HWCXKdjFJPi 7 | GgPtKUQNHjChwzSCQQGzqitXdwa60i9Sy1U09wIBIwKCAQAzbiYIHLLQbg5PAD5x 8 | 8MS9Rn+SfNIV6UUHeRWCACZJyyh9/WMdGXRfpsNyQreqEQpZArfpcaGe5YdGK0zL 9 | /3dhKMCFe0sWKhofl+K/kJnAC2XWj2W6FaZQp69PDfz7KiZxMhJwkeMJc/yIIPR9 10 | x/70cOxyuz4NH+l6Rag8510qujhxn6lGc1+ZNHGeAYmUD7wFz9/QYDZU9C0YcylA 11 | 2+Q5woU3L4b3y3JKqB6/dnsP9uF7R5KBR+qiqOwVm0nhvVU5uwbpQwTXeklopXyN 12 | rI/NeYcsDoEyb8NquVXX/GkOgY0FhqblGUR9kSdTLHq6VamelHc+dczZgMxcsq1c 13 | mnnLAoGBAP2FPssFpHJRhSr38Fq5A7mEjQeiPq2WgYV7kCpJT5F5OymcCCETIjEH 14 | 4pTk5zCWUuIBx5LlzSa0XnQSYb0100ZzvDgfm1NPmqdkpPwkkbh2xyoHYTTPJ3WG 15 | TDur8Qyi83NteveszO1TCAGBTe3zN+2ov9qzl5Y7QHF94GVFDo4NAoGBAOM1Q8eG 16 | 0KeqjutTz/UMtejoFpz0Hi1g32PfdQInHx8MDslYu3Fcpnos3xf59H7+mrRy0fUM 17 | hh27v7DiUvxUfhlojf0F3kDKeg9VZBslZF3vTCpFdKdFouZ2Cru3lCoaPSau69BC 18 | 6HQw4P+RABrgxc6CeE9FUGEEMss+wTcRItITAoGBAO8ImkpkZ9mAD9gOV6X+5kEz 19 | 1W2Y+USVOEqns9AZPGSW4AKpDvqdAvsHbzvtxAk9RtUXnumW118B1WYf9cEG3SUr 20 | SxBYUJ8B6ZaDdvxc/mwYOCBQGdK0sCz692t2OwvqGL1J95kQo/W0r8bnoT9wSqzg 21 | 72fN5rI33azVxPHExJSPAoGAGfd1deOFj4E057HOn6muY8LAwXr8InF4nbMjULQD 22 | joUJARF0gfv1xNHtnFcUoMyj912UVoUWpE/4poBD/5SgsnJZXr7XkmBIdsfuLvz1 23 | hxQItF+1j3WsN5h2QVbPGsErj2RyuLcwgk66oN1fGQO+1cXEm1hg9SUNHorUQM7C 24 | JqMCgYEAofxXJ8dOWUaFIHmKLE7Y+0+i3D1yXVIyu/puuaQGbNFHxjcJ9ZdubhLN 25 | IyzJvngtM7mC90FtUETxvErMGdTzFeKtSKBZsJ8BiLCszRCEuJf5RX6uNrFUQ2pT 26 | PEmns088Gs4KUDwjTG0zQtj3pNc5zDynDMpFKp96spefqLJqw3s= 27 | -----END RSA PRIVATE KEY----- -------------------------------------------------------------------------------- /tools/ida.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | #encoding=utf-8 3 | import os 4 | import sys 5 | import time 6 | import argparse 7 | import subprocess 8 | 9 | from shlex import split as s 10 | from lamda.client import * 11 | 12 | certfile = os.environ.get("CERTIFICATE", None) 13 | port = int(os.environ.get("PORT", 65000)) 14 | 15 | argp = argparse.ArgumentParser() 16 | argp.add_argument("-d", type=str, required=True) 17 | argp.add_argument("-a", type=str, required=True) 18 | args = argp.parse_args() 19 | 20 | certfile = os.environ.get("CERTIFICATE", None) 21 | d = Device(args.d, certificate=certfile) 22 | 23 | app = d.application(args.a) 24 | d.start_activity(**app.query_launch_activity(), debug=True) 25 | print (time.ctime(), "{} is started as debuggable mode".format(args.a)) 26 | print (time.ctime(), "Waitting for 'Waitting For Debugger' popup") 27 | if not d(textContains="Waiting").wait_for_exists(25*1000): 28 | print (time.ctime(), "No debugger prompt detected, please ensure "\ 29 | "you already run 'setdebuggable' in firerpa terminal." ) 30 | exit (1) 31 | 32 | pName = app.info().processName 33 | processes = d.enumerate_running_processes() 34 | p = list(filter(lambda p: p.processName == pName, 35 | processes))[0] 36 | print (time.ctime(), "Found pid: {}".format(p.pid)) 37 | # Build forward cmd 38 | print (time.ctime(), "Forwarding jwdp pid") 39 | cmd = s("adb forward tcp:8700 jdwp:%s" % p.pid) 40 | forward = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, 41 | stderr=subprocess.DEVNULL, 42 | shell=False) 43 | forward.wait() 44 | 45 | print (time.ctime(), "--------------------------------") 46 | print (time.ctime(), "Now please use your IDA to attach this target") 47 | print (time.ctime(), "name: {} pid: {}".format(pName, p.pid)) 48 | print (time.ctime(), "and wait for IDA 'Downloading symbols' to finish") 49 | print (time.ctime(), "when all is finished, press ENTER to continue") 50 | print (time.ctime(), "--------------------------------") 51 | 52 | _ = input() 53 | 54 | cmd = s("jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=8700") 55 | debug = subprocess.Popen(cmd, stdin=sys.stdin, 56 | stdout=sys.stdout, 57 | stderr=sys.stderr, 58 | bufsize=0, 59 | shell=False) 60 | debug.wait() -------------------------------------------------------------------------------- /tools/magisk/META-INF/com/google/android/update-binary: -------------------------------------------------------------------------------- 1 | #!/sbin/sh 2 | source /data/adb/magisk/util_functions.sh 3 | 4 | if [ ${MAGISK_VER_CODE} -lt 20400 ]; then 5 | abort "Please install Magisk v20.4 +" 6 | exit 1 7 | fi 8 | 9 | if [ "${BOOTMODE}" != "true" ]; then 10 | abort "Must install from Magisk app" 11 | fi 12 | 13 | OUTFD=$2 14 | ZIPFILE=$3 15 | install_module 16 | exit 0 -------------------------------------------------------------------------------- /tools/magisk/META-INF/com/google/android/updater-script: -------------------------------------------------------------------------------- 1 | #MAGISK 2 | -------------------------------------------------------------------------------- /tools/magisk/common/server/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firerpa/lamda/fbd5e6e0ec602df622130c53abb4e87bd783e442/tools/magisk/common/server/.keep -------------------------------------------------------------------------------- /tools/magisk/common/service.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | base=${0%/*} 3 | cert=/data/usr/lamda.pem 4 | launch="sh ${base}/server/bin/launch.sh" 5 | port=65000 6 | 7 | sleep 25 8 | export ca_store_remount=true 9 | if [ -f "${cert}" ]; then 10 | $launch --port=${port} --certificate=${cert} 11 | else 12 | $launch --port=${port} 13 | fi -------------------------------------------------------------------------------- /tools/magisk/install.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | ABI=$(getprop ro.product.cpu.abi) 3 | SERVER=$TMPDIR/lamda-server-$ABI.tar.gz 4 | BB="/data/adb/magisk/busybox" 5 | USRDIR=/data/usr 6 | 7 | if [ -d "/data/adb/ksu/" ]; then 8 | BB="/data/adb/ksu/bin/busybox" 9 | fi 10 | 11 | export LATESTARTSERVICE=true 12 | 13 | ui_print ".____ ________ _____ " 14 | ui_print "| | _____ _____ \______ \ / _ \ " 15 | ui_print "| | \__ \ / \ | | \ / /_\ \ " 16 | ui_print "| |___ / __ \_| Y Y \ | | \/ | \ " 17 | ui_print "|_______ \(____ /|__|_| / /_______ /\____|__ / " 18 | ui_print " \/ \/ \/ \/ \/ " 19 | ui_print " installer " 20 | 21 | pushd $(pwd) 22 | cd $MODPATH 23 | if [ ! -f $SERVER ]; then 24 | abort "lamda-server-${ABI}.tar.gz not in archive, please download and drop it to common/server." 25 | fi 26 | 27 | ui_print "- Extracting server files" 28 | $BB tar -xzf $SERVER 29 | 30 | ui_print "- Placing configs" 31 | mkdir -p ${USRDIR} 32 | 33 | cp -af $TMPDIR/adb_keys ${USRDIR}/.adb_keys 34 | 35 | cp -af $TMPDIR/properties.local ${USRDIR} 36 | cp -af $TMPDIR/lamda.pem ${USRDIR} 37 | 38 | ui_print "- Please reboot your device" 39 | popd -------------------------------------------------------------------------------- /tools/magisk/module.prop: -------------------------------------------------------------------------------- 1 | id=lamda 2 | name=LAMDA 3 | version=VERSION 4 | versionCode=VERSIONCODE 5 | author=rev1si0n 6 | description=Android reverse engineering & automation framework -------------------------------------------------------------------------------- /tools/magisk/uninstall.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | MODPATH=${0%/*} 3 | 4 | echo "/data/usr will not be removed, please remove it manually" -------------------------------------------------------------------------------- /tools/objection-1.11.0-command-patch.diff: -------------------------------------------------------------------------------- 1 | diff --git a/console/cli.py b/console/cli.py 2 | index 1fc22fb..80e52dc 100644 3 | --- a/console/cli.py 4 | +++ b/console/cli.py 5 | @@ -31,8 +31,10 @@ from ..utils.helpers import normalize_gadget_name, print_frida_connection_help, 6 | @click.option('--serial', '-S', required=False, default=None, help='A device serial to connect to.') 7 | @click.option('--debug', '-d', required=False, default=False, is_flag=True, 8 | help='Enable debug mode with verbose output. (Includes agent source map in stack traces)') 9 | +@click.option('--certificate', '-c', required=False, default=None, help="Frida connection certificate") 10 | +@click.option('--token', '-t', required=False, default=None, help="Frida connection token") 11 | def cli(network: bool, host: str, port: int, api_host: str, api_port: int, 12 | - gadget: str, serial: str, debug: bool) -> None: 13 | + gadget: str, serial: str, debug: bool, certificate: str, token: str) -> None: 14 | """ 15 | \b 16 | _ _ _ _ 17 | @@ -56,6 +58,8 @@ def cli(network: bool, host: str, port: int, api_host: str, api_port: int, 18 | state_connection.use_network() 19 | state_connection.host = host 20 | state_connection.port = port 21 | + state_connection.certificate = certificate 22 | + state_connection.token = token 23 | 24 | if serial: 25 | state_connection.device_serial = serial 26 | diff --git a/utils/agent.py b/utils/agent.py 27 | index 6d88e3a..fbe9b40 100644 28 | --- a/utils/agent.py 29 | +++ b/utils/agent.py 30 | @@ -126,8 +126,13 @@ class Agent(object): 31 | return device 32 | 33 | if state_connection.get_comms_type() == state_connection.TYPE_REMOTE: 34 | + kwargs = {} 35 | + if state_connection.certificate: 36 | + kwargs["certificate"] = state_connection.certificate 37 | + if state_connection.token: 38 | + kwargs["token"] = state_connection.token 39 | device = frida.get_device_manager().add_remote_device('{host}:{port}'.format( 40 | - host=state_connection.host, port=state_connection.port)) 41 | + host=state_connection.host, port=state_connection.port), **kwargs) 42 | click.secho('Using networked device @`{n}`'.format(n=device.name), bold=True) 43 | 44 | return device 45 | -------------------------------------------------------------------------------- /tools/openvpn/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.15 2 | 3 | LABEL maintainer="rev1si0n " 4 | 5 | ENV VARS=/etc/openvpn/easy-rsa/vars 6 | ENV OVPNCONFIG=/etc/openvpn/config.ovpn 7 | ENV SOURCESMIRROR=mirrors.ustc.edu.cn 8 | 9 | RUN sed -i "s/dl-cdn.alpinelinux.org/${SOURCESMIRROR}/g" /etc/apk/repositories 10 | 11 | COPY entry /usr/bin/run 12 | COPY ovpn-server-new /usr/bin 13 | COPY ovpn-client-profile /usr/bin 14 | COPY ovpn-client-revoke /usr/bin 15 | COPY ovpn-client-new /usr/bin 16 | 17 | COPY config.ovpn /root 18 | COPY vars /root 19 | 20 | RUN apk add openvpn easy-rsa bash curl jq 21 | 22 | RUN ln -sf /usr/share/easy-rsa/easyrsa /usr/bin/easyrsa 23 | RUN ln -sf ${VARS} /usr/share/easy-rsa/vars 24 | 25 | WORKDIR /etc/openvpn 26 | -------------------------------------------------------------------------------- /tools/openvpn/config.ovpn: -------------------------------------------------------------------------------- 1 | # openvpn Docker image config 2 | # https://github.com/rev1si0n/lamda/tree/master/tools/openvpn 3 | # 4 | topology subnet 5 | server 172.27.27.0 255.255.255.0 6 | 7 | proto udp 8 | port 1190 9 | 10 | dev tun 11 | 12 | # 不要编辑下面几行 easy-rsa/pki 配置 13 | ca /etc/openvpn/easy-rsa/pki/ca.crt 14 | dh /etc/openvpn/easy-rsa/pki/dh.pem 15 | cert /etc/openvpn/easy-rsa/pki/issued/lamda.crt 16 | key /etc/openvpn/easy-rsa/pki/private/lamda.key 17 | crl-verify /etc/openvpn/easy-rsa/pki/crl.pem 18 | 19 | # TLS crypt 配置二选一 20 | ;tls-auth /etc/openvpn/ta.key 0 21 | tls-crypt /etc/openvpn/ta.key 22 | 23 | cipher AES-256-GCM 24 | keepalive 15 120 25 | 26 | persist-tun 27 | persist-key 28 | 29 | ifconfig-pool-persist ipp.txt 10 30 | client-to-client 31 | 32 | client-config-dir ccd 33 | script-security 2 34 | 35 | compress lz4-v2 36 | push "compress lz4-v2" 37 | 38 | max-clients 254 39 | 40 | # 如果你想路由其他服务器上的网段到客户端 41 | ;push "route 192.168.1.0 255.255.255.0" 42 | 43 | # 如果你想要让每个客户端使用特定 DNS 44 | ;push "dhcp-option DNS 114.114.114.114" 45 | 46 | verb 4 -------------------------------------------------------------------------------- /tools/openvpn/entry: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ -f "${OVPNCONFIG}" ] && [ -f "${VARS}" ]; then 3 | exec openvpn --config config.ovpn 4 | fi 5 | -------------------------------------------------------------------------------- /tools/openvpn/ovpn-client-new: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | TC_CLIENT=/etc/openvpn/tls-crypt-v2-client/$1 3 | TC_SERVER=/etc/openvpn/tls-crypt-v2-server.key 4 | openvpn --genkey tls-crypt-v2-client ${TC_CLIENT} --tls-crypt-v2 ${TC_SERVER} 5 | easyrsa build-client-full "$1" nopass -------------------------------------------------------------------------------- /tools/openvpn/ovpn-client-profile: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export CLIENT=$2 3 | 4 | if [ -f "easy-rsa/pki/issued/${CLIENT}.crt" ]; then 5 | 6 | CRYPT_cfg_n="$(grep -Eo '^tls-(auth|crypt|crypt-v2)' config.ovpn | wc -l)" 7 | if [ 0"${CRYPT_cfg_n}" -gt 1 ]; then 8 | echo "Multiple tls-auth/crypt/crypt-v2 config detected"; exit 1 9 | fi 10 | 11 | TLS_ENCRYPTION= 12 | if [ 0"${CRYPT_cfg_n}" -eq 1 ]; then 13 | TLS_ENCRYPTION=$(grep -Eo '^tls-(auth|crypt|crypt-v2)' config.ovpn) 14 | TLS_CRYPT=$(echo ${TLS_ENCRYPTION}|tr '-' '_') 15 | else 16 | TLS_CRYPT=tls_none 17 | fi 18 | 19 | PROTO=$(sed -n -e 's/^proto *\(.\+\).*/\1/p' config.ovpn) 20 | CIPHER=$(sed -n -e 's/^cipher *\(.\+\).*/\1/p' config.ovpn) 21 | PORT=$(sed -n -e 's/^port *\([[:digit:]]\+\).*/\1/p' config.ovpn) 22 | WANIP=$(curl -s https://httpbin.org/ip | jq -r .origin) 23 | 24 | CA=$(cat easy-rsa/pki/ca.crt) 25 | CERT=$(openssl x509 -in easy-rsa/pki/issued/${CLIENT}.crt) 26 | KEY=$(cat easy-rsa/pki/private/${CLIENT}.key) 27 | 28 | SERVER_KEY_DIRECTION_n=$(sed -n -e 's/^tls-auth *.* \([[:digit:]]\).*/\1/p' config.ovpn) 29 | if [ x"${SERVER_KEY_DIRECTION_n}"x = xx ]; then 30 | SERVER_KEY_DIRECTION_n=$(sed -n -e 's/^key-direction *\(.\+\).*/\1/p' config.ovpn) 31 | fi 32 | 33 | CLIENT_KEY_DIRECTION_n= 34 | if [ x"${SERVER_KEY_DIRECTION_n}"x != xx ]; then 35 | CLIENT_KEY_DIRECTION_n=$((1^SERVER_KEY_DIRECTION_n)) 36 | fi 37 | 38 | CLIENT_KEY_DIRECTION_inline= 39 | CLIENT_KEY_DIRECTION=KEY_DIRECTION_NONE 40 | if [ x"${CLIENT_KEY_DIRECTION_n}"x != xx ]; then 41 | CLIENT_KEY_DIRECTION_inline="key-direction ${CLIENT_KEY_DIRECTION_n}" 42 | CLIENT_KEY_DIRECTION=KEY_DIRECTION_${CLIENT_KEY_DIRECTION_n} 43 | fi 44 | 45 | if [ "${TLS_ENCRYPTION}" = "tls-crypt-v2" ]; then 46 | TA=$(cat /etc/openvpn/tls-crypt-v2-client/${CLIENT}) 47 | elif [ ! -z "${TLS_ENCRYPTION}" ]; then 48 | TA=$(sed '/^#/d' ta.key) 49 | else 50 | TA= 51 | fi 52 | if [ "g$1" = govpn ]; then 53 | cat <&1 54 | client 55 | float 56 | nobind 57 | 58 | dev tun 59 | proto ${PROTO} 60 | remote ${WANIP} ${PORT} 61 | resolv-retry infinite 62 | 63 | cipher ${CIPHER} 64 | keepalive 15 60 65 | 66 | remote-cert-tls server 67 | 68 | ${CLIENT_KEY_DIRECTION_inline} 69 | <${TLS_ENCRYPTION}> 70 | ${TA} 71 | 72 | 73 | 74 | ${CA} 75 | 76 | 77 | 78 | ${CERT} 79 | 80 | 81 | 82 | ${KEY} 83 | 84 | EOL 85 | else 86 | cat <&1 87 | profile = OpenVPNProfile() 88 | profile.all_traffic = False 89 | profile.proto = OpenVPNProto.${PROTO^^} 90 | profile.host = "${WANIP}" 91 | profile.port = ${PORT} 92 | profile.cipher = OpenVPNCipher.$(echo ${CIPHER}|tr '-' '_') 93 | 94 | # auto-generated lamda OpenVPN profile, CN=${CLIENT} 95 | profile.tls_encryption = OpenVPNEncryption.${TLS_CRYPT^^} 96 | profile.tls_key_direction = OpenVPNKeyDirection.${CLIENT_KEY_DIRECTION} 97 | profile.tls_key = """ 98 | ${TA} 99 | """ 100 | 101 | profile.ca = """ 102 | ${CA} 103 | """ 104 | 105 | profile.cert = """ 106 | ${CERT} 107 | """ 108 | 109 | profile.key = """ 110 | ${KEY} 111 | """ 112 | 113 | """ 114 | # auto-generated lamda OpenVPN prop, CN=${CLIENT} 115 | # copy lines below to properties.local to let openvpn 116 | # auto connect when lamda started 117 | openvpn.proto=${PROTO} 118 | openvpn.cipher=${CIPHER} 119 | openvpn.global=false 120 | openvpn.host=${WANIP} 121 | openvpn.port=${PORT} 122 | openvpn.ca=$(echo -n "${CA}" | base64 -w 0) 123 | openvpn.cert=$(echo -n "${CERT}" | base64 -w 0) 124 | openvpn.key=$(echo -n "${KEY}" | base64 -w 0) 125 | openvpn.tls_encryption=${TLS_ENCRYPTION} 126 | openvpn.tls_key_direction=${CLIENT_KEY_DIRECTION_n} 127 | openvpn.tls_key=$(echo -n "${TA}" | base64 -w 0) 128 | openvpn.enable=true 129 | """ 130 | EOL 131 | fi 132 | fi 133 | -------------------------------------------------------------------------------- /tools/openvpn/ovpn-client-renew: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | easyrsa renew "$1" -------------------------------------------------------------------------------- /tools/openvpn/ovpn-client-revoke: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | easyrsa revoke "$1" 3 | easyrsa gen-crl -------------------------------------------------------------------------------- /tools/openvpn/ovpn-server-new: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir -p /etc/openvpn/ccd 3 | mkdir -p /etc/openvpn/easy-rsa 4 | 5 | if [ ! -f ${OVPNCONFIG} ]; then 6 | cp /root/config.ovpn ${OVPNCONFIG} 7 | fi 8 | 9 | if [ ! -f ${VARS} ]; then 10 | cp /root/vars ${VARS} 11 | fi 12 | 13 | set -ex 14 | openvpn --genkey --secret /etc/openvpn/ta.key 15 | openvpn --genkey tls-crypt-v2-server /etc/openvpn/tls-crypt-v2-server.key 16 | mkdir -p /etc/openvpn/tls-crypt-v2-client 17 | 18 | easyrsa init-pki 19 | easyrsa build-ca nopass 20 | easyrsa gen-dh 21 | easyrsa build-server-full lamda nopass 22 | easyrsa gen-crl 23 | -------------------------------------------------------------------------------- /tools/openvpn/vars: -------------------------------------------------------------------------------- 1 | # Easy-RSA 3 parameter settings 2 | 3 | # NOTE: If you installed Easy-RSA from your distro's package manager, don't edit 4 | # this file in place -- instead, you should copy the entire easy-rsa directory 5 | # to another location so future upgrades don't wipe out your changes. 6 | 7 | # HOW TO USE THIS FILE 8 | # 9 | # vars.example contains built-in examples to Easy-RSA settings. You MUST name 10 | # this file 'vars' if you want it to be used as a configuration file. If you do 11 | # not, it WILL NOT be automatically read when you call easyrsa commands. 12 | # 13 | # It is not necessary to use this config file unless you wish to change 14 | # operational defaults. These defaults should be fine for many uses without the 15 | # need to copy and edit the 'vars' file. 16 | # 17 | # All of the editable settings are shown commented and start with the command 18 | # 'set_var' -- this means any set_var command that is uncommented has been 19 | # modified by the user. If you're happy with a default, there is no need to 20 | # define the value to its default. 21 | 22 | # NOTES FOR WINDOWS USERS 23 | # 24 | # Paths for Windows *MUST* use forward slashes, or optionally double-escaped 25 | # backslashes (single forward slashes are recommended.) This means your path to 26 | # the openssl binary might look like this: 27 | # "C:/Program Files/OpenSSL-Win32/bin/openssl.exe" 28 | 29 | # DO YOUR EDITS BELOW THIS POINT 30 | 31 | # This variable is used as the base location of configuration files needed by 32 | # easyrsa. More specific variables for specific files (e.g., EASYRSA_SSL_CONF) 33 | # may override this default. 34 | # 35 | # The default value of this variable is the location of the easyrsa script 36 | # itself, which is also where the configuration files are located in the 37 | # easy-rsa tree. 38 | 39 | set_var EASYRSA "/etc/openvpn/easy-rsa" 40 | 41 | # If your OpenSSL command is not in the system PATH, you will need to define the 42 | # path to it here. Normally this means a full path to the executable, otherwise 43 | # you could have left it undefined here and the shown default would be used. 44 | # 45 | # Windows users, remember to use paths with forward-slashes (or escaped 46 | # back-slashes.) Windows users should declare the full path to the openssl 47 | # binary here if it is not in their system PATH. 48 | 49 | set_var EASYRSA_OPENSSL "openssl" 50 | # 51 | # This sample is in Windows syntax -- edit it for your path if not using PATH: 52 | #set_var EASYRSA_OPENSSL "C:/Program Files/OpenSSL-Win32/bin/openssl.exe" 53 | 54 | # Edit this variable to point to your soon-to-be-created key directory. By 55 | # default, this will be "$PWD/pki" (i.e. the "pki" subdirectory of the 56 | # directory you are currently in). 57 | # 58 | # WARNING: init-pki will do a rm -rf on this directory so make sure you define 59 | # it correctly! (Interactive mode will prompt before acting.) 60 | 61 | set_var EASYRSA_PKI "/etc/openvpn/easy-rsa/pki" 62 | 63 | # Define directory for temporary subdirectories. 64 | 65 | set_var EASYRSA_TEMP_DIR "$EASYRSA_PKI" 66 | 67 | # Define X509 DN mode. 68 | # This is used to adjust what elements are included in the Subject field as the DN 69 | # (this is the "Distinguished Name.") 70 | # Note that in cn_only mode the Organizational fields further below aren't used. 71 | # 72 | # Choices are: 73 | # cn_only - use just a CN value 74 | # org - use the "traditional" Country/Province/City/Org/OU/email/CN format 75 | 76 | set_var EASYRSA_DN "cn_only" 77 | 78 | # Organizational fields (used with 'org' mode and ignored in 'cn_only' mode.) 79 | # These are the default values for fields which will be placed in the 80 | # certificate. Don't leave any of these fields blank, although interactively 81 | # you may omit any specific field by typing the "." symbol (not valid for 82 | # email.) 83 | 84 | set_var EASYRSA_REQ_COUNTRY "" 85 | set_var EASYRSA_REQ_PROVINCE "" 86 | set_var EASYRSA_REQ_CITY "" 87 | set_var EASYRSA_REQ_ORG "" 88 | set_var EASYRSA_REQ_OU "" 89 | set_var EASYRSA_REQ_EMAIL "" 90 | 91 | # Choose a size in bits for your keypairs. The recommended value is 2048. Using 92 | # 2048-bit keys is considered more than sufficient for many years into the 93 | # future. Larger keysizes will slow down TLS negotiation and make key/DH param 94 | # generation take much longer. Values up to 4096 should be accepted by most 95 | # software. Only used when the crypto alg is rsa (see below.) 96 | 97 | set_var EASYRSA_KEY_SIZE 2048 98 | 99 | # The default crypto mode is rsa; ec can enable elliptic curve support. 100 | # Note that not all software supports ECC, so use care when enabling it. 101 | # Choices for crypto alg are: (each in lower-case) 102 | # * rsa 103 | # * ec 104 | # * ed 105 | 106 | #set_var EASYRSA_ALGO rsa 107 | 108 | # Define the named curve, used in ec & ed modes: 109 | 110 | #set_var EASYRSA_CURVE secp384r1 111 | 112 | # In how many days should the root CA key expire? 113 | 114 | # 50 years 115 | set_var EASYRSA_CA_EXPIRE 18250 116 | 117 | # In how many days should certificates expire? 118 | 119 | set_var EASYRSA_CERT_EXPIRE 3650 120 | 121 | # How many days until the next CRL publish date? Note that the CRL can still be 122 | # parsed after this timeframe passes. It is only used for an expected next 123 | # publication date. 124 | set_var EASYRSA_CRL_DAYS 3650 125 | 126 | # How many days before its expiration date a certificate is allowed to be 127 | # renewed? 128 | set_var EASYRSA_CERT_RENEW 30 129 | 130 | # Random serial numbers by default, set to no for the old incremental serial numbers 131 | # 132 | #set_var EASYRSA_RAND_SN "yes" 133 | 134 | # Support deprecated "Netscape" extensions? (choices "yes" or "no".) The default 135 | # is "no" to discourage use of deprecated extensions. If you require this 136 | # feature to use with --ns-cert-type, set this to "yes" here. This support 137 | # should be replaced with the more modern --remote-cert-tls feature. If you do 138 | # not use --ns-cert-type in your configs, it is safe (and recommended) to leave 139 | # this defined to "no". When set to "yes", server-signed certs get the 140 | # nsCertType=server attribute, and also get any NS_COMMENT defined below in the 141 | # nsComment field. 142 | 143 | #set_var EASYRSA_NS_SUPPORT "no" 144 | 145 | # When NS_SUPPORT is set to "yes", this field is added as the nsComment field. 146 | # Set this blank to omit it. With NS_SUPPORT set to "no" this field is ignored. 147 | 148 | #set_var EASYRSA_NS_COMMENT "Easy-RSA Generated Certificate" 149 | 150 | # A temp file used to stage cert extensions during signing. The default should 151 | # be fine for most users; however, some users might want an alternative under a 152 | # RAM-based FS, such as /dev/shm or /tmp on some systems. 153 | 154 | #set_var EASYRSA_TEMP_FILE "$EASYRSA_PKI/extensions.temp" 155 | 156 | # !! 157 | # NOTE: ADVANCED OPTIONS BELOW THIS POINT 158 | # PLAY WITH THEM AT YOUR OWN RISK 159 | # !! 160 | 161 | # Broken shell command aliases: If you have a largely broken shell that is 162 | # missing any of these POSIX-required commands used by Easy-RSA, you will need 163 | # to define an alias to the proper path for the command. The symptom will be 164 | # some form of a 'command not found' error from your shell. This means your 165 | # shell is BROKEN, but you can hack around it here if you really need. These 166 | # shown values are not defaults: it is up to you to know what you're doing if 167 | # you touch these. 168 | # 169 | #alias awk="/alt/bin/awk" 170 | #alias cat="/alt/bin/cat" 171 | 172 | # X509 extensions directory: 173 | # If you want to customize the X509 extensions used, set the directory to look 174 | # for extensions here. Each cert type you sign must have a matching filename, 175 | # and an optional file named 'COMMON' is included first when present. Note that 176 | # when undefined here, default behaviour is to look in $EASYRSA_PKI first, then 177 | # fallback to $EASYRSA for the 'x509-types' dir. You may override this 178 | # detection with an explicit dir here. 179 | # 180 | set_var EASYRSA_EXT_DIR "/usr/share/easy-rsa/x509-types" 181 | 182 | # If you want to generate KDC certificates, you need to set the realm here. 183 | #set_var EASYRSA_KDC_REALM "CHANGEME.EXAMPLE.COM" 184 | 185 | # OpenSSL config file: 186 | # If you need to use a specific openssl config file, you can reference it here. 187 | # Normally this file is auto-detected from a file named openssl-easyrsa.cnf from the 188 | # EASYRSA_PKI or EASYRSA dir (in that order.) NOTE that this file is Easy-RSA 189 | # specific and you cannot just use a standard config file, so this is an 190 | # advanced feature. 191 | 192 | set_var EASYRSA_SSL_CONF "/usr/share/easy-rsa/openssl-easyrsa.cnf" 193 | 194 | # Default CN: 195 | # This is best left alone. Interactively you will set this manually, and BATCH 196 | # callers are expected to set this themselves. 197 | 198 | set_var EASYRSA_REQ_CN "LAMDA" 199 | 200 | # Cryptographic digest to use. 201 | # Do not change this default unless you understand the security implications. 202 | # Valid choices include: md5, sha1, sha256, sha224, sha384, sha512 203 | 204 | #set_var EASYRSA_DIGEST "sha256" 205 | 206 | # Batch mode. Leave this disabled unless you intend to call Easy-RSA explicitly 207 | # in batch mode without any user input, confirmation on dangerous operations, 208 | # or most output. Setting this to any non-blank string enables batch mode. 209 | 210 | set_var EASYRSA_BATCH "yes" 211 | -------------------------------------------------------------------------------- /tools/paddle_ocr_http_api.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # THIS IS EXAMPLE HTTP OCR BACKEND, 3 | # DO NOT USE IN PRODUCTION 4 | import uvicorn 5 | import asyncio 6 | import paddle as paddle 7 | from paddleocr import PaddleOCR 8 | from fastapi import FastAPI, Request 9 | 10 | app = FastAPI() 11 | 12 | 13 | @app.post("/ocr") 14 | async def ocr(request: Request): 15 | image = await request.body() 16 | r = await asyncio.to_thread(ocr.ocr, image) 17 | n = bool(r and r[0] and type(r[0][-1])==float) 18 | result = (r if n else r[0]) or [] 19 | output = [[n[0], n[1][0], n[1][1]] for n in result] 20 | return output 21 | 22 | 23 | if __name__ == "__main__": 24 | ocr = PaddleOCR(use_gpu=False, drop_score=0.85, 25 | use_space_char=True) 26 | uvicorn.run(app, host="0.0.0.0", port=8000) -------------------------------------------------------------------------------- /tools/requirements.txt: -------------------------------------------------------------------------------- 1 | mitmproxy>=9.0.0,<=10.2.0 2 | dnspython 3 | httpx[socks]<0.28.0 4 | packaging 5 | Pillow -------------------------------------------------------------------------------- /tools/root.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIClDCCAXwCAQAwDQYJKoZIhvcNAQELBQAwEDEOMAwGA1UECgwFTEFNREEwHhcN 3 | MjAwMTAxMDAwMDAxWhcNMjkxMjI5MDAwMDAxWjAQMQ4wDAYDVQQKDAVMQU1EQTCC 4 | ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALnqfBZvrGZaqgk5msCRRpPz 5 | p/+464jBknlmTKetOckDTUq8V6fH/2Gfb6HjjoD5pkCtD5mSKkaHNhuxLXsFfEfc 6 | Klmnn3ZpjyNOHEA/iAO2DyEYa08xSevM7WojbF7cNj5/DYg7eb0i0+//bBlh8nlO 7 | ghSUhCTM5PCofLDU8sVXuYAiGU6UzBrIC0vHEltDkiJVLpcCtsKjEZOskPdAc7u6 8 | /aA0P5GonZ5UkRDYpa+jeJUabqWZQQEgtmvjlmUUiXwu0jRnj1n0T3fPQD3gA+LI 9 | vAE9vgvpY5XQj6otpBvsZ3MJJNKcUMQu1zOANTzO18TlA8KoBNsBy8Z9DQZKXF8C 10 | AwEAATANBgkqhkiG9w0BAQsFAAOCAQEAeGn/NyqIRI/0AGqvHP97KtQ76Tj6achb 11 | 30LIXWp+YHUaMeAVjd2Z7jSQp5mZZFl+k1fb337IeaGXofVI21eK52QX2teNoBkA 12 | /V/O1Hu35/+aiz0xsdD6wWvwo4Fy1jlmaeJhwdQacBlDGFA2jFJxuEpahfxZvUsb 13 | 3j5zU0WKTUCfEDgXFwBw12xku/7TMdCEbRsYaZ3zFTC226lQbUDN7weqFwSD+tB6 14 | RuhIxe8+cFwAsAWHClerKgZnr3t5QF078pW2GHy8CsJ7V3MZT5lZ43lS5NIB9JzZ 15 | SYxZ/izhRyh5qR73uAgsJaL56Bj+cQqnoTqhLZVl7J+M6WhWKzojsA== 16 | -----END CERTIFICATE----- 17 | -------------------------------------------------------------------------------- /tools/root.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC56nwWb6xmWqoJ 3 | OZrAkUaT86f/uOuIwZJ5ZkynrTnJA01KvFenx/9hn2+h446A+aZArQ+ZkipGhzYb 4 | sS17BXxH3CpZp592aY8jThxAP4gDtg8hGGtPMUnrzO1qI2xe3DY+fw2IO3m9ItPv 5 | /2wZYfJ5ToIUlIQkzOTwqHyw1PLFV7mAIhlOlMwayAtLxxJbQ5IiVS6XArbCoxGT 6 | rJD3QHO7uv2gND+RqJ2eVJEQ2KWvo3iVGm6lmUEBILZr45ZlFIl8LtI0Z49Z9E93 7 | z0A94APiyLwBPb4L6WOV0I+qLaQb7GdzCSTSnFDELtczgDU8ztfE5QPCqATbAcvG 8 | fQ0GSlxfAgMBAAECggEAUVmJj3Ww7Z6JXXz/ung29kE9BxfetBnjYkyBiTMyoELa 9 | HLQZ9Nf95rURbzh3n/bdKNqxA0UiS3cZlXdrC7QERBtRyqYej/0zfULN+Mzz0o/k 10 | wdoCBoZuLogecH1si3t3HtSQUsaXh8uICjFtFxQ1OaBBKgksYz/mg2luGiAr1G5F 11 | yzCjKOpPo9rjgka0OMx5PnHjd9d6rf2ckB9VlLxxEVaYoGnXJTAe+FU0sWIFIfZY 12 | E1kknQ9F+MegGEZyE/r8kRUm4+81WWPChwWlXT8TpHp1HXtI0j9PY4vlWjDBB2cO 13 | 6w8nPiHT3Hy0BYpa3Vee7a9kHljLa3ZBgq2DMnoaqQKBgQDVGKAuRbQ7CXRinRou 14 | Lh/iDwzdWLVfIB/EpClZqhIQt+YcuqKixvBtlksRewJfC7lbSM5rcNYp+NFq2z1F 15 | ol6EezmVcylAfHf9jHJrY37uR7ilwJnl7FMqNAw6hwRUm2Zhj+PgWPCVO8VpRBFE 16 | j80fLhD1rrD3TqBBvQGTs6h2OQKBgQDfWPBgFTJsgmp6XLsgLiahAKVVtHQk4lXI 17 | 7WytdNgrf7U9rT9hGsRc5TJ/BagnUKRe3u/oIxnFw3QgFg1vPRWGxd8ckA3F4Z9V 18 | RgMUJcvnSDoLNctd19sXclC7KAIEAg5VZEEPPXFrmudlbO7AVDZ2/nqWsVxbJ4ie 19 | PolKMkOnVwKBgHhBRWPXgjYux7c+4R9eeC+iPqhK/0+HWWYnHg6zoy48GWftCwrB 20 | Kb0uK37Z5CSvARM6qwKG0tUszUF4J8O8NYqd34kvTABQPYagU5G2vFLLtrATWMYf 21 | 727JoH0G5LK6X7R+9yIMDviommclOnlujVsjK/75bnShsl5mwxUPNepBAoGBAIW0 22 | V4odhmchF58S3k7gce2WVmPdOF5QRGyZfaLFPRelRxmaGkQGYyD9cGJMP6LxisTk 23 | jxgX0zjpzh3bNcWu+rEIyYzuy9/3Now08mjgS5W0TlMhrBIMw7Lgk2XHCJXfqTcD 24 | YlM+RCTXwcidErx+bXCE3VxS5ugG3all5IhPWOLXAoGBAJ+qUklRlmmTds7RhpeH 25 | dX8UlAW8/AtJfTfWoA5EPLX8jZp2v8FSSKk4OME95jVS6G8mAevHjdpaw1iwrxDX 26 | szwh9hcWxT4i2HrAwYMI2HM0HqEIjgCx+1kzDrcdsU96rLDhbaRoN9JBMh3yHI05 27 | H0KRgTsIBx2u3aMQAe3AHZOd 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /tools/rsync.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | [ $# -lt 2 ] && exit 1 3 | DEFAULT_ID_RSA=$(mktemp) 4 | PORT=${PORT:-65000} 5 | case "$1" in 6 | *':'*) 7 | p1=root@$1 8 | p2=$2 9 | ;; 10 | *) 11 | p1=$1 12 | p2=root@$2 13 | ;; 14 | esac 15 | umask 077 16 | if [ ! -f "${CERTIFICATE}" ]; then 17 | # this is the default id_rsa for ssh service 18 | cat <$DEFAULT_ID_RSA 19 | -----BEGIN RSA PRIVATE KEY----- 20 | MIIEogIBAAKCAQEA4QHmY32OT+F+maERMn1cvBRuIOIXH9yOALG+GMCngtjRJzSR 21 | n09dInmXE+PjiAqNRWvknVEjFywv0v1v/H2qSRJKR/togPgySjiABhigqDHdirNd 22 | Dh63oN2e+d0yythoLzsQrH5BSVtw05Atpkr7bW4KdfMveWuddvDACnQ3mvCXq50X 23 | IK3cOlmHXwcJrX55BhEXxgHIqw0upf0A7DC3Afz5xjOA6+K/O2EzZIIJ+sWw7/Ko 24 | 5+3m98Et0zwcxe20uNxzYf7JSMu3490YNckLiQcDrZVRUXNS70HO9HWCXKdjFJPi 25 | GgPtKUQNHjChwzSCQQGzqitXdwa60i9Sy1U09wIBIwKCAQAzbiYIHLLQbg5PAD5x 26 | 8MS9Rn+SfNIV6UUHeRWCACZJyyh9/WMdGXRfpsNyQreqEQpZArfpcaGe5YdGK0zL 27 | /3dhKMCFe0sWKhofl+K/kJnAC2XWj2W6FaZQp69PDfz7KiZxMhJwkeMJc/yIIPR9 28 | x/70cOxyuz4NH+l6Rag8510qujhxn6lGc1+ZNHGeAYmUD7wFz9/QYDZU9C0YcylA 29 | 2+Q5woU3L4b3y3JKqB6/dnsP9uF7R5KBR+qiqOwVm0nhvVU5uwbpQwTXeklopXyN 30 | rI/NeYcsDoEyb8NquVXX/GkOgY0FhqblGUR9kSdTLHq6VamelHc+dczZgMxcsq1c 31 | mnnLAoGBAP2FPssFpHJRhSr38Fq5A7mEjQeiPq2WgYV7kCpJT5F5OymcCCETIjEH 32 | 4pTk5zCWUuIBx5LlzSa0XnQSYb0100ZzvDgfm1NPmqdkpPwkkbh2xyoHYTTPJ3WG 33 | TDur8Qyi83NteveszO1TCAGBTe3zN+2ov9qzl5Y7QHF94GVFDo4NAoGBAOM1Q8eG 34 | 0KeqjutTz/UMtejoFpz0Hi1g32PfdQInHx8MDslYu3Fcpnos3xf59H7+mrRy0fUM 35 | hh27v7DiUvxUfhlojf0F3kDKeg9VZBslZF3vTCpFdKdFouZ2Cru3lCoaPSau69BC 36 | 6HQw4P+RABrgxc6CeE9FUGEEMss+wTcRItITAoGBAO8ImkpkZ9mAD9gOV6X+5kEz 37 | 1W2Y+USVOEqns9AZPGSW4AKpDvqdAvsHbzvtxAk9RtUXnumW118B1WYf9cEG3SUr 38 | SxBYUJ8B6ZaDdvxc/mwYOCBQGdK0sCz692t2OwvqGL1J95kQo/W0r8bnoT9wSqzg 39 | 72fN5rI33azVxPHExJSPAoGAGfd1deOFj4E057HOn6muY8LAwXr8InF4nbMjULQD 40 | joUJARF0gfv1xNHtnFcUoMyj912UVoUWpE/4poBD/5SgsnJZXr7XkmBIdsfuLvz1 41 | hxQItF+1j3WsN5h2QVbPGsErj2RyuLcwgk66oN1fGQO+1cXEm1hg9SUNHorUQM7C 42 | JqMCgYEAofxXJ8dOWUaFIHmKLE7Y+0+i3D1yXVIyu/puuaQGbNFHxjcJ9ZdubhLN 43 | IyzJvngtM7mC90FtUETxvErMGdTzFeKtSKBZsJ8BiLCszRCEuJf5RX6uNrFUQ2pT 44 | PEmns088Gs4KUDwjTG0zQtj3pNc5zDynDMpFKp96spefqLJqw3s= 45 | -----END RSA PRIVATE KEY----- 46 | EOL 47 | else 48 | DEFAULT_ID_RSA=$CERTIFICATE 49 | fi 50 | exec rsync -avz ${@:3} -e "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=ERROR -i $DEFAULT_ID_RSA -p $PORT" $p1 $p2 51 | -------------------------------------------------------------------------------- /tools/scp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | [ $# -lt 2 ] && exit 1 3 | DEFAULT_ID_RSA=$(mktemp) 4 | PORT=${PORT:-65000} 5 | case "$1" in 6 | *':'*) 7 | p1=root@$1 8 | p2=$2 9 | ;; 10 | *) 11 | p1=$1 12 | p2=root@$2 13 | ;; 14 | esac 15 | umask 077 16 | if [ ! -f "${CERTIFICATE}" ]; then 17 | # this is the default id_rsa for ssh service 18 | cat <$DEFAULT_ID_RSA 19 | -----BEGIN RSA PRIVATE KEY----- 20 | MIIEogIBAAKCAQEA4QHmY32OT+F+maERMn1cvBRuIOIXH9yOALG+GMCngtjRJzSR 21 | n09dInmXE+PjiAqNRWvknVEjFywv0v1v/H2qSRJKR/togPgySjiABhigqDHdirNd 22 | Dh63oN2e+d0yythoLzsQrH5BSVtw05Atpkr7bW4KdfMveWuddvDACnQ3mvCXq50X 23 | IK3cOlmHXwcJrX55BhEXxgHIqw0upf0A7DC3Afz5xjOA6+K/O2EzZIIJ+sWw7/Ko 24 | 5+3m98Et0zwcxe20uNxzYf7JSMu3490YNckLiQcDrZVRUXNS70HO9HWCXKdjFJPi 25 | GgPtKUQNHjChwzSCQQGzqitXdwa60i9Sy1U09wIBIwKCAQAzbiYIHLLQbg5PAD5x 26 | 8MS9Rn+SfNIV6UUHeRWCACZJyyh9/WMdGXRfpsNyQreqEQpZArfpcaGe5YdGK0zL 27 | /3dhKMCFe0sWKhofl+K/kJnAC2XWj2W6FaZQp69PDfz7KiZxMhJwkeMJc/yIIPR9 28 | x/70cOxyuz4NH+l6Rag8510qujhxn6lGc1+ZNHGeAYmUD7wFz9/QYDZU9C0YcylA 29 | 2+Q5woU3L4b3y3JKqB6/dnsP9uF7R5KBR+qiqOwVm0nhvVU5uwbpQwTXeklopXyN 30 | rI/NeYcsDoEyb8NquVXX/GkOgY0FhqblGUR9kSdTLHq6VamelHc+dczZgMxcsq1c 31 | mnnLAoGBAP2FPssFpHJRhSr38Fq5A7mEjQeiPq2WgYV7kCpJT5F5OymcCCETIjEH 32 | 4pTk5zCWUuIBx5LlzSa0XnQSYb0100ZzvDgfm1NPmqdkpPwkkbh2xyoHYTTPJ3WG 33 | TDur8Qyi83NteveszO1TCAGBTe3zN+2ov9qzl5Y7QHF94GVFDo4NAoGBAOM1Q8eG 34 | 0KeqjutTz/UMtejoFpz0Hi1g32PfdQInHx8MDslYu3Fcpnos3xf59H7+mrRy0fUM 35 | hh27v7DiUvxUfhlojf0F3kDKeg9VZBslZF3vTCpFdKdFouZ2Cru3lCoaPSau69BC 36 | 6HQw4P+RABrgxc6CeE9FUGEEMss+wTcRItITAoGBAO8ImkpkZ9mAD9gOV6X+5kEz 37 | 1W2Y+USVOEqns9AZPGSW4AKpDvqdAvsHbzvtxAk9RtUXnumW118B1WYf9cEG3SUr 38 | SxBYUJ8B6ZaDdvxc/mwYOCBQGdK0sCz692t2OwvqGL1J95kQo/W0r8bnoT9wSqzg 39 | 72fN5rI33azVxPHExJSPAoGAGfd1deOFj4E057HOn6muY8LAwXr8InF4nbMjULQD 40 | joUJARF0gfv1xNHtnFcUoMyj912UVoUWpE/4poBD/5SgsnJZXr7XkmBIdsfuLvz1 41 | hxQItF+1j3WsN5h2QVbPGsErj2RyuLcwgk66oN1fGQO+1cXEm1hg9SUNHorUQM7C 42 | JqMCgYEAofxXJ8dOWUaFIHmKLE7Y+0+i3D1yXVIyu/puuaQGbNFHxjcJ9ZdubhLN 43 | IyzJvngtM7mC90FtUETxvErMGdTzFeKtSKBZsJ8BiLCszRCEuJf5RX6uNrFUQ2pT 44 | PEmns088Gs4KUDwjTG0zQtj3pNc5zDynDMpFKp96spefqLJqw3s= 45 | -----END RSA PRIVATE KEY----- 46 | EOL 47 | else 48 | DEFAULT_ID_RSA=$CERTIFICATE 49 | fi 50 | ssh-add $DEFAULT_ID_RSA >/dev/null 2>&1 || true 51 | exec scp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no \ 52 | -o LogLevel=ERROR -i $DEFAULT_ID_RSA -P $PORT -pr $p1 $p2 53 | -------------------------------------------------------------------------------- /tools/socks5/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.15 2 | # this will produce large image but IDC 3 | LABEL maintainer="rev1si0n " 4 | 5 | ENV SOURCESMIRROR=mirrors.ustc.edu.cn 6 | RUN sed -i "s/dl-cdn.alpinelinux.org/${SOURCESMIRROR}/g" /etc/apk/repositories 7 | 8 | COPY entry /usr/bin 9 | 10 | RUN apk add bash make g++ git 11 | 12 | RUN mkdir -p /tmp/workdir 13 | WORKDIR /tmp/workdir 14 | 15 | RUN wget https://www.inet.no/dante/files/dante-1.4.3.tar.gz -O - | tar -xz 16 | WORKDIR /tmp/workdir/dante-1.4.3 17 | 18 | ENV ac_cv_func_sched_setscheduler=no 19 | RUN ./configure --disable-client && make -j $(nproc) 20 | RUN cp sockd/sockd /usr/bin 21 | 22 | RUN rm -rf /tmp/workdir 23 | 24 | WORKDIR / 25 | 26 | EXPOSE 1080/tcp 1080/udp 50000:55000/udp 27 | ENTRYPOINT ["entry"] 28 | -------------------------------------------------------------------------------- /tools/socks5/entry: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | LOGIN=${LOGIN:-lamda} 3 | PWD=${PASSWORD:-lamda} 4 | UDPRANGE=${UDPRANGE:-50000-55000} 5 | BIND=${BIND:-0.0.0.0} 6 | PORT=${PORT:-1080} 7 | 8 | # the default output interface 9 | DEFAULT_DEV=$(ip route | awk '/default/ { print $5 }') 10 | DEV=${DEV:-"${DEFAULT_DEV}"} 11 | 12 | deluser --remove-home ${LOGIN} 2>/dev/null 13 | adduser -D -H -s /bin/false ${LOGIN} 2>/dev/null 14 | echo "${LOGIN}:${PWD}" | chpasswd 2>/dev/null 15 | 16 | echo "SOCKS5 LOGIN: ${LOGIN}" 17 | echo "SOCKS5 PASSWORD: ${PWD}" 18 | 19 | cat </etc/danted.conf 20 | internal: ${BIND} port = ${PORT} 21 | external: ${DEV} 22 | 23 | clientmethod: none 24 | socksmethod: username 25 | 26 | user.privileged: root 27 | user.unprivileged: nobody 28 | 29 | timeout.tcp_fin_wait: 15 30 | timeout.negotiate: 15 31 | timeout.connect: 15 32 | 33 | logoutput: /proc/self/fd/2 34 | 35 | socks pass { 36 | from: 0.0.0.0/0 to: 0.0.0.0/0 37 | command: bind connect udpassociate 38 | udp.portrange: ${UDPRANGE} 39 | log: error connect 40 | } 41 | 42 | socks pass { 43 | from: 0.0.0.0/0 to: 0.0.0.0/0 44 | command: bindreply udpreply 45 | udp.portrange: ${UDPRANGE} 46 | log: error connect 47 | } 48 | 49 | client pass { 50 | from: 0.0.0.0/0 to: 0.0.0.0/0 51 | log: error 52 | } 53 | EOL 54 | 55 | exec sockd -f /etc/danted.conf -------------------------------------------------------------------------------- /tools/ssh.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | TARGET=${1:-localhost} 3 | PORT=${PORT:-65000} 4 | DEFAULT_ID_RSA=$(mktemp) 5 | 6 | umask 077 7 | if [ ! -f "${CERTIFICATE}" ]; then 8 | # this is the default id_rsa for ssh service 9 | cat <$DEFAULT_ID_RSA 10 | -----BEGIN RSA PRIVATE KEY----- 11 | MIIEogIBAAKCAQEA4QHmY32OT+F+maERMn1cvBRuIOIXH9yOALG+GMCngtjRJzSR 12 | n09dInmXE+PjiAqNRWvknVEjFywv0v1v/H2qSRJKR/togPgySjiABhigqDHdirNd 13 | Dh63oN2e+d0yythoLzsQrH5BSVtw05Atpkr7bW4KdfMveWuddvDACnQ3mvCXq50X 14 | IK3cOlmHXwcJrX55BhEXxgHIqw0upf0A7DC3Afz5xjOA6+K/O2EzZIIJ+sWw7/Ko 15 | 5+3m98Et0zwcxe20uNxzYf7JSMu3490YNckLiQcDrZVRUXNS70HO9HWCXKdjFJPi 16 | GgPtKUQNHjChwzSCQQGzqitXdwa60i9Sy1U09wIBIwKCAQAzbiYIHLLQbg5PAD5x 17 | 8MS9Rn+SfNIV6UUHeRWCACZJyyh9/WMdGXRfpsNyQreqEQpZArfpcaGe5YdGK0zL 18 | /3dhKMCFe0sWKhofl+K/kJnAC2XWj2W6FaZQp69PDfz7KiZxMhJwkeMJc/yIIPR9 19 | x/70cOxyuz4NH+l6Rag8510qujhxn6lGc1+ZNHGeAYmUD7wFz9/QYDZU9C0YcylA 20 | 2+Q5woU3L4b3y3JKqB6/dnsP9uF7R5KBR+qiqOwVm0nhvVU5uwbpQwTXeklopXyN 21 | rI/NeYcsDoEyb8NquVXX/GkOgY0FhqblGUR9kSdTLHq6VamelHc+dczZgMxcsq1c 22 | mnnLAoGBAP2FPssFpHJRhSr38Fq5A7mEjQeiPq2WgYV7kCpJT5F5OymcCCETIjEH 23 | 4pTk5zCWUuIBx5LlzSa0XnQSYb0100ZzvDgfm1NPmqdkpPwkkbh2xyoHYTTPJ3WG 24 | TDur8Qyi83NteveszO1TCAGBTe3zN+2ov9qzl5Y7QHF94GVFDo4NAoGBAOM1Q8eG 25 | 0KeqjutTz/UMtejoFpz0Hi1g32PfdQInHx8MDslYu3Fcpnos3xf59H7+mrRy0fUM 26 | hh27v7DiUvxUfhlojf0F3kDKeg9VZBslZF3vTCpFdKdFouZ2Cru3lCoaPSau69BC 27 | 6HQw4P+RABrgxc6CeE9FUGEEMss+wTcRItITAoGBAO8ImkpkZ9mAD9gOV6X+5kEz 28 | 1W2Y+USVOEqns9AZPGSW4AKpDvqdAvsHbzvtxAk9RtUXnumW118B1WYf9cEG3SUr 29 | SxBYUJ8B6ZaDdvxc/mwYOCBQGdK0sCz692t2OwvqGL1J95kQo/W0r8bnoT9wSqzg 30 | 72fN5rI33azVxPHExJSPAoGAGfd1deOFj4E057HOn6muY8LAwXr8InF4nbMjULQD 31 | joUJARF0gfv1xNHtnFcUoMyj912UVoUWpE/4poBD/5SgsnJZXr7XkmBIdsfuLvz1 32 | hxQItF+1j3WsN5h2QVbPGsErj2RyuLcwgk66oN1fGQO+1cXEm1hg9SUNHorUQM7C 33 | JqMCgYEAofxXJ8dOWUaFIHmKLE7Y+0+i3D1yXVIyu/puuaQGbNFHxjcJ9ZdubhLN 34 | IyzJvngtM7mC90FtUETxvErMGdTzFeKtSKBZsJ8BiLCszRCEuJf5RX6uNrFUQ2pT 35 | PEmns088Gs4KUDwjTG0zQtj3pNc5zDynDMpFKp96spefqLJqw3s= 36 | -----END RSA PRIVATE KEY----- 37 | EOL 38 | else 39 | DEFAULT_ID_RSA=$CERTIFICATE 40 | fi 41 | ssh-add $DEFAULT_ID_RSA >/dev/null 2>&1 || true 42 | exec ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no \ 43 | -o LogLevel=ERROR -i $DEFAULT_ID_RSA -p $PORT root@$TARGET ${@:2} 44 | -------------------------------------------------------------------------------- /tools/startmitm.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firerpa/lamda/fbd5e6e0ec602df622130c53abb4e87bd783e442/tools/startmitm.ico -------------------------------------------------------------------------------- /tools/startmitm.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright 2024 rev1si0n (lamda.devel@gmail.com). All rights reserved. 3 | # 4 | # Distributed under MIT license. 5 | # See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 6 | #encoding=utf-8 7 | import os 8 | import re 9 | import sys 10 | import time 11 | import logging 12 | import subprocess 13 | import argparse 14 | import uuid 15 | import asyncio 16 | import threading 17 | import dns.message 18 | import dns.query 19 | import httpx 20 | 21 | from socket import * 22 | from random import randint 23 | from multiprocessing import Process 24 | from urllib.parse import urlparse 25 | from functools import partial 26 | 27 | from mitmproxy.certs import CertStore 28 | from mitmproxy.tools.main import mitmweb as web 29 | from mitmproxy.options import CONF_DIR, CONF_BASENAME, KEY_SIZE 30 | from mitmproxy.version import VERSION 31 | 32 | from packaging.version import parse as ver 33 | 34 | from lamda import __version__ 35 | from lamda.client import * 36 | 37 | 38 | serial = None 39 | cleaning = False 40 | def cleanup(*args, **kwargs): 41 | global cleaning 42 | if cleaning is True: 43 | return 44 | cleaning = True 45 | log ("uninstall certificate") 46 | d.uninstall_ca_certificate(ca) 47 | log ("disable proxy") 48 | d.stop_gproxy() 49 | os._exit (0) 50 | 51 | 52 | def is_doh(server): 53 | u = urlparse(server) 54 | return u.scheme in ("http", "https") 55 | 56 | 57 | def fmt_rdns(dns, lport): 58 | return "reverse:dns://{}@{}".format(dns, lport) 59 | 60 | 61 | class DOHProxiedProtocol(asyncio.Protocol): 62 | def __init__(self, loop, server, proxy): 63 | self.server = server 64 | log ("using DOH: {}".format(server)) 65 | self.client = httpx.Client(proxies=proxy) 66 | self.loop = loop 67 | def datagram_received(self, pkt, addr): 68 | self.loop.create_task(self.handle(pkt, addr)) 69 | def connection_made(self, transport): 70 | self.transport = transport 71 | async def handle(self, pkt, addr): 72 | res = await self.loop.run_in_executor(None, 73 | self.dns_query, pkt) 74 | self.transport.sendto(res, addr) 75 | def dns_query(self, pkt): 76 | res = dns.message.from_wire(pkt) 77 | res = dns.query.https(res, self.server, 78 | session=self.client) 79 | return res.to_wire() 80 | @classmethod 81 | def start(cls, *args, **kwargs): 82 | dns = threading.Thread(target=cls._start, 83 | args=args, kwargs=kwargs) 84 | dns.daemon = True 85 | dns.start() 86 | @classmethod 87 | def _start(cls, bind, port, upstream, proxy=None): 88 | loop = asyncio.new_event_loop() 89 | factory = partial(cls, loop, upstream, proxy) 90 | coro = loop.create_datagram_endpoint(factory, 91 | local_addr=(bind, port)) 92 | loop.run_until_complete(coro) 93 | loop.run_forever() 94 | 95 | 96 | def setup_dns_upstream(args): 97 | port = randint(28080, 58080) 98 | dns = "{}:{}".format("127.0.0.1", port) 99 | DOHProxiedProtocol.start( 100 | "127.0.0.1", 101 | port, 102 | args.dns, 103 | args.upstream) 104 | args.dns = fmt_rdns(dns, proxy) 105 | 106 | 107 | def add_server(command, spec): 108 | spec and command.append("--mode") 109 | spec and command.append(spec) 110 | 111 | 112 | def add_upstream(args, ext): 113 | u = urlparse(args.upstream) 114 | upstream = "upstream:{}://{}:{}".format(u.scheme, 115 | u.hostname, 116 | u.port) 117 | args.mode = upstream 118 | cred = "{}:{}".format(u.username, u.password) 119 | u.username and ext.append("--upstream-auth") 120 | u.username and ext.append(cred) 121 | 122 | 123 | def log(*args): 124 | print (time.ctime(), *args) 125 | 126 | 127 | def die(*args): 128 | print (time.ctime(), *args) 129 | sys.exit (1) 130 | 131 | 132 | def adb(*args): 133 | command = ["adb"] 134 | if serial is not None: 135 | command.extend(["-s", serial]) 136 | command.extend(args) 137 | log (" ".join(command)) 138 | proc = subprocess.Popen(command) 139 | return proc 140 | 141 | 142 | def adb_tcp(action, aport, bport): 143 | p = adb(action, "tcp:{}".format(aport), 144 | "tcp:{}".format(bport)) 145 | return p 146 | 147 | 148 | def reverse(aport, bport): 149 | return adb_tcp("reverse", aport, bport) 150 | 151 | 152 | def forward(aport, bport): 153 | return adb_tcp("forward", aport, bport) 154 | 155 | 156 | def get_default_interface_ip_imp(target): 157 | s = socket(AF_INET, SOCK_DGRAM) 158 | s.connect(( target, lamda )) 159 | return s.getsockname()[0] 160 | 161 | 162 | def get_default_interface_ip(target): 163 | default = get_default_interface_ip_imp(target) 164 | ip = os.environ.get("LANIP", default) 165 | return ip 166 | 167 | 168 | print (r" __ __ .__ __ ") 169 | print (r" _______/ |______ ________/ |_ _____ |__|/ |_ _____ ") 170 | print (r" / ___/\ __\__ \\_ __ \ __\ / \| \ __\/ \ ") 171 | print (r" \___ \ | | / __ \| | \/| | | Y Y \ || | | Y Y \ ") 172 | print (r" /____ > |__| (____ /__| |__| |__|_| /__||__| |__|_| / ") 173 | print (r" \/ \/ \/ \/ ") 174 | print (r" Android HTTP Traffic Capture ") 175 | print (r"%60s" % ("lamda#v%s BY firerpa" % (__version__))) 176 | 177 | 178 | pkgName = None 179 | argp = argparse.ArgumentParser() 180 | 181 | login = "lamda" 182 | psw = uuid.uuid4().hex[::3] 183 | cert = os.environ.get("CERTIFICATE") 184 | proxy = int(os.environ.get("PROXYPORT", 185 | randint(28080, 58080))) 186 | webport = randint(28080, 58080) 187 | lamda = int(os.environ.get("PORT", 188 | 65000)) 189 | 190 | argp.add_argument("device", nargs=1) 191 | mod = argp.add_mutually_exclusive_group(required=False) 192 | mod.add_argument("-m", "--mode", default="regular") 193 | mod.add_argument("--upstream", type=str, default=None) 194 | argp.add_argument("--serial", type=str, default=None) 195 | argp.add_argument("--dns", type=str, default=None) 196 | args, extras = argp.parse_known_args() 197 | serial = args.serial 198 | host = args.device[0] 199 | 200 | if ":" in host: 201 | host, pkgName = host.split(":") 202 | if args.dns and ver(VERSION) < ver("9.0.0"): 203 | log ("dns mitm needs mitmproxy>=9.0.0") 204 | sys.exit (1) 205 | 206 | server = get_default_interface_ip(host) 207 | usb = server in ("127.0.0.1", "::1") 208 | 209 | if cert: 210 | log ("ssl:", cert) 211 | if args.upstream: 212 | add_upstream(args, extras) 213 | if usb and args.dns: 214 | die ("dns mitm not available in USB mode") 215 | if usb and args.upstream: 216 | log ("dns will not sent via upstream in USB mode") 217 | if args.upstream and not args.dns: 218 | die ("dns must be set in upstream mode") 219 | if args.upstream and args.dns and not is_doh(args.dns): 220 | die ("dns must be DOH in upstream mode") 221 | if usb and forward(lamda, lamda).wait() != 0: 222 | die ("adb forward failed") 223 | if usb and reverse(proxy, proxy).wait() != 0: 224 | die ("adb forward failed") 225 | if not args.upstream and args.dns and not is_doh(args.dns): 226 | args.dns = fmt_rdns(args.dns, proxy) 227 | if args.dns and is_doh(args.dns): 228 | setup_dns_upstream(args) 229 | 230 | 231 | # 创建设备实例 232 | d = Device(host, port=lamda, 233 | certificate=cert) 234 | logger.setLevel(logging.WARN) 235 | 236 | # 拼接证书文件路径 237 | DIR = os.path.expanduser(CONF_DIR) 238 | CertStore.from_store(DIR, CONF_BASENAME, KEY_SIZE) 239 | ca = os.path.join(DIR, "mitmproxy-ca-cert.pem") 240 | 241 | log ("install cacert: %s" % ca) 242 | d.install_ca_certificate(ca) 243 | 244 | # 初始化 proxy 配置 245 | profile = GproxyProfile() 246 | profile.type = GproxyType.HTTP_CONNECT 247 | profile.nameserver = "1.1.1.1" 248 | if not usb and (args.upstream or args.dns): 249 | profile.nameserver = "{}:{}".format(server, proxy) 250 | profile.drop_udp = True 251 | 252 | profile.host = server 253 | profile.port = proxy 254 | 255 | profile.login = login 256 | profile.password = psw 257 | log ("set proxy: %s:%s@%s:%s/%s" % ( 258 | login, psw, 259 | server, proxy, 260 | pkgName or "all")) 261 | if pkgName is not None: 262 | profile.application.set(d.application(pkgName)) 263 | d.start_gproxy(profile) 264 | 265 | command = [] 266 | # 设置 MITMPROXY 代理模式 267 | add_server(command, args.mode) 268 | add_server(command, args.dns) 269 | command.append("--ssl-insecure") 270 | # 代理认证,防止误绑定到公网被扫描 271 | command.append("--proxyauth") 272 | command.append("{}:{}".format(login, psw)) 273 | # 随机 web-port 274 | command.append("--web-port") 275 | command.append(str(webport)) 276 | command.append("--no-rawtcp") 277 | command.append("--listen-port") 278 | command.append(str(proxy)) 279 | # 追加额外传递的参数 280 | command.extend(extras) 281 | 282 | log (" ".join(command)) 283 | 284 | sys.exit = cleanup 285 | log ("press CONTROL + C to stop") 286 | proc = Process(target=web, name="mitmweb", 287 | args=(command,), daemon=True) 288 | proc.run() 289 | sys.exit(0) -------------------------------------------------------------------------------- /tools/startmitm.spec: -------------------------------------------------------------------------------- 1 | # -*- mode: python ; coding: utf-8 -*- 2 | from PyInstaller.building.build_main import Analysis 3 | from PyInstaller.building.api import PYZ, EXE 4 | 5 | from PyInstaller.utils.hooks import collect_data_files 6 | 7 | 8 | a = Analysis( 9 | ["startmitm.py"], 10 | pathex=[], 11 | binaries=[], 12 | datas=collect_data_files("lamda"), 13 | hiddenimports=[], 14 | hookspath=[], 15 | hooksconfig={}, 16 | excludes=["tcl", "tk", "tkinter"], 17 | win_no_prefer_redirects=False, 18 | win_private_assemblies=False, 19 | noarchive=False, 20 | ) 21 | 22 | exe = EXE( 23 | PYZ(a.pure, a.zipped_data), 24 | a.scripts, 25 | a.binaries, 26 | a.zipfiles, 27 | a.datas, 28 | [], 29 | name="startmitm", 30 | icon=["startmitm.ico"], 31 | debug=False, 32 | bootloader_ignore_signals=False, 33 | console=True, 34 | disable_windowed_traceback=False, 35 | argv_emulation=False, 36 | target_arch=None, 37 | ) -------------------------------------------------------------------------------- /tools/test-fridarpc.js: -------------------------------------------------------------------------------- 1 | Java.perform(function() { 2 | var String = Java.use("java.lang.String") 3 | rpc.exports = { 4 | getMyString: function (paramA, paramB) { 5 | return performRpcJVMCall(function() { 6 | // 可以使用 Frida java 相关功能,Java.use 等 7 | var newParam = String.$new("helloWorld").toString() 8 | return newParam + ":" + paramA + paramB 9 | }) 10 | }, 11 | getMyString1: function (paramA, paramB) { 12 | return performRpcJVMCallOnMain(function() { 13 | // 可以使用 Frida java 相关功能,Java.use 等 14 | // 执行于应用的主进程,适用于涉及到 UI 主线程相关的功能 15 | var newParam = String.$new("helloWorld").toString() 16 | return newParam + ":" + paramA + paramB 17 | }) 18 | }, 19 | getMyString2: function (paramA, paramB) { 20 | return performRpcCall(function() { 21 | // 这里不能使用 Java 相关功能 22 | return paramA + paramB 23 | }) 24 | }, 25 | } 26 | }); 27 | -------------------------------------------------------------------------------- /tools/test.pem: -------------------------------------------------------------------------------- 1 | LAMDA SSL CERTIFICATE (CN=test,PASSWD=a1c0e3ea707a54de7a0f95) 2 | -----BEGIN PRIVATE KEY----- 3 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDVcLZP9oLQZDHF 4 | yWJSke4gG+IJfH+LZY4qu3u/NrDpHvB7i9WMk1lQ/aLHb4WvjzPK+THNokG760CQ 5 | XAMJVKGfatprcKQwo0hoX6v6XlMYYRSQmop7zRiKg7vq+5vKOCCdJp1eISbew2LH 6 | Nf1/rYzZpkT5lz1Lfdzm4yrAKuMkKrgzgO2QpOBAWXvgbXoA07bt7N86Y8gMdU0t 7 | zR/DrhKN/I1WXJMu1N0AnTl2QtHDoGB7E2KLivl2l6IvtkabxDNyciGmLNPiLFIk 8 | YOHyg1H71Bv5M84NSX75sln9uMPe39SEVRhSJm4w/OkWfp9tjYELwtzatXhIbhKs 9 | h/NeMe9dAgMBAAECggEABbQnYGepWJb02uDmJxK4lv8Sa/J5w2iJWLb94umRPLQ+ 10 | SkQ9sVisBbAMI4w6uar4AAU8wXlZNwOzC/3ezucGEqkxAQys4T0xItORAvXLqVZ0 11 | IuZzq5nwJ/NxQsxKfihAfDKbTff7fpnLZUtvZMlnKYHPTLmFQnkwkrL2DNXt5U96 12 | arTP5NcLuh46uOwjRT9hZ7+XB/nmOKy5xWxh5eLBbIQ2kKE/uebRUXDfMtnmm8vh 13 | QHoU3syw9YpMqD9VAjipijAtpmIpkl5zdVHNvCWBHi666q+1zqJGxUT80lxz57du 14 | ToDQPsYt8QD/vc4i1j7tl6rG3PZBM3NK5TydV2FygQKBgQDaG2ruwilraGYG6MAl 15 | 4AvYmAcHGAe0B4tfkdu/PjweEd2YAvN2HAeugVTIh5xZeRR04Q8eSFzpShJpDJd4 16 | uLHGqrvrjW/X+xEHsO56sc64bzmpybVApeBp86QFI98WqffAr7qso8pxRc6gSEMn 17 | NSquugjlaM9NRfqJ8r/6FIfBLQKBgQD6hbtggHuRhLxGacMhDo9Ziqre6/G7Woft 18 | GaFfaP3lY53f3HOu+256LX65eaXE7kmyP8dC3eV/n1OwoLwAbmAgjDYWu7OJti8A 19 | OloU6kgNEp5g08zUZPZGsR2FLweiRH+CvNtPYjBrvaHAKUSiKkpJtJVxZHuIzJZF 20 | 5TfC6V3k8QKBgDyjtNZO+08Who9TNOES6pg8pG+PeczO8CwRFISWXAaMNwzlfSUQ 21 | Y/5bjOP3+DtUE6DvVdG4ksR1yKqWSqLQzvSKUZcLCtaEwlZeFd/dAbl7iw+uugsQ 22 | U1WB3M9lCsh1VyGmegM3wrg9jVY44RrMiGJt7L1Dp6c3VpH2APQZsyi9AoGBANOi 23 | jfykDb+M5pCFYDZY2njGUDsqD3g6roF6GX1EcNiMIx6uWXwFI/tK27dMMOIAe3l9 24 | r5OpaOs7abPY1Xl3xPU5/aeOwckgguwqX1cz49JHXExoIK187SAjF9EfPc+zFhUX 25 | /h090bHy7OYs9rIYD9HcIDM+s62JR5mcXlLmWk/BAoGBAJEXPWNHXL+kYz3/uGW7 26 | tJwHTC1elBcrW/hzI1kxdHWznUisSZW2Vp9oL0IckAuVBLzxe/GXz8bQN6d9l2d0 27 | tkfRj5NjC953Kcuq3RzDfUN4q72RUVMiE8uoI0dUVijW37KU0HKrmil0hqM5yob5 28 | UfXOCd9JTQIlycgMXDzNm4Kz 29 | -----END PRIVATE KEY----- 30 | -----BEGIN CERTIFICATE----- 31 | MIICqDCCAZCgAwIBAgIRAPsc1PQ5pnH3a6MFfGUMp6YwDQYJKoZIhvcNAQELBQAw 32 | EDEOMAwGA1UECgwFTEFNREEwHhcNMjAwMTAxMDAwMDAxWhcNMjkxMjI5MDAwMDAx 33 | WjAPMQ0wCwYDVQQDDAR0ZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC 34 | AQEA1XC2T/aC0GQxxcliUpHuIBviCXx/i2WOKrt7vzaw6R7we4vVjJNZUP2ix2+F 35 | r48zyvkxzaJBu+tAkFwDCVShn2raa3CkMKNIaF+r+l5TGGEUkJqKe80YioO76vub 36 | yjggnSadXiEm3sNixzX9f62M2aZE+Zc9S33c5uMqwCrjJCq4M4DtkKTgQFl74G16 37 | ANO27ezfOmPIDHVNLc0fw64SjfyNVlyTLtTdAJ05dkLRw6BgexNii4r5dpeiL7ZG 38 | m8QzcnIhpizT4ixSJGDh8oNR+9Qb+TPODUl++bJZ/bjD3t/UhFUYUiZuMPzpFn6f 39 | bY2BC8Lc2rV4SG4SrIfzXjHvXQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAXD4/W 40 | B0aImZXjPm4qRpNk2fRzcSX80l6NVZYlIWvXjQqQwWfs/Hg3d5saJbrAfqeOkYPu 41 | cyrDXVOt/QLEC91AHkcEbuGGO0cESf28wT3U3FrIog1KUrMDjXQHoOodBi8gMiPf 42 | dNqhLI7d42AMrJSwYQ9RPooXoTglCkGwGouD8nKEy2cGyS13yPp4lx/SY4uBDESK 43 | FQ+GFQLLFBKPdvMsltpv2AaLZdwrQxhT6i55SZn5+Kow5LlX/DGuL9RtOvfvOKse 44 | QgzNAH7BF3lgoBbcbOrfEPk65dFQ7CWb/uh6cVifJ7qC9//LatIfoUPVrbEwY/gQ 45 | NAEqXrWn0fnaG4qA 46 | -----END CERTIFICATE----- 47 | -----BEGIN CERTIFICATE----- 48 | MIIClDCCAXwCAQAwDQYJKoZIhvcNAQELBQAwEDEOMAwGA1UECgwFTEFNREEwHhcN 49 | MjAwMTAxMDAwMDAxWhcNMjkxMjI5MDAwMDAxWjAQMQ4wDAYDVQQKDAVMQU1EQTCC 50 | ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALnqfBZvrGZaqgk5msCRRpPz 51 | p/+464jBknlmTKetOckDTUq8V6fH/2Gfb6HjjoD5pkCtD5mSKkaHNhuxLXsFfEfc 52 | Klmnn3ZpjyNOHEA/iAO2DyEYa08xSevM7WojbF7cNj5/DYg7eb0i0+//bBlh8nlO 53 | ghSUhCTM5PCofLDU8sVXuYAiGU6UzBrIC0vHEltDkiJVLpcCtsKjEZOskPdAc7u6 54 | /aA0P5GonZ5UkRDYpa+jeJUabqWZQQEgtmvjlmUUiXwu0jRnj1n0T3fPQD3gA+LI 55 | vAE9vgvpY5XQj6otpBvsZ3MJJNKcUMQu1zOANTzO18TlA8KoBNsBy8Z9DQZKXF8C 56 | AwEAATANBgkqhkiG9w0BAQsFAAOCAQEAeGn/NyqIRI/0AGqvHP97KtQ76Tj6achb 57 | 30LIXWp+YHUaMeAVjd2Z7jSQp5mZZFl+k1fb337IeaGXofVI21eK52QX2teNoBkA 58 | /V/O1Hu35/+aiz0xsdD6wWvwo4Fy1jlmaeJhwdQacBlDGFA2jFJxuEpahfxZvUsb 59 | 3j5zU0WKTUCfEDgXFwBw12xku/7TMdCEbRsYaZ3zFTC226lQbUDN7weqFwSD+tB6 60 | RuhIxe8+cFwAsAWHClerKgZnr3t5QF078pW2GHy8CsJ7V3MZT5lZ43lS5NIB9JzZ 61 | SYxZ/izhRyh5qR73uAgsJaL56Bj+cQqnoTqhLZVl7J+M6WhWKzojsA== 62 | -----END CERTIFICATE----- 63 | --------------------------------------------------------------------------------