Flutter逆向技术的探讨与研究(2)
Flutter逆向技术的探讨与研究(2)
我们想办法从头部开始分析
说实话我对C++并不熟悉 导致我在看这些代码的时候非常艰难
好在他们的代码命名非常规范,我连蒙带猜看出了一些东西。
dart如何解析这个快照的头部部分代码在
snapsshot.h
中 这里有个非常关键的标准位
0xdcdcf5f5
在这里被定义为`kMagicValue
`
static const int32_t kMagicValue = 0xdcdcf5f5;
static const intptr_t kMagicOffset = 0;
static const intptr_t kMagicSize = sizeof(int32_t);
static const intptr_t kLengthOffset = kMagicOffset + kMagicSize; //0+32
static const intptr_t kLengthSize = sizeof(int64_t);
static const intptr_t kKindOffset = kLengthOffset + kLengthSize;//0+32+64
static const intptr_t kKindSize = sizeof(int64_t);
static const intptr_t kHeaderSize = kKindOffset + kKindSize;//0+32+64+64 = 160
分析这段代码可以得出三个东西
一个魔数Size
一个kindSize
而且这个kind是个枚举类 大概就是当前的编译快照类型
enum Kind {
kFull, // Full snapshot of an application.
kFullCore, // Full snapshot of core libraries. Agnostic to null safety.
kFullJIT, // Full + JIT code
kFullAOT, // Full + AOT code
kNone, // gen_snapshot
kInvalid
};
一个LengthSize
这个魔数也就是表示如果以这段开头的二进制就是快照的开始。
我们用 elftools 把这里读出来试试
snapshot_stream = BytesIO(snapshot)
snapshot_stream.seek(0)
kMagicValue = snapshot_stream.read(4).hex()
kLengthValue = snapshot_stream.read(8).hex()
kKindValue = snapshot_stream.read(8).hex()
print(kMagicValue)
print(kLengthValue)
print(kKindValue)
输出
f5f5dcdc
fed20b0000000000
0300000000000000
好像有点对得上了
魔数 f5f5dcdc 读出来了
03 kind 对应 AOT快照
fed20b 应该是镜像的大小
我们找到了头来继续往下分析
我找到了一个 SnapshotHeaderReader 类在clustered_snapshot.h
里面
里面正好描写了读出来的几个头部字段
SnapshotHeaderReader(snapshot->kind(),
snapshot->Addr(),
snapshot->length())
接下来是两个字段一个是
verrsion 在 VerifyVersion()
里面说明了他有128的长度
features 字段在 VerifyFeatures()
里面长度
他的长度是在
const char* expected_features = Dart::FeaturesString(isolate_group, (isolate_group == NULL), kind_);
推断出来的 做了一大堆的判断拼接,不过我们可以看到最后的一个字符是 safety
显然是不同的版本这个长度是不同的
我们可以盲测 测试出这个string的长度
我们可以依次读出来
version_hash = snapshot_stream.read(32).decode('UTF-8')
features = snapshot_stream.read(64+64+32+11).decode('UTF-8')
print(version_hash)
print(features)
输出:
9cf77f4405212c45daf608e1cd646852
product no-code_comments no-dwarf_stack_traces_mode lazy_async_stacks no-lazy_dispatchers use_bare_instructions dedup_instructions no-"asserts" arm-eabi softfp null-safety
到这里我先暂时停下了反序列化工作,以为对于C++的不熟悉导致我非常难受。我决定先去学习一波C语言,再回头来翻译这份代码。
template <typename T = intptr_t>
T ReadUnsigned() {
return Read<T>(kEndUnsignedByteMarker);
}