VirtualBox

Changeset 54993 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Mar 27, 2015 3:57:07 PM (10 years ago)
Author:
vboxsync
Message:

SUPHardNt: Extended the free/replace unknown exec memory trick a little.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyProcess-win.cpp

    r54560 r54993  
    15411541
    15421542
     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 */
     1554static 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
    15431722/**
    15441723 * Scans the virtual memory of the process.
     
    16041783                         ? " *%p-%p %#06x/%#06x %#09x  %ls\n"
    16051784                         : "  %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,
    16071786                         MemInfo.AllocationProtect, MemInfo.Type, pThis->aImages[iImg].Name.UniStr.Buffer));
    16081787
     
    16781857                 */
    16791858                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);
    17491860                /*
    17501861                 * Unmap mapped memory, failing that, drop exec privileges.
     
    17541865                    SUP_DPRINTF(("supHardNtVpScanVirtualMemory: Unmapping exec mem at %p (%p/%p LB %#zx)\n",
    17551866                                 uPtrWhere, MemInfo.AllocationBase, MemInfo.BaseAddress, MemInfo.RegionSize));
    1756                     rcNt = NtUnmapViewOfSection(pThis->hProcess, MemInfo.AllocationBase);
     1867                    rcNt = NtUnmapViewOfSection(hProcess, MemInfo.AllocationBase);
    17571868                    if (!NT_SUCCESS(rcNt))
    17581869                    {
    17591870                        PVOID  pvCopy = MemInfo.BaseAddress;
    17601871                        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);
    17621873                        if (!NT_SUCCESS(rcNt2))
    1763                             rcNt2 = NtProtectVirtualMemory(pThis->hProcess, &pvCopy, &cbCopy, PAGE_READONLY, NULL);
     1874                            rcNt2 = NtProtectVirtualMemory(hProcess, &pvCopy, &cbCopy, PAGE_READONLY, NULL);
    17641875                        if (!NT_SUCCESS(rcNt2))
    17651876                            supHardNtVpSetInfo2(pThis, VERR_SUP_VP_UNMAP_AND_PROTECT_FAILED,
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette