#include <iostream>
#include <Windows.h>
#include "util.h"

#ifdef _WIN64
void print_thread_context(const CONTEXT& ctx)
{
	std::cout << "Context dump:\n";
	std::cout << "---\n";
	std::cout << std::hex;
	std::cout << "RAX: " << ctx.Rax << "\n";
	std::cout << "RBX: " << ctx.Rbx << "\n";
	std::cout << "RCX: " << ctx.Rcx << " (Entry Point VA)\n";
	std::cout << "RDX: " << ctx.Rdx << " (PEB address)\n";
	std::cout << "RIP: " << ctx.Rip << "\n";
	std::cout << "---\n";
}
#else
void print_thread_context(const CONTEXT& ctx)
{
	std::cout << "Context dump:\n";
	std::cout << "---\n";
	std::cout << std::hex;
	std::cout << "EAX: " << ctx.Eax << "(Entry Point VA)\n";
	std::cout << "EBX: " << ctx.Ebx << "(PEB address)\n";
	std::cout << "ECX: " << ctx.Ecx << "\n";
	std::cout << "EDX: " << ctx.Edx << "\n";
	std::cout << "EIP: " << ctx.Eip << "\n";
	std::cout << "---\n";
}
#endif

void print_thread_context_wow64(const WOW64_CONTEXT& ctx)
{
	std::cout << "Wow64 Context dump:\n";
	std::cout << "---\n";
	std::cout << std::hex;
	std::cout << "EAX: " << ctx.Eax << "(Entry Point VA)\n";
	std::cout << "EBX: " << ctx.Ebx << "(PEB address)\n";
	std::cout << "ECX: " << ctx.Ecx << "\n";
	std::cout << "EDX: " << ctx.Edx << "\n";
	std::cout << "EIP: " << ctx.Eip << "\n";
	std::cout << "---\n";
}

int main(int argc, char *argv[])
{
#ifdef _WIN64
	std::cout << "Create Process: 64 bit version\n";
#else
	std::cout << "Create Process: 32 bit version\n";
#endif
	if (argc < 2) {
		std::cout << "Args: <path to the EXE>\n";
		return 0;
	}
	LPSTR path = argv[1];
	std::cout << "Creating the process: " << path << "\n";
	PROCESS_INFORMATION pi = { 0 };

	bool isCreated = create_new_process(path, CREATE_SUSPENDED, pi);
	if (!isCreated) {
		std::cout << "Failed creating the process: " << path << "\n";
		return -1;
	}
	std::cout << "Process created, PID: " << std::dec << pi.dwProcessId << "\n";

	CONTEXT ctx = { 0 };
	ctx.ContextFlags = CONTEXT_INTEGER;
	if (GetThreadContext(pi.hThread, &ctx)){
		print_thread_context(ctx);
	}
	else {
		std::cout << "[-] Getting thread context has failed\n";
	}
#ifdef _WIN64
	BOOL is32 = FALSE;
	IsWow64Process(pi.hProcess, &is32);
	if (is32) {
		WOW64_CONTEXT ctx = { 0 };
		ctx.ContextFlags = CONTEXT_INTEGER;
		if (Wow64GetThreadContext(pi.hThread, &ctx)) {
			print_thread_context_wow64(ctx);
		}
	}
	else {
		std::cout << "[-] Getting Wow64 context has failed\n";
	}
#endif
	std::cout << "The process is created as suspended, press any key to resume the main thread!\n";
	system("pause");

	ResumeThread(pi.hThread);
	std::cout << "Thread resumed!\n";
	system("pause");
	return 0;
}
