#include "stdafx.h"
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <lmcons.h>
#include <lmalert.h>
#include "HookFunc.h"
#include <nb30.h>
#include "Util.h"
#include "filter.h"

char g_szDllPath[128];
HINSTANCE g_hInstance;
CSocketFilter socket_filter;

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
	if(ul_reason_for_call =DLL_PROCESS_ATTACH)
	{
		GetProfileString("APIHook", "dll_path", "", g_szDllPath, sizeof(g_szDllPath));
	}

	return TRUE;
}

int WINAPI cSocket(int af, int type, int protocol)
{
	WriteLog("cSocket, af=%d, type=%d, protocol=%d", af, type, protocol);

	return socket(af, type, protocol);
}

struct hostent * WINAPI cGethostbyname (const char * name)
{
	// filter IE url
	WriteLog("gethostbyname:name:%s", name);
	if(socket_filter.FilterDNS((char *)name))
	{
		WSASetLastError(-1);
		return NULL;
	}
	return gethostbyname(name);
}

int WINAPI cAccept(SOCKET s, struct sockaddr *pname, int *pnamelen)
{
	int port =GetLocalPortBySocket(s);

	WriteLog("cAccept");

	int s1 =accept(s, pname, pnamelen);

	if(s1 >0)
	{
		int err=WSAGetLastError();
		if(socket_filter.FilterAccept(s))
		{
			WSASetLastError(-1);
			return -1;
		}
	}

	return s1;
}

int WINAPI cConnect(SOCKET s, struct sockaddr *name, int namelen)
{
	struct sockaddr_in *paddr =(struct sockaddr_in *)name;

	char *ip =inet_ntoa(paddr->sin_addr);
	int port =ntohs(paddr->sin_port);
	WriteLog("connect: ip=%s, port=%d\n", ip, port);
	
	if(socket_filter.FilterConnect(ip, port))
	{
		WSASetLastError(-1);	
		return -1;
	}

	return connect(s, name, namelen);
}

int WINAPI cRecv(SOCKET s,	char *buf, int len, int flags)
{
	WriteLog("\ncRecv");

	int recved_len =recv(s, (char *)buf, len, flags);
	int err;

	err =WSAGetLastError();

	if(recved_len >0)
	{
		socket_filter.FilterRecv(s, buf, len);
	}
	
	WSASetLastError(err);

	return recved_len;
}

int WINAPI cSend(SOCKET s,	char *buf, int len,	int flags)
{
	int ret;

	WriteLog("\ncSend");

	socket_filter.FilterSend(s, buf, len);
	ret =send(s, (char *)buf, len, flags);
	
	int err =WSAGetLastError();
	// do something
	WSASetLastError(err);
	
	return ret;
}

int WINAPI cSendto (SOCKET s, char FAR * buf, int len, int flags, struct sockaddr FAR * to, int tolen)
{
	WriteLog("cSendto");
	char *ip =inet_ntoa(((struct sockaddr_in *)to)->sin_addr);
	int port =ntohs(((struct sockaddr_in *)to)->sin_port);

	if(socket_filter.FilterConnect(ip, port))
	{
		WSASetLastError(-1);	
		return -1;
	}
	socket_filter.FilterSendTo(ip, port, buf, len);
	return sendto(s, buf, len, flags, to, tolen);
}

int WINAPI cRecvfrom (SOCKET s, char FAR * buf, int len, int flags, struct sockaddr FAR * from, int *fromlen)
{
	WriteLog("cRecvfrom");
	char *ip =inet_ntoa(((struct sockaddr_in *)from)->sin_addr);
	int port =ntohs(((struct sockaddr_in *)from)->sin_port);

	len = recvfrom(s, buf, len, flags, from, fromlen);
	
	int err=WSAGetLastError();
	socket_filter.FilterRecvFrom(ip, port, buf, len);
	WSASetLastError(err);

	return len;
}

HINSTANCE WINAPI cLoadLibraryA(char *name)
{
	char fname[128];
	GetModuleFileName(NULL, fname, sizeof(fname));
	WriteLog("%s,LoadLibraryA:%s", fname, name);
	return LoadLibraryA(name);
}

HINSTANCE WINAPI cLoadLibraryW(LPWSTR name)
{
	char fname[128];
	GetModuleFileName(NULL, fname, sizeof(fname));

	char aname[128];
	WideCharToMultiByte( CP_ACP, 0, name, -1, aname, 128,NULL,NULL); 
	WriteLog("%s,LoadLibraryW:%s", fname, aname);

	return LoadLibraryW(name);
}

