版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wei11556/article/details/83111011
首先我们去官网下载一个Charles工具,https://www.charlesproxy.com/download;下载之后直接安装就可以了,然后我们打开使用:
这时候我们看到上面有一个提示就是30天的试用期,然后每次开启都有这样的提示,而且进入使用的时候当需要查看一条请求信息的时候也会需要等待很久,感觉特别不舒服,所以破解他,他是Java编写的,破解难度低,从这一点看我们Android中把重要信息放到so中去做是多么重要。
首先找到charles.jar文件,然后直接jd-gui直接打开即可:
用jd-gui打开charles.jar之后,直接全局搜索字符串:This is a 30 day trial version
破解修改:
public class Main {
// 主函数
public static void main(String[] args) throws Exception {
String oldJarPath = "J:\\CODE\\test\\charles.jar"; //原jar路径
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
String name = oldJarPath.substring(0, oldJarPath.lastIndexOf("."));
String outClassPath = name + uuid; //解压临时文件路径
String newJarPath = name + "_Crack.jar"; //重新压缩后的jar路径
System.out.println("原jar路径:" + oldJarPath);
System.out.println("解压临时文件路径:" + outClassPath);
System.out.println("新jar路径:" + newJarPath);
//解压
Decompression.uncompress(oldJarPath, outClassPath);
//输出class
CrackClass.crack(oldJarPath, outClassPath);
//压缩
Compressor.compress(newJarPath, outClassPath);
//删除压缩的文件夹
if (StrongFileUtil.deleteDirPath(outClassPath)) {
System.out.println("删除压缩临时文件夹成功");
}
}
}
package lisn.util;
import java.io.IOException;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;
public class CrackClass {
public static void crack(String oldJarPath, String outClassPath) throws NotFoundException, CannotCompileException, IOException {
// 这个是得到反编译的池
ClassPool pool = ClassPool.getDefault();
// 取得需要反编译的jar文件,设定路径
pool.insertClassPath(oldJarPath);
// 取得需要反编译修改的文件,注意是完整路径
CtClass cc1 = pool.get("com.xk72.charles.kKPk");
try {
// 取得需要修改的方法
CtMethod ctMethod = cc1.getDeclaredMethod("lcJx", null);
// 修改方法体直接return true;
ctMethod.setBody("{return true;}");
ctMethod = cc1.getDeclaredMethod("JZlU", null);
ctMethod.setBody("{return \"Regisered 珊哥\";}");
cc1.writeFile(outClassPath);
System.out.println("反编译class修改成功");
} catch (NotFoundException e) {
System.out.println("反编译class异常:" + e);
}
}
}
package lisn.util;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.zip.CRC32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class Compressor {
private static final int BUFFER = 8192;
public static void compress(String pathName, String srcPathName) {
File fileName = new File(pathName);
File file = new File(srcPathName);
if (!file.exists())
throw new RuntimeException(srcPathName + "不存在!");
try {
File[] sourceFiles = file.listFiles();
if (null == sourceFiles || sourceFiles.length < 1) {
System.out.println("待压缩的文件目录:" + srcPathName + "里面不存在文件,无需压缩.");
} else {
FileOutputStream fileOutputStream = new FileOutputStream(fileName);
CheckedOutputStream cos = new CheckedOutputStream(fileOutputStream,
new CRC32());
ZipOutputStream out = new ZipOutputStream(cos);
String basedir = "";
for (int i = 0; i < sourceFiles.length; i++) {
compress(sourceFiles[i], out, basedir);
}
out.close();
System.out.println("压缩成功");
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static void compress(File file, ZipOutputStream out, String basedir) {
/* 判断是目录还是文件 */
if (file.isDirectory()) {
compressDirectory(file, out, basedir);
} else {
compressFile(file, out, basedir);
}
}
/**
* 压缩目录
*
* @param dir
* @param out
* @param basedir
*/
private static void compressDirectory(File dir, ZipOutputStream out, String basedir) {
if (!dir.exists())
return;
File[] files = dir.listFiles();
for (int i = 0; i < files.length; i++) {
/* 递归 */
compress(files[i], out, basedir + dir.getName() + "/");
}
}
/**
* 压缩文件
*
* @param file
* @param out
* @param basedir
*/
private static void compressFile(File file, ZipOutputStream out, String basedir) {
if (!file.exists()) {
return;
}
try {
BufferedInputStream bis = new BufferedInputStream(
new FileInputStream(file));
String filePath = basedir + file.getName();
System.out.println("压缩文件:" + filePath);
ZipEntry entry = new ZipEntry(filePath);
out.putNextEntry(entry);
int count;
byte data[] = new byte[BUFFER];
while ((count = bis.read(data, 0, BUFFER)) != -1) {
out.write(data, 0, count);
}
bis.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
package lisn.util;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
//解压
public class Decompression {
private static final int BUFFER = 8192;
public static void uncompress(String jarFilePath, String tarDirPath) {
File jarFile = new File(jarFilePath);
File tarDir = new File(tarDirPath);
if (!jarFile.exists())
throw new RuntimeException(jarFilePath + "不存在!");
try {
JarFile jfInst = new JarFile(jarFile);
Enumeration<JarEntry> enumEntry = jfInst.entries();
while (enumEntry.hasMoreElements()) {
JarEntry jarEntry = enumEntry.nextElement();
File tarFile = new File(tarDir, jarEntry.getName());
if (jarEntry.getName().contains("META-INF")) {
File miFile = new File(tarDir, "META-INF");
if (!miFile.exists()) {
miFile.mkdirs();
}
}
makeFile(jarEntry, tarFile);
if (jarEntry.isDirectory()) {
continue;
}
FileChannel fileChannel = new FileOutputStream(tarFile).getChannel();
InputStream ins = jfInst.getInputStream(jarEntry);
transferStream(ins, fileChannel);
}
System.out.println("解压成功!");
} catch (FileNotFoundException e) {
System.out.println("解压异常>>>" + e);
} catch (IOException e) {
System.out.println("解压异常>>>" + e);
}
}
/**
* 流交换操作
*
* @param ins 输入流
* @param channel 输出流
*/
private static void transferStream(InputStream ins, FileChannel channel) {
ByteBuffer byteBuffer = ByteBuffer.allocate(BUFFER);
ReadableByteChannel rbcInst = Channels.newChannel(ins);
try {
while (-1 != (rbcInst.read(byteBuffer))) {
byteBuffer.flip();
channel.write(byteBuffer);
byteBuffer.clear();
}
} catch (IOException ioe) {
ioe.printStackTrace();
} finally {
if (null != rbcInst) {
try {
rbcInst.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != channel) {
try {
channel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 创建文件
*
* @param jarEntry jar实体
* @param fileInst 文件实体
* @throws IOException 抛出异常
*/
public static void makeFile(JarEntry jarEntry, File fileInst) {
if (!fileInst.exists()) {
if (jarEntry.isDirectory()) {
fileInst.mkdirs();
} else {
try {
if (!fileInst.getParentFile().exists()) {
fileInst.getParentFile().mkdirs();
}
fileInst.createNewFile();
System.out.println("解压文件:".concat(fileInst.getPath()));
} catch (IOException e) {
System.out.println("创建文件失败>>>".concat(fileInst.getPath()));
}
}
}
}
}
package lisn.util;
import java.io.File;
public class StrongFileUtil {
public static boolean deleteDirPath(String filepath) {
File file = new File(filepath);
if (!file.exists()){
throw new RuntimeException(filepath + "不存在!");
}else{
return deleteDir(file);
}
}
//递归删除目录
public static boolean deleteDir(File file) {
if (!file.exists()) {
System.out.println("[deleteDir]File " + file.getAbsolutePath()
+ " does not exist.");
return false;
}
if (file.isDirectory()) {// 目录
File[] files = file.listFiles();
for (File subFile : files) {
boolean isSuccess = deleteDir(subFile);
if (!isSuccess) {
return isSuccess;
}
}
} else {// 文件
boolean isSuccess = file.delete();
if (!isSuccess) {
return isSuccess;
}
}
if (file.isDirectory()) {
return file.delete();
} else {
return true;
}
}
}
本文使用的是 javassist-3.15.0-GA.jar 版本下载
本文的目的只有一个就是学习逆向分析技巧,如果有人利用本文技术进行非法操作带来的后果都是操作者自己承担,和本文以及本文作者没有任何关系