文章目录

  • 前言
  • 一、easy-dex
  • 二、使用步骤
    • 1.dex和odex文件结构
    • 2.jadx分析apk
    • 3.IDA
    • 4.jadx打开easy-dex.dex
  • 总结

前言

APK解包后是没有dex文件的,运行代码使用了NativeActivity的方法封装到了libnative.so 这个文件中。APK实际包含了2个APP,这2个APP的包名一致。一个存放在libnative.so文件中,另一个是解压后的dex文件。APK安装后,的功能是摇晃收集达到一定次数(10秒100次,肯定做不到)然后解压一个dex文件到特定的目录下。flag在通过分析释放出来dex文件得出。

这里得到flag涉及了几个步骤:

  • 得到释放的dex文件
  • 将dex文件合成新的APK动态调试(非必须)
  • 静态分析dex文件
  • 编写解密算法求出flag

提示:以下是本篇文章正文内容,下面案例可供参考

一、easy-dex

题目链接:https://adworld.xctf.org.cn/task/task_list?type=mobile&number=6&grade=0&page=1

二、使用步骤

1.dex和odex文件结构

dex文件结构

文件头固定:64 65 78 0A 30 33 35 00

odex是dex的优化,结构如下:

文件头固定:64 65 79 0A 30 33 36 00

2.jadx分析apk

可以看一下AndroidManifest

可以看到这个是个纯C/C++写的,没有Java代码,是个NativeActivity。

但是后面又有个MainActivity,所以可能是运行so之后就会放出来一个dex。

NativeActivity的启动函数是android_main,进入so中查看android_main

3.IDA


源码分析

