/* * Process per-sector "fixups" that NTFS uses to detect corruption of * multi-sector data structures, like MFT records. */ static int ntfs_fixup( char *buf, size_t len, u_int32_t magic, u_int32_t bytesPerSector) { struct fixuphdr *fhp = (struct fixuphdr *) buf; int i; u_int16_t fixup; u_int16_t *fxp; u_int16_t *cfxp; u_int32_t fixup_magic; u_int16_t fixup_count; u_int16_t fixup_offset; fixup_magic = OSReadLittleInt32(&fhp->fh_magic,0); if (fixup_magic != magic) { error("ntfs_fixup: magic doesn't match: %08x != %08x\n", fixup_magic, magic); return (ERROR); } fixup_count = OSReadLittleInt16(&fhp->fh_fnum,0); if ((fixup_count - 1) * bytesPerSector != len) { error("ntfs_fixup: " \ "bad fixups number: %d for %ld bytes block\n", fixup_count, (long)len); /* XXX printf kludge */ return (ERROR); } fixup_offset = OSReadLittleInt16(&fhp->fh_foff,0); if (fixup_offset >= len) { error("ntfs_fixup: invalid offset: %x", fixup_offset); return (ERROR); } fxp = (u_int16_t *) (buf + fixup_offset); cfxp = (u_int16_t *) (buf + bytesPerSector - 2); fixup = *fxp++; for (i = 1; i < fixup_count; i++, fxp++) { if (*cfxp != fixup) { error("ntfs_fixup: fixup %d doesn't match\n", i); return (ERROR); } *cfxp = *fxp; cfxp = (u_int16_t *)(((caddr_t)cfxp) + bytesPerSector); } return (0); }
/* * Find a resident attribute of a given type. Returns a pointer to the * attribute data, and its size in bytes. */ static int ntfs_find_attr( char *buf, u_int32_t attrType, void **attrData, size_t *attrSize) { struct filerec *filerec; struct attr *attr; u_int16_t offset; filerec = (struct filerec *) buf; offset = OSReadLittleInt16(&filerec->fr_attroff,0); attr = (struct attr *) (buf + offset); /*ее Should we also check offset < buffer size? */ while (attr->a_hdr.a_type != 0xFFFFFFFF) /* same for big/little endian */ { if (OSReadLittleInt32(&attr->a_hdr.a_type,0) == attrType) { if (attr->a_hdr.a_flag != 0) { //verbose("NTFS: attriubte 0x%X is non-resident\n", attrType); return 1; } *attrSize = OSReadLittleInt16(&attr->a_r.a_datalen,0); *attrData = buf + offset + OSReadLittleInt16(&attr->a_r.a_dataoff,0); return 0; /* found it! */ } /* Skip to the next attribute */ offset += OSReadLittleInt32(&attr->a_hdr.reclen,0); attr = (struct attr *) (buf + offset); } return 1; /* No matching attrType found */ }
static uint64_t ReadMMIO(uint64_t phys, uint8_t length){ uint64_t value = 0; //uint32_t *ioaddr; IOMemoryDescriptor* io_desc; IOMemoryMap* io_map; uint64_t page_offset = phys & PAGE_MASK; log_addr((uint64_t) page_offset, 64, "page_offset"); xlate_pa_va(phys, &io_desc, &io_map); if(io_map) { log_addr(io_map->getVirtualAddress(), 64, "io_map->getVirtualAddress"); switch (length) { case 1: value = *(volatile uint8_t *)((uintptr_t)(io_map->getVirtualAddress()) + page_offset); break; case 2: value = OSReadLittleInt16((void *)io_map->getVirtualAddress(), page_offset); break; case 4: value = OSReadLittleInt32((void *)io_map->getVirtualAddress(), page_offset); break; case 8: value = OSReadLittleInt64((void *)io_map->getVirtualAddress(), page_offset); default: pmem_error("ReadMMIO Incorrect read length"); break; } // DEBUG //ioaddr = (uint32_t *) (io_map->getVirtualAddress() + page_offset); //log_addr((uint64_t)ioaddr, 64, "ioaddr"); } unxlate_pa_va(&io_desc, &io_map); return value; }
/* * Parse/validate a security buffer. Verifies that supplied offset/length don't go * past end of avaialble data. Returns ptr to actual data and its length. Returns * NTLM_ERR_PARSE_ERR on bogus values. */ OSStatus ntlmParseSecBuffer( const unsigned char *cp, /* start of security buffer */ const unsigned char *bufStart, /* start of whole msg buffer */ unsigned bufLen, /* # of valid bytes starting at bufStart */ const unsigned char **data, /* RETURNED, start of actual data */ uint16_t *dataLen) /* RETURNED, length of actual data */ { assert(cp >= bufStart); uint16_t secBufLen = OSReadLittleInt16(cp, 0); /* skip length we just parsed plus alloc size, which we don't use */ cp += 4; uint32_t offset = OSReadLittleInt32(cp, 0); if((offset + secBufLen) > bufLen) { dprintf("ntlmParseSecBuffer: buf overflow\n"); return NTLM_ERR_PARSE_ERR; } *data = bufStart + offset; *dataLen = secBufLen; return errSecSuccess; }
/* * Examine a volume to see if we recognize it as a mountable. */ void NTFSGetDescription(CICell ih, char *str, long strMaxLen) { struct bootfile *boot; unsigned bytesPerSector; unsigned sectorsPerCluster; int mftRecordSize; u_int64_t totalClusters; u_int64_t cluster, mftCluster; size_t mftOffset; void *nameAttr; size_t nameSize; char *buf; buf = (char *)malloc(MAX_CLUSTER_SIZE); if (buf == 0) { goto error; } /* * Read the boot sector, check signatures, and do some minimal * sanity checking. NOTE: the size of the read below is intended * to be a multiple of all supported block sizes, so we don't * have to determine or change the device's block size. */ Seek(ih, 0); Read(ih, (long)buf, MAX_BLOCK_SIZE); boot = (struct bootfile *) buf; /* * The first three bytes are an Intel x86 jump instruction. I assume it * can be the same forms as DOS FAT: * 0xE9 0x?? 0x?? * 0xEC 0x?? 0x90 * where 0x?? means any byte value is OK. */ if (boot->reserved1[0] != 0xE9 && (boot->reserved1[0] != 0xEB || boot->reserved1[2] != 0x90)) { goto error; } /* * Check the "NTFS " signature. */ if (memcmp((const char *)boot->bf_sysid, "NTFS ", 8) != 0) { goto error; } /* * Make sure the bytes per sector and sectors per cluster are * powers of two, and within reasonable ranges. */ bytesPerSector = OSReadLittleInt16(&boot->bf_bps,0); if ((bytesPerSector & (bytesPerSector-1)) || bytesPerSector < 512 || bytesPerSector > 32768) { //verbose("NTFS: invalid bytes per sector (%d)\n", bytesPerSector); goto error; } sectorsPerCluster = boot->bf_spc; /* Just one byte; no swapping needed */ if ((sectorsPerCluster & (sectorsPerCluster-1)) || sectorsPerCluster > 128) { //verbose("NTFS: invalid sectors per cluster (%d)\n", bytesPerSector); goto error; } /* * Calculate the number of clusters from the number of sectors. * Then bounds check the $MFT and $MFTMirr clusters. */ totalClusters = OSReadLittleInt64(&boot->bf_spv,0) / sectorsPerCluster; mftCluster = OSReadLittleInt64(&boot->bf_mftcn,0); if (mftCluster > totalClusters) { ////verbose("NTFS: invalid $MFT cluster (%lld)\n", mftCluster); goto error; } cluster = OSReadLittleInt64(&boot->bf_mftmirrcn,0); if (cluster > totalClusters) { //verbose("NTFS: invalid $MFTMirr cluster (%lld)\n", cluster); goto error; } /* * Determine the size of an MFT record. */ mftRecordSize = (int8_t) boot->bf_mftrecsz; if (mftRecordSize < 0) mftRecordSize = 1 << -mftRecordSize; else mftRecordSize *= bytesPerSector * sectorsPerCluster; //verbose("NTFS: MFT record size = %d\n", mftRecordSize); /* * Read the MFT record for $Volume. This assumes the first four * file records in the MFT are contiguous; if they aren't, we * would have to map the $MFT itself. * * This will fail if the device sector size is larger than the * MFT record size, since the $Volume record won't be aligned * on a sector boundary. */ mftOffset = mftCluster * sectorsPerCluster * bytesPerSector; mftOffset += mftRecordSize * NTFS_VOLUMEINO; Seek(ih, mftOffset); Read(ih, (long)buf, mftRecordSize); #if UNUSED if (lseek(fd, mftOffset, SEEK_SET) == -1) { //verbose("NTFS: lseek to $Volume failed: %s\n", strerror(errno)); goto error; } if (read(fd, buf, mftRecordSize) != mftRecordSize) { //verbose("NTFS: error reading MFT $Volume record: %s\n", strerror(errno)); goto error; }
bool EX2Probe (const void *buf) { return (OSReadLittleInt16(buf+0x438,0)==0xEF53); }
NTSTATUS SMBRawTransaction( SMBHANDLE inConnection, const void *lpInBuffer, size_t nInBufferSize, void *lpOutBuffer, size_t nOutBufferSize, size_t *lpBytesRead) { NTSTATUS status; int err; void * hContext; struct smb_header header; mbuf_t words = NULL; mbuf_t bytes = NULL; mbuf_t response = NULL; size_t len; const void * ptr; bzero(&header, sizeof(header)); status = SMBServerContext(inConnection, &hContext); if (!NT_SUCCESS(status)) { return status; } if ((size_t)nInBufferSize < sizeof(struct smb_header) || (size_t)nOutBufferSize < sizeof(struct smb_header)) { err = STATUS_BUFFER_TOO_SMALL; goto errout; } /* Split the request buffer into the header, the parameter words and the * data bytes. */ ptr = lpInBuffer; ADVANCE(ptr, sizeof(uint32_t)); header.command = *(uint8_t *)ptr; if ((size_t)nInBufferSize < (sizeof(struct smb_header) + sizeof(uint8_t))) { err = STATUS_BUFFER_TOO_SMALL; goto errout; } ptr = lpInBuffer; ADVANCE(ptr, sizeof(struct smb_header)); len = (*(uint8_t *)ptr) * sizeof(uint16_t); ADVANCE(ptr, sizeof(uint8_t)); /* skip word_count field */ if (mbuf_attachcluster(MBUF_WAITOK, MBUF_TYPE_DATA, &words, (void *)ptr, NULL, len, NULL)) { err = STATUS_NO_MEMORY; goto errout; } mbuf_setlen(words, len); ADVANCE(ptr, len); /* skip parameter words */ if ((uintptr_t)ptr > ((uintptr_t)lpInBuffer + nInBufferSize) || (uintptr_t)ptr < (uintptr_t)mbuf_data(words)) { err = STATUS_MARSHALL_OVERFLOW; goto errout; } len = OSReadLittleInt16(ptr, 0); ADVANCE(ptr, sizeof(uint16_t)); /* skip byte_count field */ if (mbuf_attachcluster(MBUF_WAITOK, MBUF_TYPE_DATA, &bytes, (void *)ptr, NULL, len, NULL)) { err = STATUS_NO_MEMORY; goto errout; } mbuf_setlen(bytes, len); ADVANCE(ptr, len); if ((uintptr_t)ptr > ((uintptr_t)lpInBuffer + nInBufferSize) || (uintptr_t)ptr < (uintptr_t)mbuf_data(bytes)) { err = STATUS_MARSHALL_OVERFLOW; goto errout; } /* Set up the response buffer so that we leave room to place the * SMB header at the front. */ len = (size_t)(nOutBufferSize - sizeof(struct smb_header)); if (mbuf_attachcluster(MBUF_WAITOK, MBUF_TYPE_DATA, &response, ((uint8_t *)lpOutBuffer + sizeof(struct smb_header)), NULL, len, NULL)) { err = STATUS_NO_MEMORY; goto errout; } err = smb_ioc_request(hContext, &header, words, bytes, response); if (err) { err = STATUS_IO_DEVICE_ERROR; goto errout; } /* Stash the new SMB header at the front of the output buffer so the * caller gets the server status code, etc. */ memcpy(lpOutBuffer, lpInBuffer, sizeof(header)); OSWriteLittleInt32(lpOutBuffer, 0, *(const uint32_t *)(void *)SMB_SIGNATURE); OSWriteLittleInt32(lpOutBuffer, offsetof(struct smb_header, status), header.status); OSWriteLittleInt16(lpOutBuffer, offsetof(struct smb_header, flags), header.flags); OSWriteLittleInt32(lpOutBuffer, offsetof(struct smb_header, flags2), header.flags2); *lpBytesRead = mbuf_len(response) + sizeof(struct smb_header); /* We return success, even though the server may have failed the call. The * caller is responsible for parsing the reply packet and looking at the * status field in the header. */ err = STATUS_SUCCESS; errout: if (words) mbuf_freem(words); if (bytes) mbuf_freem(bytes); if (response) mbuf_freem(response); return err; }