MochaPayload/source/ios_kernel/source/elf_patcher.c

94 lines
3.2 KiB
C
Raw Normal View History

2020-04-28 15:07:52 +02:00
/***************************************************************************
* Copyright (C) 2016
* by Dimok
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any
* damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any
* purpose, including commercial applications, and to alter it and
* redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you
* must not claim that you wrote the original software. If you use
* this software in a product, an acknowledgment in the product
* documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and
* must not be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
***************************************************************************/
#include "elf_abi.h"
2022-02-04 14:23:22 +01:00
#include "types.h"
2020-04-28 15:07:52 +02:00
#include "utils.h"
2020-06-20 23:43:44 +02:00
static Elf32_Phdr *get_section(u32 data, u32 vaddr) {
2020-04-28 15:07:52 +02:00
Elf32_Ehdr *ehdr = (Elf32_Ehdr *) data;
2022-02-04 14:23:22 +01:00
if (!IS_ELF(*ehdr) || (ehdr->e_type != ET_EXEC) || (ehdr->e_machine != EM_ARM)) {
2020-04-28 15:07:52 +02:00
return 0;
}
Elf32_Phdr *phdr = 0;
u32 i;
2020-06-20 23:43:44 +02:00
for (i = 0; i < ehdr->e_phnum; i++) {
2020-04-28 15:07:52 +02:00
phdr = (Elf32_Phdr *) (data + ehdr->e_phoff + ehdr->e_phentsize * i);
2020-06-20 23:43:44 +02:00
if ((vaddr >= phdr[0].p_vaddr) && ((i == ehdr->e_phnum) || (vaddr < phdr[1].p_vaddr))) {
2020-04-28 15:07:52 +02:00
break;
}
}
return phdr;
}
2020-06-20 23:43:44 +02:00
void section_write_bss(u32 ios_elf_start, u32 address, u32 size) {
2020-04-28 15:07:52 +02:00
Elf32_Phdr *phdr = get_section(ios_elf_start, address);
2020-06-20 23:43:44 +02:00
if (!phdr)
2020-04-28 15:07:52 +02:00
return;
2020-06-20 23:43:44 +02:00
if ((address - phdr->p_vaddr + size) > phdr->p_memsz) {
2020-04-28 15:07:52 +02:00
phdr->p_memsz = (address - phdr->p_vaddr + size);
}
}
2020-06-20 23:43:44 +02:00
void section_write(u32 ios_elf_start, u32 address, const void *data, u32 size) {
2020-04-28 15:07:52 +02:00
Elf32_Phdr *phdr = get_section(ios_elf_start, address);
2020-06-20 23:43:44 +02:00
if (!phdr)
2020-04-28 15:07:52 +02:00
return;
2020-06-20 23:43:44 +02:00
u32 *addr = (u32 *) (ios_elf_start + address - phdr->p_vaddr + phdr->p_offset);
2020-04-28 15:07:52 +02:00
2020-06-20 23:43:44 +02:00
if ((address - phdr->p_vaddr + size) > phdr->p_filesz) {
2020-04-28 15:07:52 +02:00
u32 additionalSize = address - phdr->p_vaddr + size - phdr->p_filesz;
Elf32_Ehdr *ehdr = (Elf32_Ehdr *) ios_elf_start;
2020-06-20 23:43:44 +02:00
Elf32_Phdr *tmpPhdr;
2020-04-28 15:07:52 +02:00
u32 i;
2020-06-20 23:43:44 +02:00
for (i = (ehdr->e_phnum - 1); i >= 0; i--) {
2020-04-28 15:07:52 +02:00
tmpPhdr = (Elf32_Phdr *) (ios_elf_start + ehdr->e_phoff + ehdr->e_phentsize * i);
2020-06-20 23:43:44 +02:00
if (phdr->p_offset < tmpPhdr->p_offset) {
reverse_memcpy((u8 *) ios_elf_start + tmpPhdr->p_offset + additionalSize, (u8 *) ios_elf_start + tmpPhdr->p_offset, tmpPhdr->p_filesz);
2020-04-28 15:07:52 +02:00
tmpPhdr->p_offset += additionalSize;
2020-06-20 23:43:44 +02:00
} else {
2020-04-28 15:07:52 +02:00
break;
}
}
phdr->p_filesz += additionalSize;
2020-06-20 23:43:44 +02:00
if (phdr->p_memsz < phdr->p_filesz) {
2020-04-28 15:07:52 +02:00
phdr->p_memsz = phdr->p_filesz;
}
}
// in most cases only a word is copied to an aligned address so do a short cut for performance
2020-06-20 23:43:44 +02:00
if (size == 4 && !((unsigned int) addr & 3) && !((unsigned int) data & 3)) {
*(u32 *) addr = *(u32 *) data;
} else {
2020-04-28 15:07:52 +02:00
kernel_memcpy(addr, data, size);
}
}