1-21 安卓文件分析-dex

库文件:
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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值