Loki 1.8: dokumen tentang Pencuri Data muda dan yang akan datang





Pada pertengahan Juni, perang melawan virus korona di Kazakhstan berjalan lancar. Khawatir dengan meningkatnya jumlah kasus (bahkan mantan Presiden Nursultan Nazarbayev terinfeksi), otoritas lokal memutuskan untuk menutup kembali semua pusat perbelanjaan dan hiburan, toko rantai, pasar dan bazar. Pada saat itu, penjahat dunia maya memanfaatkan situasi tersebut dengan mengirimkan surat jahat ke perusahaan Rusia dan internasional.



Surat-surat berbahaya, yang disamarkan sebagai seruan dari Menteri Kesehatan Republik Kazakhstan, dicegat oleh IB Grup Sistem Deteksi Ancaman (TDS). Lampiran berisi dokumen yang, ketika diluncurkan, menginstal program jahat dari keluarga Loki PWS (Pencuri Kata Sandi), yang dirancang untuk mencuri login dan kata sandi dari komputer yang terinfeksi. Di masa mendatang, penyerang dapat menggunakannya untuk mendapatkan akses ke akun email untuk penipuan finansial, spionase, atau menjualnya di forum peretas.



Dalam artikel ini, Nikita Karpov, analis di CERT-GIB , memeriksa salah satu Pencuri Data paling populer saat ini - Loki.



Hari ini kita akan mempertimbangkan salah satu versi bot yang populer - 1.8. Ini secara aktif dijual, dan panel admin bahkan dapat ditemukan di domain publik: di sini .



Contoh panel Admin:







Loki ditulis dalam C ++ dan merupakan salah satu malware paling populer yang digunakan untuk mencuri informasi pengguna dari komputer yang terinfeksi. Sama seperti momok di zaman kita - virus ransomware - Pencuri Data, setelah diserang di komputer korban, melakukan tugas dengan kecepatan sangat tinggi - tidak perlu mendapatkan pijakan dan meningkatkan keistimewaannya dalam sistem, ia hampir tidak menyisakan waktu untuk bertahan dari serangan. Oleh karena itu, dalam acara dengan malware yang mencuri data pengguna, peran utama dimainkan oleh investigasi insiden tersebut.



Membongkar dan mendapatkan dump malware yang bisa diterapkan



Distribusi dalam banyak kasus terjadi melalui lampiran di milis. Pengguna, menyamar sebagai file yang sah, mengunduh dan membuka lampiran, meluncurkan malware.



Penanda injeksi menunjukkan keberadaan Loader.





Dengan bantuan DIE kami mendapatkan informasi bahwa file sumber ditulis dalam VB6.





Grafik entropi menunjukkan sejumlah besar data terenkripsi.





Saat diluncurkan, proses pertama membuat proses anak, menyuntikkannya, dan keluar. Proses kedua bertanggung jawab atas kerja malware. Setelah beberapa saat, kami menghentikan proses dan menyimpan dump memori. Untuk mengonfirmasi bahwa Loki ada di dalam dump, lihat di dalam url pusat perintah, yang biasanya diakhiri dengan fre.php .





Kami membuang fragmen memori yang berisi Loki dan menyesuaikan header PE.



Kami akan memeriksa kinerja dump menggunakan sistem TDS Huntbox.





Fungsi bot



Dalam proses pemeriksaan kode malware yang telah didekompilasi, kami menemukan bagian yang berisi empat fungsi yang segera berjalan setelah inisialisasi pustaka yang diperlukan untuk operasi tersebut. Setelah membongkar masing-masing di dalamnya, kami menentukan tujuan dan fungsinya dari malware kami.





Nama fungsi telah diganti namanya menjadi lebih deskriptif untuk kenyamanan.

Fungsionalitas bot ditentukan oleh dua fungsi utama:



  1. Pencuri Data adalah fungsi pertama yang bertanggung jawab untuk mencuri data dari 101 aplikasi dan mengirimkannya ke server.
  2. Downloader - permintaan dari perintah CnC (Command & Control) untuk dieksekusi.


Demi kenyamanan, tabel di bawah mencantumkan semua aplikasi tempat instans Loki yang sedang diperiksa mencoba mencuri data.

