这一题不easy,不知为何叫这个名字。。。。

1. apk 安装到手机,不知所云,各种亮瞎眼闪光

2. jadx 打开apk,一行java代码都没有,打开AndroidManifest看看

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.a.sample.findmydex" platformBuildVersionCode="24" platformBuildVersionName="7">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="24"/>
<application android:theme="@style/AppTheme" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:hasCode="false" android:allowBackup="false" android:fullBackupContent="false">
<activity android:label="@string/app_name" android:name="android.app.NativeActivity" android:configChanges="orientation|keyboardHidden">
<meta-data android:name="android.app.lib_name" android:value="native"/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name="com.a.sample.findmydex.MainActivity">
<intent-filter>
<action android:name="com.a.sample.findmydex.MAIN"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
</application>
</manifest>

注意这一行<meta-data android:name="android.app.lib_name" android:value="native"/>

还有android:hasCode="false"

说明代码在native层

2. so拖入到IDA中进行分析

符号表中看到一个叫android_main的函数,打开看看

,函数比较大,看留下的日志可以得出,需要我们摇晃手机100次的样子;先摇了再说

2023-03-22 15:21:29.741 6951-6976/? I/FindMyDex: Oh yeah~ You Got it~ 17 times to go~
2023-03-22 15:21:29.891 6951-6976/? I/FindMyDex: Oh yeah~ You Got it~ 15 times to go~
2023-03-22 15:21:30.041 6951-6976/? I/FindMyDex: Oh yeah~ You Got it~ 13 times to go~
2023-03-22 15:21:30.192 6951-6976/? I/FindMyDex: Oh yeah~ You Got it~ 11 times to go~
2023-03-22 15:21:30.207 6951-6976/? I/FindMyDex: Oh yeah~ You Got it~ 9 times to go~
2023-03-22 15:21:30.342 6951-6976/? I/FindMyDex: Oh yeah~ You Got it~ 7 times to go~
2023-03-22 15:21:30.491 6951-6976/? I/FindMyDex: Oh yeah~ You Got it~ 5 times to go~
2023-03-22 15:21:30.658 6951-6976/? I/FindMyDex: Oh yeah~ You Got it~ 3 times to go~
2023-03-22 15:21:30.790 6951-6976/? I/FindMyDex: Oh yeah~ You Got it~ 1 times to go~

看来实在监听我们摇晃的次数,达到次数后就打开界面

达到100次后,这里有一串代码

if ( v14 == 100 )
{
if ( time(0) - v6 > 9 )
{
_android_log_print(4, "FindMyDex", "OH~ You are too slow. Please try again");
qmemcpy(v3, &unk_7004, (size_t)off_43A18);
v10 = 0;
}
else
{
v20 = v6;
if ( uncompress(dest, &destLen, (const Bytef *)v3, (uLong)off_43A18) )
_android_log_print(5, "FindMyDex", "Dangerous operation detected.");
v21 = open(filename, 577, 511);
if ( !v21 )
_android_log_print(5, "FindMyDex", "Something wrong with the permission.");
write(v21, dest, destLen);
close(v21);
free(dest);
free(v3);
if ( access(name, 0) && mkdir(name, 0x1FFu) )
_android_log_print(5, "FindMyDex", "Something wrong with the permission..");
sub_2368(a1);
remove(filename);
_android_log_print(4, "FindMyDex", "Congratulations!! You made it!");
sub_2250(a1);
v10 = 0x80000000;
v6 = v20;
}
}

感觉实在写文件,然后又删了,看看删之前的sub_2368函数

  if ( (*(int (__fastcall **)(_DWORD, JNIEnv **, _DWORD))(**(_DWORD **)(*(_DWORD *)(a1 + 12) + 4) + 16))(
*(_DWORD *)(*(_DWORD *)(a1 + 12) + 4),
&v21,
0) != -1 )
{
v4 = (*v21)->FindClass(v21, "android/app/Activity");
v5 = (*v21)->GetMethodID(v21, v4, "getClassLoader", "()Ljava/lang/ClassLoader;");
v6 = (*v21)->CallObjectMethod(v21, *(jobject *)(*(_DWORD *)(a1 + 12) + 12), v5);
v7 = (*v21)->NewStringUTF(v21, v25);
v8 = (*v21)->NewStringUTF(v21, v22);
v9 = (*v21)->FindClass(v21, "dalvik/system/DexClassLoader");
v10 = (*v21)->GetMethodID(
v21,
v9,
"<init>",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)V");
v11 = (*v21)->NewObject(v21, v9, v10, v7, v8, 0, v6);
v12 = (*v21)->FindClass(v21, "android/content/ContextWrapper");
v13 = (*v21)->GetFieldID(v21, v12, "mBase", "Landroid/content/Context;");
v14 = (*v21)->GetObjectField(v21, *(_DWORD *)(*(_DWORD *)(a1 + 12) + 12), v13);
v15 = (*v21)->GetObjectClass(v21, v14);
v16 = (*v21)->GetFieldID(v21, v15, "mPackageInfo", "Landroid/app/LoadedApk;");
v17 = (*v21)->GetObjectField(v21, v14, v16);
v18 = (*v21)->GetObjectClass(v21, v17);
v19 = (*v21)->GetFieldID(v21, v18, "mClassLoader", "Ljava/lang/ClassLoader;");
(*v21)->GetObjectField(v21, v17, v19);
(*v21)->SetObjectField(v21, v17, v19, v11);
}
return _stack_chk_guard - v27;
}

