/** * @copydoc RTNetIPv6PseudoChecksumBits */ DECLINLINE(uint32_t) rtNetIPv6PseudoChecksumBits(PCRTNETADDRIPV6 pSrcAddr, PCRTNETADDRIPV6 pDstAddr, uint8_t bProtocol, uint32_t cbPkt) { uint32_t u32Sum = pSrcAddr->au16[0] + pSrcAddr->au16[1] + pSrcAddr->au16[2] + pSrcAddr->au16[3] + pSrcAddr->au16[4] + pSrcAddr->au16[5] + pSrcAddr->au16[6] + pSrcAddr->au16[7] + pDstAddr->au16[0] + pDstAddr->au16[1] + pDstAddr->au16[2] + pDstAddr->au16[3] + pDstAddr->au16[4] + pDstAddr->au16[5] + pDstAddr->au16[6] + pDstAddr->au16[7] + RT_H2BE_U16(RT_HIWORD(cbPkt)) + RT_H2BE_U16(RT_LOWORD(cbPkt)) + 0 + RT_H2BE_U16(RT_MAKE_U16(bProtocol, 0)); return u32Sum; }
RTDECL(uint16_t) ASMByteSwapU16(uint16_t u16) { return RT_MAKE_U16(RT_HIBYTE(u16), RT_LOBYTE(u16)); }
/* Used by PutEventMultiTouch and PutEventMultiTouchString. */ HRESULT Mouse::putEventMultiTouch(LONG aCount, LONG64 *paContacts, ULONG aScanTime) { if (aCount >= 256) { return E_INVALIDARG; } DisplayMouseInterface *pDisplay = mParent->getDisplayMouseInterface(); ComAssertRet(pDisplay, E_FAIL); HRESULT rc = S_OK; uint64_t* pau64Contacts = NULL; uint8_t cContacts = 0; /* Deliver 0 contacts too, touch device may use this to reset the state. */ if (aCount > 0) { /* Create a copy with converted coords. */ pau64Contacts = (uint64_t *)RTMemTmpAlloc(aCount * sizeof(uint64_t)); if (pau64Contacts) { int32_t x1, y1, x2, y2; /* Takes the display lock */ pDisplay->getFramebufferDimensions(&x1, &y1, &x2, &y2); LONG i; for (i = 0; i < aCount; i++) { uint32_t u32Lo = RT_LO_U32(paContacts[i]); uint32_t u32Hi = RT_HI_U32(paContacts[i]); int32_t x = (int16_t)u32Lo; int32_t y = (int16_t)(u32Lo >> 16); uint8_t contactId = RT_BYTE1(u32Hi); bool fInContact = (RT_BYTE2(u32Hi) & 0x1) != 0; bool fInRange = (RT_BYTE2(u32Hi) & 0x2) != 0; LogRel3(("%s: [%d] %d,%d id %d, inContact %d, inRange %d\n", __FUNCTION__, i, x, y, contactId, fInContact, fInRange)); /* Framebuffer dimensions are 0,0 width, height, that is x2,y2 are exclusive, * while coords are inclusive. */ int32_t xAdj = x1 < x2 ? ((x - 1 - x1) * VMMDEV_MOUSE_RANGE) / (x2 - x1) : 0; int32_t yAdj = y1 < y2 ? ((y - 1 - y1) * VMMDEV_MOUSE_RANGE) / (y2 - y1) : 0; bool fValid = ( xAdj >= VMMDEV_MOUSE_RANGE_MIN && xAdj <= VMMDEV_MOUSE_RANGE_MAX && yAdj >= VMMDEV_MOUSE_RANGE_MIN && yAdj <= VMMDEV_MOUSE_RANGE_MAX); if (fValid) { uint8_t fu8 = (fInContact? 0x01: 0x00) | (fInRange? 0x02: 0x00); pau64Contacts[cContacts] = RT_MAKE_U64_FROM_U16((uint16_t)xAdj, (uint16_t)yAdj, RT_MAKE_U16(contactId, fu8), 0); cContacts++; } } } else {
/* Used by PutEventMultiTouch and PutEventMultiTouchString. */ HRESULT Mouse::putEventMultiTouch(LONG aCount, LONG64 *paContacts, ULONG aScanTime) { if (aCount >= 256) { return E_INVALIDARG; } DisplayMouseInterface *pDisplay = mParent->getDisplayMouseInterface(); ComAssertRet(pDisplay, E_FAIL); /* Touch events are mapped to the primary monitor, because the emulated USB * touchscreen device is associated with one (normally the primary) screen in the guest. */ ULONG uScreenId = 0; ULONG cWidth = 0; ULONG cHeight = 0; LONG xOrigin = 0; LONG yOrigin = 0; HRESULT rc = pDisplay->getScreenResolution(uScreenId, &cWidth, &cHeight, NULL, &xOrigin, &yOrigin); ComAssertComRCRetRC(rc); uint64_t* pau64Contacts = NULL; uint8_t cContacts = 0; /* Deliver 0 contacts too, touch device may use this to reset the state. */ if (aCount > 0) { /* Create a copy with converted coords. */ pau64Contacts = (uint64_t *)RTMemTmpAlloc(aCount * sizeof(uint64_t)); if (pau64Contacts) { int32_t x1 = xOrigin; int32_t y1 = yOrigin; int32_t x2 = x1 + cWidth; int32_t y2 = y1 + cHeight; LogRel3(("%s: screen [%d] %d,%d %d,%d\n", __FUNCTION__, uScreenId, x1, y1, x2, y2)); LONG i; for (i = 0; i < aCount; i++) { uint32_t u32Lo = RT_LO_U32(paContacts[i]); uint32_t u32Hi = RT_HI_U32(paContacts[i]); int32_t x = (int16_t)u32Lo; int32_t y = (int16_t)(u32Lo >> 16); uint8_t contactId = RT_BYTE1(u32Hi); bool fInContact = (RT_BYTE2(u32Hi) & 0x1) != 0; bool fInRange = (RT_BYTE2(u32Hi) & 0x2) != 0; LogRel3(("%s: [%d] %d,%d id %d, inContact %d, inRange %d\n", __FUNCTION__, i, x, y, contactId, fInContact, fInRange)); /* x1,y1 are inclusive and x2,y2 are exclusive, * while x,y start from 1 and are inclusive. */ if (x <= x1 || x > x2 || y <= y1 || y > y2) { /* Out of range. Skip the contact. */ continue; } int32_t xAdj = x1 < x2? ((x - 1 - x1) * VMMDEV_MOUSE_RANGE) / (x2 - x1) : 0; int32_t yAdj = y1 < y2? ((y - 1 - y1) * VMMDEV_MOUSE_RANGE) / (y2 - y1) : 0; bool fValid = ( xAdj >= VMMDEV_MOUSE_RANGE_MIN && xAdj <= VMMDEV_MOUSE_RANGE_MAX && yAdj >= VMMDEV_MOUSE_RANGE_MIN && yAdj <= VMMDEV_MOUSE_RANGE_MAX); if (fValid) { uint8_t fu8 = (fInContact? 0x01: 0x00) | (fInRange? 0x02: 0x00); pau64Contacts[cContacts] = RT_MAKE_U64_FROM_U16((uint16_t)xAdj, (uint16_t)yAdj, RT_MAKE_U16(contactId, fu8), 0); cContacts++; } } } else {
/** * Initalizes the triple fault / boot hack. * * Always call vmmR0TripleFaultHackTerm to clean up, even when this call fails. * * @returns VBox status code. */ int vmmR0TripleFaultHackInit(void) { /* * Map the first page. */ int rc = RTR0MemObjEnterPhys(&g_hMemPage0, 0, PAGE_SIZE, RTMEM_CACHE_POLICY_DONT_CARE); AssertRCReturn(rc, rc); rc = RTR0MemObjMapKernel(&g_hMapPage0, g_hMemPage0, (void *)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE); AssertRCReturn(rc, rc); g_pbPage0 = (uint8_t *)RTR0MemObjAddress(g_hMapPage0); LogRel(("0040:0067 = %04x:%04x\n", RT_MAKE_U16(g_pbPage0[0x467+2], g_pbPage0[0x467+3]), RT_MAKE_U16(g_pbPage0[0x467+0], g_pbPage0[0x467+1]) )); /* * Allocate some "low core" memory. If that fails, just grab some memory. */ //rc = RTR0MemObjAllocPhys(&g_hMemLowCore, PAGE_SIZE, _1M - 1); //__debugbreak(); rc = RTR0MemObjEnterPhys(&g_hMemLowCore, 0x7000, PAGE_SIZE, RTMEM_CACHE_POLICY_DONT_CARE); AssertRCReturn(rc, rc); rc = RTR0MemObjMapKernel(&g_hMapLowCore, g_hMemLowCore, (void *)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE); AssertRCReturn(rc, rc); g_pbLowCore = (uint8_t *)RTR0MemObjAddress(g_hMapLowCore); g_HCPhysLowCore = RTR0MemObjGetPagePhysAddr(g_hMapLowCore, 0); LogRel(("Low core at %RHp mapped at %p\n", g_HCPhysLowCore, g_pbLowCore)); /* * Save memory we'll be overwriting. */ g_pvSavedLowCore = RTMemAlloc(PAGE_SIZE); AssertReturn(g_pvSavedLowCore, VERR_NO_MEMORY); memcpy(g_pvSavedLowCore, g_pbLowCore, PAGE_SIZE); g_u32SavedVector = RT_MAKE_U32_FROM_U8(g_pbPage0[0x467], g_pbPage0[0x467+1], g_pbPage0[0x467+2], g_pbPage0[0x467+3]); g_u16SavedCadIndicator = RT_MAKE_U16(g_pbPage0[0x472], g_pbPage0[0x472+1]); /* * Install the code. */ size_t cbCode = (uintptr_t)&vmmR0TripleFaultHackEnd - (uintptr_t)&vmmR0TripleFaultHackStart; AssertLogRelReturn(cbCode <= PAGE_SIZE, VERR_OUT_OF_RANGE); memcpy(g_pbLowCore, &vmmR0TripleFaultHackStart, cbCode); g_pbPage0[0x467+0] = 0x00; g_pbPage0[0x467+1] = 0x70; g_pbPage0[0x467+2] = 0x00; g_pbPage0[0x467+3] = 0x00; g_pbPage0[0x472+0] = 0x34; g_pbPage0[0x472+1] = 0x12; /* * Configure the status port and cmos shutdown command. */ uint32_t fSaved = ASMIntDisableFlags(); ASMOutU8(0x70, 0x0f); ASMOutU8(0x71, 0x0a); ASMOutU8(0x70, 0x05); ASMInU8(0x71); ASMReloadCR3(); ASMWriteBackAndInvalidateCaches(); ASMSetFlags(fSaved); #if 1 /* For testing & debugging. */ vmmR0TripleFaultHackTripleFault(); #endif return VINF_SUCCESS; }
static void supR3HardenedDirectSyscall(PSUPHNTIMPDLL pDll, PCSUPHNTIMPFUNC pImport, PCSUPHNTIMPSYSCALL pSyscall, PSUPHNTLDRCACHEENTRY pLdrEntry, uint8_t *pbBits, bool fReportErrors) { /* * Skip non-syscall entries. */ if (!pSyscall->puApiNo) return; /* * Locate the virgin bits. */ RTLDRADDR uValue; int rc = RTLdrGetSymbolEx(pLdrEntry->hLdrMod, pbBits, (uintptr_t)pDll->pbImageBase, UINT32_MAX, pImport->pszName, &uValue); if (RT_FAILURE(rc)) { SUPHNTIMP_ERROR(fReportErrors, 16, "supR3HardenedDirectSyscall", kSupInitOp_Misc, rc, "%s: RTLdrGetSymbolEx failed on %s: %Rrc", pDll->pszName, pImport->pszName, rc); return; } uintptr_t offSymbol = (uintptr_t)uValue - (uintptr_t)pDll->pbImageBase; uint8_t const *pbFunction = &pbBits[offSymbol]; /* * Parse the code and extract the API call number. */ #ifdef RT_ARCH_AMD64 /* Pattern #1: XP64/W2K3-64 thru Windows 8.1 0:000> u ntdll!NtCreateSection ntdll!NtCreateSection: 00000000`779f1750 4c8bd1 mov r10,rcx 00000000`779f1753 b847000000 mov eax,47h 00000000`779f1758 0f05 syscall 00000000`779f175a c3 ret 00000000`779f175b 0f1f440000 nop dword ptr [rax+rax] */ if ( pbFunction[ 0] == 0x4c /* mov r10, rcx */ && pbFunction[ 1] == 0x8b && pbFunction[ 2] == 0xd1 && pbFunction[ 3] == 0xb8 /* mov eax, 0000yyzzh */ //&& pbFunction[ 4] == 0xZZ //&& pbFunction[ 5] == 0xYY && pbFunction[ 6] == 0x00 && pbFunction[ 7] == 0x00 && pbFunction[ 8] == 0x0f /* syscall */ && pbFunction[ 9] == 0x05 && pbFunction[10] == 0xc3 /* ret */ ) { *pSyscall->puApiNo = RT_MAKE_U16(pbFunction[4], pbFunction[5]); *pImport->ppfnImport = pSyscall->pfnType1; return; } #else /* Pattern #1: XP thru Windows 7 kd> u ntdll!NtCreateSection ntdll!NtCreateSection: 7c90d160 b832000000 mov eax,32h 7c90d165 ba0003fe7f mov edx,offset SharedUserData!SystemCallStub (7ffe0300) 7c90d16a ff12 call dword ptr [edx] 7c90d16c c21c00 ret 1Ch 7c90d16f 90 nop The variable bit is the value loaded into eax: XP=32h, W2K3=34h, Vista=4bh, W7=54h Pattern #2: Windows 8.1 0:000:x86> u ntdll_6a0f0000!NtCreateSection ntdll_6a0f0000!NtCreateSection: 6a15eabc b854010000 mov eax,154h 6a15eac1 e803000000 call ntdll_6a0f0000!NtCreateSection+0xd (6a15eac9) 6a15eac6 c21c00 ret 1Ch 6a15eac9 8bd4 mov edx,esp 6a15eacb 0f34 sysenter 6a15eacd c3 ret The variable bit is the value loaded into eax: W81=154h Note! One nice thing here is that we can share code pattern #1. */ if ( pbFunction[ 0] == 0xb8 /* mov eax, 0000yyzzh*/ //&& pbFunction[ 1] <= 0xZZ //&& pbFunction[ 2] <= 0xYY && pbFunction[ 3] == 0x00 && pbFunction[ 4] == 0x00) { *pSyscall->puApiNo = RT_MAKE_U16(pbFunction[1], pbFunction[2]); if ( pbFunction[5] == 0xba /* mov edx, offset SharedUserData!SystemCallStub */ && pbFunction[ 6] == 0x00 && pbFunction[ 7] == 0x03 && pbFunction[ 8] == 0xfe && pbFunction[ 9] == 0x7f && pbFunction[10] == 0xff /* call [edx] */ && pbFunction[11] == 0x12 && ( ( pbFunction[12] == 0xc2 /* ret 1ch */ && pbFunction[13] == pSyscall->cbParams && pbFunction[14] == 0x00) || ( pbFunction[12] == 0xc3 /* ret */ && pSyscall->cbParams == 0) ) ) { *pImport->ppfnImport = pSyscall->pfnType1; return; } if ( pbFunction[ 5] == 0xe8 /* call [$+3] */ && RT_ABS(*(int32_t *)&pbFunction[6]) < 0x10 && ( ( pbFunction[10] == 0xc2 /* ret 1ch */ && pbFunction[11] == pSyscall->cbParams && pbFunction[12] == 0x00) || ( pbFunction[10] == 0xc3 /* ret */ && pSyscall->cbParams == 0) ) ) { *pImport->ppfnImport = pSyscall->pfnType2; return; } } #endif /* * Failed to parse it. */ volatile uint8_t abCopy[16]; memcpy((void *)&abCopy[0], pbFunction, sizeof(abCopy)); SUPHNTIMP_ERROR(fReportErrors, 17, "supR3HardenedWinInitImports", kSupInitOp_Misc, rc, "%ls: supHardNtLdrCacheOpen failed: '%s': %.16Rhxs", pDll->pwszName, pImport->pszName, &abCopy[0]); }
RTDECL(int) RTZipGzipDecompressIoStream(RTVFSIOSTREAM hVfsIosIn, uint32_t fFlags, PRTVFSIOSTREAM phVfsIosOut) { AssertPtrReturn(hVfsIosIn, VERR_INVALID_HANDLE); AssertReturn(!(fFlags & ~RTZIPGZIPDECOMP_F_ALLOW_ZLIB_HDR), VERR_INVALID_PARAMETER); AssertPtrReturn(phVfsIosOut, VERR_INVALID_POINTER); uint32_t cRefs = RTVfsIoStrmRetain(hVfsIosIn); AssertReturn(cRefs != UINT32_MAX, VERR_INVALID_HANDLE); /* * Create the decompression I/O stream. */ RTVFSIOSTREAM hVfsIos; PRTZIPGZIPSTREAM pThis; int rc = RTVfsNewIoStream(&g_rtZipGzipOps, sizeof(RTZIPGZIPSTREAM), RTFILE_O_READ, NIL_RTVFS, NIL_RTVFSLOCK, &hVfsIos, (void **)&pThis); if (RT_SUCCESS(rc)) { pThis->hVfsIos = hVfsIosIn; pThis->offStream = 0; pThis->fDecompress = true; pThis->SgSeg.pvSeg = &pThis->abBuffer[0]; pThis->SgSeg.cbSeg = sizeof(pThis->abBuffer); RTSgBufInit(&pThis->SgBuf, &pThis->SgSeg, 1); memset(&pThis->Zlib, 0, sizeof(pThis->Zlib)); pThis->Zlib.opaque = pThis; rc = inflateInit2(&pThis->Zlib, MAX_WBITS | RT_BIT(5) /* autodetect gzip header */); if (rc >= 0) { /* * Read the gzip header from the input stream to check that it's * a gzip stream as specified by the user. * * Note! Since we've told zlib to check for the gzip header, we * prebuffer what we read in the input buffer so it can * be handed on to zlib later on. */ rc = RTVfsIoStrmRead(pThis->hVfsIos, pThis->abBuffer, sizeof(RTZIPGZIPHDR), true /*fBlocking*/, NULL /*pcbRead*/); if (RT_SUCCESS(rc)) { /* Validate the header and make a copy of it. */ PCRTZIPGZIPHDR pHdr = (PCRTZIPGZIPHDR)pThis->abBuffer; if ( pHdr->bId1 == RTZIPGZIPHDR_ID1 && pHdr->bId2 == RTZIPGZIPHDR_ID2 && !(pHdr->fFlags & ~RTZIPGZIPHDR_FLG_VALID_MASK)) { if (pHdr->bCompressionMethod == RTZIPGZIPHDR_CM_DEFLATE) rc = VINF_SUCCESS; else rc = VERR_ZIP_UNSUPPORTED_METHOD; } else if ( (fFlags & RTZIPGZIPDECOMP_F_ALLOW_ZLIB_HDR) && (RT_MAKE_U16(pHdr->bId2, pHdr->bId1) % 31) == 0 && (pHdr->bId1 & 0xf) == RTZIPGZIPHDR_CM_DEFLATE ) { pHdr = NULL; rc = VINF_SUCCESS; } else rc = VERR_ZIP_BAD_HEADER; if (RT_SUCCESS(rc)) { pThis->Zlib.avail_in = sizeof(RTZIPGZIPHDR); pThis->Zlib.next_in = &pThis->abBuffer[0]; if (pHdr) { pThis->Hdr = *pHdr; /* Parse on if there are names or comments. */ if (pHdr->fFlags & (RTZIPGZIPHDR_FLG_NAME | RTZIPGZIPHDR_FLG_COMMENT)) { /** @todo Can implement this when someone needs the * name or comment for something useful. */ } } if (RT_SUCCESS(rc)) { *phVfsIosOut = hVfsIos; return VINF_SUCCESS; } } } } else rc = rtZipGzipConvertErrFromZlib(pThis, rc); /** @todo cleaning up in this situation is going to go wrong. */ RTVfsIoStrmRelease(hVfsIos); } else RTVfsIoStrmRelease(hVfsIosIn); return rc; }