FARPROC WINAPI cGetProcAddress(HMODULE hMod, char *name)
{
	char fname[128];
	GetModuleFileName(NULL, fname, sizeof(fname));
	if(strstr(fname, "APIHook") ==NULL)
		WriteLog("%s,GetProcAddress:%s", fname, name);
	return GetProcAddress(hMod, name);
}

int WINAPI cNetbios(PNCB pncb)
{
	WriteLog("Netbios");

	return Netbios(pncb);
}

int WINAPI cNetAlertRaise(	LPWSTR event_name, LPVOID buf, DWORD buf_len)
{
	WriteLog("cNetAlertRaise...");
	return NetAlertRaise(event_name, buf, buf_len);
}

int WINAPI cWSHOpenSocket(	int *family, int *type, int *protocol, LPWSTR device_name, LPVOID *context, LPDWORD event)
{
	WriteLog("WSHOpenSocket:event=%d", *event);

	HMODULE hMod=GetModuleHandle("WSHTcpip.dll");
	if(hMod ==NULL) return -1;
	WSHOPENSOCKET WSHOpenSocket =(WSHOPENSOCKET)GetProcAddress(hMod, "WSHOpenSocket");
	if(WSHOpenSocket ==NULL) return -1;

	return WSHOpenSocket(family, type, protocol, device_name, context,event);
}

int WINAPI cWSHOpenSocket2(int *family, int *type, int *protocol, int group, int flags, LPWSTR device_name, LPVOID *context, LPDWORD event)
{
	WriteLog("WSHOpenSocket2");

	HMODULE hMod=GetModuleHandle("WSHTcpip.dll");
	if(hMod ==NULL) return -1;
	WSHOPENSOCKET2 WSHOpenSocket2 =(WSHOPENSOCKET2)GetProcAddress(hMod, "WSHOpenSocket2");
	if(WSHOpenSocket2 ==NULL) return -1;

	return WSHOpenSocket2(family, type, protocol, group, flags, device_name, context,event);
}

int WINAPI cWSHNotify(	PVOID context, int sock, HANDLE ao, HANDLE co, DWORD event)
{
	
	HMODULE hMod=GetModuleHandle("WSHTcpip.dll");
	if(hMod ==NULL) return -1;
	WSHNOTIFY WSHNotify =(WSHNOTIFY)GetProcAddress(hMod, "WSHNotify");

	WriteLog("cWSHNotify:event=%d", event);

	return WSHNotify(context, sock, ao, co, event);
}

// test hookprocess
int WINAPI cExitProcess(int exit_code)
{
	char mod_name[128];

	WriteLog("cExitProcess:exit_code=%d", exit_code);
	GetModuleFileName(NULL, mod_name, sizeof(mod_name));
	if(!strstr(mod_name, "hookprocess"))
	{
		ExitProcess(exit_code);
	}
	return 0;
}


DWORD WINAPI cCreateProcessW(
	LPCWSTR lpApplicationName,
	LPWSTR lpCommandLine, 
	LPSECURITY_ATTRIBUTES lpProcessAttributes,
	LPSECURITY_ATTRIBUTES lpThreadAttributes,
	BOOL bInheritHandles,
	DWORD dwCreationFlags,
	LPVOID lpEnvironment,
	LPCWSTR lpCurrentDirectory,
	LPSTARTUPINFOW lpStartupInfo,
	LPPROCESS_INFORMATION lpProcessInformation
)
{
	char cmd[600];
	int len =WideCharToMultiByte( CP_ACP, 0, lpCommandLine, -1, cmd, 128,NULL,NULL); 
	cmd[len] =0;

	BOOL ifsuccess = CreateProcessW(lpApplicationName,
		lpCommandLine, lpProcessAttributes,
		lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment,
		lpCurrentDirectory, lpStartupInfo, lpProcessInformation);
	DWORD err =GetLastError();
	if(ifsuccess)
	{
		//HWND hWndNotify =FindWindow("APIHookNotify", NULL);
		//if(hWndNotify) PostMessage(hWndNotify, WM_APP+100, lpProcessInformation->dwProcessId, 0L);
		/*ResumeThread(lpProcessInformation->hThread);
		int ret=WaitForInputIdle(lpProcessInformation->hProcess, INFINITE);
		ResumeThread(lpProcessInformation->hThread);
		HANDLE hProcess=lpProcessInformation->hProcess;
		if((int)SuspendThread(lpProcessInformation->hThread) !=-1)
		{
		//if(is_nt)
		{
			char szdll[128];
			wsprintf(szdll, "%s\\HookFunc.dll", g_szDllPath);
		WriteLog("CreateProcessW: InjectLib %s", szdll);
			InjectLib(hProcess, szdll, TRUE);
			wsprintf(szdll, "%s\\APIHookxp.dll", g_szDllPath);
		WriteLog("CreateProcessW: InjectLib %s", szdll);
			InjectLib(hProcess, szdll, TRUE);
		}
		ResumeThread(lpProcessInformation->hThread);
		}
		WriteLog("CreateProcessW:%s, wait ret=%d, processid=%d", cmd, ret,lpProcessInformation->dwProcessId);
		*/
	}
	else WriteLog("CreateProcessW failed:%s", cmd);
	SetLastError(err);
	return (DWORD)ifsuccess;
}

