6 minute read

Nahamcon CTF was an online CTF even held on June 12th-13th. Unfortunately I was only able to dedicate a few hours so I focused on the easier challenges.


Agent 95

  • Clue: They’ve given you a number, and taken away your name~
  • Points: 50
  • Solves: 1788

The Web page gives us the following message:

You don’t look like our agent! We will only give our flag to our Agent 95! He is still running an old version of Windows…

I used BurpSuite to change the User agent to Mozilla/4.0 (compatible; MSIE 4.0; Windows 95) which I got from useragentstring.com. The response is the flag.


  • Clue: BooOooOooOOoo! This spooOoOooky client-side cooOoOode sure is scary! What spoOoOoOoky secrets does he have in stooOoOoOore??
  • Points: 75
  • Solves: 1375

Ascii Ghost

The web page has an ascii art ghost, which scrolls infinitely. By looking at the source code we find that the infinite scrolling is done using javascript /jquery.jscroll2.js.

The javascript is obfuscated

var _0xbcec=["\x75\x73\x65\x20\x73\x74\x72\x69\x63\x74","\x6A\x73\x63\x72\x6F\x6C\x6C","\x3C\x73\x6D\x61\x6C\x6C\x3E\x4C\x6F\x61\x64\x69\x6E\x67\x2E\x2E\x2E\x3C\x2F\x73\x6D\x61\x6C\x6C\x3E","\x61\x3A\x6C\x61\x73\x74","","\x66\x6C\x61\x67","\x53\x6B\x4E\x55\x52\x6E\x74\x7A\x63\x47\x39\x76\x62\x32\x39\x76\x61\x33\x6C\x66\x5A\x32\x68\x76\x63\x33\x52\x7A\x58\x32\x6C\x75\x58\x33\x4E\x30\x62\x33\x4A\x68\x5A\x32\x56\x39","\x73\x65\x74\x49\x74\x65\x6D","\x6C\x6F\x63\x61\x6C\x53\x74\x6F\x72\x61\x67\x65","\x64\x61\x74\x61","\x66\x75\x6E\x63\x74\x69\x6F\x6E","\x64\x65\x66\x61\x75\x6C\x74\x73","\x65\x78\x74\x65\x6E\x64","\x6F\x76\x65\x72\x66\x6C\x6F\x77\x2D\x79","\x63\x73\x73","\x76\x69\x73\x69\x62\x6C\x65","\x66\x69\x72\x73\x74","\x6E\x65\x78\x74\x53\x65\x6C\x65\x63\x74\x6F\x72","\x66\x69\x6E\x64","\x62\x6F\x64\x79","\x68\x72\x65\x66","\x61\x74\x74\x72",

I used beautifier.io to de-obfuscate the code.

(function(_0xe943x1) {
    'use strict';
    _0xe943x1['jscroll'] = {
        defaults: {
            debug: false,
            autoTrigger: true,
            autoTriggerUntil: false,
            loadingHtml: '<small>Loading...</small>',
            padding: 0,
            nextSelector: 'a:last',
            contentSelector: '',
            pagingSelector: '',
            callback: false
    window['localStorage']['setItem']('flag', atob('SkNURntzcG9vb29va3lfZ2hvc3RzX2luX3N0b3JhZ2V9'));
    var _0xe943x2 = function(_0xe943x3, _0xe943x4) {
        var _0xe943x5 = _0xe943x3['data']('jscroll'),
            _0xe943x6 = (typeof _0xe943x4 === 'function') ? {
                callback: _0xe943x4
            } : _0xe943x4,
            _0xe943x7 = _0xe943x1['extend']({}, _0xe943x1['jscroll']['defaults'], _0xe943x6, _0xe943x5 || {}),
            _0xe943x8 = (_0xe943x3['css']('overflow-y') === 'visible'),
            _0xe943x9 = _0xe943x3['find'](_0xe943x7['nextSelector'])['first'](),
            _0xe943xa = _0xe943x1(window),
            _0xe943xb = _0xe943x1('body'),
            _0xe943xc = _0xe943x8 ? _0xe943xa : _0xe943x3,
            _0xe943xd = _0xe943x1['trim'](_0xe943x9['attr']('href') + ' ' + _0xe943x7['contentSelector']),
            _0xe943xe = function() {
                var _0xe943x17 = _0xe943x1(_0xe943x7['loadingHtml'])['filter']('img')['attr']('src');
                if (_0xe943x17) {
                    var _0xe943x18 = new Image();
                    _0xe943x18['src'] = _0xe943x17


The code sets the item “flag” to the string SkNURntzcG9vb29va3lfZ2hvc3RzX2luX3N0b3JhZ2V9 if we base64 decode this string we get the flag.

Another way to solve this challenge is to simply use chrome dev tools, where the flag is stored in Local Storage.

Local Ghost


  • Clue: Ring ring! Need to look up a number? This phonebook has got you covered! But you will only get a flag if it is an emergency!
  • Points: 100
  • Solves: 561

The web page gives us the following:

Sorry! You are in /index.php/?file=
The phonebook is located at phphonebook.php

I first tried going directly to phphonebook.php and got the following page:


I then tried going to /index.php/?file=phphonebook.php and got the same page. I realised quickly that it was a local file inclusion, but spent too long trying to look for other files, like a flag.php, which doesn’t exist.

Eventually I realised / remembered that I might be able to get the contents of phphonebook.php by using base64 encoding.


It works! This gives us the contents of phphonebook.php encoded in base64.

Decoding it gives us the following code:

<!DOCTYPE html>
<html lang="en">
    <meta charset="utf-8">
    <link href="main.css" rel="stylesheet">

  <body class="bg">
    <h1 id="header"> Welcome to the Phphonebook </h1>

    <div id="im_container">

      <img src="book.jpg" width="50%" height="30%"/>

      <p class="desc">
      This phphonebook was made to look up all sorts of numbers! Have fun...

      <form method="POST" action="#">
        <label id="form_label">Enter number: </label>
        <input type="text" name="number">
        <input type="submit" value="Submit">

    <div id="php_container">

    	if (isset($emergency)){

From the code we learn that flag.txt will be read if the emergency variable is set, however it doesn’t matter what this is set too.

We can use BurpSuite to add the line emergency=123 to the body of the POST request to phphonebook.php which will return the flag.

Binary Exploitation


  • Clue: Hey! Listen!
  • Points: 75
  • Solves: 255

We are given an nc session to join nc jh2i.com 50011 and a binary to download called dangerous. When we run dangerous it asks for a name and then prints the name along with an ascii sword

Its dangerous to go alone

First step is to cause a segmentation fault by overflowing the buffer, to this just input a large number of characters, I started with 100 and increased from there. At 500 we get our segmentation fault.


We can use pattern_create and pattern_offset from msf to find the correct input length, which is 497.

The next step is to identify a vulnerable function. Using Ghidra I found a function at 0x0040130e which reads ./flag.txt and outputs it.

We can now get the flag with the following:


vulnfunc = '\x0e\x13\x40\x00\x00\x00\x00\x00'
buff = 'A' * 497

print buff + vulnfunc




  • Clue: Will you find the flag, or get lost in the vortex?
  • Points: 75
  • Solves: 582

When we connect the output looks like random characters (like cat /dev/urandom).

We can redirect the output to a file then grep for the flag.

 nc jh2i.com 50017 > vortex.txt
 cat vortex.txt | grep flag


Fake File

  • Clue: Wait… where is the flag?
  • Points: 100
  • Solves: 521

We connect to nc jh2i.com 50026 We run ls -la to see all files, there seems to be a file named ..

If we highlight and copy the line then look at it as hex we see the filename contains characters outside the ascii table, the filename in hex is 2e 2e e2 80 80.

If we simply copy and paste the filename we can use cat:

user@host:/home/user$ cat .. 
cat .. 



  • Clue: This must be a typo…. it was kust one letter away!
  • Points: 50
  • Solves: 383

We are given an image


The challenge name and clue suggest we use a common stegonography tool called Jsteg

go run cmd/jsteg/main.go reveal luke.jpg



  • Clue: Doh! Stupid steganography… Note, this flag is not in the usual format.
  • Points: 50
  • Solves: 516


This time running steghide extract with no password will find flag.txt

steghide extract -sf doh.jpg
cat flag.txt



  • Clue: This time we have a username. Can you track down NahamConTron?
  • Points: 50
  • Solves: 702

The challenge name suggests Instagram, so I looked up the username and the flag is in the account’s bio.




  • Clue: cowsay is hiding something from us!
  • Points: 20
  • Solves: 1908

We are given a binary. Running it gives us:

/ Sorry, I'm not allow to reveal any \
\ secrets...                         /
         \   ^__^ 
          \  (oo)\_______
             (__)\       )\/\
                 ||----w |
                 ||     ||

Use strings to find the flag

strings clisay

/ Sorry, I'm not allow to reveal any \
\ secrets...                         /
         \   ^__^ 
          \  (oo)\_______
             (__)\       )\/\
                 ||----w |
                 ||     ||

Note: Using grep will only find the first half of the flag


  • Clue: Hacker memes. So meta.
  • Points: 25
  • Solves: 2019


Running strings on the image will give us the flag

strings hackermeme.jpg | grep flag

Mr. Robot

  • Clue: Elliot needs your help. You know what to do.
  • Points: 25
  • Solves: 1581

jh2i.com:50032 A static webpage. The flag is in robots.txt http://jh2i.com:50032/robots.txt


  • Clue: Become the admin!
  • Points: 30
  • Solves: 1310

If we edit the cookie on the page to set user to admin, we get “you are logged in as nqzva.” This is the rot 13 of admin, so setting the cookie to nqzva and refreshing will give us the flag.


Easy Keesy

  • Clue: Dang it, not again…
  • Points: 30
  • Solves: 670

We are given a keepass database file. We can crack the password using john.

keepass2john easy_keesy > keehash

john -format:keepass --wordlist=/usr/share/wordlists/rockyou.txt keehash

The password is monkey, We can open the database in keepass to get the flag.


I used PCRT to fix the image

python PCRT.py -i pang.png -o pong.png