n1book_android1

  1. 安装apk,打开应用界面,输入字符,检验到错误,程序直接退出

  2. 用jadx龟打开,发现几个360壳的玩意

可以用PKID检验一下,确实是360 加固

  1. 那接下来就是脱壳了,试过很多一些脱壳方法,很多都脱不了壳

    用了BlackDex32脱壳

到对应目录下找到dump出来的dex文件

  1. 用dex2jar转jar文件,输入命令

    d2j-dex2jar dex文件路径
    
  1. 再用jadx龟打开jar文件

  2. 至于从哪里入手,看最初manifest.xml文件

目标就是找到com.sec.n1book1这个包

oncreate方法中并没有在java层实现关键操作,那就是在so层实现


可以看到下面有个Secert类,当时我点进去看了,发现在java层声明好的check函数,程序应该是把检验在java声明好,然后再到so层实现调用

public class Secret {
    static int check(String str) {
        return AESUtils.encryptString2Base64(str, str.substring(0, 6), "123456").replaceAll("\r|\n", BuildConfig.FLAVOR).equals("u0uYYmh4yRpPIT/zSP7EL/MOCliVoVLt3gHcrXDymLc=") ? 0 : -1;
    }
}

可以看到在进行所AESUtils.encryptString2Base64和代替操作后,与"u0uYYmh4yRpPIT/zSP7EL/MOCliVoVLt3gHcrXDymLc="进行匹配


进一步找到AES算法的实现函数

package com.sec.n1book1;

