/* Attach to a running process.
   PID is the process ID to attach to, specified by the user
   or a higher layer.  */
static int
win32_attach (unsigned long pid)
{
  HANDLE h;
  winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL;
  DWORD err;
#ifdef _WIN32_WCE
  HMODULE dll = GetModuleHandle (_T("COREDLL.DLL"));
#else
  HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
#endif
  DebugSetProcessKillOnExit = GETPROCADDRESS (dll, DebugSetProcessKillOnExit);

  h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
  if (h != NULL)
    {
      if (DebugActiveProcess (pid))
	{
	  if (DebugSetProcessKillOnExit != NULL)
	    DebugSetProcessKillOnExit (FALSE);

	  /* win32_wait needs to know we're attaching.  */
	  attaching = 1;
	  do_initial_child_stuff (h, pid, 1);
	  return 0;
	}

      CloseHandle (h);
    }

  err = GetLastError ();
  error ("Attach to process failed (error %d): %s\n",
	 (int) err, strwinerror (err));
}
Exemple #2
0
/* Detach from all inferiors.  */
static int
win32_detach (void)
{
  winapi_DebugActiveProcessStop DebugActiveProcessStop = NULL;
  winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL;
#ifdef _WIN32_WCE
  HMODULE dll = GetModuleHandle (_T("COREDLL.DLL"));
#else
  HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
#endif
  DebugActiveProcessStop = GETPROCADDRESS (dll, DebugActiveProcessStop);
  DebugSetProcessKillOnExit = GETPROCADDRESS (dll, DebugSetProcessKillOnExit);

  if (DebugSetProcessKillOnExit == NULL
      || DebugActiveProcessStop == NULL)
    return -1;

  {
    struct thread_resume resume;
    resume.thread = -1;
    resume.step = 0;
    resume.sig = 0;
    resume.leave_stopped = 0;
    win32_resume (&resume);
  }

  if (!DebugActiveProcessStop (current_process_id))
    return -1;

  DebugSetProcessKillOnExit (FALSE);

  win32_clear_inferiors ();
  return 0;
}
BOOL My_DebugSetProcessKillOnExit()
{
	BOOL KillOnExit=NULL;
	BOOL returnVal_Real = NULL;
	BOOL returnVal_Intercepted = NULL;

	DWORD error_Real = 0;
	DWORD error_Intercepted = 0;
	disableInterception();
	returnVal_Real = DebugSetProcessKillOnExit (KillOnExit);
	error_Real = GetLastError();
	enableInterception();
	returnVal_Intercepted = DebugSetProcessKillOnExit (KillOnExit);
	error_Intercepted = GetLastError();
	return ((returnVal_Real == returnVal_Intercepted) && (error_Real == error_Intercepted));
}
Exemple #4
0
//------------------------------------------------------------------------------
// Name: DebuggerCore()
// Desc: constructor
//------------------------------------------------------------------------------
DebuggerCore::DebuggerCore() : page_size_(0), process_handle_(0), start_address(0), image_base(0) {
	DebugSetProcessKillOnExit(false);

	SYSTEM_INFO sys_info;
	GetSystemInfo(&sys_info);
	page_size_ = sys_info.dwPageSize;

	set_debug_privilege(GetCurrentProcess(), true); // gogo magic powers
}
void CDebugger::Attach(DWORD dwProcessId) {
    cout << "[+] Debugger attach to pid:" << dwProcessId << endl;

    m_bActive = DebugActiveProcess(dwProcessId);
    if (m_bActive) {
        bool bSuccess = DebugSetProcessKillOnExit(m_bKillOnExit);
        DebugLoop();
    } else {
        cout << "[-] Attach failed!" << endl;
    }
}
Exemple #6
0
void spwanAndHook_(char *dlltoinject,opt *options){
	STARTUPINFO         sInfo;
	PROCESS_INFORMATION pInfo;

	printf("[Info] Launching process: %s\n",options->cmdline);
	ZeroMemory(&sInfo, sizeof(sInfo));
	sInfo.cb = sizeof(sInfo);
	ZeroMemory(&pInfo, sizeof(pInfo));

	if (CreateProcess(options->cmdline, NULL, NULL, NULL, FALSE, DEBUG_ONLY_THIS_PROCESS/*CREATE_SUSPENDED*/, NULL, NULL, &sInfo, &pInfo))
	{
		char cmd[512];
		printf("[info] New pid: %d\n",pInfo.dwProcessId);
		sprintf(cmd,"EXECUTING \"%s\" HOOKING PID %d",options->cmdline,pInfo.dwProcessId);
		logger(options->ini,"injector",cmd,strlen(cmd));

		DEBUG_EVENT             debugEvent;

		do{
//			printf(">> %x\n",debugEvent.dwDebugEventCode);
		    if(!WaitForDebugEvent(&debugEvent, 1000)) break;
		    if(debugEvent.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT)
		    {
//				SuspendThread(debugEvent.u.CreateProcessInfo.hThread);
//				printf("Injecting!\n");
				injecta(pInfo.dwProcessId,dlltoinject,options);
				Sleep(1000);
//				ResumeThread(debugEvent.u.CreateProcessInfo.hThread);
				DebugSetProcessKillOnExit(FALSE);
		        DebugActiveProcessStop(debugEvent.dwProcessId);
				break;
		    }
		    ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);
		} while(1);

		/*
		if(WaitForInputIdle((void*)pInfo.hProcess,5)==WAIT_FAILED) printf("[info] Wait failed, console app? :p");
		if(options->waitKeyPress){
			printf("Press [intro] to resume process..\n");
			getchar();
		}*/
//		injecta(pInfo.dwProcessId,dlltoinject,options);
//		ResumeThread((void*)pInfo.hThread);
//		WaitForInputIdle((void*)pInfo.dwProcessId,INFINITE);
//		Sleep(100);
	    CloseHandle(pInfo.hThread);
	    CloseHandle(pInfo.hProcess);
	}else{
		printf("[Error] Unable to create the process (path not found?)\n");
	}
}
void CDebugger::Start() {
    // Reset debugger status
    Reset();

    STARTUPINFO startInfo;
    PROCESS_INFORMATION processInfo;

    ZeroMemory(&startInfo, sizeof(startInfo));
    startInfo.cb = sizeof(startInfo);
    ZeroMemory(&processInfo, sizeof(processInfo));

    bool bSuccess = CreateProcess(m_pExePath, m_pArg, NULL, NULL, false, DEBUG_PROCESS, NULL, NULL, &startInfo, &processInfo);
    if (bSuccess) {
        cout << "[+] Start debugging process: " << m_pExePath << endl;
    } else {
        cout << "[-] Could not start debugging process: " << m_pExePath << " Error = " << GetLastError() << endl;
    }

    m_bActive = true;
    DebugSetProcessKillOnExit(m_bKillOnExit);

    return DebugLoop();
}
/* Detach from inferior PID.  */
static int
win32_detach (int pid)
{
  struct process_info *process;
  winapi_DebugActiveProcessStop DebugActiveProcessStop = NULL;
  winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL;
#ifdef _WIN32_WCE
  HMODULE dll = GetModuleHandle (_T("COREDLL.DLL"));
#else
  HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
#endif
  DebugActiveProcessStop = GETPROCADDRESS (dll, DebugActiveProcessStop);
  DebugSetProcessKillOnExit = GETPROCADDRESS (dll, DebugSetProcessKillOnExit);

  if (DebugSetProcessKillOnExit == NULL
      || DebugActiveProcessStop == NULL)
    return -1;

  {
    struct thread_resume resume;
    resume.thread = minus_one_ptid;
    resume.kind = resume_continue;
    resume.sig = 0;
    win32_resume (&resume, 1);
  }

  if (!DebugActiveProcessStop (current_process_id))
    return -1;

  DebugSetProcessKillOnExit (FALSE);
  process = find_process_pid (pid);
  remove_process (process);

  win32_clear_inferiors ();
  return 0;
}
Exemple #9
0
void *Ploopgrab(LPVOID args)
{
    DEBUG_EVENT  dbg;
    DWORD cont = DBG_CONTINUE, size = 0;
    TCHAR pszFilename[MAX_PATH+1];
    DWORD64 mod;
    struct proc_uc *tmp = args;
    struct ps_prochandle *P = tmp->ps;
    int first_execp = 0;
    BOOL wow = 0;
    char *s;
    DWORD Options = SymGetOptions();

    if (DebugActiveProcess(P->pid) == 0) {
        dprintf( "failed to debug process (%d): %d\n", P->pid, GetLastError() );
        pthread_mutex_lock(&P->mutex);
        P->status = PS_STOP;
        P->flags = CREATE_FAILED;
        if (P->status == PS_STOP)
            pthread_cond_signal(&P->cond);
        pthread_mutex_unlock(&P->mutex);
        return NULL;
    }

    DebugSetProcessKillOnExit(FALSE);

    P->wstat = 0;
    P->exitcode = 0;
    P->event = CreateEvent(NULL,FALSE,FALSE,NULL);
    P->dll_load_order = 1;
    SymSetOptions(Options|SYMOPT_INCLUDE_32BIT_MODULES|SYMOPT_DEFERRED_LOADS|SYMOPT_DEBUG);

    while (1) {
        if (WaitForDebugEvent(&dbg, INFINITE) == 0) {
            return NULL;
        }

        cont = DBG_CONTINUE;
        pthread_mutex_lock(&P->mutex);

        switch (dbg.dwDebugEventCode) {
        case CREATE_PROCESS_DEBUG_EVENT:
            P->thandle = dbg.u.CreateProcessInfo.hThread;
            P->phandle = dbg.u.CreateProcessInfo.hProcess;
            if ((SymInitialize(P->phandle, 0, FALSE) == FALSE)) {
                dprintf("SymInitialize failed (%d): %d\n", P->pid, GetLastError());
                break;
            }

            s = GetFileNameFromHandle(dbg.u.CreateProcessInfo.hFile, pszFilename);
            addmodule(P, dbg.u.CreateProcessInfo.hFile, s, dbg.u.CreateProcessInfo.lpBaseOfImage, PE_TYPE_EXE, P->dll_load_order);
            size = GetFileSize(dbg.u.CreateProcessInfo.hFile, NULL);
            if (size == INVALID_FILE_SIZE) {
                size = 0;
            }

            if ((mod = SymLoadModuleEx(P->phandle,  dbg.u.CreateProcessInfo.hFile, s, NULL,
                                       (ULONG_PTR) dbg.u.CreateProcessInfo.lpBaseOfImage, size, NULL, 0)) == FALSE) {
                dprintf("SymLoadModule64 Failed for %s: %d\n", s, GetLastError());
                break;
            }

#if __amd64__
            if (Is32bitProcess(P->phandle)) {
                P->model = PR_MODEL_ILP32;
                wow = 1;
            } else
                P->model = PR_MODEL_ILP64;
#else
            P->model = PR_MODEL_ILP32;
#endif

            CloseHandle(dbg.u.CreateProcessInfo.hFile);
            P->status = PS_RUN;
            P->msg.type = 0;
            break;
        case CREATE_THREAD_DEBUG_EVENT:
            P->status = PS_RUN;
            P->msg.type = 0;
            break;
        case LOAD_DLL_DEBUG_EVENT:
            s = GetFileNameFromHandle(dbg.u.LoadDll.hFile, pszFilename);
            if (first_execp) {
                P->dll_load_order++;
            }
            addmodule(P, dbg.u.LoadDll.hFile, s, dbg.u.LoadDll.lpBaseOfDll, PE_TYPE_DLL, P->dll_load_order);
            size = GetFileSize(dbg.u.CreateProcessInfo.hFile, NULL);
            if (size == INVALID_FILE_SIZE) {
                size = 0;
            }
#if __amd64__
            /* Not tracing 64 bit dlls for 32 bit process */
            if (P->model == PR_MODEL_ILP32 && is64bitmodule(dbg.u.LoadDll.lpBaseOfDll, s)) {
                CloseHandle(dbg.u.LoadDll.hFile );
                break;
            }
#endif
            if ((mod = SymLoadModuleEx(P->phandle,  dbg.u.LoadDll.hFile, s, NULL,
                                       (ULONG_PTR) dbg.u.LoadDll.lpBaseOfDll, size, NULL, 0)) == FALSE) {
                dprintf("SymLoadModule64 failed for %s: %d\n", s, GetLastError());
                break;
            }

            CloseHandle(dbg.u.LoadDll.hFile );

            if (first_execp == 0) {
                P->status = PS_RUN;
                P->msg.type = RD_DLACTIVITY;
            } else {
                P->status = PS_STOP;
                P->msg.type = RD_DLACTIVITY;
            }
            break;
        case UNLOAD_DLL_DEBUG_EVENT:
            if (SymUnloadModule64(P->phandle, (ULONG_PTR) dbg.u.UnloadDll.lpBaseOfDll) ==  FALSE) {
                dprintf("SymUnloadModule64 failed-Imagebase %p: %d\n", dbg.u.UnloadDll.lpBaseOfDll, GetLastError());
                break;
            }
            delmodule(P, (ULONG64) dbg.u.UnloadDll.lpBaseOfDll);
            P->status = PS_RUN;
            P->msg.type = RD_DLACTIVITY;
            break;
        case EXIT_PROCESS_DEBUG_EVENT:
            P->exitcode = dbg.u.ExitProcess.dwExitCode;
            P->status = PS_UNDEAD;
            P->msg.type = RD_NONE;
            //SymCleanup(P->phandle);
            break;
        case EXIT_THREAD_DEBUG_EVENT:
            P->status = PS_RUN;
            P->msg.type = 0;
            break;
        case EXCEPTION_DEBUG_EVENT:
            switch(dbg.u.Exception.ExceptionRecord.ExceptionCode) {
            case EXCEPTION_BREAKPOINT:
                if (first_execp++ == 0) {
                    pthread_cond_signal(&P->cond);
                }
                P->status = PS_STOP;
                P->msg.type = 0;

                break;
            default:
                if (dbg.u.Exception.dwFirstChance == 0)
                    P->wstat = dbg.u.Exception.ExceptionRecord.ExceptionCode;
                P->status = PS_RUN;
                cont = DBG_EXCEPTION_NOT_HANDLED;
                break;
            }
            break;
        default:
            P->status = PS_RUN;
            dprintf("Debug Event not processed: %d\n", dbg.dwDebugEventCode);
            break;
        }

        if (P->status != PS_RUN)
            SetEvent(P->event);

        while (P->status == PS_STOP)
            pthread_cond_wait(&P->cond, &P->mutex);
        pthread_mutex_unlock(&P->mutex);

        ContinueDebugEvent(dbg.dwProcessId, dbg.dwThreadId, cont);
    }

}
int wmain(int argc, WCHAR *argv[])
{

	/* Display welcome message */
	printf("handle_monitor %s - Adam Kramer\n", VERSION_NUMBER);

	/* These variables hold configuration options, which can be altered by arguments passed */
	BOOL bIncludeSigned = FALSE;
	BOOL bSuspendProcess = FALSE;
	BOOL bVerbose = FALSE;
	DWORD dNumberCycles = 10;
	DWORD dHandleChangeThreshold = 10;
	DWORD dIterationPause = 1000;

	/* Process arguments */
	if (argc > 1)
	{
		for (int iNumberArgs = 1; iNumberArgs < argc; iNumberArgs++)
		{
			/* /signed - will include signed files in the alerts */
			if (!wcscmp(argv[iNumberArgs], L"/signed"))
			{
				bIncludeSigned = TRUE;
				printf("Info: Will show signed files as well as unsigned\n");
			}
			/* /suspect - will attempt to suspend suspicious processes */
			else if (!wcscmp(argv[iNumberArgs], L"/suspend"))
			{
				bSuspendProcess = TRUE;
				printf("Info: Will attempt to suspend suspicious processes\n");
			}
			/* /verbose - will display details of iterations and hidden results */
			else if (!wcscmp(argv[iNumberArgs], L"/verbose"))
			{
				bVerbose = TRUE;
				printf("Info: Will display verbose status messages\n");
			}
			/* /cycles - allows the user to set cycles completed before analysis */
			else if (WCHAR* wSetCycles = wcsstr(argv[iNumberArgs], L"/cycles="))
			{
				wSetCycles = wcschr(wSetCycles, '=');

				if (!(dNumberCycles = _wtol(++wSetCycles)))
				{
					printf("Error: Invalid /cycles parameter\n");
					return 1;
				}

				printf("Info: Setting number of cycles to %d\n", dNumberCycles);
			}
			/* /threshold - allows the user to set the threshold for minimum number of new handles which are suspicious */
			else if (WCHAR* wSetThreshold = wcsstr(argv[iNumberArgs], L"/threshold="))
			{
				wSetThreshold = wcschr(wSetThreshold, '=');

				if (!(dHandleChangeThreshold = _wtol(++wSetThreshold)))
				{
					printf("Error: Invalid /threshold parameter\n");
					return 1;
				}

				printf("Info: Setting handle threshold to %d\n", dHandleChangeThreshold);
			}
			/* /pause - allows the user to set a pause between cycles (reduce system load, increase window for finding something) */
			else if (WCHAR* wSetPause = wcsstr(argv[iNumberArgs], L"/pause="))
			{
				wSetPause = wcschr(wSetPause, '=');

				dIterationPause = _wtol(++wSetPause);
				printf("Info: Setting pause between cycles to %dms\n", dIterationPause);
			}
		}
		/* End of argument processing */
	}
	else
	{
		/* No argument passed, accordingly display the usage instructions */
		printf("Usage: handle_monitor.exe <optional parameters>\n\n");
		printf("Optional parameters:\n");
		printf("/cycles=X - Set number of cycles before a review [Default: 10]\n");
		printf("/threshold=X - Set suspicion threshold for number of new handles [Default: 10]\n");
		printf("/pause=X - Set pause in milliseconds between cycles [Default: 1000]\n");
		printf("/signed - Include signed executables in review process\n");
		printf("/suspend - Suspend processes identified as suspicious\n");
		printf("/verbose - Display verbose progress messages\n\n");
		printf("Info: No parameters specified, launching monitoring (Ctrl+C to stop)\n");
	}

	/* Import functions manually from NTDLL */
	_NtQuerySystemInformation NtQuerySystemInformation =
		(_NtQuerySystemInformation)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQuerySystemInformation");

	_NtDuplicateObject NtDuplicateObject =
		(_NtDuplicateObject)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtDuplicateObject");

	_NtQueryObject NtQueryObject =
		(_NtQueryObject)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryObject");

	/* Master loop! - This runs forever until a user presses Ctrl+C */
	for (;;)
	{
		/* Update user that process is starting (if /verbose mode activiated) */
		if (bVerbose)
			printf("Verbose Info: Starting sequence\n");

		/* Variables used for retrieving handles */
		NTSTATUS status;
		ULONG handleInfoSize = 0x10000;
		HANDLE processHandle;
		ULONG i;
		PSYSTEM_HANDLE_INFORMATION handleInfo;

		/* Used in each handle iteration to identify the index in iProcessArray of the specific process */
		int iCurrentProcess_ArrayIndex = -1;

		/* Handle array - PROCESS INDEX / HANDLE NUMBER / TEXT OF HANDLE
			This holds all handles which have been found per process */
		auto cHandleArray = new WCHAR[MAX_PROCESSES][MAX_FILE_HANDLES][MAX_PATH]();
		signed int iProcessArray[MAX_PROCESSES][3] = { 0 };

		/* Set process array to -1, which indicates nothing has been set */
		for (int j = 0; j < (MAX_PROCESSES - 1); j++)
			iProcessArray[j][0] = -1;

		/* Loop dNumberCycles [default: 10] times before analysing result */
		for (unsigned int iCycleCounter = 1; iCycleCounter <= dNumberCycles; iCycleCounter++)
		{
			handleInfoSize = 0x10000;
			handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize);

			/* NtQuerySystemInformation won't give us the correct buffer size, so we guess by doubling the buffer size. */
			while ((status = NtQuerySystemInformation(SystemHandleInformation, handleInfo, handleInfoSize, NULL)) == STATUS_INFO_LENGTH_MISMATCH)
				handleInfo = (PSYSTEM_HANDLE_INFORMATION)realloc(handleInfo, handleInfoSize *= 2);

			/* NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH. */
			if (!NT_SUCCESS(status))
			{
				printf("NtQuerySystemInformation failed!\n");
				return 1;
			}

			/* Loop for each handle on the system, processing it accordingly... */
			for (i = 0; i < handleInfo->HandleCount; i++)
			{
				SYSTEM_HANDLE handle = handleInfo->Handles[i];
				HANDLE dupHandle = NULL;
				POBJECT_TYPE_INFORMATION objectTypeInfo;

				/* Open a handle to the process associated with the handle */
				if (!(processHandle = OpenProcess(PROCESS_DUP_HANDLE, FALSE, handle.ProcessId)))
					continue;

				/* Duplicate the handle so we can query it. */
				if (!NT_SUCCESS(NtDuplicateObject(processHandle, (HANDLE)handle.Handle, GetCurrentProcess(), &dupHandle, GENERIC_READ, 0, 0)))
				{
					CloseHandle(processHandle);
					CloseHandle(dupHandle);
					continue;
				}

				/* Query the object type */
				objectTypeInfo = (POBJECT_TYPE_INFORMATION)malloc(0x1000);
				if (!NT_SUCCESS(NtQueryObject(dupHandle, ObjectTypeInformation, objectTypeInfo, 0x1000, NULL)))
				{
					free(objectTypeInfo);
					CloseHandle(processHandle);
					CloseHandle(dupHandle);
					continue;
				}

				/* If it's not a file handle, go to next one (as we're only interested in file handles) */
				if (wcscmp(objectTypeInfo->Name.Buffer, L"File"))
				{
					free(objectTypeInfo);
					CloseHandle(processHandle);
					CloseHandle(dupHandle);
					continue;
				}

				/* Identify the filename from the handle we're looking at */
				WCHAR* wHandleFileName = new WCHAR[MAX_PATH]();

				if (!GetFileNameFromHandle(dupHandle, wHandleFileName))
				{
					free(objectTypeInfo);
					free(wHandleFileName);
					CloseHandle(processHandle);
					CloseHandle(dupHandle);
					continue;
				}

				/* This is where we add our findings to the database */
				iCurrentProcess_ArrayIndex = -1;

				/* Check whether we've already got an entry for the process we're looking at */
				for (int j = 0; j < (MAX_PROCESSES - 1); j++)
					if (iProcessArray[j][PROCESS_ARRAY_INDEX] == handle.ProcessId)
						iCurrentProcess_ArrayIndex = j;

				/* If not, create a new entry for the process associated with the current handle */
				if (iCurrentProcess_ArrayIndex == -1)
					for (int j = 0; j < (MAX_PROCESSES - 1); j++)
						if (iProcessArray[j][PROCESS_ARRAY_INDEX] == -1)
						{
							iProcessArray[j][PROCESS_ARRAY_INDEX] = handle.ProcessId;
							iCurrentProcess_ArrayIndex = j;
							break;
						}

				/* If there's more than MAX_PROCESSES, throw an error
					TODO: Tidy this up, identify number of running processes dynamically and set array size accordingly */
				if (iCurrentProcess_ArrayIndex == -1)
				{
					printf("Error: Too many processes running!\n");
					return 1;
				}

				/* Look through the handle array, to see whether the filename can be found */
				WCHAR cCurrentHandleText[MAX_PATH];
				for (int j = 0; j < (MAX_FILE_HANDLES - 1); j++)
				{
					/* If we hit NULL, there are no more to find, so add ours */
					swprintf_s(cCurrentHandleText, MAX_PATH, L"%ls", wHandleFileName);

					if (!wcscmp(cHandleArray[iCurrentProcess_ArrayIndex][j], L"")){
						wcscpy_s(cHandleArray[iCurrentProcess_ArrayIndex][j], cCurrentHandleText);
						break;
					}
					/* If we find ours, then stop searching */
					else if (!wcscmp(cHandleArray[iCurrentProcess_ArrayIndex][j], cCurrentHandleText))
						break;
				}

				/* If it's the first (or last) cycle, tally how many entries in the handle array for this
					particular process we have so far */

				if (iCycleCounter == 1)
					for (int j = 0; j < (MAX_FILE_HANDLES - 1); j++)
						if (!wcscmp(cHandleArray[iCurrentProcess_ArrayIndex][j], L"")){
							iProcessArray[iCurrentProcess_ArrayIndex][PROCESS_ARRAY_COUNT_START_CYCLE] = (j - 1);
							break;
						}

				if (iCycleCounter == dNumberCycles)
					for (int j = 0; j < (MAX_FILE_HANDLES - 1); j++)
						if (!wcscmp(cHandleArray[iCurrentProcess_ArrayIndex][j], L"")) {
							iProcessArray[iCurrentProcess_ArrayIndex][PROCESS_ARRAY_COUNT_END_CYCLE] = (j - 1);
							break;
						}

				free(objectTypeInfo);
				free(wHandleFileName);
				CloseHandle(dupHandle);
				CloseHandle(processHandle);
			}
			free(handleInfo);

			/* If the iteration pause is not 0, sleep for the requested time [Default: 1000ms] */
			if (dIterationPause)
				Sleep(dIterationPause);

			/* If /verbose active - inform user which cycle we are on */
			if (bVerbose)
				if (iCycleCounter == 1)
					printf("Verbose Info: Completed cycle %d", iCycleCounter);
				else if (iCycleCounter == dNumberCycles)
					printf(" %d\n", iCycleCounter);
				else
					printf(" %d", iCycleCounter);
		}

		/* If /verbose active - inform user we are now starting a review */
		if (bVerbose)
			printf("Verbose Info: Cycles completed, beginning review\n");

		/* Check if any of them met threshold*/
		for (int j = 0; j < (MAX_PROCESSES - 1); j++)
		{
			if (iProcessArray[j][PROCESS_ARRAY_COUNT_END_CYCLE] < iProcessArray[j][PROCESS_ARRAY_COUNT_START_CYCLE])
				continue;

			/* dHandleDelta is the difference between number of handles for a process from first cycle to the last one  */
			DWORD dHandleDelta = (iProcessArray[j][PROCESS_ARRAY_COUNT_END_CYCLE] - iProcessArray[j][PROCESS_ARRAY_COUNT_START_CYCLE]);

			/* Check whether the delta is equal or above the threshold */
			if (dHandleDelta >= dHandleChangeThreshold)
			{
				HANDLE pHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, iProcessArray[j][PROCESS_ARRAY_INDEX]);
				TCHAR tProcessName[MAX_PATH];
				GetModuleFileNameEx(pHandle, 0, tProcessName, MAX_PATH);
				CloseHandle(pHandle);

				/* If we don't want signed, yet it is signed, skip... */
				if (!bIncludeSigned && (is_signed(tProcessName) == 0))
				{
					if (bVerbose)
						wprintf(L"Verbose Info: Skipping alert on %s (%d) despite trigger, as it is signed (use /signed to alert on signed executables too)\n", tProcessName, iProcessArray[j][PROCESS_ARRAY_INDEX]);
					continue;
				}

				/* Inform the user if we have a suspicious process */
				wprintf(L"Alert! Process: %s (%d) has had a suspicious number of handles (%d) created in the last cycle\nNew handles created during this cycle:\n", tProcessName, iProcessArray[j][PROCESS_ARRAY_INDEX], dHandleDelta);

				for (DWORD k = 1; k <= dHandleDelta; k++)
					wprintf(L"%s\n", cHandleArray[j][iProcessArray[j][PROCESS_ARRAY_COUNT_START_CYCLE] + k]);

				if (bSuspendProcess)
				{

					printf("Info: Attempting to suspend process %d\n", iProcessArray[j][PROCESS_ARRAY_INDEX]);

					/* Attach debugger to process (freeze it!)*/
					if (!DebugActiveProcess(iProcessArray[j][PROCESS_ARRAY_INDEX]))
					{
						printf("Info: Could not attach to process %d as a debugger\n", iProcessArray[j][PROCESS_ARRAY_INDEX]);
					}
					else
					{
						DebugSetProcessKillOnExit(FALSE);

						printf("Info: Successfully attached to process %d as debugger\n", iProcessArray[j][PROCESS_ARRAY_INDEX]);
						printf("Info: It will remain frozen until this process is terminated\n");
					}
				}

				printf("------------------------------------------------------------------------------\n");

			}
		}

		if (bVerbose)
			printf("Verbose Info: Review complete\n");

		free(cHandleArray);

	}

	return 0;
}
int main(int argc, char **argv){
    if( argc<2){
        printf("Usage: %s <ip address>\n", argv[0]);
        return 1;
    }
    
    if( IsDebuggerPresent()){
        HANDLE iphlpapi=LoadLibrary("iphlpapi.dll");
        if( !iphlpapi){
            perror("iphlpapi.dll");
            return 1;
        }
        FARPROC IcmpSendEcho=GetProcAddress(iphlpapi, "IcmpSendEcho");
        FARPROC IcmpCreateFile=GetProcAddress(iphlpapi, "IcmpCreateFile");
        FARPROC IcmpCloseHandle=GetProcAddress(iphlpapi, "IcmpCloseHandle");
        if( (IcmpSendEcho && IcmpCreateFile && IcmpCloseHandle)==0){
            perror("icmp functions");
            return 1;
        }
        
        unsigned long ipaddr=INADDR_NONE, params[2];
        HANDLE hIcmpFile;
        char data[32], *reply;
        int replySize=sizeof(ICMP_ECHO_REPLY)+sizeof(data);
        
        if( (ipaddr=inet_addr(argv[1]))==INADDR_NONE){
            perror("Illegal IP address!");
            return 1;
        }
        
        if( (hIcmpFile=(HANDLE)IcmpCreateFile())==INVALID_HANDLE_VALUE){
            perror("IcmpCreateFile");
            return 1;
        }
        
        reply=(char *)malloc(replySize);
        ZeroMemory(data, sizeof(data));
        params[0]=PARAM;
        params[1]=(unsigned long)GetProcAddress(iphlpapi, "IcmpSendEcho2Ex");
        
        RaiseException(EXCEPTION_BREAKPOINT, 0, 2, params);
        puts("Exception raised!");
        IcmpSendEcho(hIcmpFile, ipaddr, data, sizeof(data), NULL, reply, replySize, 1000);
        puts("This line should never be shown...");
        IcmpCloseHandle(hIcmpFile);
        return 0;
    }
    
    PROCESS_INFORMATION pi;
    STARTUPINFO si;
    HANDLE hProcess, hThread;
    DEBUG_EVENT debugEvent;
    EXCEPTION_RECORD *ExceptionRecord=&debugEvent.u.Exception.ExceptionRecord;
    CONTEXT context;
    FARPROC IcmpSendEcho2Ex=NULL;
    char path[256], args[512], originalByte[1];
    
    ZeroMemory(?, sizeof(PROCESS_INFORMATION));
    ZeroMemory(&si, sizeof(STARTUPINFO));
    ZeroMemory(&debugEvent, sizeof(DEBUG_EVENT));
    ZeroMemory(&context, sizeof(CONTEXT));
    ZeroMemory(path, sizeof(path));
    ZeroMemory(args, sizeof(args));
    si.cb=sizeof(STARTUPINFO);
    si.dwFlags=STARTF_USESHOWWINDOW;
    si.wShowWindow=SW_HIDE;
    context.ContextFlags=CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
    
    GetModuleFileName(NULL, path, sizeof(path)-1);
    snprintf(args, sizeof(args)-1, "%s %s", path, argv[1]);
    
    if( !CreateProcess(
        NULL,
        args,
        NULL,
        NULL,
        FALSE,
        DEBUG_PROCESS,
        NULL,
        NULL,
        &si,
        ?
    )){
       perror("CreateProcess");
       return 1;
    }
    
    if( (hProcess=OpenProcess(PROCESS_ALL_ACCESS, FALSE, pi.dwProcessId))==NULL){
       perror("OpenProcess");
       return 1;
    }
    
    HANDLE kernel32=LoadLibrary("kernel32.dll");
    FARPROC DebugSetProcessKillOnExit=GetProcAddress(kernel32, "DebugSetProcessKillOnExit");
    FARPROC DebugActiveProcessStop=GetProcAddress(kernel32, "DebugActiveProcessStop");
    FARPROC OpenThread=GetProcAddress(kernel32, "OpenThread");
    CloseHandle(kernel32);
    DebugSetProcessKillOnExit(TRUE);
    
    while(WaitForDebugEvent(&debugEvent, INFINITE) && debugEvent.dwDebugEventCode!=EXIT_PROCESS_DEBUG_EVENT){
             if( debugEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT && ExceptionRecord->ExceptionCode==EXCEPTION_BREAKPOINT){
                 if( ExceptionRecord->NumberParameters>1 && ExceptionRecord->ExceptionInformation[0]==PARAM){
                     IcmpSendEcho2Ex=(FARPROC)ExceptionRecord->ExceptionInformation[1];
                     printf("IcmpSendEcho2Ex %p\n", IcmpSendEcho2Ex);
                     if( !BreakpointSet(hProcess, IcmpSendEcho2Ex, &originalByte)){
                         perror("BreakpointSet");
                         break;
                     }
                 }
                 else if( ExceptionRecord->ExceptionAddress==IcmpSendEcho2Ex){
                      printf("EIP %p\n", IcmpSendEcho2Ex);
                      if( !BreakpointRetrieve(hProcess, IcmpSendEcho2Ex, &originalByte)){
                          perror("BreakpointRetrieve");
                          break;
                      }
                      if((hThread=(HANDLE)OpenThread(THREAD_ALL_ACCESS, FALSE, debugEvent.dwThreadId))==NULL) puts("OpenThread");
                      if(!GetThreadContext(hThread, &context)) puts("GetThreadContext");
                      context.Eip -= 1;
                      if(!SetThreadContext(hThread, &context)) puts("SetThreadContext");
                      CreateThread(NULL, 0, (void *)Terminate, hProcess, 0, NULL);
                 }
             }
             else if( debugEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT){
                  puts("Exception!");
                  DebugActiveProcessStop(debugEvent.dwProcessId);
                  break;
             }
             ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);
             ZeroMemory(&debugEvent, sizeof(DEBUG_EVENT));
    }
    
    return 0;
}
Exemple #12
0
void DebuggerThread::run()
{
	if ( !DebugActiveProcess( debugger->processId ) )
		return;

	DebugSetProcessKillOnExit( FALSE );
	HANDLE hImageFile = NULL;
	//bool go = false;
	//HANDLE target_thread = 0;

	while( !commit_suicide )
	{
		DEBUG_EVENT dbgEvent;
		if ( !WaitForDebugEvent( &dbgEvent, 100 ) )
		{
			//if ( go )
			//{
			//	DWORD t0 = GetTickCount();
			//	CONTEXT threadcontext;
			//	threadcontext.ContextFlags = CONTEXT_i386 | CONTEXT_CONTROL;

			//	HRESULT result = SuspendThread(target_thread);

			//	if(result == 0xffffffff)
			//		__asm int 3

			//	SetThreadPriority( target_thread, THREAD_PRIORITY_TIME_CRITICAL );
			//	result = GetThreadContext(target_thread, &threadcontext);
			//	SetThreadPriority( target_thread, THREAD_PRIORITY_NORMAL );

			//	ResumeThread(target_thread);
			//	
			//	DWORD t1 = GetTickCount();
			//	char buf[256];
			//	sprintf(buf, "%08x - %ims\n", t1, t1 - t0);
			//	OutputDebugString(buf);
			//}
	
			DWORD err = GetLastError();
			continue;
		}

		WaitForSingleObject( hMutex, INFINITE );
		switch (dbgEvent.dwDebugEventCode) 
		{ 
		case EXCEPTION_DEBUG_EVENT:
			SetEvent( readyEvent );
			//go = true;
			break;

		case CREATE_THREAD_DEBUG_EVENT: 
			debugger->hThreads.push_back( ThreadInfo( dbgEvent.dwThreadId, dbgEvent.u.CreateThread.hThread ) );
			break;

		case CREATE_PROCESS_DEBUG_EVENT:
			debugger->hProcess = dbgEvent.u.CreateProcessInfo.hProcess;
			hImageFile = dbgEvent.u.CreateProcessInfo.hFile;
			debugger->hThreads.push_back( ThreadInfo( dbgEvent.dwThreadId, dbgEvent.u.CreateProcessInfo.hThread ) );
			//target_thread = dbgEvent.u.CreateProcessInfo.hThread;
			break;

		case EXIT_THREAD_DEBUG_EVENT: 
			// Display the thread's exit code. 
			break;

		case EXIT_PROCESS_DEBUG_EVENT: 
			// Display the process's exit code. 
			break;

		case LOAD_DLL_DEBUG_EVENT: 
			// Read the debugging information included in the newly 
			// loaded DLL. Be sure to close the handle to the loaded DLL 
			// with CloseHandle.
			break;

		case UNLOAD_DLL_DEBUG_EVENT: 
			// Display a message that the DLL has been unloaded. 
			break;

		case OUTPUT_DEBUG_STRING_EVENT: 
			// Display the output debugging string. 
			break;

		} 

		ReleaseMutex( hMutex );
		ContinueDebugEvent( dbgEvent.dwProcessId, dbgEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED );
	}

	if ( hImageFile )
		CloseHandle( hImageFile );

	DebugActiveProcessStop( debugger->processId );
}
Exemple #13
0
DWORD WINAPI DebugThread(LPVOID arg)
{
	DEBUG_EVENT evt;
	DWORD dwContinue;
	DWORD dwBPAddress = 0x44D471;
	DWORD dwBPEnd = 0x44D47C;
	DWORD dwDataRead = 0x443848;
	DWORD dwDataSucceed = 0x44384D;
	BYTE bBPAddr = 0;
	BYTE bBPEnd = 0;
	BYTE bDataRead = 0;
	BYTE bDataSucceed = 0;
	DWORD dwRead;

	DWORD dwDataLength = 0;	//[ESP + 0x10] at 0x443848
	char szName[16];		//[ESP + 0x0C] at 0x44384D
	char szHeader[8];		//[ESP + 0x08] at 0x44384D This value should "BSE 1.0\0"

	BOOL bFlag = FALSE;
	BOOL bFlag2 = FALSE;
	BOOL bAlpha = FALSE;

	CONTEXT lcContext;
	HANDLE hThread = NULL;
	HANDLE hProcess = NULL;

	LPVOID ptr, ptr2;
	BYTE *pBMPData;
	DWORD dwLength;
	BYTE *pData;

	Image *result;
//	SYSTEMTIME time;
	WCHAR str[64];

	unsigned short width;
	unsigned short height;

	szName[0] = 0;

	if (DebugActiveProcess(dwProcessID))
		SetEvent(hAttachSucceeded);

	SetEvent(hDebugInit);

	DebugSetProcessKillOnExit(FALSE);

	while (TRUE)
	{
		if (WaitForSingleObject(hDebugEnd, 0) == WAIT_OBJECT_0)
			break;

		dwContinue = DBG_CONTINUE;

		if (WaitForDebugEvent(&evt, 10))
		{
			switch (evt.dwDebugEventCode)
			{
				case CREATE_PROCESS_DEBUG_EVENT:
					bDataRead = SetSoftwareBreakpoint(evt.u.CreateProcessInfo.hProcess, dwDataRead);

					hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, evt.dwProcessId);

					CloseHandle(evt.u.CreateProcessInfo.hFile);
					break;
				case CREATE_THREAD_DEBUG_EVENT:
					break;
				case LOAD_DLL_DEBUG_EVENT:
					CloseHandle(evt.u.LoadDll.hFile);
					break;
				case EXCEPTION_DEBUG_EVENT:
					if (evt.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT)
					{
						if (evt.u.Exception.ExceptionRecord.ExceptionAddress == (PVOID)dwBPAddress)
						{
						//	if (bFlag)
						//	{
							//	MessageBeep(0);
								bAlpha = FALSE;

								hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, evt.dwThreadId);

								lcContext.ContextFlags = CONTEXT_ALL;
								GetThreadContext(hThread, &lcContext);

								ptr = (LPVOID)(lcContext.Eax + 0x08);
								ReadProcessMemory(hProcess, ptr, &pBMPData, 4, &dwRead);

								ReadProcessMemory(hProcess, (LPVOID)pBMPData, &width, 2, &dwRead);
								ReadProcessMemory(hProcess, (LPVOID)(pBMPData + 2), &height, 2, &dwRead);
								dwLength = width * height * 4;

								pData = (BYTE *)calloc(dwLength, sizeof(BYTE));
								if (pData)
								{
									wsprintf(str, L"[%dx%d] %S", width, height, szName);
									
									if (SendMessage(hListLayer, LB_FINDSTRINGEXACT, -1, (LPARAM)str) == LB_ERR)
									{
										SendMessage(hListLayer, LB_INSERTSTRING, 0, (LPARAM)str);

										ReadProcessMemory(hProcess, (LPVOID)(pBMPData + 0x10), pData, dwLength, &dwRead);
										result = (Image *)calloc(1, sizeof(Image));

										result->width = width;
										result->height = height;
										result->data = (PIXEL *)pData;

										//Is this bitmap has no alpha channel (all alpha channel == 0)
										for (int i = 0; i < width * height; i++)
											if (result->data[i].a != 0x00)
											{
												bAlpha = TRUE;
												break;
											}

										//Set alpha channel
										if (!bAlpha)
											for (int i = 0; i < width * height; i++)
												result->data[i].a = 0xFF;

										//Insert Decoded Image to List
										SendMessage(hListLayer, LB_SETITEMDATA, 0, (LPARAM)result);
									}
								}

								MoveEIPBack(hThread);
								bBPEnd = SetSoftwareBreakpoint(hProcess, dwBPEnd);
								ResetSoftwareBreakpoint(hProcess, dwBPAddress, bBPAddr);

								CloseHandle(hThread);
						//	}
						//	else
								bFlag = TRUE;
						}
						else if (evt.u.Exception.ExceptionRecord.ExceptionAddress == (PVOID)dwBPEnd)
						{
						//	if (bFlag2)
						//	{
								hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, evt.dwThreadId);

								MoveEIPBack(hThread);
								bDataRead = SetSoftwareBreakpoint(hProcess, dwDataRead);
								ResetSoftwareBreakpoint(hProcess, dwBPEnd, bBPEnd);

								CloseHandle(hThread);
						//	}
						//	else
								bFlag2 = TRUE;
						}
						else if (evt.u.Exception.ExceptionRecord.ExceptionAddress == (PVOID)dwDataRead)
						{
							hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, evt.dwThreadId);

							lcContext.ContextFlags = CONTEXT_ALL;
							GetThreadContext(hThread, &lcContext);

							ptr = (LPVOID)(lcContext.Esp + 0x10);
							ReadProcessMemory(hProcess, ptr, &dwDataLength, 4, &dwRead);

							MoveEIPBack(hThread);
							bDataSucceed = SetSoftwareBreakpoint(hProcess, dwDataSucceed);
							ResetSoftwareBreakpoint(hProcess, dwDataRead, bDataRead);

							CloseHandle(hThread);
						}
						else if (evt.u.Exception.ExceptionRecord.ExceptionAddress == (PVOID)dwDataSucceed)
						{
							hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, evt.dwThreadId);

							MoveEIPBack(hThread);

							if (dwDataLength)
							{
								lcContext.ContextFlags = CONTEXT_ALL;
								GetThreadContext(hThread, &lcContext);

								if (lcContext.Eax == dwDataLength)
								{
									ptr = (LPVOID)(lcContext.Esp + 0x08);
									ReadProcessMemory(hProcess, ptr, &ptr2, 4, &dwRead);
									ReadProcessMemory(hProcess, ptr2, &szHeader, 8, &dwRead);

									if (strncmp(szHeader, "BSE 1.0\0", 8) == 0)
									{
										//Read Succeed
										ptr = (LPVOID)(lcContext.Esp + 0x0C);
										ReadProcessMemory(hProcess, ptr, &ptr2, 4, &dwRead);
										ReadProcessMemory(hProcess, ptr2, &szName, 16, &dwRead);

										bBPAddr = SetSoftwareBreakpoint(hProcess, dwBPAddress);
									}
									else
										bDataRead = SetSoftwareBreakpoint(hProcess, dwDataRead);
								}
								else
									bDataRead = SetSoftwareBreakpoint(hProcess, dwDataRead);
							}
							else
								bDataRead = SetSoftwareBreakpoint(hProcess, dwDataRead);

							ResetSoftwareBreakpoint(hProcess, dwDataSucceed, bDataSucceed);

							CloseHandle(hThread);
						}
					}
					else if (evt.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP)
					{
					}
					else
						dwContinue = DBG_EXCEPTION_NOT_HANDLED;
					break;
				case EXIT_PROCESS_DEBUG_EVENT:
					SetEvent(hDebugEnd);
					break;
				default:
					dwContinue = DBG_EXCEPTION_NOT_HANDLED;
					break;
			}

			ContinueDebugEvent(evt.dwProcessId, evt.dwThreadId, dwContinue);
		}
	}
	if (bDataRead)
		ResetSoftwareBreakpoint(hProcess, dwDataRead, bDataRead);
	if (bDataSucceed)
		ResetSoftwareBreakpoint(hProcess, dwDataSucceed, bDataSucceed);
	if (bBPAddr)
		ResetSoftwareBreakpoint(hProcess, dwBPAddress, bBPAddr);
	if (bBPEnd)
		ResetSoftwareBreakpoint(hProcess, dwBPEnd, bBPEnd);

	if (hProcess)
		CloseHandle(hProcess);

	DebugActiveProcessStop(dwProcessID);

	return 0;
}
Exemple #14
0
void WINAPI EnterDebugging(DWORD dwPid)
{
	
	DWORD dwAction = DBG_CONTINUE;
	int ret;
	DWORD dwAddress,dwRead;	
	BYTE bCode[16];

	::dwPid = dwPid;
	DebugSetProcessKillOnExit(0);

	hProcess = OpenProcess(PROCESS_ALL_ACCESS,0,dwPid);
	if (hProcess == 0)
	{
		Log("OpenProcess[CREATE_PROCESS_DEBUG_EVENT:Pid:%d] failed:%d",dwPid,GetLastError());
		ExitProcess(0);
	}

	while (WaitForDebugEvent(&dbg_event,INFINITE))
	{
		dwAction = DBG_CONTINUE;			
		
		switch (dbg_event.dwDebugEventCode)
		{
			case CREATE_PROCESS_DEBUG_EVENT:
				Log("CREATE_PROCESS_DEBUG_EVENT:Base:%x OEP:%x",dbg_event.u.CreateProcessInfo.lpBaseOfImage,dbg_event.u.CreateProcessInfo.lpStartAddress);				
				create_process_handler((DWORD) dbg_event.u.CreateProcessInfo.lpBaseOfImage,(DWORD)dbg_event.u.CreateProcessInfo.lpStartAddress);
				Load_Dll_Event(dbg_event.u.CreateProcessInfo.hFile,(DWORD)dbg_event.u.CreateProcessInfo.lpBaseOfImage);
				hProcess = OpenProcess(PROCESS_ALL_ACCESS,0,dwPid);
				if (hProcess == 0)
				{
					Log("OpenProcess[CREATE_PROCESS_DEBUG_EVENT:Pid:%d] failed:%d",dwPid,GetLastError());
					ExitProcess(0);
				}
				break;
			case CREATE_THREAD_DEBUG_EVENT:
				Log("Thread starting... entry point:%x[ht:%x:id:%d] ",dbg_event.u.CreateThread.lpStartAddress,dbg_event.u.CreateThread.hThread,dbg_event.dwThreadId);
				createthread_handler((DWORD)dbg_event.u.CreateThread.lpStartAddress,(DWORD)dbg_event.dwThreadId);
				break;
			case EXCEPTION_DEBUG_EVENT:
				Log("EXCEPTION_DEBUG_EVENT(%x) fc:%x address:0x%x code:0x%x",EXCEPTION_DEBUG_EVENT,dbg_event.u.Exception.dwFirstChance,dbg_event.u.Exception.ExceptionRecord.ExceptionAddress,dbg_event.u.Exception.ExceptionRecord.ExceptionCode);
				dwAction = DBG_EXCEPTION_NOT_HANDLED;
				switch(dbg_event.u.Exception.ExceptionRecord.ExceptionCode)
				{
					case EXCEPTION_INVALID_HANDLE:
						Log("EXCEPTION_INVALID_HANDLE");
						break;
					case EXCEPTION_BREAKPOINT:
						
						dwAddress = (DWORD)dbg_event.u.Exception.ExceptionRecord.ExceptionAddress;
						ret = breakpoint_handler(dwAddress,dbg_event.dwThreadId);
						
						Log("BP exception at:%x ret:%x",dwAddress,ret);
						dwAction = ret;
						
						break;
					case EXCEPTION_SINGLE_STEP:
						Log("EXCEPTION_SINGLE_STEP:%x ",dbg_event.u.Exception.ExceptionRecord.ExceptionAddress);
						ReadProcessMemory(hProcess,dbg_event.u.Exception.ExceptionRecord.ExceptionAddress,bCode,16,&dwRead);
						singlestep_handler((DWORD)dbg_event.u.Exception.ExceptionRecord.ExceptionAddress,bCode,dbg_event.dwThreadId);
						dwAction = DBG_CONTINUE;
						break;
					}
				break;
				
			case EXIT_PROCESS_DEBUG_EVENT:
				Log("EXIT_PROCESS_DEBUG_EVENT");
				return;
			case EXIT_THREAD_DEBUG_EVENT:
				Log("Thread exiting... entry point:%x ",dbg_event.u.CreateThread.lpStartAddress);
				break;
			case LOAD_DLL_DEBUG_EVENT:
				Log("LOAD_DLL_DEBUG_EVENT:base:0x%x handle:0x%x",dbg_event.u.LoadDll.lpBaseOfDll,dbg_event.u.LoadDll.hFile);
				Load_Dll_Event(dbg_event.u.LoadDll.hFile,(DWORD)dbg_event.u.LoadDll.lpBaseOfDll);
				break;
			case OUTPUT_DEBUG_STRING_EVENT:
				Log("OUTPUT_DEBUG_STRING_EVENT");
				break;
			case RIP_EVENT:
				Log("RIP_EVENT");
				break;
			case UNLOAD_DLL_DEBUG_EVENT:
				Log("UNLOAD_DLL_DEBUG_EVENT:%x",dbg_event.u.UnloadDll.lpBaseOfDll);
				unload_dll_handler((DWORD)dbg_event.u.UnloadDll.lpBaseOfDll);
				break;
		}		
		ContinueDebugEvent(dwPid,dbg_event.dwThreadId,dwAction);
	}
	return;
}