dex理論基礎
dex檔案作為android的的主要格式,它是可以直接在Dalvik虛擬機中加載運行的檔案,
dex 檔案可以分為3個模塊,頭檔案(header)、索引區(xxxx_ids)、資料區(data),
我們在進行對android加固和脫殼的時候都需要進行和dex檔案格式打交道,
它在系統的定義是定義在/art/runtime/dex_file檔案中的,下面對dex檔案格式的幾個關鍵函式進行分析,
CheckMagicAndVersion 函式
//判斷dex檔案中魔法值dex后面所跟的版本
bool DexFile::CheckMagicAndVersion(std::string* error_msg) const {
//dex檔案魔法值是存在在頭檔案header中的,所有通過header就可以獲取魔法值
if (!IsMagicValid(header_->magic_)) {
std::ostringstream oss;
oss << "Unrecognized magic number in " << GetLocation() << ":"
<< " " << header_->magic_[0]
<< " " << header_->magic_[1]
<< " " << header_->magic_[2]
<< " " << header_->magic_[3];
*error_msg = oss.str();
return false;
}
//判斷獲取的魔法值是否有效
if (!IsVersionValid(header_->magic_)) {
std::ostringstream oss;
oss << "Unrecognized version number in " << GetLocation() << ":"
<< " " << header_->magic_[4]
<< " " << header_->magic_[5]
<< " " << header_->magic_[6]
<< " " << header_->magic_[7];
*error_msg = oss.str();
return false;
}
return true;
}
DexFile函式定義
//獲取決議dex檔案格式
DexFile::DexFile(const byte* base, size_t size,
const std::string& location,
uint32_t location_checksum,
MemMap* mem_map)
: begin_(base),
size_(size),
location_(location),
location_checksum_(location_checksum),
mem_map_(mem_map),
header_(reinterpret_cast<const Header*>(base)),
string_ids_(reinterpret_cast<const StringId*>(base + header_->string_ids_off_)),
type_ids_(reinterpret_cast<const TypeId*>(base + header_->type_ids_off_)),
field_ids_(reinterpret_cast<const FieldId*>(base + header_->field_ids_off_)),
method_ids_(reinterpret_cast<const MethodId*>(base + header_->method_ids_off_)),
proto_ids_(reinterpret_cast<const ProtoId*>(base + header_->proto_ids_off_)),
class_defs_(reinterpret_cast<const ClassDef*>(base + header_->class_defs_off_)),
find_class_def_misses_(0),
class_def_index_(nullptr),
build_class_def_index_mutex_("DexFile index creation mutex") {
CHECK(begin_ != NULL) << GetLocation();
CHECK_GT(size_, 0U) << GetLocation();
}
FindClassDef 函式定義
//查找dex檔案中的class_ids資料
const DexFile::ClassDef* DexFile::FindClassDef(uint16_t type_idx) const {
//獲取class的數量
size_t num_class_defs = NumClassDefs();
for (size_t i = 0; i < num_class_defs; ++i) {
const ClassDef& class_def = GetClassDef(i);
if (class_def.class_idx_ == type_idx) {
return &class_def;
}
}
return NULL;
}
FindFieldId 函式定義
//查找dex檔案中的fileId
const DexFile::FieldId* DexFile::FindFieldId(const DexFile::TypeId& declaring_klass,
const DexFile::StringId& name,
const DexFile::TypeId& type) const {
// Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
const uint16_t class_idx = GetIndexForTypeId(declaring_klass);
const uint32_t name_idx = GetIndexForStringId(name);
const uint16_t type_idx = GetIndexForTypeId(type);
int32_t lo = 0;
int32_t hi = NumFieldIds() - 1;
while (hi >= lo) {
int32_t mid = (hi + lo) / 2;
//獲取FileId資料
const DexFile::FieldId& field = GetFieldId(mid);
if (class_idx > field.class_idx_) {
lo = mid + 1;
} else if (class_idx < field.class_idx_) {
hi = mid - 1;
} else {
if (name_idx > field.name_idx_) {
lo = mid + 1;
} else if (name_idx < field.name_idx_) {
hi = mid - 1;
} else {
if (type_idx > field.type_idx_) {
lo = mid + 1;
} else if (type_idx < field.type_idx_) {
hi = mid - 1;
} else {
//成功回傳獲取到的fileId資料
return &field;
}
}
}
}
return NULL;
}
FindMethodId 函式定義
該函式多所對應的是dex檔案中的Method table資料
//查找dex檔案中的FindMethodId資料
const DexFile::MethodId* DexFile::FindMethodId(const DexFile::TypeId& declaring_klass,
const DexFile::StringId& name,
const DexFile::ProtoId& signature) const {
// Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
const uint16_t class_idx = GetIndexForTypeId(declaring_klass);
const uint32_t name_idx = GetIndexForStringId(name);
const uint16_t proto_idx = GetIndexForProtoId(signature);
int32_t lo = 0;
//獲取dex檔案中的所有MethodIds的數量
int32_t hi = NumMethodIds() - 1;
//當數量大于0
while (hi >= lo) {
//折半的方式進去一個個獲取
int32_t mid = (hi + lo) / 2;
const DexFile::MethodId& method = GetMethodId(mid);
if (class_idx > method.class_idx_) {
lo = mid + 1;
} else if (class_idx < method.class_idx_) {
hi = mid - 1;
} else {
if (name_idx > method.name_idx_) {
lo = mid + 1;
} else if (name_idx < method.name_idx_) {
hi = mid - 1;
} else {
if (proto_idx > method.proto_idx_) {
lo = mid + 1;
} else if (proto_idx < method.proto_idx_) {
hi = mid - 1;
} else {
return &method;
}
}
}
}
return NULL;
}
FindStringId 函式
該函式對應的是在dex檔案中的String table上
//查找dex檔案中的StringId資料
const DexFile::StringId* DexFile::FindStringId(const char* string) const {
int32_t lo = 0;
//獲取dex檔案中的所有StringId是數量
int32_t hi = NumStringIds() - 1;
while (hi >= lo) {
int32_t mid = (hi + lo) / 2;
const DexFile::StringId& str_id = GetStringId(mid);
const char* str = GetStringData(str_id);
int compare = CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(string, str);
if (compare > 0) {
lo = mid + 1;
} else if (compare < 0) {
hi = mid - 1;
} else {
return &str_id;
}
}
return NULL;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/294972.html
標籤:其他
