还不完整, 继续整理中
// 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;
}