TyphoonCon Challenge 2019

During TyphoonCon 2019 we held an open contest which involved a specially crafted binary program we provided. The goal of the contest was to code a program which, when launched, interacts with the challenge program via network traffic and obtains the hidden message: “TyphoonCon 2019 Get this string first!”.
The winners where chosen based on the time they submitted a fully working solution which included the following:

  1. Documentation of the attack flow used in their program
  2. Code which utilizes network communication between itself and the challenge program

The challenge was not an easy one, and it involved several techniques which required experienced security experts use, making it non-trivial and highly challenging.
Eventually, three final winners were announced:

  • First Place: Niklas Breitfeld @brymko
  • Second Place: Tom Dohrmann @13Erbse
  • Third Place: Peace-Maker @jhartung10

You can get the challenge and the full writeups of the three winners on our Github.com repository here:
TyphoonCon Challenge 2019 – Github Repository

Thank you for participating, see you soon in our next challenge!
Be sure to check out our upcoming even in June 2020:

All offensive security conference

beVX Conference Challenge – OffensiveCon

During the event of OffensiveCon, we launched a reverse engineering and encryption challenge and gave the attendees the change to win great prizes.
The challenge was divided into two parts, a file – can be downloaded from here: https://www.beyondsecurity.com/bevxcon/bevx-challenge-1 – that you had to download and reverse engineer and server that you had to access to have a running version of this file.
The challenge could not have been resolved without access to the server as the encryption key that you were supposed to extract was only available in the running version on the server.
We had some great solutions sent to us, some of them were posted below – some arrived after the deadline, and some were not eligible as their solution was incomplete, but in the end we had three winners.
First place winner got an all paid, flight and hotel, and entry to our security conference beVX in September, second place prize winner got flight and entry to our security conference and the third place winner got a free entry to our event.
(more…)

Happy New Year 2018 – Challenge Solution

In our post found here: https://blogs.securiteam.com/index.php/archives/3616, we hid a challenge.
The challenge was split into two parts:
1. Finding it
2. Solving it
Finding it wasn’t very hard, the challenge was hidden inside the image, it wasn’t anything fancy, just inside the image you had a zip file appended to the end of the file:

wget https://blogs.securiteam.com/wp-content/uploads/2018/01/2018_2.jpg
--2018-01-04 07:XX:XX--  https://blogs.securiteam.com/wp-content/uploads/2018/01/2018_2.jpg
Resolving blogs.securiteam.com... 104.196.190.188
Connecting to blogs.securiteam.com|104.196.190.188|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 84283 (82K) [image/jpeg]
Saving to: ‘2018_2.jpg’
2018_2.jpg 100%[=================================================>]  82.31K   321KB/s    in 0.3s
2018-01-04 07:XX:XX (321 KB/s) - ‘2018_2.jpg’ saved [84283/84283]
$ xxd 2018_2.jpg | tail
000148a0: 0000 e817 0000 0900 1800 0000 0000 0000  ................
000148b0: 0000 fd81 0000 0000 6368 616c 6c65 6e67  ........challeng
000148c0: 6555 5405 0003 b50b 495a 7578 0b00 0104  eUT.....IZux....
000148d0: e803 0000 04e8 0300 0050 4b01 021e 0314  .........PK.....
000148e0: 0000 0008 009b 9021 4c14 3bc1 9d86 0000  .......!L.;.....
000148f0: 009c 0000 0006 0018 0000 0000 0001 0000  ................
00014900: 00b4 817b 0900 0052 4541 444d 4555 5405  ...{...READMEUT.
00014910: 0003 265c 4a5a 7578 0b00 0104 e803 0000  ..&\JZux........
00014920: 04e8 0300 0050 4b05 0600 0000 0002 0002  .....PK.........
00014930: 009b 0000 0041 0a00 0000 00              .....A.....

If you binwalk inspect the file you will see:

$ binwalk 2018_2.jpg
DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             JPEG image data, JFIF standard 1.01
81481         0x13E49         Zip archive data, at least v2.0 to extract, compressed size: 2360, uncompressed size: 6120, name: challenge
83908         0x147C4         Zip archive data, at least v2.0 to extract, compressed size: 134, uncompressed size: 156, name: README
84261         0x14925         End of Zip archive

This looks really promising now, a ZIP file has been appended to the image, and binwalk tells us it’s located at offset 81481. We can use dd to get the archive.

$ dd if=2018_2.jpg of=challenge.zip bs=1 skip=81481
2802+0 records in
2802+0 records out
2802 bytes (2.8 kB, 2.7 KiB) copied, 0.00661634 s, 423 kB/s

Binwalk also tells us, there are two files inside the archive (challenge and README). Use unzip to get them.

$ unzip challenge.zip
Archive:  challenge.zip
  inflating: challenge
  inflating: README

(NOTE: If you downloaded the file to a Linux machine (though other machines may have also worked), and just unziped it you got two files:
1. README
2. challenge
There was no need to use dd)
The readme was pretty simple, just instructed you to make the challenge ELF binary file spit out text:

Make 'challenge' output the following text (without a new line):
Happy New Year! From Beyond Security SSD :)
First correct submission will get 1,000$ USD!

