├── .gitignore ├── Makefile ├── README.md ├── ida-mbn-sbl-loader.cpp ├── ida-mbn-sbl-loader.py └── mbn.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Mac OS 2 | 3 | export __MAC__=1 4 | SWITCH64=-D__EA64__ 5 | TOOLCHAIN=/usr/local/Cellar/gcc/5.3.0/bin/ 6 | CXX=$(TOOLCHAIN)g++-5 7 | CC=$(TOOLCHAIN)gcc-5 8 | LD= $(CC) 9 | 10 | #LDFLAGS=-static -L/dat 11 | CFLAGS=-Wextra -Os -D__MAC__ -m32 -arch i386 -D__IDP__ -D__PLUGIN__ -I$(SDKPATH)/include 12 | CXXFLAGS= -D__MAC__ $(SWITCH64) -I$(SDKPATH)/include -I$(SDKDIR)/ldr 13 | LDFLAGS=-dynamiclib -m32 -L/Users/surge/Desktop/SDK/idasdk66/lib -lida 14 | 15 | SDKPATH := /Users/surge/Desktop/SDK/idasdk66 16 | LIBIDAPATH := /Users/surge/Desktop/SDK/idasdk66/lib 17 | 18 | SRC= ida-mbn-sbl-loader.cpp 19 | OBJS= ida-mbn-sbl-loader.o 20 | PLUGIN := ida-mbn-sbl-loader.pmc 21 | 22 | all: $(pmc) $(ldw) 23 | 24 | pmc: $(SRC) 25 | 26 | ida-mbn-sbl-loader.cpp: $(OBJS) 27 | $(CXX) $(CXXFLAGS) -o $(PLUGIN) $(OBJS) $(LDFLAGS) 28 | 29 | ida-mbn-sbl-loader.o: $(SRC) 30 | $(CXX) $(CFLAGS) $(SRC) -v -c 31 | 32 | clean: 33 | rm $(PLUGIN) $(OBJS) 34 | 35 | 36 | # WIN32 37 | export __EA64__=1 38 | export __WIN32__=1 39 | SWITCH64=-D__NT__ 40 | TOOLCHAIN=/usr/local/Cellar/gcc/5.3.0/bin/ 41 | CXX=$(TOOLCHAIN)g++-5 42 | CC=$(TOOLCHAIN)gcc-5 43 | LD= $(CC) 44 | 45 | CXXFLAGS2=-DWIN32 -D__NT__ -D__IDP__ -I$(SDKPATH)/include -I$(SDKPATH)/ldr -mrtd 46 | CFLAGS+=-I/Users/surge/Downloads/tcc-0.9.25-my/win32/include -I$(SDKPATH)/include -I$(SDKDIR)/ldr 47 | LFLAGS=/Users/surge/Desktop/SDK/idasdk66/lib/x86_win_gcc_32/ida.a -Wl, -dll -shared 48 | 49 | SDKPATH := /Users/surge/Desktop/SDK/idasdk66 50 | LIBIDAPATH := /Users/surge/Desktop/SDK/idasdk66/lib 51 | 52 | SRC= ida-mbn-sbl-loader.cpp 53 | OBJS= ida-mbn-sbl-loader.o 54 | PLUGIN= ida-mbn-sbl-loader.ldw 55 | 56 | ldw: $(SRC) 57 | 58 | ida-mbn-sbl-loader.cpp: $(OBJS) 59 | $(CXX) $(CXXFLAGS2) -o $(PLUGIN) $(OBJS) $(LDFLAGS) 60 | 61 | ida-mbn-sbl-loader.o: $(SRC) 62 | $(CXX) $(CFLAGS) $(SRC) -v -c 63 | 64 | 65 | clean: 66 | rm $(PLUGIN) $(OBJS) 67 | 68 | 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Instructions: 2 | 3 | Copy any one of, or all three of the loaders (ida-mbn-sbl-loader.py, ida-mbn-sbl-loader.plw, ida-mbn-sbl-loader.pmc( to $IDADIR/loaders/ 4 | 5 | load the attached aboot.mbn and it should load it right in 6 | 7 | The ida-mbn-sbl-loader.cpp is the source for the plw (Windows version) of the plugin and can be built with visual studio (only tested and confirmed to build for me on 2013 version though). I havent uploaded the sln or studio build config files yet but it uses the same files as the mac and linux versions though so it shouldn't be too hard to figure out. 8 | 9 | 10 | These exist but I commented out the segment adding code because there's gotta be a easier way to find the segments without having the source itself, I'm not sure if maybe FindInstructions as defined in the idaapi could be used to make finding these segs less of a "hardcoded" and more of "dynamically found" type of thing. 11 | 12 | 13 | Segment Sections 14 | 00 .ARM.exidx 15 | 01 .text.boot .text .rodata .ARM.exidx .data .bss 16 | 02 17 | 18 | 19 | Below are the actual addresses of the data_start (of the DATA segment) and .bss etc that were provided by a source in the know. The goal for now is to get this loader to recognize those data and bss addresses and add them correctly. The loader by Ralekdev does almost achieve this, but not quite you got download his loader from here and test yourself to see. https://github.com/ralekdev/mbn_ida_loader/blob/master/mbn_ida_loader.py 20 | 21 | Segment type: Absolute symbols 22 | __dtor_list = 0x88F3AE6C 23 | __ctor_list = 0x88F3AE6C 24 | __data_end = 0x88F3AE6C 25 | __data_start = 0x88E54740 26 | __data_start_rom = 0x88E54740 27 | __ctor_end = 0x88F3AE6C 28 | _end_of_ram = 0x89000000 29 | __bss_start = 0x88F3AE6C 30 | _end = 0x88F4DC54 31 | __dtor_end = 0x88F3AE6C 32 | -------------------------------------------------------------------------------- /ida-mbn-sbl-loader.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | # Ida Mbn/Sbl loader for Ida Pro - by @Surge1223 3 | # 4 | # Relocation table isnt correct yet, send me an email if you 5 | # know how to correct this (surge1223@gmail.com). 6 | # Also support for osbl, dbl, and pbl 7 | # can be added if theres a need, just add the header and where 8 | # to unpack from 9 | */ 10 | 11 | #include <..\ldr\idaldr.h> 12 | #include 13 | #include 14 | #include "mbn.h" 15 | 16 | #define YES_NO( condition ) ( condition ? "yes" : "no" ) 17 | typedef std::vector CHARS; 18 | #define mbn_MAGIC ` = 0x73D71034 19 | #define FLASH_CODE_WORD = 0x844BDCD1 20 | #define BOOT_COOKIE_MAGIC_NUMBER = 0x33836685 21 | #define MAGIC_NUM = 0x73D71034 22 | #define HDR_FLASH_VER = 0x00000003 23 | #define PAGE_SIZE_MAGIC_NUM = 0x7D0B435A 24 | #define MI_FSBL_MAGIC1 = 0x6FC123DF 25 | #define MI_FSBL_MAGIC2 = 0x60FDEFC7 26 | #define MI_OSBL_MAGIC1 = 0x6CBA1CFD 27 | #define MI_OSBL_MAGIC2 = 0x68D2CBE9 28 | #define MI_SBL2_MAGIC1 = 0x6012780C 29 | #define MI_SBL2_MAGIC2 = 0x6C93B127 30 | #define NOR_SBL1_HEADER = ' 0) 46 | { 47 | if (qlread(file, &data[0], size) == -1) 48 | { 49 | data.resize(0); 50 | } 51 | } 52 | return data.size() == size; 53 | } 54 | 55 | //-------------------------------------------------------------------------- 56 | // 57 | // check input file format. if recognized, then return 1 58 | // and fill 'fileformatname'. 59 | // otherwise return 0 60 | // 61 | 62 | 63 | static unsigned int SWAP_BYTES_32(unsigned int a) 64 | { 65 | return ((a >> 24) & 0x000000FF) | ((a >> 8) & 0x0000FF00) | ((a << 8) & 0x00FF0000) | ((a << 24) & 0xFF000000); // Swap dword LE to BE 66 | } 67 | 68 | //------------------------------------------------------------------------ 69 | static unsigned short READ_BE_WORD(unsigned char *addr) 70 | { 71 | return (addr[0] << 8) | addr[1]; // Read BE word 72 | } 73 | 74 | //------------------------------------------------------------------------ 75 | static unsigned int READ_BE_UINT(unsigned char *addr) 76 | { 77 | return (READ_BE_WORD(&addr[0]) << 16) | READ_BE_WORD(&addr[2]); // Read BE unsigned int by pointer 78 | } 79 | 80 | //------------------------------------------------------------------------ 81 | static void add_sub(unsigned int addr, const char *name, unsigned int max) 82 | { 83 | if (!((addr >= 0x200) && (addr < max))) return; 84 | 85 | ea_t e_addr = toEA(ask_selector(0), addr); 86 | auto_make_proc(e_addr); 87 | set_name(e_addr, name); 88 | } 89 | 90 | //------------------------------------------------------------------------ 91 | static void add_segment(ea_t start, ea_t end, const char *name, const char *class_name, const char *cmnt) 92 | { 93 | if (!add_segm(0, start, end, name, class_name)) loader_failure(); 94 | segment_t *segm = getseg(start); 95 | set_segment_cmt(segm, cmnt, false); 96 | doByte(start, 1); 97 | } 98 | //------------------------------------------------------------------------ 99 | 100 | //------------------------------------------------------------------------ 101 | static mbn_hdr hdr; 102 | static sbl_hdr shdr; 103 | int accept_file(linput_t *li, char fileformatname[MAX_FILE_FORMAT_NAME], int n) 104 | { 105 | 106 | if (n != 0) 107 | return 0; 108 | 109 | // quit if file is smaller than size of iNes header 110 | if (qlsize(li) < sizeof(mbn_hdr)) 111 | return 0; 112 | 113 | // set filepos to offset 0 114 | // imglen = qlsize(li); 115 | qlseek(li, 0, SEEK_SET); 116 | 117 | // read MBN header 118 | if (qlread(li, &hdr, MBN_HDR_SIZE) != MBN_HDR_SIZE) 119 | return 0; 120 | 121 | // read SBL header 122 | if (qlread(li, &shdr, SBL_HDR_SIZE) != SBL_HDR_SIZE) 123 | return 0; 124 | 125 | // this is the name of the file format which will be 126 | // displayed in IDA's dialog 127 | qstrncpy(fileformatname, "QCOM Bootloader", MAX_FILE_FORMAT_NAME); 128 | 129 | // set processor to ARM 130 | if (ph.id != PLFM_6502) 131 | { 132 | msg("QCOM Bootloader detected: setting processor type to ARM.\n"); 133 | set_processor_type("ARM", SETPROC_ALL); 134 | } 135 | 136 | return (1 | ACCEPT_FIRST); 137 | } 138 | //-------------------------------------------------------------------------- 139 | void mbnhdr(linput_t *li, mbn &ex) 140 | { 141 | //lread(li, &ex, sizeof(ex)); 142 | //mbn_hdr(li, ex); 143 | //lread(li, &mbn_hdr, sizeof(mbn)); 144 | lread4bytes(li, &ex.image_id, true); 145 | lread4bytes(li, &ex.flash_parti_ver, true); 146 | lread4bytes(li, &ex.image_src, true); 147 | lread4bytes(li, &ex.image_dest_ptr, true); 148 | lread4bytes(li, &ex.image_size, true); 149 | lread4bytes(li, &ex.code_size, true); 150 | lread4bytes(li, &ex.signature_ptr, true); 151 | lread4bytes(li, &ex.signature_size, true); 152 | lread4bytes(li, &ex.cert_chain_ptr, true); 153 | lread4bytes(li, &ex.cert_chain_size, true); 154 | 155 | set_processor_type("arm", SETPROC_ALL | SETPROC_FATAL); 156 | } 157 | //-------------------------------------------------------------------------- 158 | void sblhdr(linput_t *li, sbl &ex) 159 | { 160 | //lread(li, &ex, sizeof(ex)); 161 | //mbn_hdr(li, ex); 162 | //lread(li, &mbn_hdr, sizeof(mbn)); 163 | lread4bytes(li, &ex.codeword, true); 164 | lread4bytes(li, &ex.magic, true); 165 | lread4bytes(li, &ex.image_id, true); 166 | lread4bytes(li, &ex.image_src, true); 167 | lread4bytes(li, &ex.image_dest_ptr, true); 168 | lread4bytes(li, &ex.image_size, true); 169 | lread4bytes(li, &ex.code_size, true); 170 | lread4bytes(li, &ex.signature_ptr, true); 171 | lread4bytes(li, &ex.signature_size, true); 172 | lread4bytes(li, &ex.cert_chain_ptr, true); 173 | lread4bytes(li, &ex.cert_chain_size, true); 174 | set_processor_type("arm", SETPROC_ALL | SETPROC_FATAL); 175 | } 176 | 177 | //-------------------------------------------------------------------------- 178 | // 179 | // load file into the database. 180 | static void idaapi load_file(linput_t *li, ushort neflags, const char * fileformatname) { 181 | 182 | ea_t entry_point; 183 | mbn hdr; 184 | mbn ex; 185 | sbl hds; 186 | CHARS data; 187 | // display a messagebox asking the user for details 188 | // 1 - Yes 189 | // 0 - No 190 | // -1 - Cancel 191 | int answer = askyn_cv(1, 192 | "MBN/SBL loader by Surge1223.\n\n" 193 | "The partition may have a different start address if SBL1.\n" 194 | "Choose \"Yes\" to load the SBL1 type,\n" 195 | "\"No\" to load all other MBN types\n\n" 196 | "\nDo you want to load the SBL1 code?\n\n" 197 | , NULL 198 | ); 199 | // user chose "cancel" ? 200 | if (answer == BADADDR) 201 | { 202 | qexit(1); 203 | } 204 | 205 | // user chose "yes" = arm9 206 | else if (answer) 207 | { 208 | // and read the whole header 209 | lread(li, &hds, SBL_HDR_SIZE); 210 | msg("Codeword: : %08x\n", hds.codeword); 211 | msg("Magic No.: : %08x\n", hds.magic); 212 | msg("Image ID: : %08x\n", ex.image_id); 213 | msg("Source Location: : %08x\n", ex.image_src); 214 | msg("Destination Address: : %08x\n", ex.image_dest_ptr); 215 | msg("Image Size: : %08x\n", ex.image_size); 216 | msg("Code Size: : %08x\n", ex.code_size); 217 | msg("Signature Ptr: : %08x\n", ex.signature_ptr); 218 | msg("Signature Size: : %08x\n", ex.signature_size); 219 | msg("Cert Chain Ptr: : %08x\n", ex.cert_chain_ptr); 220 | msg("Cert Chain Size: : %08x\n", ex.cert_chain_size); 221 | //read the program header from the input file 222 | //lread(li, &hdr, MBN_HDR_SIZE); 223 | //file2base does a seek and read from the input file into the database 224 | //file2base is prototyped in loader.hpp 225 | file2base(li, sizeof(sbl), hds.image_dest_ptr, hds.image_dest_ptr + hds.code_size, true); 226 | //try to add a new code segment to contain the program bytes 227 | if (!add_segm(0, hds.image_dest_ptr, hds.image_dest_ptr + hds.code_size, BOOT_SEGMENT, CLASS_CODE)) { 228 | 229 | loader_failure(); 230 | } 231 | add_entry(hds.image_dest_ptr, hds.image_dest_ptr, "_start", true); 232 | //retrieve a handle to the new segment 233 | segment_t *s = get_segm_by_name(BOOT_SEGMENT); 234 | //so that we can set 32 bit addressing mode on 235 | set_segm_addressing(s, 1); //set 32 bit addressing 236 | //tell IDA to create the file header comment for us. Do this only once 237 | create_filename_cmt(); 238 | //Add an entry point so that the processor module knows at least one 239 | //address that contains code. This is the root of the recursive descent 240 | //disassembly process 241 | add_entry(hds.image_dest_ptr, hds.image_dest_ptr, "HEADER", true); 242 | //Add an entry point so that the processor module knows at least one 243 | //address that contains code. This is the root of the recursive descent 244 | //disassembly process 245 | //---------------------------------------------------------------------- 246 | } 247 | //read the program header from the input file 248 | lread(li, &hdr, MBN_HDR_SIZE); 249 | msg("Codeword: : %08x\n", hdr.flash_parti_ver); 250 | msg("Magic No.: : %08x\n", hdr.image_id); 251 | msg("Source Location: : %08x\n", hdr.image_src); 252 | msg("Destination Address: : %08x\n", hdr.image_dest_ptr); 253 | msg("Image Size: : %08x\n", hdr.image_size); 254 | msg("Code Size: : %08x\n", hdr.code_size); 255 | msg("Signature Ptr: : %08x\n", hdr.signature_ptr); 256 | msg("Signature Size: : %08x\n", hdr.signature_size); 257 | msg("Cert Chain Ptr: : %08x\n", hdr.cert_chain_ptr); 258 | msg("Cert Chain Size: : %08x\n", hdr.cert_chain_size); 259 | 260 | //read the program header from the input file 261 | //lread(li, &hdr, MBN_HDR_SIZE); 262 | //file2base does a seek and read from the input file into the database 263 | //file2base is prototyped in loader.hpp 264 | file2base(li, MBN_HDR_SIZE, hdr.image_dest_ptr, hdr.image_dest_ptr + hdr.code_size, true); 265 | //try to add a new code segment to contain the program bytes 266 | if (!add_segm(0, hdr.image_dest_ptr, hdr.image_dest_ptr + hdr.code_size, BOOT_SEGMENT, CLASS_CODE)) { 267 | 268 | loader_failure(); 269 | } 270 | //retrieve a handle to the new segment 271 | segment_t *s = get_segm_by_name(BOOT_SEGMENT); 272 | //so that we can set 32 bit addressing mode on 273 | set_segm_addressing(s, 1); //set 32 bit addressing 274 | //tell IDA to create the file header comment for us. Do this only once 275 | create_filename_cmt(); 276 | //Add an entry point so that the processor module knows at least one 277 | //address that contains code. This is the root of the recursive descent 278 | //disassembly process 279 | add_entry(hdr.image_dest_ptr, hdr.image_dest_ptr, "HEADER", true); 280 | //Add an entry point so that the processor module knows at least one 281 | //address that contains code. This is the root of the recursive descent 282 | //disassembly process 283 | //---------------------------------------------------------------------- 284 | } 285 | //---------------------------------------------------------------------- 286 | // 287 | // defines, names and comments an item 288 | // 289 | static void define_item(ushort address, asize_t size, char *shortdesc, char *comment) 290 | { 291 | do_unknown(address, true); 292 | set_name(address, shortdesc); 293 | set_cmt(address, comment, true); 294 | } 295 | 296 | 297 | bool idaapi init_loader_options(linput_t *li) 298 | { 299 | mbn ex; 300 | mbnhdr(li, ex); 301 | return true; 302 | } 303 | 304 | int idaapi save_file(FILE * file, const char * formatname) 305 | { 306 | if (file == NULL) return 1; 307 | 308 | segment_t *s = get_segm_by_name(BOOT_SEGMENT); 309 | if (!s) return 0; 310 | 311 | base2file(file, 0, s->startEA, s->endEA); 312 | return 1; 313 | } 314 | 315 | static ea_t get_vector(ea_t vec) 316 | { 317 | return get_word(vec); 318 | } 319 | 320 | 321 | //---------------------------------------------------------------------- 322 | // 323 | // define location as word (2 byte), convert it to an offset, rename it 324 | // and comment it with the file offset 325 | // 326 | static void name_vector(ushort address, const char *name) 327 | { 328 | do_unknown(address, true); 329 | do_data_ex(address, wordflag(), 2, BADNODE); 330 | set_offset(address, 0, 0); 331 | set_name(address, name); 332 | } 333 | 334 | //---------------------------------------------------------------------- 335 | // 336 | // LOADER DESCRIPTION BLOCK 337 | // 338 | //---------------------------------------------------------------------- 339 | __declspec(dllexport) 340 | loader_t LDSC = 341 | { 342 | IDP_INTERFACE_VERSION, 343 | 0, 344 | accept_file, 345 | load_file, 346 | save_file, 347 | NULL, 348 | NULL, 349 | }; 350 | -------------------------------------------------------------------------------- /ida-mbn-sbl-loader.py: -------------------------------------------------------------------------------- 1 | # Ida Mbn Sbl and ELF test loader - by @Surge1223 2 | # 3 | # Mostly from scratch to figure out fucking segments 4 | # 5 | # Relocation table isnt correct yet, send me an email if you 6 | # know how to correct this. Also support for osbl, dbl, and pbl 7 | # can be added if theres a need, just add the header (or adjust the SBL hdr) 8 | # and where to unpack from 9 | 10 | from idaapi import * 11 | from idautils import * 12 | from idc import * 13 | import os 14 | import sys 15 | import struct 16 | 17 | # Magic numbers filled in for boot headers 18 | FLASH_PARTI_VERSION = 3 19 | NOR_SBL1_HEADER = ' 0: return 0 547 | if hexRead(li, 0) != None: 548 | print ("hex at first 4 bytes 0 {} ".format(str(hexRead(li, 0x80 + 0x20)))) 549 | entry = (str(hex(dwordAt(li, 12)))) 550 | if (str(hex(dwordAt(li, 12)))) [-1] == 'L': 551 | entry = (str(hex(dwordAt(li, 12)))) [:-1] 552 | print ("entry address: " + (entry)) 553 | if dwordAt(li, 4) == MAGIC_NUM: 554 | idaapi.set_processor_type("arm:ARMv7-A&R", SETPROC_ALL|SETPROC_FATAL) 555 | idc.ChangeConfig('ARM_DEFAULT_ARCHITECTURE = metaarm') 556 | idc.ChangeConfig('ARM_SIMPLIFY = NO') 557 | return SBL 558 | 559 | if hexRead(li, 4) == HDR_FLASH_VER: 560 | print ("hex at first 4 bytes 1 {} ".format(str(hexRead(li, 4)))) 561 | idaapi.set_processor_type("arm:ARMv7-A&R", SETPROC_ALL|SETPROC_FATAL) 562 | idc.ChangeConfig('ARM_DEFAULT_ARCHITECTURE = metaarm') 563 | idc.ChangeConfig('ARM_SIMPLIFY = NO') 564 | return MBN 565 | 566 | if hexRead(li, 0) == 1179403647: 567 | print ("hex at first 4 bytes 2 {} ".format(str(hexRead(li, 0x52 + 0x24)))) 568 | idaapi.set_processor_type("arm:ARMv7-A&R", SETPROC_ALL|SETPROC_FATAL) 569 | idc.ChangeConfig('ARM_DEFAULT_ARCHITECTURE = metaarm') 570 | idc.ChangeConfig('ARM_SIMPLIFY = NO') 571 | return ELF 572 | 573 | return 574 | 575 | # ----------------------------------------------------------------------- 576 | 577 | def load_file(li, neflags, format): 578 | 579 | idaapi.set_processor_type("arm:ARMv7-A&R", SETPROC_ALL|SETPROC_FATAL) 580 | idc.ChangeConfig('ARM_DEFAULT_ARCHITECTURE = metaarm') 581 | 582 | if format == SBL: 583 | return load_file_sbl(li, neflags, format) 584 | if format == MBN: 585 | return load_file_mbn(li, neflags, format) 586 | if format == ELF: 587 | return load_file_elf(li, neflags, format) 588 | return 589 | 590 | # ----------------------------------------------------------------------- 591 | 592 | def load_file_mbn(li, neflags, format): 593 | 594 | # set the processor type and enable 'metaarm' so ida disassembles all instructions 595 | idaapi.set_processor_type("arm:ARMv7-A&R", idaapi.SETPROC_ALL | idaapi.SETPROC_FATAL) 596 | idc.ChangeConfig('ARM_DEFAULT_ARCHITECTURE = metaarm') 597 | 598 | # rewind the input file and read its contents 599 | # extract the values from the rom into the class 600 | li.seek(0) 601 | 602 | # initialize class Mbn_Hdr with size of input file 603 | init_val = li.read(li.size()) 604 | print ("size: " + str(len(init_val))) 605 | rom = Mbn_Hdr(init_val) 606 | 607 | offs = rom.Mbn_Hdrsz() 608 | offset = li.tell() 609 | FormatHex(rom.image_dest_ptr) 610 | 611 | # gen the segment class object references 612 | rom.genMbn_segs() 613 | rom.getSize() 614 | 615 | (rom.image_id, 616 | rom.flash_parti_ver, 617 | rom.image_src, 618 | rom.image_dest_ptr, 619 | rom.image_size, 620 | rom.code_size, 621 | rom.sig_ptr, 622 | rom.sig_size, 623 | rom.cert_chain_ptr, 624 | rom.cert_chain_size) = struct.unpack_from(rom.MBN_HEADER, init_val) 625 | 626 | image_base = rom.image_dest_ptr - rom.image_src 627 | image_size = rom.sig_size + rom.cert_chain_size 628 | start = 0x28 629 | ''' This is necessary to 4byte align the image_size''' 630 | if (image_size % 4) != 0: 631 | image_size += (4 - (image_size % 4)) 632 | rom.image_size = image_size 633 | 634 | ''' This is necessary to 4byte align the code_size''' 635 | if (rom.code_size % 4) != 0: 636 | rom.code_size += (4 - (rom.code_size % 4)) 637 | code_size = rom.code_size 638 | 639 | hdr_offset = rom.Mbn_Hdrsz() 640 | header_start = rom.image_dest_ptr 641 | header_end = 0x140 642 | code_start = rom.image_dest_ptr + header_end 643 | li.seek(40) 644 | 645 | # li.file2base(0, header_start, header_start + code_size, 0) 646 | 647 | #CODE SEGMENT 648 | codeseg = header_start 649 | AddSeg(codeseg, codeseg + code_size, 0, 1, idaapi.saRel32Bytes, idaapi.scPub) 650 | SetSegClass(codeseg, "CODE") 651 | RenameSeg(codeseg, "CODE") 652 | code_end = codeseg + code_size 653 | li.file2base(start, codeseg, code_end, 0) 654 | 655 | 656 | #BOOT SEGMENT 657 | bootseg = header_start 658 | AddSeg(bootseg, bootseg + header_end, 0, 1, idaapi.saRelByte, idaapi.scPub) 659 | SetSegClass(bootseg, "CODE") 660 | RenameSeg(bootseg, ".text.boot") 661 | li.file2base(start, bootseg, bootseg + header_end, 0) 662 | 663 | #RO_DATA SEGMENT 664 | def findrodata(image_base, data_start): 665 | roseg = header_start 666 | roseg_size = (code_end - data_start) 667 | AddSeg(roseg, roseg + roseg_size, 0, 1, idaapi.saRelPara, idaapi.scPub) 668 | SetSegClass(roseg, "CODE") 669 | RenameSeg(roseg, ".rodata") 670 | #li.file2base(code_size, roseg, roseg + roseg_size, 0) 671 | 672 | 673 | #DATA SEGMENT 674 | def finddataseg(image_base): 675 | inst = DecodeInstruction(image_base) 676 | vec_reset = image_base 677 | if inst.get_canon_mnem() == 'B': 678 | vec_reset = inst.Op1.addr 679 | search_start = vec_reset 680 | search_end = search_start + 0x100 681 | 682 | data_insts = FindBinary(search_start, SEARCH_DOWN, "?? 00 ?? ?? ?? 10 ?? ?? ?? 20 ?? ??") 683 | if data_insts == BADADDR or data_insts > search_end: 684 | return False 685 | 686 | data_start = Dword(DecodeInstruction(data_insts + 4).Op2.addr) 687 | data_end = Dword(DecodeInstruction(data_insts + 8).Op2.addr) 688 | data_end = (data_end + 3) & ~3 689 | 690 | AddSeg(data_start, data_end, 0, 1, idaapi.saGroup, idaapi.scPub) 691 | SetSegClass(data_start, "DATA") 692 | RenameSeg(data_start, "DATA") 693 | 694 | 695 | bss_insts = FindBinary(data_insts, SEARCH_DOWN, "34 00 ?? ?? 34 10 ?? ??") 696 | if bss_insts == BADADDR or bss_insts > search_end: 697 | return False 698 | 699 | bss_start = Dword(DecodeInstruction(bss_insts + 0).Op2.addr) 700 | bss_end = Dword(DecodeInstruction(bss_insts + 4).Op2.addr) 701 | 702 | AddSeg(bss_start, bss_end, 0, 1, idaapi.saRelByte, idaapi.scPub) 703 | SetSegClass(bss_start, "BSS") 704 | RenameSeg(bss_start, "BSS") 705 | 706 | kmain_addr = FindBinary(search_start, SEARCH_DOWN, "?? ?? 00 FA") 707 | if kmain_addr == BADADDR or kmain_addr > search_end: 708 | return False 709 | 710 | idc.Message("new func is at 0x%08x\n" % kmain_addr) 711 | kmain_addr = DecodeInstruction(kmain_addr).Op1.addr 712 | MakeName(kmain_addr, "kmain") 713 | idaapi.add_entry(kmain_addr, kmain_addr, "kmain", 1) 714 | # findrodata(image_base, data_start) 715 | return True 716 | 717 | 718 | finddataseg(header_start) 719 | idaapi.add_entry(header_start, header_start, "_start", 1) 720 | idaapi.set_segm_addressing(idaapi.get_segm_by_name(".text.boot"), 1) 721 | # idaapi.set_segm_addressing(idaapi.get_segm_by_name(".rodata"), 1) 722 | # idaapi.set_segm_addressing(idaapi.get_segm_by_name("CODE"), 1) 723 | 724 | 725 | idaapi.analyze_area(bootseg, header_end) 726 | armcinstr(bootseg) 727 | idaapi.analyze_area(bootseg, header_end) 728 | idaapi.analyze_area(codeseg, code_end) 729 | 730 | 731 | 732 | 733 | AddIdbComment(image_base, 'Flash Part Version: ', rom.flash_parti_ver) 734 | AddIdbComment(image_base, 'Source Location: ', rom.image_src) 735 | AddIdbComment(image_base, 'Destination Address: ', rom.image_dest_ptr) 736 | AddIdbComment(image_base, 'Image Size: ', rom.image_size) 737 | AddIdbComment(image_base, 'Code Size: ', rom.code_size) 738 | AddIdbComment(image_base, 'Signature Ptr: ', rom.sig_ptr) 739 | AddIdbComment(image_base, 'Signature Size: ', rom.sig_size) 740 | AddIdbComment(image_base, 'Cert Chain Ptr: ', rom.cert_chain_ptr) 741 | AddIdbComment(image_base, 'Cert Chain Size: ', rom.cert_chain_size) 742 | 743 | return 1 744 | 745 | 746 | # ----------------------------------------------------------------------- 747 | 748 | def load_file_sbl(li, neflags, format): 749 | 750 | # set the processor type and enable 'metaarm' so ida disassembles all instructions 751 | idaapi.set_processor_type("arm:ARMv7-A&R", idaapi.SETPROC_ALL | idaapi.SETPROC_FATAL) 752 | idc.ChangeConfig('ARM_DEFAULT_ARCHITECTURE = metaarm') 753 | 754 | # rewind the input file and read its contents 755 | # extract the values from the rom into the class 756 | li.seek(0) 757 | 758 | # initialize class Sbl_Hdr with size of input file 759 | init_val = li.read(li.size()) 760 | rom = Sbl_Hdr(init_val) 761 | offs = rom.Sbl_Hdrsz() 762 | size = li.tell() 763 | 764 | # gen the segment class object references 765 | rom.genSbl_segs() 766 | rom.getSize() 767 | 768 | (rom.codeword, 769 | rom.magic, 770 | rom.image_id, 771 | rom.reserved_1, 772 | rom.reserved_2, 773 | rom.image_src, 774 | rom.image_dest_ptr, 775 | rom.image_size, 776 | rom.code_size, 777 | rom.sig_ptr, 778 | rom.sig_size, 779 | rom.cert_chain_ptr, 780 | rom.cert_chain_size, 781 | rom.oem_root_cert_sel, 782 | rom.oem_num_root_certs, 783 | rom.reserved_5, 784 | rom.reserved_6, 785 | rom.reserved_7, 786 | rom.reserved_8, 787 | rom.reserved_9) = struct.unpack_from(Sbl_Hdr.SBL_HEADER, init_val) 788 | 789 | 790 | 791 | image_base = rom.image_dest_ptr - rom.image_src 792 | image_size = rom.code_size + rom.sig_size +rom.cert_chain_size 793 | start = 0x285 794 | ''' This is necessary to 4byte align the image_size''' 795 | if (image_size % 4) != 0: 796 | image_size += (4 - (image_size % 4)) 797 | rom.image_size = image_size 798 | 799 | ''' This is necessary to 4byte align the code_size''' 800 | if (rom.code_size % 4) != 0: 801 | rom.code_size += (4 - (rom.code_size % 4)) 802 | code_size = rom.code_size - start 803 | 804 | hdr_offset = rom.Sbl_Hdrsz() 805 | header_start = rom.image_dest_ptr 806 | header_end = rom.image_dest_ptr + 80 807 | code_start = rom.image_dest_ptr 808 | code_end = code_start + rom.code_size 809 | start = 0x285 810 | 811 | li.file2base(start, code_start, code_start + code_size, 0) 812 | 813 | #BOOT SEGMENT 814 | idc.AddSeg(header_start, header_end, 0, 1, idaapi.saRelPara, idaapi.scPub) 815 | SetSegmentType(header_start, idaapi.SEG_CODE) 816 | RenameSeg(header_start, ".text.boot") 817 | 818 | #CODE SEGMENT 819 | AddSeg(code_start, code_start + rom.code_size, 0, 1, idaapi.saRelPara, idaapi.scPub) 820 | SetSegmentType(code_start, idaapi.SEG_CODE) 821 | RenameSeg(code_start, "CODE") 822 | 823 | image_base = rom.image_dest_ptr 824 | image_code = (rom.image_dest_ptr + rom.image_size) 825 | idaapi.add_entry(header_start, header_start, "_start", 1) 826 | idaapi.set_segm_addressing(idaapi.getseg(header_start), 1) 827 | 828 | AddIdbComment(image_base, 'Codeword: ', rom.codeword) 829 | AddIdbComment(image_base, 'Magic No.: ', rom.magic) 830 | AddIdbComment(image_base, 'Source Location: ', rom.image_src) 831 | AddIdbComment(image_base, 'Destination Address: ', rom.image_dest_ptr) 832 | AddIdbComment(image_base, 'Image Size: ', rom.image_size) 833 | AddIdbComment(image_base, 'Code Size: ', rom.code_size) 834 | AddIdbComment(image_base, 'Signature Ptr: ', rom.sig_ptr) 835 | AddIdbComment(image_base, 'Signature Size: ', rom.sig_size) 836 | AddIdbComment(image_base, 'Cert Chain Ptr: ', rom.cert_chain_ptr) 837 | AddIdbComment(image_base, 'Cert Chain Size: ', rom.cert_chain_size) 838 | AddIdbComment(image_base, 'OEM Cert Sel: ', rom.oem_root_cert_sel) 839 | AddIdbComment(image_base, 'OEM Cert Num: ', rom.oem_num_root_certs) 840 | 841 | 842 | return 1 843 | 844 | # ----------------------------------------------------------------------- 845 | 846 | 847 | def load_file_elf(li, neflags, format): 848 | 849 | # set the processor type and enable 'metaarm' so ida disassembles all instructions 850 | idaapi.set_processor_type("arm:ARMv7-A&R", idaapi.SETPROC_ALL | idaapi.SETPROC_FATAL) 851 | idc.ChangeConfig('ARM_DEFAULT_ARCHITECTURE = metaarm') 852 | 853 | # rewind the input file and read its contents 854 | # extract the values from the rom into the class 855 | li.seek(0) 856 | 857 | # initialize class ELF Hdr with size of input file 858 | init_val = li.read(li.size()) 859 | b = Buf(init_val) 860 | rom = Elf32_Ehdr(b) 861 | offs = rom.Elf32_Hdrsz() 862 | size = li.tell() 863 | 864 | # gen the segment class object references 865 | rom.genElf_segs() 866 | rom.getSize() 867 | 868 | 869 | rom.e_ident = li.read(16) 870 | (rom.e_type, 871 | rom.e_machine, 872 | rom.e_version, 873 | rom.e_entry, 874 | rom.e_phoff, 875 | rom.e_shoff, 876 | rom.e_flags, 877 | rom.e_ehsize, 878 | rom.e_phentsize, 879 | rom.e_phnum, 880 | rom.e_shentsize, 881 | rom.e_shnum, 882 | rom.e_shstrndx) = b.readUnpack(Elf32_Ehdr.ELF_HEADER) 883 | 884 | hdr_offset = rom.Elf32_Hdrsz() 885 | header_start = rom.e_entry 886 | header_end = rom.e_entry + rom.e_phoff 887 | code_start = rom.e_entry 888 | code_end = rom.e_entry + rom.e_ehsize 889 | start = 0x28 890 | 891 | #CODE SEGMENT 892 | AddSeg(code_start, code_start + rom.e_ehsize, 0, 1, idaapi.saRelPara, idaapi.scPub) 893 | SetSegmentType(code_start, idaapi.SEG_CODE) 894 | RenameSeg(code_start, "CODE") 895 | 896 | image_base = rom.e_entry 897 | image_code = (rom.e_entry + rom.e_ehsize) 898 | idaapi.add_entry(header_start, header_start, "HEADER", 1) 899 | idaapi.set_segm_addressing(idaapi.getseg(header_start), 1) 900 | 901 | 902 | AddIdbComment(image_base, 'e_type: ', rom.e_type) 903 | AddIdbComment(image_base, 'e_machine: ', rom.e_machine) 904 | AddIdbComment(image_base, 'e_version: ', rom.e_version) 905 | AddIdbComment(image_base, 'Image Entry VA: ', rom.e_entry) 906 | AddIdbComment(image_base, 'ELFH_PHOFF_OFFSET: ', rom.e_phoff) 907 | AddIdbComment(image_base, 'ELFH_SHOFF_OFFSET: ', rom.e_shoff) 908 | AddIdbComment(image_base, 'e_flags: ', rom.e_flags) 909 | AddIdbComment(image_base, 'ELF HDR SZ (bytes): ', rom.e_ehsize) 910 | AddIdbComment(image_base, 'PHDR Entry SZ: ', rom.e_phentsize) 911 | AddIdbComment(image_base, 'ELFH_PHNUM_OFFSET: ', rom.e_phnum) 912 | AddIdbComment(image_base, 'SHDR Entry SZ: ', rom.e_shentsize) 913 | AddIdbComment(image_base, 'ELFH_SHNUM_OFFSET: ', rom.e_shnum) 914 | AddIdbComment(image_base, 'Section HDR (sh) index: ', rom.e_shstrndx) 915 | 916 | return 1 917 | 918 | -------------------------------------------------------------------------------- /mbn.h: -------------------------------------------------------------------------------- 1 | #ifndef __MBN_H__ 2 | #define __MBN_H__ 3 | 4 | typedef struct mbn { 5 | int image_id; 6 | int header_part_ver; 7 | int image_src; 8 | int image_dest_ptr; 9 | int image_size; 10 | int code_size; 11 | int signature_ptr; 12 | int signature_size; 13 | int cert_chain_ptr; 14 | int cert_chain_size; 15 | } mbn_hdr; 16 | 17 | 18 | // size of MBN header 19 | #define MBN_HDR_SIZE sizeof( mbn_hdr ) 20 | 21 | 22 | //============================ 23 | 24 | #endif 25 | 26 | #ifndef __SBL_H__ 27 | #define __SBN_H__ 28 | 29 | typedef struct sbl { 30 | int codeword; 31 | int magic; /* Magic number */ 32 | int image_id; /* image content */ 33 | int image_src; 34 | int image_dest_ptr; 35 | int image_size; 36 | int code_size; 37 | int signature_ptr; 38 | int signature_size; 39 | int cert_chain_ptr; 40 | int cert_chain_size; 41 | int oem_root_cert_sel; 42 | int oem_num_root_certs; 43 | } sbl_hdr; 44 | 45 | // size of SBL header 46 | #define SBL_HDR_SIZE sizeof( sbl_hdr ) 47 | 48 | 49 | //============================ 50 | #endif 51 | --------------------------------------------------------------------------------