深夜提醒

现在是深夜,建议您注意休息,不要熬夜哦~

🏮 🏮 🏮

新年快乐

祝君万事如意心想事成!

share-image
中
ESC

A Complete Implementation Guide to Android App Security Hardening

English 阅读中文版

1. Code Obfuscation and Hardening

1.1 Enable Code Obfuscation

Modify the app/build.gradle.kts file:

android {
buildTypes {
release {
isMinifyEnabled = true // Enable code obfuscation
isShrinkResources = true // Enable resource shrinking
proguardFiles(
getDefaultProguardFile(\
proguard-android-optimize.txt\),
\proguard-rules.pro\
)
}
debug {
isMinifyEnabled = false
}
}
}

1.2 Configure ProGuard Rules

Create or modify the app/proguard-rules.pro file:

# Basic configuration
-keepattributes SourceFile,LineNumberTable
-renamesourcefileattribute SourceFile
-keepattributes *Annotation*
-keepattributes Signature
-keepattributes Exceptions

# Kotlin configuration
-keep class kotlin.Metadata { *; }
-dontwarn kotlin.**
-keepclassmembers class ** {
<fields>;
}

# Kotlin Coroutines
-keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {}
-keepnames class kotlinx.coroutines.CoroutineExceptionHandler {}
-dontwarn kotlinx.coroutines.**

# Jetpack Compose
-keep class androidx.compose.** { *; }
-dontwarn androidx.compose.**

# Retrofit & OkHttp
-keepattributes Signature, InnerClasses, EnclosingMethod
-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations
-keepclassmembers,allowshrinking,allowobfuscation interface * {
@retrofit2.http.* <methods>;
}
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
-dontwarn javax.annotation.**
-dontwarn kotlin.Unit
-dontwarn retrofit2.KotlinExtensions
-dontwarn retrofit2.KotlinExtensions$*

# OkHttp
-dontwarn okhttp3.**
-dontwarn okio.**
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase

# Gson
-keepattributes Signature
-keepattributes *Annotation*
-dontwarn sun.misc.**
-keep class com.google.gson.** { *; }
-keep class * implements com.google.gson.TypeAdapter
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer

# Keep data model classes
-keep class com.awen.running.network.** { *; }
-keep class com.awen.running.data.** { *; }

# AMap SDK
-keep class com.amap.api.** { *; }
-keep class com.autonavi.** { *; }
-dontwarn com.amap.api.**
-dontwarn com.autonavi.**

# Alibaba Cloud NUI SDK
-keep class com.alibaba.** { *; }
-dontwarn com.alibaba.**

# FastJSON
-keep class com.alibaba.fastjson.** { *; }
-dontwarn com.alibaba.fastjson.**

# MPAndroidChart
-keep class com.github.mikephil.charting.** { *; }
-dontwarn com.github.mikephil.charting.**

# Bluetooth-related
-keep class android.bluetooth.** { *; }
-keep class com.awen.running.bluetooth.** { *; }

# Strip sensitive info
-assumenosideeffects class android.util.Log {
public static *** d(...);
public static *** v(...);
public static *** i(...);
}

# Keep Serializable classes
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}

# Keep Parcelable classes
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable *;
}

# Keep enums
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}

2. Network Communication Security

2.1 Configure SSL Certificate Pinning

Modify the app/src/main/java/com/awen/running/network/RetrofitClient.kt file:

package com.awen.running.network

import android.content.Context
import android.content.SharedPreferences
import com.awen.running.BuildConfig
import com.awen.running.security.EncryptedStorage
import okhttp3.CertificatePinner
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit

object RetrofitClient {
private const val BASE_URL = \https://api.awen.me/api/v1/\

// No longer using ordinary SharedPreferences; switched to encrypted storage
private var authToken: String? = null
private var userId: Int? = null

private var applicationContext: Context? = null

/**
* Initialize (call in Application)
*/
fun init(context: Context) {
applicationContext = context.applicationContext
// Load token from encrypted storage
authToken = EncryptedStorage.getToken(context)
userId = EncryptedStorage.getUserId(context)
}

/**
* SSL certificate pinning (prevents man-in-the-middle attacks)
*/
private val certificatePinner = CertificatePinner.Builder()
.add(\api.awen.me\, \sha256/v9InP1GnrRxH80k4Mrccvr2JwZEsrJh+LVyOGzcZmk4=\) // real certificate fingerprint
.add(\api.awen.me\, \sha256/mTGuGxOfs9PK15aUeNsmQQQ6VL8f0bCvdvEEqkjC6M8=\) // backup certificate
.build()

private val loggingInterceptor = HttpLoggingInterceptor().apply {
// Enable verbose logging only in Debug builds, to prevent leaking sensitive info
level = if (BuildConfig.DEBUG) {
HttpLoggingInterceptor.Level.BODY
} else {
HttpLoggingInterceptor.Level.NONE // Disable logging in Release builds
}
}

private val client: OkHttpClient by lazy {
OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
// Enable SSL certificate pinning (strongly recommended for production)
.certificatePinner(certificatePinner) // Enable certificate pinning
.addInterceptor(loggingInterceptor)
.addInterceptor { chain ->
val original = chain.request()
val requestBuilder = original.newBuilder()
.header(\Content-Type\, \application/json\)

// Add the Authorization header
authToken?.let {
requestBuilder.header(\Authorization\, \Bearer
\)
}

chain.proceed(requestBuilder.build())
}
.build()
}

val apiService: ApiService by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(ApiService::class.java)
}

/**
* Save token
*/
fun setToken(token: String, userId: Int? = null) {
authToken = token
this.userId = userId
// Also save to encrypted storage
applicationContext?.let { context ->
EncryptedStorage.saveToken(context, token)
userId?.let { EncryptedStorage.saveUserId(context, it) }
}
}

/**
* Get token
*/
fun getToken(): String? = authToken

/**
* Get user ID
*/
fun getUserId(): Int? = userId

/**
* Whether a token exists
*/
fun hasToken(): Boolean = !authToken.isNullOrEmpty()

/**
* Clear token (call on logout)
*/
fun clearToken() {
authToken = null
userId = null
// Also clear encrypted storage
applicationContext?.let { context ->
EncryptedStorage.clearToken(context)
}
}
}

2.2 Network Security Configuration

Create the app/src/main/res/xml/network_security_config.xml file:

<?xml version=\1.0\ encoding=\utf-8\?>
<network-security-config>
<!-- Disallow cleartext traffic -->
<base-config cleartextTrafficPermitted=\false\>
<trust-anchors>
<certificates src=\system\ />
</trust-anchors>
</base-config>

<!-- Allow HTTPS only -->
<domain-config cleartextTrafficPermitted=\false\>
<domain includeSubdomains=\true\>api.awen.me</domain>
</domain-config>
</network-security-config>

Reference it in app/src/main/AndroidManifest.xml:

<application
android:networkSecurityConfig=\@xml/network_security_config\
...>

3. Data Storage Security

3.1 Add the Encrypted Storage Dependency

Modify the app/build.gradle.kts file:

dependencies {
// Other dependencies...

// Encrypted storage
implementation(\androidx.security:security-crypto:1.1.0-alpha06\)
}

3.2 Create an Encrypted Storage Utility Class

Create the app/src/main/java/com/awen/running/security/EncryptedStorage.kt file:

package com.awen.running.security

import android.content.Context
import android.content.SharedPreferences
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey
import java.security.SecureRandom
import javax.crypto.Cipher
import javax.crypto.KeyGenerator
import javax.crypto.SecretKey
import javax.crypto.spec.GCMParameterSpec
import javax.crypto.spec.SecretKeySpec
import android.util.Base64

