├── .gitmodules ├── README.md ├── analyze_kernel.cpp ├── analyze_kernel.h ├── find_load_module.cpp └── find_load_module.exe /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "SKRoot-linuxKernelRoot"] 2 | path = SKRoot-linuxKernelRoot 3 | url = https://github.com/abcz316/SKRoot-linuxKernelRoot 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FindLoadModule: 无源码 Linux 内核函数定位器 2 | 3 | **FindLoadModule** 是一个强大的工具,设计用于在无 Linux 内核源代码的环境中找到内核函数 `load_module` 的具体位置。 4 | 5 | ## 目标 6 | 本工具的目标是让开发人员在无源码环境下,能够顺利去除驱动加载的验证,从而让驱动在无源码的内核情况下正常运行。 7 | 8 | ## 兼容性 9 | FindLoadModule 可以广泛应用于所有 Linux ARM64 内核。无论使用何种版本的 ARM64 内核,都可以依赖 FindLoadModule 工具来定位 `load_module` 函数。 10 | 11 | ## 使用方法 12 | 1. 首先,将FindLoadModule编译出来。 13 | 2. 然后,将Android内核的boot.img文件解包,得到image镜像文件。 14 | 3. 如果镜像文件是压缩的(例如,image.gz),你需要进一步解压,得到实际的内核二进制文件。 15 | 4. 将这个内核二进制文件拖入此工具,你将直接得到`load_module`的位置。 16 | 5. 使用IDA跳转至该位置,浏览上下文。你将看到非常熟悉的`load_module`,进行适当的修改,即可去除所有驱动加载的验证。 17 | -------------------------------------------------------------------------------- /analyze_kernel.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "analyze_kernel.h" 3 | 4 | AnalyzeKernel::AnalyzeKernel(const std::vector& file_buf) : m_file_buf(file_buf), m_kernel_sym_parser(file_buf) 5 | { 6 | } 7 | 8 | AnalyzeKernel::~AnalyzeKernel() 9 | { 10 | } 11 | 12 | bool AnalyzeKernel::analyze_kernel_symbol() { 13 | if (!m_kernel_sym_parser.init_kallsyms_lookup_name()) { 14 | std::cout << "Failed to initialize kallsyms lookup name" << std::endl; 15 | return false; 16 | } 17 | if (!find_symbol_offset()) { 18 | std::cout << "Failed to find symbol offset" << std::endl; 19 | return false; 20 | } 21 | return true; 22 | } 23 | 24 | KernelSymbolOffset AnalyzeKernel::get_symbol_offset() { 25 | return m_kernel_sym_offset; 26 | } 27 | 28 | bool AnalyzeKernel::find_symbol_offset() { 29 | m_kernel_sym_offset._text_offset = m_kernel_sym_parser.kallsyms_lookup_name("_text"); 30 | m_kernel_sym_offset._stext_offset = m_kernel_sym_parser.kallsyms_lookup_name("_stext"); 31 | m_kernel_sym_offset.load_module_offset = m_kernel_sym_parser.kallsyms_lookup_name("load_module"); 32 | if (m_kernel_sym_offset.load_module_offset == 0) { 33 | m_kernel_sym_offset.load_module_offset = m_kernel_sym_parser.kallsyms_lookup_name("load_module", true); 34 | } 35 | return m_kernel_sym_offset.load_module_offset; 36 | } -------------------------------------------------------------------------------- /analyze_kernel.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "SKRoot-linuxKernelRoot\patch_kernel_root\kernel_symbol_parser.h" 3 | #include 4 | #include 5 | 6 | struct KernelSymbolOffset { 7 | size_t _text_offset = 0; 8 | size_t _stext_offset = 0; 9 | size_t load_module_offset = 0; 10 | }; 11 | 12 | class AnalyzeKernel 13 | { 14 | public: 15 | AnalyzeKernel(const std::vector & file_buf); 16 | ~AnalyzeKernel(); 17 | 18 | public: 19 | bool analyze_kernel_symbol(); 20 | KernelSymbolOffset get_symbol_offset(); 21 | private: 22 | bool find_symbol_offset(); 23 | const std::vector& m_file_buf; 24 | KernelSymbolParser m_kernel_sym_parser; 25 | KernelSymbolOffset m_kernel_sym_offset; 26 | }; -------------------------------------------------------------------------------- /find_load_module.cpp: -------------------------------------------------------------------------------- 1 | // patch_kernel_root.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 2 | // 3 | 4 | #include "SKRoot-linuxKernelRoot\patch_kernel_root\ase_func.h" 5 | #include "analyze_kernel.h" 6 | 7 | bool check_file_path(const char* file_path) { 8 | size_t len = strlen(file_path); 9 | if (len > 4 && strcmp(file_path + len - 4, ".img") == 0) { 10 | return false; 11 | } 12 | return true; 13 | } 14 | 15 | int main(int argc, char* argv[]) { 16 | ++argv; 17 | --argc; 18 | 19 | std::cout << "本工具用于查找在aarch64 Linux内核文件中load_module的位置" << std::endl; 20 | 21 | if (argc < 1) { 22 | std::cout << "无输入文件" << std::endl; 23 | system("pause"); 24 | return 0; 25 | } 26 | const char* file_path = argv[0]; 27 | 28 | if (!check_file_path(file_path)) { 29 | std::cout << "Please enter the correct Linux kernel binary file path. " << std::endl; 30 | 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; 31 | system("pause"); 32 | return 0; 33 | } 34 | 35 | std::vector file_buf = read_file_buf(file_path); 36 | if (!file_buf.size()) { 37 | std::cout << "Fail to open file:" << file_path << std::endl; 38 | system("pause"); 39 | return 0; 40 | } 41 | 42 | AnalyzeKernel analyze_kernel(file_buf); 43 | if (!analyze_kernel.analyze_kernel_symbol()) { 44 | std::cout << "Failed to analyze kernel symbols" << std::endl; 45 | system("pause"); 46 | return 0; 47 | } 48 | KernelSymbolOffset sym = analyze_kernel.get_symbol_offset(); 49 | 50 | std::cout << "_text: 0x" << sym._text_offset << std::endl; 51 | std::cout << "_stext: 0x" << sym._stext_offset << std::endl; 52 | std::cout << "load_module: 0x" << sym.load_module_offset << std::endl; 53 | system("pause"); 54 | return 0; 55 | } -------------------------------------------------------------------------------- /find_load_module.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abcz316/find_load_module/b9d7e1349596a09021a6084ee7f000e04629909c/find_load_module.exe --------------------------------------------------------------------------------