ID Fungsi aplikasi ID Fungsi aplikasi ID Fungsi aplikasi
1 Mozilla Firefox 35 FTPInfo 69 ClassicFTP
2 Comodo IceDragon 36 LinasFTP 70 Putty / KiTTY
3 Apple Safari 37 FileZilla 71 Thunderbird
4 K-Meleon 38 Staf-FTP 72 Foxmail
lima SeaMonkey 39 BlazeFtp 73 Pocomail
6 Kawanan 40 NETFile 74 IncrediMail
7 JARINGAN BlackHawk 41 GoFTP 75 Gmail notifier pro
8 Lunascape 42 ALFTP 76 Memeriksa surat
sembilan Google chrome 43 DeluxeFTP 77 WinFtp
sepuluh Opera 44 Komandan Total 78 Martin Prikryl
sebelas Browser QTWeb 45 FTPGetter 79 32BitFtp
12 QupZilla 46 WS_FTP 80 FTP Navigator
tigabelas Internet Explorer 47 File konfigurasi Klien Email 81 Surat

(softwarenetz)
empat belas Opera 2 48 Poker kemiringan penuh 82 Opera Mail
limabelas Cyberfox 49 Pokerstars 83 Kotak pos
enambelas Bulan pucat 50 ExpanDrive 84 FossaMail
17 Waterfox 51 Kuda 85 Becky!
delapan belas Pidgin 52 FlashFXP 86 POP3
19 SuperPutty 53 NovaFTP 87 Pandangan
20 FTPShell 54 NetDrive 88 Ymail2
21 NppFTP 55 Total Komandan 2 89 Trojitá
22 MyFTP 56 SmartFTP 90 TrulyMail
23 FTPBox 57 Manajer FAR 91 File .spn
24 sherrod FTP 58 Bitvise 92 Daftar Tugas
25 FTP Sekarang 59 RealVNC

TightVNC
93 Perekat
26 NexusFile 60 Dompet mSecure 94 NoteFly
27 Xftp 61 Syncovery 95 NoteZilla
28 EasyFTP 62 FreshFTP 96 Catatan tempel
29 SftpNetDrive 63 BitKinex 97 KeePass
tigapuluh AbleFTP 64 UltraFXP 98 Enpass
31 JaSFtp 65 FTP Sekarang 2 99 RoboForm saya
32 Otomatiskan 66 Vandyk SecureFX 100 1Password
33 Cyberduck 67 Pakar FTP Aman Odin 101 Mikrotik WinBox
34 Fullsync 68 Melemparkan
Pada tahap ini, analisis statis malware selesai, dan di bagian selanjutnya kita akan mempertimbangkan bagaimana Loki berkomunikasi dengan server.



Jaringan



Ada dua masalah yang perlu ditangani untuk merekam interaksi jaringan:



  1. Pusat Komando hanya tersedia pada saat penyerangan.
  2. Wireshark tidak merekam komunikasi bot di loopback, jadi Anda perlu menggunakan cara lain.


Solusi paling sederhana adalah mengarahkan ulang alamat CnC yang akan berkomunikasi dengan Loki ke localhost. Untuk bot, server sekarang tersedia kapan saja, meskipun tidak merespons, tetapi tidak perlu merekam komunikasi bot. Untuk mengatasi masalah kedua, kita akan menggunakan utilitas RawCap, yang memungkinkan kita untuk menulis komunikasi yang kita butuhkan ke pcap. Selanjutnya, kami akan mengurai pcap yang direkam di Wireshark.





Sebelum setiap komunikasi, bot memeriksa ketersediaan CnC dan, jika tersedia, membuka soket. Semua komunikasi jaringan berlangsung di lapisan transport menggunakan protokol TCP, dan HTTP digunakan di lapisan aplikasi.



Tabel di bawah ini menunjukkan header paket yang digunakan Loki sebagai standar.

