metasploit-framework/external/source/exploits/CVE-2018-4237/libspc/dictionary.c

263 lines
7.9 KiB
C

#include "datatypes.h"
#include "utils.h"
#include <stdlib.h>
#include <stdio.h>
extern int fileport_makeport(int fd, mach_port_t* port);
spc_dictionary_t* spc_dictionary_create()
{
return calloc(sizeof(spc_dictionary_t), 1);
}
void spc_dictionary_destroy(spc_dictionary_t* dict)
{
spc_dictionary_item_t* current, *last;
current = dict->items;
while (current) {
free(current->key);
spc_value_destroy(current->value);
last = current;
current = current->next;
free(last);
}
free(dict);
}
spc_dictionary_item_t* spc_dictionary_lookup(spc_dictionary_t* dict, const char* key)
{
spc_dictionary_item_t* current = dict->items;
while (current) {
if (strcmp(current->key, key) == 0)
return current;
current = current->next;
}
return NULL;
}
spc_dictionary_item_t* spc_dictionary_add_item(spc_dictionary_t* dict, const char* key, uint32_t type)
{
spc_dictionary_item_t* item = spc_dictionary_lookup(dict, key);
if (item) {
spc_value_destroy(item->value);
} else {
item = malloc(sizeof(spc_dictionary_item_t));
item->next = dict->items;
dict->items = item;
dict->num_items++;
item->key = strdup(key);
}
item->value.type = type;
return item;
}
void spc_dictionary_set_value(spc_dictionary_t* dict, const char* key, spc_value_t value)
{
spc_dictionary_item_t* item = spc_dictionary_add_item(dict, key, SPC_TYPE_STRING);
item->value = value;
}
void spc_dictionary_set_string(spc_dictionary_t* dict, const char* key, const char* value)
{
spc_dictionary_item_t* item = spc_dictionary_add_item(dict, key, SPC_TYPE_STRING);
item->value.value.str = strdup(value);
}
void spc_dictionary_set_uint64(spc_dictionary_t* dict, const char* key, uint64_t value)
{
spc_dictionary_item_t* item = spc_dictionary_add_item(dict, key, SPC_TYPE_UINT64);
item->value.value.u64 = value;
}
void spc_dictionary_set_int64(spc_dictionary_t* dict, const char* key, int64_t value)
{
spc_dictionary_item_t* item = spc_dictionary_add_item(dict, key, SPC_TYPE_INT64);
item->value.value.i64 = value;
}
void spc_dictionary_set_data(spc_dictionary_t* dict, const char* key, const void* bytes, size_t len)
{
spc_dictionary_item_t* item = spc_dictionary_add_item(dict, key, SPC_TYPE_DATA);
void* buf = malloc(len);
memcpy(buf, bytes, len);
item->value.value.data.ptr = buf;
item->value.value.data.size = len;
}
void spc_dictionary_set_fd(spc_dictionary_t* dict, const char* key, int fd)
{
mach_port_t fileport;
fileport_makeport(fd, &fileport);
spc_dictionary_item_t* item = spc_dictionary_add_item(dict, key, SPC_TYPE_FD);
item->value.value.port.name = fileport;
item->value.value.port.type = MACH_MSG_TYPE_COPY_SEND;
}
// TODO make port type a parameter
void spc_dictionary_set_send_port(spc_dictionary_t* dict, const char* key, mach_port_t port)
{
mach_port_addref(port, MACH_PORT_RIGHT_SEND);
spc_dictionary_item_t* item = spc_dictionary_add_item(dict, key, SPC_TYPE_SEND_PORT);
item->value.value.port.name = port;
item->value.value.port.type = MACH_MSG_TYPE_COPY_SEND;
}
void spc_dictionary_set_receive_port(spc_dictionary_t* dict, const char* key, mach_port_t port)
{
mach_port_addref(port, MACH_PORT_RIGHT_RECEIVE);
spc_dictionary_item_t* item = spc_dictionary_add_item(dict, key, SPC_TYPE_RECV_PORT);
item->value.value.port.name = port;
item->value.value.port.type = MACH_MSG_TYPE_MOVE_RECEIVE;
}
void spc_dictionary_set_bool(spc_dictionary_t* dict, const char* key, int value)
{
spc_dictionary_item_t* item = spc_dictionary_add_item(dict, key, SPC_TYPE_BOOL);
item->value.value.u64 = value;
}
uint64_t spc_dictionary_get_uint64(spc_dictionary_t* dict, const char* key)
{
spc_dictionary_item_t* item = spc_dictionary_lookup(dict, key);
if (!item || item->value.type != SPC_TYPE_UINT64)
return 0;
return item->value.value.u64;
}
int64_t spc_dictionary_get_int64(spc_dictionary_t* dict, const char* key)
{
spc_dictionary_item_t* item = spc_dictionary_lookup(dict, key);
if (!item || item->value.type != SPC_TYPE_INT64)
return 0;
return item->value.value.i64;
}
const char* spc_dictionary_get_string(spc_dictionary_t* dict, const char* key)
{
spc_dictionary_item_t* item = spc_dictionary_lookup(dict, key);
if (!item || item->value.type != SPC_TYPE_STRING)
return NULL;
return item->value.value.str;
}
int spc_dictionary_get_bool(spc_dictionary_t* dict, const char* key)
{
spc_dictionary_item_t* item = spc_dictionary_lookup(dict, key);
if (!item || item->value.type != SPC_TYPE_BOOL)
return 0;
return item->value.value.u64;
}
mach_port_t spc_dictionary_get_send_port(spc_dictionary_t* dict, const char* key)
{
spc_dictionary_item_t* item = spc_dictionary_lookup(dict, key);
if (!item || item->value.type != SPC_TYPE_SEND_PORT)
return MACH_PORT_NULL;
mach_port_addref(item->value.value.port.name, MACH_PORT_RIGHT_SEND);
return item->value.value.port.name;
}
mach_port_t spc_dictionary_get_receive_port(spc_dictionary_t* dict, const char* key)
{
spc_dictionary_item_t* item = spc_dictionary_lookup(dict, key);
if (!item || item->value.type != SPC_TYPE_RECV_PORT)
return MACH_PORT_NULL;
mach_port_addref(item->value.value.port.name, MACH_PORT_RIGHT_RECEIVE);
return item->value.value.port.name;
}
void spc_dump_value(spc_value_t value, int indent)
{
char* indent_str = malloc(indent + 1);
memset(indent_str, ' ', indent);
indent_str[indent] = 0;
switch (value.type) {
case SPC_TYPE_NULL:
printf("%*cnull\n", indent, ' ');
break;
case SPC_TYPE_BOOL:
printf("%*c%s\n", indent, ' ', value.value.u64 ? "true" : "false");
break;
case SPC_TYPE_UINT64:
printf("%*c%llu\n", indent, ' ', value.value.u64);
break;
case SPC_TYPE_INT64:
printf("%*c%lli\n", indent, ' ', value.value.i64);
break;
case SPC_TYPE_DOUBLE:
printf("%*c%f\n", indent, ' ', value.value.dbl);
break;
case SPC_TYPE_STRING:
printf("%*c%s\n", indent, ' ', value.value.str);
break;
case SPC_TYPE_UUID: {
char buf[0x21];
for (int i = 0; i < 0x10; i++) {
sprintf(&buf[2*i], "%02x", ((unsigned char*)value.value.str)[i]);
}
buf[0x20] = 0;
printf("%*cuuid: %s\n", indent, ' ', buf);
break;
}
case SPC_TYPE_ARRAY: {
spc_array_t* array = value.value.array;
printf("%*c[\n", indent, ' ');
for (size_t i = 0; i < array->length; i++) {
spc_dump_value(array->values[i], indent + 2);
}
printf("%*c]\n", indent, ' ');
break;
}
case SPC_TYPE_DICT: {
spc_dictionary_item_t* current = value.value.dict->items;
while (current) {
printf("%*c%s:\n", indent, ' ', current->key);
spc_dump_value(current->value, indent + 2);
current = current->next;
}
break;
}
case SPC_TYPE_SEND_PORT:
printf("%*cport send right: %d\n", indent, ' ', value.value.port.name);
break;
case SPC_TYPE_RECV_PORT:
printf("%*cport receive right: %d\n", indent, ' ', value.value.port.name);
break;
case SPC_TYPE_DATA:
printf("%*cdata: 0x", indent, ' ');
for (size_t i = 0; i < value.value.data.size; i++)
printf("%02x", value.value.data.ptr[i]);
printf("\n");
break;
default:
printf("%*cUnknown item of type %d\n", indent, ' ', value.type);
}
free(indent_str);
}
void spc_dump(spc_dictionary_t* dict)
{
spc_value_t value;
value.type = SPC_TYPE_DICT;
value.value.dict = dict;
spc_dump_value(value, 0);
}