static void*
MapAlignedPagesSlow(size_t size, size_t alignment)
{
    /* Overallocate and unmap the region's edges. */
    size_t reqSize = size + alignment - pageSize;
    void* region = MapMemory(reqSize);
    if (!region)
        return nullptr;

    void* regionEnd = (void*)(uintptr_t(region) + reqSize);
    void* front;
    void* end;
    if (growthDirection <= 0) {
        size_t offset = OffsetFromAligned(regionEnd, alignment);
        end = (void*)(uintptr_t(regionEnd) - offset);
        front = (void*)(uintptr_t(end) - size);
    } else {
        size_t offset = OffsetFromAligned(region, alignment);
        front = (void*)(uintptr_t(region) + (offset ? alignment - offset : 0));
        end = (void*)(uintptr_t(front) + size);
    }

    if (front != region)
        UnmapPages(region, uintptr_t(front) - uintptr_t(region));
    if (end != regionEnd)
        UnmapPages(end, uintptr_t(regionEnd) - uintptr_t(end));

    return front;
}
/*
 * In a low memory or high fragmentation situation, alignable chunks of the
 * desired size may still be available, even if there are no more contiguous
 * free chunks that meet the |size + alignment - pageSize| requirement of
 * MapAlignedPagesSlow. In this case, try harder to find an alignable chunk
 * by temporarily holding onto the unaligned parts of each chunk until the
 * allocator gives us a chunk that either is, or can be aligned.
 */
