mirror of
https://github.com/adron-s/mtik_initrd_hacks.git
synced 2026-01-27 16:17:16 +01:00
add support for RouterOS 7.1rc4 and aarch64(arm64 - RB5009)
This commit is contained in:
parent
21d602c331
commit
f08d8a4a6c
15 changed files with 172 additions and 28 deletions
36
README.md
36
README.md
|
|
@ -1,20 +1,48 @@
|
|||
# Mikrotik netboot/initrd jailbreak
|
||||
|
||||
(C) Sergey Sergeev, 2019-2020
|
||||
(C) Sergey Sergeev, 2019-2021
|
||||
|
||||
All that you do is at your own risk!
|
||||
The author has not liable for any of you actions and their consequences!
|
||||
This code is presented as is and is solely for educational purposes ONLY!
|
||||
This code is presented as is and is solely for educational purposes ONLY! -
|
||||
to investigate the internals of a Linux distro called RouterOS.
|
||||
In particular, to facilitate porting OpenWRT to new Mikrotik devices.
|
||||
For injection(jailbreak) to RouterOS is used the standard(for almost any Linux)
|
||||
initrd mechanism. Native binary init file is replaced with a fake one. This modified
|
||||
init forks itself (spawning its daemon copy) and then pass control to the original init
|
||||
process. The begotten daemon copy waits for the filesystem to initialize and installs
|
||||
busybox and then launch the telnetd service. To run Linux kernel with modified init file,
|
||||
uses the standard RouterBOOT ability - loading via the network using dhcp/bootp and tftp
|
||||
server. dhcp/bootp server can be deployed on another device with RouterOS and OpenWRT or
|
||||
even tftp32 program. For a one-time launch with tftp, You can use this commands in RouterOS:
|
||||
/system/routerboard/settings/set boot-device=try-ethernet-once-then-nand
|
||||
/system/reboot
|
||||
|
||||
0) Use RouterOS 6.44 or 6.45.6 or 7.0b1!
|
||||
and after that do the following:
|
||||
0) Use RouterOS 6.44 or 6.45.6 or 7.x(7.1rc4)!
|
||||
1) Upload(using FTP) content of ./for_ftp_upload/pub/* to /pub
|
||||
(or /flash or /flash/rw/disk/pub) folder on target RouterOS device
|
||||
2) Netboot(via bootp and tftp) with kernel-new.elf
|
||||
3) telnet x.x.x.x 22111
|
||||
|
||||
Cyrillic:
|
||||
Все что вы делаете, вы делаете на свой страх и риск!
|
||||
Автор не несет никакой ответственности за ваши действия и их последствия!
|
||||
Данный код представляется as-is и исключительно в учебных целях!
|
||||
Данный код представляется as-is и исключительно в учебных целях -
|
||||
для исследования внутреннего устройства дистрибутива Linux под названием
|
||||
RouterOS. В частностия для для облегчения портирования OpenWRT на новые
|
||||
устройства от Mikrotik. Для внедрения(jailbreak-а) в RouterOS используется
|
||||
стандартный(практически для любого Linux-а) механизм initrd. Родной бинарный
|
||||
файл init-а заменяется на поддельный. Этот измененный init форкает себя(порождая
|
||||
свою копию-демона) и дальше передает управление родному init процессу. Порожденная
|
||||
копия-демон ожидает инициализации файловой системы и запускает скрипт установки
|
||||
busybox с последующим запуском telnetd сервиса. Для запуска ядра Linux с измененным
|
||||
init файлом используется штатный механизм RouterBOOT - загрузка через сеть
|
||||
с использованием dhcp/bootp и tftp сервера. dhcp/bootp сервером может выступать
|
||||
как другое устройство с RouterOS так и OpenWRT или даже программа tftp32.
|
||||
Для единоразового запуска с tftp вы можете выполнить следующие команды в RouterOS:
|
||||
/system/routerboard/settings/set boot-device=try-ethernet-once-then-nand
|
||||
/system/reboot
|
||||
|
||||
For Developers:
|
||||
Place routeros-XXX.mpk to ./ros/
|
||||
|
|
|
|||
BIN
cpio-fs-aarch64/bin/busybox
Executable file
BIN
cpio-fs-aarch64/bin/busybox
Executable file
Binary file not shown.
1
cpio-fs-aarch64/bin/busybox.readme
Normal file
1
cpio-fs-aarch64/bin/busybox.readme
Normal file
|
|
@ -0,0 +1 @@
|
|||
busybox скомпилен вот тут: /home/prog/openwrt/switch/mikrotik-tools-master/busybox-arm-soft-float
|
||||
BIN
cpio-fs-aarch64/init
Executable file
BIN
cpio-fs-aarch64/init
Executable file
Binary file not shown.
BIN
cpio-fs-aarch64/oldinit
Executable file
BIN
cpio-fs-aarch64/oldinit
Executable file
Binary file not shown.
3
cpio-fs-aarch64/readme.txt
Normal file
3
cpio-fs-aarch64/readme.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
binary files from routeros arm64 7.1rc4!
|
||||
routeros needs armv7 compiler!
|
||||
In fact, the entire user space in it is still use 32bit!
|
||||
|
|
@ -23,7 +23,9 @@ static unsigned char data[64 * 1024 * 1024];
|
|||
int main(int argc, char *argv[]){
|
||||
int fd;
|
||||
unsigned char *p;
|
||||
void *last_p;
|
||||
void *last_p, *end;
|
||||
size_t rest_size;
|
||||
size_t total_payload_size = 0;
|
||||
int count = 0;
|
||||
size_t len;
|
||||
if(argc !=2)
|
||||
|
|
@ -38,19 +40,42 @@ int main(int argc, char *argv[]){
|
|||
die(-3);
|
||||
printf("Successfully readed %zd bytes\n", len);
|
||||
printf("Begin of search...\n");
|
||||
last_p = (void*)data;
|
||||
end = (void*)data + len;
|
||||
last_p = data;
|
||||
p = (void*)data;
|
||||
p += 0x2F4D;
|
||||
//p += 0x2F4D;
|
||||
do{
|
||||
if(p[4] == 0x7F && p[3] == 0xFF && p[2] == 0x80 && p[1] == 0x00 && p[0] == 0x00){
|
||||
//if(1){
|
||||
printf("%04d: 0x%08lx: %lu: %02X %02X %02X %02X %02X\n", count++,
|
||||
((void*)p - (void*)data),
|
||||
(void*)p - last_p, p[4], p[3], p[2], p[1], p[0]);
|
||||
if(*(uint64_t *)p == 0x040A000000010007LLU){ //check for kernel start magic value
|
||||
printf("Kernel start magic is found at: 0x%08lx\n", (void*)data - (void*)p);
|
||||
last_p = p;
|
||||
last_p = p = (void*)p + 15;
|
||||
}
|
||||
p = (void *)p + 1;
|
||||
}while((void*)p + sizeof(data[0]) - (void*)data < len);
|
||||
|
||||
//chunk header(5 bytes)
|
||||
//if(p[4] == 0x7F && p[3] == 0xFF && p[2] == 0x80 && p[1] == 0x00 && p[0] == 0x00){
|
||||
//if(p[4] == 0x7F && p[3] == 0xFF && p[0] == 0x00){
|
||||
if (p[0] == 0 || p[0] == 1) {
|
||||
int prev_block_size = p != last_p ? ((void*)p - last_p) - 5 : 0;
|
||||
int hdr_chunk_len = p[2] << 8 | p[1];
|
||||
total_payload_size += hdr_chunk_len;
|
||||
if (prev_block_size != 0x8000 && last_p != p)
|
||||
printf(" !!! Unusual chunk size: %d !!!\n", prev_block_size);
|
||||
printf("%04d: 0x%08lx: (%d + 5): %02X %02X %02X %02X %02X\n", count++,
|
||||
((void*)p - (void*)data), hdr_chunk_len,
|
||||
p[4], p[3], p[2], p[1], p[0]);
|
||||
last_p = p;
|
||||
rest_size = end - ((void*)p + 5 + hdr_chunk_len);
|
||||
if (p[0] == 1)
|
||||
break;
|
||||
p += 5 + hdr_chunk_len;
|
||||
}
|
||||
//p = (void *)p + 1;
|
||||
}while((void*)p + 4 < end);
|
||||
p = end - rest_size;
|
||||
//printf("Last tailed chunk size: %d + 5: [ %02x %02x ]\n", p[2] << 8 | p[1], p[1], p[2]);
|
||||
printf("Payload total size is: %zd\n", total_payload_size);
|
||||
printf("Garbage(tail) size is: %zd\n", rest_size);
|
||||
printf("Total blocks is: %d\n", count);
|
||||
printf("...search is Ended\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,19 +10,29 @@ void die(int code){
|
|||
exit(code);
|
||||
}
|
||||
|
||||
static inline uint32_t swab32(uint32_t x)
|
||||
{
|
||||
return x << 24 | x >> 24 |
|
||||
(x & (uint32_t)0x0000ff00UL)<<8 |
|
||||
(x & (uint32_t)0x00ff0000UL)>>8;
|
||||
}
|
||||
|
||||
static unsigned char data[64 * 1024 * 1024];
|
||||
|
||||
/* kernel header is 20 bytes:
|
||||
kernel start magic(8 bytes) - 07 00 01 00 00 00 0A 04
|
||||
kernel size(4 bytes) - variable
|
||||
tail magic(3 bytes) - 00 78 01
|
||||
chunks header or splitter(5 bytes) - 00 00 80 FF 7F or something else(for last chunk)
|
||||
chunks header-splitter(5 bytes) - 00 00 80 FF 7F or something else(for last chunk)
|
||||
*/
|
||||
void *do_kernel_start_search(unsigned char *p, void *end){
|
||||
uint64_t *k;
|
||||
typeof(p) start = p;
|
||||
do{
|
||||
k = (void*)p;
|
||||
if(*k == 0x040A000000010007LLU){ //check for kernel start magic value
|
||||
printf("Kernel header(start magic) is found at: 0x%08lx\n", (void *)p - (void*)start);
|
||||
//printf("Kernel size: %u bytes\n", swab32(*(uint32_t *)(k + 1))); //TODO: !!!! ??? !!!
|
||||
k = (void *)k + 8 + 4; //to tail magic
|
||||
/* printf("0x%08lx: %02X %02X %02X, %016lX\n", ((void*)p - (void*)data),
|
||||
p[12], p[13], p[14], *k); */
|
||||
|
|
@ -35,7 +45,7 @@ void *do_kernel_start_search(unsigned char *p, void *end){
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void *do_kernel_extract(unsigned char *p, void *end, char *file_name){
|
||||
static inline void *do_kernel_extract_OLD(unsigned char *p, void *end, char *file_name){
|
||||
int fd;
|
||||
fd = open(file_name, O_WRONLY | O_CREAT);
|
||||
size_t len;
|
||||
|
|
@ -73,6 +83,42 @@ void *do_kernel_extract(unsigned char *p, void *end, char *file_name){
|
|||
close(fd);
|
||||
}
|
||||
|
||||
void *do_kernel_extract(unsigned char *p, void *end, char *file_name){
|
||||
int fd;
|
||||
typeof(p) start = p;
|
||||
fd = open(file_name, O_WRONLY | O_CREAT);
|
||||
size_t len, chunk_size, total_size = 0;
|
||||
int count = 0;
|
||||
if(fd < 0)
|
||||
die(-11);
|
||||
do {
|
||||
int is_last_chunk = p[0] == 1;
|
||||
chunk_size = p[2] << 8 | p[1]; //extract current chunk len from chunk header(5 bytes)
|
||||
printf("%04d: 0x%08lx: (%zd + 5): %02X %02X %02X %02X %02X\n", count,
|
||||
(void *)p - (void*)start, chunk_size, p[4], p[3], p[2], p[1], p[0]);
|
||||
p += 5; //skip chunk header(splitter)
|
||||
if (chunk_size > (end - (void*)p)) {
|
||||
printf(" !!! Current chunk size is bigger that rest data size ! %zd > %zd !\n"
|
||||
" Source file was truncated ???\n", chunk_size, (end - (void*)p));
|
||||
break;
|
||||
}
|
||||
len = write(fd, p, chunk_size);
|
||||
//printf("writing chunk %d, len = %zd bytes\n", count, len);
|
||||
count++;
|
||||
if (len != chunk_size) {
|
||||
fprintf(stderr, "write to result file '%s' len %zd != %zd\n", file_name, chunk_size, len);
|
||||
break;
|
||||
}
|
||||
total_size += len;
|
||||
p += chunk_size;
|
||||
if (is_last_chunk)
|
||||
break;
|
||||
} while ((void*)p + 5 <= end);
|
||||
printf("Successfully writed %d chunks(%zd bytes) to '%s'\n", count,
|
||||
total_size, file_name);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
int fd;
|
||||
void *start;
|
||||
|
|
|
|||
Binary file not shown.
24
globals.sh
24
globals.sh
|
|
@ -1,11 +1,23 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
#(C) Sergey Sergeev aka adron, 2019
|
||||
#(C) Sergey Sergeev aka adron, 2019-2021
|
||||
#
|
||||
|
||||
TARGET_ARCH="arm"
|
||||
#rb5009
|
||||
TARGET_ARCH="aarch64"
|
||||
#rb3011(ipq806x), rb450dx4(ipq401x)
|
||||
#TARGET_ARCH="arm"
|
||||
#ath79, ramips
|
||||
#TARGET_ARCH="mips"
|
||||
|
||||
TOOLS_BINS_PREFIX="openwrt-linux"
|
||||
|
||||
[ ${TARGET_ARCH} = "aarch64" ] && {
|
||||
OPENWRT_DIR=/home/prog/openwrt/2021-openwrt/last-openwrt/openwrt
|
||||
export STAGING_DIR=$OPENWRT_DIR/staging_dir/toolchain-aarch64_cortex-a72_gcc-11.2.0_musl
|
||||
TOOLS_BINS_PREFIX="$TOOLS_BINS_PREFIX-musl"
|
||||
}
|
||||
|
||||
[ ${TARGET_ARCH} = "arm" ] && {
|
||||
OPENWRT_DIR=/home/prog/openwrt/lede-all/2019-openwrt-all/openwrt-ipq806x
|
||||
export STAGING_DIR=$OPENWRT_DIR/staging_dir/toolchain-arm_cortex-a15+neon-vfpv4_gcc-7.4.0_musl_eabi
|
||||
|
|
@ -19,7 +31,7 @@ TARGET_ARCH="arm"
|
|||
export STAGING_DIR=$OPENWRT_DIR/staging_dir/toolchain-mips_24kc_gcc-7.3.0_musl
|
||||
}
|
||||
|
||||
GCC=$STAGING_DIR/bin/${TARGET_ARCH}-openwrt-linux-gcc
|
||||
OBJDUMP=$STAGING_DIR/bin/${TARGET_ARCH}-openwrt-linux-objdump
|
||||
OBJCOPY=$STAGING_DIR/bin/${TARGET_ARCH}-openwrt-linux-objcopy
|
||||
LD=$STAGING_DIR/bin/${TARGET_ARCH}-openwrt-linux-ld
|
||||
GCC=$STAGING_DIR/bin/${TARGET_ARCH}-${TOOLS_BINS_PREFIX}-gcc
|
||||
OBJDUMP=$STAGING_DIR/bin/${TARGET_ARCH}-${TOOLS_BINS_PREFIX}-objdump
|
||||
OBJCOPY=$STAGING_DIR/bin/${TARGET_ARCH}-${TOOLS_BINS_PREFIX}-objcopy
|
||||
LD=$STAGING_DIR/bin/${TARGET_ARCH}-${TOOLS_BINS_PREFIX}-ld
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
#(C) Sergey Sergeev aka adron, 2019
|
||||
#(C) Sergey Sergeev aka adron, 2019-2021
|
||||
#
|
||||
|
||||
. ../globals.sh
|
||||
|
||||
GCC_ARGS="-static"
|
||||
#for 7.0rc1 we need gcc with soft-float ONLY!
|
||||
#apt-get install gcc-arm-linux-gnueabi
|
||||
[ ${TARGET_ARCH} = "arm" ] && {
|
||||
|
|
@ -12,9 +13,19 @@
|
|||
OBJCOPY=arm-linux-gnueabi-objcopy
|
||||
}
|
||||
|
||||
[ ${TARGET_ARCH} = "aarch64" ] && {
|
||||
GCC=arm-linux-gnueabihf-gcc
|
||||
OBJCOPY=arm-linux-gnueabihf-objcopy
|
||||
# GCC_ARGS="$GCC_ARGS -mfloat-abi=soft"
|
||||
}
|
||||
|
||||
CPIO_FS="../cpio-fs-${TARGET_ARCH}"
|
||||
|
||||
$GCC -static ./init.c -o ${CPIO_FS}/init
|
||||
#$GCC $GCC_ARGS ./test.c -o ./test
|
||||
#$OBJCOPY --strip-all ./test ./test
|
||||
#exit 0
|
||||
|
||||
$GCC $GCC_ARGS ./init.c -o ${CPIO_FS}/init
|
||||
$OBJCOPY --strip-all ${CPIO_FS}/init ${CPIO_FS}/init
|
||||
|
||||
#exit 0
|
||||
|
|
|
|||
|
|
@ -68,8 +68,8 @@ int main(int argc, char *argv[]){
|
|||
pid_t pid;
|
||||
argv[0] = "/oldinit";
|
||||
|
||||
environ[0] = "PATH=/sbin:/bin";
|
||||
environ[1] = NULL;
|
||||
//environ[0] = "PATH=/sbin:/bin";
|
||||
//environ[1] = NULL;
|
||||
|
||||
pid = fork();
|
||||
if(pid == (pid_t)0){ //child
|
||||
|
|
|
|||
BIN
ready-kernels/kernel-new-7.1b4-arm64.elf
Executable file
BIN
ready-kernels/kernel-new-7.1b4-arm64.elf
Executable file
Binary file not shown.
|
|
@ -48,6 +48,7 @@ extract_kernel_elf(){
|
|||
local offsets
|
||||
local offset
|
||||
local kernel_elf_size=0
|
||||
local garbage_size=70
|
||||
offsets=`kernel_bin_binwalk | sed -n 's/ELF,//p' | sed -n 's/^\([0-9]\+\).*/\1/p'`
|
||||
local elf_last_offset
|
||||
local first_xz_offset
|
||||
|
|
@ -60,6 +61,7 @@ extract_kernel_elf(){
|
|||
first_xz_offset=${offset}
|
||||
break
|
||||
done
|
||||
echo "${elf_last_offset} - ${first_xz_offset}"
|
||||
#elf size without xz
|
||||
kernel_elf_size=$((${first_xz_offset}-${elf_last_offset}))
|
||||
local p
|
||||
|
|
@ -68,10 +70,15 @@ extract_kernel_elf(){
|
|||
size=$(get_file_size ./bins/kernel.p${p}.xz)
|
||||
kernel_elf_size=$((${kernel_elf_size}+${size}))
|
||||
done
|
||||
#dd if=./bins/kernel.bin bs=1 skip=${elf_last_offset} of=./bins/kernel-all.elf
|
||||
dd if=./bins/kernel.bin bs=1 skip=${elf_last_offset} count=${kernel_elf_size} of=./bins/kernel.elf
|
||||
[ -f ./bins/p3-garbage.bin ] && {
|
||||
offset=484 #[ 45 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 ] <-- ${offset}
|
||||
dd if=./bins/p3-garbage.bin bs=${offset} count=1 >> ./bins/kernel.elf
|
||||
size=$(get_file_size ./bins/p3-garbage.bin)
|
||||
#some of this data may be related to the elf (for 64-bit kernels - RB5009, ...\)
|
||||
[ $size -gt $garbage_size ] && {
|
||||
offset=$((size-garbage_size))
|
||||
dd if=./bins/p3-garbage.bin bs=${offset} count=1 >> ./bins/kernel.elf
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -95,6 +102,10 @@ extract_kernel_cpiofs(){
|
|||
cp ./init ./oldinit
|
||||
}
|
||||
|
||||
#extract_kernel_elf
|
||||
#unpack_kernel_bin
|
||||
#exit 0
|
||||
|
||||
unpack_kernel_bin
|
||||
|
||||
( xz -dc --single-stream > ./bins/initramfs.cpio && cat > ./bins/p3-garbage.bin ) < ./bins/kernel.p3.xz
|
||||
|
|
|
|||
7
x1/README.txt
Normal file
7
x1/README.txt
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
These files are obtained by the following commands:
|
||||
dd if=./ros/routeros-7.1rc4-arm.npk of=x1/x1-32b.bin bs=$((0x009ee000)) skip=1
|
||||
dd if=./ros/routeros-7.1rc4-arm.npk of=x1/x1-64b.bin bs=$((0x00a06000)) skip=1
|
||||
0x009ee000 and 0x00a06000 is obtained from ./unpack-npk.sh ./ros/routeros-7.1rc4-arm.npk:
|
||||
..
|
||||
Kernel header(start magic) is found at: 0x009ee000
|
||||
.
|
||||
Loading…
Add table
Reference in a new issue