这一看就是在动态加载dex,那么可以怀疑时so中动态释放出来了dex,然后加载

4. hook 以下remove 看一下文件写在哪了

    var lib_handler = Process.findModuleByName("libnative.so")
var dst_addr = new NativePointer(lib_handler.base.add(0x00002762 + 1))
console.log("==== " + dst_addr)
Interceptor.attach(dst_addr, {
onEnter:function(args) {
console.log("==== args: " + ptr(args[0]).readCString())
console.log("==== r0: " + print_dump(this.context.r0 ))
}
})

得出:/data/data/com.a.sample.findmydex/files/classes.dex

5. nop remove 不能让他删了,好取出文件


var lib_handler = Process.findModuleByName("libnative.so")
var dst_addr = new NativePointer(lib_handler.base.add(0x00002762))
Memory.patchCode(dst_addr, 4, function (code) {
var cw = new ArmWriter(code, { pc: dst_addr });
cw.putNop()
cw.flush();
});

成功得到classes.dex

6. 将classes.dex 和 之前反编译出来的resources.arsc 一起拖入jadx中就可以看到代码了

public class MainActivity extends u {
private static byte[] m = {-120, 77, -14, -38, 17, 5, -42, 44, -32, 109, 85, 31, 24, -91, -112, -83, 64, -83, Byte.MIN_VALUE, 84, 5, -94, -98, -30, 18, 70, -26, 71, 5, -99, -62, -58, 117, 29, -44, 6, 112, -4, 81, 84, 9, 22, -51, 95, -34, 12, 47, 77}; /* JADX INFO: Access modifiers changed from: private */
public static byte[] b(String str, String str2) {
try {
BufferedInputStream bufferedInputStream = new BufferedInputStream(new ByteArrayInputStream(str.getBytes()));
ArrayList arrayList = new ArrayList();
Object a = b.a(str2.getBytes());
for (byte[] bArr = new byte[16]; bufferedInputStream.read(bArr, 0, 16) != -1; bArr = new byte[16]) {
arrayList.add(b.a(bArr, 0, a));
}
ByteBuffer allocate = ByteBuffer.allocate(arrayList.size() * 16);
for (Object obj : arrayList.toArray()) {
allocate.put((byte[]) obj);
}
return allocate.array();
} catch (Exception e) {
return new byte[1];
}
} /* JADX INFO: Access modifiers changed from: protected */
@Override // android.support.v7.a.u, android.support.v4.a.v, android.support.v4.a.p, android.app.Activity
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity_main);
((Button) findViewById(R.id.button)).setOnClickListener(new a(this, (EditText) findViewById(R.id.edit_text), this));
}
}

通过分析(查看其他大佬的分析)可知,这是用了twofish算法实现的加密,twofish 首先时对称加密输出byte数组,然后通过base64生成字符串输出,推测m就是没有被base64编码过的byte数组,处理成base64后,

import base64
a = [-120, 77, -14, -38, 17, 5, -42, 44, -32, 109, 85, 31, 24, -91, -112, -83, 64, -83, -128, 84, 5, -94, -98, -30, 18, 70, -26, 71, 5, -99, -62, -58, 117, 29, -44, 6, 112, -4, 81, 84, 9, 22, -51, 95, -34, 12, 47, 77]
a = [i&255 for i in a]
b = base64.b64encode(bytes(a))
print(b) 日志
iE3y2hEF1izgbVUfGKWQrUCtgFQFop7iEkbmRwWdwsZ1HdQGcPxRVAkWzV/eDC9N

用在线的twofish算法解密可得出结果qwb{TH3y_Io<e_EACh_OTh3r_FOrEUER}

