In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Network Security >
Share
Shulou(Shulou.com)05/31 Report--
This article mainly introduces "find out what the function using Kernel Task is". In the daily operation, I believe that many people have doubts about finding out what the function using Kernel Task is. The editor has consulted all kinds of information and sorted out simple and easy-to-use operation methods. I hope it will be helpful to answer the doubt of "find out what the function using Kernel Task is". Next, please follow the editor to study!
Positioning Kernel Task
To get kernel information, we need to navigate to the address of Kernel Task and read through tfp0's kread. To locate the Kernel Task, the key is to find the code that gets the Kernel Task, then try to locate the code from memory, and then analyze the instruction to figure out the file offset of the variable.
Find functions that use Kernel Task
The following code that accesses Kernel Task can be found in xnu-4903.221.2:
Intproc_apply_resource_actions (void * bsdinfo, _ _ unused int type, int action) {proc_t p = (proc_t) bsdinfo; switch (action) {case PROC_POLICY_RSRCACT_THROTTLE: / * no need to do anything * / break; case PROC_POLICY_RSRCACT_SUSPEND: task_suspend (p-> task); break Case PROC_POLICY_RSRCACT_TERMINATE: psignal (p, SIGKILL); break; case PROC_POLICY_RSRCACT_NOTIFY_KQ: / * not implemented * / break; case PROC_POLICY_RSRCACT_NOTIFY_EXC: panic ("shouldn't be applying exception notification to process!"); break;} return (0);}
Here is a string "shouldn't be applying exception notification to process!" It can be used for auxiliary positioning, which will be stored in the _ _ TEXT,__cstring segment after compilation. The string address can be found by searching the _ _ TEXT,__cstring segment in memory, which we call location_str.
Navigate to the String XREF in the function
Since ARM addressing often requires two instructions to complete, we need to statically analyze the code snippet in order to locate the code that uses location_str. When we find that the value in the register is equal to location_str, we find a XREF. By this means, we can locate the statement panic ("shouldn't be applying exception notification to process!") in memory. The corresponding instruction address.
Go back to Kernel Task XREF.
The fastest way to locate Kernel Task is to go back to task_suspend (p-> task). When task_suspend accesses p-> task for the first time, it must address the task. We can find the file offset of task from the addressing instruction, and add the base address of the kernel in memory to get the address of Kernel Task.
Kern_return_ttask_suspend (task_t task) {kern_return_t kr; mach_port_t port, send, old_notify; mach_port_name_t name; if (task = = TASK_NULL | | task = = kernel_task) return (KERN_INVALID_ARGUMENT); task_lock (task); / /.
From the above analysis, we can see that the crux of the problem lies in the location of XREF. Below, we will analyze a String Based XREF location algorithm to solve the above problems.
Load Kernelcache in memory
According to the Kernelcache definition given by iPhone Wiki [1]:
The kernelcache is basically the kernel itself as well as all of its extensions (AppleImage3NORAccess, IOAESAccelerator, IOPKEAccelerator, etc.) Into one file, then packed/encrypted in an IMG3 (iPhone OS 2.0 and above) or 8900 (iPhone OS 1.0 through 1.1.4) container.
Kernelcache means that kernel and its extensions are packaged in a file and stored in IMG3 format (iOS 2 or above).
In the previous article, we introduced the sandboxie escape method based on tfp0. Through sandboxie escape, we can read the kernelcache from / System/Library/Caches/com.apple.kernelcaches/kernelcache, which is both the mirror loaded by the current system.
Readers can open the jailbreak.m file of Undecimus, search for "Initializing patchfinder" to locate the loading code of kernelcache, the loading method is similar to ordinary Mach-O files, it is also to read Mach Header and Load Commands first, and then record the offset segment by segment, the specific code is in the init_kernel function.
Instead of repeating the loading process here, just a few key global variables are pointed out:
Cstring_base and cstring_size are the virtual address and length of the _ _ TEXT,__cstring segment
Xnucore_base and xnucore_size are _ _ TEXT,__TEXT_EXEC segments, that is, the virtual address and length of the code snippet
Kerndumpbase is the smallest virtual address of all segments, that is, the virtual base address loaded by kernelcache. In ordinary Mach-O files, this value is usually the virtual address of _ _ PAGEZERO segment 0x100000000, but in the kernel it seems to be the virtual address 0xFFFFFFF007004000 of _ _ TEXT segment.
Kernel is a complete mapping of kernelcache in user space, that is, a fully loaded kernel image.
Find String Based XREF
Include a find_strref function in Undecimus to locate the XREF of the string:
Addr_tfind_strref (const char * string, int n, enum string_bases string_base, bool full_match, bool ppl_base) {uint8_t * str; addr_t base; addr_t size; enum text_bases text_base = ppl_base?text_ppl_base:text_xnucore_base; switch (string_base) {case string_base_const: base = const_base; size = const_size Break; case string_base_data: base = data_base; size = data_size; break; case string_base_oslstring: base = oslstring_base; size = oslstring_size; break; case string_base_pstring: base = pstring_base; size = pstring_size Text_base = text_prelink_base; break; case string_base_cstring: default: base = cstring_base; size = cstring_size; break;} addr_t off = 0 While ((str = boyermoore_horspool_memmem (kernel + base + off, size-off, (uint8_t *) string, strlen (string) {/ / Only match the beginning of strings / / first_string | |\ 0this_string if ((str = = kernel + base | | * (str-1) = ='\ 0') & (! full_match | | strcmp ((char *) str, string) = = 0) break / / find after str off = str-(kernel + base) + 1;} if (! str) {return 0;} / find xref return find_reference (str-kernel + kerndumpbase, n, text_base);}
It requires passing the string string, the sequence number of the reference n, the base segment string_base, whether it matches the full_match exactly, and whether it is located in the _ _ PPLTEXT segment. For scenarios looking for Kernel Task, our input parameters are as follows:
Addr_t str = find_strref ("\" shouldn't be applying exception notification ", 2, string_base_cstring, false, false)
That is, based on _ _ TEXT,__cstring, an exact match is not required to find the address where the second cross-reference is located.
Location string address
The positioning logic of the string address is in the boyermoore_horspool_memmem function:
Static unsigned char* boyermoore_horspool_memmem (const unsigned char* haystack, size_t hlen, const unsigned char* needle, size_t nlen) {size_t last, scan = 0; size_t bad_char_ skip [Uchar _ MAX + 1] / * Officially called: * bad character shift * / / * Sanity checks on the parameters * / if (nlen add x8, x8, str@PAGEOFF bl _ panic * / addr_t str = find_strref ("\" shouldn't be applying exception notification ", 2, string_base_cstring, false, false); if (! str) return 0; str-= kerndumpbase / / find bl _ task_suspend addr_t call = step64_back (kernel, str, 0x10, INSN_CALL); if (! call) return 0; addr_t task_suspend = follow_call64 (kernel, call); if (! task_suspend) return 0; addr_t adrp = step64 (kernel, task_suspend, 204, INSN_ADRP); if (! adrp) return 0; addr_t kern_task = calc64 (kernel, adrp, adrp + 0x8, 8) If (! kern_task) return 0; return kern_task + kerndumpbase;}
The whole process is mainly divided into three steps:
Backtrack to find the call point of bl _ task_suspend and solve the address of the task_suspend function
Search backward for the first adrp instruction from the task_suspend function, which is the addressing of Kernel Task
Extract the Kernel Task address from the addressing instruction.
Let's go back to the snippet of the proc_apply_resource_actions function:
Switch (action) {case PROC_POLICY_RSRCACT_THROTTLE: / * no need to do anything * / break; case PROC_POLICY_RSRCACT_SUSPEND: task_suspend (p-> task); break; case PROC_POLICY_RSRCACT_TERMINATE: psignal (p, SIGKILL); break; case PROC_POLICY_RSRCACT_NOTIFY_KQ: / * not implemented * / break Case PROC_POLICY_RSRCACT_NOTIFY_EXC: panic ("shouldn't be applying exception notification to process!"); break;}
The machine code may not be generated in the order of case when compiling, so we need to find the actual representation in kernelcache according to str XREF. A simple way is to hit a breakpoint after find_strref ("\" shouldn't be applying exception notification ", 2, string_base_cstring, false, false) to get the file offset of str XREF, and then use binary analysis tools to disassemble this part of kernelcache.
Breakpoint debugging shows that str XREF is located in 0x0000000000f9f084, which should be an add instruction:
/ * * adrp x8, str@PAGE str-- > add x8, x8, str@PAGEOFF bl _ panic * /
When you open it in the Mach-O viewer, you can see that 0x0000000000f9f084 is indeed an add instruction:
There are two ways to locate task_suspend (p-> task). One is that p-> task is an offset-based structure member addressing with obvious characteristics, and the second is to look at the parameter preparation before the function call. There is an offset addressing of + 16 at 0xf9f074, which is obviously a calculation of the p-> task address, so there is a call to task_suspend (p-> task) at 0xf9f078.
So you can trace back three instructions from the add instruction, and when you find the CALL instruction, you can find the address of the task_suspend:
/ / find bl _ task_suspendaddr_t call = step64_back (kernel, str, 0x10, INSN_CALL); if (! call) return 0 return addrystt task_suspend = follow_call64 (kernel, call); if (! task_suspend) return 0
Then we search backward for the first adrp instruction from the starting address of the task_suspend function to find the adrp statement for Kernel Task, and statically analyze adrp & add to calculate the address of Kernel Task:
Addr_t adrp = step64 (kernel, task_suspend, 20: 4, INSN_ADRP); if (! adrp) return 0 * * addrystt kern_task = calc64 (kernel, adrp, adrp + 0x8, 8); if (! kern_task) return 0
Note that what we get here is still fileoff, and we need to add kerndumpbase to get the virtual address:
Return kern_task + kerndumpbase
It is important to note that if you want to read Kernel Task in the kernel, you need to add kernel_slide to this address.
At this point, the study of "finding what the function that uses Kernel Task is" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.