-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathida-mbn-sbl-loader.cpp
349 lines (312 loc) · 11.7 KB
/
ida-mbn-sbl-loader.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
/*
# Ida Mbn/Sbl loader for Ida Pro - by @Surge1223
#
# Relocation table isnt correct yet, send me an email if you
# know how to correct this ([email protected]).
# Also support for osbl, dbl, and pbl
# can be added if theres a need, just add the header and where
# to unpack from
*/
#include <..\ldr\idaldr.h>
#include <windows.h>
#include <vector>
#include "mbn.h"
#define YES_NO( condition ) ( condition ? "yes" : "no" )
typedef std::vector<unsigned char> CHARS;
#define mbn_MAGIC ` = 0x73D71034
#define FLASH_CODE_WORD = 0x844BDCD1
#define BOOT_COOKIE_MAGIC_NUMBER = 0x33836685
#define MAGIC_NUM = 0x73D71034
#define HDR_FLASH_VER = 0x00000003
#define PAGE_SIZE_MAGIC_NUM = 0x7D0B435A
#define MI_FSBL_MAGIC1 = 0x6FC123DF
#define MI_FSBL_MAGIC2 = 0x60FDEFC7
#define MI_OSBL_MAGIC1 = 0x6CBA1CFD
#define MI_OSBL_MAGIC2 = 0x68D2CBE9
#define MI_SBL2_MAGIC1 = 0x6012780C
#define MI_SBL2_MAGIC2 = 0x6C93B127
#define NOR_SBL1_HEADER = '<II72s'
#define NOR_SBL1_HEADER_SZ = struct.calcsize(NOR_SBL1_HEADER)
#define ALIGNMENT = 256
#define NOR_CODE_WORD = 0x844bdcd1
#define HEADER_SIZE sizeof(mbn)
const char BOOT_SEGMENT[] = "MBN_CODE";
char IDAP_comment[] = "loader to dissassemble mbn/sbl booatloaders";
char IDAP_help[] = "QCOM Bootloader Plugin";
char IDAP_hotkey[] = "Alt-X";
bool LoadFile(linput_t * file, CHARS & data)
{
unsigned size = qlsize(file);
data.resize(size);
if (size > 0)
{
if (qlread(file, &data[0], size) == -1)
{
data.resize(0);
}
}
return data.size() == size;
}
//--------------------------------------------------------------------------
//
// check input file format. if recognized, then return 1
// and fill 'fileformatname'.
// otherwise return 0
//
static unsigned int SWAP_BYTES_32(unsigned int a)
{
return ((a >> 24) & 0x000000FF) | ((a >> 8) & 0x0000FF00) | ((a << 8) & 0x00FF0000) | ((a << 24) & 0xFF000000); // Swap dword LE to BE
}
//------------------------------------------------------------------------
static unsigned short READ_BE_WORD(unsigned char *addr)
{
return (addr[0] << 8) | addr[1]; // Read BE word
}
//------------------------------------------------------------------------
static unsigned int READ_BE_UINT(unsigned char *addr)
{
return (READ_BE_WORD(&addr[0]) << 16) | READ_BE_WORD(&addr[2]); // Read BE unsigned int by pointer
}
//------------------------------------------------------------------------
static void add_sub(unsigned int addr, const char *name, unsigned int max)
{
if (!((addr >= 0x200) && (addr < max))) return;
ea_t e_addr = toEA(ask_selector(0), addr);
auto_make_proc(e_addr);
set_name(e_addr, name);
}
//------------------------------------------------------------------------
static void add_segment(ea_t start, ea_t end, const char *name, const char *class_name, const char *cmnt)
{
if (!add_segm(0, start, end, name, class_name)) loader_failure();
segment_t *segm = getseg(start);
set_segment_cmt(segm, cmnt, false);
doByte(start, 1);
}
//------------------------------------------------------------------------
//------------------------------------------------------------------------
static mbn_hdr hdr;
static sbl_hdr shdr;
int accept_file(linput_t *li, char fileformatname[MAX_FILE_FORMAT_NAME], int n)
{
if (n != 0)
return 0;
// quit if file is smaller than size of iNes header
if (qlsize(li) < sizeof(mbn_hdr))
return 0;
// set filepos to offset 0
// imglen = qlsize(li);
qlseek(li, 0, SEEK_SET);
// read MBN header
if (qlread(li, &hdr, MBN_HDR_SIZE) != MBN_HDR_SIZE)
return 0;
// read SBL header
if (qlread(li, &shdr, SBL_HDR_SIZE) != SBL_HDR_SIZE)
return 0;
// this is the name of the file format which will be
// displayed in IDA's dialog
qstrncpy(fileformatname, "QCOM Bootloader", MAX_FILE_FORMAT_NAME);
// set processor to ARM
if (ph.id != PLFM_6502)
{
msg("QCOM Bootloader detected: setting processor type to ARM.\n");
set_processor_type("ARM", SETPROC_ALL);
}
return (1 | ACCEPT_FIRST);
}
//--------------------------------------------------------------------------
void mbnhdr(linput_t *li, mbn &ex)
{
//lread(li, &ex, sizeof(ex));
//mbn_hdr(li, ex);
//lread(li, &mbn_hdr, sizeof(mbn));
lread4bytes(li, &ex.image_id, true);
lread4bytes(li, &ex.flash_parti_ver, true);
lread4bytes(li, &ex.image_src, true);
lread4bytes(li, &ex.image_dest_ptr, true);
lread4bytes(li, &ex.image_size, true);
lread4bytes(li, &ex.code_size, true);
lread4bytes(li, &ex.signature_ptr, true);
lread4bytes(li, &ex.signature_size, true);
lread4bytes(li, &ex.cert_chain_ptr, true);
lread4bytes(li, &ex.cert_chain_size, true);
set_processor_type("arm", SETPROC_ALL | SETPROC_FATAL);
}
//--------------------------------------------------------------------------
void sblhdr(linput_t *li, sbl &ex)
{
//lread(li, &ex, sizeof(ex));
//mbn_hdr(li, ex);
//lread(li, &mbn_hdr, sizeof(mbn));
lread4bytes(li, &ex.codeword, true);
lread4bytes(li, &ex.magic, true);
lread4bytes(li, &ex.image_id, true);
lread4bytes(li, &ex.image_src, true);
lread4bytes(li, &ex.image_dest_ptr, true);
lread4bytes(li, &ex.image_size, true);
lread4bytes(li, &ex.code_size, true);
lread4bytes(li, &ex.signature_ptr, true);
lread4bytes(li, &ex.signature_size, true);
lread4bytes(li, &ex.cert_chain_ptr, true);
lread4bytes(li, &ex.cert_chain_size, true);
set_processor_type("arm", SETPROC_ALL | SETPROC_FATAL);
}
//--------------------------------------------------------------------------
//
// load file into the database.
static void idaapi load_file(linput_t *li, ushort neflags, const char * fileformatname) {
ea_t entry_point;
mbn hdr;
mbn ex;
sbl hds;
CHARS data;
// display a messagebox asking the user for details
// 1 - Yes
// 0 - No
// -1 - Cancel
int answer = askyn_cv(1,
"MBN/SBL loader by Surge1223.\n\n"
"The partition may have a different start address if SBL1.\n"
"Choose \"Yes\" to load the SBL1 type,\n"
"\"No\" to load all other MBN types\n\n"
"\nDo you want to load the SBL1 code?\n\n"
, NULL
);
// user chose "cancel" ?
if (answer == BADADDR)
{
qexit(1);
}
// user chose "yes" = arm9
else if (answer)
{
// and read the whole header
lread(li, &hds, SBL_HDR_SIZE);
msg("Codeword: : %08x\n", hds.codeword);
msg("Magic No.: : %08x\n", hds.magic);
msg("Image ID: : %08x\n", ex.image_id);
msg("Source Location: : %08x\n", ex.image_src);
msg("Destination Address: : %08x\n", ex.image_dest_ptr);
msg("Image Size: : %08x\n", ex.image_size);
msg("Code Size: : %08x\n", ex.code_size);
msg("Signature Ptr: : %08x\n", ex.signature_ptr);
msg("Signature Size: : %08x\n", ex.signature_size);
msg("Cert Chain Ptr: : %08x\n", ex.cert_chain_ptr);
msg("Cert Chain Size: : %08x\n", ex.cert_chain_size);
//read the program header from the input file
//lread(li, &hdr, MBN_HDR_SIZE);
//file2base does a seek and read from the input file into the database
//file2base is prototyped in loader.hpp
file2base(li, sizeof(sbl), hds.image_dest_ptr, hds.image_dest_ptr + hds.code_size, true);
//try to add a new code segment to contain the program bytes
if (!add_segm(0, hds.image_dest_ptr, hds.image_dest_ptr + hds.code_size, BOOT_SEGMENT, CLASS_CODE)) {
loader_failure();
}
add_entry(hds.image_dest_ptr, hds.image_dest_ptr, "_start", true);
//retrieve a handle to the new segment
segment_t *s = get_segm_by_name(BOOT_SEGMENT);
//so that we can set 32 bit addressing mode on
set_segm_addressing(s, 1); //set 32 bit addressing
//tell IDA to create the file header comment for us. Do this only once
create_filename_cmt();
//Add an entry point so that the processor module knows at least one
//address that contains code. This is the root of the recursive descent
//disassembly process
add_entry(hds.image_dest_ptr, hds.image_dest_ptr, "HEADER", true);
//Add an entry point so that the processor module knows at least one
//address that contains code. This is the root of the recursive descent
//disassembly process
//----------------------------------------------------------------------
}
//read the program header from the input file
lread(li, &hdr, MBN_HDR_SIZE);
msg("Codeword: : %08x\n", hdr.flash_parti_ver);
msg("Magic No.: : %08x\n", hdr.image_id);
msg("Source Location: : %08x\n", hdr.image_src);
msg("Destination Address: : %08x\n", hdr.image_dest_ptr);
msg("Image Size: : %08x\n", hdr.image_size);
msg("Code Size: : %08x\n", hdr.code_size);
msg("Signature Ptr: : %08x\n", hdr.signature_ptr);
msg("Signature Size: : %08x\n", hdr.signature_size);
msg("Cert Chain Ptr: : %08x\n", hdr.cert_chain_ptr);
msg("Cert Chain Size: : %08x\n", hdr.cert_chain_size);
//read the program header from the input file
//lread(li, &hdr, MBN_HDR_SIZE);
//file2base does a seek and read from the input file into the database
//file2base is prototyped in loader.hpp
file2base(li, MBN_HDR_SIZE, hdr.image_dest_ptr, hdr.image_dest_ptr + hdr.code_size, true);
//try to add a new code segment to contain the program bytes
if (!add_segm(0, hdr.image_dest_ptr, hdr.image_dest_ptr + hdr.code_size, BOOT_SEGMENT, CLASS_CODE)) {
loader_failure();
}
//retrieve a handle to the new segment
segment_t *s = get_segm_by_name(BOOT_SEGMENT);
//so that we can set 32 bit addressing mode on
set_segm_addressing(s, 1); //set 32 bit addressing
//tell IDA to create the file header comment for us. Do this only once
create_filename_cmt();
//Add an entry point so that the processor module knows at least one
//address that contains code. This is the root of the recursive descent
//disassembly process
add_entry(hdr.image_dest_ptr, hdr.image_dest_ptr, "HEADER", true);
//Add an entry point so that the processor module knows at least one
//address that contains code. This is the root of the recursive descent
//disassembly process
//----------------------------------------------------------------------
}
//----------------------------------------------------------------------
//
// defines, names and comments an item
//
static void define_item(ushort address, asize_t size, char *shortdesc, char *comment)
{
do_unknown(address, true);
set_name(address, shortdesc);
set_cmt(address, comment, true);
}
bool idaapi init_loader_options(linput_t *li)
{
mbn ex;
mbnhdr(li, ex);
return true;
}
int idaapi save_file(FILE * file, const char * formatname)
{
if (file == NULL) return 1;
segment_t *s = get_segm_by_name(BOOT_SEGMENT);
if (!s) return 0;
base2file(file, 0, s->startEA, s->endEA);
return 1;
}
static ea_t get_vector(ea_t vec)
{
return get_word(vec);
}
//----------------------------------------------------------------------
//
// define location as word (2 byte), convert it to an offset, rename it
// and comment it with the file offset
//
static void name_vector(ushort address, const char *name)
{
do_unknown(address, true);
do_data_ex(address, wordflag(), 2, BADNODE);
set_offset(address, 0, 0);
set_name(address, name);
}
//----------------------------------------------------------------------
//
// LOADER DESCRIPTION BLOCK
//
//----------------------------------------------------------------------
__declspec(dllexport)
loader_t LDSC =
{
IDP_INTERFACE_VERSION,
0,
accept_file,
load_file,
save_file,
NULL,
NULL,
};