【CTF 安卓逆向】[SCTF2019]Strange_apk——安卓父子组件通信机制
本帖最后由 hans7 于 2022-7-26 01:04 编辑本文52pojie:https://www.52pojie.cn/thread-1666622-1-1.html
本文juejin:https://juejin.cn/post/7124354639419408414/
**作者:(https://blog.csdn.net/hans774882968)以及(https://juejin.cn/user/1464964842528888)**
### 获取另一个APK
打开JEB:
```java
@Override// android.content.ContextWrapper
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
try {
File _ = this.getDir("sctf_odex", 0);
File l = this.getDir("sctf_lib", 0);
this.odexPath = _.getAbsolutePath();
this.libPath = l.getAbsolutePath();
this.apkFileName = _.getAbsolutePath() + "/sctf.apk";
File File = new File(this.apkFileName);
Log.i("demo", "apk size:" + File.length());
if(!File.exists()) {
File.createNewFile();
this._(this.__("data"));
}
Object currentActivityThread = s.invokeStaticMethod("android.app.ActivityThread", "currentActivityThread", new Class, new Object);
String packageName = this.getPackageName();
WeakReference v5 = Build.VERSION.SDK_INT >= 19 ? ((WeakReference)((ArrayMap)s.getFieldOjbect("android.app.ActivityThread", currentActivityThread, "mPackages")).get(packageName)) : ((WeakReference)((HashMap)s.getFieldOjbect("android.app.ActivityThread", currentActivityThread, "mPackages")).get(packageName));
DexClassLoader dLoader = new DexClassLoader(this.apkFileName, this.odexPath, this.libPath, ((ClassLoader)s.getFieldOjbect("android.app.LoadedApk", v5.get(), "mClassLoader")));
s.setFieldOjbect("android.app.LoadedApk", "mClassLoader", v5.get(), dLoader);
Log.i("demo", "classloader:" + dLoader);
}
catch(Exception e) {
Log.i("demo", "error:" + Log.getStackTraceString(e));
e.printStackTrace();
}
}
```
这里有一个特殊的知识点:`attachBaseContext`方法调用时机早于`onCreate`。另外,查看代码易知`this._(this.__("data"));`会获得一个新的apk。那我们写个获取新apk的脚本:
```python
def get_byte(v):
return v.to_bytes(1, byteorder='little')
with open('data', 'rb') as f:
a = f.read()
with open('sctf.apk', 'wb') as g:
for i in range(len(a)):
g.write(get_byte(a ^ ord("syclover")))
```
### 安卓父子组件通信机制
逐一查看`sctf.demo.myapplication`下的每个类。我们发现`t`这个类是主界面。如下:
```java
package sctf.demo.myapplication;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View.OnClickListener;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import java.math.BigInteger;
import java.security.MessageDigest;
public class t extends AppCompatActivity {
@Override// android.support.v4.app.FragmentActivity
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
String v6;
TextView tv = (TextView)this.findViewById(0x7F07008B);// id:textView2
Button bu = (Button)this.findViewById(0x7F070023);// id:button2
if(requestCode == 1 && resultCode == -1) {
String key = "";
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update("syclover".getBytes());
v6 = new BigInteger(1, md.digest()).toString(16);
}
catch(Exception e) {
e.printStackTrace();
goto label_29;
}
key = v6;
label_29:
if(f.encode(data.getStringExtra("data_return"), key).equals("~8t808_8A8n848r808i8d8-8w808r8l8d8}8")) {
tv.setVisibility(0);
bu.setVisibility(4);
return;
}
Toast.makeText(this.getApplicationContext(), "one more step", 1).show();
}
}
@Override// android.support.v7.app.AppCompatActivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(0x7F09001C);// layout:activity
((Button)this.findViewById(0x7F070023)).setOnClickListener(new View.OnClickListener() {// id:button2
@Override// android.view.View$OnClickListener
public void onClick(View v) {
Intent intent = new Intent("sctf.demo.myapplication.MAIN");
intent.addCategory("sctf.demo.myapplication.LAUNCHER");
t.this.startActivityForResult(intent, 1);
}
});
}
}
```
这里使用了`Intent`类,找到参考链接1,可知这是安卓开发里**父子组件的通信机制**。因为`sctf.demo.myapplication`下就那几个类,我们很容易猜到子组件是`s`类:
```java
package sctf.demo.myapplication;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View.OnClickListener;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class s extends AppCompatActivity {
@Override// android.support.v7.app.AppCompatActivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(0x7F09001D);// layout:activity_main
Button bu = (Button)this.findViewById(0x7F070022);// id:button
this.findViewById(0x7F07008A);// id:textView
bu.setOnClickListener(new View.OnClickListener() {
@Override// android.view.View$OnClickListener
public void onClick(View v) {
String s1 = "";
String s2 = "";
int i = 0;
String v0 = ((EditText)this.findViewById(0x7F070037)).getText().toString();// id:editText
if(v0.length() == 30) {
while(i < 12) {
s1 = s1 + v0.charAt(i);
++i;
}
String v1_1 = f.sctf(s1);
while(i < 30) {
s2 = s2 + v0.charAt(i);
++i;
}
if(v1_1.equals("c2N0ZntXM2xjMG1l")) {
Intent intent = new Intent();
intent.putExtra("data_return", s2);
s.this.setResult(-1, intent);
s.this.finish();
return;
}
Toast.makeText(s.this.getApplicationContext(), "something wrong", 1).show();
return;
}
Toast.makeText(s.this.getApplicationContext(), "something wrong", 1).show();
}
});
}
}
```
由参考链接1可知,`"data_return"`属性用来传递输入串的最后18个字符。
`f.sctf()`是base64编码,所以把`"c2N0ZntXM2xjMG1l"`进行base64解码,就是flag的前12个字符。
`f.encode()`如下:
```java
public static String encode(String str, String key) {
int s = str.length();
int c = key.length();
StringBuilder t = new StringBuilder();
int f;
for(f = 0; f < s; ++f) {
t.append(str.charAt(f));
t.append(key.charAt(f / c));
}
return t.toString();
}
```
所以取出`"~8t808_8A8n848r808i8d8-8w808r8l8d8}8"`下标为偶数的(0-indexed)字符就是flag的后18个字符。
```python
import base64
lef = base64.b64decode("c2N0ZntXM2xjMG1l").decode()
print(lef)
enc, ky = "", ""
goal = "~8t808_8A8n848r808i8d8-8w808r8l8d8}8"
for i in range(len(goal)):
if i % 2:
ky += goal
else:
enc += goal
print(enc, ky)
print("ans = %s" % (lef + enc))
```
### 参考链接
1. 安卓父子组件通信机制:`onActivityResult() + Intent()`:https://blog.csdn.net/weixin_41008021/article/details/90346700 挺不错,值得下载。 完全不懂啊 感谢楼主教学 xuwei9663 发表于 2022-8-3 21:21
完全不懂啊
可以实操一遍,往往能有所收获(我觉得最难的还是装软件qwq)。
如果还是不懂就放弃这题,补上相关的软件和基础知识以后再回来看,就发现它变简单了。
页:
[1]