Asia 24 WeiMinCheng Systemui As Evilpip The Hijacking Attacks On Modern Mobile Devices
Asia 24 WeiMinCheng Systemui As Evilpip The Hijacking Attacks On Modern Mobile Devices
#BHASIA @BlackHatEvents
WhoAreWe
# BHASIA @BlackHatEvents
What is AHA
• Activity Hijack Attack(AHA) almost zero cost and easy to exploit
• Hijack target app for stealing sensitive data or runtime privilege
• Adware, BankBot, Ransomware, Rat…
# BHASIA @BlackHatEvents
How AHA Work
• Take Android4.0 as an example
• Case of Simplocker, malware for Android4.0
• Essence is abuse NEW_TASK FLAG to seize FG Task
# BHASIA @BlackHatEvents
Task And Back-Stack
• Task Stack is a collection of activities
• User can only interact with ONE Front Task (in most case)
# BHASIA @BlackHatEvents
Classic Attack Scheme
# BHASIA @BlackHatEvents
Classic Attack Scheme
# BHASIA @BlackHatEvents
Key Factors OF AHA
# BHASIA @BlackHatEvents
Google will not allow this happen
# BHASIA @BlackHatEvents
Restriction 0x1 No Leak State
• getRunningTasks || getRunningAppProcesses requires no permission
• Leak runtime state of other app by special interface before API22
• Only Return Caller’s Data in API>=22
# BHASIA @BlackHatEvents
Restriction 0x1 No Leak State
• Still have side-channel way to bypass in API<26
• cat /proc/{target_pid}/oom_score_adj
• Work for non-privilege user!
# BHASIA @BlackHatEvents
Restriction 0x1 No Leak State
• Google update SELinux Policy in 2017
• Hidepid=2 like protections
• Restrict App access file in non-AppDomain
# BHASIA @BlackHatEvents
Restriction 0x2 No BAL
API29+ App without privilege can’t start Activity from Background
No BAL == can’t inject target from Background
Most Adware && Hijackware disppeared due to this
https://developer.android.com/guide/components/activities/background-starts
# BHASIA @BlackHatEvents
Compromise Scheme
• Turn to AccessibilityService||SystemServices||SAW permission
• Complex User Interaction&&Dangerous Runtime Permission
• Satisfy BAL Restriction Exemptions in document
• Requires System System Bind…
• Requires Visible App Bind…
• Requires Holds System Privilege…
• Almost impossible…
# BHASIA @BlackHatEvents
Restriction 0x3 BEL&&LMKD
• Background Service in API26+ get High OOM_ADJ&&Low Priority!
• BgProcess == IDLE Process, LMKD kill idle process first
• System Broadcast Trick BANNED in API24+!
https://developer.android.com/about/versions/oreo/background
# BHASIA @BlackHatEvents
Compromise Scheme
Compromise scheme provided by Google
Start Foreground Service For Low OOM_ADJ
• Have to notify User, no silent process
• 3rd ROM even not allow FgService long time running
# BHASIA @BlackHatEvents
But, Compromise Scheme Really Work?
• Grant dangerous permission → Complex User Interaction
• No Silent Running → Awared by user
• Case Of Xiaomi OS, even no persistently process
• High attack cost, highly user detectable → Attack failed
When #removeTask
AOSP will call #isProcStateBackground
MIUI directly call forceStop to all process.
• No Permission required
• Undetectable
• Hijack precisely
• Attack High Version Device
# BHASIA @BlackHatEvents
1st High Wall: BAL Restriction
# BHASIA @BlackHatEvents
Analyse BAL Restriction
Activity#startActivity
Handled By ActivityManagerService(AMS)
ActivityStarter#executeRequest
API33
# BHASIA @BlackHatEvents
Analyse BAL Restriction
System try to start target component
restrictedBgActivity
Decide whether to move Task to front
ActivityStarter#setInitialState
determines
moveToFront
shouldAbortBackgroundActivityStart(shouldABAS)
# BHASIA @BlackHatEvents
Analyse BAL Restriction
Developer Doc give some exemption for check func
hasActiviteVisibleWindow
# BHASIA @BlackHatEvents
Analyse BAL Restriction
WindowState#onSurfaceShownChanged
mNumNonAppVisibleWindowMap
Inside hasNonAppVisibleWindow
# BHASIA @BlackHatEvents
Window Type&&Z-Axis
WindowToken#addWindow
WindowState#<init>
WindowComparator compare BaseLayer value
Window Type decides mBaseLayer
Which decides Z-axis indirectly
Higher BaseLayer, Higher Z-axis
getWindowLayerFromTypeLw
# BHASIA @BlackHatEvents
Visible Window
hasNonAppVisibleWindow
• Window Type > FIRST_SYSTEM_WINDOW && != TYPE_TOAST
Non-Privilege App usually gets BASE_APPLICATION window
Almost invisible in most time
TYPE_APPLICATION_OVERLAY =
FIRST_SYSTEM_WINDOW + 38;
# BHASIA @BlackHatEvents
What is Picture-in-Picture
• Non-SAW Permission float-window compromise scheme for developer
• Pinned Activity in PiP window at the top of screen
• Handled by SystemUI Component
• Window Type > FIRST_SYSTEM_WINDOW and Permission-less
# BHASIA @BlackHatEvents
What is Picture-in-Picture
• Non-SAW Permission float-window compromise scheme for developer
• Pinned Activity in PiP window at the top of screen
• Handled by SystemUI Component
• Window Type > FIRST_SYSTEM_WINDOW and Permission-less
# BHASIA @BlackHatEvents
What is Picture-in-Picture
Unable to abuse PiP directly
• Pip window can’t hide from screen
• Pinned Activity can be detected by User(Even use transparent theme)
• User can remove PiP window at any time
• PiP is highly detectable feature!
# BHASIA @BlackHatEvents
CVE-2021-0485 By valsamaras
Invalid Input for a abnormal PiP Window
Visible for System, But Invisible for User
Abnormal 1 pixel PiP window
Almost invisible
# BHASIA @BlackHatEvents
CVE-2021-0485 By valsamaras
PipBoundsAlgorithm Patch
aad7fdc4f82ad56e332d3c23c5d07719e069b099
# BHASIA @BlackHatEvents
New Attack Surface
Nice bug expanding Attack Surface
# BHASIA @BlackHatEvents
How PiP Work
ATMS#enterPictureInPictureMode
RootWindowContainer#moveActivityToPinnedRootTask
# BHASIA @BlackHatEvents
How PiP Work
IPC
Task#sendTaskAppear ShellTaskOrganizer#onTaskAppeared
com.android.systemui PipTaskOrganizer#onTaskAppeared
# BHASIA @BlackHatEvents
How PiP Work
# BHASIA @BlackHatEvents
Analyse Attack Vector
Prevent IPC!
Scheme 0x1:
Attack PiP chain, make App task in ‘visible’ state
But no systemUI handle PiP window
# BHASIA @BlackHatEvents
Analyse Attack Vector
Scheme 0x1:
User Space have no way to affect the code execute in System_Server
Can’t prevent IPC
# BHASIA @BlackHatEvents
Analyse Attack Vector
Scheme 0x2:
Attack SystemUI side, create CVE-2021-0485-like vuln
# BHASIA @BlackHatEvents
Attack SourceRectHint
# BHASIA @BlackHatEvents
Attack SourceRectHint
Enter PiP Mode with 1-pixel Rect, Run POC in Android13.0.0_r7 branch AVD
We get a 1-pixel Window indeed, but recover to normal size within 0.5s
Around 0.5s
PipTaskOrganizer#onTaskAppeared
# BHASIA @BlackHatEvents
Trace Rect
finishResize creates a WindowContainerTransaction(WCT) instance
Pass to prepareFinishResizeTransaction with normal size Rect defined by System
Set a SurfaceControl.Transaction and the Rect for WCT inside function
# BHASIA @BlackHatEvents
Trace Rect
applyFinishBoundsResize carry WCT to IPC with SystemServer
# BHASIA @BlackHatEvents
Trace Rect
* Before IPC
applyFinishBoundsResize Extra SurfaceControl.Transaction, IPC with System
Pass SCT into setMainWindowSizeChangeTransaction
Task#setMainWindowSizeChangeTransaction
SystemServer directly call merge to render SCT on screen
Cause Pip Window resize to normal after merge,
any way to prevent merge???
# BHASIA @BlackHatEvents
Trace Rect
# BHASIA @BlackHatEvents
Trace Rect
# BHASIA @BlackHatEvents
Diff Analyse
Compare different branch
API32 found code change
# BHASIA @BlackHatEvents
API32 For 12.1.0_r27
Sets the SCT
WindowStateAnimator#setSurfaceBoundariesLocked
# BHASIA @BlackHatEvents
Analyse CALL STACK
• ActivityRecord#prepareSurface in the call stack
• Related with Activity Launch/Rendering (Enter PiP Mode will relaunch Activity)
• User space can affect it indirectly!
# BHASIA @BlackHatEvents
Attack API32
• API33&&API32 SystemUI all finally call to setMainWindowSizeChangeTransaction
• API33
1. setMWSCT call merge, no way prevent pip size back to normal
2. Whole chain handled by SystemUI
• API32
1. setMWSCT sets SCT to global member, wait for access
2. Activity reDraw will access SCT and call merge == frozen reDraw, merge will not be called
# BHASIA @BlackHatEvents
CVE-2023-40116
# BHASIA @BlackHatEvents
ActivityOptions
Api_diff list -> makeLaunchIntoPip
Return ActivityOptions object
Activity#startActivity(Intent,Bundle)
Additional options for Activity launch
https://developer.android.com/sdk/api_diff/33/changes
# BHASIA @BlackHatEvents
ActivityOptions
Save received PipParam to AO packaged Bundle By LAUNCH_INTO_PIP_PARAMS Key
Bundle used to set options for Activity start
# BHASIA @BlackHatEvents
CVE-2023-21269
Check Bundle by isLaunchIntoPip()
• Where is BAL restriction check?????
Directly call moveActivityToPinnedRootTask without any check???
• Set app to pinned state from background at any time for API33+
# BHASIA @BlackHatEvents
2nd High Wall: State Leaking
# BHASIA @BlackHatEvents
Bug OR Trick?
Bug I met when I am developing an app…
• After merge code → throw Exception by startServiceCommon
• Before merge at bug position: bindService
• After merge at bug position: startService
# BHASIA @BlackHatEvents
Side Channel Detector
Background Execution Limitation
• Throw exception when start background service
• Background Process Detector!
• Bypass Limitation? Explote Limitation!
# BHASIA @BlackHatEvents
A-254674510
ActiveServices#startServiceLocked
# BHASIA @BlackHatEvents
Other Tricks?
# BHASIA @BlackHatEvents
3rd High Wall: Breaking LMKD
# BHASIA @BlackHatEvents
LMKD & OOM_ADJ Score
• Lower oom_adj → Higher priority • Fg Service usually gets score of 250
• Higher oom_adj → Lower priority • No silent process
• LMKD kills high oom score process first
• Bg process always gets high oom score
# BHASIA @BlackHatEvents
OOM_ADJ Calc Trick
Service bound by 3rd Client with oom score < Bounder oom score
• Bounder may gets oom score VISIBLE_APP_ADJ
# BHASIA @BlackHatEvents
AccessibilityService
• Accessibility function handled by AccessibilityManagerService
• Non-privilege App needs to declare specific Intent-Filter
• Intent-Filter pointing a specific Service
# BHASIA @BlackHatEvents
AccessibilityManagerService
• AccessibilityManagerService will find all Service with specific Intent-Filter
• Create AccessibilityServiceConnection by specific Intent-Filter
• Call bindLocked
AccessibilityManagerService#updateServiceLocked
# BHASIA @BlackHatEvents
Bound by System!
AccessibilityManagerService run as system_server(UID=1000)
System_server gets oom score of -900
Non-privilege gets oom socre of 100!
But Accessibility requires dangerous runtime-permission!
# BHASIA @BlackHatEvents
AccountManager
AccountManager API added in API5(2009)
Handled by privilege AccountManagerService
For Developers:
• Declare Service with abstract Component “AccountAuthenticator”!
• Declare Intent-Filter with specific Action!
• No Need dangerous runtime permission!
# BHASIA @BlackHatEvents
AddAccount
Get AM by getSystemService
Call addAccount
new Session().bind()
AccountManager$AmsTask$Response#onResult POC
# BHASIA @BlackHatEvents
DEMO OF PERSISTENT POC
# BHASIA @BlackHatEvents
# BHASIA @BlackHatEvents
Full Chain Of Hijack Exp
# BHASIA @BlackHatEvents
# BHASIA @BlackHatEvents
THANKS!
#BHASIA @BlackHatEvents