int __fastcall android_main(_DWORD *a1)
{void *v2; // r5char *v3; // r10int v4; // r2int v5; // r1time_t v6; // r8int *v7; // r0int v8; // r3int v9; // r6int v10; // r4float v11; // s0int v12; // r0int v13; // r5int v14; // r5int v15; // r3void *v16; // r0int v17; // r2int v18; // r1char *v19; // r3time_t v20; // r5int v21; // r8Bytef *dest; // [sp+8h] [bp-158h]int v24; // [sp+10h] [bp-150h] BYREFchar v25[4]; // [sp+14h] [bp-14Ch] BYREFint v26[13]; // [sp+18h] [bp-148h] BYREFuLongf destLen; // [sp+4Ch] [bp-114h] BYREFchar v28[8]; // [sp+50h] [bp-110h] BYREFint v29; // [sp+58h] [bp-108h]float v30; // [sp+70h] [bp-F0h]char name[4]; // [sp+B8h] [bp-A8h] BYREFint v32; // [sp+BCh] [bp-A4h]int v33; // [sp+C0h] [bp-A0h]int v34; // [sp+C4h] [bp-9Ch]int v35; // [sp+C8h] [bp-98h]int v36; // [sp+CCh] [bp-94h]int v37; // [sp+D0h] [bp-90h]int v38; // [sp+D4h] [bp-8Ch]int v39; // [sp+D8h] [bp-88h]int v40; // [sp+DCh] [bp-84h]int v41; // [sp+E0h] [bp-80h]__int16 v42; // [sp+E4h] [bp-7Ch]char v43; // [sp+E6h] [bp-7Ah]char filename[4]; // [sp+E8h] [bp-78h] BYREFint v45; // [sp+ECh] [bp-74h]int v46; // [sp+F0h] [bp-70h]int v47; // [sp+F4h] [bp-6Ch]int v48; // [sp+F8h] [bp-68h]int v49; // [sp+FCh] [bp-64h]int v50; // [sp+100h] [bp-60h]int v51; // [sp+104h] [bp-5Ch]int v52; // [sp+108h] [bp-58h]int v53; // [sp+10Ch] [bp-54h]int v54; // [sp+110h] [bp-50h]int v55; // [sp+114h] [bp-4Ch]int v56; // [sp+118h] [bp-48h]char v57; // [sp+11Ch] [bp-44h]int v58; // [sp+124h] [bp-3Ch]destLen = 0x100000;dest = (Bytef *)malloc(0x100000u);v2 = off_43A18;v3 = (char *)malloc((size_t)off_43A18);qmemcpy(v3, &unk_7004, (size_t)v2);*(_DWORD *)filename = -1651995345;v45 = -2003974520;v46 = -1966700387;v47 = -2000190330;v48 = -2071422265;v49 = -947092071;v50 = -1920499569;v51 = -1936879484;v52 = -2138061167;v53 = -962950011;v54 = -1702328950;v55 = -946172774;v56 = -376337267;v57 = 0;*(_DWORD *)name = -1651995194;v32 = -2003974520;v33 = -1966700387;v34 = -2000190330;v35 = -2071422265;v36 = -947092071;v37 = -1920499569;v38 = -1936879484;v39 = -2138061167;v40 = -962950011;v41 = -1853059706;v43 = 0;v4 = 1;v42 = -5690;dofilename[v4++] ^= 0xE9u;while ( v4 != 53 );v5 = 1;name[0] = 47;doname[v5++] ^= 0xE9u;while ( v5 != 47 );j_app_dummy();memset(v26, 0, sizeof(v26));*a1 = v26;a1[1] = sub_29B8;a1[2] = sub_2B90;v26[0] = (int)a1;v26[1] = ASensorManager_getInstance();v26[2] = ASensorManager_getDefaultSensor(v26[1], 1);v6 = 0;v26[3] = ASensorManager_createEventQueue(v26[1], a1[7], 3, 0, 0);v7 = (int *)a1[5];if ( v7 ){v8 = v7[1];v9 = v7[2];v26[10] = *v7;v26[11] = v8;v26[12] = v9;}_android_log_print(4, "FindMyDex", "Can you shake your phone 100 times in 10 seconds?");v10 = 0;do{while ( 1 ){v12 = 0;if ( !v26[4] )v12 = -1;v13 = ALooper_pollAll(v12, 0, v25, &v24);if ( v13 >= 0 )break;if ( v26[4] ){v11 = *(float *)&v26[10] + 0.01;if ( (float)(*(float *)&v26[10] + 0.01) > 1.0 )v11 = 0.0;*(float *)&v26[10] = v11;sub_2C14(v26);}}if ( v24 )(*(void (__fastcall **)(_DWORD *))(v24 + 8))(a1);if ( v13 == 3 && v26[2] ){while ( 1 ){do{if ( ASensorEventQueue_getEvents(v26[3], v28, 1) < 1 )goto LABEL_51;}while ( v29 != 1 );if ( (v10 & 1) != 0 ){if ( v30 >= -15.0 ){LABEL_30:v14 = v10;goto LABEL_31;}if ( v10 == 1 )v6 = time(0);v14 = v10 + 1;}else{if ( v30 <= 15.0 )goto LABEL_30;v14 = v10 + 1;if ( v10 >= 0 )_android_log_print(4, "FindMyDex", "Oh yeah~ You Got it~ %d times to go~", 99 - v10);}
LABEL_31:v10 = v14;if ( (unsigned int)(v14 - 1) <= 0x58 ){v10 = v14;v15 = v14 / 10;if ( v14 % 10 == 9 ){v16 = off_43A18;v17 = (int)off_43A18 / 10;v18 = (v15 + 1) * ((int)off_43A18 / 10);if ( (int)off_43A18 / 10 * v15 < v18 ){v19 = &v3[v17 * v15];do{--v17;*v19++ ^= v14;}while ( v17 );}if ( v14 == 89 ){while ( v18 < (int)v16 )v3[v18++] ^= 0x59u;}v10 = v14 + 1;}}if ( v14 == 100 ){if ( (int)(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;}}}}
LABEL_51:;}while ( !a1[15] );sub_2BDA(v26);return _stack_chk_guard - v58;
}


要求10秒内晃动100次,并逐渐解密dex文件,解密算法使用异或操作。加密的dex文件存放位置:

