📜 ⬆️ ⬇️

Manual editing of uboot-elf in the name of DHCP and SSH

Once I got into the hands of a piece of hardware AEWIN SCB-3240, which should forever settle in the server rack in order to never touch it again. It was planned to use it not for its intended purpose, but for the purpose of testing our product. Kaspersky Lab has a tradition of releasing an antivirus SDK for every conceivable platform, as long as there is something there that can compile the code in C. Accordingly, the SDK needs anti-virus databases that, despite the fact that they are the same for all products, are still it is necessary to test - in case of an error in the SDK itself, or the database loader, or some features of the platform, or ... In general, a million reasons. And in order to learn about problems, we learned a little earlier than from new cases in support, the last line of defense are dozens of pieces of hardware that check each set of anti-virus databases for performance.

That is, of interest were not the capabilities of AEWIN to work with the network, but only its essence in the form of MIPS / Linux. The problem was that the piece of iron did not provide for any adequate connection. Everything that was offered to me - console port, telnet and any dhcp.

Unfortunately, the worst fears were not in vain. The device had no permanent storage, and it lived only from powering up to rebooting, each time deploying a reference image.
')
Total that I needed. To teach getting an address via DHCP, to teach her to accept SSH connections, and try not to break along the way.

Part one. Ssh.
As an SSH server, it was decided to take dropbear. In fact, no comparative testing and parsing of the features was carried out - I chose what I already worked with. For the first step, we will need the source code dropbear - https://matt.ucc.asn.au/dropbear/ and OcteonSDK - the latter is available only to partners, so let's assume that we already have it.
The process itself is simple. Unpacking the toolchain from the SDK, unpacking the dropbear sources, going to:

export CC=/home/pony/octeon_sdk/tools-gcc-4.1/bin/mips64-octeon-linux-gnu-gcc ./configure --host=mips64-octeon-linux-gnu --prefix=/home/pony/dropbear --exec-prefix=/home/pony/dropbear/bin --disable-zlib make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp" make install 

Pick up from / home / pony / dropbear / bin binaries

Part two. Firmware.
Here we need a TFTP server and, to facilitate overwork, an OpenDHCP server.

We connect the hardware to the first network port (this will get ip faster) to the working machine, run TFTP + OpenDHCP

We connect to the console port - in my case it was a pair of CiscoConsole + TrendNet COM2USB , we turn on the hardware. We skip the first “Hit any key to stop autoboot”, wait for the second -
Interface 3 has 4 ports (LOOP)
Interface 4 has 1 ports (AGL)
Hit any key to stop autoboot: 0

We get the address by DHCP
Octeon aewin3240 (ram) # dhcp

See how it loads:
Octeon aewin3240 (ram) # grepenv boot
bootcmd = fatload mmc 1: 2 0x100000 vmlinux.64; bootoctlinux 0x100000 coremask = 0xf mem = 0

That is, the image of the system is stored on the internal MMC card. We need to take this image for ourselves.

We read the image from the piece of iron into memory - we have the name and path with the file (mmc 1: 2 vmlinux.64), judging by the download command, it is expected that the address 0x100000 is free:
Octeon aewin3240 (ram) # fatload mmc 1: 2 0x100000 vmlinux.64

Fill it with TFTP (we get the size as a result in the console from the previous step, we just need to translate it into hex):
Octeon aewin3240 (ram) # tftpput 0x100000 0x332C650 192.168.0.1:vmlinux.64

Part Three Vivisection.

The resulting file is a self-extracting ELF, in the manner of the initramfs in the kit, which is also unpacked with the kernel during the boot phase. Accordingly, we need to get this image, make the necessary edits and collect it back. Unfortunately, I don’t have the original — with the kernel and other files from which ELF was going. Therefore, it is necessary to uncover the saw and surgical glue. Let's see what is in the file -

