private IEnumerable <ImportedFunction> ReadImportedFunctions(IntPtr originalFirstThunk, IntPtr firstThunk)
        {
            var result = new List <ImportedFunction>();

            var thunkData = Marshal.ReadInt32(originalFirstThunk);

            while (thunkData != 0)
            {
                var import = new ImportedFunction
                {
                    ImportedByOrdinal = (thunkData & 0x80000000) != 0,
                    FunctionPtr       = firstThunk
                };

                if (import.ImportedByOrdinal)
                {
                    Console.WriteLine("Imported by ordinal.");
                    import.Ordinal = thunkData & (~0x7FFFFFFF);
                }
                else
                {
                    // We ignore the hint stored in the structure since it's not relevant for us
                    var importByNamePtr = IntPtrUtil.Add(_handle, thunkData);
                    import.Name = Marshal.PtrToStringAnsi(IntPtrUtil.Add(importByNamePtr, 2));
                }

                result.Add(import);

                firstThunk         = IntPtrUtil.Add(firstThunk, 4);
                originalFirstThunk = IntPtrUtil.Add(originalFirstThunk, 4);
                thunkData          = Marshal.ReadInt32(originalFirstThunk);
            }

            return(result);
        }
        public PeHeader(IntPtr imageHandle)
        {
            DosHeader = (IMAGE_DOS_HEADER)Marshal.PtrToStructure(imageHandle, typeof(IMAGE_DOS_HEADER));

            var optionalHeaderPtr = IntPtrUtil.Add(imageHandle, DosHeader.e_lfanew);

            NtHeader = (IMAGE_NT_HEADERS)Marshal.PtrToStructure(optionalHeaderPtr,
                                                                typeof(IMAGE_NT_HEADERS));
        }
        public T ReadStructure <T>(int offset)
        {
            if (!Valid)
            {
                throw new InvalidOperationException("The library is not loaded.");
            }

            var ptr = IntPtrUtil.Add(Handle, offset);

            return((T)Marshal.PtrToStructure(ptr, typeof(T)));
        }
        /// <summary>
        /// Reads a portion of memory in relation to the library start.
        /// </summary>
        /// <param name="offset"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public void WriteMemory(int offset, byte[] data)
        {
            if (!Valid)
            {
                throw new InvalidOperationException("The library is not loaded.");
            }

            var ptr = IntPtrUtil.Add(Handle, offset);

            Protection oldProtection;

            Win32Api.VirtualProtect(ptr, (uint)data.Length, Protection.ReadWrite, out oldProtection);
            Marshal.Copy(data, 0, ptr, data.Length);
            Win32Api.VirtualProtect(ptr, (uint)data.Length, oldProtection, out oldProtection);
        }
        /// <summary>
        /// Reads a portion of memory in relation to the library start.
        /// </summary>
        /// <param name="offset"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public byte[] ReadMemory(int offset, int length)
        {
            if (!Valid)
            {
                throw new InvalidOperationException("The library is not loaded.");
            }

            var ptr = IntPtrUtil.Add(Handle, offset);

            var result = new byte[length];

            Marshal.Copy(ptr, result, 0, length);

            return(result);
        }
        public void WriteStructure <T>(int offset, T structure)
        {
            if (!Valid)
            {
                throw new InvalidOperationException("The library is not loaded.");
            }

            var ptr = IntPtrUtil.Add(Handle, offset);

            uint size = (uint)Marshal.SizeOf(structure);

            Protection oldProtection;

            Win32Api.VirtualProtect(ptr, size, Protection.ReadWrite, out oldProtection);
            Marshal.StructureToPtr(structure, ptr, false);
            Win32Api.VirtualProtect(ptr, size, oldProtection, out oldProtection);
        }
        private IntPtr CreateVirtualHandle(string key, int archiveIndex)
        {
            var handle = new IntPtr(0x7FFF0000);

            while (_virtualHandles.ContainsKey(handle))
            {
                handle = IntPtrUtil.Add(handle, 1);
            }

            var archiveInfo = _extractor.ArchiveFileData[archiveIndex];
            var stream      = new MemoryStream((int)archiveInfo.Size);

            _extractor.ExtractFile(archiveIndex, stream);
            stream.Seek(0, SeekOrigin.Begin);

            _virtualHandles[handle] = new VirtualHandle {
                Filename = key, Stream = stream, ArchiveInfo = archiveInfo
            };

            return(handle);
        }
        private void Load()
        {
            var header = new PeHeader(_handle);

            var imageDataDirectory = header.NtHeader.OptionalHeader.DataDirectory[(int)DataDictionaryId.ImportSymbols];

            Console.WriteLine("IAT @ " + imageDataDirectory.VirtualAddress);

            var iatStart = IntPtrUtil.Add(_handle, imageDataDirectory.VirtualAddress);

            var importDescriptor     = (IMAGE_IMPORT_DESCRIPTOR)Marshal.PtrToStructure(iatStart, typeof(IMAGE_IMPORT_DESCRIPTOR));
            var importDescriptorSize = Marshal.SizeOf(typeof(IMAGE_IMPORT_DESCRIPTOR));

            while (importDescriptor.Characteristics != 0)
            {
                var namePtr = IntPtrUtil.Add(_handle, importDescriptor.Name1);
                var dllName = Marshal.PtrToStringAnsi(namePtr);

                if (dllName == null)
                {
                    throw new NullReferenceException();
                }

                dllName = dllName.ToLower();

                if (!Table.ContainsKey(dllName))
                {
                    Table.Add(dllName, new List <ImportedFunction>());
                }

                var orgFirstThunk = IntPtrUtil.Add(_handle, importDescriptor.OriginalFirstThunk);
                var firstThunk    = IntPtrUtil.Add(_handle, importDescriptor.FirstThunk);

                Table[dllName].AddRange(ReadImportedFunctions(orgFirstThunk, firstThunk));

                // Read next IAT entry
                iatStart         = IntPtrUtil.Add(iatStart, importDescriptorSize);
                importDescriptor = (IMAGE_IMPORT_DESCRIPTOR)Marshal.PtrToStructure(iatStart, typeof(IMAGE_IMPORT_DESCRIPTOR));
            }
        }
        private IntPtr FindFirstFileHook(string fileName, IntPtr findFileDataPtr)
        {
#if TRACE
            Console.WriteLine("Find File: " + fileName);
#endif

            fileName = RewriteFilename(fileName, "FindFirstFile");

            var key = NormalizeFileName(fileName);

            var results = new List <WIN32_FIND_DATA>();

            /*
             * Search in directory overlays
             */
            if (!Path.IsPathRooted(fileName))
            {
                // Search for files in the virtual write directory
                if (_settings.WriteAccessVirtualization)
                {
                    var path = Path.Combine(_settings.VirtualWriteDirectory, fileName);
                    FindFilesWin32(path, results);
                }

                // Search for files in other directories
                foreach (var overlay in _settings.DirectoryOverlays)
                {
                    var path = Path.Combine(overlay, fileName);
                    FindFilesWin32(path, results);
                }

                if (_archiveFiles.ContainsKey(key))
                {
                    var index = _archiveFiles[key];
                    results.Add(ArchiveInfoToFindData(_extractor.ArchiveFileData[index]));
                }
                else if (key.Contains("*"))
                {
                    var regex = new Regex(WildcardToRegex(NormalizeFileName(key)));

                    foreach (var entry in _archiveFiles)
                    {
                        if (regex.IsMatch(entry.Key))
                        {
                            var archiveFileInfo = _extractor.ArchiveFileData[entry.Value];
                            results.Add(ArchiveInfoToFindData(archiveFileInfo));
#if TRACE
                            Console.WriteLine("Adding match from archive: " + archiveFileInfo.FileName);
#endif
                        }
                    }
                }
            }

            FindFilesWin32(fileName, results);

            if (results.Count == 0)
            {
                return(Win32Api.InvalidHandle);
            }

            var handle = new IntPtr(1);
            while (_activeSearches.ContainsKey(handle))
            {
                handle = IntPtrUtil.Add(handle, 1);
            }

            var search = new ActiveSearch(results);
            _activeSearches[handle] = search;

            search.Iterator.MoveNext();
            Marshal.StructureToPtr(search.Iterator.Current, findFileDataPtr, false);

            return(handle);
        }