/**********************************************************************
* mkbootimg hacking
* 声明:
* 1. 本文源代码来自myzr_android4_2_2_1_1_0.tar.bz2中的mkbootimg.c;
* 2. 通过阅读该源码,可知Android的boot.img合成原理;
*
* 深圳 南山平山村 曾剑鋒 Mon May 4 13:09:49 CST 2015
**********************************************************************/ /* tools/mkbootimg/mkbootimg.c
**
** Copyright 2007, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/ typedef struct boot_img_hdr boot_img_hdr; #define BOOT_MAGIC "ANDROID!"
#define BOOT_MAGIC_SIZE 8
#define BOOT_NAME_SIZE 16
#define BOOT_ARGS_SIZE 512 /**
* 用于暂存需要的数据的结构体
*/
struct boot_img_hdr
{
unsigned char magic[BOOT_MAGIC_SIZE]; //文件类型标识 unsigned kernel_size; /* size in bytes 内核文件大小 */
unsigned kernel_addr; /* physical load addr 内核文件的起始地址 */ unsigned ramdisk_size; /* size in bytes randisk文件的大小*/
unsigned ramdisk_addr; /* physical load addr randisk文件的起始地址 */ unsigned second_size; /* size in bytes */
unsigned second_addr; /* physical load addr */ unsigned tags_addr; /* physical addr for kernel tags */
unsigned page_size; /* flash page size we assume */
unsigned unused[]; /* future expansion: should be 0 */ unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */ unsigned char cmdline[BOOT_ARGS_SIZE]; /* 如果U-Boot没有指定bootargs,就会使用这里的参数 */ unsigned id[]; /* timestamp / checksum / sha1 / etc 个人感觉主要用于保存校验数据 */
}; #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h> #include "mincrypt/sha.h"
#include "bootimg.h" /**
* 主要用于加载各种需要的文件的函数
*/
static void *load_file(const char *fn, unsigned *_sz)
{
char *data;
int sz;
int fd; data = ;
fd = open(fn, O_RDONLY); //带开文件
if(fd < ) return ; sz = lseek(fd, , SEEK_END); //跳到文件末尾,这样就知道文件的大小了
if(sz < ) goto oops; if(lseek(fd, , SEEK_SET) != ) goto oops; //返回到文件头 data = (char*) malloc(sz); //分配和文件一样大小的内存空间
if(data == ) goto oops; if(read(fd, data, sz) != sz) goto oops; //将文件内容读取到内存中
close(fd); if(_sz) *_sz = sz; //相当于返回文件的大小
return data; //返回文件数据的首地址 oops:
close(fd);
if(data != ) free(data);
return ;
} /**
* mkbootimg使用说明
*/
int usage(void)
{
fprintf(stderr,"usage: mkbootimg\n"
" --kernel <filename>\n"
" --ramdisk <filename>\n"
" [ --second <2ndbootloader-filename> ]\n"
" [ --cmdline <kernel-commandline> ]\n"
" [ --board <boardname> ]\n"
" [ --base <address> ]\n"
" [ --pagesize <pagesize> ]\n"
" -o|--output <filename>\n"
);
return ;
} /**
* boot.img中每部分数据都是以页为单位存储的,如果数据不足一页的倍数,
* 那么就将该页剩下的空间以0填充
*/
static unsigned char padding[] = { , }; int write_padding(int fd, unsigned pagesize, unsigned itemsize)
{
/**
* pagesize一般都是比较大的整数,例如:1k,2k,4k等等,那么
* pagesize-1,就变成了由0开始,后面跟了一堆1,例如:
* 1k = 10000000000(二进制);
* 1k-1 = 01111111111(二进制);
*/
unsigned pagemask = pagesize - ;
unsigned count; /**
* 由上面的解析可知,这里是确保itemsize需要填充的0的个数
* 小于pagesize并且大于0
* itemsize&pagemask相当于itemsize对pagemask取余
*/
if((itemsize & pagemask) == ) {
return ;
} /**
* 计算出需要填充多少个0, itemsize&pagemask相当于itemsize对pagemask取余
*/
count = pagesize - (itemsize & pagemask); if(write(fd, padding, count) != count) {
return -;
} else {
return ;
}
} int main(int argc, char **argv)
{
boot_img_hdr hdr; char *kernel_fn = ;
void *kernel_data = ;
char *ramdisk_fn = ;
void *ramdisk_data = ;
char *second_fn = ;
void *second_data = ;
char *cmdline = "";
char *bootimg = ;
char *board = "";
unsigned pagesize = ; //默认一页占用2K
int fd;
SHA_CTX ctx;
uint8_t* sha;
unsigned base = 0x10000000; //基址
unsigned kernel_offset = 0x00008000;
unsigned ramdisk_offset = 0x01000000;
unsigned second_offset = 0x00f00000;
unsigned tags_offset = 0x00000100; //可执行文件必须有参数,需知道内核文件在那里,ramdisk在那里等等信息
argc--;
argv++; memset(&hdr, , sizeof(hdr)); //清空结构体数据 /**
* 获取命令行参数
*/
while(argc > ){
char *arg = argv[];
char *val = argv[];
if(argc < ) {
return usage();
}
argc -= ;
argv += ;
if(!strcmp(arg, "--output") || !strcmp(arg, "-o")) {
bootimg = val;
} else if(!strcmp(arg, "--kernel")) {
kernel_fn = val;
} else if(!strcmp(arg, "--ramdisk")) {
ramdisk_fn = val;
} else if(!strcmp(arg, "--second")) {
second_fn = val;
} else if(!strcmp(arg, "--cmdline")) {
cmdline = val;
} else if(!strcmp(arg, "--base")) {
base = strtoul(val, , );
} else if(!strcmp(arg, "--kernel_offset")) {
kernel_offset = strtoul(val, , );
} else if(!strcmp(arg, "--ramdisk_offset")) {
ramdisk_offset = strtoul(val, , );
} else if(!strcmp(arg, "--second_offset")) {
second_offset = strtoul(val, , );
} else if(!strcmp(arg, "--tags_offset")) {
tags_offset = strtoul(val, , );
} else if(!strcmp(arg, "--board")) {
board = val;
} else if(!strcmp(arg,"--pagesize")) {
pagesize = strtoul(val, , );
if ((pagesize != ) && (pagesize != )) { //页大小只能是两种情况,2k或者4k
fprintf(stderr,"error: unsupported page size %d\n", pagesize);
return -;
}
} else {
return usage();
}
}
hdr.page_size = pagesize; //设置页大小 /**
* 计算各种偏移地址
*/
hdr.kernel_addr = base + kernel_offset;
hdr.ramdisk_addr = base + ramdisk_offset;
hdr.second_addr = base + second_offset;
hdr.tags_addr = base + tags_offset; if(bootimg == ) {
fprintf(stderr,"error: no output filename specified\n");
return usage();
} if(kernel_fn == ) {
fprintf(stderr,"error: no kernel image specified\n");
return usage();
} if(ramdisk_fn == ) {
fprintf(stderr,"error: no ramdisk image specified\n");
return usage();
} if(strlen(board) >= BOOT_NAME_SIZE) {
fprintf(stderr,"error: board name too large\n");
return usage();
} strcpy(hdr.name, board); //板子类型 memcpy(hdr.magic, BOOT_MAGIC, BOOT_MAGIC_SIZE); //文件类型 //kernel命令行参数,如果U-Boot没有给出,将是用这里的参数
if(strlen(cmdline) > (BOOT_ARGS_SIZE - )) {
fprintf(stderr,"error: kernel commandline too large\n");
return ;
}
strcpy((char*)hdr.cmdline, cmdline); //加载内核文件,同时获取内核文件的大小
kernel_data = load_file(kernel_fn, &hdr.kernel_size);
if(kernel_data == ) {
fprintf(stderr,"error: could not load kernel '%s'\n", kernel_fn);
return ;
} if(!strcmp(ramdisk_fn,"NONE")) {
ramdisk_data = ;
hdr.ramdisk_size = ;
} else {
ramdisk_data = load_file(ramdisk_fn, &hdr.ramdisk_size);
if(ramdisk_data == ) {
fprintf(stderr,"error: could not load ramdisk '%s'\n", ramdisk_fn);
return ;
}
} if(second_fn) {
second_data = load_file(second_fn, &hdr.second_size);
if(second_data == ) {
fprintf(stderr,"error: could not load secondstage '%s'\n", second_fn);
return ;
}
} /* put a hash of the contents in the header so boot images can be
* differentiated based on their first 2k.
*/
/**
* 个人理解这里是产生一些校验数据,可以不用关心,不影响阅读
*/
SHA_init(&ctx);
SHA_update(&ctx, kernel_data, hdr.kernel_size);
SHA_update(&ctx, &hdr.kernel_size, sizeof(hdr.kernel_size));
SHA_update(&ctx, ramdisk_data, hdr.ramdisk_size);
SHA_update(&ctx, &hdr.ramdisk_size, sizeof(hdr.ramdisk_size));
SHA_update(&ctx, second_data, hdr.second_size);
SHA_update(&ctx, &hdr.second_size, sizeof(hdr.second_size));
sha = SHA_final(&ctx);
memcpy(hdr.id, sha,
SHA_DIGEST_SIZE > sizeof(hdr.id) ? sizeof(hdr.id) : SHA_DIGEST_SIZE); /**
* 打开输出目标文件,如果文件不存在,那么就创建该文件,如果存在,那么就清空
*/
fd = open(bootimg, O_CREAT | O_TRUNC | O_WRONLY, );
if(fd < ) {
fprintf(stderr,"error: could not create '%s'\n", bootimg);
return ;
} /**
* 这里相当于写入文件头,和写bmp文件差不多的意思
*/
if(write(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) goto fail;
if(write_padding(fd, pagesize, sizeof(hdr))) goto fail; /**
* 接下来按一定顺序写内容
*/
if(write(fd, kernel_data, hdr.kernel_size) != hdr.kernel_size) goto fail;
if(write_padding(fd, pagesize, hdr.kernel_size)) goto fail; if(write(fd, ramdisk_data, hdr.ramdisk_size) != hdr.ramdisk_size) goto fail;
if(write_padding(fd, pagesize, hdr.ramdisk_size)) goto fail; if(second_data) {
if(write(fd, second_data, hdr.second_size) != hdr.second_size) goto fail;
if(write_padding(fd, pagesize, hdr.ramdisk_size)) goto fail;
} return ; fail:
unlink(bootimg);
close(fd);
fprintf(stderr,"error: failed writing '%s': %s\n", bootimg,
strerror(errno));
return ;
}

mkbootimg hacking的更多相关文章

  1. ★Kali信息收集~ 1.Google Hacking + Github Hacking

    一.google hacking site site:cnblogs.com 毒逆天 intitle intitle:login allintitle allintitle:index of alli ...

  2. 狗汪汪玩转无线电 -- GPS Hacking

    狗汪汪玩转无线电 -- GPS Hacking Kevin2600 · 2015/12/09 10:12 0x00 序 GPS Hacking 在过去几年的安全会议上一直都是很受关注的议题. 但往往因 ...

  3. GnuRadio Hacking②:使用SDR嗅探北欧芯片无线键盘鼠标数据包

    0×00 前言 上半年的时候安全公司Bastille Networks(巴士底狱)安全研究员发现大多数无线鼠标和接收器之间的通信信号是不加密的,黑客可对一两百米范围内存在漏洞的无线键鼠进行嗅探甚至劫持 ...

  4. GnuRadio Hacking①:使用GnuRadio+SDR破解固定码无线遥控

    0×01 信号捕获 在这篇文章中,我们将使用GnuRadio+SDR硬件对某品牌型号的无线跳蛋进行无线重放攻击的演示. 市面上常见的无线遥控工作的频段,通常工作在315Mhz.433Mhz,也有少数的 ...

  5. GSM Hacking Part② :使用SDR捕获GSM网络数据并解密

    0×00 在文章第一部分 GSM Hacking Part① :使用SDR扫描嗅探GSM网络 搭建了嗅探GSM流量的环境,在第二部中,我们来讨论如何捕获发短信以及通话过程中的流量,从捕获到的数据中解密 ...

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

    在这篇文章中我们将讨论如何获取安卓.苹果设备中的微信聊天记录,并演示如何利用后门通过Metasploit对安卓设备进行控制.文章比较基础.可动手性强,有设备的童鞋不妨边阅读文章边操作,希望能激发大家对 ...

  7. Redis代码阅读之Hacking Strings

    Hacking Strings The implementation of Redis strings is contained in sds.c ( sds stands for Simple Dy ...

  8. RFID Hacking④:使用ProxMark3 破解门禁

    文中提及的部分技术可能带有一定攻击性,仅供安全学习和教学用途,禁止非法使用! 0×00 前言 国际黑客大会Defcon传统之一:开锁!因为黑客认为锁也是一种安全挑战.我们在黑客题材电影.电视剧中也常常 ...

  9. Rootkit Hacking Technology && Defence Strategy Research

    目录 . The Purpose Of Rootkit . Syscall Hijack . LKM Module Hidden . Network Communication Hidden . Fi ...

随机推荐

  1. jQuery双击编辑td数据

    html <td class="remark" style="width: 200px;"> {$vo.remark} </td> js ...

  2. 机器学习 Matplotlib库入门

    2017-07-21 15:22:05 Matplotlib库是一个优秀的python的数据可视化的第三方类库,其中的pyplot支持了类似matlab的图像输出操作.matplotlib.pyplo ...

  3. smarty课程---smarty3的安装和使用

    smarty课程---smarty3的安装和使用 一.总结 一句话总结:smarty 是什么,就不多说了,用过php,接触过php的人都对smarty 再熟悉不过了.它是一个很强大的代码分离软件,作为 ...

  4. getpagesize.c:32: __getpagesize: Assertion `_rtld_global_ro._dl_pagesize != 0' failed

    为arm 编译 mysql , 执行的时候出现了这个问题. 好像是个bug, https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=626379 重新编译 ...

  5. 关于一致性hash详细

    一致性哈希算法在1997年由麻省理工学院提出的一种分布式哈希(DHT)实现算法,设计目标是为了解决因特网中的热点(Hot spot)问题,初衷和CARP十分类似.一致性哈希修正了CARP使用的简 单哈 ...

  6. 20170731xlVba根据数据表和模板表生成新表

    Public Sub SplitData() Dim Wb As Workbook Dim Sht As Worksheet Dim NewSht As Worksheet Dim arr As Va ...

  7. RabbitMq windows 安装

    参考官方网址: http://www.rabbitmq.com/install-windows-manual.html http://www.rabbitmq.com/install-windows. ...

  8. Spring Boot 文档

    本节对 Spring Boot 的参考文档做了一个简单概述.本章节对全文的参考手册进行内容上的一些索引. 你可以参考本节,从头到尾依次阅读该文档,也可以跳过不感兴趣的内容. Spring Boot 参 ...

  9. linux 不解压日志压缩包直接搜索里面的内容

  10. sql去重;同一条数据出现多条取一条的sql语句

    理论上相同数据个别字段值不同重复问题: 1.某字段重复,其他字段值不同时,按重复字段分组只取一条的sql语句(eg:相同的数据某个字段值有差别导致存储两条或多条无意义重复数据的情况)select s. ...