Link File and Sdcard in Android

由于工作上的变动,以及研究目标的转变,笔者没有完成博客建立之初订的一月一篇博文的目标,今天动笔才发现博客开通已经整整两年。回看这两年来的文章,其中不乏有些凑数的水文,实是没有什么价值。 那么就将这两年之际新作为一个的开始,重新制定一个目标,从头再来。

问题提出

sdcard 目录是 Android 系统中存在的默认目录,有时候即使手机中没有插入 sdcard 也会存在一个 sdcard 目录,这个目录可以被所有的已安装应用访问,笔者因此有一个想法,是否可以通过 sdcard 中的链接文件来绕过某些针对文件路径的合法性检测。

Read More

AST Fuzz —— a New Kind of Fuzzer

Introduce

Fuzz 测试作为安全领域内的热点话题经久不衰,这主要归功于它在漏洞挖掘领域的卓越表现,fuzz 测试是目前已知的用于挖掘漏洞的最有效手段之一。在与浏览器相关安全的研究中,fuzz 更是占有举足轻重的地位。

As a fruitful vulnerable auto detect method, Fuzz always get a lot of attention. Fuzz is one of the most effient way in vulberable digging. In browser security, it also play an important role.

Fuzz 的本质无非是向某个测试对象发送一系列畸形数据来试图引发程序内部发生的一些错误。一般来说 Fuzz 可以分成两种基本形式:生成式和变异式。
变异式 Fuzz 是指针对已知的合法输入进行随机或者基于经验的变异,从而产生不可预知的输入。比较典型的工具有 Peach Fuzzer、ProxyFuzz 等。
生成式 Fuzz 是指根据已有的经验,规范一个输入的格式,然后基于这个格式生成一系列的输入。比如 SPIKE、Domato 以及一系列浏览器 DOM fuzz。
浏览器安全研究中,在以 DOM 对象作为重点研究目标阶段,Fuzz 技术展现了十分优越的性能,短时间内发现了大量 DOM 对象间深层调用所引发的 UAF 漏洞。这其中固然有浏览器 DOM 设计时的缺陷,但是面对如此众多的对象和如此复杂的调用关系,唯有 Fuzz 才可以高效的对其进行测试。

Essentially, Fuzz is a frame that sending a series of data to a target program, and try to trigger internal errors. In general, Fuzz can divided into two types: Generator-FUZZ and Mutator-Fuzz.
Mutator-Fuzz try to produce a heristic or random mutation based on a legally seed. Peach-Fuzzer and Proxy-Fuzzer is two famous mutator fuzz.
While Generator-Fuzz try to produce a generate based on given rules. SPIKE, Domato and most of open-source DOM Fuzzer all belong to this cateory.
In browser security research, Fuzzer has done fantastic jobs target in DOM. With fuzz, researchers find a huge number of UAF vulnerables in short time. It is true that’s due to the weakness in DOM objects’ top designation, but for a complex system like browser, maybe fuzz is the most effient way to find out flaws.

同时我们也发现了一个问题,即撞洞率太高,一个问题可能会陆续被多个研究者发现,这说明大家所使用的 fuzz 思路是十分接近的。笔者阅读了一些开源的 DOM Fuzzer 源码,发现这些 Fuzzer 虽然具体的形式不同,但是其思想都是通过构造尽可能复杂的语句和 DOM 间对象关系来使目标产生一些异常。这种思路在对 DOM 的研究上已经取得了很大的成功,但是在近两年针对 js 引擎,尤其是 JIT 引擎上,它的表现却不尽如人意。不仅效果很差,而且 Fuzz 产生的样本质量也都普遍不高,可用性很低。分析原因可以看出,旧有的一些 Fuzz 方法大都使用语料库自由组合的方式构造 JS 语句,因而会产生大量无意义的错误代码。而当引擎执行到这些代码时会抛出 RuntimeError 之类的异常,从而提前终止样本。为了使样本可以继续完整执行,Fuzzer 会加入大量的 TryCatch 语句以屏蔽这些异常,进而会影响原本程序的语意。研究 DOM 对象时这种方法自然无可厚非,但是在 JS 引擎,尤其是 JIT 引擎中,TryCatch 会极大的影响引擎的表现,从而使得大部分功能永远无法执行到。其次这种从已有的语料库中进行拼凑的方法需要 Fuzzer 本身对语法的全方位覆盖,而那些语料库覆盖不到的地方则永远不会被访问,这就大大减少了 Fuzz 可以检测到的攻击面,降低了测试效果。

MeanWhile, we also encounter a problem, Clash! The vulnerables we find with our fuzzer can always be noticed by other researchers. It is means we use very similar ideals. After reviewed some open-source DOM-Fuzzer, I realized even though these various specific forms, their core ideas are to make some abnormalities in the target by constructing as many complex statements as possible. This way had achieved great success in DOM , but failed in recent years. Since 2015 most browser researchers are foucing on javascript energe, especially JIT engine. Most of the old fuzzer use the free combination of corpus to construct JS statement, which will generate a lot of meaningless error codes. When the engine execute these codes, it will throw exceptions such as RuntimeError,which will terminates the program early. In order for the sample to continue, Fuzzer will add a large amount of TryCatch statements to block these exceptions. This method is naturally understandable for DOM-Fuzzer, but in the JS engine, especially the JIT engine, TryCatch would greatly affects their performance, so that most functions can never be reseached. What’s more, this method require the full coverage of the grammar by the Fuzzer itself, and those places the corpus cannot cover will never be accessed, which would greatly decrease the attack surface.

针对目前 JS 引擎 Fuzz 遇到的这种困境,笔者在 18 年 6 月提出了一套全新的 fuzz 方案 ———— AST Fuzz。以 JS 语言解析而成的 AST 树作为媒介进行模糊测试。这种方法不仅可以有效的避免无意义代码的生成,还可以大大提升语法的覆盖率,并且在实际应用过程中还有着意想不到的收获。

In response to this dilemma encountered by the current Fuzz, I proposed a new fuzz idea in June 18th – AST Fuzz! This idea is focus on IR, The AST tree parsed in JS language is used as a medium for fuzzing. This method can not only effectively avoid the generation of meaningless code, but also greatly improve the grammar coverage, and there are unexpected gains in the actual applying.

Read More

Babel HelloWorld

由于一个偶然的契机,笔者接触到了一个 js 处理神器 ———— babel,可以用来方便快速的处理 js 代码,实现自定义功能。笔者花了几天的时间对 babel 的实现原理和使用方法进行了简单的梳理,特此记录,以备之后的学习。

babel 的官方网站上有着较为完备的文档,其 GitHub 上也有各个语言版本的详细使用手册,笔者在学习过程中主要参考了以下两个网站。

https://www.sitepoint.com/understanding-asts-building-babel-plugin/

https://github.com/jamiebuilds/babel-handbook/blob/master/translations/zh-Hans/plugin-handbook.md#toc-stages-of-babel

基础

Babel 是一个用于操作 js 的框架,它为用户提供了方便的接口可以通过插件自定义操作。

Babel 的主要思想就是通过操作 js 代码对应的 AST 树得到另一个符合语法的 js。

Read More

EVM Simulator

CTF 的时候遇到一个以太坊相关的题目,只有合约的 opcode,最后在纸上用手演算做出来的。当时就感觉如果有一个能直接调试 opcode 的东西就好了。在 Salt 大佬 的建议下,花了一天的时间改了改 octopus,攒了一个简易的调试器。

https://github.com/Hearmen/evm_emulator

EVM emulator

这个调试器是基于 octopus 开发的。 octopus 是研究者 pventuzelo 开发的一款以太坊逆向工具,使用这个工具可以很方便的将大部分 ETH 上的 opcode 编译成 CFG

调试器为了方便,直接在 octopus 的源码上进行了修改,以后可能会把这一部分抠出来。

有了 octopus 的基础,调试器实现起来就非常方便。octopus已经将将 opcode 的执行流程进行了分析,基于这个分析我们只需要实现一个 stack,一个 memory 和一个 storage 即可。

Read More

ETH Varible Overlap

