现在新版本的微信有了一定的防修改机制。不过都是一些比较简单的针对apktool等工具的。制造一些异常,使工具无法正常工作,这样就可以对代码起到保护作用,这里来讲讲它的几种异常的处理。不要用来做坏事哦!
解包异常
错误信息如下:
错误信息如下:
S: Could not decode file, replacing by FALSE value: drawable-hdpi/voip_videobar_bg_pressed.9.png
S: Could not decode file, replacing by FALSE value: drawable-hdpi/voip_receiverwitch_pressed.png
S: Could not decode file, replacing by FALSE value: drawable-hdpi/qqmail_read_attach_list3_pressed.9.png
S: Could not decode file, replacing by FALSE value: drawable-hdpi/talk_room_volume_mask.png
S: Could not decode file, replacing by FALSE value: drawable-hdpi/shakeforsong_btn_on.png
S: Could not decode file, replacing by FALSE value: drawable-hdpi/radar_search_quit_icon.png
提示说各种图片资源无法找到,我们试着查找也无法在res下找到对应的png文件,不要灰心,再仔细找找,看是否藏在了什么地方,直接把.apk改成.zip,然后解压,你会发现在weixin5.0.3.1\assets\preload有一些jar文件,正常的apk文件是没有这样的目录结构的,用java decompiler打开jar或者把jar的扩展名换成zip or rar打开,你就可以以看到每个jar里都有一些png图片,这些图片正是上面异常中无法找到的。
同时你还可以看到有几个奇怪的jar
开始我以为是一个分割存储的压缩文件,之后我随便找了一个jar进行分割压缩,然后对比十六进制数据,发现不是分割压缩,其实它就是一个数据流切割而已,只要我们写个程序顺序读取三个文件,再写成一个文件就可以了,原来该jar中依然包含着图片,也需要把它们提取出来。
在linux下有相应的工具可以直接做到,不过我们是windows平台,也很简单,自己写一个吧。代码如下
imp
ort java.io.BufferedInputStream;
imp
ort java.io.BufferedOutputStream;
imp
ort java.io.DataInputStream;
imp
ort java.io.DataOutputStream;
imp
ort java.io.FileInputStream;
imp
ort java.io.FileNotFoundException;
imp
ort java.io.FileOutputStream;
imp
ort java.io.IOException;
public class compound
{
public static String fileArray[] = {"com.tencent.mm.plugin.voip.jar.0","com.tencent.mm.plugin.voip.jar.1","com.tencent.mm.plugin.voip.jar.2"};
public static String targetFile = "com.tencent.mm.plugin.voip.jar";
public static byte[] buff = new byte[1024];
public static DataOutputStream out = null;
public static DataInputStream in = null;
public static String path = null;
public static void main(String[] args)
{
if(args.length <= 0)
{
System.out.println("you can not specified the dst path!");
return;
}
path= args[0];
try
{
System.out.println(path + targetFile);
out = new DataOutputStream(new FileOutputStream(path + targetFile));
}
catch(FileNotFoundException e)
{
e.printStackTrace();
}
for(int i = 0; i < fileArray.length; i++)
{
try
{
in = new DataInputStream(new BufferedInputStream(new FileInputStream(path + fileArray[i])));
int len = 0;
try
{
while((len = in.read(buff)) != -1)
{
System.out.println(len);
out.write(buff, 0, len);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
catch(FileNotFoundException e)
{
e.printStackTrace();
}
}
}
}
1.把\assets\preload下的jar中的图片copy出来
2.用rar直接把weixin5.0.3.1解压
3.把上面copy出来的图片放到weixin5.0.3.1\res\drawable-en-hdpi下面
4.再用rar把weixin5.0.3.1压缩为weixin5.0.3.1.zip,并重命名为weixin5.0.3.1.apk
5.再使用解压命令java -jar apktool_1_4_2.jar d -d weixin5.0.3.1.apk weixin5.0.3.1 这里我们可以看到,以经可以正常解包了
打包时异常解决
libpng error: Not a PNG file
ERROR: Failure processing PNG image D:\reverse\Tools\weixin5.0.3.1_final\res\drawable-hdpi\app_panel_voiceviop_icon.png
提示这个文件不是一个合法的png文件,通过查资料发现它真正的格式是exif文件格式,截图如下
解决方法
把它的扩展名改为exif,app_panel_voiceviop_icon.exif
打包异常2
D:\reverse\Tools\weixin5.0.3.1_final\res\values\strings.xml:2520: error: Multiple substitutions specified in non-positional format; did you mean to add the form
atted="false" attribute?
D:\reverse\Tools\weixin5.0.3.1_final\res\values\strings.xml:2520: error: Unexpected end tag string
先来看看strings.xml2520处的内容
解决方法,改成如下
<string name="favorite_second_format">%1$02d:%2$02d</string>
这个与aapt版本有关,新版本的aapt对string.xml中定义的字符串格式要求比之前严格,对%+格式描述符这样的需要添加变量编号,这有些像某些脚本语言在进行格式化输出时,要与之后要输出的变量指定对应关系。
打包异常3
D:\reverse\Tools\weixin5.0.3.1\res\values\public.xml:434: error: Public symbol drawable/account_avatar_bg declared here is not defined.
D:\reverse\Tools\weixin5.0.3.1\res\values\public.xml:435: error: Public symbol drawable/account_icon declared here is not defined.
D:\reverse\Tools\weixin5.0.3.1\res\values\public.xml:436: error: Public symbol drawable/accounts_saftphone_icon declared here is not defined.
D:\reverse\Tools\weixin5.0.3.1\res\values\public.xml:437: error: Public symbol drawable/accounts_warning_icon declared here is not defined.
D:\reverse\Tools\weixin5.0.3.1\res\values\public.xml:61: error: Public symbol drawable/addfriend_whitebtn declared here is not defined.
D:\reverse\Tools\weixin5.0.3.1\res\values\public.xml:439: error: Public symbol drawable/addfriends_bkg declared here is not defined.
D:\reverse\Tools\weixin5.0.3.1\res\values\public.xml:440: error: Public symbol drawable/addfriends_button declared here is not defined.
D:\reverse\Tools\weixin5.0.3.1\res\values\public.xml:441: error: Public symbol drawable/addicon declared here is not defined.
D:\reverse\Tools\weixin5.0.3.1\res\values\public.xml:442: error: Public symbol drawable/albumglow declared here is not defined.
D:\reverse\Tools\weixin5.0.3.1\res\values\public.xml:443: error: Public symbol drawable/albums_bg declared here is not defined.
让我们先来看看434行存的是什么内容
让我们先来看看434行存的是什么内容
通过查资料,可以知道错误的原因大概是因为id的顺序有问题,在同一种类型之内,要按id值进行排序。
解决方法---对public.xml中所有原素进行排序处理
所以,写了一个java程序对public.xml中所有原素进行排序
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class resource_sort
{
public static List<String> all = null;
public static List<String> typeSequence = null;
public static Map<String,List<String>> unique = null;
public static DataOutputStream out = null;
public static DataInputStream in = null;
public static String file = null;
public static Pattern pattern = Pattern.compile("<public type=\"(\\w*?)\" name=\"([ \\w\\.]*?)\" id=\"0x([\\dabcdef]*)\" />");
public static void main(String[] args)
{
List<String> all = new ArrayList<String>();
unique = new HashMap<String, List<String>>();
typeSequence = new ArrayList<String>();
if(args.length <= 0)
{
System.out.println("path error!");
return;
}
file = args[0];
try
{
in = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
int len = 0;
try
{
String line = null;
int i = 0;
String type = null;
while((line = in.readLine()) != null)
{
//System.out.println(line);
type = getValue(line,1);
if(type == null)
{
System.out.println(line);
continue;
}
//all.add(line);
if(!unique.containsKey(type))
{
List<String> newList = new ArrayList<String>();
unique.put(type, newList);
typeSequence.add(type);
}
List<String> tempList = unique.get(type);
tempList.add(line);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
catch(FileNotFoundException e)
{
e.printStackTrace();
}
/*******************sort and write our xml*******************/
try
{
out = new DataOutputStream(new FileOutputStream(file + "_new.xml"));
}
catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
//write <?xml version=\"1.0\" encoding=\"utf-8\"?>
//write <resources>
try
{
out.writeBytes("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
out.writeBytes("<resources>\n");
}
catch(IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
//write line
//Set<String> keys = unique.keySet();
//for(Iterator it = keys.iterator(); it.hasNext();)
for(int i = 0; i < typeSequence.size(); i++)
{
//String type = (String)it.next();
//System.out.println("-------------------------------------------------");
List<String> list = unique.get(typeSequence.get(i));
Collections.sort(list, new MyComparator());
for(int j = 0;j < list.size(); j++)
{
String line = list.get(j);
//System.out.println(line);
try
{
out.writeBytes(line + "\n");
}
catch(IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//write </resources>
try
{
out.writeBytes("</resources>\n");
}
catch(IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static String getValue(String str, int groupIndex/*1 type,2 name,3 id*/)
{
Matcher matcher = pattern.matcher(str);
if(matcher.find())
{
return matcher.group(groupIndex);
}
return null;
}
}
import java.util.Comparator;
public class MyComparator implements Comparator<String>
{
@Override
public int compare(String arg0, String arg1)
{
int id1 = Integer.valueOf(resource_sort.getValue(arg0,3),16);
int id2 = Integer.valueOf(resource_sort.getValue(arg1,3),16);
return id1 - id2;
}
}