qmemcpy(v3, &unk_7004, (size_t)v2);//v2为3CA10

地址:0x7004 大小:3CA10

加密算法是将这部分内容分为10分,并且分别和9、19、29、39、49、59、69、79、89
进行异或。如下:

数据范围 异或值
(0, 24833) 9
(24833, 49666) 19
(49666, 74499) 29
(74499, 99332) 39
(99332, 124165) 49
(124165, 148998) 59
(148998, 173831) 69
(173831, 198664) 79
(198664, 223497) 89
(223497, 248336) 89

IDA pro中直接运行python脚本得到dex文件,代码如下:

dump地址文件

import idaapi
addr = 0x7004
size = 0x3CA10with open('C:/Users/Happy/Desktop/题目/dump', 'wb') as f:f.write(idaapi.get_bytes(addr,size))print('dump finished')

python解密

import zlibwith open('dump', 'rb') as f:data1 = f.read()data = list(data1)v14 = 0while True:if (v14 - 1) <= 0x58:v15 = v14 // 10if v14 % 10 == 9:v16 = 0x3CA10v17 = 0x3CA10 // 10v18 = (v15 + 1) * (0x3CA10 // 10)if 0x3CA10 // 10 * v15 < v18:v19 = v17 * v15v17 -= 1data[v19] ^= v14v19 += 1while v17:v17 -= 1data[v19] ^= v14v19 += 1if v14 == 89:while v18 < v16:data[v18] ^= 0x59v18 += 1else:breakv14 += 1filebytes = bytes(data)
with open('easy-dex.dex', 'wb') as w:w.write(zlib.decompress(filebytes))
print('decrypt finished')


运行脚本文件得到easy-dex.dex文件

4.jadx打开easy-dex.dex

package com.a.sample.findmydex;import android.os.Bundle;
import android.support.v7.a.u;
import android.widget.Button;
import android.widget.EditText;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;/* loaded from: C:\Users\Happy\Desktop\题目\easy-dex.dex */
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.Activitypublic void onCreate(Bundle bundle) {super.onCreate(bundle);setContentView(2130968602);((Button) findViewById(2131427413)).setOnClickListener(new a(this, (EditText) findViewById(2131427412), this));}
}

在资源文件中找到:twofish

python还原加密字符串

import base64
m = [-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]
data = []
for i in m:data.append(i&0xFF)
print(base64.b64encode(bytes(data)))


加密字符串:iE3y2hEF1izgbVUfGKWQrUCtgFQFop7iEkbmRwWdwsZ1HdQGcPxRVAkWzV/eDC9N

加密密钥:I have a male fish and a female fish.

在线解密网址:http://tool.chacuo.net/crypttwofish


得到flag:qwb{TH3y_Io<e_EACh_OTh3r_FOrEUER}


总结

  • ida
  • jadx
  • 异或
  • base64
  • dex

