DEFCON CTF Quals 2018 - smcauth

ELF

Verilog

Description

This was a pretty difficult crypto challenge that ended up involving some reverse engineering. It took a while to get any solves, we got it third. Thanks to @nullptr for what turned out to be a really fun challenge (and thanks for not giving in and giving us source :) )

Given is an ELF, which is a Rust binary, and a Verilog file which contains a ‘circuit’.

Example command line input:

Server: ./smcauth verify --netlist smcauth_syn.v --secret $(python -c 'print "A"*(256/8)')
Client: ./smcauth auth --netlist smcauth_syn.v --verifier 127.0.0.1:5331 --secret $(python -c 'print "A"*32')

The verify command runs a server and the auth command runs a client (ostensibly, the challenge server is running as verify). The server (verify) takes --netlist, which is supposed to be the verilog file, and a --secret, which must be 32 printable ascii characters. The client (auth) takes --netlist (the verilog file), --verifier, which is the IP of the server, and --secret (also 32 printable ascii). When the server runs with a secret x, if a client connects with the same secret x the server will return “INFO authentication successful”, but if a client connects with a different secret y the server returns “WARN authentication failed”. We figured that the secret being passed by the server would be the flag, and it was incumbent upon us to input a secret that evaluated successfully.

Solution

From the circuit given and the behavior, it was easy to deduce that this was a Garbled Circuit . If you aren’t familiar with these, I’d highly recommend reading through the protocol before continuing.

In our case, the server is the “generator” or “garbler”, referred to as Alice in the Wikipedia, and the client is the “evaluator”, referred to as Bob …

...Read more

Dissecting LLVM Obfuscator Part 1

Kareem El-Faramawi, Toshi Piazza

LLVM Obfuscator is an industry-grade obfuscator which we have encountered frequently in the past few years of CTFing. This blog post documents our work in understanding the design of the obfuscator itself, as well as any possible weaknesses in the implementations of the obfuscation passes. We use this work to automate the task of emitting cleaned and working binaries via Binary Ninja.

Introduction

The open source LLVM Obfuscator manifests as 3 relatively disjoint LLVM passes, each implementing some sort of obfuscation that obscures the CFG or arithmetic computation of the original program in some way.

Also note that, due to the fact that these passes operate over LLVM IR, it supports almost every architecture under the sun.

Information for each of the three passes can be found here:

These are simply the documentation pages maintained by the authors for each respective pass. However, if the documentation is deficient, the source is also an obvious ground truth.

Unfortunately, the llvm-obfuscator repo maintains multiple branches, one for each version of LLVM that that branch targets, with a clone of the entire LLVM repository, so it’s easy to get lost in the code. The passes for the 4.0 branch can be found here, in the lib/Transforms folder, as is customary for LLVM passes.

This blog post will focus on the control flow flattening pass, as we find it to be one of the most interesting passes in the LLVM Obfuscator ecosystem, as well as the most effective.

Control Flow Flattening

We can visualize the effects of the Control Flow Flattening pass as the following CFG transformation:

  1. Collect all of the original basic blocks in a CFG
  2. Lay them down flat “at the bottom” of the CFG, and remove all original edges
  3. Add …
...Read more