安卓 day1 怎么才刚开始学?

Intent#

android.content.Intent 是安卓中用于组件间通信的核心类,描述一个操作的意图,例如启动一个 Activity、Service 或发送 Broadcast。

分为显式(指定确切组件类,new Intent(this, TargetActivity.class)),隐式(不确定组件,只描述操作,如打开网页的 ACTION_VIEW

// 显式 Intent:启动指定 Activity
Intent intent = new Intent(this, SecondActivity.class);
intent.putExtra("message", "Hello");
startActivity(intent);

// 隐式 Intent:发送邮件
Intent intent = new Intent(Intent.ACTION_SEND); // 此处只给行为,不指定具体目标 app
intent.setType("text/plain"); // 设置携带数据的类型,便于过滤 app
intent.putExtra(Intent.EXTRA_TEXT, "Hello World");
startActivity(Intent.createChooser(intent, "选择应用")); // 弹出对话框,由用户选择 app

sendBroadcast(Intent intent)#

向系统发送一个普通广播(Unordered Broadcast),异步分发 Intent 到所有注册了匹配 action 的 BroadcastReceiver ,接收器并行处理。

一个题

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="1"
    android:versionName="1.0"
    package="com.example.test.ctf02"
    platformBuildVersionCode="24"
    platformBuildVersionName="7">
    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="24"/>
    <application
        android:theme="@style/AppTheme"
        android:label="@string/app_name"
        android:icon="@mipmap/ic_launcher"
        android:debuggable="true"
        android:allowBackup="true"
        android:supportsRtl="true">
        <activity android:name="com.example.test.ctf02.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <receiver
            android:name="com.example.test.ctf02.GetAndChange"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="android.is.very.fun"/>
            </intent-filter>
        </receiver>
        <activity android:name="com.example.test.ctf02.NextContent"/>
        <activity android:name="com.example.test.ctf02.MainActivity2"/>
    </application>
</manifest>

MainActivity 是一个简单的加密,过了之后进入 MainActivity2

public class MainActivity2 extends AppCompatActivity {
    Button button;
    EditText editText;
    ImageView imageView;

    @Override // android.support.v7.app.AppCompatActivity, android.support.v4.app.FragmentActivity, android.support.v4.app.BaseFragmentActivityGingerbread, android.app.Activity
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_2);
        init();
        this.button.setOnClickListener(new View.OnClickListener() { // from class: com.example.test.ctf02.MainActivity2.1
            @Override // android.view.View.OnClickListener
            public void onClick(View v) {
                String str = MainActivity2.this.editText.getText().toString();
                Intent intent = new Intent(str);
                MainActivity2.this.sendBroadcast(intent);
            }
        });
    }

    public void init() {
        this.imageView = (ImageView) findViewById(R.id.image);
        this.imageView.setImageResource(R.drawable.timg);
        this.editText = (EditText) findViewById(R.id.pwd);
        this.button = (Button) findViewById(R.id.button);
    }
}

onClick() 中,输入值 str 作为 action 传入 intent ,到这里可以去 AndroidManifest.xml 看一眼。

<receiver
            android:name="com.example.test.ctf02.GetAndChange"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="android.is.very.fun"/>
            </intent-filter>
        </receiver>

注册了一个 receiver GetAndChange,内容就是启动第三个 Activity NextContent,intent-filter 标签代表匹配条件,这说明传入 android.is.very.fun 就能触发接收器。

这里是静态注册,receiver 还能在运行时用 Context.registerReceiver() 动态注册。

// 在 onCreate 或其他方法中
IntentFilter filter = new IntentFilter("com.example.CUSTOM_ACTION");
MyReceiver receiver = new MyReceiver();
registerReceiver(receiver, filter);  // 注册

// 在 onDestroy 或 onPause 中注销
unregisterReceiver(receiver);

MainActivity 启动 MainActivity2 当然也是用到 Intent

Intent intent = new Intent(MainActivity.this, (Class<?>) MainActivity2.class);
MainActivity.this.startActivity(intent);
MainActivity.this.finish();
return; // onClick() 返回

这是 app 中界面导航的范式。

这题的 apk 其实有很多可疑的地方,比如 assets 里面有个压缩包,export 出来又打不开,010 看一眼发现是 .jpg,直接改一下后缀名就可以看到图片里的 flag。并且直接去看 NextContent 的话也可以发现很可疑的东西

public void Change() throws IOException {
        String strFile = getApplicationContext().getDatabasePath("img.jpg").getAbsolutePath();
        try {
            File f = new File(strFile);
            if (f.exists()) {
                f.delete();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            InputStream is = getApplicationContext().getResources().getAssets().open("timg_2.zip");
            FileOutputStream fos = new FileOutputStream(strFile);
            byte[] buffer = new byte[1024];
            while (true) {
                int count = is.read(buffer);
                if (count <= 0) {
                    break;
                } else {
                    fos.write(buffer, 0, count);
                }
            }
            fos.flush();
            fos.close();
            is.close();
        } catch (Exception e2) {
            e2.printStackTrace();
        }
        this.imageView.setImageBitmap(BitmapFactory.decodeFile(strFile));
    }

是一个图片覆盖的逻辑,把压缩包盖到图片上了,不难想到去看这个压缩包。