BSidesSF 2022 Writeups: Miscellaneous Challenges (loca, reallyprettymundane)

Hey folks,

This is my (Ron's / iagox86's) author writeups for the BSides San Francisco 2022 CTF. You can get the full source code for everything on github. Most have either a Dockerfile or instructions on how to run locally. Enjoy!

Here are the four BSidesSF CTF blogs:

Loca - A weird Windows reversing challenge

Several years ago, I wrote a challenge called launchcode, where I backdoored calc.exe so it would detect a certain pattern of button presses and display a special message if it detects them (that in turn was based on a bug in Steam). But often, if I replaced certain bytes in the executable, it would mysteriously corrupt the code and crash! I eventually figured out it was due to "relocations", and I thought I'd make a challenge based on that.

This is where loca came from!

A Windows binary (ie, PE file) has a section called .reloc, or relocation. That section is essentially a big list (encoded in a weird, page-based DOS-ey feeling way) that lists every hardcoded memory address in the PE image.

When the Windows loader loads the PE image at an address where it doesn't want to be loaded to (which is always with ASLR), it will navigate that list and update each address in the loaded binary. It adds the difference between where it wants to be loaded and where it is actually loaded to the original value. That way, no matter where the image is loaded into memory, the hardcoded addresses will point to the right spot.

That's obviously a ridiculous way to handle relocations, but I'm sure there are pros and cons.

For this challenge, I calculate a simple request/response. The problem is that the initial value of the checksum I calculate is marked as a relocation, which means it changes based on where it's loaded. That means that for a solution, you need to:

  • Realize it's relocating the seed address
  • Leak a memory address using an information-disclosure issue
  • Calculate the result for the current offset

All this has the bonus that it breaks debugging - debuggers disable ASLR, which means if you debug this executable you'll miss the trick entirely. I'm not sure if that's good or bad, because I had several people ask questions, but it certainly made it challenging!

reallyprettymundane

reallyprettymundane is an RPM-spec-injection attack. It's based on something I found while investigating CVE-2022-1388. Basically, if you can add newlines to an RPM's .spec file, you can run arbitrary code by adding a new section to the .spec. Some sections contain executable code, and that's what we care about!

For our solution, we target the %check section, which consists of shell commands. The solution is somewhat complex, because I didn't want to spawn a shell, but the bones of it is this form:

    :body => {
      :name        => 'name',
      :summary     => 'summary',
      :version     => 'hi',
      :release     => '2',

      # The payload is here - it copies the flag over top of the target filename
      :description => "description\n\n%check\n\ncp #{ FLAG_PATH } $RPM_BUILD_ROOT/name/#{ TARGET_FILE_NAME }*\n",

      'file'  => [t],
    }

Specifically, the description, which is:

description

%check

cp #{ FLAG_PATH } $RPM_BUILD_ROOT/name/#{ TARGET_FILE_NAME }*

You could run any shell command in there - the one I came up with copies the flag file into the folder that's being packaged up. That way, it sends me the flag and I don't have to deal with code execution!

Comments

Join the conversation on this Mastodon post (replies will appear below)!

    Loading comments...