static void*
MapAlignedPagesLastDitch(size_t size, size_t alignment)
{
    void* tempMaps[MaxLastDitchAttempts];
    int attempt = 0;
    void* p = MapMemory(size);
    if (OffsetFromAligned(p, alignment) == 0)
        return p;
    for (; attempt < MaxLastDitchAttempts; ++attempt) {
        GetNewChunk(&p, tempMaps + attempt, size, alignment);
        if (OffsetFromAligned(p, alignment) == 0) {
            if (tempMaps[attempt])
                UnmapPages(tempMaps[attempt], size);
            break;
        }
        if (!tempMaps[attempt])
            break; /* Bail if GetNewChunk failed. */
    }
    if (OffsetFromAligned(p, alignment)) {
        UnmapPages(p, size);
        p = nullptr;
    }
    while (--attempt >= 0)
        UnmapPages(tempMaps[attempt], size);
    return p;
}
コード例 #3
0
ファイル: Host.c プロジェクト: EvanLloyd/tianocore
/*++

Routine Description:
  Opens and memory maps a file using Unix services. If BaseAddress is non zero
  the process will try and allocate the memory starting at BaseAddress.

Arguments:
  FileName            - The name of the file to open and map
  MapSize             - The amount of the file to map in bytes
  CreationDisposition - The flags to pass to CreateFile().  Use to create new files for
                        memory emulation, and exiting files for firmware volume emulation
  BaseAddress         - The base address of the mapped file in the user address space.
                         If passed in as NULL the a new memory region is used.
                         If passed in as non NULL the request memory region is used for
                          the mapping of the file into the process space.
  Length              - The size of the mapped region in bytes

Returns:
  EFI_SUCCESS      - The file was opened and mapped.
  EFI_NOT_FOUND    - FileName was not found in the current directory
  EFI_DEVICE_ERROR - An error occured attempting to map the opened file

**/
EFI_STATUS
MapFile (
  IN  CHAR8                     *FileName,
  IN OUT  EFI_PHYSICAL_ADDRESS  *BaseAddress,
  OUT UINT64                    *Length
  )
{
  int     fd;
  VOID    *res;
  UINTN   FileSize;

  fd = open (FileName, O_RDWR);
  if (fd < 0) {
    return EFI_NOT_FOUND;
  }
  FileSize = lseek (fd, 0, SEEK_END);


  res = MapMemory (fd, FileSize, PROT_READ | PROT_EXEC, MAP_PRIVATE);

  close (fd);

  if (res == NULL) {
    perror ("MapFile() Failed");
    return EFI_DEVICE_ERROR;
  }

  *Length = (UINT64) FileSize;
  *BaseAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) res;

  return EFI_SUCCESS;
}
void*
MapAlignedPages(size_t size, size_t alignment)
{
    MOZ_ASSERT(size >= alignment);
    MOZ_ASSERT(size % alignment == 0);
    MOZ_ASSERT(size % pageSize == 0);
    MOZ_ASSERT(alignment % allocGranularity == 0);

    void* p = MapMemory(size);

    /* Special case: If we want page alignment, no further work is needed. */
    if (alignment == allocGranularity)
        return p;

    if (OffsetFromAligned(p, alignment) == 0)
        return p;

    void* retainedAddr;
    GetNewChunk(&p, &retainedAddr, size, alignment);
    if (retainedAddr)
        UnmapPages(retainedAddr, size);
    if (p) {
        if (OffsetFromAligned(p, alignment) == 0)
            return p;
        UnmapPages(p, size);
    }

    p = MapAlignedPagesSlow(size, alignment);
    if (!p)
        return MapAlignedPagesLastDitch(size, alignment);

    MOZ_ASSERT(OffsetFromAligned(p, alignment) == 0);
    return p;
}
static void*
MapAlignedPagesSlow(size_t size, size_t alignment)
{
    /*
     * Windows requires that there be a 1:1 mapping between VM allocation
     * and deallocation operations.  Therefore, take care here to acquire the
     * final result via one mapping operation.  This means unmapping any
     * preliminary result that is not correctly aligned.
     */
    void* p;
    do {
        /*
         * Over-allocate in order to map a memory region that is definitely
         * large enough, then deallocate and allocate again the correct size,
         * within the over-sized mapping.
         *
         * Since we're going to unmap the whole thing anyway, the first
         * mapping doesn't have to commit pages.
         */
        size_t reserveSize = size + alignment - pageSize;
        p = MapMemory(reserveSize, MEM_RESERVE);
        if (!p)
            return nullptr;
        void* chunkStart = (void*)AlignBytes(uintptr_t(p), alignment);
        UnmapPages(p, reserveSize);
        p = MapMemoryAt(chunkStart, size, MEM_COMMIT | MEM_RESERVE);

        /* Failure here indicates a race with another thread, so try again. */
    } while (!p);

    return p;
}
コード例 #6
0
ファイル: Host.c プロジェクト: EvanLloyd/tianocore
/*++

Routine Description:
  This service is called from Index == 0 until it returns EFI_UNSUPPORTED.
  It allows discontinuous memory regions to be supported by the emulator.
  It uses gSystemMemory[] and gSystemMemoryCount that were created by
  parsing the host environment variable EFI_MEMORY_SIZE.
  The size comes from the varaible and the address comes from the call to
  UnixOpenFile.

Arguments:
  Index      - Which memory region to use
  MemoryBase - Return Base address of memory region
  MemorySize - Return size in bytes of the memory region

Returns:
  EFI_SUCCESS - If memory region was mapped
  EFI_UNSUPPORTED - If Index is not supported

**/
EFI_STATUS
SecUnixPeiAutoScan (
  IN  UINTN                 Index,
  OUT EFI_PHYSICAL_ADDRESS  *MemoryBase,
  OUT UINT64                *MemorySize
  )
{
  void *res;

  if (Index >= gSystemMemoryCount) {
    return EFI_UNSUPPORTED;
  }

  *MemoryBase = 0;
  res = MapMemory (
          0, gSystemMemory[Index].Size,
          PROT_READ | PROT_WRITE | PROT_EXEC,
          MAP_PRIVATE | MAP_ANONYMOUS
          );
  if (res == MAP_FAILED) {
    return EFI_DEVICE_ERROR;
  }
  *MemorySize = gSystemMemory[Index].Size;
  *MemoryBase = (UINTN)res;
  gSystemMemory[Index].Memory = *MemoryBase;

  return EFI_SUCCESS;
}
コード例 #7
0
ファイル: GrVkBuffer.cpp プロジェクト: BertiKarsunke/skia
bool GrVkBuffer::vkUpdateData(const GrVkGpu* gpu, const void* src, size_t srcSizeInBytes,
                              bool* createdNewBuffer) {
    SkASSERT(!this->vkIsMapped());
    VALIDATE();
    if (srcSizeInBytes > fDesc.fSizeInBytes) {
        return false;
    }

    if (!fResource->unique()) {
        // in use by the command buffer, so we need to create a new one
        fResource->unref(gpu);
        fResource = Create(gpu, fDesc);
        if (createdNewBuffer) {
            *createdNewBuffer = true;
        }
    }

    void* mapPtr;
    VkResult err = VK_CALL(gpu, MapMemory(gpu->device(), alloc(), 0, srcSizeInBytes, 0, &mapPtr));

    if (VK_SUCCESS != err) {
        return false;
    }

    memcpy(mapPtr, src, srcSizeInBytes);

    VK_CALL(gpu, UnmapMemory(gpu->device(), alloc()));

    return true;
}
コード例 #8
0
ファイル: MapMemory.c プロジェクト: 0xDEC0DE8/libhijack
int main(int argc, char *argv[])
{
	HIJACK *hijack;
	FUNC *func;
	unsigned long addr;
	PLT *plts, *plt;
	
	if (argc != 2)
		usage(argv[0]);
	
	hijack = InitHijack();
    ToggleFlag(hijack, F_DEBUG);
    ToggleFlag(hijack, F_DEBUG_VERBOSE);
	AssignPid(hijack, atoi(argv[1]));
	
	if (Attach(hijack) != ERROR_NONE)
	{
		fprintf(stderr, "[-] Couldn't attach!\n");
		exit(EXIT_FAILURE);
	}

	if (LocateAllFunctions(hijack) != ERROR_NONE)
	{
		fprintf(stderr, "[-] Couldn't locate all functions!\n");
		exit(EXIT_FAILURE);
	}

    if (LocateSystemCall(hijack) != ERROR_NONE) {
        fprintf(stderr, "[-] Couldn't locate system call!\n");
        exit(EXIT_FAILURE);
    }

    addr = MapMemory(hijack, NULL, 8192, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_SHARED);
    if (GetErrorCode(hijack) != ERROR_NONE) {
        fprintf(stderr, "[-] %s\n", GetErrorString(hijack));
        perror("ptrace");
    }
	
	printf("[*] PLT/GOT @ 0x%016lx\n", hijack->pltgot);
	printf("[*] Baseaddr @ 0x%016lx\n", hijack->baseaddr);
    printf("[*] Syscall @ 0x%016lx\n", hijack->syscalladdr);
    printf("[*] addr @ 0x%016lx\n", addr);

	Detach(hijack);
	
	return 0;
}
void*
AllocateMappedContent(int fd, size_t offset, size_t length, size_t alignment)
{
#define NEED_PAGE_ALIGNED 0
    size_t pa_start; // Page aligned starting
    size_t pa_end; // Page aligned ending
    size_t pa_size; // Total page aligned size
    struct stat st;
    uint8_t* buf;

    // Make sure file exists and do sanity check for offset and size.
    if (fstat(fd, &st) < 0 || offset >= (size_t) st.st_size ||
        length == 0 || length > (size_t) st.st_size - offset)
        return nullptr;

    // Check for minimal alignment requirement.
#if NEED_PAGE_ALIGNED
    alignment = std::max(alignment, pageSize);
#endif
    if (offset & (alignment - 1))
        return nullptr;

    // Page aligned starting of the offset.
    pa_start = offset & ~(pageSize - 1);
    // Calculate page aligned ending by adding one page to the page aligned
    // starting of data end position(offset + length - 1).
    pa_end = ((offset + length - 1) & ~(pageSize - 1)) + pageSize;
    pa_size = pa_end - pa_start;

    // Ask for a continuous memory location.
    buf = (uint8_t*) MapMemory(pa_size);
    if (!buf)
        return nullptr;

    buf = (uint8_t*) MapMemoryAt(buf, pa_size, PROT_READ | PROT_WRITE,
                                  MAP_PRIVATE | MAP_FIXED, fd, pa_start);
    if (!buf)
        return nullptr;

    // Reset the data before target file, which we don't need to see.
    memset(buf, 0, offset - pa_start);

    // Reset the data after target file, which we don't need to see.
    memset(buf + (offset - pa_start) + length, 0, pa_end - (offset + length));

    return buf + (offset - pa_start);
}
/*
 * mmap calls don't have to be matched with calls to munmap, so we can unmap
 * just the pages we don't need. However, as we don't know a priori if addresses
 * are handed out in increasing or decreasing order, we have to try both
 * directions (depending on the environment, one will always fail).
 */
