1. 程式人生 > >javassist 破解抓包工具Charles

javassist 破解抓包工具Charles

這時候我們看到上面有一個提示就是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 版本下載

程式碼下載

本文的目的只有一個就是學習逆向分析技巧,如果有人利用本文技術進行非法操作帶來的後果都是操作者自己承擔,和本文以及本文作者沒有任何關係