Android中的Apk的加固加壳原理解析和实现Word文档下载推荐.docx

上传人:b****5 文档编号:20280913 上传时间:2023-01-21 格式:DOCX 页数:35 大小:31.88KB
下载 相关 举报
Android中的Apk的加固加壳原理解析和实现Word文档下载推荐.docx_第1页
第1页 / 共35页
Android中的Apk的加固加壳原理解析和实现Word文档下载推荐.docx_第2页
第2页 / 共35页
Android中的Apk的加固加壳原理解析和实现Word文档下载推荐.docx_第3页
第3页 / 共35页
Android中的Apk的加固加壳原理解析和实现Word文档下载推荐.docx_第4页
第4页 / 共35页
Android中的Apk的加固加壳原理解析和实现Word文档下载推荐.docx_第5页
第5页 / 共35页
点击查看更多>>
下载资源
资源描述

Android中的Apk的加固加壳原理解析和实现Word文档下载推荐.docx

《Android中的Apk的加固加壳原理解析和实现Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《Android中的Apk的加固加壳原理解析和实现Word文档下载推荐.docx(35页珍藏版)》请在冰豆网上搜索。

Android中的Apk的加固加壳原理解析和实现Word文档下载推荐.docx

1)checksum

文件校验码,使用alder32算法校验文件除去maigc,checksum外余下的所有文件区域,用于检查文件错误。

2)signature

使用SHA-1算法hash除去magic,checksum和signature外余下的所有文件区域,用于唯一识别本文件。

3)file_size

Dex文件的大小。

为什么说我们只需要关注这三个字段呢?

因为我们需要将一个文件(加密之后的源Apk)写入到Dex中,那么我们肯定需要修改文件校验码(checksum).因为他是检查文件是否有错误。

那么signature也是一样,也是唯一识别文件的算法。

还有就是需要修改dex文件的大小。

不过这里还需要一个操作,就是标注一下我们加密的Apk的大小,因为我们在脱壳的时候,需要知道Apk的大小,才能正确的得到Apk。

那么这个值放到哪呢?

这个值直接放到文件的末尾就可以了。

所以总结一下我们需要做:

修改Dex的三个文件头,将源Apk的大小追加到壳dex的末尾就可以了。

我们修改之后得到新的Dex文件样式如下:

那么我们知道原理了,下面就是代码实现了。

所以这里有三个工程:

1、源程序项目(需要加密的Apk)

2、脱壳项目(解密源Apk和加载Apk)

3、对源Apk进行加密和脱壳项目的Dex的合并

三、项目案例

下面先来看一下源程序

1、需要加密的源程序Apk项目:

ForceApkObj

需要一个Application类,这个到后面说为什么需要:

MyApplication.Java

[java]viewplaincopy

packagecom.example.forceapkobj;

importandroid.app.Application;

importandroid.util.Log;

publicclassMyApplicationextendsApplication{

@Override

publicvoidonCreate(){

super.onCreate();

Log.i("

demo"

"

sourceapkonCreate:

"

+this);

}

}

就是打印一下onCreate方法。

MainActivity.Java

importandroid.app.Activity;

importandroid.content.Intent;

importandroid.os.Bundle;

importandroid.view.View;

importandroid.view.View.OnClickListener;

importandroid.widget.TextView;

publicclassMainActivityextendsActivity{

protectedvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

TextViewcontent=newTextView(this);

content.setText("

IamSourceApk"

);

content.setOnClickListener(newOnClickListener(){

publicvoidonClick(Viewarg0){

Intentintent=newIntent(MainActivity.this,SubActivity.class);

startActivity(intent);

}});

setContentView(content);

app:

+getApplicationContext());

也是打印一下内容。

2、加壳程序项目:

DexShellTools

加壳程序其实就是一个Java工程,因为我们从上面的分析可以看到,他的工作就是加密源Apk,然后将其写入到脱壳Dex文件中,修改文件头,得到一个新的Dex文件即可。

看一下代码:

packagecom.example.reforceapk;

importjava.io.ByteArrayOutputStream;

importjava.io.File;

importjava.io.FileInputStream;

importjava.io.FileOutputStream;

importjava.io.IOException;

importjava.security.MessageDigest;