/**
* Encrypted storage utility class - for securely storing sensitive data
*/
object EncryptedStorage {

private const val ENCRYPTED_PREFS_NAME = \encrypted_prefs\
private const val ANDROID_KEYSTORE = \AndroidKeyStore\
private const val AES_MODE = \AES/GCM/NoPadding\

/**
* Get an encrypted SharedPreferences instance
*/
private fun getEncryptedPrefs(context: Context): SharedPreferences {
val masterKey = MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()

return EncryptedSharedPreferences.create(
context,
ENCRYPTED_PREFS_NAME,
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
}

// ==================== JWT Token operations ====================

private const val KEY_JWT_TOKEN = \jwt_token\
private const val KEY_USER_ID = \user_id\

/**
* Save JWT token
*/
fun saveToken(context: Context, token: String) {
getEncryptedPrefs(context).edit()
.putString(KEY_JWT_TOKEN, token)
.apply()
}

/**
* Get JWT token
*/
fun getToken(context: Context): String? {
return getEncryptedPrefs(context).getString(KEY_JWT_TOKEN, null)
}

/**
* Save user ID
*/
fun saveUserId(context: Context, userId: Int) {
getEncryptedPrefs(context).edit()
.putInt(KEY_USER_ID, userId)
.apply()
}

/**
* Get user ID
*/
fun getUserId(context: Context): Int? {
return getEncryptedPrefs(context).getInt(KEY_USER_ID, -1).takeIf { it != -1 }
}

/**
* Clear token
*/
fun clearToken(context: Context) {
getEncryptedPrefs(context).edit()
.remove(KEY_JWT_TOKEN)
.remove(KEY_USER_ID)
.apply()
}

/**
* Check whether a valid token exists
*/
fun hasValidToken(context: Context): Boolean {
val token = getToken(context)
return !token.isNullOrEmpty()
}

// ==================== Other sensitive data operations ====================

private const val KEY_RESTING_HEART_RATE = \resting_heart_rate\
private const val KEY_HEART_RATE_ZONE_SETTINGS = \heart_rate_zone_settings\

/**
* Save resting heart rate
*/
fun saveRestingHeartRate(context: Context, restingRate: Int) {
getEncryptedPrefs(context).edit()
.putInt(KEY_RESTING_HEART_RATE, restingRate)
.apply()
}

/**
* Get resting heart rate
*/
fun getRestingHeartRate(context: Context): Int? {
val rate = getEncryptedPrefs(context).getInt(KEY_RESTING_HEART_RATE, -1)
return if (rate != -1) rate else null
}

/**
* Save heart-rate zone settings
*/
fun saveHeartRateZoneSettings(context: Context, settings: String) {
getEncryptedPrefs(context).edit()
.putString(KEY_HEART_RATE_ZONE_SETTINGS, settings)
.apply()
}

/**
* Get heart-rate zone settings
*/
fun getHeartRateZoneSettings(context: Context): String? {
return getEncryptedPrefs(context).getString(KEY_HEART_RATE_ZONE_SETTINGS, null)
}

/**
* Clear all encrypted data
*/
fun clearAll(context: Context) {
getEncryptedPrefs(context).edit()
.clear()
.apply()
}
}

4. App Signing and Release

4.1 Generate a Signing Key

Run the following command on the command line:

keytool -genkey -v -keystore running-release.keystore \
-alias running-key \
-keyalg RSA \
-keysize 2048 \
-validity 10000

4.2 Configure Signing

Modify the app/build.gradle.kts file:

android {
signingConfigs {
create(\release\) {
storeFile = file(rootDir.absolutePath + \/running-release.keystore\)
storePassword = System.getenv(\KEYSTORE_PASSWORD\) ?: System.getProperty(\KEYSTORE_PASSWORD\)
keyAlias = \running-key\
keyPassword = System.getenv(\KEY_PASSWORD\) ?: System.getProperty(\KEY_PASSWORD\)
}
}

buildTypes {
release {
signingConfig = signingConfigs.getByName(\release\)
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile(\proguard-android-optimize.txt\),
\proguard-rules.pro\
)
}
debug {
isMinifyEnabled = false
}
}
}

4.3 Secure Build Commands

Production environment:

KEYSTORE_PASSWORD=your_password KEY_PASSWORD=your_password ./gradlew assembleRelease

PowerShell environment:

=\your_password\; =\your_password\; ./gradlew assembleRelease

Local development environment:

./gradlew assembleRelease -DKEYSTORE_PASSWORD=your_password -DKEY_PASSWORD=your_password

5. Runtime Security Detection

5.1 Create a Security Detection Utility Class

Create the app/src/main/java/com/awen/running/security/SecurityUtils.kt file:

package com.awen.running.security

import android.content.Context
import android.os.Build
import android.provider.Settings
import java.io.File

/**
* Security utility class: root detection, emulator detection, anti-debugging
*/
object SecurityUtils {

/**
* Detect whether the device is rooted
* @return true means rooted, false means not rooted
*/
fun isDeviceRooted(): Boolean {
return checkRootMethod1() || checkRootMethod2() || checkRootMethod3()
}

/**
* Method 1: check for common root management tools
*/
private fun checkRootMethod1(): Boolean {
val paths = arrayOf(
\/system/app/Superuser.apk\,
\/sbin/su\,
\/system/bin/su\,
\/system/xbin/su\,
\/data/local/xbin/su\,
\/data/local/bin/su\,
\/system/sd/xbin/su\,
\/system/bin/failsafe/su\,
\/data/local/su\,
\/su/bin/su\
)

for (path in paths) {
if (File(path).exists()) {
return true
}
}
return false
}

/**
* Method 2: run the su command to detect
*/
private fun checkRootMethod2(): Boolean {
var process: Process? = null
return try {
process = Runtime.getRuntime().exec(arrayOf(\/system/xbin/which\, \su\))
val bufferedReader = process.inputStream.bufferedReader()
bufferedReader.readLine() != null
} catch (e: Exception) {
false
} finally {
process?.destroy()
}
}

/**
* Method 3: check system properties
*/
private fun checkRootMethod3(): Boolean {
val buildTags = Build.TAGS
return buildTags != null && buildTags.contains(\test-keys\)
}

/**
* Detect whether it's running in an emulator
* @return true means emulator, false means real device
*/
fun isEmulator(): Boolean {
return (Build.FINGERPRINT.startsWith(\generic\)
|| Build.FINGERPRINT.startsWith(\unknown\)
|| Build.MODEL.contains(\google_sdk\)
|| Build.MODEL.contains(\Emulator\)
|| Build.MODEL.contains(\Android
SDK
built
for
x86\)
|| Build.MANUFACTURER.contains(\Genymotion\)
|| (Build.BRAND.startsWith(\generic\) && Build.DEVICE.startsWith(\generic\))
|| \google_sdk\ == Build.PRODUCT
|| Build.HARDWARE.contains(\goldfish\)
|| Build.HARDWARE.contains(\ranchu\))
}

/**
* Detect whether it's currently being debugged
* @return true means being debugged, false means not
*/
fun isDebuggerConnected(): Boolean {
return android.os.Debug.isDebuggerConnected()
}

/**
* Detect whether USB debugging is enabled
*/
fun isUsbDebuggingEnabled(context: Context): Boolean {
return Settings.Global.getInt(
context.contentResolver,
Settings.Global.ADB_ENABLED,
0
) > 0
}

/**
* Comprehensive security check
* @return the check result and risk warnings
*/
fun performSecurityCheck(context: Context): SecurityCheckResult {
val risks = mutableListOf<String>()

if (isDeviceRooted()) {
risks.add(\Device is rooted, security risk present\)
}

if (isEmulator()) {
risks.add(\Emulator environment detected\)
}

if (isDebuggerConnected()) {
risks.add(\Debugger connection detected\)
}

if (isUsbDebuggingEnabled(context)) {
risks.add(\USB debugging is enabled\)
}

return SecurityCheckResult(
isSafe = risks.isEmpty(),
risks = risks
)
}

/**
* Security check result
*/
data class SecurityCheckResult(
val isSafe: Boolean,
val risks: List<String>
)
}