static void
GetNewChunk(void** aAddress, void** aRetainedAddr, size_t size, size_t alignment)
{
    void* address = *aAddress;
    void* retainedAddr = nullptr;
    bool addrsGrowDown = growthDirection <= 0;
    int i = 0;
    for (; i < 2; ++i) {
        /* Try the direction indicated by growthDirection. */
        if (addrsGrowDown) {
            size_t offset = OffsetFromAligned(address, alignment);
            void* head = (void*)((uintptr_t)address - offset);
            void* tail = (void*)((uintptr_t)head + size);
            if (MapMemoryAt(head, offset)) {
                UnmapPages(tail, offset);
                if (growthDirection >= -8)
                    --growthDirection;
                address = head;
                break;
            }
        } else {
            size_t offset = alignment - OffsetFromAligned(address, alignment);
            void* head = (void*)((uintptr_t)address + offset);
            void* tail = (void*)((uintptr_t)address + size);
            if (MapMemoryAt(tail, offset)) {
                UnmapPages(address, offset);
                if (growthDirection <= 8)
                    ++growthDirection;
                address = head;
                break;
            }
        }
        /* If we're confident in the growth direction, don't try the other. */
        if (growthDirection < -8 || growthDirection > 8)
            break;
        /* If that failed, try the opposite direction. */
        addrsGrowDown = !addrsGrowDown;
    }
    /* If our current chunk cannot be aligned, see if the next one is aligned. */
    if (OffsetFromAligned(address, alignment)) {
        retainedAddr = address;
        address = MapMemory(size);
    }
    *aAddress = address;
    *aRetainedAddr = retainedAddr;
}
コード例 #11
0
ファイル: GrVkBuffer.cpp プロジェクト: BertiKarsunke/skia
void* GrVkBuffer::vkMap(const GrVkGpu* gpu) {
    VALIDATE();
    SkASSERT(!this->vkIsMapped());

    if (!fResource->unique()) {
        // in use by the command buffer, so we need to create a new one
        fResource->unref(gpu);
        fResource = Create(gpu, fDesc);
    }

    VkResult err = VK_CALL(gpu, MapMemory(gpu->device(), alloc(), 0, VK_WHOLE_SIZE, 0, &fMapPtr));
    if (err) {
        fMapPtr = nullptr;
    }

    VALIDATE();
    return fMapPtr;
}
/*
 * On Windows, map and unmap calls must be matched, so we deallocate the
 * unaligned chunk, then reallocate the unaligned part to block off the
 * old address and force the allocator to give us a new one.
 */
