mkbootimg hacking

  1 /**********************************************************************
  2  *                       mkbootimg hacking
  3  *  声明:
  4  *      1. 本文源代码来自myzr_android4_2_2_1_1_0.tar.bz2中的mkbootimg.c;
  5  *      2. 通过阅读该源码,可知Android的boot.img合成原理;
  6  *
  7  *              深圳 南山平山村 曾剑鋒 Mon May  4 13:09:49 CST 2015
  8  **********************************************************************/
  9
 10 /* tools/mkbootimg/mkbootimg.c
 11 **
 12 ** Copyright 2007, The Android Open Source Project
 13 **
 14 ** Licensed under the Apache License, Version 2.0 (the "License");
 15 ** you may not use this file except in compliance with the License.
 16 ** You may obtain a copy of the License at
 17 **
 18 **     http://www.apache.org/licenses/LICENSE-2.0
 19 **
 20 ** Unless required by applicable law or agreed to in writing, software
 21 ** distributed under the License is distributed on an "AS IS" BASIS,
 22 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 23 ** See the License for the specific language governing permissions and
 24 ** limitations under the License.
 25 */
 26
 27 typedef struct boot_img_hdr boot_img_hdr;
 28
 29 #define BOOT_MAGIC "ANDROID!"
 30 #define BOOT_MAGIC_SIZE 8
 31 #define BOOT_NAME_SIZE 16
 32 #define BOOT_ARGS_SIZE 512
 33
 34 /**
 35  * 用于暂存需要的数据的结构体
 36  */
 37 struct boot_img_hdr
 38 {
 39     unsigned char magic[BOOT_MAGIC_SIZE];           //文件类型标识
 40
 41     unsigned kernel_size;  /* size in bytes         内核文件大小 */
 42     unsigned kernel_addr;  /* physical load addr    内核文件的起始地址 */
 43
 44     unsigned ramdisk_size; /* size in bytes         randisk文件的大小*/
 45     unsigned ramdisk_addr; /* physical load addr    randisk文件的起始地址 */
 46
 47     unsigned second_size;  /* size in bytes         */
 48     unsigned second_addr;  /* physical load addr    */
 49
 50     unsigned tags_addr;    /* physical addr for kernel tags */
 51     unsigned page_size;    /* flash page size we assume */
 52     unsigned unused[2];    /* future expansion: should be 0 */
 53
 54     unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */
 55
 56     unsigned char cmdline[BOOT_ARGS_SIZE];   /* 如果U-Boot没有指定bootargs,就会使用这里的参数 */
 57
 58     unsigned id[8]; /* timestamp / checksum / sha1 / etc  个人感觉主要用于保存校验数据 */
 59 };
 60
 61 #include <stdio.h>
 62 #include <stdlib.h>
 63 #include <string.h>
 64 #include <unistd.h>
 65 #include <fcntl.h>
 66 #include <errno.h>
 67
 68 #include "mincrypt/sha.h"
 69 #include "bootimg.h"
 70
 71 /**
 72  * 主要用于加载各种需要的文件的函数
 73  */
 74 static void *load_file(const char *fn, unsigned *_sz)
 75 {
 76     char *data;
 77     int sz;
 78     int fd;
 79
 80     data = 0;
 81     fd = open(fn, O_RDONLY);                    //带开文件
 82     if(fd < 0) return 0;
 83
 84     sz = lseek(fd, 0, SEEK_END);                //跳到文件末尾,这样就知道文件的大小了
 85     if(sz < 0) goto oops;
 86
 87     if(lseek(fd, 0, SEEK_SET) != 0) goto oops;  //返回到文件头
 88
 89     data = (char*) malloc(sz);                  //分配和文件一样大小的内存空间
 90     if(data == 0) goto oops;
 91
 92     if(read(fd, data, sz) != sz) goto oops;     //将文件内容读取到内存中
 93     close(fd);
 94
 95     if(_sz) *_sz = sz;                          //相当于返回文件的大小
 96     return data;                                //返回文件数据的首地址
 97
 98 oops:
 99     close(fd);
100     if(data != 0) free(data);
101     return 0;
102 }
103
104 /**
105  * mkbootimg使用说明
106  */
107 int usage(void)
108 {
109     fprintf(stderr,"usage: mkbootimg\n"
110             "       --kernel <filename>\n"
111             "       --ramdisk <filename>\n"
112             "       [ --second <2ndbootloader-filename> ]\n"
113             "       [ --cmdline <kernel-commandline> ]\n"
114             "       [ --board <boardname> ]\n"
115             "       [ --base <address> ]\n"
116             "       [ --pagesize <pagesize> ]\n"
117             "       -o|--output <filename>\n"
118             );
119     return 1;
120 }
121
122
123
124 /**
125  * boot.img中每部分数据都是以页为单位存储的,如果数据不足一页的倍数,
126  * 那么就将该页剩下的空间以0填充
127  */
128 static unsigned char padding[4096] = { 0, };
129
130 int write_padding(int fd, unsigned pagesize, unsigned itemsize)
131 {
132     /**
133      * pagesize一般都是比较大的整数,例如:1k,2k,4k等等,那么
134      * pagesize-1,就变成了由0开始,后面跟了一堆1,例如:
135      * 1k   = 10000000000(二进制);
136      * 1k-1 = 01111111111(二进制);
137      */
138     unsigned pagemask = pagesize - 1;
139     unsigned count;
140
141     /**
142      * 由上面的解析可知,这里是确保itemsize需要填充的0的个数
143      * 小于pagesize并且大于0
144      * itemsize&pagemask相当于itemsize对pagemask取余
145      */
146     if((itemsize & pagemask) == 0) {
147         return 0;
148     }
149
150     /**
151      * 计算出需要填充多少个0, itemsize&pagemask相当于itemsize对pagemask取余
152      */
153     count = pagesize - (itemsize & pagemask);
154
155     if(write(fd, padding, count) != count) {
156         return -1;
157     } else {
158         return 0;
159     }
160 }
161
162 int main(int argc, char **argv)
163 {
164     boot_img_hdr hdr;
165
166     char *kernel_fn = 0;
167     void *kernel_data = 0;
168     char *ramdisk_fn = 0;
169     void *ramdisk_data = 0;
170     char *second_fn = 0;
171     void *second_data = 0;
172     char *cmdline = "";
173     char *bootimg = 0;
174     char *board = "";
175     unsigned pagesize = 2048;                   //默认一页占用2K
176     int fd;
177     SHA_CTX ctx;
178     uint8_t* sha;
179     unsigned base           = 0x10000000;       //基址
180     unsigned kernel_offset  = 0x00008000;
181     unsigned ramdisk_offset = 0x01000000;
182     unsigned second_offset  = 0x00f00000;
183     unsigned tags_offset    = 0x00000100;
184
185     //可执行文件必须有参数,需知道内核文件在那里,ramdisk在那里等等信息
186     argc--;
187     argv++;
188
189     memset(&hdr, 0, sizeof(hdr));              //清空结构体数据
190
191     /**
192      * 获取命令行参数
193      */
194     while(argc > 0){
195         char *arg = argv[0];
196         char *val = argv[1];
197         if(argc < 2) {
198             return usage();
199         }
200         argc -= 2;
201         argv += 2;
202         if(!strcmp(arg, "--output") || !strcmp(arg, "-o")) {
203             bootimg = val;
204         } else if(!strcmp(arg, "--kernel")) {
205             kernel_fn = val;
206         } else if(!strcmp(arg, "--ramdisk")) {
207             ramdisk_fn = val;
208         } else if(!strcmp(arg, "--second")) {
209             second_fn = val;
210         } else if(!strcmp(arg, "--cmdline")) {
211             cmdline = val;
212         } else if(!strcmp(arg, "--base")) {
213             base = strtoul(val, 0, 16);
214         } else if(!strcmp(arg, "--kernel_offset")) {
215             kernel_offset = strtoul(val, 0, 16);
216         } else if(!strcmp(arg, "--ramdisk_offset")) {
217             ramdisk_offset = strtoul(val, 0, 16);
218         } else if(!strcmp(arg, "--second_offset")) {
219             second_offset = strtoul(val, 0, 16);
220         } else if(!strcmp(arg, "--tags_offset")) {
221             tags_offset = strtoul(val, 0, 16);
222         } else if(!strcmp(arg, "--board")) {
223             board = val;
224         } else if(!strcmp(arg,"--pagesize")) {
225             pagesize = strtoul(val, 0, 10);
226             if ((pagesize != 2048) && (pagesize != 4096)) {     //页大小只能是两种情况,2k或者4k
227                 fprintf(stderr,"error: unsupported page size %d\n", pagesize);
228                 return -1;
229             }
230         } else {
231             return usage();
232         }
233     }
234     hdr.page_size = pagesize;           //设置页大小
235
236     /**
237      * 计算各种偏移地址
238      */
239     hdr.kernel_addr =  base + kernel_offset;
240     hdr.ramdisk_addr = base + ramdisk_offset;
241     hdr.second_addr =  base + second_offset;
242     hdr.tags_addr =    base + tags_offset;
243
244     if(bootimg == 0) {
245         fprintf(stderr,"error: no output filename specified\n");
246         return usage();
247     }
248
249     if(kernel_fn == 0) {
250         fprintf(stderr,"error: no kernel image specified\n");
251         return usage();
252     }
253
254     if(ramdisk_fn == 0) {
255         fprintf(stderr,"error: no ramdisk image specified\n");
256         return usage();
257     }
258
259     if(strlen(board) >= BOOT_NAME_SIZE) {
260         fprintf(stderr,"error: board name too large\n");
261         return usage();
262     }
263
264     strcpy(hdr.name, board);    //板子类型
265
266     memcpy(hdr.magic, BOOT_MAGIC, BOOT_MAGIC_SIZE);     //文件类型
267
268     //kernel命令行参数,如果U-Boot没有给出,将是用这里的参数
269     if(strlen(cmdline) > (BOOT_ARGS_SIZE - 1)) {
270         fprintf(stderr,"error: kernel commandline too large\n");
271         return 1;
272     }
273     strcpy((char*)hdr.cmdline, cmdline);
274
275     //加载内核文件,同时获取内核文件的大小
276     kernel_data = load_file(kernel_fn, &hdr.kernel_size);
277     if(kernel_data == 0) {
278         fprintf(stderr,"error: could not load kernel ‘%s‘\n", kernel_fn);
279         return 1;
280     }
281
282     if(!strcmp(ramdisk_fn,"NONE")) {
283         ramdisk_data = 0;
284         hdr.ramdisk_size = 0;
285     } else {
286         ramdisk_data = load_file(ramdisk_fn, &hdr.ramdisk_size);
287         if(ramdisk_data == 0) {
288             fprintf(stderr,"error: could not load ramdisk ‘%s‘\n", ramdisk_fn);
289             return 1;
290         }
291     }
292
293     if(second_fn) {
294         second_data = load_file(second_fn, &hdr.second_size);
295         if(second_data == 0) {
296             fprintf(stderr,"error: could not load secondstage ‘%s‘\n", second_fn);
297             return 1;
298         }
299     }
300
301     /* put a hash of the contents in the header so boot images can be
302      * differentiated based on their first 2k.
303      */
304     /**
305      * 个人理解这里是产生一些校验数据,可以不用关心,不影响阅读
306      */
307     SHA_init(&ctx);
308     SHA_update(&ctx, kernel_data, hdr.kernel_size);
309     SHA_update(&ctx, &hdr.kernel_size, sizeof(hdr.kernel_size));
310     SHA_update(&ctx, ramdisk_data, hdr.ramdisk_size);
311     SHA_update(&ctx, &hdr.ramdisk_size, sizeof(hdr.ramdisk_size));
312     SHA_update(&ctx, second_data, hdr.second_size);
313     SHA_update(&ctx, &hdr.second_size, sizeof(hdr.second_size));
314     sha = SHA_final(&ctx);
315     memcpy(hdr.id, sha,
316            SHA_DIGEST_SIZE > sizeof(hdr.id) ? sizeof(hdr.id) : SHA_DIGEST_SIZE);
317
318     /**
319      * 打开输出目标文件,如果文件不存在,那么就创建该文件,如果存在,那么就清空
320      */
321     fd = open(bootimg, O_CREAT | O_TRUNC | O_WRONLY, 0644);
322     if(fd < 0) {
323         fprintf(stderr,"error: could not create ‘%s‘\n", bootimg);
324         return 1;
325     }
326
327     /**
328      * 这里相当于写入文件头,和写bmp文件差不多的意思
329      */
330     if(write(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) goto fail;
331     if(write_padding(fd, pagesize, sizeof(hdr))) goto fail;
332
333     /**
334      * 接下来按一定顺序写内容
335      */
336     if(write(fd, kernel_data, hdr.kernel_size) != hdr.kernel_size) goto fail;
337     if(write_padding(fd, pagesize, hdr.kernel_size)) goto fail;
338
339     if(write(fd, ramdisk_data, hdr.ramdisk_size) != hdr.ramdisk_size) goto fail;
340     if(write_padding(fd, pagesize, hdr.ramdisk_size)) goto fail;
341
342     if(second_data) {
343         if(write(fd, second_data, hdr.second_size) != hdr.second_size) goto fail;
344         if(write_padding(fd, pagesize, hdr.ramdisk_size)) goto fail;
345     }
346
347     return 0;
348
349 fail:
350     unlink(bootimg);
351     close(fd);
352     fprintf(stderr,"error: failed writing ‘%s‘: %s\n", bootimg,
353             strerror(errno));
354     return 1;
355 }
时间: 2024-11-07 15:31:43

mkbootimg hacking的相关文章

移动安全初探:窃取微信聊天记录、Hacking Android with Metasploit

在这篇文章中我们将讨论如何获取安卓.苹果设备中的微信聊天记录,并演示如何利用后门通过Metasploit对安卓设备进行控制.文章比较基础.可动手性强,有设备的童鞋不妨边阅读文章边操作,希望能激发大家对移动终端的安全兴趣. (文章内容存在一定攻击性,目的在于普及终端安全知识.提高安全意识,如有非法使用,后果自负) “如何获取Android.iPhone手机上的微信聊天记录? ” 0×00 条件: 安卓设备已获取root权限,安装SSHDroid(通过ssh.ftp连接手机) Apple设备越狱,安

I.MX6 recovery mode hacking

/******************************************************************************** * I.MX6 recovery mode hacking * 说明: * 看一下i.MX6 Recovery模式是怎么工作的. * * 2017-6-12 深圳 龙华樟坑村 曾剑锋 ****************************************************************************

Redis代码阅读之Hacking Strings

Hacking Strings The implementation of Redis strings is contained in sds.c ( sds stands for Simple Dynamic Strings ).The C structure sdshdr declared in sds.h represents a Redis string: struct sdshdr { long len; long free; char buf[]; }; The buf charac

我来Hacking JDBC,你并不需要它

我们喜欢和JDBC打交道,以前从未有人这样说过.很严肃的说,JDBC是一个非常优秀的API.这可能是现在Java能够成为一个受欢迎的平台的重要原因之一. 在JDK1.1之前,ODBC出现之前(很久之前的事情了),很难去想象有平台会标准化数据库的访问.在那个时候SQL语言甚至本身还没有标准化,随后出现的面向Java的简单的JDBC API,工作中你需要也就是一下几点: connection:使之能够让领域模型与数据库交互 PreparedStatement:让你能够运行SQL语句的对象 Resul

Rootkit Hacking Technology &amp;&amp; Defence Strategy Research

目录 1. The Purpose Of Rootkit 2. Syscall Hijack 3. LKM Module Hidden 4. Network Communication Hidden 5. File Hidden 6. Process Hidden 7. Hidden Port Remote Reverse Connections 8. Programe Replacing 1. The Purpose Of Rootkit Basically, the purpose of r

google hacking for penetration testers 手册笔记

参考链接: Advanced operators reference Google hacking database 注意:以下内容涉及到大量参考图表,图表均在本人相册<google hacking参数查询表>里 第一章 谷歌搜索基础知识 1.谷歌翻译 可看作透明代理 利用: “翻译此页” 2.黄金法则: 不区分大小写 通配符*代表一个单词,非单一字母或一系列字母,在一单词开始或结尾使用星号和直接使用单词效果相同 保留查询关键字权利 强制搜索:         加引号:“words” 或 用布

OK335xS davinci mdio driver hacking

/******************************************************************************* * OK335xS davinci mdio driver hacking * 说明: * 以前一直也想对网卡驱动的工作原理进行跟踪,这次正好有机会,先跟mdio接口部分 * 的代码. * * 2016-3-1 深圳 南山平山村 曾剑锋 **************************************************

I.MX6 android BatteryService jni hacking

/**************************************************************************** * I.MX6 android BatteryService jni hacking * 声明: * 本文主要是为了知道Android的获取的电源管理的数据的jni是从Linux系统的 * 什么位置获取的,获取的机制是什么. * * 2016-2-22 深圳 南山平山村 曾剑锋 ********************************

OK335xS 网络连接打印信息 hacking

/*********************************************************************** * OK335xS 网络连接打印信息 hacking * 说明: * 当我们插入网线的时候,经常会看到对应的网卡已连接,当前属于10M. * 100M网卡工作状态等等信息,那么这些信息是如何被输出的,工作机制是什么, * 网卡的速度是由phy决定的还是由mac决定的,是不是在phy对应的中断里处理, * 等等,这些内容都需要去确认. * * 2016-