-
-
Save anonymous/008aaaa48262a3dc34eac206d2a8c0e5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
# @Date : 2014-08-27 21:49:19 | |
# @Author : nforest@k33nteam.org | |
import os | |
import re | |
import sys | |
import time | |
import struct | |
import r2pipe | |
import json | |
#//////////////////////////////////////////////////////////////////////////////////////////// | |
kallsyms = { | |
'arch' :32, | |
'_start' :0, | |
'numsyms' :0, | |
'address' :[], | |
'type' :[], | |
'name' :[], | |
'address_table' : 0, | |
'name_table' : 0, | |
'type_table' : 0, | |
'token_table' : 0, | |
'table_index_table' : 0, | |
} | |
def INT(offset, vmlinux): | |
bytes = kallsyms['arch'] / 8 | |
s = vmlinux[offset:offset+bytes] | |
f = 'I' if bytes==4 else 'Q' | |
(num,) = struct.unpack(f, s) | |
return num | |
def INT32(offset, vmlinux): | |
s = vmlinux[offset:offset+4] | |
(num,) = struct.unpack('I', s) | |
return num | |
def INT64(offset, vmlinux): | |
s = vmlinux[offset:offset+8] | |
(num,) = struct.unpack('Q', s) | |
return num | |
def SHORT(offset, vmlinux): | |
s = vmlinux[offset:offset+2] | |
(num,) = struct.unpack('H', s) | |
return num | |
def STRIPZERO(offset, vmlinux, step=4): | |
NOTZERO = INT32 if step==4 else INT | |
for i in xrange(offset,len(vmlinux),step): | |
if NOTZERO(i, vmlinux): | |
return i | |
#////////////////////// | |
def do_token_index_table(kallsyms , offset, vmlinux): | |
kallsyms['token_index_table'] = offset | |
print '[+]kallsyms_token_index_table = ', hex(offset) | |
def do_token_table(kallsyms, offset, vmlinux): | |
kallsyms['token_table'] = offset | |
print '[+]kallsyms_token_table = ', hex(offset) | |
for i in xrange(offset,len(vmlinux)): | |
if SHORT(i,vmlinux) == 0: | |
break | |
for i in xrange(i, len(vmlinux)): | |
if ord(vmlinux[i]): | |
break | |
offset = i-2 | |
do_token_index_table(kallsyms , offset, vmlinux) | |
def do_marker_table(kallsyms, offset, vmlinux): | |
kallsyms['marker_table'] = offset | |
print '[+]kallsyms_marker_table = ', hex(offset) | |
offset += (((kallsyms['numsyms']-1)>>8)+1)*(kallsyms['arch']/8) | |
offset = STRIPZERO(offset, vmlinux) | |
do_token_table(kallsyms, offset, vmlinux) | |
def do_type_table(kallsyms, offset, vmlinux): | |
flag = True | |
for i in xrange(offset,offset+256*4,4): | |
if INT(i, vmlinux) & ~0x20202020 != 0x54545454: | |
flag = False | |
break | |
if flag: | |
kallsyms['type_table'] = offset | |
while INT(offset, vmlinux): | |
offset += (kallsyms['arch']/8) | |
offset = STRIPZERO(offset, vmlinux) | |
else: | |
kallsyms['type_table'] = 0 | |
print '[+]kallsyms_type_table = ', hex(kallsyms['type_table']) | |
offset -= 4 | |
do_marker_table(kallsyms, offset, vmlinux) | |
def do_name_table(kallsyms, offset, vmlinux): | |
kallsyms['name_table'] = offset | |
print '[+]kallsyms_name_table = ', hex(offset) | |
for i in xrange(kallsyms['numsyms']): | |
length = ord(vmlinux[offset]) | |
offset += length+1 | |
while offset%4 != 0: | |
offset += 1 | |
offset = STRIPZERO(offset, vmlinux) | |
do_type_table(kallsyms, offset, vmlinux) | |
# decompress name and type | |
name_offset = 0 | |
for i in xrange(kallsyms['numsyms']): | |
offset = kallsyms['name_table']+name_offset | |
length = ord(vmlinux[offset]) | |
offset += 1 | |
name_offset += length+1 | |
name = '' | |
while length: | |
token_index_table_offset = ord(vmlinux[offset]) | |
xoffset = kallsyms['token_index_table']+token_index_table_offset*2 | |
token_table_offset = SHORT(xoffset, vmlinux) | |
strptr = kallsyms['token_table']+token_table_offset | |
while ord(vmlinux[strptr]): | |
name += '%c' % ord(vmlinux[strptr]) | |
strptr += 1 | |
length -= 1 | |
offset += 1 | |
if kallsyms['type_table']: | |
kallsyms['type'].append('X') | |
kallsyms['name'].append(name) | |
else: | |
kallsyms['type'].append(name[0]) | |
kallsyms['name'].append(name[1:]) | |
def do_guess_start_address(kallsyms, vmlinux): | |
_startaddr_from_xstext = 0 | |
_startaddr_from_banner = 0 | |
_startaddr_from_processor = 0 | |
for i in xrange(kallsyms['numsyms']): | |
if kallsyms['name'][i] in ['_text', 'stext', '_stext', '_sinittext', '__init_begin']: | |
if hex(kallsyms['address'][i]): | |
if _startaddr_from_xstext==0 or kallsyms['address'][i]<_startaddr_from_xstext: | |
_startaddr_from_xstext = kallsyms['address'][i] | |
elif kallsyms['name'][i] == 'linux_banner': | |
linux_banner_addr = kallsyms['address'][i] | |
linux_banner_fileoffset = vmlinux.find('Linux version ') | |
if linux_banner_fileoffset: | |
_startaddr_from_banner = linux_banner_addr - linux_banner_fileoffset | |
elif kallsyms['name'][i] == '__lookup_processor_type_data': | |
lookup_processor_addr = kallsyms['address'][i] | |
step = kallsyms['arch'] / 8 | |
if kallsyms['arch'] == 32: | |
addr_base = 0xC0008000 | |
else: | |
addr_base = 0xffffffc000080000 | |
for i in xrange(0,0x100000,step): | |
_startaddr_from_processor = addr_base + i | |
fileoffset = lookup_processor_addr - _startaddr_from_processor | |
if lookup_processor_addr == INT(fileoffset, vmlinux): | |
break | |
if _startaddr_from_processor == _startaddr_from_processor+0x100000: | |
_startaddr_from_processor = 0 | |
if _startaddr_from_banner: | |
kallsyms['_start'] = _startaddr_from_banner | |
elif _startaddr_from_processor: | |
kallsyms['_start'] = _startaddr_from_processor | |
elif _startaddr_from_xstext: | |
kallsyms['_start'] = _startaddr_from_xstext | |
if kallsyms['arch']==64 and _startaddr_from_banner!=_startaddr_from_xstext: | |
kallsyms['_start'] = 0xffffffc000000000 + INT(8, vmlinux) | |
print '[+]kallsyms_guess_start_addresses = ', hex(0xffffffc000000000 + INT(8, vmlinux)) if kallsyms['arch']==64 else '', hex(_startaddr_from_xstext), hex(_startaddr_from_banner), hex(_startaddr_from_processor) | |
return kallsyms['_start'] | |
def do_address_table(kallsyms, offset, vmlinux): | |
step = kallsyms['arch'] / 8 | |
if kallsyms['arch'] == 32: | |
addr_base = 0xC0000000 | |
else: | |
addr_base = 0xffffffc000000000 | |
kallsyms['address'] = [] | |
for i in xrange(offset, len(vmlinux), step): | |
addr = INT(i, vmlinux) | |
if addr < addr_base: | |
return (i-offset)/step | |
else: | |
kallsyms['address'].append(addr) | |
return 0 | |
def do_kallsyms(kallsyms, vmlinux): | |
step = kallsyms['arch'] / 8 | |
offset = 0 | |
vmlen = len(vmlinux) | |
while offset+step < vmlen: | |
num = do_address_table(kallsyms, offset, vmlinux) | |
if num > 40000: | |
kallsyms['numsyms'] = num | |
break | |
else: | |
offset += (num+1)*step | |
if kallsyms['numsyms'] == 0: | |
print '[!]lookup_address_table error...' | |
return | |
kallsyms['address_table'] = offset | |
print '[+]kallsyms_address_table = ', hex(offset) | |
offset += kallsyms['numsyms']*step | |
offset = STRIPZERO(offset, vmlinux, step) | |
num = INT(offset, vmlinux) | |
offset += step | |
print '[+]kallsyms_num = ', kallsyms['numsyms'], num | |
if abs(num-kallsyms['numsyms']) > 128: | |
kallsyms['numsyms'] = 0 | |
print ' [!]not equal, maybe error...' | |
return | |
if num > kallsyms['numsyms']: | |
for i in xrange(kallsyms['numsyms'],num): | |
kallsyms['address'].insert(0,0) | |
kallsyms['numsyms'] = num | |
offset = STRIPZERO(offset, vmlinux) | |
do_name_table(kallsyms, offset, vmlinux) | |
do_guess_start_address(kallsyms, vmlinux) | |
return | |
def do_get_arch(kallsyms, vmlinux): | |
def fuzzy_arm64(vmlinux): | |
step = 8 | |
offset = 0 | |
vmlen = len(vmlinux) - len(vmlinux)%8 | |
addr_base = 0xffffffc000000000 | |
while offset+step < vmlen: | |
for i in xrange(offset, vmlen, step): | |
if INT64(i, vmlinux) < addr_base: | |
addrnum = (i-offset)/step | |
if addrnum > 10000: | |
return True | |
else: | |
offset = i+step | |
return False | |
if re.search('ARMd', vmlinux[:0x200]): | |
kallsyms['arch'] = 64 | |
elif fuzzy_arm64(vmlinux): | |
kallsyms['arch'] = 64 | |
else: | |
kallsyms['arch'] = 32 | |
print '[+]kallsyms_arch = ', kallsyms['arch'] | |
#///////////// | |
def print_kallsyms(kallsyms, vmlinux): | |
buf = '\n'.join( '%x %c %s'%(kallsyms['address'][i],kallsyms['type'][i],kallsyms['name'][i]) for i in xrange(kallsyms['numsyms']) ) | |
open('kallsyms','w').write(buf) | |
#//////////////////////////////////////////////////////////////////////////////////////////// | |
def accept_file(li, n): | |
""" | |
Check if the file is of supported format | |
@param li: a file-like object which can be used to access the input data | |
@param n : format number. The function will be called with incrementing | |
number until it returns zero | |
@return: 0 - no more supported formats | |
string "name" - format name to display in the chooser dialog | |
dictionary { 'format': "name", 'options': integer } | |
options: should be 1, possibly ORed with ACCEPT_FIRST (0x8000) | |
to indicate preferred format | |
""" | |
# we support only one format per file | |
if n > 0: | |
return 0 | |
# magic = li.read(8) | |
# if magic != 'ANDROID!': | |
# return 0 | |
return "Android OS Kernel(ARM)" | |
def load_file(): | |
""" | |
Load the file into database | |
@param li: a file-like object which can be used to access the input data | |
@param neflags: options selected by the user, see loader.hpp | |
@return: 0-failure, 1-ok | |
""" | |
r2p = r2pipe.open() | |
info = r2p.cmdj("ij") | |
with open(info["core"]["file"], 'rb') as f: | |
vmlinux = f.read() | |
do_get_arch(kallsyms, vmlinux) | |
do_kallsyms(kallsyms, vmlinux) | |
# print_kallsyms(kallsyms, vmlinux) | |
if kallsyms['numsyms'] == 0: | |
print '[!]get kallsyms error...' | |
return 0 | |
print '[+]kallsyms_start_address = ', hex(kallsyms['_start']) | |
r2p.cmd("e asm.arch = arm") | |
siol_map = r2p.cmdj("omj")[0]["map"] | |
set_baddr = "omr " + str(siol_map) + " " + str(kallsyms["_start"]) | |
r2p.cmd(set_baddr) | |
seg = "S 0 " + str(kallsyms["_start"]) + " " + str(len(vmlinux)) + " .text rx" | |
r2p.cmd(seg) | |
#li.file2base(0, kallsyms['_start'], kallsyms['_start']+li.size(), True) | |
#s = idaapi.segment_t() | |
#s.bitness = kallsyms['arch'] / 32 | |
#s.startEA = kallsyms['_start'] | |
#s.endEA = kallsyms['_start']+li.size() | |
#idaapi.add_segm_ex(s,".text","CODE",ADDSEG_OR_DIE) | |
r2p.cmd("fs symbols") | |
for i in xrange(kallsyms['numsyms']): | |
if kallsyms['type'][i] in ['t','T']: | |
cmd = "f sym." + kallsyms["name"][i] + " @ " + str(kallsyms["address"][i]) | |
r2p.cmd(cmd) | |
#idaapi.add_entry(kallsyms['address'][i], kallsyms['address'][i], kallsyms['name'][i], 1) | |
else: | |
cmd = "f sym." + kallsyms["name"][i] + " @ " + str(kallsyms["address"][i]) | |
r2p.cmd(cmd) | |
#idaapi.add_entry(kallsyms['address'][i], kallsyms['address'][i], kallsyms['name'][i], 0) | |
r2p.cmd("e anal.strings = true") | |
r2p.cmd("s " + str(kallsyms["_start"])) | |
print "Android vmlinux loaded..." | |
return 1 | |
#//////////////////////////////////////////////////////////////////////////////////////////// | |
load_file() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment