文件加壳实现(三) —— ZwUnmapViewOfSection

还不完整, 继续整理中


// TestShell.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include "PEOperate.h"

/*
	以挂起的形式创建进程,
	获取Context
  */

#define KEY 0x56


#pragma pack(push, 1)  
typedef struct{  
    unsigned long VirtualAddress;  
    unsigned long SizeOfBlock;  
} *PImageBaseRelocation;  
#pragma pack(pop)  			
			
// 重定向PE用到的地址  
void DoRelocation(PIMAGE_NT_HEADERS peH, void *OldBase, void *NewBase)  
{  
    unsigned long Delta = (unsigned long)NewBase - peH->OptionalHeader.ImageBase;  
    PImageBaseRelocation p = (PImageBaseRelocation)((unsigned long)OldBase   
        + peH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);  
    while(p->VirtualAddress + p->SizeOfBlock)  
    {  
        unsigned short *pw = (unsigned short *)((int)p + sizeof(*p));  
        for(unsigned int i=1; i <= (p->SizeOfBlock - sizeof(*p)) / 2; ++i)  
        {  
            if((*pw) & 0xF000 == 0x3000){  
                unsigned long *t = (unsigned long *)((unsigned long)(OldBase) + p->VirtualAddress + ((*pw) & 0x0FFF));  
                *t += Delta;  
            }  
            ++pw;  
        }  
        p = (PImageBaseRelocation)pw;  
    }  
}  


//在指定位置分配空间
BOOL AllocShellSize()
{
	typedef void *(__stdcall *pfVirtualAllocEx)(unsigned long, void *, unsigned long, unsigned long, unsigned long);  
	pfVirtualAllocEx MyVirtualAllocEx = NULL;  
	MyVirtualAllocEx = (pfVirtualAllocEx)GetProcAddress(GetModuleHandle("Kernel32.dll"), "VirtualAllocEx");  
	
	//p = MyVirtualAllocEx((unsigned long)res, (void *)peH->OptionalHeader.ImageBase, ImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);  
	//p = MyVirtualAllocEx((unsigned long)res, NULL, ImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); 
	
	

	return FALSE;
}

// 卸载原外壳占用内存  
BOOL UnloadShell(HANDLE ProcHnd, unsigned long BaseAddr)  
{  
    typedef unsigned long (__stdcall *pfZwUnmapViewOfSection)(unsigned long, unsigned long);  
    pfZwUnmapViewOfSection ZwUnmapViewOfSection = NULL;  
    BOOL res = FALSE;  
    HMODULE m = LoadLibrary("ntdll.dll");  
    if(m){  
        ZwUnmapViewOfSection = (pfZwUnmapViewOfSection)GetProcAddress(m, "ZwUnmapViewOfSection"); 
		//MessageBox(0,"1111",0,0);
        if(ZwUnmapViewOfSection)  
            res = (ZwUnmapViewOfSection((unsigned long)ProcHnd, BaseAddr) == 0);  
        FreeLibrary(m);  
    }  
    return res;  
}  


LPVOID GetLastSecData(LPSTR lpszFile,DWORD &fileSize)
{
	LPVOID pFileBuffer = NULL;
	pFileBuffer= ReadPEFile(lpszFile);
	if(!pFileBuffer)
	{
		printf("文件读取失败\n");
		return NULL;
	}
	
	PIMAGE_DOS_HEADER pDosHeader = NULL;
	PIMAGE_NT_HEADERS pNTHeader = NULL;
	PIMAGE_FILE_HEADER pPEHeader = NULL;
	PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
	PIMAGE_SECTION_HEADER pSectionHeader = NULL;
	PIMAGE_SECTION_HEADER pSectionHeader_LAST = NULL;

	//Header信息
	pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+pDosHeader->e_lfanew);
	pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader)+4);
	pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER);
	pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader+pPEHeader->SizeOfOptionalHeader);
	pSectionHeader_LAST = (PIMAGE_SECTION_HEADER)((DWORD)pSectionHeader+(pPEHeader->NumberOfSections-1)*40);

	int fileLength = pSectionHeader_LAST->PointerToRawData+pSectionHeader_LAST->SizeOfRawData;
	
	//判断是否已经加壳
	if(strcmp((char*)pSectionHeader_LAST->Name,".enSec")!=0)
	{
		MessageBox(0,"没有加壳","错误",0);
		return NULL;
	}
	
	fileSize = pSectionHeader_LAST->SizeOfRawData;
	LPVOID pEncryptBuffer = malloc(fileSize);
	memset(pEncryptBuffer,0,fileSize);
	CHAR* pNew = (CHAR*)pEncryptBuffer;

	CHAR* pOld = (CHAR*)((DWORD)pFileBuffer+pSectionHeader_LAST->PointerToRawData);

	//将最后一个段的数据拷贝到pEncryptBuffer中,并解密
	for(int i=0;i<(int)fileSize;i++)
	{
		pNew[i] = pOld[i]^KEY;
	}

	
	//关闭文件
	free(pFileBuffer);
	return pEncryptBuffer;
}





int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
 	// TODO: Place code here.
	
	TCHAR shellDirectory[256]={0};
	GetModuleFileName(NULL,shellDirectory,256);
	//MessageBox(0,shellDirectory,0,0);
	
	DWORD encryptSize = 0;

	LPVOID encryptFileBuffer = NULL;
	encryptFileBuffer = GetLastSecData(shellDirectory,encryptSize);
	
	//失败则结束
	if(encryptFileBuffer == NULL)
	{
		MessageBox(0,"解密失败","失败",0);
		//return 0;
	}
	
	//成功,goon
	//WirteToFile(encryptFileBuffer,encryptSize,"C:\\aaa.exe");
	//MessageBox(0,"结束","写出完成",MB_OK);
	
	//以挂起的形式创建进程
	
	STARTUPINFO si={0};
	si.cb = sizeof(STARTUPINFO);
	PROCESS_INFORMATION pi;
	CreateProcess(shellDirectory,
		NULL,
		NULL,
		NULL,
		FALSE,
		CREATE_SUSPENDED,
		NULL,
		NULL,
		&si,&pi);
	
	TCHAR szTempStr[256]={0};
	
	sprintf(szTempStr,"进程消息: %x , %x \n",pi.hProcess,pi.hThread);
	CONTEXT contx;
	contx.ContextFlags = CONTEXT_FULL;
	GetThreadContext(pi.hThread,&contx);
	DWORD shellOEP = contx.Eax;
	
	//获取IMAGE_BASE的信息
	char* baseAddress = (CHAR*)contx.Ebx+8;
	TCHAR szBuffer[4]={0};
	ReadProcessMemory(pi.hProcess,baseAddress,szBuffer,4,NULL);
	int* fileImageBase;
	fileImageBase = (int*)szBuffer;
	DWORD shellImageBase  = *fileImageBase;

	//卸载外壳程序
	BOOL isUnload = UnloadShell(pi.hProcess,shellImageBase);
	/*
	if(isUnload)
	{
		MessageBox(0,"成功","1",0);
	}else
	{
		MessageBox(0,"失败","0",0);
	}
	*/
	
	//在指定位置分配空间
	//位置: Src的ImageBase
	//大小:  Src的SizeOfImage
	BOOL isAlloc = AllocShellSize();

	
	
	//ResumeThread(pi.hThread);
	return 0;
}



原文链接: 文件加壳实现(三) —— ZwUnmapViewOfSection 版权所有,转载时请注明出处,违者必究。
注明出处格式:流沙团 ( https://gyarmy.com/post-369.html )

发表评论

0则评论给“文件加壳实现(三) —— ZwUnmapViewOfSection”