【愚公系列】2023年08月 攻防世界-MOBILE(easy-app)
前言
下面介绍两个反编译工具
- jadx是一个用于反编译Android APK文件的开源工具,静态反编译,查找索引功能强大
- jeb和IDA很像,属于动态调试,可以看java汇编也可以生成伪代码,还可以动态attach到目标调试
对于so文件的逆向工具选择
- IDA逆向工具是一款反汇编器,被广泛应用于软件逆向工程领域,能够反汇编各种不同平台的二进制程序代码,并还原成可读的汇编代码。
Objection是一款移动设备运行时漏洞利用工具,该工具由Frida驱动,可以帮助研究人员访问移动端应用程序,并在无需越狱或root操作的情况下对移动端应用程序的安全进行评估检查。
安装命令
pip3 install objection
frida是一款便携的、自由的、支持全平台的hook框架,可以通过编写JavaScript、Python代码来和frida_server端进行交互
frida的安装可以参考:https://www.jianshu.com/p/60cfd3f6afde
一、easy-app
1.题目
2.答题
2.1 静态调试
1、源码分析
jadx打开文件
当我们点击check按钮的时候,程序会调用check方法,参数即是我们的输入字符串,check方法的实现在native-lib.so库中
对其进行解包操作,获得该so库,IDA打开找到check函数
可以看到了flag{}
2.2 动态调试
因为静态调试太费时间,进行动态调试
上传ida的服务端,并对它赋予可执行权限,然将其运行起来
>adb push android_server /data/local/tmp
>adb push android_server64 /data/local/tmp
# chmod 777 android_server64
# chmod 777 android_server
# ./android_server &
[1] 11122
taimen:/data/local/tmp # IDA Android 64-bit remote debug server(ST) v1.22. Hex-Rays (c) 2004-2017
Listening on 0.0.0.0:23946...
进行端口转发
>adb forward tcp:23946 tcp:23946
手机端打开应用
ida进行远程调试配置
选中要调试的进程
点击ok,成功调试起来了,
在Modules模块窗口,通过ctal+f寻找到native-lib.so
找到目标函数Java_com_example_myapplication_MainActivity_check(),继续双击这个函数,即可查看对应的汇编代码,
点击tab键对其进行反编译为伪代码
通过静态分析,可以得知我们要输入的字符串长度为38位,且前5位为"flag{",最后一位为“}”,而中间是32位是需要我们去逆向分析得到的。
check函数进行第一次转换,去掉flag格式,将输入分成两组,一组16个字符。
将前十六位的高四位和后十六位的低四位组合存放到后十六位,将后十六位的高四位和前十六位的低四位组合存放到前十六位。
之后在分成4组进行tea加密,key这里运行时候被修改了,正确的应该是0x42,0x37,0x2c,0x21。
之后进行换表base64加密,这个有一个点就是,base64_encode中不止包括了base64加密,还有移位操作。将编码之后的base64,每三位循环向左移动,第四位做分隔符不变.
从文件中找base64的表为abcdefghijklmnopqrstuvwxyz!@#$%^&*()ABCDEFGHIJKLMNOPQRSTUVWXYZ+/。所有算法反推回去就是flag
2.3 逆向代码
第一步
#coding:utf8
base64_out="e)n*pNe%PQy!^oS(@HtkUu+Cd$#hmmK&ieytiWwYkIA="
print(len(base64_out))#44
base64_ok=""
temp=""
for i in range(len(base64_out)):
if i%4==0:
temp=base64_out[i:i+4]
#print(temp)
base64_ok+=temp[2]
base64_ok+=temp[0]
base64_ok+=temp[1]
base64_ok+=temp[3]
else:
print("")
print(base64_ok)#ne)*epN%yPQ!S^o(t@Hk+UuC#d$hKmm&yietwiWYAkI=
base64解密
import base64
import string
import binascii
base64_ok="ne)*epN%yPQ!S^o(t@Hk+UuC#d$hKmm&yietwiWYAkI="
outtab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
intab = "abcdefghijklmnopqrstuvwxyz!@#$%^&*()ABCDEFGHIJKLMNOPQRSTUVWXYZ+/"
teaout=(base64.b64decode(base64_ok.translate(base64_ok.maketrans(intab,outtab))))#b'4H\xe1\x10\xfc^c=\x1a\xd9\xf3\xa2M\xba\xca\xfb\x85&p7G\xb8\xc3 `\x81\x13X\x8e\xbc\x90\xab'
print(teaout)
print(type(teaout))
tea_out=binascii.hexlify(teaout).decode('utf-8')#https://www.delftstack.com/zh/howto/python/python-convert-hex-to-byte/
print(tea_out)#3448e110fc5e633d1ad9f3a24dbacafb8526703747b8c320608113588ebc90ab
然后在进行tea解密
#include<stdio.h>
#include <string.h>
void decrypt(unsigned int *v, unsigned int *k)
{
unsigned int v0 = v[0], v1 = v[1], sum = 0xC6EF3720, i;
unsigned int delta = 0x9e3779b9;
unsigned int k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
for (i = 0; i < 32; i++)
{
v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
sum -= delta;
}
v[0] = v0;
v[1] = v1;
}
int main(){
int i=0;
unsigned int v[2] = {0, 0}, k[4] = {66, 55, 44, 33};
char tea_out[64]="\x34\x48\xe1\x10\xfc\x5e\x63\x3d\x1a\xd9\xf3\xa2\x4d\xba\xca\xfb\x85\x26\x70\x37\x47\xb8\xc3\x20\x60\x81\x13\x58\x8e\xbc\x90\xab";
for(i=0;i<strlen(tea_out);i+=8){
unsigned int *v=(unsigned int *)&tea_out[i];
//printf("%x %x\n", v[0], v[1]);
decrypt(v, k);
printf("%x %x\n", v[0], v[1]);
}
return 0;
}
/*
36346065 38673534
65353537 62303531
61333232 34363160
63316239 35356761
即6560343634356738373535653135306232323361603136343962316361673535
*/
最后在进行高位替换
tea="6560343634356738373535653135306232323361603136343962316361673535"
tea1=tea[::2]#从0都结束 每step2进行取值 https://blog.csdn.net/Evan123mg/article/details/49232089
tea2=tea[1::2]#从1都结束 每step2进行取值
print(tea1)#6633336333363336 3336633336366633
print(tea2)#50464578755515022231016492131755
temp=tea1[16:]+tea1[:16] #3336633336366633 6633336333363336 高16位和低16位换位置
print(temp)
flag=""
for i in range(len(temp)):
flag+=temp[i]+tea2[i]
print(flag)#3530346664353738376535656165303262623331303166343932316331373565
print(bytes.fromhex(flag))#b'504fd5787e5eae02bb3101f4921c175e'
然后再拼接上面的"flag{“和”}"就是正确的输入
flag{504fd5787e5eae02bb3101f4921c175e}
- 点赞
- 收藏
- 关注作者
评论(0)