root @ ponybuntu: / home / root / uboot # objdump -h vmlinux.64
Sections:
Idx Name Size VMA LMA File off Algn
...
11 .init.text 0002a534 ffffffff8090e000 ffffffff8090e000 0080f000 2 ** 5
CONTENTS, ALLOC, LOAD, READONLY, CODE
12 .init.data 02aee0d0 ffffffff80938540 ffffffff80938540 00839540 2 ** 5
CONTENTS, ALLOC, LOAD, DATA
13 .exit.text 00001920 ffffffff83426610 ffffffff83426610 03327610 2 ** 2
CONTENTS, ALLOC, LOAD, READONLY, CODE
...
the only initramfs candidate is the .init.data section with a size of 0x02aee0d0 = 45015248 bytes
To begin with, let's bow to the Gentushniki and find out that the initramfs images are stored in gzip. We are looking for headers from the GZIP format inside the image:
root @ ponybuntu: / home / root / uboot # binwalk vmlinux.64 | grep gzip
5962904 0x5AFC98 gzip compressed data, from Unix, NULL date: Thu Jan 1 03:00:00 1970, max compression
8705696 0x84D6A0 gzip compressed data from Unix, last modified: Mon Feb 2 19:15:12 2015, max compression

Only 0x84D6A0 is suitable for off-set under .init.data - try to pull it out. The archive does not go beyond the section, therefore the size is the address of the beginning of the next section minus the address of the beginning of the gzip:
0x03327610 - 0x0084D6A0 = 0x02AD9F70 = 44932976 bytes. Cut it out:
root @ ponybuntu: / home / root / uboot # dd if = vmlinux.64 bs = 1 oflag = seek_bytes skip = 8705696 count = 44932976> ramfs.gz.orig

Unpack:
root @ ponybuntu: / home / root / uboot # gunzip <ramfs.gz.orig> initramfs.cpio
gzip: stdin: decompression OK, trailing garbage ignored

And here we are waiting for the Fail. Judging by the “trailing garbage ignored”, not everything in the cut piece turned out to be an archive. For us it still goes around comes around, but for now, suppose everything is in order.

Remember the size of the initramfs.cpio = 143785984

Part Four Cooking image.
Mount initramfs in a temporary folder:
root @ ponybuntu: / tmp / ramfs # cpio -i -d -H newc --no-absolute-filenames <initramfs.cpio
root @ ponybuntu: / tmp / ramfs # ls
bin dev etc examples home init lib lib32 lib32-fp lib64 lib64-fp linuxrc mnt mnth proc root sbin share sys tmp usr var

We add Dropbear binaries to / bin and / sbin and configure its autostart + eth0 increment + get IP in / sbin / rc - add
 echo Setting up network ifconfig eth0 up udhcpc -i eth0 #Start sshd if it exists if [ -e /sbin/dropbear ]; then echo Generating Drpbear keys if [ ! -e /etc/ssh_host_rsa_key ]; then /bin/dropbearkey -t rsa -f /etc/ssh_host_rsa_key fi if [ ! -e /etc/ssh_host_dsa_key ]; then /bin/dropbearkey -t dss -f /etc/ssh_host_dsa_key fi echo Starting Dropbear /sbin/dropbear -d /etc/ssh_host_dsa_key -r /etc/ssh_host_rsa_key fi 

We clean out / examples - hardworking Chinese have forgotten to do this, which gives us too much space that can be used under our files so that the final archive will not get out of the original ELF

Putting it back into the initramfs image:
root @ ponybuntu: / tmp / ramfs # find. | cpio -H newc -o> /home/root/uboot/initramfs.cpio

Pack the image in gzip:
root @ ponybuntu: / home / root / uboot # gzip --best <initramfs.cpio> ramfs

Paste the resulting gzip in place of the old:
root @ ponybuntu: / home / root / uboot # dd conv = notrunc if = ramfs of = vmlinux.64 oflag = seek_bytes seek = 8705696
87758 + 1 records in
87758 + 1 records out
44932351 bytes (45 MB) copied, 0.130304 s, 345 MB / s

Here I am running ahead. This image, after being poured onto a piece of iron, quickly falls into the kernel panic with complaints about unpacking. And the point is definitely that the “unpacker” from ELF is not as phlegmatic as its colleague gzip, and clearly expects that the size of the archive will be known for sure. We recall that above we already received “trailing garbage”, which subtly hinted to us that not everything that we considered to be an archive was such. According to gzip specs, the last entry in the archive is the size of the unpacked data in LittleEndian. Remember the size of the initramfs.cpio = 143785984 = 0x08920000 . We are looking for this in the proposed end of the archive:

