Penguin Plugins


Linux Firmware Rehosting.

This section provides an introduction to using plugins with penguin. We will learn how to modify rehostings and analyze rehosted systems using built-in penguin plugins.

Some notes and reminders:

  • /challenge is a read-only directory, you'll need to copy files to /tmp or your home directory to modify them.
    • If you have results you would like to save for a future challenge, you can copy them to your home directory.
  • Provide a key to /challenge/solve to get your pwn.college flag.
  • Most of these challenges involve small "constructed" firmware that we made to highlight a specfic rehosting problem. That means they are significantly less noisy on the console than actual firmware.
    • Feel free to copy /examples/patch_output.yaml into your project to have the system console directed to stdout. (e.g., cp /examples/patch_output.yaml ./projects/FIRMWARENAME)


Challenges

For computers that have an Operating System, the OS interface can tell us a lot about what is going on. For example, you may have used strace to troubleshoot or analyze Linux software in the past by examining the system calls that are being executed. Those types of analyses can be useful for troubleshooting rehostings and analyzing embedded software.

We will be working with the OpenIPC firmware again.

As a reminder, you can enable syscalls logging to the datastore with this configuration option (which can either be added to config.yaml in your project or as a patch like patch_syscalls.yaml):

plugins:
  syscalls_logger: {}

And then you can use the syscalls script from within the challenge container to inspect the contents of the datastore. Don't forget to point --results to the correct directory.

During firmware boot, the init program will run /bin/hostname with an argument -F. The solution to the challenge is the path of the file that passed to /bin/hostname with -F, without any quotes or anything that syscalls may output.

Notes:

  • We provide the firmware rootfs.tar.gz again, but feel free to use your project from last time
  • List of system calls with links to descriptions: https://man7.org/linux/man-pages/man2/syscalls.2.html
  • If you're running with the penguin project in your home directory, you should probably disable syscalls_logger after this exercise

Connect with SSH

Link your SSH key, then connect with: ssh hacker@pwn.college

In Linux, pseudofiles are files that don’t really exist on disk as stored data, but represent some other entity, be it a device, kernel data structures, or runtime state. In the case of firmware rehosting, we will often want to create models for the pseudofiles in /dev that do not exist due to missing hardware or drivers.

The pseudofiles built-in penguin plugin manages and interacts with the penguin tooling to create and manage pseudofiles that the guest will use.

This is a constructed challenge that will require you to set up a pseudofile and model correct behavior the firmware expects when it tries to read from the pseudofile. Once you have the correct behavior modeled the program will print the solution for you to obtain the flag.

The file /challenge/pseudofiles-1.rootfs.tar.gz contains the rootfs for you to use.

The source for the challenge binary is available at /challenge/pseudofiles-1.c`

Feel free to use the example below as a starting point for your model:

pseudofiles:
  /dev/wrongdevice:
    write:
      model: discard
    read:
      model: const_buf
      val: "The contents we need will be here"

Notes:

  • In this course "constructed challenges" represent artificial firmwares that we've created to highlight a particular rehosting challenge
    • Building isolated examples can be useful for troubleshooting rehostings. You can build your own using the build_basic_rootfs.py script.
  • Instead of looking at console.log, you can have the device's console print to stdout by copying /examples/patch_output.yaml into your project.
  • Your key for /challenge/solve will be wrapped in IGLOO{}. That is meant for the key to be easier to find in system console output and should also be included in the string you pass to /challenge/solve

Connect with SSH

Link your SSH key, then connect with: ssh hacker@pwn.college

Very often, embedded software requires correct device functionality to run. That device functionality can be queried in a number of ways, but on Linux this is often covered by the "catch-all" ioctl system call. As such, firmware rehosting can involve modeling ioctl behavior in order to present a "healthy" device to a system's software stack.

This is a constructed challenge that will require you to set up a pseudofile and model its IOCTL behavior. Once you have the correct behavior modeled the program will print the key to obtain the flag from /challenge/solve.

As a starting point, consider this (very wrong) device model:

pseudofiles:
  /dev/wrongdevice:
    ioctl:
      12:
        model: return_const
        val: 0

Source code file is at /challenge/pseudofiles-2.c.

In the container, edit the yaml file patches/challenge.yaml

Connect with SSH

Link your SSH key, then connect with: ssh hacker@pwn.college

In IoT devices, configuration options are often stored in an nvram key/value store. This sort of device is difficult to emulate with low-level precise device models, however many devices follow a similar API to query that key/value store. E.g., nvram_get("key") will return a value.

In penguin, you can modify (or add to) the nvram: dictionary in the config to modify the runtime behavior of that key/value store.

In this challenge, the constructed firmware expects a particular key/value pair to unlock the key for /challenge/solve. Feel free to look at the source in /challenge/libinject-nvram.c to see what key and value you should provide.

Connect with SSH

Link your SSH key, then connect with: ssh hacker@pwn.college

In addition to emulating NVRAM, penguin's library injection features can be used to build your own custom models to override dynamically linked functions. Similar to libnvram, working at the API level can often be a simpler way of tackling rehosting issues due to missing devices or broken drivers.

For this challenge you are given a simple firmware image that tries to initialize a sensor device. Can you make the initialization check succeed?

Note: we don't need a custom model here, feel free to use a built-in lib_inject function

Connect with SSH

Link your SSH key, then connect with: ssh hacker@pwn.college

30-Day Scoreboard:

This scoreboard reflects solves for challenges in this module after the module launched in this dojo.

Rank Hacker Badges Score