【攻防世界】Moblie系列之Easy-so

【攻防世界】Mobile系列之Easy-so

代码分析

运行该apk,就是一个登陆验证程序,通过验证输入字符串来返回不同提示信息

使用jadx工具对目标apk进行反编译,先来定位MainActivity类的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class MainActivity extends AppCompatActivity {
/* access modifiers changed from: protected */
@Override // android.support.v7.app.AppCompatActivity, android.support.v4.app.SupportActivity, android.support.v4.app.FragmentActivity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((Button) findViewById(R.id.button)).setOnClickListener(new View.OnClickListener() {
/* class com.testjava.jack.pingan2.MainActivity.AnonymousClass1 */

public void onClick(View v) {
if (cyberpeace.CheckString(((EditText) MainActivity.this.findViewById(R.id.editText)).getText().toString()) == 1) {
Toast.makeText(MainActivity.this, "验证通过!", 1).show();
} else {
Toast.makeText(MainActivity.this, "验证失败!", 1).show();
}
}
});
}
}

这里只用了一个cyberpeace.checkString方法来对输入框中字符串进行检验,该函数为一个native层的so文件。我们把so文件拖入IDA进行分析,定位CheckString函数

反汇编获取其伪代码

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
bool __fastcall Java_com_testjava_jack_pingan2_cyberpeace_CheckString(__int64 a1, __int64 a2, __int64 a3)
{
const char *v3; // x20
__int64 v4; // x0
signed int v5; // w21
unsigned __int64 v6; // x22
_BYTE *v7; // x0
_BYTE *v8; // x19
size_t v9; // w2
unsigned __int64 v10; // x20
_BYTE *v11; // x8
char v12; // w9
char v13; // w10
char v14; // w9
__int64 v15; // x20
_BYTE *v16; // x8
char v17; // w10
unsigned __int64 v18; // x0
unsigned __int64 v19; // x8

v3 = (const char *)(*(__int64 (__fastcall **)(__int64, __int64, _QWORD))(*(_QWORD *)a1 + 1352LL))(a1, a3, 0LL);
v4 = strlen(v3); //计算输入的字符串长度
v5 = v4;
v6 = ((v4 << 32) + 0x100000000LL) >> 32;
v7 = malloc((unsigned __int64)((v4 << 32) + 0x100000000LL) >> 32); //根据字符串长度开辟内存空间,v7为指向头的指针
v8 = v7;
if ( v6 > v5 )
v9 = v6 - v5;
else
v9 = 0;
memset(&v7[v5], 0, v9); //将v7长度扩增一倍并添加的都是0
memcpy(v8, v3, v5); //将v3的内容复制给v8
if ( strlen(v8) >= 2uLL ) //将v8的第v10个字符与第v10+16个字符交换位置
{
v10 = 0LL;
do
{
v11 = &v8[v10]; //v11为v8的首地址
v12 = v8[v10 + 16];
v13 = v8[v10++];
*v11 = v12;
v11[16] = v13;
}
while ( (unsigned __int64)strlen(v8) >> 1 > v10 );
}
if ( *v8 ) //进行位置变换,每两个字符串头尾交换
{
v14 = v8[1];
v8[1] = *v8;
*v8 = v14;
if ( strlen(v8) >= 3uLL )
{
v15 = 0LL;
do
{
v16 = &v8[v15];
v17 = v8[v15 + 2];
v16[2] = v8[v15 + 3];
v16[3] = v17;
v18 = strlen(v8);
v19 = v15 + 4;
v15 += 2LL;
}
while ( v18 > v19 );
}
}
return strcmp(v8, "f72c5a36569418a20907b55be5bf95ad") == 0; //将变换后的v8与"f72c5a36569418a20907b55be5bf95ad"字符串作比较
}

根据上述代码来对原字符串进行一个逻辑反推

  • f7 2c 5a 36 56 94 18 a2 09 07 b5 5b e5 bf 95 ad 两两交换,得到7f c2 a5 63 65 49 81 2a 90 70 5b b5 5e fb 59 da
  • 将7f c2 a5 63 65 49 81 2a 90 70 5b b5 5e fb 59 da均分成两断,头尾互换得到90 70 5b b5 5e fb 59 da 7f c2 a5 63 65 49 81 2a
  • 得到flag{90705bb55efb59da7fc2a5636549812a}

算法还原

python脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
data = list('f72c5a36569418a20907b55be5bf95ad') #经过变化后的字符串
for i in range(0,len(data),2):
str1 = data[i+1]
data[i+1] = data[i]
data[i] = str1
print('第一个循环题后的字符串:'+''.join(data))
for i in range(len(data)//2):
str2 = data[i]
data[i] = data[i+16]
data[i+16] = str2
flag = ''.join(data)
print('第二个循环后的字符串: '+flag)
print('flag{'+flag+'}')

java脚本

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
import java.lang.reflect.Array;
import java.util.Arrays;

public class Main {

public static void easygo() {
String string = "f72c5a36569418a20907b55be5bf95ad";
char[] data = string.toCharArray();
System.out.println(data);
//第二个循环进行变换
int i=0;
int n = data.length;;
do {
char str = data[i];
data [i] = data[i+1];
data[i+1] = str;
i=i+2;
}while(i<n);
String str = new String(data);
System.out.println("第二次循环体运行后的结果: "+str );

//第一个循环体
for(i=0;i<n/2;i++)
{
char temp = data[i];
data[i] = data[i+16];
data[i+16] = temp;
}
System.out.println("第二次循环体运行后的结果: "+String.valueOf(data) );


}
public static void main(String[] args) {

easygo();
}
}

得到flag{90705bb55efb59da7fc2a5636549812a}

使用解得的字符串登录,验证成功

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

让我给大家分享喜悦吧!

微信