1.复制系统镜文件像会出现问题吗
2.Fridaåè°è¯
3.Hikari源码分析 - AntiDebug
4.Android开发App如何进行加固?
5.你应该了解的注入手游外挂实现原理
复制系统镜文件像会出现问题吗
复制系统镜文件像会出现问题吗(镜像文件无法复制)
本文介绍了 个优化 Docker 镜像安全性的技巧。每个技巧都解释了底层的源码攻击载体,以及一个或多个缓解方法。注入这些技巧包括了避免泄露构建密钥、源码以非 root 用户身份运行,注入或如何确保使用最新的源码淘宝返利app源码依赖和更新等。
前言当你是注入刚开始使用 Docker 的新手时,你很可能会创建不安全的源码 Docker 镜像,使攻击者很容易借此接管容器,注入甚至可能接管整个主机,源码然后渗透到你公司的注入其他基础设施中。
可以被滥用来接管你的源码系统的攻击向量有很多,例如:
启动的注入应用程序(在你 Dockerfile 的 ENTRYPOINT 中指定)以 root 用户身份运行。这样以来,源码一旦攻击者利用了一个漏洞并获得了 shell 权限,注入他们就可以接管 Docker 守护程序所运行的主机。你的镜像是基于一个过时的和/或不安全的基础镜像,其中包含(现在)众所周知的安全漏洞。你的镜像包含了一些工具(如 curl、apt 等),一旦攻击者获得了某种访问权,就可以通过这些工具将恶意软件加载到容器中。下面的各个章节讲解了能够优化你的镜像安全性的各种方法。它们是按重要性/影响程度排序的,也就是说排名靠前的方法更重要。
避免泄露构建密钥构建密钥是只在构建 Docker 镜像时需要的凭证(不是在运行时)。例如,你可能想在你的镜像中包含某个应用程序的一个编译版本,这个应用的源代码是闭源的,并且其 Git 存储库是有访问保护的。在构建镜像时,你需要克隆 Git 存储库(这需要构建密钥,例如该存储库的 SSH 访问密钥),从源代码构建应用程序,然后再删除源代码(和密钥)。
“泄露“构建密钥是说你不小心把这种密钥烘焙到了你的镜像的某个层中。这种情况很严重,因为拉取你的镜像的所有人都可以检索到这些机密。这个问题源于这样一个事实,即 Docker 镜像是以纯粹的加法方式逐层构建的。你在一个层中删除的文件只是被“标记”为已删除,但拉取你镜像的人们仍然可以使用高级工具访问它们。
可以使用以下两种方法之一来避免泄露构建密钥。
多阶段构建Docker 多阶段构建(官方文档)有许多用例,例如加快你的镜像构建速度,或减少镜像大小。本系列的其他文章会详细介绍其他用例。总之,你也可以通过多阶段构建来避免泄露构建密钥,如下所示:
创建一个阶段 #A,将凭证复制到其中,并使用它们来检索其他工件(例如上述例子中的 Git 存储库)和执行进一步的步骤(例如编译一个应用程序)。阶段 #A 的构建确实包含了构建的密钥!创建一个 #B 阶段,其中你只从 #A 阶段复制非加密的工件,例如一个已编译的应用程序。只发布/推送阶段 #B 的php源码复制镜像BuildKit 的密钥背景知识如果你使用 docker build 进行构建,可以实际执行构建的后端选项不止一个。其中较新和较快的后端是 BuildKit,你需要在 Linux 上设置环境变量 DOCKER_BUILDKIT=1 来显式启用它。注意,BuildKit 在 Windows/MacOS 的 Docker for Desktop 上是默认启用的。
正如这里的文档所解释的(阅读它们以了解更多细节),BuildKit 构建引擎支持 Dockerfile 中的额外语法。要使用构建密钥,请在你的 Dockerfile 中放入类似下面这样的内容:
RUN --mount=type=secret,id=mysecret,dst=/foobar
复制代码
当 RUN 语句被执行时,密钥将对这个构建容器可用,但不会将密钥本身(这里是:/foobar 文件夹)放入构建的镜像中。你需要在运行 docker build 命令时指定密钥的源文件/文件夹(位于主机上)的路径,例如:
docker build --secret id=mysecret,src=mysecret.txt -t sometag
复制代码
不过有一点需要注意:你不能通过 docker-compose up --build 来构建需要密钥的镜像,因为 Docker-compose 还不支持用于构建的--secret 参数,见 GitHub问题。如果你依赖 docker-compose 的构建,请使用方法 1(多阶段构建)。
题外话:不要推送在开发机上构建的镜像你应该一直在一个干净的环境中构建和推送镜像(例如 CI/CD 管道),其中构建代理会将你的存储库克隆到一个新目录。
使用本地开发机器进行构建的问题是,你的本地 Git 存储库的“工作树“可能是脏的。例如,它可能包含有开发过程中需要的密钥文件,例如对中转甚至生产服务器的访问密钥。如果没有通过.dockerignore 排除这些文件,那么 Dockerfile 中的“COPY . .“等语句可能会意外导致这些密钥泄露到最终镜像中。
以非 root 用户身份运行默认情况下,当有人通过“docker run yourImage:yourTag“运行你的镜像时,这个容器(以及你在 ENTRYPOINT/CMD 中的程序)会以 root 用户身份运行(在容器和主机上)。这给了一个使用某种漏洞在你的运行容器中获得 shell 权限的攻击者以下权力:
对主机上所有显式挂载到容器中的目录的无限制写权限(因为是 root)。能够在容器中做 Linux 根用户可以做的一切事情。例如,攻击者可以安装他们需要的额外工具来加载更多的恶意软件,比如说通过 apt-get install(非 root 用户无法做到这一点)。如果你的镜像容器是用 docker run --privileged 启动的,攻击者甚至可以接管整个主机。为了避免这种情况,你应该以非 root 用户(你在 docker build 过程中创建的一些用户)的身份运行你的应用程序。在你的 Dockerfile 中的某个地方(通常是在结尾处)放置以下语句:
# Create a new user (including a home-directory, which is optional)RUN useradd --create-home appuser# Switch to this userUSER appuser
复制代码
Dockerfile 中所有在 USER appuser 语句之后的命令(如 RUN、CMD 或 ENTRYPOINT)都将以这个用户运行。这里有一些需要注意的地方:
在切换到非 root 用户之前,你通过 COPY 复制到镜像中的文件(或由某些 RUN 命令创建的文件)是由 root 用户拥有的,因此以非 root 用户身份运行的应用程序无法写入。为了解决这个问题,请把创建和切换到非 root 用户的代码移到 Dockerfile 的开头。如果这些文件是在 Dockerfile 的开头以根用户身份创建的(存储在/root/下面,而不是/home/appuser/下面),那么你的程序期望在用户的主目录中的某个地方(例如~/.cache)的文件,现在从应用程序的视角来看可能突然消失了。如果你的应用程序监听一个 TCP/UDP 端口,就必须使用大于 的端口。小于等于 的端口只能以 root 用户身份使用,或者以一些高级 Linux 能力来使用,但你不应该仅仅为了这个目的而给你的容器这些能力。使用最新的基础镜像构建和更新系统包如果你使用的基础镜像包含了某个真正的 Linux 发行版(如 Debian、Ubuntu 或 alpine 镜像)的exui源码下载全部工具集,其中包括一个软件包管理器,建议使用该软件包管理器来安装所有可用的软件包更新。
背景知识基础镜像是由某人维护的,他配置了 CI/CD 管道计划来构建基础镜像,并定期推送到 Docker Hub。你无法控制这个时间间隔,而且经常发生的情况是,在该管道将更新的 Docker 镜像推送到 Docker Hub 之前,Linux 发行版的包注册表(例如通过 apt)中已经有了安全补丁。例如,即使基础镜像每周推送一次,也有可能在最近的镜像发布几小时或几天后出现安全更新。
因此,最好总是运行更新本地软件包数据库和安装更新的包管理器命令,采用无人值守模式(不需要用户确认)。每个 Linux 发行版的这个命令都不一样。
例如,对于 Ubuntu、Debian 或衍生的发行版,使用 RUN apt-get update && apt-get -y upgrade
另一个重要的细节是,你需要告诉 Docker(或你使用的任何镜像构建工具)来刷新基础镜像。否则,如果你引用一个基础镜像,比如 python:3(而 Docker 在其本地镜像缓存中已经有了这样一个镜像),Docker 甚至不会检查 Docker Hub 上是否存在更新的 python:3 版本。为了摆脱这种行为,你应该使用这个命令:
docker build --pull
复制代码
这可以确保 Docker 在构建镜像之前拉取你的 Dockerfile 中 FROM 语句中提到的镜像的更新。
你还应该注意 Docker 的层缓存机制,它会让你的镜像变得陈旧,因为 RUN etc. updates>命令的层是缓存的,直到基础镜像维护者发布新版本的基础镜像才刷新。如果你发现基础镜像的发布频率相当低(比如少于一周一次),那么定期(比如每周一次)重建你的镜像并禁用层缓存是个好主意。你可以运行以下命令来做到这一点:
docker build --pull --no-cache
复制代码
定期更新第三方依赖你编写的软件是基于第三方的依赖,也就是由其他人制作的软件。这包括了:
你的镜像下面的基础 Docker 镜像,或你作为自己应用程序的一部分使用的第三方软件组件,例如通过 pip/npm/gradle/apt/……安装的组件。如果你的镜像中的这些依赖过时了,就会增加攻击面,因为过时的依赖往往有可利用的安全漏洞。
你可以定期使用 SCA(软件组件分析)工具来解决这个问题,比如Renovate Bot。这些工具(半)自动将你声明的第三方依赖更新为最新版本,例如在你的 Dockerfile、Python 的 requirements.txt、NPM 的 packages.json 等文件中声明的列表。你需要设计你的 CI 管道,使 SCA 工具所做的更改自动触发你的镜像的 re-build。
这种自动触发的镜像重建对于处在只维护模式,但代码仍将被客户在生产环境中使用(客户希望它是安全的)的项目特别有用。在维护期间,你不再开发新的特性,也不会构建新的镜像,因为没有新的提交(由你做出)来触发新的构建。然而,源码管理 tfs由 SCA 工具做出的提交确实会再次触发镜像构建。
你可以在我的相关博文中找到更多关于 Renovate bot 的细节。
对你的镜像进行漏洞扫描即使你执行了上述建议,比如说你的镜像总是使用最新的第三方依赖,它仍然可能是不安全的(例如一个依赖已经被弃用的情况)。在这种情况下,“不安全“意味着一个(或多个)依赖有已知的安全漏洞(在一些 CVE 数据库中注册)。
出于这个原因,你可以给你的 Docker 镜像提供某种工具来扫描所有包含的文件,以找到这种漏洞。这些工具有两种形式:
你显式调用的 CLI 工具(例如在 CI 管道中),比如说Trivy(OSS,在 CI 管道中非常容易使用,见 Trivy文档)、Clair(OSS,但设置和使用比 Trivy 更复杂),或Snyk(通过“docker scan“集成到 Docker CLI 中,见cheat sheet,但只有有限的免费计划!)集成到你推送镜像的镜像注册中心的扫描器,如 Harbor(内部使用 Clair 或 Trivy)。还有一些商业产品,如Anchore。因为这些扫描器是通用的,它们还试图覆盖一大堆包注册表,所以可能不会特别为你在自己项目中使用的编程语言或包注册表定制。有时,你应该调查你的编程语言生态系统提供了哪些工具。例如,对于 Python 来说就有一个专门针对 Python 包的安全工具。
扫描你的 Dockerfile 是否违反了最佳实践有时,问题来自于你在 Dockerfile 中放置的语句,这些语句是不好的实践(但你没有意识到)。为此可以使用诸如checkov、Conftest、trivy或hadolint等工具,它们是 Dockerfile 的 linter。为了选择正确的工具,你需要查看它的默认规则/政策。例如,hadolint 比 checkov 或 conftest 提供的规则更多,因为它是专门针对 Dockerfiles 的。这些工具也是相互补充的,因此在你的 Dockerfiles 上运行多个工具(如 hadolint 和 trivy)确实是有意义的。不过要做好准备,因为你需要维护“忽略文件“,在这个文件中的规则会被忽略——可能是由于误报而有意忽略它们,或者是你准备故意破坏规则。
不要对 Docker Hub 使用 Docker 内容信任为了验证你使用的基础镜像确实是由该镜像背后的公司构建和推送的,你可以使用 Docker 内容信任(见官方文档)特性。只需在运行 docker build 或 docker pull 时将 DOCKER_CONTENT_TRUST 环境变量设为“1“即可启用该特性。Docker 守护进程将拒绝提取没有经过发布者签名的镜像。
不幸的是,大约一年前开始社区就不再以这种方式签名镜像了。就连 Docker Inc.也在 年 月停止了签名官方 Docker镜像,也没有官方解释。网站源码 曲线问题更大的是如果你使用“docker pull docker:latest”这样的命令,只会下载一个过时很久的镜像。
你可以查看一下镜像签名的其他实现,比如说cosign(不过我还没试过)。
扫描你自己的代码是否有安全问题安全问题通常来源于其他人的代码,也就是流行的第三方依赖。因为它们应用广泛,所以在黑客那里是“有利可图“的。然而,有时是你自己的代码在作怪。例如,你可能不小心实现了 SQL 注入的可能性、堆栈溢出的错误,等等。
为了找到这些问题,你可以使用所谓的 SAST(静态应用安全测试)工具。一方面,有一些特定于编程语言的工具(你必须单独研究),如 Python 的bandit,或 Java 的Checkstyle/Spotbugs。另一方面,还有一些支持多种编程语言和框架的工具套件(其中一些是非免费/商业的),如SonarQube(对于它还有SonarLintIDE 插件)。这里是 SAST 工具列表。
在实践中,安全扫描有两种基本方法:
连续(自动)扫描:你创建一个 CI 作业,在每次推送时扫描你的代码。这可以让你的代码安全性保持在一个较高的水平上,但你必须弄清楚如何忽略误报(这是一项持续的维护工作)。如果你使用 GitLab,可能还会发现 GitLab 的免费 SAST功能很有趣。不定期(手动)扫描:团队中一些有安全意识的成员在本地运行安全检查,例如每月一次或每次发布前,并手动查看结果。使用 docker-slim 来删除不必要的文件docker-slim工具可以获取大型 Docker 镜像,临时运行它们,分析哪些文件在临时容器中是被真正使用的,然后生成一个新的、单层的 Docker 镜像——其中所有未使用的文件都会被删除。这样做有两个好处:
镜像被缩小镜像变得更加安全,因为不需要的工具被删除了(例如 curl 或包管理器)。请参考我之前文章中的 Docker slim部分以了解更多细节。
使用最小的基础镜像一个镜像中存储的软件(如 CLI 工具等)越多,攻击面就越大。使用“最小“的镜像是一个很好的实践,它越小越好(无论如何这是一个很好的优势),并且应该包含尽可能少的工具。最小的镜像甚至超越了“优化体积“的镜像(如alpine或:-slim,如 python:3.8-slim):前者没有任何包管理器。这使攻击者很难加载额外的工具。
最安全的最小基础镜像是SCRATCH,它完全不包含任何东西。只有当你在镜像中放置自包含的二进制文件时,才能用 FROM SCRATCH 启动你的 Dockerfile——这些二进制文件烘焙进了所有的依赖(包括 C-runtimes)。
如果 SCRATCH 不适合你,谷歌的无发行版(distroless)镜像可以是一个很好的选择,特别是当你正在为常见的编程语言(如 Python 或 Node.js)构建应用程序,或者需要一个最小的 Debian 基础镜像时。
不幸的是,最小镜像有几个需要注意的地方:
无发行版的注意事项:不建议使用谷歌在 gcr.io 上发布的针对特定编程语言的镜像,因为那里只有一个 latest 版本标签,以及 major 版本的标签(例如 python 的“3“,或 Node 的““)。你无法控制具体的语言运行时版本(例如是否使用 Python 3.8.3 或 3.8.4 等),这破坏了你的镜像构建的可重用性。定制(和构建你自己的)无发行版镜像是相当复杂的:你需要熟悉 Bazel 的构建系统并自己构建镜像。注意:如果你唯一需要的定制是“以非 root 用户身份运行代码”,那么每个无发行版基础镜像中都有一个默认的非 root 用户,详见这里。最小基础镜像的常规注意事项:使用最小基础镜像调试容器是很棘手的,因为有用的工具(比如/bin/sh)现在不见了。对于 Docker,你可以运行第二个调试容器(它确实有一个 shell 和调试工具,例如 alpine:latest),并使其共享你的最小容器的 PID 命名空间,例如通过 docker run -it --rm --pid=container: --cap-add SYS_PTRACE alpine sh对于 Kubernetes,你可以使用短期容器,见这里的例子使用受信任的基础镜像一个受信任的镜像指的是经过某人(要么是你自己的组织,要么是其他人)按照比如说某种安全级别审核的镜像。这对具有高安全要求和规定的受管制行业(银行、航空航天等)来说可能特别重要。
虽然你自己可以通过从头开始建立可信的镜像来完成审计工作,但这是不可取的。因为你(这个镜像的构建者)必须确保所有与审计有关的任务都已完成,并有正确的记录(例如记录镜像中的包列表、执行的 CVE 检查及其结果等等)。这项任务非常繁重。相反,我们建议将这项工作外包出去,使用商业性的“可信注册表“——它提供了一套选定的可信镜像,如 RedHat 的通用基础镜像(UBI)。RedHat 的 UBI 现在也可以在 Docker Hub 上免费获取。
背景知识在 Docker Hub 上托管的镜像没有经过审计。它们是“按原样“提供的。它们可能是不安全的(甚至包含恶意软件),而且没有人会通知你这一点。因此,使用 Docker Hub 中不安全的基础镜像也会让你的镜像变得不安全。
另外,你不应该把审计和上面提到的 Docker 的内容信任混为一谈!内容信任只确认来源(镜像上传者)的身份,并不会确认与镜像安全性有关的任何事实。
测试你的镜像是否能在降低能力的情况下工作Linux capabilities 是 Linux 内核的一个特性,它允许你控制一个应用程序可以使用哪些内核特性,例如一个进程是否可以发送信号(如 SIGKILL)、配置网络接口、挂载磁盘,或调试进程等。完整的列表见这里。一般来说,你的应用程序需要的功能越少越好。
启动你的镜像容器的所有人都可以给予(或拿走)这些能力,例如通过调用“docker run --cap-drop=ALL “。默认情况下 Docker 会放弃所有能力,除了这里定义的那些以外。你的应用程序可能不需要所有这些功能。
作为一个最佳实践,你可以尝试启动你的镜像容器,放弃所有能力(使用--cap-drop=ALL),看看它是否仍然正常工作。如果不能,请搞清楚哪些功能是缺失的,并且你是否真的需要它们。然后请记录你的镜像需要哪些功能(以及为什么),这会给运行你镜像的用户带去更多信心。
总结提升你的镜像安全性并非闲庭信步。你需要花时间来评估和实施每一种实践。本文中的列表应该可以节省你的时间,因为收集和排序重要步骤的工作已经为你做好了。
所幸,提升你的应用程序的安全性是一个迭代过程。你可以从小处着手,每次实施一个步骤。不过你确实需要得到管理层的支持。这有时是很难办的,特别是有时你的经理会对建议有抵触情绪,他们可能倾向于从过去的经验来做推断(“我们,或我们的客户,以前从未被黑过,那么为什么这种问题现在会发生在我们身上?我们需要的是特性!“)。你有几个选择:可以说服你的经理为安全性分配资源。例如,如果你有一个直接接触客户的渠道(你在为其构建软件),那么可以说服他们,让他们要求把安全性作为一个“特性“。或者在你的行业中寻找安全漏洞的报告(例如一个直接的竞争对手受到了影响),以证明黑客攻击确实发生了,甚至你的行业也出了问题,而且它们有严重的(财务)影响。
原文链接:.shark.tracerpidappå称çè¿ç¨
æ们ç´æ¥è¿å ¥adbæ¥çè¿ç¨
å¯ä»¥çå°ç¡®å®æ两个è¿ç¨ï¼fridaåä¸æ¸ ä½ è¦æ³¨å ¥åªä¸ªè¿ç¨æ以æ¥åºå¦ä¸é误ã
æ们éæ©ç¶è¿ç¨è¿è¡æ³¨å ¥
å«æ们ç¨rootå»æ§è¡ï¼è¿éæ¯æ²¡æç¨çãæ们å°adbççè¿ä¸ªç¶è¿ç¨çTracerPidä¿¡æ¯å°±ç¥éäº
è³äºä¸ºä»ä¹çTracerPid请移æ¥æç« TracerPidåè°è¯
å¯ä»¥çå°ç¶è¿ç¨å·²ç»è¢«åè¿ç¨ATTACHï¼èfridaä¹ä¾èµäºptraceæ以è¿éè¯å®æ³¨å ¥ä¸è¿å»
æ们ä¸è¦è®©fridaæ³¨å ¥ï¼èæ¯ä½¿ç¨fridaå¯å¨appï¼ä½¿ç¨-fé项ï¼æ们åè¯Fridaæ³¨å ¥Zygote并å¼å§å¯å¨åºç¨ç¨åº
è¿æä¸ç§æè¡¥ä¸çæ¹å¼ï¼å¨ä¸é¢åèä¸æãè¿éå°±ä¸åèµè¿°ã
è¿ä¸ªåè°è¯å ¶å®å°±æ¯ç¨äº TracerPidåè°è¯ çåçï¼ä½æ¯å¨è¿éæä¸äºä¸ä¸æ ·ã
1:è¿éæ¯åè¿ç¨ATTACHç¶è¿ç¨
2:å¨Android8ä¸ptrace(PTRACE_TRACEME, 0, 0, 0); è½ç¶è¿åçä¸æ¯-1ä½æ¯æ æ³æå
æ以æ们è¿éè¦ä½¿ç¨ptrace(PTRACE_ATTACH, parent, 0, 0)æ¥å®ç°ã
PTRACE_ATTACHåæ°
ptrace(PTRACE_ATTACH,pid)
è·è¸ªæå®pid è¿ç¨ãpid表示被è·è¸ªè¿ç¨ã被è·è¸ªè¿ç¨å°æ为å½åè¿ç¨çåè¿ç¨ï¼å¹¶è¿å ¥ä¸æ¢ç¶æ
PTRACE_CONTåæ°
ptrace(PTRACE_CONT, pid, 0, signal)
继ç»æ§è¡ãpid表示被è·è¸ªçåè¿ç¨ï¼signal为0å忽ç¥å¼èµ·è°è¯è¿ç¨ä¸æ¢çä¿¡å·ï¼è¥ä¸ä¸º0å继ç»å¤çä¿¡å·signal
å 使ç¨PTRACE_ATTACHè¿è¡éå ï¼è¿æ¶å被éå è¿ç¨ä¼é»å¡ãå使ç¨PTRACE_CONT继ç»æ§è¡è¢«éå çè¿ç¨ã为äºç¡®ä¿PTRACE_CONTè½è¢«æ§è¡æ们å¨PTRACE_ATTACHå®åè¦é©¬ä¸waité»å¡å½å线ç¨ãå½éå æååwaité»å¡è§£é¤å°±è½æ§è¡å°PTRACE_CONTäº
Android APPç ´è§£å©å¨Fridaä¹åè°è¯å¯¹æ
ptrace使ç¨ç®ä»
Hikari源码分析 - AntiDebug
一、框架分析 针对PASS的具体实现进行深入分析。该PASS旨在提升编译后程序的抵抗调试能力,其核心逻辑包括两个主要方面: 链接预编译的反调试IR代码 特定于平台的内联汇编注入 针对Darwin操作系统上的AArch架构,若未找到ADBCallBack和InitADB函数,PASS会尝试直接注入内联汇编代码。该代码片段可能利用系统调用,如ptrace,来检测是否处于调试环境。 此外,配置允许用户指定预编译反调试IR文件的路径和函数混淆概率。 具体实现包括: 检查预编译IR路径,构建默认路径并链接预编译的IR文件。 修改ADBCallBack和InitADB函数属性,确保它们在编译和链接阶段表现出反调试行为。 初始化标志和目标三元组信息,准备为每个模块提供初始化和链接预编译IR的过程。 模块处理和函数处理涉及应用概率值来决定是否对模块和函数应用反调试混淆。 预编译的反调试IR文件包含了一系列用于反调试的函数和结构,如检测调试器的代码、修改执行路径以规避调试跟踪、以及插桩代码以检测异常行为。 通过LLVM工具链中的llvm-dis工具,可以将.bc文件转换为可读的LLVM IR文件。该文件结构包含多个结构体定义、全局声明、函数实现和属性。 函数ADBCallBack简单地终止程序并执行无法到达的指令。函数InitADB执行系统调用和检查来检测调试状态,可能涉及进程信息查询、动态库加载、系统调用、内存分配、异常端口检查等操作。 系统调用声明确保了程序能调用各种底层函数进行操作,如sysctl、dlopen、dlsym、task_get_exception_ports、isatty、ioctl等。 总结,通过在编译器优化阶段插入反调试逻辑,相较于源代码实现,基于LLVM Pass的AntiDebug方法提供了更好的隐蔽性、可移植性、灵活性、维护性和混淆程度。然而,这种方法需要对LLVM框架有深入理解,可能增加构建和调试复杂度。Android开发App如何进行加固?
1.避
免技巧:使用内部API。即便我们总是建议不要这么做,但还是有一些开发者选择使用那些不支持或者内部的API。例如,许多开发者使用内部的亮度控制和蓝
牙切换API,这些API出现在1.0和1.1版本上。一个Bug——在Android
1.5上进行了修正——允许App在不需要请求权限的情况下使用这些API。结果,使用了这些API的App在1.5上挂掉了。如果你在App中使用了这
些内部API,你需要做的是:停止这一做法,更新你的程序。
2.避
免技巧:直接操作Settings。严格来讲,这一条不算,因为我们可以通过Android本身进行操作。但之所以我们加上了这一条,是因为一些开发者做
了一些调皮的事情:一些App悄无声息地修改了系统设定,而没有通知用户。例如,一些App没有询问用户就直接打开了GPS,而另外一些则可能直接打开了
数据传输。
因此,应用程序不能直接操作某个特定的系统设定值,即便是它们之前能这么做。例如,App不能直接打开或关闭GPS。不是说使
用会导致App崩溃,而是不应该使用这些API。代替的,App需要发出一个Intent来启动相应的Settings配置画面,这样用户可以手动地修改
这些设定。详细情况可以参考android.provider.Settings.Secure类,你可以在1.5_pre(和之后的)SDK文档中找
到。注意,只有那些移动到Settings.Secure类中设定受到影响。其它的,还会像Android 1.1那样有着相同的功能。
3.避
免技巧:过分布局。由于View渲染部分的变化,在布局中,过于深(超过层左右)或过于多(超过个左右)的View树层次可能会导致程序崩溃。过
于复杂的布局总归是有危险的,尽管你可以认为Android
1.5已经好于1.1。大多数开发者不需要对此担心,但如果你的App有着非常复杂的布局,你还是应该对其“瘦身”。你可以使用一些高级的布局类,如
FrameLayout和TableLayout,来简化你的布局。
4.避
免技巧:不好的硬件假设。Android
1.5支持软键盘,因此,不久就会有很多设备不再包含物理键盘。如果你的程序假设物理键盘存在(例如,如果你创建一个自定义的View,并接收键按下消
息),你必须保证在只有软键盘的设备上也工作正常。想了解更多关于这方面的信息,请继续关注这个Blog,我们将会有更多关于处理软键盘的详细资料。
5.避
免技巧:无意识的旋转。运行Android
1.5(及以上)的设备能够根据用户手持设备的方向自动地旋转屏幕。一些1.5的设备默认这么做,而其它的需要用户手动设置。应用程序自己的重定向在某种
程度上会导致不可预期的行为(不论是使用加速度计还是其它一些东西)。这种情况通常发生在应用程序假设有物理键盘时才能旋转;如果设备没有物理键盘,这些
App就不能进行重定向,而这明显就是个编码错误。开发者应该明确应用程序能在任何时间都能处理重定向。
同样,App可以使用加速度计做到与系统
相同的事情——直接重定向自己,这也会引发奇怪的结果。一些App使用加速度计来监测像晃动动作什么的,而又不将其方向锁定为垂直或水平,经常会导致在方
向上来回翻动。而这就会激怒用户。(你可以在manifest文件中使用android:screenOrientation特性来锁定App的方向为垂
直或水平。)
你应该了解的手游外挂实现原理
外挂实现原理简介
不同类型的外挂,其实现原理相差较大。这里根据外挂分类介绍其大致实现原理。
4.1 辅助
辅助类外挂基于游戏客户端,动态修改游戏数据,实现游戏优势。这类外挂通常为定制化设计,针对特定游戏。
4.1.1 专用插件
专用插件类外挂以插件形式出现,通过注入技术将功能模块注入游戏进程,执行入口函数。Android平台采用Zygote注入或直接ptrace注入,iOS则利用Cydia框架注入dylib。外挂作者需逆向分析游戏逻辑,定位关键函数地址,通过HOOK操作实现功能。常见的功能包括秒怪、无敌等。
4.1.2 通用工具
通用工具实现跨游戏功能,如内存修改器、变速器、按键精灵、模拟器和抓包工具。内存修改器读写游戏内存数据,通过注入或取巧方式实现。变速器修改系统时间度量,影响游戏帧率。按键精灵模拟用户操作,依赖系统API。模拟器在PC上运行手游,通过模拟Android系统实现。抓包工具编辑网络数据包,通过硬件或HOOK实现。
4.2 破解版
破解版是通过修改独立游戏客户端实现。这类外挂通过逆向分析游戏协议或修改逻辑代码和数据资源,实现游戏功能。逻辑代码修改涉及不同游戏引擎的代码,如Unity、cocos等。数据资源包括、配置和音乐等,通过替换或修改实现游戏逻辑变化。
外挂的实现涉及多种技术,如注入、HOOK、逆向工程和API调用。开发者需深入理解游戏逻辑和系统机制,以实现特定功能。更多游戏安全知识及资讯请关注腾讯Gslab游戏安全实验室。