34C3CTF vim

| Lense

Challenge description

Category: rev
Points: 215 (dynamic, calculated from solves)
Solves: 18

This is not compatible with emacs!

Tested with vim 7.4 on amd64 Ubuntu 16.04 (package vim 2:7.4.1689-3ubuntu1.2)

Difficulty: Easy

Preface

There are a lot of words here. If you looked at the challenge during the competition and just missed a few things, you might want to skip ahead to the high-level loop summary section.

Understanding the challenge file

Vim refresher

If you’re a complete Vim beginner, I recommend going through vimtutor. Just run it from a shell.

Here’s a list of every command that this challenge uses (all in normal mode):

  • h
  • j
  • k
  • l
  • ^
  • $
  • 0
  • G
  • f
  • F
  • t
  • Y
  • y
  • @
  • "
  • r (only after you get the flag)
  • d (only after you get the flag)

If you don’t know what some of them do, look them up in Vim’s help like: :help j or :h j. You might also be interested in the general concepts:

  • count (and the rest of notation or the whole intro.txt file)
  • registers
  • quote_quote
  • quote_alpha

and the command :registers for debugging. As an aside, the most common way I know to interact with registers is with q, which puts typed characters into the given register as a way to record macros. qx@x was a pattern I learned when I was a beginner, but I didn’t make the connection to registers for a long time.

Another thing to know is that @ execution will stop when a command fails to execute. For example, qx0hl@x will put 0hl in register "x and try to run it, but because 0h goes to the first character, h can’t move left and it will stop executing before moving right with l. I found this …

...Read more

HXP 2017 pdf.pdf

| Lense

Challenge description

RTFM! and a link to pdf.pdf.

Our approach

The PDF contained a bunch of different types of content, like text, a vector drawing, a bitmap image, embedded fonts, internal and external links, annotated rectangles around the links, table of contents metadata, and presumably the flag. It ended with a link to the PDF spec, and we took that to mean that we should write a PDF parser.

PDF file format overview

It turns out that while rendering PDFs is extremely painful, just parsing a PDF is only moderately painful, and the spec isn’t as bad as I was expecting.

File sections

Header

The first line is a comment (starting with %) with the PDF version number. The challenge used version 1.5. The second line is a comment with 4 non-ascii bytes, designed to keep text viewers from trying to render PDFs as plaintext.

Body

The body is a series of objects. They aren’t rendered implicitly, but they can be referenced by other objects and the XRef table at the end.

Footer

The footer can have a whole bunch of different types that render the PDF differently, but since we were just trying to parse the PDF, we didn’t deal with it much. At a high level, the footer contains a cross-reference table that points to byte-offsets in the file of objects.

Object types

In this PDF, the body consisted entirely of indirect objects. Those indirect objects contained streams of compressed data, which contained one or more direct objects of arbitrary type. I’m sure there are many other ways that PDFs can be structured, but we just had to deal with this.

Indirect objects

Format:

<object number> <generation number> obj
<contents (stream)>
endobj

In our PDF, generation number was always 0 and the contents …

...Read more

CSAW Quals 2017 FuntimeJS

| pernicious

FuntimeJS

This challenge was formally Part 2 of LittleQuery (Web). Description:

JavaScript is memory safe, right? So you can’t read the flag at physical address 0xdeadbeeeef, right? Right?

This was a very interesting challenge from CSAW Quals 2017 (although whether a funtime was had is still questionable…). We are given a web page where we can submit javascript, and a link to the open source project that will run it, runtime.js, an “operating system…that runs JavaScript.” Because running javascript in ring 0 is just what this world needs… This writeup is a bit long, skimming is not discouraged.

Step 1: Arbitrary Read/Write

Finding a bug was a lengthy process of going through the source and trying things out. The syscalls seemed a good place to start, especially a few:

// runtime.js syscalls: Low level system access
DECLARE_NATIVE(BufferAddress);       // Get buffer physical address
...
DECLARE_NATIVE(GetSystemResources);  // Get low-level system resources

console.log(__SYSCALL.bufferAddress(new Uint8Array(17))) => [ 17, 510626304, 0, 0, 0, 0 ]

Huh, that second entry looks suspicously like a memory address… Looking a bit into the source for getSystemResources (some stuff is cut out):

NATIVE_FUNCTION(NativesObject, GetSystemResources) {
  LOCAL_V8STRING(s_memory_range, "memoryRange");
                                       //     vvvvv   memoryRanges's type
  obj->Set(context, s_memory_range, (new ResourceMemoryRangeObject(Range<size_t>(0, 0xffffffff)))
           ->BindToTemplateCache(th->template_cache())
           ->GetInstance());
}

