چالش بدافزار اول - dmesg

توضیحات

من فکر می‌کردم خیلی باهوش هستم، یه کلید ساختم یه رازی رو باهاش رمز کردم، کلید رو جای دوری مخفی‌اش کردم ولی متاسفانه گرفتار بدافزار شدم.
امیدوارم بدافزارِ باهوشی نبوده باشه.

قالب پرچم در این سوال به صورت some_l33t_string است.

حل چالش

گام اول

پس از بارگیری سوال و استخراج محتوای آن، در اولین گام نوع پرونده را با دستور file تشخیص می‌دهیم:

memory.dump: ELF 64-bit LSB core file, x86-64, version 1 (SYSV)

اما با توجه به اندازۀ فایل، احتمالاً این فایل از جنس اجرایی نیست! و البته از اسم فایل هم پی می‌بریم که یک دامپ حافظه است.

در سوالاتی که با دامپ حافظه روبرو هستیم، معمولاً چند کار را انجام می‌دهیم:

  • مشاهده رشته‌های موجود در حافظه

  • تشخیص نوع سیستم‌عامل برای استفاده در ابزار volatility

  • یافتن پردازه‌هایی که در حافظه در حال اجرا بودند

  • جستجو به دنبال چند کلیدواژه خاص که از متن سوال یا اسم فایل‌ها گرفته‌ایم

و کارهایی از این قبیل. حال ترکیبی از این موارد را انجام می‌دهیم.

گام دوم

ابتدا به دنبال نسخه سیستم‌عامل می‌گردیم. برای اینکار در رشته‌های قابل چاپ حافظه عبارت linux version را فیلتر می‌کنیم:

parcham $ strings memory.dump | grep -i "linux version"
Oct 25 04:47:39 debian kernel: [    0.000000] Linux version 3.16.0-4-amd64 (debian-kernel@lists.debian.org) (gcc version 4.8.4 (Debian 4.8.4-1) ) #1 SMP Debian 3.16.51-2 (2017-12-03)
MESSAGE=Linux version 3.16.0-4-amd64 (debian-kernel@lists.debian.org) (gcc version 4.8.4 (Debian 4.8.4-1) ) #1 SMP Debian 3.16.51-2 (2017-12-03)
Linux version 3.16.0-4-amd64 (debian-kernel@lists.debian.org) (gcc version 4.8.4 (Debian 4.8.4-1) ) #1 SMP Debian 3.16.51-2 (2017-12-03)
Linux version 3.16.0-4-amd64 (debian-kernel@lists.debian.org) (gcc version 4.8.4 (Debian 4.8.4-1) ) #1 SMP Debian 3.16.51-2 (2017-12-03)
Linux version %d.%d.%d
2020-10-25T04:47:39.796897-04:00 debian kernel: [    0.000000] Linux version 3.16.0-4-amd64 (debian-kernel@lists.debian.org) (gcc version 4.8.4 (Debian 4.8.4-1) ) #1 SMP Debian 3.16.51-2 (2017-12-03)
Oct 25 04:47:39 debian kernel: [    0.000000] Linux version 3.16.0-4-amd64 (debian-kernel@lists.debian.org) (gcc version 4.8.4 (Debian 4.8.4-1) ) #1 SMP Debian 3.16.51-2 (2017-12-03)
Oct 25 04:47:39 debian kernel: [    0.000000] Linux version 3.16.0-4-amd64 (debian-kernel@lists.debian.org) (gcc version 4.8.4 (Debian 4.8.4-1) ) #1 SMP Debian 3.16.51-2 (2017-12-03)

پس متوجه می‌شویم که با نسخه debian 3.16 روبرو هستیم. حال به سراغ ابزار volatility می‌رویم و پروفایل‌های مربوط به این نسخه را دانلود می‌کنیم (اگر در اضافه کردن پروفایل به مشکل خوردید ویدیو مقدمه قسمت آیرو را ببینید). با استفاده از volatility ابتدا یک bash می‌گیریم تا لیستی از دستوراتی که زده شده را ببینیم:

