androidå èä¼å导è´Inlined method resolution crossed dex file boundary
æè¿Appå¨androidä¸åºç°äºä¸ä¸ªè¯¡å¼çnative å´©æºï¼å¾ä¸å®¹æåºç°ï¼ä½é½æ¯æ个ç¹ç¹å°±æ¯å®è£ Appåè¿ä¸æ®µæ¶é´æä¼åºç°ï¼æè¿ç¨æ²¡ç¨ï¼è¦çå®è£ åä¸ä¸ªapkï¼å´©æºç«å»æ¶å¤±ï¼æ¥å¿ä¸ºå¦ä¸ï¼
æ索系ç»artæºç ä¸æåºå¼å¸¸çå°æ¹:
åç°å¤§è´ææå°±æ¯ï¼æ们Appä¸éæäºframwworkçandroid.net.wifi.IWifiScannerè¿ä¸ªç±»ï¼å¨ç³»ç»dexoptä¹ååçäºå èä¼åï¼å¯¼è´è¿ä¸ªç³»ç»ç类被å æå°odexä¸äºï¼ç¶å被系ç»æ£æµå°callerä¸calleeå¤äºä¸åçdex fileï¼ä¹å°±æ¯å¨Appçodexä¸æä¸ä»½ï¼å¨ç³»ç»framework-wifi.jarä¸ä¹æä¸ä»½ï¼æ以主å¨åèµ·abortï¼inlineä¸å 许跨dexæ件ï¼ï¼å¯¼è´åºç¨åºç°éªéçå¼å¸¸é®é¢ï¼ä½æ¯sdkå°äºPçè¯ï¼åªä¼æ¥WARNINGèä¸æ¯FATALã
äºæ¯å¨å®è£ äºAppä¹åæå¨å¯¹apkè¿è¡dexopt
è¿ä¸ªå´©æºå°±å¿ ç°äºï¼è¿æ ·å°±æ¯è¾å¥½åæäºï¼åªéè¦é²æ¢è¿ä¸ªç±»è¢«dexä¼åå æå°±è¡äºï¼å 个try-catchå°±å¯ä»¥ã
åèï¼
Androidçé¾æçââå å èä¼å导è´9.0æºåNative Crash
Android Pæ°å¢æ£æµé¡¹ åºç¨çä¿®å¤åé大影å
å¦ä½è¿è¡ODEXåç¼è¯å®ä¾
0x åè¨
使ç¨å¼æºå·¥å ·åºç°é®é¢èä¸å¾é¾å¨ç½ä¸æ¥æ¾å°è§£å³æ¹æ¡çæ¶åï¼æ好ç解å³æ¹æ³å°±æ¯ç 究å®çæºç ï¼å 为é£æ ·è½ä¸ºæ们æä¾æ´å¤çä¿¡æ¯ã
0x æ建smali/baksmaliæºç è°è¯ç¯å¢
é¦å æ们å¨githubä¸æåsmali/baksmaliçæºç
git clone /JesusFreke/smali.git
å¯ä»¥çåºè¯¥é¡¹ç®éç¨äºgradeèªå¨åæå»ºå·¥å ·æ¥ç¼è¯æºç çï¼å æ¤æ们å¯ä»¥å¨android studioä¸å¯¼å ¥è¯¥é¡¹ç®ï¼å¦ä¸å¾æ示ï¼
çæçbaksmaliå¨å¦ä¸ç®å½ä¸é¢ï¼
ä¸å¾ä¸çProgram argumentsä¸ï¼-aé项代表api levelï¼å¯ä»¥éè¿å¦ä¸å±æ§è·å¾ï¼
æ¥éå¦ä¸ï¼
Error occurred while disassembling classLandroid.support.v4.util.TimeUtils; - skipping class
java.lang.RuntimeException: Invalid methodindex:
atorg.jf.dexlib2.analysis.InlineMethodResolver$InlineMethodResolver_version.resolveExecuteInline(InlineMethodResolver.java:)
atorg.jf.dexlib2.analysis.MethodAnalyzer.analyzeExecuteInline(MethodAnalyzer.java:)
atorg.jf.dexlib2.analysis.MethodAnalyzer.analyzeInstruction(MethodAnalyzer.java:)
atorg.jf.dexlib2.analysis.MethodAnalyzer.analyze(MethodAnalyzer.java:)
atorg.jf.dexlib2.analysis.MethodAnalyzer.<init>(MethodAnalyzer.java:)
atorg.jf.baksmali.Adaptors.MethodDefinition.addAnalyzedInstructionMethodItems(MethodDefinition.java:)
atorg.jf.baksmali.Adaptors.MethodDefinition.getMethodItems(MethodDefinition.java:)
atorg.jf.baksmali.Adaptors.MethodDefinition.writeTo(MethodDefinition.java:)
atorg.jf.baksmali.Adaptors.ClassDefinition.writeDirectMethods(ClassDefinition.java:)
atorg.jf.baksmali.Adaptors.ClassDefinition.writeTo(ClassDefinition.java:)
atorg.jf.baksmali.baksmali.disassembleClass(baksmali.java:)
atorg.jf.baksmali.baksmali.access$(baksmali.java:)
atorg.jf.baksmali.baksmali$1.call(baksmali.java:)
atorg.jf.baksmali.baksmali$1.call(baksmali.java:)
atjava.util.concurrent.FutureTask.run(FutureTask.java:)
atjava.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:)
atjava.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:)
atjava.lang.Thread.run(Thread.java:)
æ们ç´æ¥éå®åºéçå°æ¹ï¼å¨ä¸é¢åºéä¿¡æ¯æ 红è²çå°æ¹ï¼å¹¶ä¸å¨æåºå¼å¸¸å¤ä¸æç¹ï¼æ们å¯ä»¥å¤æåºéåå æ¯å 为åç¼è¯smaliæ令execute-lineæ¶ä¼ å ¥äºä¸ä¸ªæªç¥çDalvikèææºçå é¨javaæ¹æ³ç´¢å¼inlineIndex=ï¼
ç¶åï¼æ们æinline.txtä½ä¸º-Té项çåæ°ä¼ éè¿å»ï¼
DexClassLoaderåPathClassLoaderçåºå«
å¨ä½¿ç¨Javaèææºæ¶ï¼æ们ç»å¸¸èªå®ä¹ç»§æ¿èªClassLoaderçç±»å è½½å¨ãç¶åéè¿defineClassæ¹æ³æ¥ä»ä¸ä¸ªäºè¿å¶æµä¸å è½½Classãèå¨Androidä¸æ们æ æ³è¿ä¹ä½¿ç¨ï¼Androidä¸ClassLoaderçdefineClassæ¹æ³å ·ä½æ¯è°ç¨VMClassLoaderçdefineClassæ¬å°éææ¹æ³ãèè¿ä¸ªæ¬å°æ¹æ³ä»ä¹é½æ²¡åï¼åªæ¯æåºäºä¸ä¸ªâUnsupportedOperationExceptionâå¼å¸¸ã
æ¢ç¶å¨Dalvikèææºéï¼ClassLoaderä¸å¥½ç¨ï¼é£ä¹Androidå®æ¹ä¸ºäºè§£å³è¿ä¸ªé®é¢ï¼å¸®æ们ä»ClassLoaderä¸æ´¾çåºäºä¸¤ä¸ªç±»ï¼DexClassLoaderåPathClassLoaderãåä¸ç两è å¾åï¼é£ä¹ç©¶ç«äºè å¨ä½¿ç¨ä¸é¢æä½ä¸åï¼è¿éæå大家ä¸èµ·æ¢è®¨ä¸ä¸ã
é¦å æ¥çä¸ä¸äºè çæé æ¹æ³
DexClassLoader
public DexClassLoader (String dexPath,源码龙兵同城源码 String dexOutputDir, String libPath, ClassLoader parent)
åæ°è¯¦è§£ï¼
dexPathï¼dexæ件路å¾å表ï¼å¤ä¸ªè·¯å¾ä½¿ç¨â:âåé
dexOutputDirï¼ç»è¿ä¼åçdexæ件ï¼odexï¼æ件è¾åºç®å½
libPathï¼å¨æåºè·¯å¾ï¼å°è¢«æ·»å å°appå¨æåºæ索路å¾å表ä¸ï¼
parentï¼è¿æ¯ä¸ä¸ªClassLoaderï¼è¿ä¸ªåæ°ç主è¦ä½ç¨æ¯ä¿çjavaä¸ClassLoaderçå§ææºå¶ï¼ä¼å ç¶ç±»å è½½å¨å è½½classesï¼ç±ä¸èä¸çå è½½æºå¶ï¼é²æ¢éå¤å 载类åèç ï¼
DexClassLoaderæ¯ä¸ä¸ªå¯ä»¥ä»å å«classes.dexå®ä½ç.jaræ.apkæ件ä¸å è½½classesçç±»å è½½å¨ãå¯ä»¥ç¨äºå®ç°dexçå¨æå è½½ã代ç çæ´æ°ççãè¿ä¸ªç±»å è½½å¨å¿ é¡»è¦ä¸ä¸ªappçç§æãå¯åç®å½æ¥ç¼åç»è¿ä¼åçclassesï¼odexæ件ï¼ï¼ä½¿ç¨Context.getDir(String, int)æ¹æ³å¯ä»¥å建ä¸ä¸ªè¿æ ·çç®å½ï¼ä¾å¦ï¼
File dexOutputDir = context.getDir(âdexâ, 0);
PathClassLoader
PathClassLoaderæä¾ä¸¤ä¸ªå¸¸ç¨æé æ¹æ³
public PathClassLoader (String path, ClassLoader parent)
public PathClassLoader (String path, String libPath, ClassLoader parent)
åæ°è¯¦è§£ï¼
pathï¼æ件æè ç®å½çå表
libPathï¼å å«libåºçç®å½å表
parentï¼ç¶ç±»å è½½å¨
PathClassLoaderæä¾ä¸ä¸ªç®åçClassLoaderå®ç°ï¼å¯ä»¥æä½å¨æ¬å°æ件系ç»çæ件å表æç®å½ä¸çclassesï¼ä½ä¸å¯ä»¥ä»ç½ç»ä¸å è½½classesã
为äºä¾¿äºç解ï¼æ们æ¥çä¸ä¸äºè çæºç ï¼
è¿éåå¾çæè¿°
// DexClassLoader.java
public class DexClassLoader extends BaseDexClassLoader {
public DexClassLoader(String dexPath, String optimizedDirectory,
String libraryPath, ClassLoader parent) {
super(dexPath, new File(optimizedDirectory), libraryPath, parent);
}
}
// çæææï¼ç´åæ¬æ¥çæå µ/mynameishuangshuai
// PathClassLoader.java
public class PathClassLoader extends BaseDexClassLoader {
public PathClassLoader(String dexPath, ClassLoader parent) {
super(dexPath, null, null, parent);
}
public PathClassLoader(String dexPath, String libraryPath,
ClassLoader parent) {
super(dexPath, null, libraryPath, parent);
}
}
å¾ææ¾ä¸¤è é½ç»§æ¿äºBaseDexClassLoaderç±»ï¼å¹¶åäºä¸ä¸å°è£ ï¼å ·ä½çå®ç°è¿æ¯å¨ç¶ç±»éãä¸é¾çåºï¼ä¸»è¦çåºå«å¨äºPathClassLoaderçoptimizedDirectoryåæ°åªè½æ¯nullï¼é£ä¹optimizedDirectoryæ¯åä»ä¹ç¨çå¢ï¼æ们è¿BaseDexClassLoaderå»ççè¿ä¸ªåæ°ã
public BaseDexClassLoader(String dexPath, File optimizedDirectory,
String libraryPath, ClassLoader parent) {
super(parent);
this.originalPath = dexPath;
this.pathList = new DexPathList(this, dexPath, libraryPath, optimizedDirectory);
}
代ç ä¸ä¸optimizedDirectoryæå ³çå°æ¹æ¯new ä¸ä¸ªDexPathListå®ä¾ã
public DexPathList(ClassLoader definingContext, String dexPath,
String libraryPath, File optimizedDirectory) {
â¦â¦
this.dexElements = makeDexElements(splitDexPath(dexPath), optimizedDirectory);
}
private static Element[] makeDexElements(ArrayList<File> files,
File optimizedDirectory) {
ArrayList<Element> elements = new ArrayList<Element>();
for (File file : files) {
ZipFile zip = null;
DexFile dex = null;
String name = file.getName();
if (name.endsWith(DEX_SUFFIX)) {
dex = loadDexFile(file, optimizedDirectory);
} else if (name.endsWith(APK_SUFFIX) || name.endsWith(JAR_SUFFIX)
|| name.endsWith(ZIP_SUFFIX)) {
zip = new ZipFile(file);
}
â¦â¦
if ((zip != null) || (dex != null)) {
elements.add(new Element(file, zip, dex));
}
}
return elements.toArray(new Element[elements.size()]);
}
private static DexFile loadDexFile(File file, File optimizedDirectory)
throws IOException {
if (optimizedDirectory == null) {
return new DexFile(file);
} else {
String optimizedPath = optimizedPathFor(file, optimizedDirectory);
return DexFile.loadDex(file.getPath(), optimizedPath, 0);
}
}
/
*** Converts a dex/jar file path and an output directory to an
* output file path for an associated optimized dex file.
*/
private static String optimizedPathFor(File path,
File optimizedDirectory) {
String fileName = path.getName();
if (!fileName.endsWith(DEX_SUFFIX)) {
int lastDot = fileName.lastIndexOf(".");
if (lastDot < 0) {
fileName += DEX_SUFFIX;
} else {
StringBuilder sb = new StringBuilder(lastDot + 4);
sb.append(fileName, 0, lastDot);
sb.append(DEX_SUFFIX);
fileName = sb.toString();
}
}
File result = new File(optimizedDirectory, fileName);
return result.getPath();
}
optimizedDirectoryæ¯ç¨æ¥ç¼åæ们éè¦å è½½çdexæ件çï¼å¹¶å建ä¸ä¸ªDexFile对象ï¼å¦æå®ä¸ºnullï¼é£ä¹ä¼ç´æ¥ä½¿ç¨dexæ件åæçè·¯å¾æ¥å建DexFile
对象ã
optimizedDirectoryå¿ é¡»æ¯ä¸ä¸ªå é¨åå¨è·¯å¾ï¼æ 论åªç§å¨æå è½½ï¼å è½½çå¯æ§è¡æ件ä¸å®è¦åæ¾å¨å é¨åå¨ãDexClassLoaderå¯ä»¥æå®èªå·±çoptimizedDirectoryï¼æ以å®å¯ä»¥å è½½å¤é¨çdexï¼å 为è¿ä¸ªdexä¼è¢«å¤å¶å°å é¨è·¯å¾çoptimizedDirectoryï¼èPathClassLoader没æoptimizedDirectoryï¼æ以å®åªè½å è½½å é¨çdexï¼è¿äºå¤§é½æ¯åå¨ç³»ç»ä¸å·²ç»å®è£ è¿çapkéé¢çã
éè¿ä»¥ä¸çåæï¼æ们å¯ä»¥å¾åºäºè åè½ä¸çåºå«
DexClassLoaderï¼è½å¤å è½½æªå®è£ çjar/apk/dex
PathClassLoaderï¼åªè½å 载系ç»ä¸å·²ç»å®è£ è¿çapk
2024-12-23 06:42
2024-12-23 06:28
2024-12-23 05:57
2024-12-23 04:40
2024-12-23 04:27