static void
GetNewChunk(void** aAddress, void** aRetainedAddr, size_t size, size_t alignment)
{
    void* address = *aAddress;
    void* retainedAddr = nullptr;
    do {
        size_t retainedSize;
        size_t offset = OffsetFromAligned(address, alignment);
        if (!offset)
            break;
        UnmapPages(address, size);
        retainedSize = alignment - offset;
        retainedAddr = MapMemoryAt(address, retainedSize, MEM_RESERVE);
        address = MapMemory(size, MEM_COMMIT | MEM_RESERVE);
        /* If retainedAddr is null here, we raced with another thread. */
    } while (!retainedAddr);
    *aAddress = address;
    *aRetainedAddr = retainedAddr;
}
コード例 #13
0
void GrVkBuffer::internalMap(GrVkGpu* gpu, size_t size, bool* createdNewBuffer) {
    VALIDATE();
    SkASSERT(!this->vkIsMapped());

    if (!fResource->unique()) {
        if (fDesc.fDynamic) {
            // in use by the command buffer, so we need to create a new one
            fResource->recycle(gpu);
            fResource = this->createResource(gpu, fDesc);
            if (createdNewBuffer) {
                *createdNewBuffer = true;
            }
        } else {
            SkASSERT(fMapPtr);
            this->addMemoryBarrier(gpu,
                                   buffer_type_to_access_flags(fDesc.fType),
                                   VK_ACCESS_TRANSFER_WRITE_BIT,
                                   VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
                                   VK_PIPELINE_STAGE_TRANSFER_BIT,
                                   false);
        }
    }

    if (fDesc.fDynamic) {
        const GrVkAlloc& alloc = this->alloc();
        VkResult err = VK_CALL(gpu, MapMemory(gpu->device(), alloc.fMemory,
                                              alloc.fOffset + fOffset,
                                              size, 0, &fMapPtr));
        if (err) {
            fMapPtr = nullptr;
        }
    } else {
        if (!fMapPtr) {
            fMapPtr = new unsigned char[this->size()];
        }
    }

    VALIDATE();
}
コード例 #14
0
ファイル: GrVkBuffer.cpp プロジェクト: OwenTan/skia
void* GrVkBuffer::vkMap(const GrVkGpu* gpu) {
    VALIDATE();
    SkASSERT(!this->vkIsMapped());
    if (!fResource->unique()) {
        // in use by the command buffer, so we need to create a new one
        fResource->unref(gpu);
        fResource = Create(gpu, fDesc);
    }

    if (fDesc.fDynamic) {
        const GrVkAlloc& alloc = this->alloc();
        VkResult err = VK_CALL(gpu, MapMemory(gpu->device(), alloc.fMemory,
                                              alloc.fOffset + fOffset,
                                              fDesc.fSizeInBytes, 0, &fMapPtr));
        if (err) {
            fMapPtr = nullptr;
        }
    } else {
        fMapPtr = new unsigned char[this->size()];
    }

    VALIDATE();
    return fMapPtr;
}
コード例 #15
0
ファイル: SecMain.c プロジェクト: AshleyDeSimone/edk2
int
main (
  IN  int   Argc,
  IN  char  **Argv,
  IN  char  **Envp
  )
/*++

Routine Description:
  Main entry point to SEC for Unix. This is a unix program

Arguments:
  Argc - Number of command line arguments
  Argv - Array of command line argument strings
  Envp - Array of environmemt variable strings

Returns:
  0 - Normal exit
  1 - Abnormal exit

--*/
{
  EFI_STATUS            Status;
  EFI_PHYSICAL_ADDRESS  InitialStackMemory;
  UINT64                InitialStackMemorySize;
  UINTN                 Index;
  UINTN                 Index1;
  UINTN                 Index2;
  UINTN                 PeiIndex;
  CHAR8                 *FileName;
  BOOLEAN               Done;
  VOID                  *PeiCoreFile;
  CHAR16                *MemorySizeStr;
  CHAR16                *FirmwareVolumesStr;
  UINTN                 *StackPointer;

  setbuf(stdout, 0);
  setbuf(stderr, 0);

  MemorySizeStr      = (CHAR16 *) PcdGetPtr (PcdUnixMemorySizeForSecMain);
  FirmwareVolumesStr = (CHAR16 *) PcdGetPtr (PcdUnixFirmwareVolume);

  printf ("\nEDK SEC Main UNIX Emulation Environment from edk2.sourceforge.net\n");

#ifdef __APPLE__
  //
  // We can't use dlopen on OS X, so we need a scheme to get symboles into gdb
  // We need to create a temp file that contains gdb commands so we can load
  // symbols when we load every PE/COFF image.
  //
  Index = strlen (*Argv);
  gGdbWorkingFileName = malloc (Index + strlen(".gdb") + 1);
  strcpy (gGdbWorkingFileName, *Argv);
  strcat (gGdbWorkingFileName, ".gdb");
#endif


  //
  // Allocate space for gSystemMemory Array
  //
  gSystemMemoryCount  = CountSeperatorsInString (MemorySizeStr, '!') + 1;
  gSystemMemory       = calloc (gSystemMemoryCount, sizeof (UNIX_SYSTEM_MEMORY));
  if (gSystemMemory == NULL) {
    printf ("ERROR : Can not allocate memory for system.  Exiting.\n");
    exit (1);
  }
  //
  // Allocate space for gSystemMemory Array
  //
  gFdInfoCount  = CountSeperatorsInString (FirmwareVolumesStr, '!') + 1;
  gFdInfo       = calloc (gFdInfoCount, sizeof (UNIX_FD_INFO));
  if (gFdInfo == NULL) {
    printf ("ERROR : Can not allocate memory for fd info.  Exiting.\n");
    exit (1);
  }
  //
  // Setup Boot Mode. If BootModeStr == "" then BootMode = 0 (BOOT_WITH_FULL_CONFIGURATION)
  //
  printf ("  BootMode 0x%02x\n", (unsigned int)PcdGet32 (PcdUnixBootMode));

  //
  // Open up a 128K file to emulate temp memory for PEI.
  //  on a real platform this would be SRAM, or using the cache as RAM.
  //  Set InitialStackMemory to zero so UnixOpenFile will allocate a new mapping
  //
  InitialStackMemorySize  = STACK_SIZE;
  InitialStackMemory = (UINTN)MapMemory(0,
          (UINT32) InitialStackMemorySize,
          PROT_READ | PROT_WRITE | PROT_EXEC,
          MAP_ANONYMOUS | MAP_PRIVATE);
  if (InitialStackMemory == 0) {
    printf ("ERROR : Can not open SecStack Exiting\n");
    exit (1);
  }

  printf ("  SEC passing in %u KB of temp RAM at 0x%08lx to PEI\n",
    (unsigned int)(InitialStackMemorySize / 1024),
    (unsigned long)InitialStackMemory);

  for (StackPointer = (UINTN*) (UINTN) InitialStackMemory;
     StackPointer < (UINTN*)(UINTN)((UINTN) InitialStackMemory + (UINT64) InitialStackMemorySize);
     StackPointer ++) {
    *StackPointer = 0x5AA55AA5;
  }

  //
  // Open All the firmware volumes and remember the info in the gFdInfo global
  //
  FileName = (CHAR8 *)malloc (StrLen (FirmwareVolumesStr) + 1);
  if (FileName == NULL) {
    printf ("ERROR : Can not allocate memory for firmware volume string\n");
    exit (1);
  }

  Index2 = 0;
  for (Done = FALSE, Index = 0, PeiIndex = 0, PeiCoreFile = NULL;
       FirmwareVolumesStr[Index2] != 0;
       Index++) {
    for (Index1 = 0; (FirmwareVolumesStr[Index2] != '!') && (FirmwareVolumesStr[Index2] != 0); Index2++)
      FileName[Index1++] = FirmwareVolumesStr[Index2];
    if (FirmwareVolumesStr[Index2] == '!')
      Index2++;
    FileName[Index1]  = '\0';

    //
    // Open the FD and remmeber where it got mapped into our processes address space
    //
    Status = MapFile (
          FileName,
          &gFdInfo[Index].Address,
          &gFdInfo[Index].Size
          );
    if (EFI_ERROR (Status)) {
      printf ("ERROR : Can not open Firmware Device File %s (%x).  Exiting.\n", FileName, (unsigned int)Status);
      exit (1);
    }

    printf ("  FD loaded from %s at 0x%08lx",
      FileName, (unsigned long)gFdInfo[Index].Address);

    if (PeiCoreFile == NULL) {
      //
      // Assume the beginning of the FD is an FV and look for the PEI Core.
      // Load the first one we find.
      //
      Status = SecFfsFindPeiCore ((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) gFdInfo[Index].Address, &PeiCoreFile);
      if (!EFI_ERROR (Status)) {
        PeiIndex = Index;
        printf (" contains SEC Core");
      }
    }

    printf ("\n");
  }
  //
  // Calculate memory regions and store the information in the gSystemMemory
  //  global for later use. The autosizing code will use this data to
  //  map this memory into the SEC process memory space.
  //
  Index1 = 0;
  Index = 0;
  while (1) {
    UINTN val = 0;
    //
    // Save the size of the memory.
    //
    while (MemorySizeStr[Index1] >= '0' && MemorySizeStr[Index1] <= '9') {
      val = val * 10 + MemorySizeStr[Index1] - '0';
      Index1++;
    }
    gSystemMemory[Index++].Size = val * 0x100000;
    if (MemorySizeStr[Index1] == 0)
      break;
    Index1++;
  }

  printf ("\n");

  //
  // Hand off to PEI Core
  //
  SecLoadFromCore ((UINTN) InitialStackMemory, (UINTN) InitialStackMemorySize, (UINTN) gFdInfo[0].Address, PeiCoreFile);

  //
  // If we get here, then the PEI Core returned. This is an error as PEI should
  //  always hand off to DXE.
  //
  printf ("ERROR : PEI Core returned\n");
  exit (1);
}
コード例 #16
0
ファイル: SecMain.c プロジェクト: AshleyDeSimone/edk2
EFI_STATUS
MapFile (
  IN  CHAR8                     *FileName,
  IN OUT  EFI_PHYSICAL_ADDRESS  *BaseAddress,
  OUT UINT64                    *Length
  )