parcham $ python2 vol.py --profile=LinuxDebian86x64 -f memory.dump linux_bash
Pid      Name                 Command Time                   Command
-------- -------------------- ------------------------------ -------
 798 bash                 2020-10-25 08:48:22 UTC+0000   cat cron.log
 798 bash                 2020-10-25 08:48:52 UTC+0000   su root -c 'echo YES!! > /dev/kmsg'
 798 bash                 2020-10-25 08:49:04 UTC+0000   su root -c 'echo READ ME! > /dev/kmsg'
 798 bash                 2020-10-25 08:49:13 UTC+0000   su root -c 'echo READ DMESG! > /dev/kmsg'
 798 bash                 2020-10-25 08:49:20 UTC+0000   while read line; do echo $line > /dev/kmsg; done < cron.log
 798 bash                 2020-10-25 08:49:20 UTC+0000   [1:41 AM]
 798 bash                 2020-10-25 08:49:24 UTC+0000   while read line; do echo $line > /dev/kmsg; done < cron.log
 798 bash                 2020-10-25 08:49:25 UTC+0000   while read line; do echo $line > /dev/kmsg; done < cron.log
 798 bash                 2020-10-25 08:49:28 UTC+0000   dmesg
 798 bash                 2020-10-25 08:53:42 UTC+0000    dmesg -c
 798 bash                 2020-10-25 08:53:43 UTC+0000    dmesg -c
 798 bash                 2020-10-25 08:53:44 UTC+0000    dmesg -c
 798 bash                 2020-10-25 08:53:47 UTC+0000   while read line; do echo $line > /dev/kmsg; done < cron.log
 798 bash                 2020-10-25 08:53:49 UTC+0000   while read line; do echo $line > /dev/kmsg; done < cron.log
 798 bash                 2020-10-25 08:53:55 UTC+0000   su root -c 'echo READ DMESG! > /dev/kmsg'
 798 bash                 2020-10-25 08:53:57 UTC+0000   su root -c 'echo READ DMESG! > /dev/kmsg'

از خروجی این بخش و با توجه به اسم سوال (dmesg) متوجه می‌شویم که احتمالاً سوال مربوط به این دستور است. اول اگر با این دستور آشنا نیستیم، توضیحاتش را می‌خوانیم:

dmesg is a command on most Unix-like operating systems that prints the message buffer of the kernel. The output includes messages produced by the device drivers.

پس اطلاعاتی از پیغام‌های چاپ شده در بافر سیستم را به ما می‌دهد. حال با استفاده از volatility این دستور را اجرا می‌کنیم:

parcham $ python2 vol.py --profile=LinuxDebian86x64 -f memory.dump linux_dmesg
[85250361908.85] YES!!
[96723146667.96] READ ME!
[105589877398.105] READ DMESG!
[113188994115.113] ......::Master, this is what I found::......
[113189371706.113] 0x1d 0x5c 0x4 0x7e 0x6c 0xe 0x7f 0x50 0x3a 0x15 0x2c 0x16 0xa 0x6b 0x4 0x10 0x16 0x40 0x32 0x1e 0x6c 0x2a 0x23 0xa 0x10 0x1c 0x9 0x3a 0x42 0x7 0x52 0x17 0x27 0x6b 0x0 0x7b 0x41 0x1c 0x14 0x43 0x3a 0x3d 0x7d 0x17 0x40 0xe 0x4b 0x55 0x68 0x15 0x4c 0x41......I4mK3yKeepMes4fe
[113189538591.113] ......::I deleted myself::......
[113189686102.113] ......::Please validate them with EVIL!!::......#!/usr/bin/env python

اطلاعات زیادی در خروجی این دستور چاپ می‌شود که فقط بخش مهم آن را آورده‌ایم. در اینجا به راحتی می‌بینیم که یک پیام رمزشده به صورت hex داریم و در انتهای آن کلید مربوطه هم قرار داده شده است. همچنین نوشته شده که لطفا من رو با شیطان اجرا کن!

گام سوم

خب ادامه می‌دهیم. تا اینجا یک متن رمزشده و یک کلید داریم و به ما گفته شده که با شیطان آن را اجرا کنیم. پس به دنبال شیطان می‌گردیم.
منطقی به‌نظر می‌رسد که دنبال یک کد پایتون باشیم چون در انتهای آخرین خط از خروجی بالا از پایتون استفاده شده. اینجاست که از strings استفاده می‌کنیم و به دنبال همین رشته در دامپ می‌گردیم. مطابق با ویدیو آموزشی، ابتدا تمام رشته‌های قابل چاپ را در یک فایل ریخته و سپس با پرچم n- رشته موردنظر را جست‌وجو می‌کنیم تا بتوانیم قبل و بعد از آن را ببینیم:

