库文件:
jar包 ,aar包
dex文件:
dex header头
string_ids
type_ids
proto_ids 索引结构区
field_ids
method_ids
class_def
data 数据区
linked_data 静态链接数据区
struct DesFile{
const DexOptHeader* pOptHeader;//这是啥?
const DexHeader * pHeader;
const DexStringId* pStringIds;
const DexTypeId * pTypeIds;
const DexFieldId* pFieldIds;
const DexMethodId* pMethodIds;
const DexProtoId * pProtoIds;
const DexClassDef* pClassDefs;
const DexLink* pLinkData;
//可能有
const DexClasssLookup * pClassLookup;
const void * pRegisterMapPool;
const u1* baseAddr;//dex file data start
int overhead;
void * auxData;
}
//DexHeader
struct DexHeader {
u1 magic[8]; //dex版本标识
u4 checksum; //adler32检验
u1 signature[KSHA1DigestLen]; // sha-1散列值
u4 fileSize; //整个文件大小
u4 headersize; // dexheader结构大小
u4 endianTag; //字节序标记
u4 linkSize; //链接段大小
u4 linkoff; //链接段的偏移量
u4 mapOff; //dexmaplisr的文件偏移? (虚拟机解析的结构)
u4 stringIdsSize; //dexstringid的个数
u4 stringidsoff; //dexstringid的文件偏移
u4 typeidssize; //类似
u4 typeIdsOff;
u4 protoIdsSize;
u4 protoIds0ff;
u4 fieldIdsSize;
u4 fieldIdsOff;
u4 methodIdsSize;
u4 methodIdsOff;
u4 classDefsSize;
u4 classDefsOff;
u4 dataSize;
u4 dataOff;
}
magic字段“dex.035”
checknum检验是否损坏或修改
headersize占字节数0x70
dalvik虚拟机解析dex文件内容,最终将其映射成dexMapList数据结构,dexheader的mapoff字段指明dexmaplist在dex文件的偏移(ok)
struct DexMapList {
u4 size; //dexmapitem结构的个数
DexMapItem list[1]; //DexMapItem结构
]
struct DexMaoItem {
u2 type;//后面的枚举
u2 unused;
u4 ize;
u4 offset;
};
enum {
kDexTypeHeaderItem 0
kDexTypeStingIdItem 1
kDexTypeTypeIdItem 2
kDexTypeProtoIdItem 3
kDexTypeFieldItem 4
kDexTypeMethodIdItem 5
kDexTypeClassDefItem 6
kDexTypeMapList 0x1000
kDexTypeTypeList 0x1001
kDexTypeAnnotationSetRefList 0x1002
kDexTypeAnnotationSetItem 0x1003
kDexTypeClassDataItem 0x2000
kDexTypeCodeItem 0x2001
kDexTypeStringDataItem 0x2002
kDexTypeDebugInfoItem 0x2003
kDexTypeAnnotationItem 0x2004
kDexTypeEncodedArrayItem 0x2005
kDexTypeAnnotationsDirectoryItem 0x2006
}
(字符串)
struct DexStringId{
u4 stringdataoff; //字符串数据偏移
}
(类型)
struct DexTypeId{
u4 descriptoridx; //指向dexstringid的索引
}
(声明类型)
struct DexProtoId{
u4 shortyidx(方法声明:返回类型和参数组成); //指向dexstringid的索引
u4 returnTypeidx(返回类型字符串);//指向dextypeid列表的索引
u4 parametersoff;(参数,几个,类型) //指向dextypelist的偏移量
};
struct DexTypeList{
u4 size; //dextypeitem有几个
DexTypeItem list[1]; //dextypeitem结构
}
struct DexTypeItem{
u4 typeidx;//指向dextypeid列表的索引
}
struct DexFieldId{//声明字段?
u2 classIdx; //类的类型,指向DexTypeId列表的索引
u2 typeIdx; //字段类型,指向DexTypeId列表的索引
u4 nameIdx; //字段名,指向DexStringId列表的索引
}
(方法声明)
struct DexMethodId{
u2 classIdx;//指向DexTypeId的索引 类的类型
u2 protoIdx;//指向Dexprotoid的索引 声明类型
u4 nameIdx; //方法名 指向DexStringIdx
}
struct DexClassDef{
u4 classIdx; //类的类型 ->DexTypeId索引
u4 accessFlags;//访问标志
u4 superclassIdx;//父类的类型 ->DexTypeId索引
u4 interfacesOff; //接口 ->DexTypeList偏移
u4 sourceFileIdx; //源文件名 ->DexStringId索引
u4 annotationsoff;//->注解(DexAnnotationsDirectoryItem)
u4 classDataOff;//->DexClassData偏移
u4 staticValuesOff;->DexEncodedArray偏移
struct DexClassData{
DexClassDataHeader header;//指定字段与方法的个数
DexField * staticFields;//静态字段
DexField * instanceFields;//实例字段
DexMethod *directMethods;//直接方法
DexMethod * virtualMethods;//虚方法
}
}
struct DexClassDataHeader {
u4 staticFieldsSize;//静态字段个数
u4 instanceFieldsSize;//实例字段个数
u4 directMethodsSize;//直接方法个数
u4 virtualMethodsSize;//虚方法
}
struct DexField{
u4 fieldIdx; //->DexFieldid索引
u4 accessFlags;;访问标志
}
struct DexMethod{
u4 methodIdx; //->DexMethodId索引
u4 accessFlags //->访问标志
u4 codeOff; //->dexcode结构偏移量
};
struct DexCode{
u2 registersSize; //使用寄存器的个数
u2 insSize; //参数个数
u2 outsSize;//调用其他方法数据时用寄存器的个数
u2 triesSize; //tey/catch的个数
u4 debugInfo0ff; //指向调试信息的偏移量
u4 insnsSize; //指令集的个数?
u2 insns[1];//指令集?
}
checksum是第3个字段signature到文件结尾来算adler32
signature是从filesize到文件结尾算sha1
修改dex文件 ida patch后重新签名有两个方法
1.010editor加载脚本DexFixer.1sc
int endian = ReadInt(0x28);
if(endian == 0x12345678) //判断大小端绪
{
LittleEndian();
}
else
{
BigEndian();
}
uchar sha1[20];
ReadBytes(sha1,0xc,20);//读取源文件的sha1
Printf("src sha1: ");
uint i = 0;
for( i=0; i < 20; ++i)
{
Printf("%02x",sha1[i]);
}
Printf("\n");
uchar checksum[20];
ChecksumAlgBytes(CHECKSUM_SHA1,checksum,0x20);//计算patch过dex文件的sha1
Printf("calced sha1:");
for(i = 0 ; i <20 ; ++i )
{
Printf("%02x",checksum[i]);
}
int adler32 = ReadInt(0x8);//读取原文件的checksum
if(Memcmp(checksum,sha1,20) != 0){
WriteBytes(checksum,0xc,20);
} else {
Printf("same sha1\n");
}
int adler32_ = Checksum(CHECKSUM_ADLER32,0xc);
Printf("src adler32: %x\n",adler32);
Printf("calced adler32: %x\n",adler32_);
if(adler32_ != adler32)
{
WriteInt(0x8,adler32_)
}
else {
Printf("same adler32\n");
}
2.dex2jar(d2j-dex-recompute-checksum)
d2j-dex-recompute-checksum -f ./classes.dex
1.改class.dex改签名
2.重新用apktool打包 再签名就行
apktool d 解包 修改smail代码
apktool b 打包
在使用signapk(脚本)签名,就能够安装了
明日计划:
1.AndroidManifest.xml
2.resources.arsc