Bidang Nilai Deskripsi
Agen pengguna Mozilla / 4.08 (Charon; Inferno) Agen pengguna khas untuk Loki
Menerima * / *
Jenis konten aplikasi / aliran oktet
Pengkodean Konten biner
Content-Key 7DE968CC Hasil hashing dari header sebelumnya (hashing dilakukan oleh algoritma CRC kustom dengan polinomial 0xE8677835)
Koneksi Menutup
Mari perhatikan body paketnya:



  1. Struktur data yang direkam bergantung pada versi bot, dan di versi sebelumnya tidak ada bidang yang bertanggung jawab untuk opsi enkripsi dan kompresi.
  2. Server menentukan bagaimana memproses data yang diterima berdasarkan jenis permintaan. Ada 7 jenis data yang bisa dibaca server:

    • 0x26 Data dompet curian
    • 0x27 Data Aplikasi yang Dicuri
    • 0x28 Permintaan perintah dari server
    • 0x29 Membongkar file yang dicuri
    • 0x2A POS
    • Data Keylogger 0x2B
    • Tangkapan Layar 0x2C
  3. Dalam contoh yang diperiksa, hanya ada 0x27, 0x28 dan 0x2B.
  4. Setiap permintaan berisi informasi umum tentang bot dan sistem yang terinfeksi, yang menurutnya server mengidentifikasi semua laporan untuk satu mesin, dan kemudian ada informasi yang bergantung pada jenis permintaan.
  5. Dalam versi terbaru bot, hanya kompresi data yang diterapkan, dan bidang terenkripsi disiapkan untuk masa depan dan tidak diproses oleh server.
  6. Library APLib open source digunakan untuk mengompres data.


Saat membuat permintaan dengan data yang dicuri, bot mengalokasikan buffer berukuran 0x1388 (5000 byte). Struktur permintaan 0x27 ditunjukkan pada tabel di bawah ini:

Bias Ukuran Nilai Deskripsi
0x0 0x2 0x0012 Versi bot
0x2 0x2 0x0027 Jenis permintaan (kirim data yang dicuri)
0x4 0xD ckav.ru ID Biner (XXXXX11111 juga terjadi)
0x11 0x10 - Nama pengguna
0x21 0x12 - Nama komputer
0x33 0x12 - Nama domain komputer
0x45 0x4 - Resolusi layar (lebar dan tinggi)

0x49 0x4 -
0x4D 0x2 0x0001 Bendera hak pengguna (1 jika administrator)
0x4F 0x2 0x0001 Bendera SID (1 jika diatur)
0x51 0x2 0x0001 Bendera bit sistem (1 jika x64)
0x53 0x2 0x0006 Versi Windows (nomor versi utama)
0x55 0x2 0x0001 Versi Windows (nomor versi minor)
0x57 0x2 0x0001 Informasi sistem tambahan (1 = VER_NT_WORKSTATION)
0x59 0x2 -
0x5B 0x2 0x0000 Apakah data yang dicuri dikirim
0x5D 0x2 0x0001 Apakah kompresi data digunakan
0x5F 0x2 0x0000 Jenis kompresi
0x61 0x2 0x0000 Apakah enkripsi data digunakan
0x63 0x2 0x0000 Tipe enkripsi
0x65 0x36 - MD5 dari nilai register MachineGuid
0x9B - - Data curian terkompresi
Tahap kedua interaksi dengan server dimulai setelah diperbaiki dalam sistem. Bot mengirimkan permintaan dengan tipe 0x28, yang strukturnya ditunjukkan di bawah ini:



Ukuran buffer: 0x2BC (700 byte)

Bias Ukuran Nilai Deskripsi
0x0 0x2 0x0012 Versi bot
0x2 0x2 0x0028 Jenis permintaan (permintaan perintah dari pusat perintah)
0x4 0xD ckav.ru ID Biner (XXXXX11111 juga terjadi)
0x11 0x10 - Nama pengguna
0x21 0x12 - Nama komputer
0x33 0x12 - Nama domain komputer
0x45 0x4 - Resolusi layar (lebar dan tinggi)
0x49 0x4 -
0x4D 0x2 0x0001 Bendera hak pengguna (1 jika administrator)
0x4F 0x2 0x0001 Bendera SID (1 jika diatur)
0x51 0x2 0x0001 Bendera bit sistem (1 jika x64)
0x53 0x2 0x0006 Versi Windows (nomor versi utama)
0x55 0x2 0x0001 Versi Windows (nomor versi minor)
0x57 0x2 0x0001 Informasi sistem tambahan (1 = VER_NT_WORKSTATION)
0x59 0x2 0xFED0
0x5B 0x36 - MD5 dari nilai register MachineGuid
Setelah permintaan, bot mengharapkan untuk menerima respon dari server yang berisi nomor dan perintah itu sendiri. Varian perintah yang mungkin diperoleh menggunakan analisis statis dari kode malware yang didekompilasi dan disajikan di bawah ini.



