Beispiel #1
2
pid_t fork(void)
{
 NTSTATUS nErrCode;
 CONTEXT ctxThreadContext;
 HANDLE hProcess;
 HANDLE hThread;
 INITIAL_TEB itInitialTeb;
 CLIENT_ID ciClientId;
 MEMORY_BASIC_INFORMATION mbiStackInfo;
 THREAD_BASIC_INFORMATION tbiThreadInfo;

 struct __tagcsrmsg{
  PORT_MESSAGE PortMessage;
  struct CSRSS_MESSAGE CsrssMessage;
  PROCESS_INFORMATION ProcessInformation;
  CLIENT_ID Debugger;
  ULONG CreationFlags;
  ULONG VdmInfo[2];
 } csrmsg;

 /* STEP 1: Duplicate current process */ 
 nErrCode = NtCreateProcess
 (
  &hProcess,
  PROCESS_ALL_ACCESS,
  NULL,
  NtCurrentProcess(),
  TRUE,
  0,
  0,
  0
 );

 /* failure */
 if(!NT_SUCCESS(nErrCode))
 {
  ERR("NtCreateProcess() failed with status 0x%08X\n", nErrCode);
  goto fail;
 }

 /* STEP 2: Duplicate current thread */
 /* 2.1: duplicate registers */
 ctxThreadContext.ContextFlags =
  CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS | CONTEXT_FLOATING_POINT;
 
 /* get the current thread's registers */
 nErrCode = NtGetContextThread(NtCurrentThread(), &ctxThreadContext);
 
 /* failure */
 if(!NT_SUCCESS(nErrCode))
 {
  ERR("NtGetContextThread() failed with status 0x%08X\n", nErrCode);
  goto cleanup_and_fail;
 }

 /* redirect the child process to the child_branch label (see 4.3 below) */
 ctxThreadContext.Eip = (ULONG)&&child_branch;
 
 /* 2.2: duplicate stack */
 /* get stack base and size */
 nErrCode = NtQueryVirtualMemory
 (
  NtCurrentProcess(),
  (PVOID)ctxThreadContext.Esp,
  MemoryBasicInformation,
  &mbiStackInfo,
  sizeof(mbiStackInfo),
  0
 );
 
 /* failure */
 if(!NT_SUCCESS(nErrCode))
 {
  ERR("NtQueryVirtualMemory() failed with status 0x%08X\n", nErrCode);
  goto cleanup_and_fail;
 }
 
 itInitialTeb.StackCommit = 0;
 itInitialTeb.StackReserve = 0;
 itInitialTeb.StackBase = (PVOID)((ULONG)(mbiStackInfo.BaseAddress) + mbiStackInfo.RegionSize);
 itInitialTeb.StackLimit = mbiStackInfo.BaseAddress;
 itInitialTeb.StackAllocate = mbiStackInfo.AllocationBase;
 
 /* 2.3: create duplicate thread */
 nErrCode = NtCreateThread
 (
  &hThread,
  THREAD_ALL_ACCESS,
  NULL,
  hProcess,
  (CLIENT_ID *)&ciClientId,
  &ctxThreadContext,
  &itInitialTeb,
  TRUE
 );
 
 /* failure */
 if(!NT_SUCCESS(nErrCode))
 {
  ERR("NtCreateThread() failed with status 0x%08X\n", nErrCode);
  goto cleanup_and_fail;
 }

 /* 2.4: duplicate the TEB */
 /* store the client id in the child thread's stack (see 4.3b) */
 nErrCode = NtWriteVirtualMemory
 (
  hProcess,
  &ciClientId,
  &ciClientId,
  sizeof(ciClientId),
  0
 );
 
 /* failure */
 if(!NT_SUCCESS(nErrCode))
 {
  ERR("NtWriteVirtualMemory() failed with status 0x%08X\n", nErrCode);
  goto cleanup_and_fail;
 }
 
 /* get the child thread's TEB base */
 nErrCode = NtQueryInformationThread
 (
  hThread,
  ThreadBasicInformation,
  &tbiThreadInfo,
  sizeof(tbiThreadInfo),
  0
 );
 
 /* failure */
 if(!NT_SUCCESS(nErrCode))
 {
  ERR("NtQueryInformationThread() failed with status 0x%08X\n", nErrCode);
  goto cleanup_and_fail;
 }
 
 /* copy the TEB */ 
 nErrCode = NtWriteVirtualMemory
 (
  hProcess,
  tbiThreadInfo.TebBaseAddress,
  NtCurrentTeb(),
  sizeof(TEB),
  0
 );
 
 /* failure */
 if(!NT_SUCCESS(nErrCode))
 {
  ERR("NtWriteVirtualMemory() failed with status 0x%08X\n", nErrCode);
  goto cleanup_and_fail;
 }
 
 /* STEP 3: Call Win32 subsystem */
 memset(&csrmsg, 0, sizeof(csrmsg));

 csrmsg.ProcessInformation.hProcess = hProcess;
 csrmsg.ProcessInformation.hThread = hThread;
 csrmsg.ProcessInformation.dwProcessId = (DWORD)ciClientId.UniqueProcess;
 csrmsg.ProcessInformation.dwThreadId = (DWORD)ciClientId.UniqueThread;

 nErrCode = CsrClientCallServer(&csrmsg, 0, 0x10000, 0x24);

 /* failure */
 if(!NT_SUCCESS(nErrCode))
 {
  ERR("CsrClientCallServer() failed with status 0x%08X\n", nErrCode);
  goto cleanup_and_fail;
 }
 
 /* STEP 4: Finalization */
 /* 4.1: resume thread */
 nErrCode = NtResumeThread(hThread, 0);
 
 /* 4.2: close superfluous handles */
 NtClose(hProcess);
 NtClose(hThread);
 
 /* 4.3: (parent) return the child process id */
 return ((pid_t)(ciClientId.UniqueProcess));

 /* 4.3b: (child) cleanup and return 0 */
child_branch:
 /* restore the thread and process id in the TEB */ 
 memcpy(&NtCurrentTeb()->Cid, &ciClientId, sizeof(ciClientId));
 
 /* return 0 */
 return (0);

cleanup_and_fail:
 NtTerminateProcess(hProcess, nErrCode);

fail:
 errno = __status_to_errno(nErrCode);
 return (-1);
 
}
	LPVOID GetProcAddr(HANDLE hProc)
	{
		AcquireLock();
		DWORD pid,addr,len;
		if (hProc==NtCurrentProcess()) pid=current_process_id;
		else
		{
			PROCESS_BASIC_INFORMATION info;
			NtQueryInformationProcess(hProc,ProcessBasicInformation,&info,sizeof(info),&len);
			pid=info.uUniqueProcessId;
		}
		pid>>=2;
		for (UINT_PTR i=0;i<count;i++)
		{
			if ((proc_record[i]&0xFFF)==pid)
			{
				addr=proc_record[i]&~0xFFF;
				ReleaseLock();
				return (LPVOID)addr;
			}
		}
		len=0x1000;
		NtAllocateVirtualMemory(hProc,(PVOID*)(proc_record+count),0,&len,
			MEM_COMMIT,PAGE_EXECUTE_READWRITE);
		DWORD base = proc_record[count];
		proc_record[count] |= pid;
		union
		{
			LPVOID buffer;
			DWORD b;
		};
		b = base;
		LPVOID fun_table[3];
		*(DWORD*)(normal_routine + ADDR0) += base;
		NtWriteVirtualMemory(hProc, buffer, normal_routine, 0x14, 0);
		*(DWORD*)(normal_routine + ADDR0) -= base;
		b += 0x14;
		fun_table[0] = NtTerminateThread;
		fun_table[1] = NtQueryVirtualMemory;
		fun_table[2] = MessageBoxW;
		NtWriteVirtualMemory(hProc, buffer, fun_table, 0xC, 0);
		b += 0xC;
		*(DWORD*)(except_routine + ADDR1) += base;
		*(DWORD*)(except_routine + ADDR2) += base;
		*(DWORD*)(except_routine + ADDR3) += base;
		NtWriteVirtualMemory(hProc, buffer, except_routine, 0xE0, 0);
		*(DWORD*)(except_routine + ADDR1) -= base;
		*(DWORD*)(except_routine + ADDR2) -= base;
		*(DWORD*)(except_routine + ADDR3) -= base;
		count++;
		ReleaseLock();
		return (LPVOID)base;
	}
