Changeset 54993 in vbox for trunk/src/VBox
- Timestamp:
- Mar 27, 2015 3:57:07 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyProcess-win.cpp
r54560 r54993 1541 1541 1542 1542 1543 #ifdef IN_RING3 1544 /** 1545 * Frees (or replaces) executable memory of allocation type private. 1546 * 1547 * @returns VBox status code. 1548 * @param pThis The process scanning state structure. Details 1549 * about images are added to this. 1550 * @param hProcess The process to verify. 1551 * @param pMemInfo The information we've got on this private 1552 * executable memory. 1553 */ 1554 static void supHardNtVpFreeOrReplacePrivateExecMemory(PSUPHNTVPSTATE pThis, HANDLE hProcess, 1555 MEMORY_BASIC_INFORMATION const *pMemInfo) 1556 { 1557 NTSTATUS rcNt; 1558 1559 /* 1560 * Try figure if the entire allocation size. Free/Alloc may fail otherwise. 1561 */ 1562 PVOID pvFree = pMemInfo->AllocationBase; 1563 SIZE_T cbFree = pMemInfo->RegionSize + ((uintptr_t)pMemInfo->BaseAddress - (uintptr_t)pMemInfo->AllocationBase); 1564 for (;;) 1565 { 1566 SIZE_T cbActual = 0; 1567 MEMORY_BASIC_INFORMATION MemInfo2 = { 0, 0, 0, 0, 0, 0, 0 }; 1568 uintptr_t uPtrNext = (uintptr_t)pvFree + cbFree; 1569 rcNt = g_pfnNtQueryVirtualMemory(hProcess, 1570 (void const *)uPtrNext, 1571 MemoryBasicInformation, 1572 &MemInfo2, 1573 sizeof(MemInfo2), 1574 &cbActual); 1575 if (!NT_SUCCESS(rcNt)) 1576 break; 1577 if (pMemInfo->AllocationBase != MemInfo2.AllocationBase) 1578 break; 1579 } 1580 SUP_DPRINTF(("supHardNtVpFreeOrReplacePrivateExecMemory: %s exec mem at %p (LB %#zx, %p LB %#zx)\n", 1581 pThis->fFlags & SUPHARDNTVP_F_EXEC_ALLOC_REPLACE_WITH_RW ? "Replacing" : "Freeing", 1582 pvFree, cbFree, pMemInfo->BaseAddress, pMemInfo->RegionSize)); 1583 1584 /* 1585 * In the BSOD workaround mode, we need to make a copy of the memory before 1586 * freeing it. 1587 */ 1588 uintptr_t uCopySrc = (uintptr_t)pvFree; 1589 size_t cbCopy = 0; 1590 void *pvCopy = NULL; 1591 if (pThis->fFlags & SUPHARDNTVP_F_EXEC_ALLOC_REPLACE_WITH_RW) 1592 { 1593 cbCopy = cbFree; 1594 pvCopy = RTMemAllocZ(cbCopy); 1595 if (!pvCopy) 1596 { 1597 supHardNtVpSetInfo2(pThis, VERR_SUP_VP_REPLACE_VIRTUAL_MEMORY_FAILED, "RTMemAllocZ(%#zx) failed", cbCopy); 1598 return; 1599 } 1600 1601 rcNt = supHardNtVpReadMem(hProcess, uCopySrc, pvCopy, cbCopy); 1602 if (!NT_SUCCESS(rcNt)) 1603 supHardNtVpSetInfo2(pThis, VERR_SUP_VP_REPLACE_VIRTUAL_MEMORY_FAILED, 1604 "Error reading data from original alloc: %#x (%p LB %#zx)", rcNt, uCopySrc, cbCopy, rcNt); 1605 } 1606 1607 /* 1608 * Free the memory. 1609 */ 1610 for (uint32_t i = 0; i < 10; i++) 1611 { 1612 PVOID pvFreeInOut = pvFree; 1613 SIZE_T cbFreeInOut = 0; 1614 rcNt = NtFreeVirtualMemory(hProcess, &pvFreeInOut, &cbFreeInOut, MEM_RELEASE); 1615 if (!NT_SUCCESS(rcNt)) 1616 { 1617 SUP_DPRINTF(("supHardNtVpFreeOrReplacePrivateExecMemory: Free attempt #1 failed: %#x [%p LB 0]\n", rcNt, pvFree)); 1618 pvFreeInOut = pvFree; 1619 cbFreeInOut = cbFree; 1620 rcNt = NtFreeVirtualMemory(hProcess, &pvFreeInOut, &cbFreeInOut, MEM_RELEASE); 1621 if (!NT_SUCCESS(rcNt)) 1622 { 1623 SUP_DPRINTF(("supHardNtVpFreeOrReplacePrivateExecMemory: Free attempt #2 failed: %#x [%p LB %#zx]\n", 1624 rcNt, pvFree, cbFree)); 1625 pvFreeInOut = pMemInfo->BaseAddress; 1626 cbFreeInOut = pMemInfo->RegionSize; 1627 rcNt = NtFreeVirtualMemory(hProcess, &pvFreeInOut, &cbFreeInOut, MEM_RELEASE); 1628 if (NT_SUCCESS(rcNt)) 1629 { 1630 pvFree = pMemInfo->BaseAddress; 1631 cbFree = pMemInfo->RegionSize; 1632 SUP_DPRINTF(("supHardNtVpFreeOrReplacePrivateExecMemory: Free attempt #3 succeeded [%p LB %#zx]\n", 1633 pvFree, cbFree)); 1634 } 1635 else 1636 supHardNtVpSetInfo2(pThis, VERR_SUP_VP_FREE_VIRTUAL_MEMORY_FAILED, 1637 "NtFreeVirtualMemory [%p LB %#zx and %p LB %#zx] failed: %#x", 1638 pvFree, cbFree, pMemInfo->BaseAddress, pMemInfo->RegionSize, rcNt); 1639 } 1640 } 1641 1642 /* 1643 * Query the region again, redo the free operation if there's still memory there. 1644 */ 1645 if (!NT_SUCCESS(rcNt) || (pThis->fFlags & SUPHARDNTVP_F_EXEC_ALLOC_REPLACE_WITH_RW)) 1646 break; 1647 SIZE_T cbActual = 0; 1648 MEMORY_BASIC_INFORMATION MemInfo3 = { 0, 0, 0, 0, 0, 0, 0 }; 1649 NTSTATUS rcNt2 = g_pfnNtQueryVirtualMemory(hProcess, pvFree, MemoryBasicInformation, 1650 &MemInfo3, sizeof(MemInfo3), &cbActual); 1651 if (!NT_SUCCESS(rcNt2)) 1652 break; 1653 SUP_DPRINTF(("supHardNtVpFreeOrReplacePrivateExecMemory: QVM after free %u: [%p]/%p LB %#zx s=%#x ap=%#x rp=%#p\n", 1654 i, MemInfo3.AllocationBase, MemInfo3.BaseAddress, MemInfo3.RegionSize, MemInfo3.State, 1655 MemInfo3.AllocationProtect, MemInfo3.Protect)); 1656 if (pMemInfo->State == MEM_FREE) 1657 break; 1658 SUP_DPRINTF(("supHardNtVpFreeOrReplacePrivateExecMemory: Retrying free...\n")); 1659 } 1660 1661 /* 1662 * Restore memory as non-executable - Kludge for Trend Micro sakfile.sys 1663 * and Digital Guardian dgmaster.sys BSODs. 1664 */ 1665 if (NT_SUCCESS(rcNt) && (pThis->fFlags & SUPHARDNTVP_F_EXEC_ALLOC_REPLACE_WITH_RW)) 1666 { 1667 PVOID pvAlloc = pvFree; 1668 SIZE_T cbAlloc = cbFree; 1669 rcNt = NtAllocateVirtualMemory(hProcess, &pvAlloc, 0, &cbAlloc, MEM_COMMIT, PAGE_READWRITE); 1670 if (!NT_SUCCESS(rcNt)) 1671 supHardNtVpSetInfo2(pThis, VERR_SUP_VP_REPLACE_VIRTUAL_MEMORY_FAILED, 1672 "NtAllocateVirtualMemory (%p LB %#zx) failed with rcNt=%#x allocating " 1673 "replacement memory for working around buggy protection software. " 1674 "See VBoxStartup.log for more details", 1675 pvAlloc, cbFree, rcNt); 1676 else if ( (uintptr_t)pvFree < (uintptr_t)pvAlloc 1677 || (uintptr_t)pvFree + cbFree > (uintptr_t)pvAlloc + cbFree) 1678 supHardNtVpSetInfo2(pThis, VERR_SUP_VP_REPLACE_VIRTUAL_MEMORY_FAILED, 1679 "We wanted NtAllocateVirtualMemory to get us %p LB %#zx, but it returned %p LB %#zx.", 1680 pMemInfo->BaseAddress, pMemInfo->RegionSize, pvFree, cbFree, rcNt); 1681 else 1682 { 1683 /* 1684 * Copy what we can, considering the 2nd free attempt. 1685 */ 1686 uint8_t *pbDst = (uint8_t *)pvFree; 1687 size_t cbDst = cbFree; 1688 uint8_t *pbSrc = (uint8_t *)pvCopy; 1689 size_t cbSrc = cbCopy; 1690 if ((uintptr_t)pbDst != uCopySrc) 1691 { 1692 if ((uintptr_t)pbDst > uCopySrc) 1693 { 1694 uintptr_t cbAdj = (uintptr_t)pbDst - uCopySrc; 1695 pbSrc += cbAdj; 1696 cbSrc -= cbSrc; 1697 } 1698 else 1699 { 1700 uintptr_t cbAdj = uCopySrc - (uintptr_t)pbDst; 1701 pbDst += cbAdj; 1702 cbDst -= cbAdj; 1703 } 1704 } 1705 if (cbSrc > cbDst) 1706 cbSrc = cbDst; 1707 1708 SIZE_T cbWritten; 1709 rcNt = NtWriteVirtualMemory(hProcess, pbDst, pbSrc, cbSrc, &cbWritten); 1710 if (!NT_SUCCESS(rcNt)) 1711 supHardNtVpSetInfo2(pThis, VERR_SUP_VP_FREE_VIRTUAL_MEMORY_FAILED, 1712 "NtWriteVirtualMemory (%p LB %#zx) failed: %#x", 1713 pMemInfo->BaseAddress, pMemInfo->RegionSize, rcNt); 1714 } 1715 } 1716 if (pvCopy) 1717 RTMemFree(pvCopy); 1718 } 1719 #endif /* IN_RING3 */ 1720 1721 1543 1722 /** 1544 1723 * Scans the virtual memory of the process. … … 1604 1783 ? " *%p-%p %#06x/%#06x %#09x %ls\n" 1605 1784 : " %p-%p %#06x/%#06x %#09x %ls\n", 1606 MemInfo.BaseAddress, (uintptr_t)MemInfo.BaseAddress -MemInfo.RegionSize - 1, MemInfo.Protect,1785 MemInfo.BaseAddress, (uintptr_t)MemInfo.BaseAddress + MemInfo.RegionSize - 1, MemInfo.Protect, 1607 1786 MemInfo.AllocationProtect, MemInfo.Type, pThis->aImages[iImg].Name.UniStr.Buffer)); 1608 1787 … … 1678 1857 */ 1679 1858 if (MemInfo.Type == MEM_PRIVATE) 1680 { 1681 PVOID pvFree = MemInfo.BaseAddress; 1682 SIZE_T cbFree = MemInfo.RegionSize; 1683 if (!(pThis->fFlags & SUPHARDNTVP_F_EXEC_ALLOC_REPLACE_WITH_RW)) 1684 { 1685 SUP_DPRINTF(("supHardNtVpScanVirtualMemory: Freeing exec mem at %p (%p LB %#zx)\n", 1686 uPtrWhere, MemInfo.BaseAddress, MemInfo.RegionSize)); 1687 1688 rcNt = NtFreeVirtualMemory(pThis->hProcess, &pvFree, &cbFree, MEM_RELEASE); 1689 if (!NT_SUCCESS(rcNt)) 1690 supHardNtVpSetInfo2(pThis, VERR_SUP_VP_FREE_VIRTUAL_MEMORY_FAILED, 1691 "NtFreeVirtualMemory (%p LB %#zx) failed: %#x", 1692 MemInfo.BaseAddress, MemInfo.RegionSize, rcNt); 1693 } 1694 else 1695 { 1696 /* The Trend Micro sakfile.sys and Digital Guardian dgmaster.sys BSOD kludge. */ 1697 SUP_DPRINTF(("supHardNtVpScanVirtualMemory: Replacing exec mem at %p (%p LB %#zx)\n", 1698 uPtrWhere, MemInfo.BaseAddress, MemInfo.RegionSize)); 1699 void *pvCopy = RTMemAllocZ(cbFree); 1700 if (pvCopy) 1701 { 1702 rcNt = supHardNtVpReadMem(pThis->hProcess, (uintptr_t)pvFree, pvCopy, cbFree); 1703 if (!NT_SUCCESS(rcNt)) 1704 supHardNtVpSetInfo2(pThis, VERR_SUP_VP_REPLACE_VIRTUAL_MEMORY_FAILED, 1705 "Error reading data from original alloc: %#x (%p LB %#zx)", 1706 rcNt, MemInfo.BaseAddress, MemInfo.RegionSize, rcNt); 1707 1708 rcNt = NtFreeVirtualMemory(pThis->hProcess, &pvFree, &cbFree, MEM_RELEASE); 1709 if (NT_SUCCESS(rcNt)) 1710 { 1711 pvFree = MemInfo.BaseAddress; cbFree = MemInfo.RegionSize; /* fudge */ 1712 NtFreeVirtualMemory(pThis->hProcess, &pvFree, &cbFree, MEM_RELEASE); /* fudge */ 1713 1714 pvFree = MemInfo.BaseAddress; 1715 cbFree = MemInfo.RegionSize; 1716 rcNt = NtAllocateVirtualMemory(pThis->hProcess, &pvFree, 0, &cbFree, MEM_COMMIT, PAGE_READWRITE); 1717 if (!NT_SUCCESS(rcNt)) 1718 supHardNtVpSetInfo2(pThis, VERR_SUP_VP_REPLACE_VIRTUAL_MEMORY_FAILED, 1719 "NtAllocateVirtualMemory (%p LB %#zx) failed with rcNt=%#x allocating " 1720 "replacement memory for working around buggy protection software. " 1721 "See VBoxStartup.log for more details", 1722 MemInfo.BaseAddress, MemInfo.RegionSize, rcNt); 1723 else if (pvFree != MemInfo.BaseAddress) 1724 supHardNtVpSetInfo2(pThis, VERR_SUP_VP_REPLACE_VIRTUAL_MEMORY_FAILED, 1725 "We wanted NtAllocateVirtualMemory to get us %p LB %#zx, but it returned %p LB %#zx.", 1726 MemInfo.BaseAddress, MemInfo.RegionSize, pvFree, cbFree, rcNt); 1727 else 1728 { 1729 SIZE_T cbWritten; 1730 rcNt = NtWriteVirtualMemory(pThis->hProcess, MemInfo.BaseAddress, pvCopy, MemInfo.RegionSize, 1731 &cbWritten); 1732 if (!NT_SUCCESS(rcNt)) 1733 supHardNtVpSetInfo2(pThis, VERR_SUP_VP_FREE_VIRTUAL_MEMORY_FAILED, 1734 "NtWriteVirtualMemory (%p LB %#zx) failed: %#x", 1735 MemInfo.BaseAddress, MemInfo.RegionSize, rcNt); 1736 } 1737 } 1738 else 1739 supHardNtVpSetInfo2(pThis, VERR_SUP_VP_FREE_VIRTUAL_MEMORY_FAILED, 1740 "NtFreeVirtualMemory (%p LB %#zx) failed: %#x", 1741 MemInfo.BaseAddress, MemInfo.RegionSize, rcNt); 1742 RTMemFree(pvCopy); 1743 } 1744 else 1745 supHardNtVpSetInfo2(pThis, VERR_SUP_VP_FREE_VIRTUAL_MEMORY_FAILED, 1746 "RTMemAllocZ(%#zx) failed", MemInfo.RegionSize); 1747 } 1748 } 1859 supHardNtVpFreeOrReplacePrivateExecMemory(pThis, hProcess, &MemInfo); 1749 1860 /* 1750 1861 * Unmap mapped memory, failing that, drop exec privileges. … … 1754 1865 SUP_DPRINTF(("supHardNtVpScanVirtualMemory: Unmapping exec mem at %p (%p/%p LB %#zx)\n", 1755 1866 uPtrWhere, MemInfo.AllocationBase, MemInfo.BaseAddress, MemInfo.RegionSize)); 1756 rcNt = NtUnmapViewOfSection( pThis->hProcess, MemInfo.AllocationBase);1867 rcNt = NtUnmapViewOfSection(hProcess, MemInfo.AllocationBase); 1757 1868 if (!NT_SUCCESS(rcNt)) 1758 1869 { 1759 1870 PVOID pvCopy = MemInfo.BaseAddress; 1760 1871 SIZE_T cbCopy = MemInfo.RegionSize; 1761 NTSTATUS rcNt2 = NtProtectVirtualMemory( pThis->hProcess, &pvCopy, &cbCopy, PAGE_NOACCESS, NULL);1872 NTSTATUS rcNt2 = NtProtectVirtualMemory(hProcess, &pvCopy, &cbCopy, PAGE_NOACCESS, NULL); 1762 1873 if (!NT_SUCCESS(rcNt2)) 1763 rcNt2 = NtProtectVirtualMemory( pThis->hProcess, &pvCopy, &cbCopy, PAGE_READONLY, NULL);1874 rcNt2 = NtProtectVirtualMemory(hProcess, &pvCopy, &cbCopy, PAGE_READONLY, NULL); 1764 1875 if (!NT_SUCCESS(rcNt2)) 1765 1876 supHardNtVpSetInfo2(pThis, VERR_SUP_VP_UNMAP_AND_PROTECT_FAILED,
Note:
See TracChangeset
for help on using the changeset viewer.