importjava.security.NoSuchAlgorithmException;

importjava.util.zip.Adler32;

publicclassmymain{

/**

*@paramargs

*/

publicstaticvoidmain(String[]args){

//TODOAuto-generatedmethodstub

try{

FilepayloadSrcFile=newFile("

force/ForceApkObj.apk"

//需要加壳的程序

System.out.println("

apksize:

+payloadSrcFile.length());

FileunShellDexFile=newFile("

force/ForceApkObj.dex"

//解客dex

byte[]payloadArray=encrpt(readFileBytes(payloadSrcFile));

//以二进制形式读出apk,并进行加密处理//对源Apk进行加密操作

byte[]unShellDexArray=readFileBytes(unShellDexFile);

//以二进制形式读出dex

intpayloadLen=payloadArray.length;

intunShellDexLen=unShellDexArray.length;

inttotalLen=payloadLen+unShellDexLen+4;

//多出4字节是存放长度的。

byte[]newdex=newbyte[totalLen];

//申请了新的长度

//添加解壳代码

System.arraycopy(unShellDexArray,0,newdex,0,unShellDexLen);

//先拷贝dex内容

//添加加密后的解壳数据

System.arraycopy(payloadArray,0,newdex,unShellDexLen,payloadLen);

//再在dex内容后面拷贝apk的内容

//添加解壳数据长度

System.arraycopy(intToByte(payloadLen),0,newdex,totalLen-4,4);

//最后4为长度

//修改DEXfilesize文件头

fixFileSizeHeader(newdex);

//修改DEXSHA1文件头

fixSHA1Header(newdex);

//修改DEXCheckSum文件头

fixCheckSumHeader(newdex);

Stringstr="

force/classes.dex"

;

Filefile=newFile(str);

if(!

file.exists()){

file.createNewFile();

FileOutputStreamlocalFileOutputStream=newFileOutputStream(str);

localFileOutputStream.write(newdex);

localFileOutputStream.flush();

localFileOutputStream.close();

}catch(Exceptione){

e.printStackTrace();

//直接返回数据,读者可以添加自己加密方法

privatestaticbyte[]encrpt(byte[]srcdata){

for(inti=0;

i<

srcdata.length;

i++){

srcdata[i]=(byte)(0xFF^srcdata[i]);

returnsrcdata;

*修改dex头,CheckSum校验码

*@paramdexBytes

privatestaticvoidfixCheckSumHeader(byte[]dexBytes){

Adler32adler=newAdler32();

adler.update(dexBytes,12,dexBytes.length-12);

//从12到文件末尾计算校验码

longvalue=adler.getValue();

intva=(int)value;

byte[]newcs=intToByte(va);

//高位在前,低位在前掉个个

byte[]recs=newbyte[4];

for(inti=0;

i<

4;

i++){

recs[i]=newcs[newcs.length-1-i];

System.out.println(Integer.toHexString(newcs[i]));

System.arraycopy(recs,0,dexBytes,8,4);

//效验码赋值(8-11)

System.out.println(Long.toHexString(value));

System.out.println();

*int转byte[]

*@paramnumber

*@return

publicstaticbyte[]intToByte(intnumber){

byte[]b=newbyte[4];

for(inti=3;

i>

=0;

i--){

b[i]=(byte)(number%256);

number>

>

=8;

returnb;

*修改dex头sha1值

*@throwsNoSuchAlgorithmException

privatestaticvoidfixSHA1Header(byte[]dexBytes)

throwsNoSuchAlgorithmException{

MessageDigestmd=MessageDigest.getInstance("

SHA-1"

md.update(dexBytes,32,dexBytes.length-32);

//从32为到结束计算sha--1

byte[]newdt=md.digest();

System.arraycopy(newdt,0,dexBytes,12,20);

//修改sha-1值(12-31)

//输出sha-1值,可有可无

Stringhexstr="

newdt.length;

hexstr+=Integer.toString((newdt[i]&

0xff)+0x100,16)

.substring

(1);

System.out.println(hexstr);

*修改dex头file_size值

privatestaticvoidfixFileSizeHeader(byte[]dexBytes){

//新文件长度

byte[]newfs=intToByte(dexBytes.length);

System.out.println(Integer.toHexString(dexBytes.length));

byte[]refs=newbyte[4];

refs[i]=newfs[newfs.length-1-i];

System.out.println(Integer.toHexString(newfs[i]));

System.arraycopy(refs,0,dexBytes,32,4);

//修改(32-35)

*以二进制读出文件内容

*@paramfile

*@throwsIOException

privatestaticbyte[]readFileBytes(Filefile)throwsIOException{

byte[]arrayOfByte=newbyte[1024];

ByteArrayOutputStreamlocalByteArrayOutputStream=newByteArrayOutputStream();

FileInputStreamfis=newFileInputStream(file);

while(true){

inti=fis.read(arrayOfByte);

if(i!

=-1){

localByteArrayOutputStream.write(arrayOfByte,0,i);

}else{

returnlocalByteArrayOutputStream.toByteArray();

下面来分析一下:

红色部分其实就是最核心的工作:

1>

、加密源程序Apk文件

byte[]payloadArray=encrpt(readFileBytes(payloadSrcFile));

加密算法很简单:

//直接返回数据,读者可以添加自己加密方法

privatestaticbyte[]encrpt(byte[]srcdata){

对每个字节进行异或一下即可。

(说明:

这里是为了简单,所以就用了很简单的加密算法了,其实为了增加破解难度,我们应该使用更高效的加密算法,同事最好将加密操作放到native层去做)

2>

、合并文件:

将加密之后的Apk和原脱壳Dex进行合并

intpayloadLen=payloadArray.length;

intunShellDexLen=unShellDexArray.length;

inttotalLen=payloadLen+unShellDexLen+4;

byte[]newdex=newbyte[totalLen];

//添加解壳代码

System.arraycopy(unShellDexArray,0,newdex,0,unShellDexLen);

//添加加密后的解壳数据

System.arraycopy(payloadArray,0,newdex,unShellDexLen,payloadLen);

3>

、在文件的末尾追加源程序Apk的长度

//添加解壳数据长度

System.arraycopy(intToByte(payloadLen),0,newdex,totalLen-4,4);

4>

、修改新Dex文件的文件头信息:

file_size;

sha1;

check_sum

//修改DEXfilesize文件头

fixFileSizeHeader(newdex);

//修改DEXSHA1文件头

fixSHA1Header(newdex);

//修改DEXCheckSum文件头

fixCheckSumHeader(newdex);

具体修改可以参照之前说的文件头格式,修改指定位置的字节值即可。

这里我们还需要两个输入文件:

、源Apk文件:

ForceApkObj.apk

、脱壳程序的Dex文件:

ForceApkObj.dex

那么第一个文件我们都知道,就是上面的源程序编译之后的Apk文件,那么第二个文件我们怎么得到呢?

这个就是我们要讲到的第三个项目:

脱壳程序项目,他是一个Android项目,我们在编译之后,能够得到他的classes.dex文件,然后修改一下名称就可。

3、脱壳项目:

ReforceApk

在讲解这个项目之前,我们先来了解一下这个脱壳项目的工作:

、通过反射置换android.app.ActivityThread中的mClassLoader为加载解密出APK的DexClassLoader,该DexClassLoader一方面加载了源程序、另一方面以原mClassLoader为父节点,这就保证了即加载了源程序又没有放弃原先加载的资源与系统代码。

关于这部分内容,不了解的同学可以看一下ActivityThread.java的源码:

如何得到系统加载Apk的类加载器,然后我们怎么将加载进来的Apk运行起来等问题都在这篇文章中说到了。

、找到源程序的Application,通过反射建立并运行。

这里需要注意的是,我们现在是加载一个完整的Apk,让他运行起来,那么我们知道一个Apk运行的时候都是有一个Application对象的,这个也是一个程序运行之后的全局类。

所以我们必须找到解密之后的源Apk的Application类,运行的他的onCreate方法,这样源Apk才开始他的运行生命周期。

这里我们如何得到源Apk的Application的类呢?

这个我们后面会说道。

使用meta标签进行设置。

下面来看一下代码:

importjava.io.BufferedInputStream;

importjava.io.ByteArrayInputStream;

importjava.io.DataInputStream;

importjava.lang.ref.WeakReference;

importjava

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 党团工作 > 思想汇报心得体会

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1