成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

android apk 防止反編譯技術第一篇-加殼技術

移動開發 Android
所謂apk的加殼技術和pc exe的加殼原理一樣,就是在程序的外面再包裹上另外一段代碼,保護里面的代碼不被非法修改或反編譯,在程序運行的時候優先取得程序的控制權做一些我們自己想做的工作。(哈哈,跟病毒的原理差不多)

做android framework方面的工作將近三年的時間了,現在公司讓做一下android apk安全方面的研究,于是最近就在網上找大量的資料來學習。現在將最近學習成果做一下整理總結。學習的這些成果我會做成一個系列慢慢寫出來與大家分享,共同進步。這篇主要講apk的加殼技術,廢話不多說了直接進入正題。

一、加殼技術原理

所謂apk的加殼技術和pc exe的加殼原理一樣,就是在程序的外面再包裹上另外一段代碼,保護里面的代碼不被非法修改或反編譯,在程序運行的時候優先取得程序的控制權做一些我們自己想做的工作。(哈哈,跟病毒的原理差不多)

PC exe的加殼原理如下:

二、android apk加殼實現

要想實現加殼需要解決的技術點如下:

(1)怎么第一時間執行我們的加殼程序?

首先根據上面的原理我們在apk中要想優先取得程序的控制權作為android apk的開發人員都知道Application會被系統第一時間調用而我們的程序也會放在這里執行。

(2)怎么將我們的加殼程序和原有的android apk文件合并到一起?

我們知道android apk最終會打包生成dex文件,我們可以將我們的程序生成dex文件后,將我們要進行加殼的apk和我們dex文件合并成一個文件,然后修改dex文件頭中的checksum、signature 和file_size的信息,并且要附加加殼的apk的長度信息在dex文件中,以便我們進行解殼保證原來apk的正常運行。加完殼后整個文件的結構如下:

(3)怎么將原來的apk正常的運行起來?

按照(2)中的合并方式在當我們的程序首先運行起來后,逆向讀取dex文件獲取原來的apk文件通過DexClassLoader動態加載。

具體實現如下:

(1)修改原來apk的AndroidMainfest.xml文件,假如原來apk的AndroidMainfest.xml文件內容如下:

1. <application

2. android:icon="@drawable/ic_launcher"

3. android:label="@string/app_name"

4. android:theme="@style/AppTheme" android:name="com.android.MyApplication" >

5. </application>

修改后的內容如下:

1. <application

2. android:icon="@drawable/ic_launcher"

3. android:label="@string/app_name"

4. android:theme="@style/AppTheme" android:name="com.android.shellApplication" >

5. <meta-data android:name="APPLICATION_CLASS_NAME" android:value="com.android.MyApplication"/>

6. </application>

com.android.shellApplication這個就是我們的程序的的application的名稱,而

7. <meta-data android:name="APPLICATION_CLASS_NAME" android:value="com.android.MyApplication"/>

是原來的apk的application名稱。

