当前位置: 首页 > news >正文

攻防世界安卓逆向练习

文章目录

  • 一.easy-so
    • 1. jadx分析程序逻辑
    • 2. ida查看so文件
    • 3. 解题脚本:
  • 二.ezjni
    • 1. 程序逻辑分析
    • 2. 解题脚本:
  • 三.easyjava
    • 1. 主函数逻辑
    • 2. getIndex函数
    • 3. getChar函数
    • 4.解题脚本
  • 四.APK逆向
    • 1.程序逻辑分析
    • 2.解题脚本
    • 3.动态调试
  • Android2.0
  • app3

一.easy-so

1. jadx分析程序逻辑

可以看到关键在于cyberpeace.CheckString()函数
在这里插入图片描述
双击跟进之后可以发现是native层函数
在这里插入图片描述

2. ida查看so文件

程序逻辑:
1. 将字符串保存到新的空间buffer中
2. 第一个判断是将buffer的前16个字符和后16个字符进行交换
3. 第二个判断是将buffer的2个相邻的字符互换位置

_BOOL8 __fastcall Java_com_testjava_jack_pingan2_cyberpeace_CheckString(__int64 a1, __int64 a2, __int64 a3)
{const char *str; // r14size_t len; // raxint len2; // r15dunsigned __int64 v6; // r12char *newMem; // raxchar *buffer; // r13bool v9; // ccsize_t v10; // r12size_t i; // rbxchar tmp; // alchar tmp1; // alsize_t j; // rbxchar tmp2; // alstr = (*(*a1 + 1352LL))(a1, a3, 0LL);len = strlen(str);len2 = len;v6 = ((len << 32) + 0x100000000LL) >> 32;newMem = malloc(v6);buffer = newMem;v9 = v6 <= len2;v10 = v6 - len2;if ( v9 )v10 = 0LL;memset(&newMem[len2], 0, v10);memcpy(buffer, str, len2);if ( strlen(buffer) >= 2 ){i = 0LL;do{tmp = buffer[i];buffer[i] = buffer[i + 16];buffer[i++ + 16] = tmp;}while ( strlen(buffer) >> 1 > i );//32>>1 = 16 也就是说i<16时执行循环}tmp1 = *buffer;if ( *buffer ){*buffer = buffer[1];buffer[1] = tmp1;if ( strlen(buffer) >= 3 ){j = 2LL;do{tmp2 = buffer[j];buffer[j] = buffer[j + 1];buffer[j + 1] = tmp2;j += 2LL;}while ( strlen(buffer) > j );}}return strcmp(buffer, "f72c5a36569418a20907b55be5bf95ad") == 0;
}

注意,不同的so文件得到的反汇编结果不一样
一开始我使用arm64-v8a文件夹中的so文件得到的是这个结果,显然是错误的,这个循环最后会丢失一些数据
在这里插入图片描述
后来打开x86_64文件夹的so文件就正常了

3. 解题脚本:

#include <stdio.h>
int main()
{char flag[33] = "f72c5a36569418a20907b55be5bf95ad";char tmp;for (int i = 0; i < 32; i += 2) // 两两交换{tmp = flag[i];flag[i] = flag[i + 1];flag[i + 1] = tmp;}int i = 0;do{tmp = flag[i];flag[i] = flag[i + 16];flag[i++ + 16] = tmp;} while (i<16);printf("flag{%s}",flag);//flag{90705bb55efb59da7fc2a5636549812a}return 0;
}

二.ezjni

1. 程序逻辑分析

可以看到也是获取字符串然后加密
1. 获取字符串
2. 进行base64加密(base表有更换)
3. 调用ncheck这个native函数判断结果
在这里插入图片描述
base64encode函数,换表base64加密:
在这里插入图片描述
ncheck函数,这里应该和上一题easyso是一样的操作,只是由于反编译错误
1. 先将前16和后16个字符进行交换
2. 然后从头遍历,每两个字符一组互换位置
在这里插入图片描述

2. 解题脚本:

先输出ncheck处理前的base串

#include <stdio.h>
int main()
{char flag[33] = "MbT3sQgX039i3g==AQOoMQFPskB1Bsc7";char tmp;for (int i = 0; i < 32; i += 2) // 两两交换{tmp = flag[i];flag[i] = flag[i + 1];flag[i + 1] = tmp;}int i = 0;do{tmp = flag[i];flag[i] = flag[i + 16];flag[i++ + 16] = tmp;} while (i<16);printf("%s",flag);//QAoOQMPFks1BsB7cbM3TQsXg30i9g3==return 0;
}

