1 Star 1 Fork 0

kin9-0rz / goapk

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
dex.go 7.93 KB
一键复制 编辑 原始数据 按行查看 历史
kin9-0rz 提交于 2021-02-02 16:19 . feat: 🎸 init
package dex
import (
"errors"
"io"
"io/ioutil"
)
// File Dex文件结构
type File struct {
raw []byte
stream Reader
link SizeOff // 静态链接文件中使用的数据
mapOff int // map_list的偏移
stringIds SizeOff // 字符串标识符列表
typeIds SizeOff // 类型标识符列表
protoIds SizeOff // 方法原型标识符列表
fieldIds SizeOff // 字段标识符列表
methodIds SizeOff // 方法标识符列表
classDefs SizeOff // 类定义列表
data SizeOff // map_list 数据区
dexClasses []Class // 存放field、method数据
Strings []string // 存放字符串表的数据
}
// NewFile 从APK直接读取Dex到内容,从内存中初始化File
func NewFile(reader io.Reader) (File, error) {
dexFile := File{
dexClasses: make([]Class, 0),
}
dexBytes, _ := ioutil.ReadAll(reader)
// dexFile.raw, _ = ioutil.ReadAll(reader)
dexFile.raw = dexBytes
dexFile.stream = Reader{
data: dexFile.raw,
pos: 0,
}
// dexFile.seek(0)
// 跳过
dexFile.stream.pos = 0x20
dexBytesLen := len(dexBytes)
if dexBytesLen != int(dexFile.stream.U32()) {
return dexFile, errors.New("Dex长度异常!")
}
if dexFile.stream.U32() != 0x70 {
return dexFile, errors.New("Dex头长度异常!")
}
if dexFile.stream.U32() != 0x12345678 {
return dexFile, errors.New("Dex endian_tag异常!")
}
dexFile.link = dexFile.stream.readSizeOff()
dexFile.mapOff = int(dexFile.stream.U32())
dexFile.stringIds = dexFile.stream.readSizeOff()
dexFile.typeIds = dexFile.stream.readSizeOff()
dexFile.protoIds = dexFile.stream.readSizeOff()
dexFile.fieldIds = dexFile.stream.readSizeOff()
dexFile.methodIds = dexFile.stream.readSizeOff()
dexFile.classDefs = dexFile.stream.readSizeOff()
dexFile.data = dexFile.stream.readSizeOff()
dexFile.Strings = make([]string, dexFile.stringIds.size)
// classes 对象数组
return dexFile, nil
}
// ParseStrings 解析字符串表
func (d *File) ParseStrings() {
for i := 0; i < d.stringIds.size; i++ {
s := d.String(i)
d.Strings = append(d.Strings, s)
}
}
// Stream 从Dex文件中,读一段数据 (TODO 这种情况是否会增加内存?)
func (d *File) Stream(offset int) Reader {
return Reader{
data: d.raw,
pos: offset,
}
}
func (d *File) String(index int) string {
s1 := d.Stream(d.stringIds.off + index*4)
dataOff := s1.U32()
s2 := d.Stream(int(dataOff))
cstrOff := s2.Uleb128()
return s2.ReadCStr(int(cstrOff))
}
// Type 获取类名/类型
func (d *File) Type(index int) string {
offset := d.typeIds.off + index*4
stream := d.Stream(offset)
strIdx := stream.U32()
return d.String(int(strIdx))
}
func (d *File) parseClassDefs() {
for i := 0; i < d.classDefs.size; i++ {
dexClass := NewClass(d, d.classDefs.off, i)
dexClass.parseData()
d.dexClasses = append(d.dexClasses, dexClass)
}
}
// Class 相关
type Class struct {
dexFile *File // 指针才对,而不是传值
className string
supperClassName string
access int
dataOff int
data ClassData
constantValuesOff int
}
// NewClass 实例化Class对象
func NewClass(dexFile *File, offset int, idx int) Class {
dexClass := Class{}
dexClass.dexFile = dexFile
stream := dexFile.Stream(offset + idx*32)
dexClass.className = dexFile.Type(int(stream.U32()))
dexClass.access = int(stream.U32())
dexClass.supperClassName = dexFile.Type(int(stream.U32()))
// skip interface list
stream.U32()
// interfaceOff := stream.U32()
// println("interfaceOff", interfaceOff)
// if interfaceOff != 0 {
// istream := dexFile.Stream(interfaceOff)
// size := istream.U32()
// for i := 0; i < size; i++ {
// println("interface", dexFile.Type(int(istream.U16())))
// }
// }
stream.U32()
stream.U32()
dexClass.dataOff = int(stream.U32())
dexClass.constantValuesOff = int(stream.U32())
return dexClass
}
func (d *Class) parseData() {
d.data = NewClassData(d.dexFile, d.dataOff)
// TODO 解析field数据。暂时没必要。
// fmt.Print(d.constantValuesOff)
// if d.constantValuesOff > 0 {
// stream := d.dexFile.Stream(d.constantValuesOff)
// fmt.Println(stream) // 解析洗后的数据
// }
}
// Field Field结构
type Field struct {
dex *File
id FieldID
access int
constantValue string
}
// NewField New Field
func NewField(dex *File, fieldIdx int, access int) Field {
f := Field{}
f.dex = dex
f.id = NewFieldID(dex, fieldIdx)
f.access = access
f.constantValue = ""
return f
}
// FieldID FieldID结构
type FieldID struct {
className string
desc string
name string
}
// NewFieldID 新建FieldID对象
func NewFieldID(dex *File, fieldIdx int) FieldID {
fid := FieldID{}
stream := dex.Stream(dex.fieldIds.off + fieldIdx*8)
fid.className = dex.Type(int(stream.U16()))
fid.desc = dex.Type(int(stream.U16()))
fid.name = dex.String(int(stream.U32()))
return fid
}
// Method 方法结构
type Method struct {
dex *File
id MethodID
access int
codeOff int
code CodeItem
}
// NewMethod new method obj
func NewMethod(dex *File, methodIdx int, acess int, codeOff int) Method {
m := Method{}
m.dex = dex
m.id = NewMethodID(dex, methodIdx)
m.access = acess
m.codeOff = codeOff
return m
}
// MethodID MethodID结构
type MethodID struct {
className string
name string
returnType string
paramTypes string
sign string
desc string
}
// NewMethodID new method id
func NewMethodID(dex *File, methodIdx int) MethodID {
mi := MethodID{}
stream := dex.Stream(dex.methodIds.off + methodIdx*8)
mi.className = dex.Type(int(stream.U16()))
protoIdx := int(stream.U16())
mi.name = dex.String(int(stream.U32()))
// fmt.Println(mi.className, mi.name)
stream2 := dex.Stream(dex.protoIds.off + protoIdx*12)
// shortyIdx := stream2.U32() #skip
stream2.pos += 4
returnIdx := stream2.U32()
parametersOff := int(stream2.U32())
mi.returnType = dex.Type(int(returnIdx))
mi.paramTypes = TypeList(dex, parametersOff)
mi.sign = "(" + mi.paramTypes + ")" + mi.returnType
mi.desc = mi.className + "->" + mi.name + mi.sign
return mi
}
// TypeList 获取参数列表
func TypeList(dex *File, offset int) string {
p := ""
if offset == 0 {
return p
}
stream := dex.Stream(offset)
size := int(stream.U32())
for i := 0; i < size; i++ {
p += dex.Type(int(stream.U16()))
}
return p
}
func (mid *MethodID) getSpacedParamTypes(isstatic int) {
}
// CodeItem 代码结构
type CodeItem struct {
nregs int // register_size
insnsSize int
tries int
listOff int
bytecode int // TODO
}
// NewCodeItem New CodeItem
func NewCodeItem(dex *File, offset int) CodeItem {
codeItem := CodeItem{}
// stream := dex.Stream(offset)
// codeItem.nregs = stream.U16()
// insSize := stream.U16()
// outsSize := stream.U16()
// triesSize := stream.U16()
// debugOff := stream.U32()
// codeItem.insnsSize = stream.U32()
// insnsStartPos := stream.pos
// TODO ...
return codeItem
}
// ClassData Class 中的数据,包含字段、方法。
type ClassData struct {
fileds []Field
methods []Method
}
// NewClassData 初始化ClassData
func NewClassData(dexFile *File, offset int) ClassData {
classData := ClassData{}
// 如果为0,表示没有fields、methods
if offset != 0 {
classData.parse(dexFile, dexFile.Stream(offset))
}
return classData
}
func (c *ClassData) parse(dexFile *File, stream Reader) {
numstatic := int(stream.Uleb128())
numinstance := int(stream.Uleb128())
numdirect := int(stream.Uleb128())
numvirtual := int(stream.Uleb128())
for _, i := range []int{numstatic, numinstance} {
fieldIdx := 0
for j := 0; j < i; j++ {
fieldIdx += int(stream.Uleb128())
ac := int(stream.Uleb128())
f := NewField(dexFile, fieldIdx, ac)
c.fileds = append(c.fileds, f)
}
}
for _, i := range []int{numdirect, numvirtual} {
mtdIdx := 0
for j := 0; j < i; j++ {
mtdIdx += int(stream.Uleb128())
access := int(stream.Uleb128())
codeOff := int(stream.Uleb128())
m := NewMethod(dexFile, mtdIdx, access, codeOff)
c.methods = append(c.methods, m)
}
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/kin9-0rz/goapk.git
git@gitee.com:kin9-0rz/goapk.git
kin9-0rz
goapk
goapk
v1.1.4

搜索帮助

344bd9b3 5694891 D2dac590 5694891