├── LICENSE ├── README.md └── android_kernel_kallsyms_import.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 dayzerosec 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # IDA Android Kernel Symbolizer 2 | IDA Android Kernel Symbolizer is an IDA Python script that allows you to import symbols from /proc/kallsyms output into an unlabelled Android kernel, typically extracted from a boot image. 3 | 4 | # How does it work? 5 | First, the script prompts you to open a file containing the contents of /proc/kallsyms output. The file should contain text that looks something like this: 6 | 7 | ``` 8 | ffffff9918280000 t _head 9 | ffffff9918280000 T _text 10 | ffffff9918280040 t pe_header 11 | ffffff9918280044 t coff_header 12 | ffffff9918280058 t optional_header 13 | ffffff9918280070 t extra_header_fields 14 | [...] 15 | ``` 16 | 17 | After the file is opened, the script parses the symbol entries and utilizes the `_text` symbol (aka. the kernel .text base address) to convert the kASLR'd virtual addresses into slides, and adds them into lookup tables. 18 | 19 | Finally, it runs through the function lookup table it just constructed to mark the address as code and create a subroutine in IDA if it does not already exists and labels it. It then does the same for the data lookup table, however it only labels the address and does not mark it as code or create a subroutine there. 20 | 21 | # Notes 22 | - Running this script is generally fairly fast (under 20 seconds), however it will trigger IDA's Auto-Analysis engine to kick in, and this can take up to 5 minutes from our tests. During this time, IDA might be sluggish. 23 | 24 | # License 25 | This script is licensed under the [MIT license](LICENSE). 26 | -------------------------------------------------------------------------------- /android_kernel_kallsyms_import.py: -------------------------------------------------------------------------------- 1 | # 2 | # This script will allow a user to use a /proc/kallsyms output file to import symbols into IDA for Android kernels. 3 | # 4 | 5 | from idautils import * 6 | from idaapi import * 7 | import time 8 | 9 | ADDRESS = 0 10 | TYPE = 1 11 | NAME = 2 12 | 13 | # Prompt the user for the kallsyms output file and open it 14 | filePath = idaapi.ask_file(0, 'kallsyms.txt|*.txt|All files (*.*)|*.*', 'Select a file containing kallsyms output') 15 | file = open(filePath, 'r') 16 | syms = file.readlines() 17 | 18 | functionTable = {} 19 | dataTable = {} 20 | kernelBase = '0' 21 | 22 | # This script can take quite a while to run - we should warn the user that IDA might be sluggish for a while. 23 | idaapi.warning('Note that after the script finishes, IDA will re-run it\'s analyzer on the ELF. Give it about 5 minutes.') 24 | 25 | # convertAddressToSlide takes a given address and converts it to a slide based on the kernel base parsed 26 | # from _text. 27 | def convertAddressToSlide(addr): 28 | return int(addr, 16) - int(kernelBase, 16) 29 | 30 | startTime = time.clock() 31 | 32 | # Iterate through each symbol 33 | for sym in syms: 34 | # Symbol entries follow the following format 35 | sym = sym.replace('\n', '') 36 | symbol = sym.split(' ') 37 | 38 | symAddress = symbol[ADDRESS] 39 | symName = symbol[NAME] 40 | symSlide = convertAddressToSlide(symAddress) 41 | 42 | # Ignore _head because it's not a function or global 43 | if symbol[NAME] == '_head': 44 | continue 45 | 46 | # IDA does not allow names with a "byte_" prefix, and a few entries do have these names, so we'll 47 | # make special exceptions and not port these names. 48 | if symbol[NAME][0:5] == 'byte_': 49 | continue 50 | 51 | # The kernel base can be found via the _text symbol 52 | if symbol[TYPE] == 'T' and symbol[NAME] == '_text': 53 | kernelBase = symbol[ADDRESS] 54 | print 'Found kernel base @ 0x' + symbol[ADDRESS] 55 | 56 | # 57 | # We're going to construct look-up tables for functions and data. The reason we're doing this instead 58 | # of just labelling here and now is some addresses have more than one symbol entry, and in the future 59 | # we may want to add a comment denoting the other names the entity goes by. 60 | # 61 | 62 | # Parse function entries 63 | if symbol[TYPE].lower() == 't': 64 | # Create a list if a list does not already exist for this address 65 | if symSlide not in functionTable: 66 | functionTable[symSlide] = [] 67 | 68 | # Add name(s) to the address entry in the function table 69 | functionTable[symSlide].append(symName) 70 | 71 | # Parse data entries 72 | elif symbol[TYPE].lower() == 'd': 73 | # Create a list if a list does not already exist for this address 74 | if symSlide not in dataTable: 75 | dataTable[symSlide] = [] 76 | 77 | # Add name(s) to the address entry in the data table 78 | dataTable[symSlide].append(symName) 79 | 80 | 81 | for vaddr, funcNames in functionTable.items(): 82 | # Mark virtual address as code, and create a function 83 | idaapi.auto_make_proc(vaddr) 84 | 85 | # Label in IDA 86 | idaapi.set_name(vaddr, funcNames[0]) 87 | 88 | for vaddr, dataNames in dataTable.items(): 89 | # Label in IDA 90 | idaapi.set_name(vaddr, dataNames[0]) 91 | 92 | endTime = time.clock() 93 | 94 | print 'Finished in ' + str(endTime - startTime) + ' seconds.' 95 | --------------------------------------------------------------------------------