这题目有些日子了,之前做Android时没太接触NDK,CM的APP还原出源码(java)后一直放在那里没动,看着pt哥、鬼哥等人都在出干货,我的虽然没什么技术含量,但还是想分享一下“经验”(板砖轻拍),下面看下题目:
题目说明:
- 请重打包本qihootest1.apk,将java层实现的解密算法移至jni层重新实现,并在同一控件中展示解密后的内容;
- 本题2分,以非重打包的方式达到同等效果的不计分。
题目附件:qihootest1.apk(软件中已经用java层代码实现了解密软件包的文件并将加密的内容显示在启动界面上)
题目不难,没壳也没做混淆,因此很适合新手做练习,但需要一定的编程基础。
源文件只有一个MainActivity.java,通过下面的smali代码结构猜测onCreate()中可能是调用decrypt()和desCrypto()来对文件进行加解密:
来看下还原出的java代码(当时比较闲,所以直接还原了代码):
try {
assetManager = getAssets(); //对assets中文件的操作
InputStream inputStream = assetManager.open("encryptedData"); //打开流
len = inputStream.available();
inputByte = new byte[len];
if(len == inputStream.read(inputByte)){
try {
decryResult = decrypt(inputByte, "Qihoo123"); //调用decrypt解密
} catch (IOException e) {
e.printStackTrace();
}
}else {
decryResult = getString(2131034122).getBytes(); //因为资源文件是直接从原APK中取得,所以这里直接用R.java中的id,作用是输出错误提示
}
String a = new String(decryResult);
decodeText.setText(a);
} catch (Exception e) {
e.printStackTrace();
}
具体代码请看附件。
有了java代码就可以移植到native层:
#include "jni.h"
#include "com_qihoo_firsttest_Res.h"
/**
* @author 花墨
* 2015年1月6日
* http://xss.sx
*/
JNIEXPORT jbyteArray JNICALL Java_com_qihoo_firsttest_Res_decrypt
(JNIEnv *env, jobject obj, jbyteArray src, jstring password){
jclass clazz_random = env->FindClass("java/security/SecureRandom");
jmethodID jm_random = env->GetMethodID(clazz_random,"","()V");
jobject jo_random = env->NewObject(clazz_random,jm_random);
jclass clazz_String = env->FindClass("java/lang/String");
jmethodID jm_string = env->GetMethodID(clazz_String,"getBytes","()[B");
jbyteArray bytearray = (jbyteArray)env->CallObjectMethod(password,jm_string);
jclass jc_DESKeySpec = env->FindClass("javax/crypto/spec/DESKeySpec");
jmethodID jm_DESKeySpec = env->GetMethodID(jc_DESKeySpec,"","([B)V");
jobject jo_DESKeySpec = env->NewObject(jc_DESKeySpec,jm_DESKeySpec,bytearray);
jclass jc_SecretKeyFactory = env->FindClass("javax/crypto/SecretKeyFactory");
jmethodID jm_SecretKeyFactory = env->GetStaticMethodID(jc_SecretKeyFactory,"getInstance","(Ljava/lang/String;)Ljavax/crypto/SecretKeyFactory;");
jobject jo_getInstance = env->CallStaticObjectMethod(jc_SecretKeyFactory,jm_SecretKeyFactory,env->NewStringUTF("DES"));
jmethodID jm_SecretKey = env->GetMethodID(jc_SecretKeyFactory,"generateSecret","(Ljava/security/spec/KeySpec;)Ljavax/crypto/SecretKey;");
jobject jo_SecretKey = env->CallObjectMethod(jo_getInstance,jm_SecretKey,jo_DESKeySpec);
jclass jc_Cipher = env->FindClass("javax/crypto/Cipher");
jmethodID jm_Cipher_getInstance = env->GetStaticMethodID(jc_Cipher,"getInstance","(Ljava/lang/String;)Ljavax/crypto/Cipher;");
jobject jo_Cipher = env->CallStaticObjectMethod(jc_Cipher,jm_Cipher_getInstance,env->NewStringUTF("DES"));
jmethodID jm_init = env->GetMethodID(jc_Cipher,"init","(ILjava/security/Key;Ljava/security/SecureRandom;)V");
env->CallVoidMethod(jo_Cipher,jm_init,2,jo_SecretKey,jo_random);
jmethodID jm_doFinal = env->GetMethodID(jc_Cipher,"doFinal","([B)[B");
jbyteArray a = (jbyteArray)env->CallObjectMethod(jo_Cipher,jm_doFinal,src);
return a;
}
最后附上java、C++源码(可直接编译运行)和原APK链接:
链接:http://pan.baidu.com/s/1jGgiBNC 密码:bjw7 解压密码:www.pd521.com
本文由 花墨 创作,采用 知识共享署名4.0 国际许可协议进行许可。
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。