(2)合并文件代碼實現如下:
?

  1. public class ShellTool { 
  2. /** 
  3. * @param args 
  4. */ 
  5. public static void main(String[] args) { 
  6. // TODO Auto-generated method stub 
  7. try { 
  8. File payloadSrcFile = new File("payload.apk");//我們要加殼的apk文件 
  9. File unShellDexFile = new File("classes.dex");//我們的程序生成的dex文件 
  10. byte[] payloadArray = encrpt(readFileBytes(payloadSrcFile)); 
  11. byte[] unShellDexArray = readFileBytes(unShellDexFile); 
  12. int payloadLen = payloadArray.length; 
  13. int unShellDexLen = unShellDexArray.length; 
  14. int totalLen = payloadLen + unShellDexLen +4
  15. byte[] newdex = new byte[totalLen]; 
  16. //添加我們程序的dex 
  17. System.arraycopy(unShellDexArray, 0, newdex, 0, unShellDexLen); 
  18. //添加要加殼的apk文件 
  19. System.arraycopy(payloadArray, 0, newdex, unShellDexLen, 
  20. payloadLen); 
  21. //添加apk文件長度 
  22. System.arraycopy(intToByte(payloadLen), 0, newdex, totalLen-44); 
  23. //修改DEX file size文件頭 
  24. fixFileSizeHeader(newdex); 
  25. //修改DEX SHA1 文件頭 
  26. fixSHA1Header(newdex); 
  27. //修改DEX CheckSum文件頭 
  28. fixCheckSumHeader(newdex); 
  29.  
  30.  
  31. String str = "outdir/classes.dex"
  32. File file = new File(str); 
  33. if (!file.exists()) { 
  34. file.createNewFile(); 
  35.  
  36. FileOutputStream localFileOutputStream = new FileOutputStream(str); 
  37. localFileOutputStream.write(newdex); 
  38. localFileOutputStream.flush(); 
  39. localFileOutputStream.close(); 
  40.  
  41.  
  42. catch (Exception e) { 
  43. // TODO Auto-generated catch block 
  44. e.printStackTrace(); 
  45.  
  46. //直接返回數據,讀者可以添加自己加密方法 
  47. private static byte[] encrpt(byte[] srcdata){ 
  48. return srcdata; 
  49.  
  50.  
  51. private static void fixCheckSumHeader(byte[] dexBytes) { 
  52. Adler32 adler = new Adler32(); 
  53. adler.update(dexBytes, 12, dexBytes.length - 12); 
  54. long value = adler.getValue(); 
  55. int va = (int) value; 
  56. byte[] newcs = intToByte(va); 
  57. byte[] recs = new byte[4]; 
  58. for (int i = 0; i < 4; i++) { 
  59. recs[i] = newcs[newcs.length - 1 - i]; 
  60. System.out.println(Integer.toHexString(newcs[i])); 
  61. System.arraycopy(recs, 0, dexBytes, 84); 
  62. System.out.println(Long.toHexString(value)); 
  63. System.out.println(); 
  64.  
  65.  
  66. public static byte[] intToByte(int number) { 
  67. byte[] b = new byte[4]; 
  68. for (int i = 3; i >= 0; i--) { 
  69. b[i] = (byte) (number % 256); 
  70. number >>= 8
  71. return b; 
  72.  
  73.  
  74. private static void fixSHA1Header(byte[] dexBytes) 
  75. throws NoSuchAlgorithmException { 
  76. MessageDigest md = MessageDigest.getInstance("SHA-1"); 
  77. md.update(dexBytes, 32, dexBytes.length - 32); 
  78. byte[] newdt = md.digest(); 
  79. System.arraycopy(newdt, 0, dexBytes, 1220); 
  80. String hexstr = ""
  81. for (int i = 0; i < newdt.length; i++) { 
  82. hexstr += Integer.toString((newdt[i] & 0xff) + 0x10016
  83. .substring(1); 
  84. System.out.println(hexstr); 
  85.  
  86.  
  87. private static void fixFileSizeHeader(byte[] dexBytes) { 
  88.  
  89.  
  90. byte[] newfs = intToByte(dexBytes.length); 
  91. System.out.println(Integer.toHexString(dexBytes.length)); 
  92. byte[] refs = new byte[4]; 
  93. for (int i = 0; i < 4; i++) { 
  94. refs[i] = newfs[newfs.length - 1 - i]; 
  95. System.out.println(Integer.toHexString(newfs[i])); 
  96. System.arraycopy(refs, 0, dexBytes, 324); 
  97.  
  98.  
  99. private static byte[] readFileBytes(File file) throws IOException { 
  100. byte[] arrayOfByte = new byte[1024]; 
  101. ByteArrayOutputStream localByteArrayOutputStream = new ByteArrayOutputStream(); 
  102. FileInputStream fis = new FileInputStream(file); 
  103. while (true) { 
  104. int i = fis.read(arrayOfByte); 
  105. if (i != -1) { 
  106. localByteArrayOutputStream.write(arrayOfByte, 0, i); 
  107. else { 
  108. return localByteArrayOutputStream.toByteArray(); 
  109.  
  110.  

(3)在我們的程序中加載運行原來的apk文件,代碼如下:

  1. public class shellApplication extends Application { 
  2.  
  3.  
  4. private static final String appkey = "APPLICATION_CLASS_NAME"
  5. private String apkFileName; 
  6. private String odexPath; 
  7. private String libPath; 
  8.  
  9.  
  10. protected void attachBaseContext(Context base) { 
  11. super.attachBaseContext(base); 
  12. try { 
  13. File odex = this.getDir("payload_odex", MODE_PRIVATE); 
  14. File libs = this.getDir("payload_lib", MODE_PRIVATE); 
  15. odexPath = odex.getAbsolutePath(); 
  16. libPath = libs.getAbsolutePath(); 
  17. apkFileName = odex.getAbsolutePath() + "/payload.apk"
  18. File dexFile = new File(apkFileName); 
  19. if (!dexFile.exists()) 
  20. dexFile.createNewFile(); 
  21. // 讀取程序classes.dex文件 
  22. byte[] dexdata = this.readDexFileFromApk(); 
  23. // 分離出解殼后的apk文件已用于動態加載 
  24. this.splitPayLoadFromDex(dexdata); 
  25. // 配置動態加載環境 
  26. Object currentActivityThread = RefInvoke.invokeStaticMethod( 
  27. "android.app.ActivityThread""currentActivityThread"
  28. new Class[] {}, new Object[] {}); 
  29. String packageName = this.getPackageName(); 
  30. HashMap mPackages = (HashMap) RefInvoke.getFieldOjbect( 
  31. "android.app.ActivityThread", currentActivityThread, 
  32. "mPackages"); 
  33. WeakReference wr = (WeakReference) mPackages.get(packageName); 
  34. DexClassLoader dLoader = new DexClassLoader(apkFileName, odexPath, 
  35. libPath, (ClassLoader) RefInvoke.getFieldOjbect( 
  36. "android.app.LoadedApk", wr.get(), "mClassLoader")); 
  37. RefInvoke.setFieldOjbect("android.app.LoadedApk""mClassLoader"
  38. wr.get(), dLoader); 
  39.  
  40.  
  41. catch (Exception e) { 
  42. // TODO Auto-generated catch block 
  43. e.printStackTrace(); 
  44.  
  45.  
  46. public void onCreate() { 
  47.  
  48.  
  49. // 如果源應用配置有Appliction對象,則替換為源應用Applicaiton,以便不影響源程序邏輯。 
  50. String appClassName = null
  51. try { 
  52. ApplicationInfo ai = this.getPackageManager() 
  53. .getApplicationInfo(this.getPackageName(), 
  54. PackageManager.GET_META_DATA); 
  55. Bundle bundle = ai.metaData; 
  56. if (bundle != null 
  57. && bundle.containsKey("APPLICATION_CLASS_NAME")) { 
  58. appClassName = bundle.getString("APPLICATION_CLASS_NAME"); 
  59. else { 
  60. return
  61. catch (NameNotFoundException e) { 
  62. // TODO Auto-generated catch block 
  63. e.printStackTrace(); 
  64.  
  65.  
  66. Object currentActivityThread = RefInvoke.invokeStaticMethod( 
  67. "android.app.ActivityThread""currentActivityThread"
  68. new Class[] {}, new Object[] {}); 
  69. Object mBoundApplication = RefInvoke.getFieldOjbect( 
  70. "android.app.ActivityThread", currentActivityThread, 
  71. "mBoundApplication"); 
  72. Object loadedApkInfo = RefInvoke.getFieldOjbect( 
  73. "android.app.ActivityThread$AppBindData"
  74. mBoundApplication, "info"); 
  75. RefInvoke.setFieldOjbect("android.app.LoadedApk""mApplication"
  76. loadedApkInfo, null); 
  77. Object oldApplication = RefInvoke.getFieldOjbect( 
  78. "android.app.ActivityThread", currentActivityThread, 
  79. "mInitialApplication"); 
  80. ArrayList<Application> mAllApplications = (ArrayList<Application>) RefInvoke 
  81. .getFieldOjbect("android.app.ActivityThread"
  82. currentActivityThread, "mAllApplications"); 
  83. mAllApplications.remove(oldApplication); 
  84. ApplicationInfo appinfo_In_LoadedApk = (ApplicationInfo) RefInvoke 
  85. .getFieldOjbect("android.app.LoadedApk", loadedApkInfo, 
  86. "mApplicationInfo"); 
  87. ApplicationInfo appinfo_In_AppBindData = (ApplicationInfo) RefInvoke 
  88. .getFieldOjbect("android.app.ActivityThread$AppBindData"
  89. mBoundApplication, "appInfo"); 
  90. appinfo_In_LoadedApk.className = appClassName; 
  91. appinfo_In_AppBindData.className = appClassName; 
  92. Application app = (Application) RefInvoke.invokeMethod( 
  93. "android.app.LoadedApk""makeApplication", loadedApkInfo, 
  94. new Class[] { boolean.class, Instrumentation.class }, 
  95. new Object[] { falsenull }); 
  96. RefInvoke.setFieldOjbect("android.app.ActivityThread"
  97. "mInitialApplication", currentActivityThread, app); 
  98.  
  99.  
  100. HashMap mProviderMap = (HashMap) RefInvoke.getFieldOjbect( 
  101. "android.app.ActivityThread", currentActivityThread, 
  102. "mProviderMap"); 
  103. Iterator it = mProviderMap.values().iterator(); 
  104. while (it.hasNext()) { 
  105. Object providerClientRecord = it.next(); 
  106. Object localProvider = RefInvoke.getFieldOjbect( 
  107. "android.app.ActivityThread$ProviderClientRecord"
  108. providerClientRecord, "mLocalProvider"); 
  109. RefInvoke.setFieldOjbect("android.content.ContentProvider"
  110. "mContext", localProvider, app); 
  111. app.onCreate(); 
  112.  
  113.  
  114. private void splitPayLoadFromDex(byte[] data) throws IOException { 
  115. byte[] apkdata = decrypt(data); 
  116. int ablen = apkdata.length; 
  117. byte[] dexlen = new byte[4]; 
  118. System.arraycopy(apkdata, ablen - 4, dexlen, 04); 
  119. ByteArrayInputStream bais = new ByteArrayInputStream(dexlen); 
  120. DataInputStream in = new DataInputStream(bais); 
  121. int readInt = in.readInt(); 
  122. System.out.println(Integer.toHexString(readInt)); 
  123. byte[] newdex = new byte[readInt]; 
  124. System.arraycopy(apkdata, ablen - 4 - readInt, newdex, 0, readInt); 
  125. File file = new File(apkFileName); 
  126. try { 
  127. FileOutputStream localFileOutputStream = new FileOutputStream(file); 
  128. localFileOutputStream.write(newdex); 
  129. localFileOutputStream.close(); 
  130.  
  131.  
  132. catch (IOException localIOException) { 
  133. throw new RuntimeException(localIOException); 
  134.  
  135.  
  136. ZipInputStream localZipInputStream = new ZipInputStream( 
  137. new BufferedInputStream(new FileInputStream(file))); 
  138. while (true) { 
  139. ZipEntry localZipEntry = localZipInputStream.getNextEntry(); 
  140. if (localZipEntry == null) { 
  141. localZipInputStream.close(); 
  142. break
  143. String name = localZipEntry.getName(); 
  144. if (name.startsWith("lib/") && name.endsWith(".so")) { 
  145. File storeFile = new File(libPath + "/" 
  146. + name.substring(name.lastIndexOf('/'))); 
  147. storeFile.createNewFile(); 
  148. FileOutputStream fos = new FileOutputStream(storeFile); 
  149. byte[] arrayOfByte = new byte[1024]; 
  150. while (true) { 
  151. int i = localZipInputStream.read(arrayOfByte); 
  152. if (i == -1
  153. break
  154. fos.write(arrayOfByte, 0, i); 
  155. fos.flush(); 
  156. fos.close(); 
  157. localZipInputStream.closeEntry(); 
  158. localZipInputStream.close(); 
  159.  
  160.  
  161.  
  162.  
  163. private byte[] readDexFileFromApk() throws IOException { 
  164. ByteArrayOutputStream dexByteArrayOutputStream = new ByteArrayOutputStream(); 
  165. ZipInputStream localZipInputStream = new ZipInputStream( 
  166. new BufferedInputStream(new FileInputStream( 
  167. this.getApplicationInfo().sourceDir))); 
  168. while (true) { 
  169. ZipEntry localZipEntry = localZipInputStream.getNextEntry(); 
  170. if (localZipEntry == null) { 
  171. localZipInputStream.close(); 
  172. break
  173. if (localZipEntry.getName().equals("classes.dex")) { 
  174. byte[] arrayOfByte = new byte[1024]; 
  175. while (true) { 
  176. int i = localZipInputStream.read(arrayOfByte); 
  177. if (i == -1
  178. break
  179. dexByteArrayOutputStream.write(arrayOfByte, 0, i); 
  180. localZipInputStream.closeEntry(); 
  181. localZipInputStream.close(); 
  182. return dexByteArrayOutputStream.toByteArray(); 
  183.  
  184.  
  185. // //直接返回數據,讀者可以添加自己解密方法 
  186. private byte[] decrypt(byte[] data) { 
  187. return data; 

 

責任編輯:chenqingxiang 來源: 51CTO
相關推薦

2015-07-20 16:37:11

2017-04-10 13:43:34

AndroidGradleAS

2011-03-14 15:52:50

Windows Azu

2014-03-28 13:14:33

2011-06-21 09:14:01

Oracle查詢

2015-05-27 09:32:29

iOS應用架構

2014-07-30 14:25:41

SwiftiBeacon

2022-08-01 08:18:58

網絡網絡協議

2015-07-13 15:52:18

反編譯Android APK

2021-11-30 19:58:51

Java問題排查

2013-04-15 10:00:14

Hyper-V虛擬化網絡

2018-10-22 12:50:20

CDN網絡內容發布網絡

2023-06-26 00:26:40

I/OJava字節流

2022-03-29 08:18:32

位圖算法索引技術

2025-04-02 08:15:00

惡意軟件終端安全網絡安全

2018-03-20 14:14:48

NB-IoT物聯網終端

2021-09-07 09:20:44

Hadoop數據容錯

2017-11-20 15:09:21

2013-12-10 09:50:03

技術技術博客

2022-05-30 21:47:21

技術目標PRD
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 免费欧美 | 国产精品免费在线 | 春色av| 亚洲欧美激情网 | 一本在线| 九九99久久 | 干一干操一操 | 午夜精品久久 | 国产精品成人在线 | 在线午夜 | 韩日精品视频 | 日本成人免费观看 | 国产成人精品久久久 | 国产精品毛片无码 | 九九热九九| 激情伊人网 | 夜夜操天天艹 | 夜夜夜夜夜夜曰天天天 | 免费精品视频 | 日本精品一区二区三区在线观看视频 | 精品粉嫩aⅴ一区二区三区四区 | 精品国产鲁一鲁一区二区张丽 | 国产在线视频在线观看 | 中文字幕 欧美 日韩 | 精品一区久久 | 精品一区二区三区av | 艹逼网 | 中文字幕av在线 | 在线天堂免费中文字幕视频 | 日日夜夜精品视频 | 国产日产欧产精品精品推荐蛮挑 | 狠狠狠色丁香婷婷综合久久五月 | 超碰日本| 九九综合九九 | 午夜视频一区二区 | 色综网 | 桃花av在线 | 视频一区二区三区中文字幕 | 欧美精品在线一区二区三区 | 欧美视频在线播放 | 亚洲成色777777在线观看影院 |