
// WeChats.cpp : 定义应用程序的类行为。
//

#include "stdafx.h"
#include "WeChats.h"
#include "WeChatsDlg.h"
#include "Injection.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CWeChatsApp

BEGIN_MESSAGE_MAP(CWeChatsApp, CWinAppEx)
	ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()


// CWeChatsApp 构造

CWeChatsApp::CWeChatsApp()
{
	// TODO: 在此处添加构造代码，
	// 将所有重要的初始化放置在 InitInstance 中
}


// 唯一的一个 CWeChatsApp 对象

CWeChatsApp theApp;


// CWeChatsApp 初始化

//////////////////////////////////////////////////////////////////////////
// BEGIN
// killWeChatMutex函数用到的未公开的声明;

typedef ULONG   PPS_POST_PROCESS_INIT_ROUTINE;  


// 以下声明，都是系统未公开的定义;
//
typedef enum {
	ProcessBasicInformation = 0,
	ProcessDebugPort = 7,
	ProcessWow64Information = 26,
	ProcessImageFileName = 27,
	ProcessBreakOnTermination = 29,
	ProcessProtectionInformation = 61,
}PROCESSINFOCLASS;

typedef struct _PEB_LDR_DATA {
	BYTE       Reserved1[8];
	PVOID      Reserved2[3];
	LIST_ENTRY InMemoryOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;

typedef struct _LDR_DATA_TABLE_ENTRY {
	PVOID Reserved1[2];
	LIST_ENTRY InMemoryOrderLinks;
	PVOID Reserved2[2];
	PVOID DllBase;
	PVOID EntryPoint;
	PVOID Reserved3;
	UNICODE_STRING FullDllName;
	BYTE Reserved4[8];
	PVOID Reserved5[3];
	union {
		ULONG CheckSum;
		PVOID Reserved6;
	};
	ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;

typedef struct _RTL_USER_PROCESS_PARAMETERS {
	BYTE           Reserved1[16];
	PVOID          Reserved2[10];
	UNICODE_STRING ImagePathName;
	UNICODE_STRING CommandLine;
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;

// 32位下的结构;
typedef struct _PEB {
	BYTE                          Reserved1[2];
	BYTE                          BeingDebugged;
	BYTE                          Reserved2[1];
	PVOID                         Reserved3[2];
	PPEB_LDR_DATA                 Ldr;
	PRTL_USER_PROCESS_PARAMETERS  ProcessParameters;
	PVOID                         Reserved4[3];
	PVOID                         AtlThunkSListPtr;
	PVOID                         Reserved5;
	ULONG                         Reserved6;
	PVOID                         Reserved7;
	ULONG                         Reserved8;
	ULONG                         AtlThunkSListPtr32;
	PVOID                         Reserved9[45];
	BYTE                          Reserved10[96];
	PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
	BYTE                          Reserved11[128];
	PVOID                         Reserved12[1];
	ULONG                         SessionId;
} PEB, *PPEB;
// 64位下的结构;
typedef struct _PEBX64 {
	BYTE Reserved1[2];
	BYTE BeingDebugged;
	BYTE Reserved2[21];
	PPEB_LDR_DATA LoaderData;
	PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
	BYTE Reserved3[520];
	PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
	BYTE Reserved4[136];
	ULONG SessionId;
} PEBX64;

typedef struct _PROCESS_BASIC_INFORMATION {
	PVOID Reserved1;
	PPEB PebBaseAddress;
	PVOID Reserved2[2];
	ULONG_PTR UniqueProcessId;
	PVOID Reserved3;
} PROCESS_BASIC_INFORMATION;

// 声音函数指针;
typedef NTSTATUS (WINAPI *pfZwQueryInformationProcess)(
	_In_      HANDLE           ProcessHandle,
	_In_      PROCESSINFOCLASS ProcessInformationClass,
	_Out_     PVOID            ProcessInformation,
	_In_      ULONG            ProcessInformationLength,
	_Out_opt_ PULONG           ReturnLength
	);

// END
//////////////////////////////////////////////////////////////////////////

NTSTATUS GetProcessModules(HANDLE hProcess, LPCTSTR lpTypName, LPCTSTR lpName)
{
	NTSTATUS Status = 0;
	pfZwQueryInformationProcess ZwQueryInformationProcess = NULL;

	PROCESS_BASIC_INFORMATION ProcessInfo;
	PPEB	pPeb;

	ZwQueryInformationProcess = (pfZwQueryInformationProcess)GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "ZwQueryInformationProcess");
	if (ZwQueryInformationProcess == NULL)
	{
		WriteTextLog(_T("查找进程模块名称失败"));
		return Status;
	}

	Status = ZwQueryInformationProcess(hProcess, ProcessBasicInformation, &ProcessInfo, sizeof(ProcessInfo), NULL);
	if (NT_SUCCESS(Status))
	{
		pPeb = (PPEB)ProcessInfo.PebBaseAddress;

		for (PLIST_ENTRY pListEntry = pPeb->Ldr->InMemoryOrderModuleList.Flink;pListEntry != &pPeb->Ldr->InMemoryOrderModuleList;pListEntry = pListEntry->Flink)
		{
			//PLDR_DATA_TABLE_ENTRY pEntry = CONTAINING_RECORD(pListEntry, LDR_DATA_TABLE_ENTRY, pListEntry);
			//wprintf(L"%s\n", pEntry->FullDllName.Buffer);
			WriteTextLog(_T("模块名称"));
		}
	}
	else
		WriteTextLog(_T("查找进程模块名称失败1"));

	CloseHandle(hProcess);
	return Status;
}

BOOL CWeChatsApp::InitInstance()
{
	// 如果一个运行在 Windows XP 上的应用程序清单指定要
	// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式，
	//则需要 InitCommonControlsEx()。否则，将无法创建窗口。
	INITCOMMONCONTROLSEX InitCtrls;
	InitCtrls.dwSize = sizeof(InitCtrls);
	// 将它设置为包括所有要在应用程序中使用的
	// 公共控件类。
	InitCtrls.dwICC = ICC_WIN95_CLASSES;
	InitCommonControlsEx(&InitCtrls);

	CWinAppEx::InitInstance();

	AfxEnableControlContainer();
	
	// 获取配置信息;
	GetIniInfo();
	GetDebugPriv();
// 	HANDLE hObject = CreateMutex(NULL, FALSE, _T("CYLGLAppXiao"));
// 	if (GetLastError() == ERROR_ALREADY_EXISTS)
// 	{
// 		return FALSE;
// 	}
// 	GetProcessModules(::GetCurrentProcess(), _T("Mutant"), _T("_WeChat_Instance_Identity_Mutex_Name"));


	
// 	int nCount = 3;
// 	getWeChatPath();
// 	for (int i = 0; i < nCount; i++)
// 		OpenWeChat();


	TCHAR szDllPath[MAX_PATH];
	ZeroMemory(szDllPath,MAX_PATH);
	DWORD ss = sizeof(szDllPath);
	DWORD sss = _tcslen(szDllPath)*sizeof(TCHAR);
	_stprintf_s(szDllPath, _T("%shook.dll"), g_szModulePath);
	vector<DWORD> vtPID = FindAllProcess(WECHAT);
	if (vtPID.size() != 0 )
	{
		vector<DWORD>::iterator it = vtPID.begin();
		//for (int i = 0; i < 1; i++)
		for (;it != vtPID.end(); it++)
		{
			CInjection inject(*it,szDllPath);
			inject.InjectDynamicLibrary();
			Sleep(3000);
			inject.EjectDynamicLibrary();
		}
	}
	// 标准初始化
	// 如果未使用这些功能并希望减小
	// 最终可执行文件的大小，则应移除下列
	// 不需要的特定初始化例程
	// 更改用于存储设置的注册表项
	// TODO: 应适当修改该字符串，
	// 例如修改为公司或组织名
	SetRegistryKey(_T("应用程序向导生成的本地应用程序"));

	CWeChatsDlg dlg;
	m_pMainWnd = &dlg;
	INT_PTR nResponse = dlg.DoModal();
	if (nResponse == IDOK)
	{
		// TODO: 在此放置处理何时用
		//  “确定”来关闭对话框的代码
	}
	else if (nResponse == IDCANCEL)
	{
		// TODO: 在此放置处理何时用
		//  “取消”来关闭对话框的代码
	}

	// 由于对话框已关闭，所以将返回 FALSE 以便退出应用程序，
	//  而不是启动应用程序的消息泵。
	return FALSE;
}