【愚公系列】2021年12月 攻防世界-简单题-MOBILE-010(easy-dex)相关推荐

  1. 【愚公系列】2021年12月 攻防世界-简单题-CRYPTO-010(转轮机加密)

    文章目录 前言 一.转轮机加密 二.使用步骤 1.下载附件 2.脚本解密 总结 前言 题目描述:你俩继续往前走,来到了前面的下一个关卡,这个铺面墙上写了好多奇奇怪怪的 英文字母,排列的的整整齐齐,店面 ...

  2. 【愚公系列】2021年12月 攻防世界-简单题-REVERSE-005(game)

    文章目录 一.game 二.使用步骤 1.IDA静态分析 2.OD动态分析 总结 一.game 题目链接:https://adworld.xctf.org.cn/task/task_list?type ...

  3. 【愚公系列】2021年12月 攻防世界-简单题-CRYPTO-002(Caesar)

    文章目录 前言 一.Caesar 二.使用步骤 1.下载附件 2.凯撒密码 总结 前言 题目描述:你成功的解出了来了灯谜,小鱼一脸的意想不到"没想到你懂得这么多啊!" 你心里面有点 ...

  4. 【愚公系列】2021年12月 攻防世界-简单题-MOBILE-002(app1)

    文章目录 一.app1 二.答题步骤 1.运行app 2.jadx反编译apk文件 总结 一.app1 题目链接:https://adworld.xctf.org.cn/task/task_list? ...

  5. 【愚公系列】2021年12月 攻防世界-简单题-CRYPTO-003(Morse)

    文章目录 前言 一.Morse 二.使用步骤 1.下载附件 2.莫尔斯电码 总结 前言 题目描述:小鱼得意的瞟了你一眼,神神气气的拿走了答对谜语的奖励,你心里暗暗较劲 想着下一个谜题一定要比小鱼更快的 ...

  6. 【愚公系列】2021年12月 攻防世界-简单题-REVERSE-001(Hello, CTF)

    文章目录 一.Hello, CTF 二.使用步骤 1.IDA 总结 一.Hello, CTF 题目链接:https://adworld.xctf.org.cn/task/task_list?type= ...

  7. 【愚公系列】2021年12月 攻防世界-简单题-WEB-004(cookie)

    文章目录 一.cookie 二.使用步骤 1.点击获取在线场景 2.查看cookie 总结 1.概念 2.机制 3.修改或者删除cookie 一.cookie 题目链接:https://adworld ...

  8. 【愚公系列】2021年12月 攻防世界-进阶题-MISC-063(saleae)

    文章目录 一.saleae 二.答题步骤 1.logicdata 总结 一.saleae 题目链接:https://adworld.xctf.org.cn/task/task_list?type=mi ...

  9. 【愚公系列】2021年12月 攻防世界-进阶题-MISC-074(latlong)

    文章目录 一.latlong 二.答题步骤 1.file 2.AX.25 3.sox 4.multimon-ng 总结 一.latlong 题目链接:https://adworld.xctf.org. ...

最新文章

  1. html中表格的页眉页脚,有一个标准的页眉页脚布局HTML网页,而无需使用table标签...
  2. Robert算子的运用
  3. CVE-2016-10229分析
  4. 深入理解ajax系列第一篇——XHR对象
  5. 启明云端分享:产品应用上,怎么选型ESP-12F\ESP-12E\ESP-12S\ESP-07S这四个模块
  6. ftpClient的连接超时设置(setConnectTimeout,setSoTimeout)
  7. Angular Component UI单元测试的隔离策略
  8. 【数据库原理及应用】经典题库附答案(14章全)——第九章:数据库安全性
  9. JVMTI标记如何影响GC暂停
  10. ueditor添加下拉事件_Excel中最智能的三级下拉菜单!
  11. jquery选择器小知识点们
  12. 怎样做网站,需要考虑的几个seo因素
  13. 数据分析实战100例(基于SQLPandas)_探索Chipotle快餐数据
  14. 惠普linux打印驱动怎么安装驱动程序,hp打印机驱动怎么安装 惠普打印机驱动程序安装方法【详解】...
  15. PackageInstaller 5.0源码分析静默安装与静默卸载
  16. FPGA经典设计思想
  17. ORA-20011: Approximate NDV failed: ORA-29913: error in executing ODCIEXTTABLEOPEN callout
  18. 超好用的jQuery插件
  19. 你对Java集合了解多少?
  20. 网络编程中的基本概念

热门文章

  1. 14个上级与下属进行绩效面谈时的主题(一)
  2. 【微信小程序】fail url not in domain list 解决方法
  3. 高效文本编辑的七种武器
  4. 基于STM32F103单片机WIFI无线APP控灯亮度灭设计
  5. 百炼-1664-放苹果-C语言-递归算法入门
  6. python股指期货tick数据_股指期货中的Tick数据是什么意思
  7. 低学历高智商,太可怕了!
  8. 易的核心理念之天道左旋、地道右旋
  9. 塞梅普雷斯 如是说 (第一部/14.朋友) (草)
  10. 独孤思维:余生不长,抓紧变现