void log_api(uint32_t index, int is_success, uintptr_t return_value, uint64_t hash, last_error_t *lasterr, ...) { va_list args; char idx[4]; va_start(args, lasterr); EnterCriticalSection(&g_mutex); if(g_api_init[index] == 0) { log_explain(index); g_api_init[index] = 1; } LeaveCriticalSection(&g_mutex); bson b; bson_init_size(&b, mem_suggested_size(1024)); bson_append_int(&b, "I", index); bson_append_int(&b, "T", get_current_thread_id()); bson_append_int(&b, "t", get_tick_count() - g_starttick); bson_append_long(&b, "h", hash); // If failure has been determined, then log the last error as well. if(is_success == 0) { bson_append_int(&b, "e", lasterr->lasterror); bson_append_int(&b, "E", lasterr->nt_status); } #if DEBUG if(index != sig_index_exception()) { _log_stacktrace(&b); } #endif bson_append_start_array(&b, "args"); bson_append_int(&b, "0", is_success); bson_append_long(&b, "1", return_value); int argnum = 2, override = 0; for (const char *fmt = sig_paramtypes(index); *fmt != 0; fmt++) { ultostr(argnum++, idx, 10); // Limitation override. Instead of displaying this right away in the // report we turn it into a buffer (much like the dropped files). if(*fmt == '!') { override = 1; argnum--; fmt++; } if(*fmt == 's') { const char *s = va_arg(args, const char *); log_string(&b, idx, s, copy_strlen(s)); } else if(*fmt == 'S') {
void log_explain(uint32_t index) { bson b; char argidx[4]; bson_init_size(&b, mem_suggested_size(1024)); bson_append_int(&b, "I", index); bson_append_string(&b, "name", sig_apiname(index)); bson_append_string(&b, "type", "info"); bson_append_string(&b, "category", sig_category(index)); bson_append_start_array(&b, "args"); bson_append_string(&b, "0", "is_success"); bson_append_string(&b, "1", "retval"); const char *fmt = sig_paramtypes(index); for (uint32_t argnum = 2; *fmt != 0; argnum++, fmt++) { ultostr(argnum, argidx, 10); // Ignore buffers, they are sent over separately. if(*fmt == '!') { argnum--; fmt++; continue; } const char *argname = sig_param_name(index, argnum-2); // On certain formats, we need to tell cuckoo about them for // nicer display / matching. if(*fmt == 'p' || *fmt == 'P') { bson_append_start_array(&b, argidx); bson_append_string(&b, "0", argname); bson_append_string(&b, "1", "p"); bson_append_finish_array(&b); } else { bson_append_string(&b, argidx, argname); } } bson_append_finish_array(&b); bson_append_start_object(&b, "flags_value"); for (uint32_t idx = 0; sig_flag_name(index, idx) != NULL; idx++) { const flag_repr_t *f = flag_value(sig_flag_value(index, idx)); bson_append_start_array(&b, sig_flag_name(index, idx)); for (uint32_t idx2 = 0; f->repr != NULL; idx2++, f++) { ultostr(idx, argidx, 10); bson_append_start_array(&b, argidx); bson_append_int(&b, "0", f->value); bson_append_string(&b, "1", f->repr); bson_append_finish_array(&b); } bson_append_finish_array(&b); } bson_append_finish_object(&b); bson_append_start_object(&b, "flags_bitmask"); for (uint32_t idx = 0; sig_flag_name(index, idx) != NULL; idx++) { const flag_repr_t *f = flag_bitmask(sig_flag_value(index, idx)); bson_append_start_array(&b, sig_flag_name(index, idx)); for (uint32_t idx2 = 0; f->repr != NULL; idx2++, f++) { ultostr(idx, argidx, 10); bson_append_start_array(&b, argidx); bson_append_int(&b, "0", f->value); bson_append_string(&b, "1", f->repr); bson_append_finish_array(&b); } bson_append_finish_array(&b); } bson_append_finish_object(&b); bson_finish(&b); log_raw(bson_data(&b), bson_size(&b)); bson_destroy(&b); }