import android.util.Base64;
import java.io.UnsupportedEncodingException;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class AESUtils {
    //声明加密模式
    private static final String CipherMode = "AES/CBC/PKCS7Padding";
	//创建IV变量,必须满足16位,不足十六位补空格
    private static IvParameterSpec createIV(String str) {
        byte[] bArr = null;
        if (str == null) {
            str = BuildConfig.FLAVOR;
        }
        StringBuffer stringBuffer = new StringBuffer(16);
        stringBuffer.append(str);
        while (stringBuffer.length() < 16) {
            stringBuffer.append(" ");
        }
        try {
            bArr = stringBuffer.substring(0, 16).getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return new IvParameterSpec(bArr);
    }
	//创建密钥,必须满足32位,不足用空格填充
    private static SecretKeySpec createKey(String str) {
        byte[] bArr = null;
        if (str == null) {
            str = BuildConfig.FLAVOR;
        }
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(str);
        while (stringBuffer.length() < 32) {
            stringBuffer.append(" ");
        }
        try {
            bArr = stringBuffer.substring(0, 32).getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return new SecretKeySpec(bArr, "AES");
    }
//第一参数base64解密,返回调用decryptByte2Byte
    public static byte[] decryptBase642Byte(String str, String str2, String str3) {
        byte[] bArr = null;
        try {
            bArr = Base64.decode(str, 0);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return decryptByte2Byte(bArr, str2, str3);
    }

    public static String decryptBase642String(String str, String str2, String str3) {
        return decryptByte2String(Base64.decode(str, 0), str2, str3);
    }
//解密实现
    public static byte[] decryptByte2Byte(byte[] bArr, String str, String str2) {
        try {
            SecretKeySpec createKey = createKey(str);
            Cipher instance = Cipher.getInstance(CipherMode);
            instance.init(2, createKey, createIV(str2));
            return instance.doFinal(bArr);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static String decryptByte2String(byte[] bArr, String str, String str2) {
        return new String(decryptByte2Byte(bArr, str, str2));
    }
//第一参数取字节,返回调用decryptByte2Byte
    public static byte[] decryptString2Byte(String str, String str2, String str3) {
        byte[] bArr = null;
        try {
            bArr = str.getBytes("UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return decryptByte2Byte(bArr, str2, str3);
    }

    public static String encryptByte2Base64(byte[] bArr, String str, String str2) {
        return new String(Base64.encode(encryptByte2Byte(bArr, str, str2), 0));
    }
//加密实现
    public static byte[] encryptByte2Byte(byte[] bArr, String str, String str2) {
        try {
            SecretKeySpec createKey = createKey(str);
            Cipher instance = Cipher.getInstance(CipherMode);
            instance.init(1, createKey, createIV(str2));
            return instance.doFinal(bArr);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static String encryptByte2String(byte[] bArr, String str, String str2) {
        return new String(encryptByte2Byte(bArr, str, str2));
    }

    public static String encryptString2Base64(String str, String str2, String str3) {
        byte[] bArr = null;
        try {
            bArr = str.getBytes("UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new String(Base64.encode(encryptByte2Byte(bArr, str2, str3), 0));
    }

    public static byte[] encryptString2Byte(String str, String str2, String str3) {
        byte[] bArr = null;
        try {
            bArr = str.getBytes("UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return encryptByte2Byte(bArr, str2, str3);
    }

    public static String encryptString2String(String str, String str2, String str3) {
        byte[] bArr = null;
        try {
            bArr = str.getBytes("UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new String(encryptByte2Byte(bArr, str2, str3));
    }
}

分析之后,略作修改,可以用java写出解密操作

import java.util.Base64;
import java.util.Base64.Encoder;
import java.util.Base64.Decoder;
import java.io.UnsupportedEncodingException;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class aesdemo  {
    private static final String CipherMode = "AES/CBC/PKCS5Padding";

    
    private static IvParameterSpec createIV(String str) {
        byte[] bArr = null;
        StringBuffer stringBuffer = new StringBuffer(16);
        stringBuffer.append(str);
        while (stringBuffer.length() < 16) {
            stringBuffer.append(" ");
        }
        try {
            bArr = stringBuffer.substring(0, 16).getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return new IvParameterSpec(bArr);
    }

    
    private static SecretKeySpec createKey(String str) {
        byte[] bArr = null;

        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(str);
        while (stringBuffer.length() < 32) {
            stringBuffer.append(" ");
        }
        try {
            bArr = stringBuffer.substring(0, 32).getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return new SecretKeySpec(bArr, "AES");
    }

    
    public static byte[] decryptBase642Byte(String str, String str2, String str3) {
        byte[] bArr = null;
        try {
        	Decoder decoder = Base64.getDecoder();
            bArr = decoder.decode(str);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return decryptByte2Byte(bArr, str2, str3);
    }

    public static String decryptBase642String(String str, String str2, String str3) {
    	Decoder decoder = Base64.getDecoder();
        return decryptByte2String(decoder.decode(str), str2, str3);
    }

    public static byte[] decryptByte2Byte(byte[] bArr, String str, String str2) {
        try {
            SecretKeySpec createKey = createKey(str);
            Cipher instance = Cipher.getInstance(CipherMode);
            instance.init(2, createKey, createIV(str2));
            return instance.doFinal(bArr);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static String decryptByte2String(byte[] bArr, String str, String str2) {
        return new String(decryptByte2Byte(bArr, str, str2));
    }

    public static byte[] decryptString2Byte(String str, String str2, String str3) {
        byte[] bArr = null;
        try {
            bArr = str.getBytes("UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return decryptByte2Byte(bArr, str2, str3);
    }

    public static String encryptByte2Base64(byte[] bArr, String str, String str2) {
    	Encoder encoder = Base64.getEncoder();
        return new String( encoder.encode(encryptByte2Byte(bArr, str, str2)));
    }

    public static byte[] encryptByte2Byte(byte[] bArr, String str, String str2) {
        try {
            SecretKeySpec createKey = createKey(str);
            Cipher instance = Cipher.getInstance(CipherMode);
            instance.init(1, createKey, createIV(str2));
            return instance.doFinal(bArr);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static String encryptByte2String(byte[] bArr, String str, String str2) {
        return new String(encryptByte2Byte(bArr, str, str2));
    }

    public static String encryptString2Base64(String str, String str2, String str3) {
        byte[] bArr = null;
        try {
            bArr = str.getBytes("UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
    	Encoder encoder = Base64.getEncoder();
        return new String(encoder.encode(encryptByte2Byte(bArr, str2, str3)));
    }

    public static byte[] encryptString2Byte(String str, String str2, String str3) {
        byte[] bArr = null;
        try {
            bArr = str.getBytes("UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return encryptByte2Byte(bArr, str2, str3);
    }

    public static String encryptString2String(String str, String str2, String str3) {
        byte[] bArr = null;
        try {
            bArr = str.getBytes("UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new String(encryptByte2Byte(bArr, str2, str3));
    }


    
    public static void main(String[] args) {
    	String	str = "u0uYYmh4yRpPIT/zSP7EL/MOCliVoVLt3gHcrXDymLc=";
    	System.out.print(decryptBase642String(str, "n1book", "123456"));

    	
    }
}

得到结果n1book{h3ckF0rfun}