Hack the Vote - x96 and Ballot Day

Awesome CTF run by RPISEC, very high quality. I played with Kernel Sanders for a bit on Friday night and helped out with two reversing challenges with the legend noopnoop. The team ended up getting 5th place overall.

almost beat ppp :eyes:


x96 - 35 solves

Description:

author: glenns

They say that, by trying to appease both sides, the centrists appease neither. Well, we recently found some centrists writing a crackme, cursing about how both sides read the same words but interpret them in different ways…

This was a pretty quick and easy one. The whole challenge was designed around x86 32-bit instructions mixed in with 64-bit instructions and retf.

Files:

_start

The important part is the ret far instruction.

retf instruction pops two numbers, return address and cs segment register. According to here and here, setting cs=0x23 puts the CPU into x86 mode, and setting cs=0x33 puts the CPU into x86-64 mode (long mode). So the interpretation of the machine code differs before and after retf.

So the cs segment register is set to 0x23 at the start of execution, but after the or al, 0x13, it becomes 0x33, which means the CPU is now in x86-64 mode. The function that is pushed onto the stack should be interpreted as x86-64 instead of x86, and luckily Binary Ninja makes that easy (Make function at address > x86_64 > x86_64).

sub_804806c

Essentially this function just does a ror on a number and then XOR’s with some encrypted data at 0x80481c3. I solved in Python with:

>>> x = 0x358d0150819cf3c4
>>> enc = b'\xa2\x8e\x90\x1fG\xf0\xfc\x9f\x87&H\xaf\xa2\xd4,N\xaf\x91\rFt|Yw\xb1\x1fR#<\xe8\x1d\xcc`\xccgW'
>>> ''.join([chr(enc[i] ^ ((x >> i)&0xff)) for i in range(0,24)])
flag{n3xt_t1m3_w3_jump_t0_r34l_m0d3}

Ballot Day - 17 solves

author: doom

Its that time again, when all the citizens in positive standing with the local enforcement can participate in the greatest tradition of all times: Casting your vote! Hopefully it all goes smoothly and there are not any demerits in store for you…

https://wargames.ret2.systems/a4bb1f1f332b5818262b/htv_2020

Ah yes, CSAW tetris flashbacks. This time we are dealing with some voting software. We aren’t given any binary, just this web interface. We can leak and decompile functions by dumping values in the debugger, which I ended up doing for two of the more complicated functions towards the end.

--------------------------------------------------
               /'\ 
__            /,O,\ 
  \   .______/,OOO,\______.   _.----------., 
 * \,__\'ooooo_OOOO______/ __/_________     \ 
  * *  * \`OO| |OO/ / __ \/_  __/ ____/  ~  / 
 * * *  *  \`| |O/ / / / / / / / __/   .   / 
    *  *   /O| |/ / /_/ / / / / /___      / 
_.      ,./OO|___/\____/ /_/ /_____/-. ~ / 
  \____/ /O'/       \'O\              \ / 
        ;'/           \';              ' 
--------------------------------------------------
 
  YOU HAVE ACCESSED AN U.S. GOVERNMENT RESOURCE.  
                                                  
  ANY ATTEMPT TO MODIFY OR EXPLOIT THIS RESOURCE  
  OR ASSOCIATED INFORMATION OTHER THAN FOR AND    
  INSTRUCTED USE IS STRICTLY PROHIBITED AND MAY   
  BE PUNISHABLE UNDER THE COMPUTER FRAUD AND      
  ABUSE ACT OF 1786.                              
 
--------[ ELECTION BALLOT ID #1603771383 ]--------
 
  PRESIDENTIAL CANDIDATES:
 
    1. George Washington
    2. Abraham Lincoln
 
ENTER CANDIDATE ID: 
>> 1
--------------------------------------------------
 
  PLEASE ENTER YOUR VOTER INFORMATION TO
     COMPLETE THIS BALLOT SUBMISSION
 
ENTER VOTER NAME: 
>> foobar
ENTER VOTER TOKEN: 
>> 1234
--------------------------------------------------
 
       /!\ INVALID BALLOT SUBMISSION /!\
 
  THIS FRAUDULENT BALLOT SUBMISSON HAS BEEN
  LOGGED AND WILL BE REVIEWED BY ELECTION
  OFFICIALS FOR MALICIOUS ACTIVITY.
 
==== EXECUTION FINISHED ====

It prompts us for a candidate ID, voter name, and voter token. We are given the source code of main. Very useful.

#include "challenge.h"

/*
               /'\
__            /,O,\
  \   .______/,OOO,\______.   _.----------.,
 * \,__\'ooooo_OOOO______/ __/__________    \
  * *    \`OO| |OO/ / __ \/_  __/ ____/     /
 * * *     \`| |O/ / / / / / / / __/       /
    *      /O| |/ / /_/ / / / / /___      /
_.      ,./OO|___/\____/ /_/ /_____/-.   /
  \____/ /O'/       \'O\              \ /
        ;'/           \';              '
*/

void main(int argc, char ** argv)
{
    if(ballot_main())
        ballot_accepted();
    else
        ballot_rejected();
}

Checking out ballot_main, we see it calls encrypt_ballot before reading in the voter token, and after reading it calls validate_ballot.

encrypt_ballot takes two arguments, the Unix timestamp and our voter name. The actual function is pretty ugly, so I used the debugger to yeet the function out so I can decompile.

encrypt_ballot

So it does some sort of encryption using the timestamp and our input.

Let’s check out validate_ballot.

validate_ballot

It takes in our encrypted ballot from the other function and the voter token we provide. It does some more operations on the encrypted ballot and makes sure it falls in the range of A-Z.

Using a Python script, we can copy the functionality to allow us to get the valid voter token so we can get the flag. At first we wondered what the easiest way would be to deal with the timestamp, probably something with their built in Python scripting tab on the site or just running our script at the same time locally. But, I realized that it just leaks the timestamp in the ballot ID.

--------[ ELECTION BALLOT ID #1603804708 ]--------

The script took some trial and error, but we eventually got the flag after providing the valid voter token.

ez clap