/*++

Routine Description:
  Opens and memory maps a file using Unix services. If BaseAddress is non zero
  the process will try and allocate the memory starting at BaseAddress.

Arguments:
  FileName            - The name of the file to open and map
  MapSize             - The amount of the file to map in bytes
  CreationDisposition - The flags to pass to CreateFile().  Use to create new files for
                        memory emulation, and exiting files for firmware volume emulation
  BaseAddress         - The base address of the mapped file in the user address space.
                         If passed in as NULL the a new memory region is used.
                         If passed in as non NULL the request memory region is used for
                          the mapping of the file into the process space.
  Length              - The size of the mapped region in bytes

Returns:
  EFI_SUCCESS      - The file was opened and mapped.
  EFI_NOT_FOUND    - FileName was not found in the current directory
  EFI_DEVICE_ERROR - An error occured attempting to map the opened file

--*/
{
  int fd;
  VOID    *res;
  UINTN   FileSize;

  fd = open (FileName, O_RDONLY);
  if (fd < 0)
    return EFI_NOT_FOUND;
  FileSize = lseek (fd, 0, SEEK_END);

#if 0
  if (IsMain)
    {
      /* Read entry address.  */
      lseek (fd, FileSize - 0x20, SEEK_SET);
      if (read (fd, &EntryAddress, 4) != 4)
  {
    close (fd);
    return EFI_DEVICE_ERROR;
  }
    }
#endif

  res = MapMemory(fd, FileSize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);

  close (fd);

  if (res == MAP_FAILED)
    return EFI_DEVICE_ERROR;

  *Length = (UINT64) FileSize;
  *BaseAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) res;

  return EFI_SUCCESS;
}
コード例 #17
0
int main(int argc, char *argv[])
{
	HIJACK *hijack;
	FUNC *funcs, *func;
	unsigned long shellcode_addr, filename_addr, dlopen_addr, dlsym_addr, funcname_addr, pltgot_addr;
	struct stat sb;
	char *shellcode, *p1;
	int fd;
	struct user_regs_struct *regs, *backup;
	
	if (argc != 5)
		usage(argv[0]);
	
	hijack = InitHijack();
    ToggleFlag(hijack, F_DEBUG);
    ToggleFlag(hijack, F_DEBUG_VERBOSE);
	AssignPid(hijack, atoi(argv[1]));
	
	if (Attach(hijack) != ERROR_NONE)
	{
		fprintf(stderr, "[-] Couldn't attach!\n");
		exit(EXIT_FAILURE);
	}
	backup = GetRegs(hijack);
	regs = malloc(sizeof(struct user_regs_struct));
	
	stat(argv[2], &sb);
	shellcode = malloc(sb.st_size);
	
	fd = open(argv[2], O_RDONLY);
	read(fd, shellcode, sb.st_size);
	close(fd);
	
	LocateAllFunctions(hijack);
	funcs = FindFunctionInLibraryByName(hijack, "/lib/libdl.so.2", "dlopen");
	if (!(funcs))
	{
		fprintf(stderr, "[-] Couldn't locate dlopen!\n");
		exit(EXIT_FAILURE);
	}
	dlopen_addr = funcs->vaddr;
	printf("dlopen_addr: 0x%08lx\n", dlopen_addr);
	
	funcs = FindFunctionInLibraryByName(hijack, "/lib/libdl.so.2", "dlsym");
	if (!(funcs))
	{
		fprintf(stderr, "[-] Couldn't locate dlsym!\n");
		exit(EXIT_FAILURE);
	}
	dlsym_addr = funcs->vaddr;
	printf("dlsym_addr: 0x%08lx\n", dlsym_addr);
	
	memcpy(regs, backup, sizeof(struct user_regs_struct));
	
	LocateSystemCall(hijack);
	filename_addr = MapMemory(hijack, (unsigned long)NULL, 4096,PROT_READ | PROT_EXEC | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE);
	
	memcpy(regs, backup, sizeof(struct user_regs_struct));
	
	p1 = memmem(shellcode, sb.st_size, "\x22\x22\x22\x22", 4);
	memcpy(p1, &filename_addr, 4);
	
	funcname_addr = filename_addr + strlen(argv[3]) + 1;
	shellcode_addr = funcname_addr + strlen(argv[4]) + 1;
	printf("filename_addr: 0x%08lx\n", filename_addr);
	printf("shellcode_addr: 0x%08lx\n", shellcode_addr);
	printf("esp: 0x%08lx\n", regs->esp);
	printf("eip: 0x%08lx\n", regs->eip);
	
	p1 = memmem(shellcode, sb.st_size, "\x33\x33\x33\x33", 4);
	memcpy(p1, &dlopen_addr, 4);
	
	p1 = memmem(shellcode, sb.st_size, "\x44\x44\x44\x44", 4);
	memcpy(p1, &funcname_addr, 4);
	
	p1 = memmem(shellcode, sb.st_size, "\x55\x55\x55\x55", 4);
	memcpy(p1, &dlsym_addr, 4);
	
	funcs = FindAllFunctionsByName(hijack, argv[4], false);
	for (func = funcs; func != NULL; func = func->next)
	{
		if (!(func->name))
			continue;
		
		pltgot_addr = FindFunctionInGot(hijack, hijack->pltgot, func->vaddr);
		if (pltgot_addr > 0)
			break;
	}
	
	printf("pltgot_addr: 0x%08lx\n", pltgot_addr);
	
	p1 = memmem(shellcode, sb.st_size, "\x66\x66\x66\x66", 4);
	memcpy(p1, &pltgot_addr, 4);
	
	WriteData(hijack, filename_addr, (unsigned char *)argv[3], strlen(argv[3]));
	WriteData(hijack, funcname_addr, (unsigned char *)argv[4], strlen(argv[4]));
	WriteData(hijack, shellcode_addr, (unsigned char *)shellcode, sb.st_size);
	
	regs->esp -= 4;
	SetRegs(hijack, regs);
	WriteData(hijack, regs->esp, &(regs->eip), 4);
	
	regs->eip = shellcode_addr;
	
	if (regs->orig_eax >= 0)
	{
		switch (regs->eax)
		{
			case -514: /* -ERESTARTNOHAND */
			case -512: /* -ERESTARTSYS */
			case -513: /* -ERESTARTNOINTR */
			case -516: /* -ERESTART_RESTARTBLOCK */
				regs->eip += 2;
				break;
		}
	}
	SetRegs(hijack, regs);
	
	Detach(hijack);
	
	return 0;
}
コード例 #18
0
ファイル: Host.c プロジェクト: EvanLloyd/tianocore
/*++

Routine Description:
  Main entry point to SEC for Unix. This is a unix program

Arguments:
  Argc - Number of command line arguments
  Argv - Array of command line argument strings
  Envp - Array of environment variable strings

Returns:
  0 - Normal exit
  1 - Abnormal exit

**/
int
main (
  IN  int   Argc,
  IN  char  **Argv,
  IN  char  **Envp
  )
{
  EFI_STATUS            Status;
  EFI_PHYSICAL_ADDRESS  InitialStackMemory;
  UINT64                InitialStackMemorySize;
  UINTN                 Index;
  UINTN                 Index1;
  UINTN                 Index2;
  UINTN                 PeiIndex;
  CHAR8                 *FileName;
  BOOLEAN               Done;
  EFI_PEI_FILE_HANDLE   FileHandle;
  VOID                  *SecFile;
  CHAR16                *MemorySizeStr;
  CHAR16                *FirmwareVolumesStr;
  UINTN                 *StackPointer;
  FILE                  *GdbTempFile;

  //
  // Xcode does not support sourcing gdb scripts directly, so the Xcode XML
  // has a break point script to source the GdbRun script.
  //
  SecGdbConfigBreak ();

  //
  // If dlopen doesn't work, then we build a gdb script to allow the
  // symbols to be loaded.
  //
  Index = strlen (*Argv);
  gGdbWorkingFileName = AllocatePool (Index + strlen(".gdb") + 1);
  strcpy (gGdbWorkingFileName, *Argv);
  strcat (gGdbWorkingFileName, ".gdb");

  //
  // Empty out the gdb symbols script file.
  //
  GdbTempFile = fopen (gGdbWorkingFileName, "w");
  if (GdbTempFile != NULL) {
    fclose (GdbTempFile);
  }

  printf ("\nEDK II UNIX Host Emulation Environment from http://www.tianocore.org/edk2/\n");

  setbuf (stdout, 0);
  setbuf (stderr, 0);

  MemorySizeStr      = (CHAR16 *) PcdGetPtr (PcdEmuMemorySize);
  FirmwareVolumesStr = (CHAR16 *) PcdGetPtr (PcdEmuFirmwareVolume);

  //
  // PPIs pased into PEI_CORE
  //
  AddThunkPpi (EFI_PEI_PPI_DESCRIPTOR_PPI, &gEmuThunkPpiGuid, &mSecEmuThunkPpi);

  SecInitThunkProtocol ();

  //
  // Emulator Bus Driver Thunks
  //
  AddThunkProtocol (&gX11ThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuGop), TRUE);
  AddThunkProtocol (&gPosixFileSystemThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuFileSystem), TRUE);
  AddThunkProtocol (&gBlockIoThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuVirtualDisk), TRUE);
  AddThunkProtocol (&gSnpThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuNetworkInterface), TRUE);

  //
  // Emulator other Thunks
  //
  AddThunkProtocol (&gPthreadThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuApCount), FALSE);

  // EmuSecLibConstructor ();

  gPpiList = GetThunkPpiList ();

  //
  // Allocate space for gSystemMemory Array
  //
  gSystemMemoryCount  = CountSeparatorsInString (MemorySizeStr, '!') + 1;
  gSystemMemory       = AllocateZeroPool (gSystemMemoryCount * sizeof (EMU_SYSTEM_MEMORY));
  if (gSystemMemory == NULL) {
    printf ("ERROR : Can not allocate memory for system.  Exiting.\n");
    exit (1);
  }
  //
  // Allocate space for gSystemMemory Array
  //
  gFdInfoCount  = CountSeparatorsInString (FirmwareVolumesStr, '!') + 1;
  gFdInfo       = AllocateZeroPool (gFdInfoCount * sizeof (EMU_FD_INFO));
  if (gFdInfo == NULL) {
    printf ("ERROR : Can not allocate memory for fd info.  Exiting.\n");
    exit (1);
  }

  printf ("  BootMode 0x%02x\n", (unsigned int)PcdGet32 (PcdEmuBootMode));

  //
  // Open up a 128K file to emulate temp memory for SEC.
  //  on a real platform this would be SRAM, or using the cache as RAM.
  //  Set InitialStackMemory to zero so UnixOpenFile will allocate a new mapping
  //
  InitialStackMemorySize  = STACK_SIZE;
  InitialStackMemory = (UINTN)MapMemory (
                                0, (UINT32) InitialStackMemorySize,
                                PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE
                                );
  if (InitialStackMemory == 0) {
    printf ("ERROR : Can not open SecStack Exiting\n");
    exit (1);
  }

  printf ("  OS Emulator passing in %u KB of temp RAM at 0x%08lx to SEC\n",
    (unsigned int)(InitialStackMemorySize / 1024),
    (unsigned long)InitialStackMemory
    );

  for (StackPointer = (UINTN*) (UINTN) InitialStackMemory;
     StackPointer < (UINTN*)(UINTN)((UINTN) InitialStackMemory + (UINT64) InitialStackMemorySize);
     StackPointer ++) {
    *StackPointer = 0x5AA55AA5;
  }

  //
  // Open All the firmware volumes and remember the info in the gFdInfo global
  //
  FileName = (CHAR8 *) AllocatePool (StrLen (FirmwareVolumesStr) + 1);
  if (FileName == NULL) {
    printf ("ERROR : Can not allocate memory for firmware volume string\n");
    exit (1);
  }

  Index2 = 0;
  for (Done = FALSE, Index = 0, PeiIndex = 0, SecFile = NULL;
       FirmwareVolumesStr[Index2] != 0;
       Index++) {
    for (Index1 = 0; (FirmwareVolumesStr[Index2] != '!') && (FirmwareVolumesStr[Index2] != 0); Index2++) {
      FileName[Index1++] = FirmwareVolumesStr[Index2];
    }
    if (FirmwareVolumesStr[Index2] == '!') {
      Index2++;
    }
    FileName[Index1]  = '\0';

    if (Index == 0) {
      // Map FV Recovery Read Only and other areas Read/Write
      Status = MapFd0 (
                FileName,
                &gFdInfo[0].Address,
                &gFdInfo[0].Size
                );
    } else {
      //
      // Open the FD and remember where it got mapped into our processes address space
      // Maps Read Only
      //
      Status = MapFile (
                FileName,
                &gFdInfo[Index].Address,
                &gFdInfo[Index].Size
                );
    }
    if (EFI_ERROR (Status)) {
      printf ("ERROR : Can not open Firmware Device File %s (%x).  Exiting.\n", FileName, (unsigned int)Status);
      exit (1);
    }

    printf ("  FD loaded from %s at 0x%08lx",FileName, (unsigned long)gFdInfo[Index].Address);

    if (SecFile == NULL) {
      //
      // Assume the beginning of the FD is an FV and look for the SEC Core.
      // Load the first one we find.
      //
      FileHandle = NULL;
      Status = PeiServicesFfsFindNextFile (
                  EFI_FV_FILETYPE_SECURITY_CORE,
                  (EFI_PEI_FV_HANDLE)(UINTN)gFdInfo[Index].Address,
                  &FileHandle
                  );
      if (!EFI_ERROR (Status)) {
        Status = PeiServicesFfsFindSectionData (EFI_SECTION_PE32, FileHandle, &SecFile);
        if (!EFI_ERROR (Status)) {
          PeiIndex = Index;
          printf (" contains SEC Core");
        }
      }
    }

    printf ("\n");
  }

  if (SecFile == NULL) {
    printf ("ERROR : SEC not found!\n");
    exit (1);
  }

  //
  // Calculate memory regions and store the information in the gSystemMemory
  //  global for later use. The autosizing code will use this data to
  //  map this memory into the SEC process memory space.
  //
  Index1 = 0;
  Index = 0;
  while (1) {
    UINTN val = 0;
    //
    // Save the size of the memory.
    //
    while (MemorySizeStr[Index1] >= '0' && MemorySizeStr[Index1] <= '9') {
      val = val * 10 + MemorySizeStr[Index1] - '0';
      Index1++;
    }
    gSystemMemory[Index++].Size = val * 0x100000;
    if (MemorySizeStr[Index1] == 0) {
      break;
    }
    Index1++;
  }

  printf ("\n");

  //
  // Hand off to SEC
  //
  SecLoadFromCore ((UINTN) InitialStackMemory, (UINTN) InitialStackMemorySize, (UINTN) gFdInfo[0].Address, SecFile);

  //
  // If we get here, then the SEC Core returned. This is an error as SEC should
  //  always hand off to PEI Core and then on to DXE Core.
  //
  printf ("ERROR : SEC returned\n");
  exit (1);
}