经过对 ETH 以及其运行时环境 EVM 的初步研究,我们在合约层面和虚拟机层面分别发现了一些问题,其中有些问题可能导致非常严重的后果,值得 ETH 智能合约的开发者注意。变量覆盖问题就是其中非常典型的一种,有很多以太坊安全研究人员都已经发现了这个问题,但是分析大都停留在结果层面,没有做进一步的探讨。本文将从变量覆盖这个问题入手结合 EVM 虚拟机和 Solidity 编译器的源码详细分析这个问题的表现,可能产生的影响,以及最终导致这个问题的 solidity 编译器根源所在。

变量覆盖

在某些合约中,我们发现在函数内部对 struct 类型的临时变量进行修改,会在某些情况下覆盖已有的全局变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
pragma solidity ^0.4.23;
// A Locked Name Registrar
contract Locked {
bool public unlocked = false; // registrar locked, no name updates
struct NameRecord { // map hashes to addresses
bytes32 name; //
address mappedAddress;
}
mapping(address => NameRecord) public registeredNameRecord; // records who registered names
mapping(bytes32 => address) public resolve; // resolves hashes to addresses
function register(bytes32 _name, address _mappedAddress) public {
// set up the new NameRecord
NameRecord newRecord;
newRecord.name = _name;
newRecord.mappedAddress = _mappedAddress;
resolve[_name] = _mappedAddress;
registeredNameRecord[msg.sender] = newRecord;
require(unlocked); // only allow registrations if contract is unlocked
}
}

合约的源码如上面所示,在正常情况下,由于合约并没有提供修改 unlocked 的接口,因此不太可能达到修改它的目的。但是实际上我们在测试中发现,只要调用合约的 register 方法就可以修改 unlocked。

Read More

EOS 搭建指南

EOS 与 ETH 相比,其架构更加复杂,由于其主链刚刚上线不久因此 EOS 中的合约数量也不多,为了学习和理解 EOS 的相关知识,笔者跟随 EOS 官网 的教程对 EOS 进行了初步的了解,由于网上目前的资料参差不齐,因此将学习过程中遇到的问题记录在此,以备查阅。

EOS 源码编译

编译过程比较繁琐,网上也有很多教程,这里不再赘述,仅记一下笔者搭建过程中遇到的一些坑。由于 EOS 代码版本迭代十分频繁,因此网上许多基于旧版本 EOS 源码的搭建教程并不适用。这里推荐使用其源码中提供的脚本 eosio_build.sh 完成工作。这个脚本会根据编译时的实际环境调用不同系统的专用脚本来完成工作,笔者的环境是 Ubuntu_16 因此最后会调用 /scripts/eosio_build_ubuntu.sh 进行编译。其中比较重要的两个点是首先需要安装最新版本的 boost ,其次是需要安装 OpenSSL,安装完成之后一般来说就可以成功的编译起来了。

如果编译过程中提示系统硬件配置等信息不符合要求,如内存硬盘等等不够大,可以直接修改脚本中的判断条件。比如默认状态下脚本要求 EOS 编译的内存要有 8G ,但是如果我们在虚拟机中进行编译内存常常不满足要求,此时只需要修改用于进行硬件检测的编译脚本即可,将这个判断条件改小。

1
2
3
4
5
if [ "${MEM_MEG}" -lt 7000 ]; then
printf "\\tYour system must have 7 or more Gigabytes of physical memory installed.\\n"
printf "\\tExiting now.\\n"
exit 1
fi

Read More

Ethernaut Zeppelin 学习

https://ethernaut.zeppelin.solutions/ 网站上列出了一系列智能合约在编写过程中可能产生的问题,可以帮助初学者很好的了解智能合约

https://github.com/OpenZeppelin/ethernaut/blob/master/gamedata/descriptions/pages/help.md 帮助文档

花了一整天假装自己 AC 了所有的题目,这里把过程中的一点总结和经验记录一下,留以备忘

Hello

题目是用来帮助熟悉平台的。这里简单记录一下平台和 Remix 编辑器的基本操作

平台首先需要安装 MetaMask 插件并登陆账户,如果打开平台时没有登陆账户,那么登陆之后需要刷新页面使账户信息生效。

Remix 是非常好用的在线编辑平台,其不仅可以编译 solidity 代码生成自己的测试合约,也可以根据地址映射链上已有的合约