parcham $ cat str.txt | grep -i "/usr/bin/env python" -n
55169:[1m......::Please validate them with EVIL!!::......#!/usr/bin/env python
192967:......::Please validate them with EVIL!!::......#!/usr/bin/env python
193022:......::Please validate them with EVIL!!::......#!/usr/bin/env python
193078:......::Please validate them with EVIL!!::......#!/usr/bin/env python
193133:......::Please validate them with EVIL!!::......#!/usr/bin/env python
193192:......::Please validate them with EVIL!!::......#!/usr/bin/env python
193256:......::Please validate them with EVIL!!::......#!/usr/bin/env python
193312:......::Please validate them with EVIL!!::......#!/usr/bin/env python
193383:......::Please validate them with EVIL!!::......#!/usr/bin/env python
193438:......::Please validate them with EVIL!!::......#!/usr/bin/env python
193502:......::Please validate them with EVIL!!::......#!/usr/bin/env python
193557:......::Please validate them with EVIL!!::......#!/usr/bin/env python
193627:......::Please validate them with EVIL!!::......#!/usr/bin/env python
193692:......::Please validate them with EVIL!!::......#!/usr/bin/env python
193747:......::Please validate them with EVIL!!::......#!/usr/bin/env python
193802:......::Please validate them with EVIL!!::......#!/usr/bin/env python
193857:......::Please validate them with EVIL!!::......#!/usr/bin/env python
193912:......::Please validate them with EVIL!!::......#!/usr/bin/env python
193967:......::Please validate them with EVIL!!::......#!/usr/bin/env python
290992:#!/usr/bin/env python
292051:        ......::Please validate them with EVIL!!::......#!/usr/bin/env python
498216:        ......::Please validate them with EVIL!!::......#!/usr/bin/env python
498272:        ......::Please validate them with EVIL!!::......#!/usr/bin/env python
538727:        ......::Please validate them with EVIL!!::......#!/usr/bin/env python
538783:        ......::Please validate them with EVIL!!::......#!/usr/bin/env python
554360:#!/usr/bin/env python

اکثر مواردی که این رشته ظاهر شده است مربوط به همان خروجی دستور dmesg است پس کاری با آنها نداریم. امّا در دو جا خود عبارت جداگانه آمده است که در آن خطوط به دنبال کد پایتون می‌گردیم.
محل اولی باز هم به درد نمی‌خورد امّا با رفتن به خط 554360 کد پایتون سالم را می‌توانیم ببینیم:

#!/usr/bin/env python 
import os 
import os.path 
import getpass
import subprocess
import itertools
import glob 
import sys
import time 
import itertools
def EVIL(s, key):
    d = s.split()
    d = [chr(int(i, 16)) for i in d]
    l =  (len(d) / len(key) + 1)
    key = key * l
    res = ' '.join(hex(ord(x) ^ ord(y)) for (x,y) in itertools.izip(d, key))
    hex_result = res.split(" ")
    result = "".join([chr(int(x, 16)) for x in hex_result])
    return result
    
def send_to_master(secret , key):
    msg = " "*11 + "......::Master, this is what I found::......\n"  
    msg += secret
    msg += "......" + key + "\n"
    f = open(sys.argv[0] , "r").read()
    msg += " "* 15 +"......::I deleted myself::......\n" 
    msg += " "*8 +"......::Please validate them with EVIL!!::......"
    msg += f 
    print (msg)
    return 
location = os.path.expanduser('~')
files = []
for r, d, f in os.walk(location):
    for item in f:
      if '.txt' in item:
          if "key" in item or "mysecret" in item:
            files.append(os.path.join(r, item))
key = ""
secret =""
for file in files:
    if "mykey" in file:
        key = file
    elif "mysecret" in file:
        secret = file
    else:
        pass
    if key and secret:
        key = open(key, "r")
        key_s = key.read().strip()
        secret = open(secret, "r")
        secret_s = secret.read().strip()
        send_to_master(secret_s, key_s)
        break

و بله! همان دو تابع شیطان و master را می‌توانیم در اینجا ببینیم. پس به پایان خط می‌رسیم و حال کافیست تا عبارت hex رمزشده را با کلید I4mK3yKeepMes4fe به تابع devil بدهیم تا پرچم را به ما بدهد. پس تکه کد زیر را به انتهای کد پایتونی که استخراج کردیم اضافه می‌کنیم.

cipher = "0x1d 0x5c 0x4 0x7e 0x6c 0xe 0x7f 0x50 0x3a 0x15 0x2c 0x16 0xa 0x6b 0x4 0x10 0x16 0x40 0x32 0x1e 0x6c 0x2a 0x23 0xa 0x10 0x1c 0x9 0x3a 0x42 0x7 0x52 0x17 0x27 0x6b 0x0 0x7b 0x41 0x1c 0x14 0x43 0x3a 0x3d 0x7d 0x17 0x40 0xe 0x4b 0x55 0x68 0x15 0x4c 0x41"
print(EVIL(cipher, "I4mK3yKeepMes4fe"))

حال بخش‌های اضافی بجز تابع شیطان را پاک کرده، کد را اجرا می‌کنیم و بوم! پرچم پیدا می‌شود:

Thi5_w45_easy_bu_t_U_ShoulD_134rn_m0re_&_M0r3:-0!!!