好友
阅读权限 10
听众
最后登录 1970-1-1
本帖最后由 windwing1883 于 2016-3-2 11:34 编辑
来源 :源于sound大神的一篇精华分析(path: http://www.52pojie.cn/thread-470508-1-1.html ).特意自己试了试, 便有了下文
目的 :由于sound分析的已经很清除透彻了 在此我只提供另一种我等小菜比较容易接受的分析思路.很佩服sound的汇编阅读代码能力!
其它 :从sound发的帖子上下载下来的apk有闪退bug,所以我自己修改了一下,会从文章结束发上下载地址.此文章意在给我等新手提供学习之用,大神就不用看了 太简单了.
一:分析APK
我直接放到代码框里面,注释
[Java] 纯文本查看 复制代码
public class NDHActivity extends Activity {
/**
* java调用非java代码接口,简单说就是调用so里面实现的方法
* @param str
* @return
*/
private native String print(String str);
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//TextView 用来显示信息
TextView tv = new TextView(this);
tv.setText("Enter the code to activate this software :");
//创建生成提示框的代码,效果就是有提示文字(setMessage方法设置)和一个按钮
final Builder builder = new Builder(this);
//设置为不能取消
builder.setCancelable(false);
//添加一个确定按钮显示为OK,添加了点击响应但是没有效果 空实现.
builder.setPositiveButton("OK", new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
});
//EditText 用来接收输入信息的 通过 getText()得到输入的内容
final EditText tv2 = new EditText(this);
/*源APK设置的输入类型为0即InputType.TYPE_NULL这样的话就输入不了了所以我给注销了
InputType.TYPE_CLASS_TEXT = 1 是普通文本
InputType.TYPE_TEXT_VARIATION_PASSWORD = 80 输入密码
InputType.TYPE_CLASS_NUMBER = 2 只能输入数字
...常用的列一下. 一般程序里直接调用这个静态常量而反编译之后就是这些静态常量对应的数字*/
// tv2.setInputType(0);
//按钮
Button bt = new Button(this);
//设置显示文本
bt.setText("Activation");
//通过得到系统的 phone服务可以得到手机的信息比如 IMEI 等,由于用不上我给注销了.顺便把
//AndroidManifest.xml里的权限也取消了.
// final TelephonyManager test = (TelephonyManager) getSystemService("phone");
//点击响应方法
bt.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//这里为什么说有bug呢 当getDeviceId的时候如果IMEI里有字母 这个方法会抛异常
//这里说一点跟sound不太一样的 模拟器一般也有IMEI的.
//
// if (Integer.decode(test.getDeviceId()).intValue() == 0) {
// builder.setMessage("Bad Password");
// } else {
// }
//tv2.getText().toString 得到输入的文本
//并传给这个是现在so库里面的方法,而这个方法会返回一个字符串
//这个字符串会被setMessage到一个提示view上
//调用show()显示这个提示框(AlertView)
builder.setMessage(NDHActivity.this.print(tv2.getText().toString()));
builder.create().show();
}
});
//将这些组件放到屏幕布局上
TableLayout tl = new TableLayout(this);
tl.addView(tv);
tl.addView(tv2);
tl.addView(bt);
//显示这个布局
setContentView(tl);
}
//装载动态链接库 即so库
//放到static{}里面的意思是 这个静态代码块在类加载的时候就调用了 要比 onCreate先调用,是自动调用的
static {
System.loadLibrary("verifyPass");
}
}
二分析so库
①此文的关键在于分析so,所以将这个文件拖进IDA (我用的6.8 32位的)选ARM Little-endian.
②function name里面找到这个native方法(方法名为 Java_com_app_ndh_NDHActivity_print,了解ndk生成so库的有应该知道为什么方法名必须这样写),双击如图
这个是汇编代码,sound是直接分析这些汇编语言的这些语言不好懂也不好分析,像我等小菜对汇编语言不是很熟悉的分析的话就很吃力了.
③我的做法是 按下 Table键(类似F5)编译成c的伪代码 (有一定几率失败),一路点确定如图
由于窗口原因不能放下所有代码,大致意思就是成c的伪代码了这样一来,分析起来就非常轻松了.
这里有个技巧像
[C] 纯文本查看 复制代码
v4 = (*(int (__fastcall **)(int, const char *))(*(_DWORD *)v7 + 668))(v7, "Bad password");
这样的代码 这个v7 就是JNIEnv* 指针变量而 +668 就是对应的一个方法,由于IDA不能识别出这个指针类型我们可以手动识别步骤是:光标点在这个v7上按y键,出现了一个文本提示框让我们输入这个类型的declaration即说明 填入 JNIEnv* OK即可这样IDA就能识别出这个类型了 对应的+668也能转成相应的方法,看雪上有人总结了这个JNIEnv* 对应地址对应的方法感兴趣的可以去搜一下.修正之后 分析关键代码如图
至此这个key已经出来了 每一位就是 v44[v70] ^ v32[v70] ,因为v44 跟v32 是一个数组算一下结果就行了,我是写了个java项目代码如下
[Java] 纯文本查看 复制代码
public static void main(String[] args) {
int [] array1 = {82,26,9,123,75,92,32,114,16,103,94,73};
int [] array2 = {1,78,76,58,0,8,20,32,68,83,12,12};
for (int i = 0; i < array1.length; i++) {
System.err.print(""+(char)(array1[i]^array2[i]));
}
}
运行就出来了,结果:STEAKT4RT4RE 至于下面代码其实没怎么看明白(将一个时间差传入一些验证方法中,代码太不好读,很疑惑以为会有其它验证),这是我的不足,看了sound的帖子明白了大致意思是对执行时间的一个antidebug.所以多读,多看,多练,还是对进步非常有好的效果的.
三 说明:
1:不要以为在so里面就有多不好逆向,自己把自己吓跑了(人们总是对于一些未知事物非常恐惧),不练永远不会.我现在的瓶颈在于so的脱壳 ,因为教程较少,没什么突破,希望得到大神们的一些指点.
2:以上内容仅供学习和娱乐.
3:感觉好的给点热心神马的.
感兴趣的可以练练手链接:http://pan.baidu.com/s/1i3VL5YH 密码:cxye
附上JNIEnv* 对应地址的方法表 链接:http://pan.baidu.com/s/1kUqanht 密码:vy8a
免费评分
查看全部评分