5.2 Use Security Detection in the App

Add to MainActivity.kt or Application.kt:

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

// Production security check
if (!BuildConfig.DEBUG) {
val result = SecurityUtils.performSecurityCheck(this)
if (!result.isSafe) {
// Show a warning or refuse to run
AlertDialog.Builder(this)
.setTitle(\Security Warning\)
.setMessage(result.risks.joinToString(\\\n\))
.setPositiveButton(\Continue\) { _, _ -> }
.setNegativeButton(\Exit\) { _, _ -> finish() }
.show()
}
}
}

5.3 Anti-Screenshot Protection

Add anti-screenshot to sensitive pages:

// In the Activity's onCreate
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
window.setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE
)
}

6. App Hardening

6.1 Use a Third-Party Hardening Platform

The following hardening platforms are recommended:

6.2 Hardening Process

# 1. Compile the Release build
./gradlew assembleRelease

# 2. Upload to the hardening platform
# - Select hardening options
# - Download the hardened APK
# - Re-sign it (hardening breaks the signature)

# 3. Test the hardened APK

7. Complete Implementation Checklist

7.1 Files to Modify

  1. app/build.gradle.kts - configure obfuscation, signing, dependencies
  2. app/proguard-rules.pro - ProGuard rules
  3. app/src/main/java/com/awen/running/network/RetrofitClient.kt - network security configuration
  4. app/src/main/res/xml/network_security_config.xml - network security configuration
  5. app/src/main/java/com/awen/running/security/EncryptedStorage.kt - encrypted storage
  6. app/src/main/java/com/awen/running/security/SecurityUtils.kt - security detection
  7. app/src/main/AndroidManifest.xml - reference the network security configuration

7.2 Commands to Run

  1. Generate the signing key: keytool -genkey -v -keystore running-release.keystore -alias running-key -keyalg RSA -keysize 2048 -validity 10000
  2. Build Release: KEYSTORE_PASSWORD=your_password KEY_PASSWORD=your_password ./gradlew assembleRelease

7.3 Verification Steps

  1. Check whether obfuscation took effect: decompile the APK and see whether the code is obfuscated
  2. Verify SSL certificate pinning: try using Charles to capture HTTPS requests
  3. Confirm data encryption: check the contents of the SharedPreferences file
  4. Verify the signature: check the APK signature info

8. Security Level Assessment

Security measure Status Score
Code obfuscation Enabled
SSL certificate pinning Configured
Sensitive data encryption Enabled
Conditional log output Enabled
Security detection Integrated
App hardening Recommended

Overall security level: Enterprise-grade (suitable for commercial apps)

9. Summary

By implementing the above security measures, your Android app will have:

  • Protection at the code level (obfuscation and hardening)
  • Security of network communication (SSL certificate pinning)
  • Security of data storage (encrypted storage)
  • Security of the runtime environment (security detection)
  • Security of the release build (signature protection)

These measures will greatly improve the app’s security and protect user data and corporate interests. Remember, security is an ongoing process; security measures need to be regularly assessed and updated to cope with new threats.


Document created: February 2026
Version: 1.0

文章作者:阿文
文章链接: https://www.awen.me/post/c9911de2.html
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 阿文的博客!
本文于 2026-02-02 20:41 发布,已超过半年(256天),请注意甄别内容是否已过期。

评论

