安卓 day1
怎么才刚开始学?
Intent
android.content.Intent 是安卓中用于组件间通信的核心类,描述一个操作的意图,例如启动一个 Activity、Service 或发送 Broadcast。
分为显式(指定确切组件类,new Intent(this, TargetActivity.class)),隐式(不确定组件,只描述操作,如打开网页的 ACTION_VIEW)
1 2 3 4 5 6 7 8 9 10
| Intent intent = new Intent(this, SecondActivity.class); intent.putExtra("message", "Hello"); startActivity(intent);
Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_TEXT, "Hello World"); startActivity(Intent.createChooser(intent, "选择应用"));
|
sendBroadcast(Intent intent)
向系统发送一个普通广播(Unordered Broadcast),异步分发 Intent 到所有注册了匹配 action 的 BroadcastReceiver ,接收器并行处理。
一个题
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
| <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
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
| public class MainActivity2 extends AppCompatActivity { Button button; EditText editText; ImageView imageView;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main_2); init(); this.button.setOnClickListener(new View.OnClickListener() { @Override 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 看一眼。
1 2 3 4 5 6 7 8
| <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() 动态注册。
1 2 3 4 5 6 7
| IntentFilter filter = new IntentFilter("com.example.CUSTOM_ACTION"); MyReceiver receiver = new MyReceiver(); registerReceiver(receiver, filter);
unregisterReceiver(receiver);
|
MainActivity 启动 MainActivity2 当然也是用到 Intent
1 2 3 4
| Intent intent = new Intent(MainActivity.this, (Class<?>) MainActivity2.class); MainActivity.this.startActivity(intent); MainActivity.this.finish(); return;
|
这是 app 中界面导航的范式。
这题的 apk 其实有很多可疑的地方,比如 assets 里面有个压缩包,export 出来又打不开,010 看一眼发现是 .jpg,直接改一下后缀名就可以看到图片里的 flag。并且直接去看 NextContent 的话也可以发现很可疑的东西
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
| 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)); }
|
是一个图片覆盖的逻辑,把压缩包盖到图片上了,不难想到去看这个压缩包。