先输出base64表

public class test1{private static final char[] table = {'i', '5', 'j', 'L', 'W', '7', 'S', '0', 'G', 'X', '6', 'u', 'f', '1', 'c', 'v', '3', 'n', 'y', '4', 'q', '8', 'e', 's', '2', 'Q', '+', 'b', 'd', 'k', 'Y', 'g', 'K', 'O', 'I', 'T', '/', 't', 'A', 'x', 'U', 'r', 'F', 'l', 'V', 'P', 'z', 'h', 'm', 'o', 'w', '9', 'B', 'H', 'C', 'M', 'D', 'p', 'E', 'a', 'J', 'R', 'Z', 'N'};public static void main(String[] args) {System.out.println("hello");String s="hellk";System.out.println(s);for (int i=0;i<table.length;i++){System.out.print(table[i]);//i5jLW7S0GX6uf1cv3ny4q8es2Q+bdkYgKOIT/tAxUrFlVPzhmow9BHCMDpEaJRZN}}
}

然后用CyberChef嗦一下
在这里插入图片描述

三.easyjava

1. 主函数逻辑

这题基本和安卓没什么关系,主要是分析java代码逻辑
主函数这里调用了一个check方法判断输入的flag
在这里插入图片描述
再看看check方法
先判断头尾flag{}格式,然后获取花括号内的字符
创建两个类用于后续的一些处理
然后使用stringBuilder和func函数创建一个新的字符串
注意func函数每次传进去的是单字符的字符串,所以每次append添加的是单个字符
在这里插入图片描述
func函数
用了两个函数来套娃操作
在这里插入图片描述

2. getIndex函数

先看看index函数(注意这里的函数名和变量名都是根据分析手动修改的)
这里的函数逻辑已经分析出来了,首先判断字符是否为字母,然后获取该字符在str中的下标
再用下标在array中查找对应位置,然后将array中的下标返回
最后使用change函数改变表(change是个循环左移一位的操作)
在这里插入图片描述

  1. array初始化
    在这里插入图片描述
  2. change函数
    在这里插入图片描述

3. getChar函数

这个逻辑就比较简单了,也是表中查值然后记录index,根据index在table表中查找字符
在这里插入图片描述

  1. list和上一个函数有类似的操作
    在这里插入图片描述

  2. judgeCount,由于字符根本没有25那么长,这个函数纯纯干扰让人多分析一下,没什么实际作用
    在这里插入图片描述

4.解题脚本

import java.util.ArrayList;
public class glass0{static String str = "abcdefghijklmnopqrstuvwxyz";static ArrayList<Integer> array = new ArrayList<>();static void change() {int value = array.get(0).intValue(); // 首个元素的int值array.remove(0); // 移除array.add(Integer.valueOf(value)); // 又加回去?str += "" + str.charAt(0);str = str.substring(1, 27); // 切割字符串并调整,左移一位的效果}public static void main(String[] args) {char[] flag="wigwrkaugala".toCharArray();String table = "abcdefghijklmnopqrstuvwxyz";int[] Table={7, 14, 16, 21, 4, 24, 25, 20, 5, 15, 9, 17, 6, 13, 3, 18, 12, 10, 19, 0, 22, 2, 11, 23, 1, 8};int[] intergerArr = {8, 25, 17, 23, 7, 22, 1, 16, 6, 9, 21, 0, 15, 5, 10, 18, 2, 24, 4, 11, 3, 14, 19, 12, 20, 13};ArrayList<Integer> list = new ArrayList<>();//初始化listfor(int i=3;i<Table.length;i++){list.add(Table[i]);}for(int i=0;i<3;i++){list.add(Table[i]);}//初始化arrayfor (int i = 2; i < intergerArr.length; i++) {array.add(intergerArr[i]); // 截取num~length后半段字符串}for (int j = 0; j < 2; j++) {array.add(intergerArr[j]); // 截取0~num-1前半段字符串}//开始解密for(int i=0;i<flag.length;i++){//获取下标值int index=table.indexOf(flag[i]);//获取num值int num=list.get(index);//这个num是getIndex函数的返回值int value=array.get(num);char chr=str.charAt(value);flag[i]=chr;change();}System.out.println(flag);//venividivkcr}
}

flag{venividivkcr}

四.APK逆向

1.程序逻辑分析

对用户名和输入的SN码进行检测,用户名这里已经给出,所以查看checkSN即可
在这里插入图片描述
checkSN
可以看到sn码有22位,然后是对userName进行md5处理,md5之后的十六进制字符串每隔2位取一个,然后用flag{}包裹住就是需要的sn码
在这里插入图片描述

2.解题脚本

