反编译改文件的一些思考方法
在反编译并且打包的过程中遇到了一些问题,记录下来以备忘。重要的不是解决的结果,而在于解决问题中的一些思考方式。
舍不得孩子套不住狼(删删删大法好)
在刚反编译完一个apk的时候,在马上反编译回去时候会提示资源文件找不到,如下所示
- 失败:
W: E:\decode\Work\...\res\values-v24\Work\cloud.tube.free.music.player.app\res\values-v24\styles.xml:11: error: Error retrieving parent for item: No resource found that matches the given name '@android:style/Animation.OptionsPanel'.
W:
W: E:\decode\Work\...\res\values-v24\styles.xml:12: error: Error retrieving parent for item: No resource found that matches the given name '@android:style/Animation.LockScreen'.
- 失败!请检查您的代码然后重试。
提示v24中的资源文件找不到,这时候最直接的方式是直接删除之,从命名来看可能和animation有关,找不到的原因也很简单,因为没有引入相应的包, 这种无关紧要的引用资源文件,一个字 删 就完事了,如果删了之后报错,就需要找对应的包引入。
明修暗道,暗度陈仓 (多版本包混淆问题解决办法)
在集成facebook包的时候,他内部因为有自己的activity,所以会用到V4的包,而且他的v4包是混淆过的,设为V4包A版本。
但是同时,在原来的app的里面,也有自己的混淆的v4包,设为v4包B版本。这时候如果不引入facebook的V4包,obviously,会报错,因为混淆文件会按照文件的先后顺序设为abcd,这时候的文件名就没有任何意义。因为不同的版本文件顺序也不一样,所以会出现MethodNotFound或者NoClassFound错误。
如果说使用改facebook包中引用的方法,把对A版本的引用转移到B版本,明显工程量大,而且不一定能找到对应的引用。反之用App的包改引用也不行。
这时候最佳办法是保留两个版本。因为smali语言和直接在android studio的代码有一个不一样是,反编译出来的资源是包含了所有用到的类,不存在外部引用gradle。所有这时候看似都引用v4包,实则一个在明(app),一个在暗(facebook)。把所有facebook v4包的名字改为v5,同时把facebook内部引用v4也改为v5.
需要注意的是改v4时要避免修改到到寄存器v4,最好的查找方法是类名(Landroid/support/v4)这样。
如上修改后会运行成功。
顺手牵羊 (巧用demo smali代码替换方法)
对于不熟悉smali语言的人来说,要修改smali语言是很需要基础的,这时候可以自己写一个demo,把需要用的方法和代码用android studio写好,再把生成的apk导出反编译后查看smali代码,这样做的好处是可以知道smali语言的一些使用规律,同时直接可以把demo的smali语言替换到需要替换的smali文件里面,可以减少错误率
不入虎穴 焉得虎子(源码回溯解决办法)
在处理facebook id的时候,遇到了一个问题,一开始以为只需要把id存入manifest即可,后面发现后台始终看不到facebook 统计数据,这时候我在反编译的代码中全局搜索meta引用名字"com.facebook.sdk.ApplicationId",发现他在FacebookSdk引用的时候有一次调用,并且他对id还有一些限制,如下
if (applicationId == null) { Object appId = ai.metaData.get(APPLICATION_ID_PROPERTY); if (appId instanceof String) { String appIdString = (String) appId; if (appIdString.toLowerCase(Locale.ROOT).startsWith("fb")) { applicationId = appIdString.substring(2); } else { applicationId = appIdString; } applicationId = (String) appId; } else if (appId instanceof Integer) { throw new FacebookException( "App Ids cannot be directly placed in the manfiest." + "They mut be prexied by 'fb' or be placed in the string resource file."); } }
可见不能直接把id写进manifest 需要使用string引用。并且需要调用facebook sdk的初始化方法才能发到facebook 后台。
需要注意三点
- metadata配置facebook id 放在string资源里面引用
- metadata配置facebook name 放在string里面引用,填写包名
- 在baseactivity里面调用初始化facebook sdk的初始化方法
弃马后炮 隔山打牛(注入代理实现抓包)
在有时候反编译的时候,需要抓包分析apk的数据和网络请求,在一般情况下,手机设置代理,电脑fiddler抓包是可行的。但是在apk使用了AsyncHttpClient和OkHttpClient框架时就抓不到包。原因是它们的网络请求会直接联网请求,而绕过电脑代理。
这时候就需要手动给AsyncHttpClient和OkHttpClient设置代理,反编译apk后,在配置页面加上如上代理smali代码,比如电脑ip是192.168.123.162,就setProxy("192.168.123.162",8888),启用8888端口,重新打包抓包就能看到数据了。
未完待续