re | [FlareOn2]Android
re | [FlareOn2]Android
因为arm的调试机被我丢学校了,,,所以这个题没法调试,小小的参考了一下国外师傅的文章:
http://nieluj.github.io/flareon2/
题目主要是native层的一个安卓逆向,ida打开,然后修一下参数:
int __fastcall Java_com_flareon_flare_ValidateActivity_validate(JNIEnv *env, jobject thiz, jstring str1)
{
JNIEnv *v3; // r5
int input; // r0
int input_1; // r6
jstring (*v6)(JNIEnv *, const char *); // r3
JNIEnv *v7; // r0
const char *v8; // r1
unsigned int v9; // r4
int v10; // r7
size_t i; // [sp+0h] [bp-1BB8h]
int v13; // [sp+4h] [bp-1BB4h]
jstring v14; // [sp+8h] [bp-1BB0h]
signed int v15; // [sp+Ch] [bp-1BACh]
unsigned int v16; // [sp+10h] [bp-1BA8h]
char dest[92]; // [sp+1Ch] [bp-1B9Ch]
char s; // [sp+78h] [bp-1B40h]
v3 = env;
v14 = str1;
j_memset(&s, 0, 0x1B28);
j_memcpy(dest, &off_5004, 92);
input = ((int (__fastcall *)(JNIEnv *, jstring, _DWORD))(*v3)->GetStringUTFChars)(v3, v14, 0);
input_1 = input;
if ( input && j_strlen(input) <= 46 )
{
v13 = 0;
v15 = 1;
for ( i = 0; i < j_strlen(input_1); i += 2 )
{
j_memset(&s, 0, 0x1B28);
v9 = 0;
if ( *(_BYTE *)(input_1 + i) )
{
v9 = *(unsigned __int8 *)(input_1 + i);
if ( *(_BYTE *)(input_1 + i + 1) )
v9 = (unsigned int)&unk_7E7E >= ((*(unsigned __int8 *)(input_1 + i) << 8) | (unsigned int)*(unsigned __int8 *)(input_1 + i + 1)) ? (*(unsigned __int8 *)(input_1 + i) << 8) | *(unsigned __int8 *)(input_1 + i + 1) : 0;
}
v10 = 0;
do
{
v16 = *(unsigned __int16 *)((char *)&word_2214 + v10);
while ( !(v9 % v16 & 0xFFFF) )
{
++*(_WORD *)(&s + v10);
v9 = v9 / v16 & 0xFFFF;
if ( v9 <= 1 )
goto LABEL_10;
}
v10 += 2;
}
while ( v10 != 0x1B28 );
LABEL_10: // 应该是比较
if ( !j_memcmp(*(_DWORD *)&dest[4 * v13], &s, 0xD94) )
++v13;
else
v15 = 0;
}
((void (__fastcall *)(JNIEnv *, jstring, int))(*v3)->ReleaseStringUTFChars)(v3, v14, input_1);
v6 = (*v3)->NewStringUTF;
v7 = v3;
if ( v13 == 23 && v15 ) // 正确
//
v8 = "That's it!";
else
v8 = (const char *)&unk_3D3C;
}
else
{
((void (__fastcall *)(JNIEnv *, jstring, int))(*v3)->ReleaseStringUTFChars)(v3, v14, input_1);
v6 = (*v3)->NewStringUTF;
v7 = v3;
v8 = (const char *)&unk_3D3C;
}
return ((int (__fastcall *)(JNIEnv *, const char *))v6)(v7, v8);
}
先清空了s,然后将全局区的一块内容拷贝到dest,这块内容是23个有效地址:
这些地址都指向了3476长度的word数组,其中大部分是0:
中间反正就是基层循环,然后v9能不能整除一个数组里的元素,这数组在rodata区,直接能看到:
如果能整除,s[index] ++;
最后反正就是比较s和dest里的东西:
国外那个师傅用的是ruby写的exp,我直接用python写了,其实中间的关键就是还原的乘方运算,在程序中是除几次,在这里其实就是乘方还原,总的来说这个题是比较有意思的一个题,比较新鲜又能学到一点东西,感觉flare-on确实是高质量比赛。
exp:
import struct
# author Mz1
t1_addr = 0x5004
with open('libvalidate.so', 'rb') as f:
f.seek(t1_addr-0x1000) # 这里要-0x1000其实我没有特别搞清楚,应该是跟elf的fov有关系的
t1_data = f.read(23*4)
t1 = struct.unpack("<"+"I"*23,t1_data)
for i in t1: # 先get所有对照表的地址
print(hex(i))
print()
f.seek(0x2214)
word_2214_data = f.read(6952)
word_2214 = struct.unpack("<"+"H"*3476, word_2214_data)
print(word_2214[:5]) # 才反应过来这不是质数吗?
res = []
for i in t1:
offset = i - 0x1000
f.seek(offset)
data = f.read(6952)
a = struct.unpack("<"+"H"*3476, data)
v = 1
for j in range(len(a)):
if a[j] != 0:
v *= word_2214[j] ** a[j]
res.append((v >> 8))
res.append((v & 0xff))
print(res)
for i in res:
print(chr(i),end='')
本文来自博客园,作者:Mz1,转载请注明原文链接:https://www.cnblogs.com/Mz1-rc/p/17035685.html
如果有问题可以在下方评论或者email:mzi_mzi@163.com
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· Vue3状态管理终极指南:Pinia保姆级教程