mkbootimg hacking
/**********************************************************************
* 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的更多相关文章
- ★Kali信息收集~ 1.Google Hacking + Github Hacking
一.google hacking site site:cnblogs.com 毒逆天 intitle intitle:login allintitle allintitle:index of alli ...
- 狗汪汪玩转无线电 -- GPS Hacking
狗汪汪玩转无线电 -- GPS Hacking Kevin2600 · 2015/12/09 10:12 0x00 序 GPS Hacking 在过去几年的安全会议上一直都是很受关注的议题. 但往往因 ...
- GnuRadio Hacking②:使用SDR嗅探北欧芯片无线键盘鼠标数据包
0×00 前言 上半年的时候安全公司Bastille Networks(巴士底狱)安全研究员发现大多数无线鼠标和接收器之间的通信信号是不加密的,黑客可对一两百米范围内存在漏洞的无线键鼠进行嗅探甚至劫持 ...
- GnuRadio Hacking①:使用GnuRadio+SDR破解固定码无线遥控
0×01 信号捕获 在这篇文章中,我们将使用GnuRadio+SDR硬件对某品牌型号的无线跳蛋进行无线重放攻击的演示. 市面上常见的无线遥控工作的频段,通常工作在315Mhz.433Mhz,也有少数的 ...
- GSM Hacking Part② :使用SDR捕获GSM网络数据并解密
0×00 在文章第一部分 GSM Hacking Part① :使用SDR扫描嗅探GSM网络 搭建了嗅探GSM流量的环境,在第二部中,我们来讨论如何捕获发短信以及通话过程中的流量,从捕获到的数据中解密 ...
- 移动安全初探:窃取微信聊天记录、Hacking Android with Metasploit
在这篇文章中我们将讨论如何获取安卓.苹果设备中的微信聊天记录,并演示如何利用后门通过Metasploit对安卓设备进行控制.文章比较基础.可动手性强,有设备的童鞋不妨边阅读文章边操作,希望能激发大家对 ...
- Redis代码阅读之Hacking Strings
Hacking Strings The implementation of Redis strings is contained in sds.c ( sds stands for Simple Dy ...
- RFID Hacking④:使用ProxMark3 破解门禁
文中提及的部分技术可能带有一定攻击性,仅供安全学习和教学用途,禁止非法使用! 0×00 前言 国际黑客大会Defcon传统之一:开锁!因为黑客认为锁也是一种安全挑战.我们在黑客题材电影.电视剧中也常常 ...
- Rootkit Hacking Technology && Defence Strategy Research
目录 . The Purpose Of Rootkit . Syscall Hijack . LKM Module Hidden . Network Communication Hidden . Fi ...
随机推荐
- .NET身份证验证
身份证号码编码规则及校验位校验算法 算法地址:http://jingyan.baidu.com/article/7f41ececff944a593d095c8c.html 简单验证长度 /// < ...
- iOS开发中各种关键字的区别
1.一些概念 1.浅Copy:指针的复制,只是多了一个指向这块内存的指针,共用一块内存. 深Copy:内存的复制,两块内存是完全不同的, 也就是两个对象指针分别指向不同的内存,互不干涉. 2.atom ...
- CentOS Redhat Linux安装 Oracle Client 的注意点
1) 安装文件要拷贝到本地文件系统执行 2) 虽然不知道 libXmu是什么,但是安装之后,关联包安装了许多,感觉很省心 yum install libXmu.i686 3) 还有找不到的包的话,用 ...
- axios构建缓存池存储基础数据
项目中经常出现需要多次使用的后端数据,通常的做法是通过变量缓存数据,或者通过类似vuex的东西来进行缓存,但是麻烦在于很可能需要判断一大堆的条件,或者说如果有权限控制的时候数据能否读取也是很麻烦的事情 ...
- 『Python』pycharm常用设置
学习一下pycharm的快捷操作,提升速度,也提升舒适度,笑. 常用快捷键 ctrl + d :复制粘贴本行到下一行 ctrl + y :删除本行 ctrl + 鼠标点击 :跳转 ctrl + / : ...
- hdu-1892-二维BIT
See you~ Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Su ...
- nyoj 1238(BFSor最短路)
最少换乘 时间限制:2000 ms | 内存限制:65535 KB 难度:3 描述 欧洲某城是一个著名的旅游胜地,每年都有成千上万的人前来观光旅行.Dr. Kong决定利用暑假好好游览一番.. ...
- Spring Data Rest如何暴露ID字段
package com.example.demo.config; import com.example.demo.model.Comp; import com.example.demo.model.P ...
- POJ 1014 Dividing (多重可行性背包)
题意 有分别价值为1,2,3,4,5,6的6种物品,输入6个数字,表示相应价值的物品的数量,问一下能不能将物品分成两份,是两份的总价值相等,其中一个物品不能切开,只能分给其中的某一方,当输入六个0是( ...
- iOS UI-团购案例(通过xib文件自定义UITableViewCell)
一.Model #import <Foundation/Foundation.h> @interface Goods : NSObject @property (nonatomic, co ...