and following the bread crumbs…

NATIVE_FUNCTION(ResourceMemoryRangeObject, Block) {
  auto base = static_cast<uint64_t>(arg0->NumberValue(context).FromJust());
  auto size = static_cast<uint32_t>(arg1->Uint32Value(context).FromJust());
  Range<size_t> subrange(base, base + size);
  if (!subrange.IsSubrangeOf(that->memory_range_)) {
    THROW_RANGE_ERROR("block: out of bounds");
  }                             //    vvvvv  return type of memoryRange.block()
  args.GetReturnValue().Set((new ResourceMemoryBlockObject(
                               MemoryBlock<uint32_t>(reinterpret_cast<void*>(base), size)))
                            ->BindToTemplateCache(th->template_cache())
                            ->GetInstance());
}

NATIVE_FUNCTION(ResourceMemoryBlockObject, Buffer) {
  PROLOGUE;
  void* ptr = that->memory_block_.base(); // <---- uses raw void* ???
  auto length = that->memory_block_.size();
  RT_ASSERT(ptr);
  RT_ASSERT(length > 0);
  auto abv8 = v8::ArrayBuffer::New …
...Read more

DEFCON Finals 2017 - Intro & Rubix

| Toshi Piazza

Over the weekend, July 28-31 2017 RPISEC competed with Lab RATs and Techsec in DEFCON Finals, one of the most important CTFs of every year. Only 15 teams in the world get to qualify for the event each year, and our team under Lab RATs was able to earn the right to compete among 14 other globally professional teams.

This writeup covers the first challenge presented at DEFCON Finals, which kept us on our toes throughout the competition. It was deceptively simple, and also served as an introduction to cLEMENCy, a terrifying 9-bit middle endian architecture, as well as to the toolchain that was used to create all future binaries.

The majority of this writeup will involve getting our feet wet with cLEMENCy while setting up a comfortable environment for reverse engineering the later challenges released at DEFCON.

DEFCON Challenge Format

A link to the challenge binary can be found here

For the CTF we are given only an emulator and a debugger to solve each of the challenges; these challenges are compiled for a 9-bit middle endian architecture, cLEMENCy. When we first run the rubix challenge under this emulator, we note that only garbage gets printed to the terminal. This output doesn’t change each run, and it’s puzzling what exactly this is. What if it’s the emulator printing out 9-bit ascii instead of 8? Indeed, when we transform from 9-bit to 8-bit between the debugger and our terminal, we end up with the following:

This service implements a rubix cube. Solve the cube and win.

Give me 54 Bytes(ie: 53,12,5,etc): <input 54 comma-delimited chars>

                Top

             R6 R7 B0
             L1 T4 R5
             A0 B7 R2

  Left         Front       Right       Back

L8 L7 L0     T0 A7 F0    R8 F3 L6    B6 T3 T6
T5 L4 …
...Read more

Google CTF Quals 2017 - Moon

| Toshi Piazza

This writeup is for the reversing challenge “Moon” we solved during 2017 Google CTF Quals. This writeup and 3 others were also submitted to the Google CTF Writeup Competition.

Dealing with GLEW

A big problem we noticed early on was the use of GL3W, which generates code to lazily load all OpenGL functions at runtime—at all places where an OpenGL function was used we would simply see a call to some offset in the data section. Unfortunately we couldn’t find a script to re-symbolize function calls, but we plan to make one soon-ish :)

We can see the huge routine which calls LoadLibrary on every OpenGL function, at sub_4032c0.

GLEW lazy loading functions

Instead of symbolizing (by hand) all of the symbols, we only bothered to load ones which had valid XREFs to them, saving a bit of time.

Running the Program

Unfortunately all the RPI-sold computers from our year are not yet reported to support OpenGL 4.3, so first and foremost we had to patch the OpenGL verification check from 4.3 to 4.2. Surprisingly, this “just worked” despite the code making use of Compute Shaders which I had thought to be introduced in OpenGL 4.3.

The program simply opens up a window, and asks for a password. After we’ve entered 32 characters, the program either responds “good” (presumably), or “Nope”.

Running the program

When we XREF the string Nope, we see that it is used when constructing the texture to be printed for this SDL event loop iteration. Not too far from “Nope” do we find “Good”, and we notice that “Good” is only selected if a particular global variable is set. We trace this back to the following code in main:

We want should_compute here …

...Read more