【攻防世界】Moblie系列之Android2.0

【攻防世界】Mobile系列之Android2.0

反编译获取原代码,定义MainActivity类,找到判断关键代码

1
2
3
ublic void onClick(View v) {
MainActivity.this.Show(JNI.getResult(MainActivity.this.pwd.getText().toString()));
}

这里调用了JNI.getresult函数,跟进该函数

1
2
3
4
5
6
7
public class JNI {
public static native int getResult(String str);

static {
System.loadLibrary("Native");
}
}

这里调用了Native层的so文件Native.so,我们使用IDA打开该文件,定位Java_com_example_test_ctf03_JNI_getResult反编译获取伪代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
bool __fastcall Java_com_example_test_ctf03_JNI_getResult(int a1, int a2, int a3)
{
_BOOL4 v3; // r4
const char *v4; // r8
char *v5; // r6
char *v6; // r4
char *v7; // r5
int i; // r0
int j; // r0

v3 = 0;
v4 = (const char *)(*(int (__fastcall **)(int, int, _DWORD))(*(_DWORD *)a1 + 676))(a1, a3, 0);
if ( strlen(v4) == 15 )
{
v5 = (char *)malloc(1u);
v6 = (char *)malloc(1u);
v7 = (char *)malloc(1u);
Init(v5, v6, v7, v4, 15);//将字符串分为a1,a2,a3
if ( !First(v5) )
goto LABEL_6;
for ( i = 0; i != 4; ++i )
v6[i] ^= v5[i];
if ( !strcmp(v6, a5) )
{
for ( j = 0; j != 4; ++j )
v7[j] ^= v6[j];
v3 = strcmp(v7, "AFBo}") == 0;
}
else
{
LABEL_6:
v3 = 0;
}
}
return v3;
}

上面的代码中有几个调用的函数,init()、First()函数,我们来一一分析下这两个函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
int __fastcall Init(int result, char *a2, char *a3, const char *a4, int a5)
{
int v5; // r5
int v6; // r10
int v7; // r6

if ( a5 < 1 )
{
v6 = 0;
}
else
{
v5 = 0;
v6 = 0;
do
{
v7 = v5 % 3;
if ( v5 % 3 == 2 )
{
a3[v5 / 3u] = a4[v5];
}
else if ( v7 == 1 )
{
a2[v5 / 3u] = a4[v5];
}
else if ( !v7 )
{
++v6;
*(_BYTE *)(result + v5 / 3u) = a4[v5];
}
++v5;
}
while ( a5 != v5 );
}
*(_BYTE *)(result + v6) = 0;
a2[v6] = 0;
a3[v6] = 0;
return result;
}

上面的代码逻辑是将字符串分为三个部分,依次按照a1,a2,a3的顺序来保存

接下来看看First()函数的代码,这里是将a1的字符进行运算后与常量”LN^dl”作比较

1
2
3
4
5
6
7
8
bool __fastcall First(char *a1)
{
int i; // r1

for ( i = 0; i != 4; ++i )
a1[i] = (2 * a1[i]) ^ 0x80;
return strcmp(a1, "LN^dl") == 0;
}

这里可以对该代码进行逆向倒推出满足该程序的字符串,代码如下

1
2
3
4
5
6
7
8
9
10
11
def re_first():
b = "LN^d1"
a1 = ''
for i in range(0,4):
print(i)
a1 += chr(int((ord(b[i])^0x80)/2))
a1+='1'
print(a1)

if __name__=='__main__':
re_first()

得到a1原来的值为fgor1,但经过该函数的调用后a1变为了”LN^d1“,接下来对a2和a3进行了变换

1
2
3
4
5
6
7
8
for ( i = 0; i != 4; ++i )
v6[i] ^= v5[i];
if ( !strcmp(v6, a5) )//v6=a5,a5=" 5-"+0x16+"a"
{
for ( j = 0; j != 4; ++j )
v7[j] ^= v6[j];
v3 = strcmp(v7, "AFBo}") == 0;
}

对a2和a3进行逆向反推获取原来的字符串,代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def re_second():
a5 = [ord(' '),ord('5'),ord('-'),0x16,ord('a')]
v5 = [ord('L'),ord('N'),ord('^'),ord('d'),ord('1')]
v6 = ''
for i in range(0,4):
v6 += chr(a5[i]^v5[i])
v6+='a'
print(v6)

def re_thrid():
v6 = [ord(' '),ord('5'),ord('-'),0x16,ord('a')]
a = "AFBo"
v7 = ''
for i in range(0,4):
v7 += chr(v6[i]^ord(a[i]))
v7 += ”}“
print(v7)


得到原来的a2为 ”l{sra“ a3为”asyo}“

到这里就得到了a1,a2和a3变换后的值,根据最上面的init()逆向分析将这三个变量进行拼接,代码如下

1
2
3
4
5
6
7
8
def re_str():
a1 = 'fgor1'
a2 = 'l{sra'
a3 = 'asoy}'
flag = ''
for i in range(5):
flag += a1[i]+a2[i]+a3[i]
print(flag)

最后得到正确的字符串flag{sosorry1a}

打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2021-2024 John Doe
  • 访问人数: | 浏览次数:

让我给大家分享喜悦吧!

微信