From this point the solution varied, our first solver reversed engineered the file and discovered what it does, which basically breaks down to:

int main(int argc, char **argv, char **envp)
{
  int ret;
  char filename[9];
  char key[13];
  strcpy(filename, "eapfxlya");
  strcpy(key, "\xFF\x6B\x28\x66\xD6\x35\xDA\x01\x4D\x64\x47\xA3");
  ret = challenge(filename, key);
  return ret;
}
int keyhash(const char *key)
{
  int ret;
  unsigned int i;
  ret = 0;
  for ( i = 0; i < strlen(key); ++i )
    ret = _rotl(key[i] ^ ret, 7);
  return ret;
}
int decode(unsigned int *key, char *out, unsigned int size)
{
  int result;
  int i;
  for ( i = 0; ; ++i )
  {
    result = i;
    if ( i >= size )
      break;
    *key *= 0x8088405;
    out[i] ^= ++*key >> 24;
  }
  return result;
}
int challenge(const char *filename, char *key)
{
  int result;
  int seed;
  unsigned int n;
  FILE *fp;
  char *ptr;
  fp = fopen(filename, "rb");
  if ( fp )
  {
    n = 1;
    seed = keyhash(key);
    while ( n )
    {
      ptr = (char *)malloc(0x200uLL);
      n = fread(ptr, 1uLL, 0x200uLL, fp);
      decode(&seed, ptr, n);
      write(1, ptr, n);
    }
    fclose(fp);
    putchar('\n');
    result = 1;
  }
  else
  {
    puts("file does not exist!");
    result = 0;
  }
  return result;
}

The program executes the following actions:

  • Open an encrypted file named “eapfxlya” (this can be confirmed with strace)
  • Generate a 32-bit key based on “\xFF\x6B\x28\x66\xD6\x35\xDA\x01\x4D\x64\x47\xA3” (see function keyhash)
  • Read the contents of the opened file
  • Decode it with XOR/ADD/MUL/SHR tricks (see function decode)

The keyhash function is pretty straight-forward so let’s have a closer look at the decode function. It’s purpose is to generate a sequence of 32-bit numbers based on a linear congruential generator (aka *predictive* pseudo number generator) which takes a precomputed hash for seed. Each number of this sequence is then shifted right and used as a 8-bit xor-mask on every byte in the file stream. In conclusion, this program can be used to decode and encode any file in a symmetric way. So let’s use the happy new year string “Happy New Year! From Beyond Security SSD :)” and feed it into the reversed program.

$ echo -ne "Happy New Year! From Beyond Security SSD :)" > eapfxlya
$ ./challenge > tmp
$ dd if=tmp of=eapfxlya bs=43 count=1 # don't forget, it's without a new line
$ ./challenge
Happy New Year! From Beyond Security SSD :)

Congratulations to: Alexandre for solving the challenge first (within 2 hours of posting it online).
A few other solutions we received included a brute forcing code (a cool one from Tukan):

root@ubuntu-512mb-ams2-01:~# cat solver.py
import sys
def reversit(inp, checksum=0xf5f6103f):
    out = ''
    for c in inp:
        checksum *= 0x08088405
        checksum &= 2**32-1
        checksum += 1
        outc = ord(c) ^ ((checksum) >> 24)
        out += chr(outc)
    return out
winner = reversit('Happy New Year! From Beyond Security SSD :)' + '\x1b' + 'P')
sys.stdout.write(winner)
root@ubuntu-512mb-ams2-01:~# python solver.py > eapfxlya
root@ubuntu-512mb-ams2-01:~# ./challenge

Security conferences – Survival guide 2017 Q4

The security conferences “Survival guide” for 2017 Q4 is here!
We have gathered the following information for you for each conference:

  • Dates:
  • Place:
  • Link to official conference website:
  • Ticket price:
  • Lectures:
  • Workshops:


So let’s get started:
(more…)

Security conferences – Survival guide 2017 Q2

As we promised, the security conferences “Survival guide” for 2017 Q2 is here!
We have gathered the following information for you for each conference:

  • Dates
  • Place
  • Link to official conference website
  • Ticket price
  • Lectures
  • Workshops

So let’s get started:

Security conferences – Survival guide part 2
(more…)