root @ ponybuntu: / home / root / uboot # tail -c 24 ramfs.gz.orig | hexdump -C
00000000 1f ff a9 e3 5f 8e 5b 98 18 00 00 92 08 00 00 00 | ...._. [......... |
00000010 00 00 00 00 02 ad 9f 65 | ....... e |

We find: 00 00 92 08 - 11 bytes before the current end of the file.

This means that the real gzip size with initramfs = 44932976 - 11 = 44932965 = 0x02AD9F65. We look above and see that the last bytes of the archive that we originally pulled out are exactly 02 ad 9f 65. Hence, “from the beginning of the archive to the end of the .init.data section” is placed not only the archive, but also a little zeros and the size of the archive. Which, apparently, is read by the kernel at boot time, and an unpacking attempt is made.

The “our” archive with initramfs prepared above is slightly smaller than the original - it means that we can paste it into the old one, and then correct the size at the end of the section:

root @ ponybuntu: / home / root / uboot # dd conv = notrunc if = ramfs of = vmlinux.64 oflag = seek_bytes seek = 8705696
87758 + 1 records in
87758 + 1 records out
44932351 bytes (45 MB) copied, 0.130304 s, 345 MB / s

We check that the file did not break from our manipulations:

root @ ponybuntu: / home / root / uboot # readelf -h vmlinux.64
ELF Header:
Magic: 7f 45 4c 46 02 02 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, big endian
Version: 1 (current)
OS / ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: MIPS R3000
Version: 0x1
Entry point address: 0xffffffff808067f330
Start of program headers: 64 (bytes into file)
Start of section headers: 53657872 (bytes into file)
Flags: 0x808b0001, noreorder, octeon, mips64r2
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 2
Size of section headers: 64 (bytes)
Number of section headers: 21
Section header string table index: 20

No complaints, let's hope that everything works. Now we need to tweak the archive size expected by the kernel. Then I lost my temper and took advantage of HexEdit, with a mouse and geyami - go to 0x0332760C and change 02 AD 9F 65 to the size of our new archive - 44932351 = 02 AD 9C FF

Save, put on the tftp-server, turn on the piece of iron, get to the second hit again again, get the address by dhcp. Download the new image from tftp to memory:

Octeon aewin3240 (ram) # tftp 0x100000 192.168.0.1:vmlinux.64
Using octeth0 device
TFTP from server 192.168.0.1; our IP address is 192.168.0.2
Filename 'vmlinux.64'.
Load address: 0x100000
Loading: ################################################ ##
10.4 MiB / s
done
Bytes transferred = 53659216 (332c650 hex)

Remember how it was previously loaded:
Octeon aewin3240 (ram) # grepenv boot
bootcmd = fatload mmc 1: 2 0x100000 vmlinux.64; bootoctlinux 0x100000 coremask = 0xf mem = 0

It is not necessary to read from the flash drive, the image is already in memory on the path 0x100000, so we just run - bootoctlinux 0x100000 coremask = 0xf mem = 0 , we see:
BusyBox v1.20.2 (2015-02-02 22:37:53 CST) built-in shell (ash)
Enter 'help' for a list of built-in commands.
~ #

Great, it loads. SSH is working. You can replace the original image with ours.
Again we reload the piece of iron to the “dhcp received” stage, download the new image again, write it from the memory on the MMC next to the original. Just in case:

Octeon aewin3240 (ram) # fatwrite mmc 1: 2 0x100000 vmlinux.64.new 332c650
writing vmlinux.64.new
53659216 bytes written

Change the loading command for the piece of iron:
Octeon aewin3240 (ram) # setenv bootcmd 'fatload mmc 1: 2 0x100000 vmlinux.64.new; bootoctlinux 0x100000 coremask = 0xf mem = 0'
Octeon aewin3240 (ram) # saveenv

Done.

I don’t know if this success-story will help someone in the future, but if I came across something like that, it would save me a day or two spent on Google. The vast majority of manuals found on the network are designed for the presence of original files — kernels, descriptions, and so on — from which you can assemble a u-boot image with one command.

Source: https://habr.com/ru/post/269537/


All Articles