DWORD Inject(HANDLE hProc, LPWSTR engine)
{
	LPVOID lpvAllocAddr = 0;
	DWORD dwWrite = 0x1000, len = 0;
	HANDLE hTH;
	WCHAR path[MAX_PATH];
	LPWSTR p;
	if (!IthCheckFile(DllName)) return -1;
	p = GetMainModulePath();
	len = wcslen(p);
	memcpy(path, p, len << 1);
	memset(path + len, 0, (MAX_PATH - len) << 1);
	for (p = path + len; *p != L'\\'; p--); //Always a \ after drive letter.
	p++;
	wcscpy(p, DllName);

	NtAllocateVirtualMemory(hProc, &lpvAllocAddr, 0, &dwWrite, MEM_COMMIT, PAGE_READWRITE);
	if (lpvAllocAddr == 0) return -1;

	CheckThreadStart();

	//Copy module path into address space of target process.
	NtWriteVirtualMemory(hProc, lpvAllocAddr, path, MAX_PATH << 1, &dwWrite);

	hTH = IthCreateThread(LoadLibrary, (DWORD)lpvAllocAddr, hProc);
	if (hTH == 0 || hTH == INVALID_HANDLE_VALUE)
	{
		ConsoleOutput(ErrorRemoteThread);
		return -1;
	}
	NtWaitForSingleObject(hTH, 0, 0);

	THREAD_BASIC_INFORMATION info;
	NtQueryInformationThread(hTH, ThreadBasicInformation, &info, sizeof(info), &dwWrite);
	NtClose(hTH);
	if (info.ExitStatus != 0)
	{
		wcscpy(p, engine);
		NtWriteVirtualMemory(hProc, lpvAllocAddr, path, MAX_PATH << 1, &dwWrite);
		hTH = IthCreateThread(LoadLibrary, (DWORD)lpvAllocAddr, hProc);
		if (hTH == 0 || hTH == INVALID_HANDLE_VALUE)
		{
			ConsoleOutput(ErrorRemoteThread);
			return -1;
		}
		NtWaitForSingleObject(hTH, 0, 0);
		NtClose(hTH);
	}

	dwWrite = 0;
	NtFreeVirtualMemory(hProc, &lpvAllocAddr, &dwWrite, MEM_RELEASE);
	return info.ExitStatus;
}
Beispiel #4
0
BOOL engine_SaveRemoteVar(HANDLE hProcess,LPVOID lpDest,LPVOID lpSrc)
{
	if (NT_SUCCESS(NtWriteVirtualMemory(hProcess,lpDest,lpSrc,sizeof(LPVOID),NULL)))
		return TRUE;

	return FALSE;
}
Beispiel #5
0
int exec_fork(HANDLE process)
{
	NTSTATUS status;
	status = NtWriteVirtualMemory(process, &startup, &startup, sizeof(startup), NULL);
	if (!NT_SUCCESS(status))
	{
		log_error("exec_fork(): NtWriteVirtualMemory() failed, status: %x", status);
		return 0;
	}
	return 1;
}
Beispiel #6
0
BOOL engine_UnHookFunctionInProcess(HANDLE hProcess,LPSTR lpModuleName,LPSTR lpFunctionName,LPVOID lpOldFunctionAddress,DWORD dwFunctionSize)
{
	LPVOID lpModule=NULL;
	LPVOID lpFunction=NULL;
	MEMORY_BASIC_INFORMATION mbi;
	CHAR   lpLocalStub[MAX_FUNC_LEN*2];
	DWORD  dwFree=0;
	DWORD  dwBytesWritten;
	
	// Get module address
	lpModule=(LPVOID)engine_GetRemoteModuleHandle(hProcess,lpModuleName);
	if (!lpModule)
		return FALSE;
		
	// Get function address
	lpFunction=engine_GetRemoteProcAddress(hProcess,lpModule,lpFunctionName);
	if (!lpFunction)
		return FALSE;

	// Get info about the function address
	if (!NT_SUCCESS(SafeNtQueryVirtualMemory(hProcess,lpFunction,MemoryBasicInformation,&mbi,sizeof(mbi),NULL)))
		return FALSE;

	// Flush instruction cache
	NtFlushInstructionCache(hProcess,mbi.BaseAddress,mbi.RegionSize);

	// Change the protection for the region
	if (!NT_SUCCESS(NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,PAGE_EXECUTE_READWRITE,&mbi.Protect)))
		return FALSE;

	// Read old functions instructions
	if (!NT_SUCCESS(SafeNtReadVirtualMemory(hProcess,lpOldFunctionAddress,lpLocalStub,dwFunctionSize,NULL)))
	{
		// restore protection
		NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL);
		return FALSE;
	}

	// Restore original function
	if (!NT_SUCCESS(NtWriteVirtualMemory(hProcess,lpFunction,lpLocalStub,dwFunctionSize,&dwBytesWritten)))
	{
		// restore protection
		NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL);
		return FALSE;
	}

	// Free stub memory
	NtFreeVirtualMemory(hProcess,&lpOldFunctionAddress,&dwFree,MEM_RELEASE);

	// Restore protection
	NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL);

	return TRUE;
}
Beispiel #7
0
// copy pe image on lpbase from current process to dwpid on the same address
BOOL engine_CopyImageToProcess(HANDLE hProcess,LPVOID lpBase)
{
	DWORD dwSize,dwFree=0;
	LPVOID lpNew=lpBase;
	
	// get PE size
	dwSize=engine_GetPEImageSize(lpBase);

	if (!NT_SUCCESS(NtAllocateVirtualMemory(hProcess,&lpNew,0,&dwSize,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE)))
		return FALSE;

	if (!NT_SUCCESS(NtWriteVirtualMemory(hProcess,lpNew,lpBase,dwSize,NULL)))
	{
		NtFreeVirtualMemory(hProcess,&lpNew,&dwFree,MEM_RELEASE);
		return FALSE;
	}

	return TRUE;
}
Beispiel #8
0
NTSTATUS
LsapGetLogonSessionData(IN OUT PLSA_API_MSG RequestMsg)
{
    OBJECT_ATTRIBUTES ObjectAttributes;
    HANDLE ProcessHandle = NULL;
    PLSAP_LOGON_SESSION Session;
    PSECURITY_LOGON_SESSION_DATA LocalSessionData;
    PVOID ClientBaseAddress = NULL;
    ULONG Length, MemSize;
    LPWSTR Ptr;
    NTSTATUS Status;

    TRACE("LsapGetLogonSessionData(%p)\n", RequestMsg);

    TRACE("LogonId: %lx\n", RequestMsg->GetLogonSessionData.Request.LogonId.LowPart);
    Session = LsapGetLogonSession(&RequestMsg->GetLogonSessionData.Request.LogonId);
    if (Session == NULL)
        return STATUS_NO_SUCH_LOGON_SESSION;

    Length = sizeof(SECURITY_LOGON_SESSION_DATA);
/*
             Session->UserName.MaximumLength +
             Session->LogonDomain.MaximumLength +
             Session->AuthenticationPackage.MaximumLength +
             Session->LogonServer.MaximumLength +
             Session->DnsDomainName.MaximumLength +
             Session->Upn.MaximumLength;

    if (Session->Sid != NULL)
        RtlLengthSid(Session->Sid);
*/

    TRACE("Length: %lu\n", Length);

    LocalSessionData = RtlAllocateHeap(RtlGetProcessHeap(),
                                       HEAP_ZERO_MEMORY,
                                       Length);
    if (LocalSessionData == NULL)
        return STATUS_INSUFFICIENT_RESOURCES;

    Ptr = (LPWSTR)((ULONG_PTR)LocalSessionData + sizeof(SECURITY_LOGON_SESSION_DATA));
    TRACE("LocalSessionData: %p  Ptr: %p\n", LocalSessionData, Ptr);

    LocalSessionData->Size = sizeof(SECURITY_LOGON_SESSION_DATA);

    RtlCopyLuid(&LocalSessionData->LogonId,
                &RequestMsg->GetLogonSessionData.Request.LogonId);

    InitializeObjectAttributes(&ObjectAttributes,
                               NULL,
                               0,
                               NULL,
                               NULL);

    Status = NtOpenProcess(&ProcessHandle,
                           PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION,
                           &ObjectAttributes,
                           &RequestMsg->h.ClientId);
    if (!NT_SUCCESS(Status))
    {
        TRACE("NtOpenProcess() failed (Status %lx)\n", Status);
        goto done;
    }

    MemSize = Length;
    Status = NtAllocateVirtualMemory(ProcessHandle,
                                     &ClientBaseAddress,
                                     0,
                                     &MemSize,
                                     MEM_COMMIT,
                                     PAGE_READWRITE);
    if (!NT_SUCCESS(Status))
    {
        TRACE("NtAllocateVirtualMemory() failed (Status %lx)\n", Status);
        goto done;
    }

    TRACE("MemSize: %lu\n", MemSize);
    TRACE("ClientBaseAddress: %p\n", ClientBaseAddress);

    Status = NtWriteVirtualMemory(ProcessHandle,
                                  ClientBaseAddress,
                                  LocalSessionData,
                                  Length,
                                  NULL);
    if (!NT_SUCCESS(Status))
    {
        TRACE("NtWriteVirtualMemory() failed (Status %lx)\n", Status);
        goto done;
    }

    RequestMsg->GetLogonSessionData.Reply.SessionDataBuffer = ClientBaseAddress;

done:
    if (ProcessHandle != NULL)
        NtClose(ProcessHandle);

    if (LocalSessionData != NULL)
        RtlFreeHeap(RtlGetProcessHeap(), 0, LocalSessionData);

    return Status;
}
Beispiel #9
0
NTSTATUS
LsapEnumLogonSessions(IN OUT PLSA_API_MSG RequestMsg)
{
    OBJECT_ATTRIBUTES ObjectAttributes;
    HANDLE ProcessHandle = NULL;
    PLIST_ENTRY SessionEntry;
    PLSAP_LOGON_SESSION CurrentSession;
    PLUID SessionList;
    ULONG i, Length, MemSize;
    PVOID ClientBaseAddress = NULL;
    NTSTATUS Status;

    TRACE("LsapEnumLogonSessions(%p)\n", RequestMsg);

    Length = SessionCount * sizeof(LUID);
    SessionList = RtlAllocateHeap(RtlGetProcessHeap(),
                                  HEAP_ZERO_MEMORY,
                                  Length);
    if (SessionList == NULL)
        return STATUS_INSUFFICIENT_RESOURCES;

    i = 0;
    SessionEntry = SessionListHead.Flink;
    while (SessionEntry != &SessionListHead)
    {
        CurrentSession = CONTAINING_RECORD(SessionEntry,
                                           LSAP_LOGON_SESSION,
                                           Entry);

        RtlCopyLuid(&SessionList[i],
                    &CurrentSession->LogonId);

        SessionEntry = SessionEntry->Flink;
        i++;
    }

    InitializeObjectAttributes(&ObjectAttributes,
                               NULL,
                               0,
                               NULL,
                               NULL);

    Status = NtOpenProcess(&ProcessHandle,
                           PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION,
                           &ObjectAttributes,
                           &RequestMsg->h.ClientId);
    if (!NT_SUCCESS(Status))
    {
        TRACE("NtOpenProcess() failed (Status %lx)\n", Status);
        goto done;
    }

    TRACE("Length: %lu\n", Length);

    MemSize = Length;
    Status = NtAllocateVirtualMemory(ProcessHandle,
                                     &ClientBaseAddress,
                                     0,
                                     &MemSize,
                                     MEM_COMMIT,
                                     PAGE_READWRITE);
    if (!NT_SUCCESS(Status))
    {
        TRACE("NtAllocateVirtualMemory() failed (Status %lx)\n", Status);
        goto done;
    }

    TRACE("MemSize: %lu\n", MemSize);
    TRACE("ClientBaseAddress: %p\n", ClientBaseAddress);

    Status = NtWriteVirtualMemory(ProcessHandle,
                                  ClientBaseAddress,
                                  SessionList,
                                  Length,
                                  NULL);
    if (!NT_SUCCESS(Status))
    {
        TRACE("NtWriteVirtualMemory() failed (Status %lx)\n", Status);
        goto done;
    }

    RequestMsg->EnumLogonSessions.Reply.LogonSessionCount = SessionCount;
    RequestMsg->EnumLogonSessions.Reply.LogonSessionBuffer = ClientBaseAddress;

done:
    if (ProcessHandle != NULL)
        NtClose(ProcessHandle);

    if (SessionList != NULL)
        RtlFreeHeap(RtlGetProcessHeap(), 0, SessionList);

    return Status;
}
INT_PTR CALLBACK PhpMemoryEditorDlgProc(
    _In_ HWND hwndDlg,
    _In_ UINT uMsg,
    _In_ WPARAM wParam,
    _In_ LPARAM lParam
    )
{
    PMEMORY_EDITOR_CONTEXT context;

    if (uMsg != WM_INITDIALOG)
    {
        context = GetProp(hwndDlg, PhMakeContextAtom());
    }
    else
    {
        context = (PMEMORY_EDITOR_CONTEXT)lParam;
        SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context);
    }

    if (!context)
        return FALSE;

    switch (uMsg)
    {
    case WM_INITDIALOG:
        {
            NTSTATUS status;

            SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)PH_LOAD_SHARED_ICON_SMALL(PhInstanceHandle, MAKEINTRESOURCE(IDI_PROCESSHACKER)));
            SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)PH_LOAD_SHARED_ICON_LARGE(PhInstanceHandle, MAKEINTRESOURCE(IDI_PROCESSHACKER)));

            if (context->Title)
            {
                SetWindowText(hwndDlg, context->Title->Buffer);
            }
            else
            {
                PPH_PROCESS_ITEM processItem;

                if (processItem = PhReferenceProcessItem(context->ProcessId))
                {
                    SetWindowText(hwndDlg, PhaFormatString(L"%s (%u) (0x%Ix - 0x%Ix)",
                        processItem->ProcessName->Buffer, HandleToUlong(context->ProcessId),
                        context->BaseAddress, (ULONG_PTR)context->BaseAddress + context->RegionSize)->Buffer);
                    PhDereferenceObject(processItem);
                }
            }

            PhInitializeLayoutManager(&context->LayoutManager, hwndDlg);

            if (context->RegionSize > 1024 * 1024 * 1024) // 1 GB
            {
                PhShowError(context->OwnerHandle, L"Unable to edit the memory region because it is too large.");
                return TRUE;
            }

            if (!NT_SUCCESS(status = PhOpenProcess(
                &context->ProcessHandle,
                PROCESS_VM_READ,
                context->ProcessId
                )))
            {
                PhShowStatus(context->OwnerHandle, L"Unable to open the process", status, 0);
                return TRUE;
            }

            context->Buffer = PhAllocatePage(context->RegionSize, NULL);

            if (!context->Buffer)
            {
                PhShowError(context->OwnerHandle, L"Unable to allocate memory for the buffer.");
                return TRUE;
            }

            if (!NT_SUCCESS(status = NtReadVirtualMemory(
                context->ProcessHandle,
                context->BaseAddress,
                context->Buffer,
                context->RegionSize,
                NULL
                )))
            {
                PhShowStatus(context->OwnerHandle, L"Unable to read memory", status, 0);
                return TRUE;
            }

            PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDOK), NULL,
                PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM);
            PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_SAVE), NULL,
                PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM);
            PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_BYTESPERROW), NULL,
                PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
            PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_GOTO), NULL,
                PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
            PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_WRITE), NULL,
                PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
            PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_REREAD), NULL,
                PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);

            if (MinimumSize.left == -1)
            {
                RECT rect;

                rect.left = 0;
                rect.top = 0;
                rect.right = 290;
                rect.bottom = 140;
                MapDialogRect(hwndDlg, &rect);
                MinimumSize = rect;
                MinimumSize.left = 0;
            }

            context->HexEditHandle = GetDlgItem(hwndDlg, IDC_MEMORY);
            PhAddLayoutItem(&context->LayoutManager, context->HexEditHandle, NULL, PH_ANCHOR_ALL);
            HexEdit_SetBuffer(context->HexEditHandle, context->Buffer, (ULONG)context->RegionSize);

            {
                PH_RECTANGLE windowRectangle;

                windowRectangle.Position = PhGetIntegerPairSetting(L"MemEditPosition");
                windowRectangle.Size = PhGetScalableIntegerPairSetting(L"MemEditSize", TRUE).Pair;
                PhAdjustRectangleToWorkingArea(NULL, &windowRectangle);

                MoveWindow(hwndDlg, windowRectangle.Left, windowRectangle.Top,
                    windowRectangle.Width, windowRectangle.Height, FALSE);

                // Implement cascading by saving an offsetted rectangle.
                windowRectangle.Left += 20;
                windowRectangle.Top += 20;

                PhSetIntegerPairSetting(L"MemEditPosition", windowRectangle.Position);
                PhSetScalableIntegerPairSetting2(L"MemEditSize", windowRectangle.Size);
            }

            {
                PWSTR bytesPerRowStrings[7];
                ULONG i;
                ULONG bytesPerRow;

                for (i = 0; i < sizeof(bytesPerRowStrings) / sizeof(PWSTR); i++)
                    bytesPerRowStrings[i] = PhaFormatString(L"%u bytes per row", 1 << (2 + i))->Buffer;

                PhAddComboBoxStrings(GetDlgItem(hwndDlg, IDC_BYTESPERROW),
                    bytesPerRowStrings, sizeof(bytesPerRowStrings) / sizeof(PWSTR));

                bytesPerRow = PhGetIntegerSetting(L"MemEditBytesPerRow");

                if (bytesPerRow >= 4)
                {
                    HexEdit_SetBytesPerRow(context->HexEditHandle, bytesPerRow);
                    PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_BYTESPERROW),
                        PhaFormatString(L"%u bytes per row", bytesPerRow)->Buffer, FALSE);
                }
            }

            context->LoadCompleted = TRUE;
        }
        break;
    case WM_DESTROY:
        {
            if (context->LoadCompleted)
            {
                PhSaveWindowPlacementToSetting(L"MemEditPosition", L"MemEditSize", hwndDlg);
                PhRemoveElementAvlTree(&PhMemoryEditorSet, &context->Links);
                PhUnregisterDialog(hwndDlg);
            }

            RemoveProp(hwndDlg, PhMakeContextAtom());

            PhDeleteLayoutManager(&context->LayoutManager);

            if (context->Buffer) PhFreePage(context->Buffer);
            if (context->ProcessHandle) NtClose(context->ProcessHandle);
            PhClearReference(&context->Title);

            if ((context->Flags & PH_MEMORY_EDITOR_UNMAP_VIEW_OF_SECTION) && context->ProcessId == NtCurrentProcessId())
                NtUnmapViewOfSection(NtCurrentProcess(), context->BaseAddress);

            PhFree(context);
        }
        break;
    case WM_SHOWWINDOW:
        {
            SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)context->HexEditHandle, TRUE);
        }
        break;
    case WM_COMMAND:
        {
            switch (GET_WM_COMMAND_ID(wParam, lParam))
            {
            case IDCANCEL:
            case IDOK:
                DestroyWindow(hwndDlg);
                break;
            case IDC_SAVE:
                {
                    static PH_FILETYPE_FILTER filters[] =
                    {
                        { L"Binary files (*.bin)", L"*.bin" },
                        { L"All files (*.*)", L"*.*" }
                    };
                    PVOID fileDialog;
                    PPH_PROCESS_ITEM processItem;

                    fileDialog = PhCreateSaveFileDialog();

                    PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER));

                    if (!context->Title && (processItem = PhReferenceProcessItem(context->ProcessId)))
                    {
                        PhSetFileDialogFileName(fileDialog,
                            PhaFormatString(L"%s_0x%Ix-0x%Ix.bin", processItem->ProcessName->Buffer,
                            context->BaseAddress, context->RegionSize)->Buffer);
                        PhDereferenceObject(processItem);
                    }
                    else
                    {
                        PhSetFileDialogFileName(fileDialog, L"Memory.bin");
                    }

                    if (PhShowFileDialog(hwndDlg, fileDialog))
                    {
                        NTSTATUS status;
                        PPH_STRING fileName;
                        PPH_FILE_STREAM fileStream;

                        fileName = PH_AUTO(PhGetFileDialogFileName(fileDialog));

                        if (NT_SUCCESS(status = PhCreateFileStream(
                            &fileStream,
                            fileName->Buffer,
                            FILE_GENERIC_WRITE,
                            FILE_SHARE_READ,
                            FILE_OVERWRITE_IF,
                            0
                            )))
                        {
                            status = PhWriteFileStream(fileStream, context->Buffer, (ULONG)context->RegionSize);
                            PhDereferenceObject(fileStream);
                        }

                        if (!NT_SUCCESS(status))
                            PhShowStatus(hwndDlg, L"Unable to create the file", status, 0);
                    }

                    PhFreeFileDialog(fileDialog);
                }
                break;
            case IDC_GOTO:
                {
                    PPH_STRING selectedChoice = NULL;

                    while (PhaChoiceDialog(
                        hwndDlg,
                        L"Go to Offset",
                        L"Enter an offset:",
                        NULL,
                        0,
                        NULL,
                        PH_CHOICE_DIALOG_USER_CHOICE,
                        &selectedChoice,
                        NULL,
                        L"MemEditGotoChoices"
                        ))
                    {
                        ULONG64 offset;

                        if (selectedChoice->Length == 0)
                            continue;

                        if (PhStringToInteger64(&selectedChoice->sr, 0, &offset))
                        {
                            if (offset >= context->RegionSize)
                            {
                                PhShowError(hwndDlg, L"The offset is too large.");
                                continue;
                            }

                            SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)context->HexEditHandle, TRUE);
                            HexEdit_SetSel(context->HexEditHandle, (LONG)offset, (LONG)offset);
                            break;
                        }
                    }
                }
                break;
            case IDC_WRITE:
                {
                    NTSTATUS status;

                    if (!context->WriteAccess)
                    {
                        HANDLE processHandle;

                        if (!NT_SUCCESS(status = PhOpenProcess(
                            &processHandle,
                            PROCESS_VM_READ | PROCESS_VM_WRITE,
                            context->ProcessId
                            )))
                        {
                            PhShowStatus(hwndDlg, L"Unable to open the process", status, 0);
                            break;
                        }

                        if (context->ProcessHandle) NtClose(context->ProcessHandle);
                        context->ProcessHandle = processHandle;
                        context->WriteAccess = TRUE;
                    }

                    if (!NT_SUCCESS(status = NtWriteVirtualMemory(
                        context->ProcessHandle,
                        context->BaseAddress,
                        context->Buffer,
                        context->RegionSize,
                        NULL
                        )))
                    {
                        PhShowStatus(hwndDlg, L"Unable to write memory", status, 0);
                    }
                }
                break;
            case IDC_REREAD:
                {
                    NTSTATUS status;

                    if (!NT_SUCCESS(status = NtReadVirtualMemory(
                        context->ProcessHandle,
                        context->BaseAddress,
                        context->Buffer,
                        context->RegionSize,
                        NULL
                        )))
                    {
                        PhShowStatus(hwndDlg, L"Unable to read memory", status, 0);
                    }

                    InvalidateRect(context->HexEditHandle, NULL, TRUE);
                }
                break;
            case IDC_BYTESPERROW:
                if (HIWORD(wParam) == CBN_SELCHANGE)
                {
                    PPH_STRING bytesPerRowString = PhaGetDlgItemText(hwndDlg, IDC_BYTESPERROW);
                    PH_STRINGREF firstPart;
                    PH_STRINGREF secondPart;
                    ULONG64 bytesPerRow64;

                    if (PhSplitStringRefAtChar(&bytesPerRowString->sr, ' ', &firstPart, &secondPart))
                    {
                        if (PhStringToInteger64(&firstPart, 10, &bytesPerRow64))
                        {
                            PhSetIntegerSetting(L"MemEditBytesPerRow", (ULONG)bytesPerRow64);
                            HexEdit_SetBytesPerRow(context->HexEditHandle, (ULONG)bytesPerRow64);
                            SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)context->HexEditHandle, TRUE);
                        }
                    }
                }
                break;
            }
        }
        break;
    case WM_SIZE:
        {
            PhLayoutManagerLayout(&context->LayoutManager);
        }
        break;
    case WM_SIZING:
        {
            PhResizingMinimumSize((PRECT)lParam, wParam, MinimumSize.right, MinimumSize.bottom);
        }
        break;
    case WM_PH_SELECT_OFFSET:
        {
            HexEdit_SetEditMode(context->HexEditHandle, EDIT_ASCII);
            HexEdit_SetSel(context->HexEditHandle, (ULONG)wParam, (ULONG)wParam + (ULONG)lParam);
        }
        break;
    }

    return FALSE;
}
Beispiel #11
0
LPVOID engine_HookFunctionInProcess(HANDLE hProcess,LPSTR lpModuleName,LPSTR lpFunctionName,LPVOID lpHookFunctionAddress,PDWORD pdwHookFunctionSize,LPVOID* lpFunctionAddress,INT iRndJmp)
{
	LPVOID lpModule=NULL;
	LPVOID lpFunction=NULL;
	MEMORY_BASIC_INFORMATION mbi;
	CHAR  lpTmpFunction[MAX_FUNC_LEN*2];
	CHAR  lpLocalStub[MAX_FUNC_LEN*3];
	CHAR  lpLocalFunc[MAX_FUNC_LEN*3];
	DWORD dwBytesRead;
	DWORD dwReadLen=0;
	DWORD dwExistingJMP=0;
	DWORD dwStubSize;
	DWORD dwFree=0;
	DWORD dwBytesWritten;
	DWORD dwOldProtect;

	LPVOID lpRemoteStub=NULL;
	INT   iFuncLen;
	PBYTE pReadAddress;
	NTSTATUS ntStatus;

	// Get module address
	lpModule=(LPVOID)engine_GetRemoteModuleHandle(hProcess,lpModuleName);
	if (!lpModule)
		return NULL;
		
	// Get function address
	lpFunction=engine_GetRemoteProcAddress(hProcess,lpModule,lpFunctionName);
	if (!lpFunction)
		return NULL;

	// Get info about the function address
	if (!NT_SUCCESS(SafeNtQueryVirtualMemory(hProcess,lpFunction,MemoryBasicInformation,&mbi,sizeof(mbi),NULL)))
		return NULL;

	// Flush instruction cache
	NtFlushInstructionCache(hProcess,mbi.BaseAddress,mbi.RegionSize);

	// Change the protection for the region
	if (!NT_SUCCESS(NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,PAGE_EXECUTE_READWRITE,&mbi.Protect)))
		return NULL;

	// Fill stub buffer with nops
	RtlFillMemory(lpLocalStub,MAX_FUNC_LEN*3,NOP);

	// Read MAX_FUNC_LEN instruction(s) from the function into our function buffer
	if (!NT_SUCCESS(SafeNtReadVirtualMemory(hProcess,lpFunction,lpTmpFunction,MAX_FUNC_LEN*2,&dwBytesRead)))
	{
		NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL);
		return NULL;
	}

	pReadAddress=(PBYTE)lpTmpFunction;

	// check if first opcode in the function is a another jump
	if (*pReadAddress==LONG_JMP_OPCODE)
	{
		// get relative address
		memcpy(&dwExistingJMP,pReadAddress+1,4);
		// get absolute address
		dwExistingJMP=(DWORD)lpFunction+dwExistingJMP;
		// readlen
		dwReadLen=jtJmpTable[RELATIVE_JMP].iCodeSize

		engine_BuildJMPBuffer((CHAR*)lpLocalStub,((DWORD)lpRemoteStub+dwReadLen)-dwExistingJMP,RELATIVE_JMP);

		NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL);
		return NULL;
	}

	// Get the length of the first instruction(s)
	// This part is done by Z0MBiE's LDE32 v1.05
	iFuncLen=disasm_main(pReadAddress); // get first instruction length
	while (iFuncLen!=-1 && dwReadLen<(DWORD)jtJmpTable[iRndJmp].iCodeSize)
	{
		dwReadLen+=iFuncLen;
		pReadAddress+=iFuncLen;
		iFuncLen=disasm_main(pReadAddress); // next instruction length
	}

	// API code is too short or too long too hook this way (for now ;))
	if (dwReadLen<(DWORD)jtJmpTable[iRndJmp].iCodeSize||dwReadLen>MAX_FUNC_LEN*2)
	{
		NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL);
		return NULL;
	}

	// Read the first instruction(s) from the function into our stub buffer
	if (!NT_SUCCESS(SafeNtReadVirtualMemory(hProcess,lpFunction,lpLocalStub,dwReadLen,&dwBytesRead)))
	{	
		NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL);
		return NULL;
	}

	// Allocate space with read/write access for our "stub"
	// note: always use a relative jump for our stub -> RELATIVE_JMP

	dwStubSize=dwReadLen+jtJmpTable[RELATIVE_JMP].iCodeSize;
	if (!NT_SUCCESS(NtAllocateVirtualMemory(hProcess,&lpRemoteStub,0,&dwStubSize,MEM_COMMIT|MEM_TOP_DOWN,PAGE_READWRITE)))
	{	
		NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL);
		return NULL;
	}

	// Check
	if (dwStubSize<dwReadLen+jtJmpTable[RELATIVE_JMP].iCodeSize)
	{
		NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL);
		
		// Free allocated buffer
		NtFreeVirtualMemory(hProcess,&lpRemoteStub,&dwFree,MEM_RELEASE);
		return NULL;
	}

	engine_BuildJMPBuffer((CHAR*)lpLocalStub+dwReadLen,jtJmpTable[RELATIVE_JMP].jcStub((DWORD)lpFunction+dwReadLen,(DWORD)lpRemoteStub,dwReadLen+jtJmpTable[RELATIVE_JMP].iCodeSize),RELATIVE_JMP);

	// Copy the "stub" buffer to process memory
	if (!NT_SUCCESS(NtWriteVirtualMemory(hProcess,lpRemoteStub,lpLocalStub,dwReadLen+jtJmpTable[RELATIVE_JMP].iCodeSize,&dwBytesWritten)))
	{
		NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL);
		
		// Free allocated buffer
		NtFreeVirtualMemory(hProcess,&lpRemoteStub,&dwFree,MEM_RELEASE);
		return NULL;
	}

	// Check
	if (dwBytesWritten<dwReadLen+jtJmpTable[RELATIVE_JMP].iCodeSize)
	{
		NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL);
		
		// Free allocated buffer
		NtFreeVirtualMemory(hProcess,&lpRemoteStub,&dwFree,MEM_RELEASE);
		return NULL;
	}
	
	// change access
	if (!NT_SUCCESS(NtProtectVirtualMemory(hProcess,&lpRemoteStub,&dwStubSize,PAGE_EXECUTE_READ,&dwOldProtect)))
	{
		NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL);
		
		// Free allocated buffer
		NtFreeVirtualMemory(hProcess,&lpRemoteStub,&dwFree,MEM_RELEASE);
		return NULL;
	}
		
	// Fill it with NOP
	RtlFillMemory(lpLocalFunc,MAX_FUNC_LEN*3,NOP);

	// Prepare jmpcode
	engine_BuildJMPBuffer((CHAR*)lpLocalFunc,jtJmpTable[iRndJmp].jcFunc((DWORD)lpHookFunctionAddress,(DWORD)lpFunction,(DWORD)jtJmpTable[iRndJmp].iCodeSize),iRndJmp);
	
	ntStatus=NtWriteVirtualMemory(hProcess,lpFunction,lpLocalFunc,dwReadLen,&dwBytesWritten);
		
	// Check that we really wrote our jmpcode completely
	if (!NT_SUCCESS(ntStatus) || dwBytesWritten!=dwReadLen)
	{
		// Try to fix stuff
		if (dwBytesWritten)
			NtWriteVirtualMemory(hProcess,lpFunction,lpRemoteStub,dwBytesWritten,&dwBytesWritten);

		NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL);
		
		// Free allocated buffer
		NtFreeVirtualMemory(hProcess,&lpRemoteStub,&dwFree,MEM_RELEASE);
		return NULL;
	}
	
	// Restore protection
	NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL);

	// Save size of read function length
	if (pdwHookFunctionSize) *pdwHookFunctionSize=dwReadLen;
	// Save address of function
	if (lpFunctionAddress) *lpFunctionAddress=lpFunction;

	return lpRemoteStub;
}