  1. 对userNamemd5
  2. 对md5结果每2位取一个
import hashlib
text = "Tenshine"
hash_obj = hashlib.md5()
hash_obj.update(text.encode())
encrypted_text = hash_obj.hexdigest()
for i in range(0,len(encrypted_text),2):print(encrypted_text[i],end='')
#bc72f242a6af3857

flag:bc72f242a6af3857

3.动态调试

使用jeb动态调试
下断点后运行程序输入22个字符即可成功断下并看到字符串的值
在这里插入图片描述
jadx也可以调试,但是感觉没有jeb那么丝滑
而且这红色的是变量值,第一眼看过去还以为是报错…
在这里插入图片描述

Android2.0

主要是调用了JNI.getResult这个native函数
在这里插入图片描述
Init的功能是将str分为三段,分别存储在三个数组中,然后就是一些异或和比较操作了
在这里插入图片描述
解题脚本(注意循环是0-3,不包括第五个字符)

#include<stdio.h>
int main()
{unsigned char one[5] = "LN^dl";unsigned char two[5] = " 5-0a";two[3] = 0x16;unsigned char three[5] = "AFBo}";unsigned char flag[16] = { 0 };for (int i = 0; i < 4; i++){three[i] ^= two[i];two[i] ^= one[i];one[i] = (one[i] ^ 0x80) / 2;flag[i * 3] = one[i];flag[i * 3 + 1] = two[i];flag[i * 3 + 2] = three[i];}flag[12] = one[4];flag[13] = two[4];flag[14] = three[4];printf("%s",flag);return 0;
}

flag{sosorryla}

app3

.ab文件,chatgpt是这么解释:

通常情况下,.ab后缀的文件是Android应用程序备份文件,也称为“应用程序包文件”(.apk文件)的备份文件。
当您使用Android设备上的备份和重置功能时,系统将应用程序的数据和设置打包成一个.ab文件,以便稍后可以还原到设备上。
这些备份文件可以保存在本地存储设备或云存储中,以防意外数据丢失或设备更换。

.ab有加密和未加密两种,这里未加密就显示none
在这里插入图片描述
下载解包工具:android-backup-extractor
注意:该工具使用需要java11及以上环境
使用命令

java -jar abe.jar unpack 399649a0e89b46309dd5ae78ff96917a.ab app3.tar

在这里插入图片描述
然后就会输出app3.tar压缩包,解压即可在文件夹里面找到apk文件
在这里插入图片描述
jadx打开分析逻辑

http://www.lryc.cn/news/91731.html

相关文章:

  • 自然语言处理从入门到应用——自然语言处理的语言模型(Language Model,LM)
  • 【MySql】InnoDB一棵B+树可以存放多少行数据?
  • 【综述】视频无监督域自适应(VUDA)的小综述
  • 《深入理解计算机系统(CSAPP)》第9章虚拟内存 - 学习笔记
  • 信息论与编码 SCUEC DDDD 期末复习
  • windows安装python开发环境
  • java idea常用的快捷方式
  • lwIP 开发指南
  • RabbitMQ消息属性详解
  • shader 混合模式
  • 【大数据工具】Hive 安装
  • Android9.0 iptables用INetd实现app某个时间段禁止上网的功能实现
  • webpack.config.js基础配置(五大核心属性)
  • 【华为OD机试】阿里巴巴找黄金宝箱(IV)【2023 B卷|200分】
  • Qt6 C++基础入门2 文件结构与信号和槽
  • 常用模拟低通滤波器的设计——契比雪夫II型滤波器
  • SSM 如何使用 Redis 实现缓存?
  • uin-app如何获取微信昵称和头像的博客
  • 第六十七天学习记录:对陈正冲编著《C 语言深度解剖》中关于变量命名规则的学习
  • matlab 计算点云的线性指数
  • SpringBoot集成ElasticSearch
  • 分治入门+例题
  • 剑指offer打卡
  • 运维实用脚本整理
  • INT8 中的稀疏性:加速的训练工作流程和NVIDIA TensorRT 最佳实践
  • 隧道模式HTTP代理使用代码示例
  • 翻筋斗觅食海鸥优化算法-附代码
  • K8S常见应用场景(六)
  • 《不抱怨的世界》随记
  • 2.2 利用MyBatis实现CRUD操作