【Android 逆向】【攻防世界】easy-dex的更多相关文章

  1. 【Android 逆向】手动构造dex文件

    public class Hello { public static void main(String[] args) { System.out.println("hello android ...

  2. 逆向-攻防世界-crackme

    查壳,nSpack壳,直接用软件脱壳,IDA载入程序. 很明显,就是将402130的数据和输入的数据进行异或,判断是否等于402150处的数据.dwrd占4字节. 这道题主要记录一下刚学到的,直接在I ...

  3. 逆向-攻防世界-maze

    题目提示是走迷宫. IDA载入程序分析. 输入字符长度必须是24,开头必须是nctf{,结尾必须是}.在125处按R就可以变成字符. sub_400650和sub_400660是关键函数,分析sub_ ...

  4. 逆向-攻防世界-CSAW2013Reversing2

    运行程序乱码,OD载入搜索字符串,断电到弹窗Flag附近. 发现跳过00B61000函数,弹窗乱码,我们试试调用00B61000函数.将00B61094的指令修改为JE SHORT 00B6109b. ...

  5. 逆向-攻防世界-logmein

    iDA载入程序,shift+F12查看关键字符串,找到双击来到所在地址,进入函数 然后进入主函数, 经过分析,可以得出:输入的字符要等于  经过处理的v7和v8的异或.v8很明显,但是v7是怎么回事呢 ...

  6. 逆向-攻防世界-no-strings-attached

    看题目就知道查找不到关键字符串,为防止踩坑,strings命令查看,没有找到有用的字符串.IDA载入程序查找入口函数, main函数中有4个函数,经过分析判断authenticate()为关键函数,跟 ...

  7. 攻防世界逆向——game

    攻防世界逆向:game wp 攻防世界逆向新手区的一道题目. 是一道windows的creak,动态调试打开是这样的: 题目说明是让屏幕上所有的图像都亮之后,会出现flag,看来应该是可以玩出来的. ...

  8. [转]Android逆向之动态调试总结

    一.在SO中关键函数上下断点 刚学逆向调试时.大多都满足于在SO中某关键函数上下断点.然后通过操作应用程序,去触发这个断点,然后进行调试 详细的步骤可以参见非虫大大的<Android软件安全与逆 ...

  9. Android trap攻防思路整理

    Android trap攻防                                                                      图/文 h_one 0x01 反 ...

  10. android逆向学习小结--CrackMe_1

    断断续续的总算的把android开发和逆向的这两本书看完了,虽然没有java,和android开发的基础,但总体感觉起来还是比较能接收的,毕竟都是触类旁通的.当然要深入的话还需要对这门语言的细节特性和 ...

随机推荐

  1. [转帖]Oracle中有大量的sniped会话

    https://www.cnblogs.com/abclife/p/15699959.html 1 2 3 4 5 6 7 SQL> select status ,count(*) from g ...

  2. [转帖]一文带你了解mysql sql model的only_full_group_by模式

    https://zhuanlan.zhihu.com/p/368440685 Mysql only_full_group_by与Error 1055问题分析 1 声明 本文的数据来自网络,部分代码也有 ...

  3. [转帖]【JVM】常用虚拟机参数及实例

    常用参数表 参数 描述 -XX:+PrintGC 启动java虚拟机后,只要遇到gc,就打印日志 -XX:+PrintGCDetails gc发生时,打印更详细的日志 -XX:+PrintHeapAt ...

  4. [译]深入了解现代web浏览器(四)

    本文是根据Mariko Kosaka在谷歌开发者网站上的系列文章https://developer.chrome.com/blog/inside-browser-part4/翻译而来,共有四篇,该篇是 ...

  5. 手把手带你开发starter,点对点带你讲解原理

    京东物流 孔祥东 _____ _ ____ _ / ____| (_) | _ \ | | | (___ _ __ _ __ _ _ __ __ _| |_) | ___ ___ | |_ \___ ...

  6. element-ui表格排序

    <el-table :data="TableAwitDoArr" style="width: 100%"> <el-table-column ...

  7. 如何在centos7中完全卸载Python3

    如何在centos7中完全卸载Python3?根据查到的资料,主要就是卸载,然后删除一些软连接删除干净,逻辑很简单,贴一些具体的操作代码,记录下来 . 卸载Python3的步骤 #卸载python3 ...

  8. word文档删除空白页

    记住两个快捷键 CTRL+Backspace Shift+Backspace 鼠标箭头放在空白的页面 按住键盘上的快捷键 就可以成功删除了不要天天看营销号设置什么磅值,全选删除啥的 效果如下

  9. 压缩软件 WinRAR 去广告

    别去中国的那个代理网站下载 去国外的官网下载英文版或者湾湾版的, 这样用网上的rarreg.key文件方式就没有广告了, 不然中国的就是有广告. 这里是湾湾版的链接: https://pan.baid ...

  10. Paddlenlp之UIE分类模型【以情感倾向分析新闻分类为例】含智能标注方案)

    相关文章: Paddlenlp之UIE模型实战实体抽取任务[打车数据.快递单] 项目连接:百度AIstudio直接fork我的项目就可以复现 Paddlenlp之UIE分类模型[以情感倾向分析新闻分类 ...