1+ #include " patch_kernel_root.h"
2+ #include " analyze/base_func.h"
3+ #include " analyze/symbol_analyze.h"
4+ #include " patch_do_execve.h"
5+ #include " patch_current_avc_check.h"
6+ #include " patch_avc_denied.h"
7+ #include " patch_audit_log_start.h"
8+ #include " patch_filldir64.h"
9+
10+ #include " 3rdparty/find_mrs_register.h"
11+ #include " 3rdparty/find_imm_register_offset.h"
12+ #include " 3rdparty/find_adrp_target.h"
13+
14+ struct PatchKernelOffset {
15+ size_t cred_offset = 0 ;
16+ size_t cred_uid_offset = 0 ;
17+ size_t seccomp_offset = 0 ;
18+ uint64_t huawei_kti_addr = 0 ;
19+ };
20+
21+ struct PatchKernelResult {
22+ bool patched = false ;
23+ size_t root_key_start = 0 ;
24+ };
25+
26+ bool check_file_path (const char * file_path) {
27+ return std::filesystem::path (file_path).extension () != " .img" ;
28+ }
29+
30+ bool parser_cred_offset (const std::vector<char >& file_buf, const SymbolRegion &symbol, size_t & cred_offset) {
31+ using namespace a64_find_mrs_register ;
32+ std::vector<track_reg_info>track_info;
33+ if (!find_current_task_next_register_offset (file_buf, symbol.offset , symbol.offset + symbol.size , track_info)) return false ;
34+ cred_offset = 0 ;
35+ for (auto & t : track_info) {
36+ if (t.load_offset > 0x400 ) { cred_offset = t.load_offset ; break ; }
37+ }
38+ return cred_offset > 0 ;
39+ }
40+
41+ bool parse_cred_uid_offset (const std::vector<char >& file_buf, const SymbolRegion& symbol, size_t cred_offset, size_t & cred_uid_offset) {
42+ using namespace a64_find_imm_register_offset ;
43+ cred_uid_offset = 0 ;
44+ KernelVersionParser kernel_ver (file_buf);
45+ size_t min_off = 8 ;
46+ if (kernel_ver.is_kernel_version_less (" 6.6.8" )) min_off = 4 ;
47+
48+ std::vector<int64_t > candidate_offsets;
49+ if (!find_imm_register_offset (file_buf, symbol.offset , symbol.offset + symbol.size , candidate_offsets)) return false ;
50+
51+ auto it = std::find (candidate_offsets.begin (), candidate_offsets.end (), cred_offset);
52+ if (it != candidate_offsets.end ()) {
53+ for (++it; it != candidate_offsets.end (); ++it) {
54+ if (*it > 0x20 || *it < min_off) continue ;
55+ cred_uid_offset = *it;
56+ break ;
57+ }
58+ }
59+ return cred_uid_offset != 0 ;
60+ }
61+
62+ bool parser_seccomp_offset (const std::vector<char >& file_buf, const SymbolRegion& symbol, size_t & seccomp_offset) {
63+ using namespace a64_find_mrs_register ;
64+ std::vector<track_reg_info>track_info;
65+ if (!find_current_task_next_register_offset (file_buf, symbol.offset , symbol.offset + symbol.size , track_info)) return false ;
66+ seccomp_offset = 0 ;
67+ for (auto & t : track_info) {
68+ if (t.load_offset > 0x400 ) { seccomp_offset = t.load_offset ; break ; }
69+ }
70+ return seccomp_offset > 0 ;
71+ }
72+
73+ bool parser_huawei_kti_addr (const std::vector<char >& file_buf, const SymbolRegion& symbol, uint64_t & kti_addr) {
74+ using namespace a64_find_adrp_target ;
75+ if (symbol.size == 0 ) return false ;
76+ if (!find_adrp_target (file_buf, symbol.offset , symbol.offset + symbol.size , kti_addr)) return false ;
77+ return kti_addr > 0 ;
78+ }
79+
80+ void cfi_bypass (const std::vector<char >& file_buf, KernelSymbolOffset &sym, std::vector<patch_bytes_data>& vec_patch_bytes_data) {
81+ if (sym.__cfi_check .offset ) PATCH_AND_CONSUME (sym.__cfi_check , patch_ret_cmd (file_buf, sym.__cfi_check .offset , vec_patch_bytes_data));
82+ patch_ret_cmd (file_buf, sym.__cfi_check_fail , vec_patch_bytes_data);
83+ patch_ret_cmd (file_buf, sym.__cfi_slowpath_diag , vec_patch_bytes_data);
84+ patch_ret_cmd (file_buf, sym.__cfi_slowpath , vec_patch_bytes_data);
85+ patch_ret_cmd (file_buf, sym.__ubsan_handle_cfi_check_fail_abort , vec_patch_bytes_data);
86+ patch_ret_cmd (file_buf, sym.__ubsan_handle_cfi_check_fail , vec_patch_bytes_data);
87+ patch_ret_1_cmd (file_buf, sym.report_cfi_failure , vec_patch_bytes_data);
88+ }
89+
90+ void huawei_bypass (const std::vector<char >& file_buf, KernelSymbolOffset &sym, std::vector<patch_bytes_data>& vec_patch_bytes_data) {
91+ patch_ret_0_cmd (file_buf, sym.hkip_check_uid_root , vec_patch_bytes_data);
92+ patch_ret_0_cmd (file_buf, sym.hkip_check_gid_root , vec_patch_bytes_data);
93+ patch_ret_0_cmd (file_buf, sym.hkip_check_xid_root , vec_patch_bytes_data);
94+ }
95+
96+ PatchKernelResult patch_kernel_handler (const std::vector<char >& file_buf, const PatchKernelOffset& off, KernelSymbolOffset& sym, std::vector<patch_bytes_data>& vec_patch_bytes_data) {
97+ KernelVersionParser kernel_ver (file_buf);
98+ PatchBase patchBase (file_buf, off.cred_uid_offset , { .kti_addr = off.huawei_kti_addr });
99+ PatchDoExecve patchDoExecve (patchBase, sym);
100+ PatchCurrentAvcCheck patchCurrentAvcCheck (patchBase);
101+ PatchAvcDenied patchAvcDenied (patchBase, sym.avc_denied );
102+ PatchAuditLogStart patchAuditLogStart (patchBase, sym.audit_log_start );
103+ PatchFilldir64 patchFilldir64 (patchBase, sym.filldir64 );
104+
105+ bool patched = true ;
106+ PatchKernelResult r;
107+ if (kernel_ver.is_kernel_version_less (" 6.1.0" )) {
108+ SymbolRegion next_empty_region = { 0x200 , 0x300 };
109+ if (sym.__cfi_check .offset && sym.__cfi_check .size > next_empty_region.size ) next_empty_region = sym.__cfi_check ;
110+ auto start_b_location = next_empty_region.offset ;
111+ PATCH_AND_CONSUME (next_empty_region, 4 );
112+ r.root_key_start = next_empty_region.offset ;
113+ PATCH_AND_CONSUME (next_empty_region, patchDoExecve.patch_do_execve (next_empty_region, off.cred_offset , off.seccomp_offset , vec_patch_bytes_data));
114+ PATCH_AND_CONSUME (next_empty_region, patchFilldir64.patch_filldir64_root_key_guide (r.root_key_start , next_empty_region, vec_patch_bytes_data));
115+ PATCH_AND_CONSUME (next_empty_region, patchFilldir64.patch_filldir64_core (next_empty_region, vec_patch_bytes_data));
116+ auto current_avc_check_bl_func = next_empty_region.offset ;
117+ PATCH_AND_CONSUME (next_empty_region, patchCurrentAvcCheck.patch_current_avc_check_bl_func (next_empty_region, off.cred_offset , vec_patch_bytes_data));
118+ PATCH_AND_CONSUME (next_empty_region, patchAvcDenied.patch_avc_denied (next_empty_region, current_avc_check_bl_func, vec_patch_bytes_data));
119+ PATCH_AND_CONSUME (next_empty_region, patchAuditLogStart.patch_audit_log_start (next_empty_region, current_avc_check_bl_func, vec_patch_bytes_data));
120+ auto end_b_location = next_empty_region.offset ;
121+ patchBase.patch_jump (start_b_location, end_b_location, vec_patch_bytes_data);
122+ } else if (sym.die .offset && sym.__drm_puts_coredump .offset && sym.__drm_printfn_coredump .offset ) {
123+ PATCH_AND_CONSUME (sym.__drm_printfn_coredump , patch_ret_cmd (file_buf, sym.__drm_printfn_coredump .offset , vec_patch_bytes_data));
124+ PATCH_AND_CONSUME (sym.__drm_puts_coredump , patch_ret_cmd (file_buf, sym.__drm_puts_coredump .offset , vec_patch_bytes_data));
125+ r.root_key_start = sym.die .offset ;
126+ PATCH_AND_CONSUME (sym.die , patchDoExecve.patch_do_execve (sym.die , off.cred_offset , off.seccomp_offset , vec_patch_bytes_data));
127+ PATCH_AND_CONSUME (sym.die , patchFilldir64.patch_filldir64_root_key_guide (r.root_key_start , sym.die , vec_patch_bytes_data));
128+ PATCH_AND_CONSUME (sym.die , patchFilldir64.patch_jump (sym.die .offset , sym.__drm_puts_coredump .offset , vec_patch_bytes_data));
129+ PATCH_AND_CONSUME (sym.__drm_puts_coredump , patchFilldir64.patch_filldir64_core (sym.__drm_puts_coredump , vec_patch_bytes_data));
130+ auto current_avc_check_bl_func = sym.__drm_printfn_coredump .offset ;
131+ PATCH_AND_CONSUME (sym.__drm_printfn_coredump , patchCurrentAvcCheck.patch_current_avc_check_bl_func (sym.__drm_printfn_coredump , off.cred_offset , vec_patch_bytes_data));
132+ PATCH_AND_CONSUME (sym.__drm_printfn_coredump , patchAvcDenied.patch_avc_denied (sym.__drm_printfn_coredump , current_avc_check_bl_func, vec_patch_bytes_data));
133+ PATCH_AND_CONSUME (sym.__drm_printfn_coredump , patchAuditLogStart.patch_audit_log_start (sym.__drm_printfn_coredump , current_avc_check_bl_func, vec_patch_bytes_data));
134+ } else {
135+ patched = false ;
136+ }
137+ r.patched = patched;
138+ return r;
139+ }
140+
141+ void write_all_patch (const char * file_path, std::vector<patch_bytes_data>& vec_patch_bytes_data) {
142+ for (auto & item : vec_patch_bytes_data) {
143+ std::shared_ptr<char > spData (new (std::nothrow) char [item.str_bytes .length () / 2 ], std::default_delete<char []>());
144+ hex2bytes ((uint8_t *)item.str_bytes .c_str (), (uint8_t *)spData.get ());
145+ if (!write_file_bytes (file_path, item.write_addr , spData.get (), item.str_bytes .length () / 2 )) {
146+ std::cout << " 写入文件发生错误" << std::endl;
147+ }
148+ }
149+ if (vec_patch_bytes_data.size ()) std::cout << " Done." << std::endl;
150+ }
151+
152+ int main (int argc, char * argv[]) {
153+ ++argv;
154+ --argc;
155+
156+ std::cout << " 本工具用于生成SKRoot(Lite) ARM64 Linux内核ROOT提权代码 V12" << std::endl << std::endl;
157+
158+ #ifdef _DEBUG
159+ #else
160+ if (argc < 1 ) {
161+ std::cout << " 无输入文件" << std::endl;
162+ system (" pause" );
163+ return 0 ;
164+ }
165+ #endif
166+
167+ #ifdef _DEBUG
168+ #else
169+ const char * file_path = argv[0 ];
170+ #endif
171+ std::cout << file_path << std::endl << std::endl;
172+ if (!check_file_path (file_path)) {
173+ std::cout << " Please enter the correct Linux kernel binary file path. " << std::endl;
174+ std::cout << " For example, if it is boot.img, you need to first decompress boot.img and then extract the kernel file inside." << std::endl;
175+ system (" pause" );
176+ return 0 ;
177+ }
178+
179+ std::vector<char > file_buf = read_file_buf (file_path);
180+ if (!file_buf.size ()) {
181+ std::cout << " Fail to open file:" << file_path << std::endl;
182+ system (" pause" );
183+ return 0 ;
184+ }
185+
186+ SymbolAnalyze symbol_analyze (file_buf);
187+ if (!symbol_analyze.analyze_kernel_symbol ()) {
188+ std::cout << " Failed to analyze kernel symbols" << std::endl;
189+ system (" pause" );
190+ return 0 ;
191+ }
192+ KernelSymbolOffset sym = symbol_analyze.get_symbol_offset ();
193+ uint64_t anchor_off = sym.die .offset ;
194+
195+ PatchKernelOffset off;
196+ if (!parser_cred_offset (file_buf, sym.sys_getuid , off.cred_offset )) {
197+ std::cout << " Failed to parse cred offset" << std::endl;
198+ system (" pause" );
199+ return 0 ;
200+ }
201+
202+ if (!parse_cred_uid_offset (file_buf, sym.sys_getuid , off.cred_offset , off.cred_uid_offset )) {
203+ std::cout << " Failed to parse cred uid offset" << std::endl;
204+ system (" pause" );
205+ return 0 ;
206+ }
207+ std::cout << " cred uid offset:" << off.cred_uid_offset << std::endl;
208+
209+ if (!parser_seccomp_offset (file_buf, sym.prctl_get_seccomp , off.seccomp_offset )) {
210+ std::cout << " Failed to parse seccomp offset" << std::endl;
211+ system (" pause" );
212+ return 0 ;
213+ }
214+ std::cout << " cred offset:" << off.cred_offset << std::endl;
215+ std::cout << " seccomp offset:" << off.seccomp_offset << std::endl;
216+
217+ parser_huawei_kti_addr (file_buf, sym.kti_randomize_init , off.huawei_kti_addr );
218+ if (off.huawei_kti_addr ) std::cout << " kti addr:" << off.huawei_kti_addr << std::endl;
219+
220+ std::vector<patch_bytes_data> vec_patch_bytes_data;
221+ cfi_bypass (file_buf, sym, vec_patch_bytes_data);
222+ huawei_bypass (file_buf, sym, vec_patch_bytes_data);
223+
224+ size_t first_hook_start = 0 ;
225+ PatchKernelResult pr = patch_kernel_handler (file_buf, off, sym, vec_patch_bytes_data);
226+ if (!pr.patched ) {
227+ std::cout << " Failed to find hook start addr" << std::endl;
228+ system (" pause" );
229+ return 0 ;
230+ }
231+
232+ std::string str_root_key;
233+ size_t is_need_create_root_key = 0 ;
234+ std::cout << std::endl << " 请选择是否需要自动随机生成ROOT密匙(1需要;2不需要):" << std::endl;
235+ std::cin >> std::dec >> is_need_create_root_key;
236+ if (is_need_create_root_key == 1 ) {
237+ str_root_key = generate_random_str (ROOT_KEY_LEN);
238+ } else {
239+ std::cout << " 请输入ROOT密匙(48个字符的字符串,包含大小写和数字):" << std::endl;
240+ std::cin >> str_root_key;
241+ std::cout << std::endl;
242+ }
243+ std::string write_key = str_root_key;
244+ write_key.erase (write_key.size () - 1 );
245+ patch_data (file_buf, pr.root_key_start , (void *)write_key.c_str (), write_key.length () + 1 , vec_patch_bytes_data);
246+
247+ std::cout << " #获取ROOT权限的密匙(Key): " << str_root_key.c_str () << std::endl << std::endl;
248+
249+ size_t need_write_modify_in_file = 0 ;
250+ std::cout << " #是否需要立即写入修改到文件?(1需要;2不需要):" << std::endl;
251+ std::cin >> need_write_modify_in_file;
252+ if (need_write_modify_in_file == 1 ) {
253+ std::cout << " #正在写入,请稍后..." << std::endl;
254+ write_all_patch (file_path, vec_patch_bytes_data);
255+ }
256+ system (" pause" );
257+ return 0 ;
258+ }
0 commit comments