/**********************************************************************
* 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. 使用 XPath 选择器

    在前面的内容中,我们掌握了一些 CSS 选择器和它们的使用方法,以及 rvest 包中用于提取网页内容的函数.一般来说,CSS 选择器足够满足绝大部分的 HTML 节点匹配的需要.但是,当需要根据某些 ...

  2. 语言小知识-Java ArrayList类 深度解析

    · 问题 1:ArrayList 的 size 和 capacity 怎么理解? 如果把 ArrayList 看作一个杯子的话,capacity 就是杯子的容积,也就是代表杯子能装多少东西,而 siz ...

  3. 关于C和C++

    最开始学的就是C和C++,但只是学过,根本就不知道怎么使用. 后来接触了Python和Perl才知道怎么将编程应用于实际需求当中,读取文件,存放到数据结构,处理,输出. 但脚本语言有其固有的缺点,不能 ...

  4. 表达谱(DGE)测序与转录组测序的差别

    DGE-seq和普通的transcriptomic profiling相比较有什么不同,有什么特点? DGE就是用酶将mRNA切断,只使用靠近poly A的一小段RNA去测序. #1 由于不是测定mR ...

  5. Howto: 使用ImageBrush替换PictureMarkerSymbol以加强graphic显示性能

      软件: ArcGIS API for Microsoft Silverlight/WPF 9.3.1 操作系统: N/A 摘要:          ArcGIS API for Microsoft ...

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

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

  7. fzu1901 kmp

    For each prefix with length P of a given string S,if S[i]=S[i+P] for i in [0..SIZE(S)-p-1], then the ...

  8. 用DFS 解决全排列问题的思想详解

    首先考虑一道奥数题目: □□□ + □□□ = □□□,要将数字1~9分别填入9个□中,使得等式成立.例如173+286 = 459.请输出所有合理的组合的个数. 我们或许可以枚举每一位上所有的数,然 ...

  9. C#图片转换成二进制流并且保存到sql server数据库

    注意:我要存储文件二进制流的列的类型是text,不是image类型. 我已经实现了从数据库中读取text类型的二进制流,,现在就是不知道怎么存进去. 我的部分关键代码: StreamReader sr ...

  10. OAF中为MessageTextInput添加加事件处理

    需求:现在OAF页面上有俩输入框,单价,数量,根据单价数量,自动计算MessageStyledText金额中的值,对应的基于EO的VO的字段为UnitPrice,Quantity,Total. 实现方 ...