views:

108

answers:

0

I've successfully read a PE header from an unmanaged module loaded into memory by another process. What I'd like to do now is read the names of this module's exports. Basically, this is what I have so far (I've left out a majority of the PE parsing code, because I already know it works):

Extensions

public static IntPtr Increment(this IntPtr ptr, int amount)
{
    return new IntPtr(ptr.ToInt64() + amount);
}

public static T ToStruct<T>(this byte[] data)
{
    GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
    T result = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
    handle.Free();
    return result;
}

public static byte[] ReadBytes(this Process process, IntPtr baseAddress, int size)
{
    int bytesRead;
    byte[] bytes = new byte[size];
    Native.ReadProcessMemory(process.Handle, baseAddress, bytes, size, out bytesRead);
    return bytes;
}

public static T ReadStruct<T>(this Process process, IntPtr baseAddress)
{
    byte[] bytes = ReadBytes(process, baseAddress, Marshal.SizeOf(typeof(T)));
    return bytes.ToStruct<T>();
}

public static string ReadString(this Process process, IntPtr baseAddress, int size)
{
    byte[] bytes = ReadBytes(process, baseAddress, size);
    return Encoding.ASCII.GetString(bytes);
}

GetExports()

Native.IMAGE_DATA_DIRECTORY dataDirectory =
    NtHeaders.OptionalHeader.DataDirectory[Native.IMAGE_DIRECTORY_ENTRY_EXPORT];

if (dataDirectory.VirtualAddress > 0 && dataDirectory.Size > 0)
{
    Native.IMAGE_EXPORT_DIRECTORY exportDirectory =
        _process.ReadStruct<Native.IMAGE_EXPORT_DIRECTORY>(
            _baseAddress.Increment((int)dataDirectory.VirtualAddress));

    IntPtr namesAddress = _baseAddress.Increment((int)exportDirectory.AddressOfNames);
    IntPtr nameOrdinalsAddress = _baseAddress.Increment((int)exportDirectory.AddressOfNameOrdinals);
    IntPtr functionsAddress = _baseAddress.Increment((int)exportDirectory.AddressOfFunctions);

    for (int i = 0; i < exportDirectory.NumberOfFunctions; i++)
    {
        Console.WriteLine(_process.ReadString(namesAddress.Increment(i * 4), 64));
    }
}

When I run this, all I get is a pattern of double question marks, then completely random characters. I know the header is being read correctly, because the signatures are correct. The problem has to lie in the way that I'm iterating over the function list.