Ukuran buffer: 0x10 (16 byte) + 0x10 (16 byte) untuk setiap perintah dalam paket.

Header HTTP (awal data) \ r \ n \ r \ n [0D 0A 0D 0A] 4 byte
- - 4
2 [00 00 00 02] 4


4


4


4


4



()

#0

EXE-
[00 00 00 00] [00 00 00 00] [00 00 00 00] [00 00 00 23] www.notsogood.site/malicious.exe
#1

DLL
[00 00 00 00] [00 00 00 01] [00 00 00 00] [00 00 00 23] www.notsogood.site/malicious.dll
#2

EXE-
[00 00 00 00] [00 00 00 02] [00 00 00 00] [00 00 00 23] www.notsogood.site/malicious.exe
#8

(HDB file)
[00 00 00 00] [00 00 00 08] [00 00 00 00] [00 00 00 00] -
#9

[00 00 00 00] [00 00 00 09] [00 00 00 00] [00 00 00 00] -
#10

[00 00 00 00] [00 00 00 0A] [00 00 00 00] [00 00 00 00] -
#14

Loki
[00 00 00 00] [00 00 00 0E] [00 00 00 00] [00 00 00 00] -
#15

Loki
[00 00 00 00] [00 00 00 0F] [00 00 00 00] [00 00 00 23] www.notsogood.site/malicious.exe
# 16

Ubah frekuensi pemeriksaan respons dari server
[00 00 00 00] [00 00 00 10] [00 00 00 00] [00 00 00 01] lima
# 17

Hapus Loki dan keluar
[00 00 00 00] [00 00 00 11] [00 00 00 00] [00 00 00 00] -


Pengurai lalu lintas jaringan



Berkat analisis ini, kami memiliki semua informasi yang kami butuhkan untuk mengurai interaksi jaringan Loki.



Pengurai diimplementasikan dengan Python, menerima file pcap sebagai input dan menemukan semua komunikasi milik Loki di dalamnya.



Pertama, mari gunakan pustaka dkpt untuk menemukan semua paket TCP. Untuk hanya menerima paket http, mari kita beri filter pada port yang digunakan. Di antara paket http yang diterima, kami memilih yang berisi header Loki terkenal, dan mendapatkan komunikasi yang perlu diurai untuk mengekstrak informasi darinya dalam bentuk yang dapat dibaca.



for ts, buf in pcap:
    eth = dpkt.ethernet.Ethernet(buf)
    if not isinstance(eth.data, dpkt.ip.IP):
        ip = dpkt.ip.IP(buf)
    else:
        ip = eth.data
 
    if isinstance(ip.data, dpkt.tcp.TCP):
        tcp = ip.data
        try:
            if tcp.dport == 80 and len(tcp.data) > 0:  # HTTP REQUEST
                if str(tcp.data).find('POST') != -1:
                    http += 1
                    httpheader = tcp.data
                    continue
                else:
                    if httpheader != "":
                        print('Request information:')
 
                        pkt = httpheader + tcp.data
                        httpheader = ""
                        if debug:
                            print(pkt)
                        req += 1
                        request = dpkt.http.Request(pkt)
                        uri = request.headers['host'] + request.uri
                        parsed_payload['Network']['Source IP'] = socket.inet_ntoa(ip.src)
                        parsed_payload['Network']['Destination IP'] = socket.inet_ntoa(ip.dst)
                        parsed_payload_same['Network']['CnC'] = uri
                        parsed_payload['Network']['HTTP Method'] = request.method
 
                        if uri.find("fre.php"):
                            print("Loki detected!")
                        pt = parseLokicontent(tcp.data, debug)
                        parsed_payload_same['Malware Artifacts/IOCs']['User-Agent String'] = request.headers['user-agent']
 
                        print(json.dumps(parsed_payload, ensure_ascii=False, sort_keys=False, indent=4))
                        parsed_payload['Network'].clear()
                        parsed_payload['Compromised Host/User Data'].clear()
                        parsed_payload['Malware Artifacts/IOCs'].clear()
                        print("----------------------")
            if tcp.sport == 80 and len(tcp.data) > 0:  # HTTP RESPONCE
                resp += 1
                if pt == 40:
                    print('Responce information:')
                    parseC2commands(tcp.data, debug)
                    print("----------------------")
                    pt = 0
        except(dpkt.dpkt.NeedData, dpkt.dpkt.UnpackError):
            continue


Di semua permintaan Loki, 4 byte pertama bertanggung jawab atas versi bot dan jenis permintaan. Dengan menggunakan dua parameter ini, kami menentukan bagaimana kami akan memproses data.



def parseLokicontent(data, debug):
    index = 0
 
    botV = int.from_bytes(data[0:2], byteorder=sys.byteorder)
    parsed_payload_same['Malware Artifacts/IOCs']['Loki-Bot Version'] =  botV
 
    payloadtype = int.from_bytes(data[2:4], byteorder=sys.byteorder)
    index = 4
    print("Payload type: : %s" % payloadtype)
    if payloadtype == 39:
        parsed_payload['Network']['Traffic Purpose'] =  "Exfiltrate Application/Credential Data"
        parse_type27(data, debug)
    elif payloadtype == 40:
        parsed_payload['Network']['Traffic Purpose'] = "Get C2 Commands"
        parse_type28(data, debug)
    elif payloadtype == 43:
        parsed_payload['Network']['Traffic Purpose'] = "Exfiltrate Keylogger Data"
        parse_type2b(lb_payload)
    elif payloadtype == 38:
        parsed_payload['Network']['Traffic Purpose'] = "Exfiltrate Cryptocurrency Wallet"
    elif payloadtype == 41:
        parsed_payload['Network']['Traffic Purpose'] = "Exfiltrate Files"
    elif payloadtype == 42:
        parsed_payload['Network'].['Traffic Purpose'] = "Exfiltrate POS Data"
    elif payloadtype == 44:
        parsed_payload['Network']['Traffic Purpose'] = "Exfiltrate Screenshots"
 
    return payloadtype


Baris berikutnya adalah mengurai respons dari server. Untuk membaca hanya informasi yang berguna, cari urutan \ r \ n \ r \ n , yang menentukan akhir dari header paket dan awal perintah dari server.



def parseC2commands(data, debug):
    word = 2
    dword = 4
    end = data.find(b'\r\n\r\n')
    if end != -1:
        index = end + 4
        if (str(data).find('<html>')) == -1:
            if debug:
                print(data)
            fullsize = getDWord(data, index)
            print("Body size: : %s" % fullsize)
            index += dword
            count = getDWord(data, index)
            print("Commands: : %s" % count)
            if count == 0:
                print('No commands received')
            else:
                index += dword
                for i in range(count):
                    print("Command: %s" % (i + 1))
 
                    id = getDWord(data, index)
                    print("Command ID: %s" % id)
                    index += dword
 
                    type = getDWord(data, index)
                    print("Command type: %s" % type)
                    index += dword
 
                    timelimit = getDWord(data, index)
                    print("Command timelimit: %s" % timelimit)
                    index += dword
 
                    datalen = getDWord(data, index)
                    index += dword
 
                    command_data = getString(data, index, datalen)
                    print("Command data: %s" % command_data)
                    index += datalen
        else:
            print('No commands received')
    return None


Ini menyimpulkan analisis dari bagian utama algoritma parser dan beralih ke hasil yang kita dapatkan pada keluaran. Semua informasi ditampilkan dalam format json.



Di bawah ini adalah gambar hasil kerja parser, diperoleh dari komunikasi berbagai bot, dengan CnC berbeda dan direkam di lingkungan berbeda.



Request information:
Loki detected!
Payload type: 39
Decompressed data: 
{'Module': {'Mozilla Firefox'}, 'Version': {0}, 'Data': {'domain': {'https://accounts.google.com'}, 'username': {'none@gmail.com'}, 'password': {'test'}}}
{'Module': {'NppFTP'}, 'Version': {0}, 'Data': {b'<?xml version="1.0" encoding="UTF-8" ?>\r\n<NppFTP defaultCache="%CONFIGDIR%\\Cache\\%USERNAME%@%HOSTNAME%" outputShown="0" windowRatio="0.5" clearCache="0" clearCachePermanent="0">\r\n    <Profiles />\r\n</NppFTP>\r\n'}}
{
    "Network": {
        "Source IP": "-",
        "Destination IP": "185.141.27.187",
        "HTTP Method": "POST",
        "Traffic Purpose": "Exfiltrate Application/Credential Data",
        "First Transmission": true
    },
    "Compromised Host/User Data": {},
    "Malware Artifacts/IOCs": {}
}


Di atas adalah contoh request ke server 0x27 (mengupload data aplikasi). Untuk pengujian, akun dibuat dalam tiga aplikasi: Mozilla Firefox, NppFTP dan FileZilla. Loki memiliki tiga pilihan untuk merekam data aplikasi:



  1. Dalam bentuk database SQL (parser menyimpan database dan menampilkan semua baris yang tersedia di dalamnya).
  2. Dalam bentuk terbuka, seperti di Firefox pada contoh.
  3. Sebagai file xml, seperti NppFTP dan FileZilla.


Request information:
Loki detected!
Payload type: 39
No data stolen
{
    "Network": {
        "Source IP": "-",
        "Destination IP": "185.141.27.187",
        "HTTP Method": "POST",
        "Traffic Purpose": "Exfiltrate Application/Credential Data",
        "First Transmission": false
    },
    "Compromised Host/User Data": {},
    "Malware Artifacts/IOCs": {}
}


Permintaan kedua adalah tipe 0x28 dan meminta perintah dari server.



Responce information:
Body size: 26
Commands: 1
Command: 1
Command ID: 0
Command type: 9
Command timelimit: 0
Command data: 35


Contoh respons dari CnC, yang mengirimkan satu perintah sebagai respons untuk memulai keylogger. Dan pembongkaran selanjutnya dari data keylogger.



Request information:
Loki detected!
Payload type: : 43
{
    "Network": {
        "Source IP": "-",
        "Destination IP": "185.141.27.187",
        "HTTP Method": "POST",
        "Traffic Purpose": "Exfiltrate Keylogger Data"
    },
    "Compromised Host/User Data": {},
    "Malware Artifacts/IOCs": {}
}


Di akhir pekerjaan, parser mengeluarkan informasi yang terkandung dalam setiap permintaan dari bot (informasi tentang bot dan sistem), dan jumlah permintaan dan tanggapan yang terkait dengan Loki di file pcap.



General information:
{
    "Network": {
        "CnC": "nganyin-my.com/chief6/five/fre.php"
    },
    "Compromised Host/User Description": {
        "User Name": "-",
        "Hostname": "-",
        "Domain Hostname": "-",
        "Screen Resolution": "1024x768",
        "Local Admin": true,
        "Built-In Admin": true,
        "64bit OS": false,
        "Operating System": "Windows 7 Workstation"
    },
    "Malware Artifacts/IOCs": {
        "Loki-Bot Version": 18,
        "Binary ID": "ckav.ru",
        "MD5 from GUID": "-",
        "User-Agent String": "Mozilla/4.08 (Charon; Inferno)"
    }
}
Requests: 3
Responces: 3 




Kode parser lengkap tersedia di: github.com/Group-IB/LokiParser



Kesimpulan



Dalam artikel ini, kami melihat lebih dekat malware Loki, membongkar fungsinya, dan menerapkan pengurai lalu lintas jaringan yang akan sangat menyederhanakan proses analisis insiden dan membantu kami memahami apa yang sebenarnya dicuri dari komputer yang terinfeksi. Sementara pengembangan Loki masih berlangsung, hanya versi 1.8 (dan sebelumnya) yang telah digabungkan, yang merupakan versi yang ditemui oleh para profesional keamanan setiap hari.



Di artikel berikutnya, kami akan menganalisis Pencuri Data populer lainnya, Pony, dan membandingkan malware ini.



Indikator Kompromi (IOC):



Url:



  • nganyin-my.com/chief6/five/fre.php
  • wardia.com.pe/wp-includes/texts/five/fre.php
  • broken2.cf/Work2/fre.php
  • 185.141.27.187/danielsden/ver.php
  • Hash MD5: B0C33B1EF30110C424BABD66126017E5
  • User-Agent String: «Mozilla/4.08 (Charon; Inferno)»
  • Binary ID: «ckav.ru»



All Articles