-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathpatch_base.cpp
More file actions
89 lines (74 loc) · 2.59 KB
/
Copy pathpatch_base.cpp
File metadata and controls
89 lines (74 loc) · 2.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include "patch_base.h"
using namespace asmjit;
using namespace asmjit::a64;
using namespace asmjit::a64::Predicate;
struct cred_uid_info {
uint32_t uid; /* real UID of the task */
uint32_t gid; /* real GID of the task */
uint32_t suid; /* saved UID of the task */
uint32_t sgid; /* saved GID of the task */
uint32_t euid; /* effective UID of the task */
uint32_t egid; /* effective GID of the task */
uint32_t fsuid; /* UID for VFS ops */
uint32_t fsgid; /* GID for VFS ops */
};
PatchBase::PatchBase(const std::vector<char>& file_buf, size_t cred_uid_offset) :
m_file_buf(file_buf), m_kernel_ver_parser(file_buf), m_cred_uid_offset(cred_uid_offset) {}
PatchBase::PatchBase(const PatchBase& other)
: m_file_buf(other.m_file_buf)
, m_kernel_ver_parser(other.m_file_buf)
, m_cred_uid_offset(other.m_cred_uid_offset)
{}
PatchBase::~PatchBase() {}
int PatchBase::get_cred_atomic_usage_len() {
return m_cred_uid_offset;
}
int PatchBase::get_cred_uid_region_len() {
return sizeof(cred_uid_info);
}
int PatchBase::get_cred_euid_offset() {
return get_cred_atomic_usage_len() + offsetof(cred_uid_info, euid);
}
int PatchBase::get_cred_securebits_padding() {
if (get_cred_atomic_usage_len() == 8) {
return 4;
}
return 0;
}
uint64_t PatchBase::get_cap_ability_max() {
return 0x1FFFFFFFFFF;
}
int PatchBase::get_cap_cnt() {
return 5;
}
size_t PatchBase::patch_jump(size_t patch_addr, size_t jump_addr, std::vector<patch_bytes_data>& vec_out_patch_bytes_data) {
aarch64_asm_ctx asm_ctx = init_aarch64_asm();
auto a = asm_ctx.assembler();
aarch64_asm_b(a, (int32_t)(jump_addr - patch_addr));
std::vector<uint8_t> bytes = aarch64_asm_to_bytes(a);
if (bytes.size() == 0) return 0;
std::string str_bytes = bytes2hex((const unsigned char*)bytes.data(), bytes.size());
vec_out_patch_bytes_data.push_back({ str_bytes, patch_addr });
return bytes.size();
}
void PatchBase::emit_get_current(Assembler* a, GpX x) {
uint32_t sp_el0_id = SysReg::encode(3, 0, 4, 1, 0);
a->mrs(x, sp_el0_id);
}
void PatchBase::emit_safe_bl(Assembler* a, size_t func_base_addr, size_t target) {
RegProtectGuard g1(a, x29, x30);
size_t bl_addr = func_base_addr + a->offset();
int64_t diff = (int64_t)target - (int64_t)bl_addr;
aarch64_asm_bl_raw(a, (int32_t)diff);
}
std::vector<size_t> PatchBase::find_all_aarch64_ret_offsets(size_t offset, size_t size) {
std::vector<size_t> v_ret_addr;
for (auto i = offset; i < offset + size; i += 4) {
constexpr uint32_t kRetInstr = 0xD65F03C0;
uint32_t instr = *reinterpret_cast<const uint32_t*>(&m_file_buf[i]);
if (instr == kRetInstr) {
v_ret_addr.push_back(i);
}
}
return v_ret_addr;
}