0 条评论
😀😃😄 😁😅😂 🤣😊😇 🙂🙃😉 😌😍🥰 😘😗😙 😚😋😛 😝😜🤪 🤨🧐🤓 😎🥸🤩 🥳😏😒 😞😔😟 😕🙁☹️ 😣😖😫 😩🥺😢 😭😤😠 😡🤬🤯 😳🥵🥶 😱😨😰 😥😓🤗 🤔🤭🤫 🤥😶😐 😑😬🙄 😯😦😧 😮😲🥱 😴🤤😪 😵🤐🥴 🤢🤮🤧 😷🤒🤕 🤑🤠😈 👿👹👺 🤡💩👻 💀☠️👽 👾🤖🎃 😺😸😹 😻😼😽 🙀😿😾 👍👎👏 🙌👐🤲 🤝🤜🤛 ✌️🤞🤟 🤘👌🤏 👈👉👆 👇☝️✋ 🤚🖐️🖖 👋🤙💪 🦾🖕✍️ 🙏💅🤳 💯💢💥 💫💦💨 🕳️💣💬 👁️‍🗨️🗨️🗯️ 💭💤❤️ 🧡💛💚 💙💜🖤 🤍🤎💔 ❣️💕💞 💓💗💖 💘💝💟 ☮️✝️☪️ 🕉️☸️✡️ 🔯🕎☯️ ☦️🛐⛎ ♈♉♊ ♋♌♍ ♎♏♐ ♑♒♓ 🆔⚛️🉑 ☢️☣️📴 📳🈶🈚 🈸🈺🈷️ ✴️🆚💮 🉐㊙️㊗️ 🈴🈵🈹 🈲🅰️🅱️ 🆎🆑🅾️ 🆘❌⭕ 🛑⛔📛 🚫💯💢 ♨️🚷🚯 🚳🚱🔞 📵🚭❗ ❕❓❔ ‼️⁉️🔅 🔆〽️⚠️ 🚸🔱⚜️ 🔰♻️✅ 🈯💹❇️ ✳️❎🌐 💠Ⓜ️🌀 💤🏧🚾 ♿🅿️🈳 🈂🛂🛃 🛄🛅🛗 🚀🛸🚁 🚉🚆🚅 ✈️🛫🛬 🛩️💺🛰️
加载中...

留言反馈

😀😃😄 😁😅😂 🤣😊😇 🙂🙃😉 😌😍🥰 😘😗😙 😚😋😛 😝😜🤪 🤨🧐🤓 😎🥸🤩 🥳😏😒 😞😔😟 😕🙁☹️ 😣😖😫 😩🥺😢 😭😤😠 😡🤬🤯 😳🥵🥶 😱😨😰 😥😓🤗 🤔🤭🤫 🤥😶😐 😑😬🙄 😯😦😧 😮😲🥱 😴🤤😪 😵🤐🥴 🤢🤮🤧 😷🤒🤕 🤑🤠😈 👿👹👺 🤡💩👻 💀☠️👽 👾🤖🎃 😺😸😹 😻😼😽 🙀😿😾 👍👎👏 🙌👐🤲 🤝🤜🤛 ✌️🤞🤟 🤘👌🤏 👈👉👆 👇☝️✋ 🤚🖐️🖖 👋🤙💪 🦾🖕✍️ 🙏💅🤳 💯💢💥 💫💦💨 🕳️💣💬 👁️‍🗨️🗨️🗯️ 💭💤❤️ 🧡💛💚 💙💜🖤 🤍🤎💔 ❣️💕💞 💓💗💖 💘💝💟 ☮️✝️☪️ 🕉️☸️✡️ 🔯🕎☯️ ☦️🛐⛎ ♈♉♊ ♋♌♍ ♎♏♐ ♑♒♓ 🆔⚛️🉑 ☢️☣️📴 📳🈶🈚 🈸🈺🈷️ ✴️🆚💮 🉐㊙️㊗️ 🈴🈵🈹 🈲🅰️🅱️ 🆎🆑🅾️ 🆘❌⭕ 🛑⛔📛 🚫💯💢 ♨️🚷🚯 🚳🚱🔞 📵🚭❗ ❕❓❔ ‼️⁉️🔅 🔆〽️⚠️ 🚸🔱⚜️ 🔰♻️✅ 🈯💹❇️ ✳️❎🌐 💠Ⓜ️🌀 💤🏧🚾 ♿🅿️🈳 🈂🛂🛃 🛄🛅🛗 🚀🛸🚁 🚉🚆🚅 ✈️🛫🛬 🛩️💺🛰️