// AntiMidaDlg.cpp : file di implementazione
//

#include "stdafx.h"
#include "AntiMida.h"
#include "AntiMidaDlg.h"
#include ".\antimidadlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// finestra di dialogo CAntiMidaDlg



CAntiMidaDlg::CAntiMidaDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CAntiMidaDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

	hBrush = ::CreateSolidBrush(RGB(0, 0, 0));
}

void CAntiMidaDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, LST_PROCS, ProcList);
	DDX_Control(pDX, ID_ANTIMIDA, btnAntimida);
	DDX_Control(pDX, ID_REFRESH, btnRefresh);
}

BEGIN_MESSAGE_MAP(CAntiMidaDlg, CDialog)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_WM_CTLCOLOR()
	ON_BN_CLICKED(ID_REFRESH, OnBnClickedRefresh)
	ON_BN_CLICKED(ID_ANTIMIDA, OnBnClickedAntimida)
	ON_WM_CLOSE()
END_MESSAGE_MAP()


// gestori di messaggi di CAntiMidaDlg

BOOL CAntiMidaDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	//
	// get restore info
	//

	if (CollectInformation(&RestoreInfo) == FALSE)
	{
		MessageBox(_T("Cannot get restore information"));
		this->EndDialog(0);
		return FALSE;
	}

	//
	// cur dir
	//

	GetModuleFileName(NULL, Buffer, MAX_PATH);

	_tsplitpath(Buffer, CurDir, Buffer, NULL, NULL);
	_tcscat(CurDir, Buffer);

	//
	// load driver
	//

	if (OpenDevice(_T("antimida"), &hAntimida) == FALSE)
	{
		DWORD Error;

		wsprintf(Buffer, _T("%santimida.sys"), CurDir);

		if (LoadDeviceDriver(_T("antimida"), Buffer, &hAntimida, &Error) == FALSE)
		{
			MessageBox(_T("Cannot load driver"));
			this->EndDialog(0);
			return FALSE;
		}
	}

	//
	// send restore info to the driver
	//

	DWORD RetBytes;

	if (!DeviceIoControl(hAntimida, CODE_RESTORE_INFO, 
		&RestoreInfo, sizeof (RESTORE_INFO), NULL, 0, &RetBytes, NULL))
	{
		MessageBox(_T("Cannot communicate with the driver"));
		CloseHandle(hAntimida);
		this->EndDialog(0);
		return FALSE;
	}

	//
	// dialog init
	//

	SetIcon(m_hIcon, FALSE);		// Impostare icona piccola.

	// TODO: aggiungere qui inizializzazione aggiuntiva.

	btnAntimida.SetIcon(ICO_WIZ);
	btnAntimida.EnableBalloonTooltip();
	btnAntimida.SetTooltipText(_T("Make Process AntiMida"));

	btnRefresh.SetIcon(ICO_REF);
	btnRefresh.EnableBalloonTooltip();
	btnRefresh.SetTooltipText(_T("Refresh Process List"));

	// sets privileges

	SetPrivileges();

	// processes

	InitCommonControls();

	ProcList.SendMessage(LVM_SETEXTENDEDLISTVIEWSTYLE,
		LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP,
		LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP);

	ProcList.InsertColumn(0, "Process", LVCFMT_LEFT, 100);
	ProcList.InsertColumn(1, "PID", LVCFMT_LEFT, 80);
	ProcList.InsertColumn(2, "Location", LVCFMT_LEFT, 370);

	ListProcs();
	
	return TRUE;  // restituisce TRUE a meno che non venga impostato lo stato attivo su un controllo.
}

// Se si aggiunge alla finestra di dialogo un pulsante di riduzione a icona, per trascinare l'icona sarà necessario
//  il codice sottostante. Per le applicazioni MFC che utilizzano il modello documento/vista,
//  questa operazione viene eseguita automaticamente dal framework.

void CAntiMidaDlg::OnPaint() 
{
	CDialog::OnPaint();
}

// Il sistema chiama questa funzione per ottenere la visualizzazione del cursore durante il trascinamento
//  della finestra ridotta a icona.
HCURSOR CAntiMidaDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

BOOL CAntiMidaDlg::PreTranslateMessage(MSG* pMsg) 
{
	// TODO: Add your specialized code here and/or call the base class

	if (pMsg->message == WM_KEYDOWN)
	{
		if (pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE)
			pMsg->wParam = NULL;
	}

	return CDialog::PreTranslateMessage(pMsg);
}

VOID CAntiMidaDlg::ListProcs()
{
	LPDWORD lpdwPIDs = NULL;
	DWORD dwSize;
	DWORD dwSize2;
	DWORD dwIndex;
	HMODULE hMod;
	HANDLE hProcess;
	DWORD dwLIndex = 0;
	//MODULEINFO modi;
	TCHAR szProcName[MAX_PATH];
	TCHAR Buf[MAX_PATH];

	ProcList.DeleteAllItems();

	dwSize2 = 256 * sizeof(DWORD);

	do 
	{
		if (lpdwPIDs) 
		{
			HeapFree(GetProcessHeap(), 0, lpdwPIDs);
			dwSize2 *= 2;
		}

		lpdwPIDs = (LPDWORD) HeapAlloc(GetProcessHeap(), 0, dwSize2);

		if (lpdwPIDs == NULL) 
			return;

		if (!EnumProcesses(lpdwPIDs, dwSize2, &dwSize))
			return;

	} while (dwSize == dwSize2);

	dwSize /= sizeof(DWORD);

	for (dwIndex = 0; dwIndex < dwSize; dwIndex++) 
	{
		szProcName[0] = 0;

		hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | 
			PROCESS_VM_READ, FALSE, lpdwPIDs[dwIndex]);


		if (hProcess != NULL) 
		{
			if (EnumProcessModules(hProcess, &hMod,
				sizeof(hMod), &dwSize2)) 
			{
				if (!GetModuleFileNameEx(hProcess, hMod,
					szProcName, sizeof(szProcName)))
				{
					CloseHandle(hProcess);
					continue;
				}
			}
			else
			{
				CloseHandle(hProcess);
				continue;
			}

			if (szProcName[0] != 0) 
			{ 
				GetFileName(szProcName);

				_tsplitpath(szProcName, NULL, NULL, Buf, NULL);
				ProcList.InsertItem(dwLIndex, Buf);

				wsprintf(Buf, "%08X", lpdwPIDs[dwIndex]);
				ProcList.SetItemText(dwLIndex, 1, Buf);

				ProcList.SetItemText(dwLIndex, 2, szProcName);

				dwLIndex++;
			}

			CloseHandle(hProcess);
		}	

	}

	if (lpdwPIDs)
		HeapFree(GetProcessHeap(), 0, lpdwPIDs);
}

VOID CAntiMidaDlg::SetPrivileges(VOID)
{
	HANDLE hToken;
	TOKEN_PRIVILEGES oldtp;
	DWORD dwSize;
	HANDLE hProc;
	LUID luid;
	TOKEN_PRIVILEGES tp;

	hProc = GetCurrentProcess();

	if (!OpenProcessToken(hProc, TOKEN_QUERY | 
		TOKEN_ADJUST_PRIVILEGES, &hToken))
		return;

	if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
	{
		CloseHandle (hToken);
		return;
	}

	ZeroMemory(&tp, sizeof (tp));

	tp.PrivilegeCount = 1;
	tp.Privileges[0].Luid = luid;
	tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

	if (!AdjustTokenPrivileges (hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES),
		&oldtp, &dwSize))
	{
		CloseHandle(hToken);
	}
}

VOID CAntiMidaDlg::GetFileName(TCHAR *Name)
{
	TCHAR *path, *New, *ptr;

	path = (PTCHAR) malloc((MAX_PATH + 1) * sizeof (TCHAR));
	New = (PTCHAR) malloc((MAX_PATH + 1) * sizeof (TCHAR));

	_tcsncpy(path, Name, MAX_PATH);

	if (_tcsncmp(path, _T("\\SystemRoot"), 11) == 0) 
	{
		ptr = &path[11];  
		GetWindowsDirectory(New, MAX_PATH * sizeof (TCHAR));
		_tcscat(New, ptr);
		_tcscpy(Name, New);
	}
	else if (_tcsncmp(path, _T("\\??\\"), 4) == 0) 
	{
		ptr = &path[4];
		_tcscpy(New, ptr);
		_tcscpy(Name, New);
	}

	free(path);
	free(New);
}

HBRUSH CAntiMidaDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);

	// TODO:  Change any attributes of the DC here

	// TODO:  Return a different brush if the default is not desired
	return hbr;//hBrush;
}

void CAntiMidaDlg::OnBnClickedRefresh()
{
	ListProcs();
}