在顶部菜单中可以选择合约运行的环境,运行合约的账户。并且可以配置执行合约代码时所带有的 gas 和 value 相当于调用合约时的 .value().gas()

在执行了合约代码之后可以点击下方的 debug 按钮对合约代码进行调试

调试功能十分强大,可以查看运行时的栈,memory,opcode,等几乎所有的 EVM 关键信息

Read More

Bypass ACG With OpenProcess

https://bugs.chromium.org/p/project-zero/issues/detail?id=1435&can=1&q=&start=1200 p0 研究者 ifratric 提出的一种绕过 ACG 保护的方案,即通过修改同一 AppContainer 中的其他 MicrosoftEdgeCp.exe 进程的内存来阻止另一个进程开启 ACG 保护

ACG 的开启

进程的 ACG 需要调用函数 SetProcessMitigationPolicy.aspx) 或者 ZwSetInformationProcess 来开启。这里我们主要关注 SetProcessMitigationPolicy ,函数的原型如下

1
2
3
4
5
BOOL WINAPI SetProcessMitigationPolicy(
_In_ PROCESS_MITIGATION_POLICY MitigationPolicy,
_In_ PVOID lpBuffer,
_In_ SIZE_T dwLength
);

第一个参数指定要设定的缓解策略类型,第二个参数根据第一个参数指定不同的 Policy 数据,第三个参数指定第二个参数的长度。

Read More

MapViewOfSection and Shared-Memory

之前对于 UnmapViewOfFile 的分析中留了一个坑,即使用 SECTION 在进程之间共享内存的情况。拖了几个星期,终于把这个问题稍稍搞明白了一点。这里将相关的知识点记录一下。

问题描述

微软对于 UnmapViewOfFile 绕过 ACG 这种攻击方式的补丁是在 JIT 进程端移除了 VirtualAlloc/VirtualProtect 操作,从而切断了将其他属性内存转化为可执行页的路径。于是笔者产生了疑问:在不使用 VirtualAlloc/VirtualProtect 的情况下 Render 中的内存页是如何 commit 的

在打上补丁之后,内存的分配操作只剩下 AllocLocalView ,查看函数源码

1
2
3
4
5
6
AllocLocalView{
//...
process = GetCurrentProcess();
NtdllLibrary::Instance->MapViewOfSection(sectionHandle, process, &address, NULL, viewSize, &mapOffset, &viewSize, NtdllLibrary::ViewUnmap, NULL, flags);
//...
}

代码中调用 MapViewOfSection 在当前进程中为这个用来共享内存的 Section ,其中 CommitSize 参数为 viewSize。实际调试 Edge, 在这个调用上下断点 JIT 进程断在此处,此时 Render 中的虚拟内存地址已经由之前那次 Map 操作确定了,查看 Render 进程中对应的虚拟地址空间

1
2
3
4
5
6
7
8
9
0:001> dd 1ec`e6240000
000001ec`e6240000 ???????? ???????? ???????? ????????
000001ec`e6240010 ???????? ???????? ???????? ????????
000001ec`e6240020 ???????? ???????? ???????? ????????
000001ec`e6240030 ???????? ???????? ???????? ????????
000001ec`e6240040 ???????? ???????? ???????? ????????
000001ec`e6240050 ???????? ???????? ???????? ????????
000001ec`e6240060 ???????? ???????? ???????? ????????
000001ec`e6240070 ???????? ???????? ???????? ????????

执行这次函数调用,再次查看 Render 进程地址,发现此时对应的虚拟地址已经映射了物理地址

1
2
3
4
5
6
7
8
9
0:001> dd 1ec`e6240000
000001ec`e6240000 00000000 00000000 00000000 00000000
000001ec`e6240010 00000000 00000000 00000000 00000000
000001ec`e6240020 00000000 00000000 00000000 00000000
000001ec`e6240030 00000000 00000000 00000000 00000000
000001ec`e6240040 00000000 00000000 00000000 00000000
000001ec`e6240050 00000000 00000000 00000000 00000000
000001ec`e6240060 00000000 00000000 00000000 00000000
000001ec`e6240070 00000000 00000000 00000000 00000000

Read More