DWORD WINAPI cCreateProcessA(
	LPCSTR lpApplicationName,
	LPSTR lpCommandLine, 
	LPSECURITY_ATTRIBUTES lpProcessAttributes,
	LPSECURITY_ATTRIBUTES lpThreadAttributes,
	BOOL bInheritHandles,
	DWORD dwCreationFlags,
	LPVOID lpEnvironment,
	LPCSTR lpCurrentDirectory,
	LPSTARTUPINFO lpStartupInfo,
	LPPROCESS_INFORMATION lpProcessInformation
)
{
	WriteLog("cCreateProcessA, cmd=%s", lpCommandLine);

	BOOL ifsuccess = CreateProcessA(lpApplicationName, lpCommandLine, lpProcessAttributes,
		lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment,
		lpCurrentDirectory, lpStartupInfo, lpProcessInformation);
	//WriteLog("CreateProcessA ok! ifsuccess=%d", ifsuccess);
	if(ifsuccess)
	{
		HANDLE hProcess =lpProcessInformation->hProcess;

		//if(is_nt)
		{
			//InjectLib(hProcess, "HookFunc.dll", TRUE);
			//InjectLib(hProcess, "APIHookxp.dll", TRUE);
		}
	}
	else
	{
		DWORD err;
		err =GetLastError();
		WriteLog("CreateProcessA failed:err=%d, cmd=%s\n", err, lpCommandLine);
		SetLastError(err);
	}
	return (DWORD)ifsuccess;
}

CAPIINFO c_api_info[] =
{
	{"WSOCK32.DLL", "socket(a,b,c)", "cSocket"},
	{"WSOCK32.DLL", "accept(a,b,c)", "cAccept"},
	{"WSOCK32.DLL", "connect(SOCKET, struct sockaddr *, INT)", "cConnect"},
	{"WSOCK32.DLL", "recv(INT, char *, INT, INT)", "cRecv"},
	{"WSOCK32.DLL", "send(INT, char *, INT, INT)", "cSend"},
	{"WSOCK32.DLL", "sendto(INT, char *, INT, INT, struct sockaddr *, int)", "cSendto"},
	{"WSOCK32.DLL", "recvfrom(INT, char *, INT, INT, struct sockaddr *, int)", "cRecvfrom"},
	{"WSOCK32.DLL", "gethostbyname(char *)", "cGethostbyname"},
	//{"WSHTCPIP.DLL", "WSHOpenSocket(int *, int *, int *, LPWSTR, LPVOID *, LPDWORD)", "cWSHOpenSocket"},
	//{"WSHTCPIP.DLL", "WSHOpenSocket2(int *, int *, int *, int, int, LPWSTR, LPVOID *, LPDWORD)", "cWSHOpenSocket2"},
	//{"WSHTCPIP.DLL", "WSHNotify(PVOID, int, HANDLE, HANDLE, DWORD)", "cWSHNotify"},
	//{"netapi32.DLL", "Netbios(PNCB)", "cNetbios"},
	//{"KERNEL32.DLL", "LoadLibraryA(char *)", "cLoadLibraryA"},
	//{"KERNEL32.DLL", "ExitProcess(int)", "cExitProcess"},
	//{"KERNEL32.DLL", "CreateProcessA(1,2,3,4,5,6,7,8,9,10)", "cCreateProcessA"},
	//{"KERNEL32.DLL", "CreateProcessW(1,2,3,4,5,6,7,8,9,10)", "cCreateProcessW"},
	{NULL,NULL,NULL}
};

CAPIINFO *GetCAPIINFO()
{
	return &c_api_info[0];
}