void CAntiMidaDlg::OnBnClickedAntimida()
{
	ProcList.GetItemText(ProcList.GetNextItem(-1, LVNI_SELECTED), 1, 
		Buffer, sizeof (Buffer) -1);

	ULONG_PTR PID = _tcstoul(Buffer, 0, 16);
	
	wsprintf(Buffer, _T("%samdll.dll"), CurDir);

	ULONG_PTR BaseAddress;

	//
	// inject the module
	//

	if (InjectModule(PID, _T("amdll.dll"), &BaseAddress))
	{
		HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);

		if (hProcess == NULL)
		{
			MessageBox(_T("Cannot make the process AntiMida"), "AntiMida");
			return;
		}

		//
		// hook ReadProcessMemory
		//

		ULONG_PTR Addr = (ULONG_PTR) GetProcAddress(
			GetModuleHandle(_T("kernel32.dll")), 
			"ReadProcessMemory");

		BYTE Instr = 0xB8;

		WriteProcessMemory(hProcess, (LPVOID) Addr, &Instr, 
			sizeof (BYTE), NULL);

		Addr++;

		ULONG_PTR Rva = GetExportRva(Buffer, "_FakeReadProcessMemory@20");

		ULONG_PTR HookVA = BaseAddress + Rva;

		WriteProcessMemory(hProcess, (LPVOID) Addr, &HookVA, 
			sizeof (ULONG_PTR), NULL);

		Addr += sizeof (ULONG_PTR);

		WORD Instr2 = 0xE0FF;

		WriteProcessMemory(hProcess, (LPVOID) Addr, &Instr2, 
			sizeof (WORD), NULL);

		//
		// hook VirtualQueryEx
		//

		Addr = (ULONG_PTR) GetProcAddress(
			GetModuleHandle(_T("kernel32.dll")), 
			"VirtualQueryEx");

		WriteProcessMemory(hProcess, (LPVOID) Addr, &Instr, 
			sizeof (BYTE), NULL);

		Addr++;

		Rva = GetExportRva(Buffer, "_FakeVirtualQueryEx@16");

		HookVA = BaseAddress + Rva;

		WriteProcessMemory(hProcess, (LPVOID) Addr, &HookVA, 
			sizeof (ULONG_PTR), NULL);

		Addr += sizeof (ULONG_PTR);

		WriteProcessMemory(hProcess, (LPVOID) Addr, &Instr2, 
			sizeof (WORD), NULL);

		//
		// hook WriteProcessMemory
		//

		Addr = (ULONG_PTR) GetProcAddress(
			GetModuleHandle(_T("kernel32.dll")), 
			"WriteProcessMemory");

		WriteProcessMemory(hProcess, (LPVOID) Addr, &Instr, 
			sizeof (BYTE), NULL);

		Addr++;

		Rva = GetExportRva(Buffer, "_FakeWriteProcessMemory@20");

		HookVA = BaseAddress + Rva;

		WriteProcessMemory(hProcess, (LPVOID) Addr, &HookVA, 
			sizeof (ULONG_PTR), NULL);

		Addr += sizeof (ULONG_PTR);

		WriteProcessMemory(hProcess, (LPVOID) Addr, &Instr2, 
			sizeof (WORD), NULL);

		// 
		// hook NtAllocateVirtualMemory
		// from here i start to hook the ntdll directly
		//

		Addr = (ULONG_PTR) GetProcAddress(
			GetModuleHandle(_T("ntdll.dll")), 
			"NtAllocateVirtualMemory");

		WriteProcessMemory(hProcess, (LPVOID) Addr, &Instr, 
			sizeof (BYTE), NULL);

		Addr++;

		Rva = GetExportRva(Buffer, "_FakeNtAllocateVirtualMemory@24");

		HookVA = BaseAddress + Rva;

		WriteProcessMemory(hProcess, (LPVOID) Addr, &HookVA, 
			sizeof (ULONG_PTR), NULL);

		Addr += sizeof (ULONG_PTR);

		WriteProcessMemory(hProcess, (LPVOID) Addr, &Instr2, 
			sizeof (WORD), NULL);

		// 
		// hook NtCreateThread
		//

		Addr = (ULONG_PTR) GetProcAddress(
			GetModuleHandle(_T("ntdll.dll")), 
			"NtCreateThread");

		WriteProcessMemory(hProcess, (LPVOID) Addr, &Instr, 
			sizeof (BYTE), NULL);

		Addr++;

		Rva = GetExportRva(Buffer, "_FakeNtCreateThread@32");

		HookVA = BaseAddress + Rva;

		WriteProcessMemory(hProcess, (LPVOID) Addr, &HookVA, 
			sizeof (ULONG_PTR), NULL);

		Addr += sizeof (ULONG_PTR);

		WriteProcessMemory(hProcess, (LPVOID) Addr, &Instr2, 
			sizeof (WORD), NULL);

		//
		// hook ZwDebugContinue
		//

		Addr = (ULONG_PTR) GetProcAddress(
			GetModuleHandle(_T("ntdll.dll")), 
			"ZwDebugContinue");

		WriteProcessMemory(hProcess, (LPVOID) Addr, &Instr, 
			sizeof (BYTE), NULL);

		Addr++;

		Rva = GetExportRva(Buffer, "_FakeZwDebugContinue@12");

		HookVA = BaseAddress + Rva;

		WriteProcessMemory(hProcess, (LPVOID) Addr, &HookVA, 
			sizeof (ULONG_PTR), NULL);

		Addr += sizeof (ULONG_PTR);

		WriteProcessMemory(hProcess, (LPVOID) Addr, &Instr2, 
			sizeof (WORD), NULL);

		//
		// everything's hooked
		//

		CloseHandle(hProcess);

		MessageBox(_T("The process is now AntiMida"), "AntiMida");
	}
	else
	{
		MessageBox(_T("Cannot make the process AntiMida"), "AntiMida");
	}
}

void CAntiMidaDlg::OnClose()
{
	CloseHandle(hAntimida);
	UnloadDeviceDriverAndRemoveService(_T("antimida"));

	CDialog::OnClose();
}
