Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


[.net] [Advanced c#] Native DLL image import reading


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
No replies to this topic

#1 RenZimE   Members   -  Reputation: 128

Like
0Likes
Like

Posted 16 August 2006 - 04:15 PM

i know some people are interested in these topics, but its hard to find places where i feel comfortable posting items like these. as in the wrong hands could be used to exploit other applications. but anyway people have been asking me and have asked from time to time about checking the imports section of there applications dll's for changes. and i thought i would contribute to the forum by posting an example of doing this with in c# so that it might help some one next time they want to do some thing similar. any comments on this are welcome infact i encourage it. these files are fairly bug free. Examples only. (if you want to try this code you will have to compile with unsafe code enabled) (EDIT Updated Program.cs) - posted wrong version originaly File Name = "Interop.cs"
using System;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Security;

namespace PEHeaderTest
{
    [StructLayout(LayoutKind.Explicit)]
    public unsafe struct IMAGE_IMPORT_BY_NAME
    {
        [FieldOffset(0)]
        public ushort Hint;
        [FieldOffset(2)]
        public fixed char Name[1];
    } 

    [StructLayout(LayoutKind.Explicit)]
    public struct IMAGE_IMPORT_DESCRIPTOR
    {
        #region union 
        /// <summary>
        /// CSharp doesnt really support unions, but they can be emulated by a field offset 0
        /// </summary>

        [FieldOffset(0)]
        public uint Characteristics;            // 0 for terminating null import descriptor
        [FieldOffset(0)]
        public uint OriginalFirstThunk;         // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
        #endregion

        [FieldOffset(4)]
        public uint TimeDateStamp;                                                
        [FieldOffset(8)]
        public uint ForwarderChain;                 
        [FieldOffset(12)]
        public uint Name;
        [FieldOffset(16)]
        public uint FirstThunk; 
    }
    
    [StructLayout(LayoutKind.Explicit)]
    public struct THUNK_DATA
    {
        [FieldOffset(0)]
        public  uint ForwarderString;      // PBYTE 
        [FieldOffset(4)]
        public  uint Function;             // PDWORD
        [FieldOffset(8)]
        public  uint Ordinal;
        [FieldOffset(12)]
        public  uint AddressOfData;        // PIMAGE_IMPORT_BY_NAME
    }

    public unsafe class Interop
    {
        #region Public Constants
        public static readonly ushort IMAGE_DIRECTORY_ENTRY_IMPORT = 1; 
        #endregion
        #region Private Constants
        #region CallingConvention CALLING_CONVENTION
        /// <summary>
        ///     Specifies the calling convention.
        /// </summary>
        /// <remarks>
        ///     Specifies <see cref="CallingConvention.Winapi" /> for Windows to 
        ///     indicate that the default should be used.
        /// </remarks>
        private const CallingConvention CALLING_CONVENTION = CallingConvention.Winapi;
        #endregion CallingConvention CALLING_CONVENTION
        #region IMPORT DLL FUNCTIONS
        private const string KERNEL_DLL = "kernel32";
        private const string DBGHELP_DLL = "Dbghelp";
        #endregion
        #endregion Private Constants

        [DllImport(KERNEL_DLL, CallingConvention = CALLING_CONVENTION, EntryPoint = "GetModuleHandleA"), SuppressUnmanagedCodeSecurity]
        public static extern void* GetModuleHandleA(/*IN*/ char* lpModuleName);

        [DllImport(KERNEL_DLL, CallingConvention = CALLING_CONVENTION, EntryPoint = "GetModuleHandleW"), SuppressUnmanagedCodeSecurity]
        public static extern void* GetModuleHandleW(/*IN*/ char* lpModuleName);

        [DllImport(KERNEL_DLL,CallingConvention = CALLING_CONVENTION,EntryPoint = "IsBadReadPtr"),SuppressUnmanagedCodeSecurity]
        public static extern bool IsBadReadPtr(void* lpBase,uint ucb);

        [DllImport(DBGHELP_DLL, CallingConvention = CALLING_CONVENTION, EntryPoint = "ImageDirectoryEntryToData"), SuppressUnmanagedCodeSecurity]
        public static extern void* ImageDirectoryEntryToData(void* Base,bool MappedAsImage,ushort DirectoryEntry,out uint Size );

        
    }
}



File Name = "Program.cs"
using System;
using System.Text;
using System.Runtime.InteropServices;

namespace PEHeaderTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("This is just a sample app to demonstrate reading");
            Console.WriteLine("the imports section of a native module in c#");
            Console.WriteLine("as i have had lots of people saying you cant do this");
            Console.WriteLine("in the language");
            
            unsafe
            {
                // using mscoree.dll as an example as it doesnt export any thing
                // so nothing shows up if you use your own module.
                // and the only none delayload in mscoree.dll is the Kernel32.dll
                fixed (char* pszModule = "mscoree.dll")
                {
                    void* hMod = Interop.GetModuleHandleW(pszModule);
                    uint size = 0;
                    uint BaseAddress = (uint)hMod;

                    if (hMod != null)
                    {
                        Console.WriteLine("Got handle");

                        // try and get the Imports of Kernel32
                        IMAGE_IMPORT_DESCRIPTOR* pIID = (IMAGE_IMPORT_DESCRIPTOR*)Interop.ImageDirectoryEntryToData((void*)hMod, true,Interop.IMAGE_DIRECTORY_ENTRY_IMPORT, out size);
                        if (pIID != null)
                        {
                            Console.WriteLine("Got Image Import Descriptor");
                            while (!Interop.IsBadReadPtr((void*)pIID->OriginalFirstThunk,(uint)size))
                            {
                                try
                                {
                                    char* szName = (char*)(BaseAddress + pIID->Name);
                                    string name = Marshal.PtrToStringAnsi((IntPtr)szName);
                                    Console.WriteLine("pIID->Name = {0} BaseAddress - {1}", name,(uint)BaseAddress);

                                    THUNK_DATA* pThunkOrg = (THUNK_DATA*)(BaseAddress + pIID->OriginalFirstThunk);

                                    while (!Interop.IsBadReadPtr((void*)pThunkOrg->AddressOfData,4U))
                                    {
                                        char* szImportName;
                                        uint Ord;

                                        if ((pThunkOrg->Ordinal & 0x80000000) > 0)
                                        {
                                            Ord = pThunkOrg->Ordinal & 0xffff;
                                            Console.WriteLine("imports ({0}).Ordinal{1} - Address: {2}", name, Ord, pThunkOrg->Function);
                                        }
                                        else
                                        {
                                            IMAGE_IMPORT_BY_NAME* pIBN = (IMAGE_IMPORT_BY_NAME*)(BaseAddress + pThunkOrg->AddressOfData);

                                            if (!Interop.IsBadReadPtr((void*)pIBN, (uint)sizeof(IMAGE_IMPORT_BY_NAME)))
                                            {
                                                Ord = pIBN->Hint;
                                                szImportName = (char*)pIBN->Name;
                                                string sImportName = Marshal.PtrToStringAnsi((IntPtr)szImportName); // yes i know i am a lazy ass
                                                Console.WriteLine("imports ({0}).{1}@{2} - Address: {3}", name, sImportName, Ord,pThunkOrg->Function);
                                            }
                                            else
                                            {
                                                Console.WriteLine("Bad ReadPtr Detected or EOF on Imports");
                                                break;
                                            }
                                        }

                                        pThunkOrg++;
                                    }
                                }
                                catch (AccessViolationException e)
                                {
                                    Console.WriteLine("An Access violation occured\n"+
                                                      "this seems to suggest the end of the imports section\n");
                                    Console.WriteLine(e);
                                }

                                pIID++;
                            }

                        }

                    }                    
                }
            }
            
            Console.WriteLine("Press Any Key To Continue......");
            Console.ReadKey();
        }
    }
}



[Edited by - RenZimE on August 16, 2006 10:39:40 PM]

Sponsor:



Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS