加壳病毒检测

一个较为简单的自动脱壳,并进行识别执行文件是否为病毒的程序,很有参考价值
/*

  EPOS - Heuristic Entry-point Obscuring (Virus) Scanner 
  and Win32. CTX.Phage disinfector

  by Piotr Bania <bania.piotr@gmail.com>
  http://pb.specialised.info

  

  */


#include		<stdio.h>
#include		<stdlib.h>
#include		<conio.h>
#include		<windows.h>



#define			O_CALL			0xE8	
#define			O_JMP			0xE9


#define			TEMP_FILE_NAME	"C:\_$temp.vir"


void			scan_file(char *name);
bool			try_disinfect(char *name, DWORD where_ctx, DWORD caller, DWORD upa, DWORD sv);




int	main(int argc, char *argv[]) {

	printf("---------------------------------------------------------------------------\n");
	printf("                  EPO-SCANNER - (c) Piotr Bania\n");
	printf("                   http://pb.specialised.info\n");
	printf("---------------------------------------------------------------------------\n");

	if (argc<2) 
	{
		printf("[!] Usage: EPO-s.exe <file>\n");
		printf("[!] Press any key to exit.\n");
		getch();
		return 0;
	}

	printf("[+] Trying to scan: %s\n",argv[1]);
	scan_file(argv[1]);
	
	return 0;
}


void scan_file(char *name) {
	HANDLE file,map;
	void* mymap;
	DWORD startrange = NULL, endrange = NULL, i = NULL, loc = NULL, temp_loc = NULL, upa = NULL;
	DWORD where_ctx = NULL,caller = NULL, sv = NULL;
	PIMAGE_DOS_HEADER pMZ = NULL;
	PIMAGE_NT_HEADERS pPE = NULL;
	PIMAGE_SECTION_HEADER pSH = NULL,pSHC = NULL;
	char *temp_name = TEMP_FILE_NAME;
	WORD sections;
	int count=0;
	

	if (!CopyFile(name,temp_name,FALSE)) 
	{
		printf("[-] Error: copying file failed - no future disinfection possible, error: %d\n",GetLastError());
	}

	
	if ((file = CreateFile(name,GENERIC_READ | FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL)) == INVALID_HANDLE_VALUE) 
	{
		printf("[-] Error: Cannot open file - error: %d\n",GetLastError());
		goto error_mode1;
	}

	if ((map = CreateFileMapping(file,NULL,PAGE_READWRITE | SEC_COMMIT,NULL,NULL,NULL)) == NULL) 
	{
		printf("[-] Error: Cannot create map of file - error: %d\n",GetLastError());
		goto error_mode2;
	}

	if ((mymap = MapViewOfFile(map,FILE_MAP_ALL_ACCESS,NULL,NULL,NULL)) == NULL) 
	{
		printf("[-] Error: Cannot create map view of file - error: %d\n",GetLastError());
		goto error_mode3;
	}

	pMZ=(PIMAGE_DOS_HEADER) mymap;

	if (pMZ->e_magic != IMAGE_DOS_SIGNATURE) 
	{
		printf("[-] Error: Bad MZ signature\n");
		goto error_mode4;
	}

	pPE=(PIMAGE_NT_HEADERS) ((DWORD)mymap + pMZ->e_lfanew);

	if (IsBadReadPtr((VOID*)pPE,sizeof(PIMAGE_NT_HEADERS)) == TRUE) 
	{
		printf("[-] Error: Bad PE file\n");
		goto error_mode4;
	}

	if (pPE->Signature != IMAGE_NT_SIGNATURE || pPE->FileHeader.NumberOfSections == NULL) 
	{
		printf("[-] Error: Bad PE file\n");
		goto error_mode4;
	}

	if (pPE->OptionalHeader.ImageBase <= 0 || pPE->OptionalHeader.AddressOfEntryPoint <= 0 || pPE->FileHeader.NumberOfSections <= 0) 
	{
		printf("[-] Error: Bad PE file\n");
		goto error_mode4;
	}

	printf("[+] Imagebase: 0x%.08x - Entrypoint: 0x%.08x (0x%.08x)\n",pPE->OptionalHeader.ImageBase,pPE->OptionalHeader.AddressOfEntryPoint,pPE->OptionalHeader.ImageBase+pPE->OptionalHeader.AddressOfEntryPoint);

	sections = pPE->FileHeader.NumberOfSections;
	pSH = (PIMAGE_SECTION_HEADER)((DWORD)mymap+pMZ->e_lfanew + sizeof(IMAGE_NT_HEADERS));
	
	
	while (sections != 0) 
	{
		if (IsBadReadPtr(&pSH,sizeof(PIMAGE_SECTION_HEADER)) == TRUE) 
		{
			printf("[-] Error: Bad PE file\n");
			goto error_mode4;
		}

		char *secname=(char *) pSH->Name;
		if (secname == NULL) strcpy(secname,"NONAME");

		startrange=(DWORD) pSH->VirtualAddress + pPE->OptionalHeader.ImageBase;
		endrange=(DWORD) startrange + pSH->Misc.VirtualSize;

		if (startrange <=0 || startrange <= pPE->OptionalHeader.ImageBase || endrange <=0 || pPE->OptionalHeader.ImageBase <= 0 || pSH->Misc.PhysicalAddress < 0 || pSH->SizeOfRawData < 0) 
		{
			printf("[-] Error: The %s section is broken\n",secname);
			goto error_mode4;
		}

		if (pSH->VirtualAddress <= pPE->OptionalHeader.AddressOfEntryPoint && pPE->OptionalHeader.AddressOfEntryPoint < pSH->VirtualAddress + pSH->Misc.VirtualSize) 
		{
			printf("[+] Checking call/jump requests from %s section (EP)\n",secname);
			pSHC = pSH;
		}

	
		pSH++;
		sections--;
	}

	pSH--;
	
	if (pSHC == NULL) 
	{
		printf("[-] Error: invalid entrypoint\n");
		goto error_mode4;
	}


	printf("[+] Starting heuristics scan on %s section...\n\n",pSHC->Name);

	if (pSHC == pSH) 
	{
		printf("[!] Alert: Entrypoint points to last section (%s) -> 0x%.08x\n",pSH->Name,pPE->OptionalHeader.AddressOfEntryPoint + pPE->OptionalHeader.ImageBase);
		printf("[!] Alert: The file may be infected!\n");
		printf("[+] No deep-scan action was performed\n");
		goto error_mode4;
	}


	printf("[+] Starting from offset: 0x%.08x\n",pPE->OptionalHeader.ImageBase + pSHC->VirtualAddress);

	for (i = 0; (i != pSHC->SizeOfRawData); i++) 
	{
		loc = (DWORD)((DWORD)mymap + pSHC->PointerToRawData) + i;
		
		if ((*(BYTE*)loc) == O_CALL || (*(BYTE*)loc) == O_JMP ) 
		{
			loc++;
			temp_loc = (DWORD)((DWORD)pSHC->VirtualAddress + i + (*(DWORD*)loc)) + 5;
		
			if (temp_loc >= pSH->VirtualAddress && temp_loc <= pSH->VirtualAddress + pSH->Misc.VirtualSize) 
			{
				printf("[!] Alert: Detected request to %s(0x%.08x) section at: 0x%.08x\n",pSH->Name,pPE->OptionalHeader.ImageBase + temp_loc, pSHC->VirtualAddress + pPE->OptionalHeader.ImageBase + i);
				if (where_ctx == NULL) 
				{
					where_ctx = (DWORD)(pPE->OptionalHeader.ImageBase + temp_loc);
					caller = (DWORD)(pSHC->VirtualAddress + pPE->OptionalHeader.ImageBase + i);
					upa = (DWORD)(pSH->VirtualAddress + pPE->OptionalHeader.ImageBase);
					sv = loc - 1;
					
				}
				count++;
			}
			loc--;
		}

	}
	
	printf("[+] Scan finished, %d suspected instruction(s) found.\n",count);
	if (count != 0) 
	{
		printf("[!] Warning: the file may be infected!\n");
		printf("\n[?] Do you want to try dis-infect the file?\n");
		printf("[?] Warning: the file may be executed if this is not the CTX.Phage\n");
		printf("    infection.\n");
		printf("[?] Disinfect: (y)es / (n)o  ? \n");

		if (getch() == 'y') try_disinfect(name, where_ctx, caller, upa, sv);
		

	}

	error_mode4:
		UnmapViewOfFile(mymap);

	error_mode3:
		CloseHandle(map);
		
	error_mode2:
		CloseHandle(file);

	error_mode1:
		DeleteFile(temp_name);

}


bool try_disinfect(char *name, DWORD where_ctx, DWORD caller, DWORD upa, DWORD sv) {
	STARTUPINFO si;
	PROCESS_INFORMATION pi;
	CONTEXT tc;
	DEBUG_EVENT de;
	DWORD stack_v = NULL, _GetProcAddress = NULL, oldp;
	unsigned char patch[4] = { 0x90, 0x90, 0xCC };
	unsigned char ctx_sig[15] = { 0x6A, 0x00, 0x6A, 0x05, 0xE8, 0x05, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90, 0x90, 0x90, 0x50 };
	unsigned char ctx_fly[15];
	char *temp_name = TEMP_FILE_NAME;
	int fe=NULL, found=NULL;
	

	_GetProcAddress = (DWORD) GetProcAddress(LoadLibrary("KERNEL32.DLL"), "GetProcAddress");


	GetStartupInfo(&si);
	if (!CreateProcess(NULL,temp_name,NULL,NULL,FALSE,DEBUG_PROCESS + DEBUG_ONLY_THIS_PROCESS, NULL, NULL, &si, &pi)) 
	{
		printf("[-] Error: cannot create process, error: %d\n",GetLastError());
		goto error_di;
	}

	printf("\n[+] Process created, pid=0x%.08x\n",pi.dwProcessId);
	printf("[+] Starting emulation engine...\n");
	

	while (1) 
	{
		WaitForDebugEvent(&de,INFINITE);
		if (de.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) {
			printf("[!] Error: ups process exited...\n");
			goto error_term;
		}

		if (de.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) 
		{
			if (de.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
				if (de.u.Exception.dwFirstChance == TRUE) 
				{
					printf("[+] Exception occured at: 0x%.08x, passing to program.\n",de.u.Exception.ExceptionRecord.ExceptionAddress);
					ContinueDebugEvent(de.dwProcessId,de.dwThreadId,DBG_EXCEPTION_NOT_HANDLED);
				}
				else 
				{
					printf("[-] Hard error occured, terminating the program\n");
					printf("[-] Disinfecting failed\n");
					goto error_term;
				}

			}





			if (de.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) 
			{
				if (fe == NULL) 
				{
					fe = 1;
					printf("[+] Reached break point at 0x%.08x\n",de.u.Exception.ExceptionRecord.ExceptionAddress);
					printf("[+] Modifing 4 bytes at host stack\n");
					

					tc.ContextFlags = CONTEXT_CONTROL;
					if (!GetThreadContext(pi.hThread, &tc)) 
					{
						printf("[-] Failed to get thread context, error: %d\n",GetLastError());
						printf("[-] Disinfecting failed\n");
						goto error_term;
					}

					ReadProcessMemory(pi.hProcess, (void*)tc.Esp, &stack_v,4,NULL);

					if (stack_v == NULL) 
					{
						printf("[-] Error: reading from stack failed\n");
						printf("[-] Disinfecting failed\n");
						goto error_term;
					}

					tc.Esp = tc.Esp - 4;
					caller += 5;

					if (!WriteProcessMemory(pi.hProcess, (void*)tc.Esp, &caller, 4, NULL)) 
					{
						printf("[-] Error: writing to stack failed\n");
						printf("[-] Disinfecting failed\n");
						goto error_term;
					}
					printf("[+] Stack modified, 0x%.08x added caller -> 0x%.08x\n",tc.Esp, caller);

					printf("[+] Redirecting EIP to 0x%.08x...\n",where_ctx);
					tc.Eip = where_ctx;

					if (!SetThreadContext(pi.hThread, &tc)) 
					{
						printf("[-] Failed to set thread context, error: %d\n",GetLastError());
						printf("[-] Disinfecting failed\n");
						goto error_term;
					
					}

					VirtualProtectEx(pi.hProcess, (void*) _GetProcAddress, sizeof(patch), PAGE_READWRITE, &oldp);
					WriteProcessMemory(pi.hProcess, (void*) _GetProcAddress, &patch, sizeof(patch), NULL);
					VirtualProtectEx(pi.hProcess, (void*) _GetProcAddress, sizeof(patch), oldp, &oldp);

					printf("[+] Placed breaker at 0x%.08x\n",_GetProcAddress);

					ContinueDebugEvent(de.dwProcessId,de.dwThreadId,DBG_CONTINUE);
				}
			
			
					if ((DWORD) de.u.Exception.ExceptionRecord.ExceptionAddress > _GetProcAddress && (DWORD) de.u.Exception.ExceptionRecord.ExceptionAddress < _GetProcAddress + sizeof(patch)) 
					{
					printf("[+] Virus reached the breaker at 0x%.08x\n",de.u.Exception.ExceptionRecord.ExceptionAddress);
					

					tc.ContextFlags = CONTEXT_CONTROL;
					if (!GetThreadContext(pi.hThread, &tc)) 
					{
						printf("[-] Failed to get thread context, error: %d\n",GetLastError());
						printf("[-] Disinfecting failed\n");
						goto error_term;
					}
					
					ReadProcessMemory(pi.hProcess, (void*)tc.Esp, &stack_v, 4, NULL);
					printf("[+] Virus request captured from 0x%.08x\n",stack_v);
					printf("[+] Scanning backwards to 0x%.08x\n",upa);
				

					while (1) 
					{
						if (!ReadProcessMemory(pi.hProcess, (void*)stack_v, &ctx_fly, sizeof(ctx_sig), NULL)) break;
						if (stack_v <= upa) break;
						
						found = 1;
						for (int ii=0; ii < sizeof(ctx_sig); ii++) 
						{
							if (ctx_sig[ii] != ctx_fly[ii]) 
							{
								if (ctx_sig[ii] != 0x90) 
								{
									found = 0;
									break;
								}
							}
						}
						
						if (found == 1) 
						{
							printf("[+] Orginal bytes were found at 0x%.08x\n",stack_v + 9);
							printf("[!] Repairing the broken instruction.\n");
							ReadProcessMemory(pi.hProcess, (void*)(stack_v + 9), (void*) sv, 5, NULL);
							printf("[!] The file was disinfected!\n");
							getch();
							goto error_term;
						}

						stack_v--;
					}

					if (found == 0) 
					{
						printf("[-] Error: no signature was found.\n");
						printf("[-] Disinfecting failed\n");
						goto error_term;
					}

					goto error_term;
				}
						
			}

		}


		ContinueDebugEvent(de.dwProcessId,de.dwThreadId,DBG_EXCEPTION_NOT_HANDLED);

	}


	error_term:
		TerminateProcess(pi.hProcess,NULL);

	error_di:
		return TRUE;

}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值