Register for your free account! | Forgot your password?

Go Back   elitepvpers > Coders Den > C/C++
You last visited: Today at 22:21

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



[Help] Detach DLL from Process

Discussion on [Help] Detach DLL from Process within the C/C++ forum part of the Coders Den category.

Reply
 
Old   #1
 
iCraziE's Avatar
 
elite*gold: 0
Join Date: Jan 2010
Posts: 456
Received Thanks: 218
[Help] Detach DLL from Process

Ok so I created my dll to inject.

But I have an issue. Since I have injected my dll, when ever the target process is open. I can't rename the dll, it says that the dll is open in the process.

What do I have to do to make it so that it will detach itself?

Here is my APIENTRY code.

Code:
BOOL APIENTRY DllMain(HMODULE hModule, DWORD _reason, LPVOID lpReserved)
{
	if(_reason == DLL_PROCESS_ATTACH)
	{
		CreateThread(0, 0x1000, &Main_Thread, 0, 0, NULL);
	}

	return TRUE;
}
PS. It is saying that the dll is open in the process, even if I don't inject it.

As long as the process is open, it will say its running in the process and cant be deleted or renamed etc.

Same result if I close the process and open it again. Also same after restart computer.

Please if anyone has a solution, i'd appreciate it
iCraziE is offline  
Old 03/02/2013, 09:08   #2
 
elite*gold: 5
Join Date: Sep 2006
Posts: 385
Received Thanks: 218
Simply clean everything up that you've done and call from inside the program.
Nightblizard is offline  
Old 03/02/2013, 12:34   #3
 
iCraziE's Avatar
 
elite*gold: 0
Join Date: Jan 2010
Posts: 456
Received Thanks: 218
Where would I declare Free Library, from what I see, it isnt safe to declare it in the DLLMain.

I also use an injector? Should I create my own injector and add the freelibrary function there?
iCraziE is offline  
Old 03/02/2013, 14:54   #4
 
elite*gold: 5
Join Date: Sep 2006
Posts: 385
Received Thanks: 218
Well, you shouldn't execute any code within DllMain to begin with (yea I know, kernel32 stuff is okay to some degree, but it is still bad practise).

What I've done in a library of mine is the following:
I've exported two functions (Start and End) inside the dll. My injector looks for these functions, injects the dll, recalculates the procedures addresses (injector space to the other programs space) and then calls Start.
Upon unloading I call "End" inside the process which cleans everything up and then I call FreeLibrary (via. CreateRemoteThread).

Works pretty well that way and isn't that hacky.

Some Code:
Code:
	void Injector::UnloadDll(Process const& process, Module const& dll)
	{
		//Loads the injected dll into the injector (LoadLibrary)
		auto lib = Module::FromLibrary(Process::GetCurrentProcess(), dll.GetPath());
		//Where is the function that does all the cleanup?
		UINT_PTR endAddr = lib.GetProcAddress("End");
		//We have to recalculate the procedures address, since it isn't guaranteed to be at the same location inside the other process
		auto diff = reinterpret_cast<UINT_PTR>(dll.GetHandle()) - reinterpret_cast<UINT_PTR>(lib.GetHandle());
		endAddr = endAddr + diff;
		//Call End
		auto thread = process.CreateRemoteThread(endAddr);
		thread.WaitForSingleObject();
		//After everything got cleaned up, unload the dll
		auto thread2 = process.CreateRemoteThread(reinterpret_cast<UINT_PTR>(FreeLibrary), reinterpret_cast<LPVOID>(dll.GetHandle()));
		thread2.WaitForSingleObject();
	}
Calling "Start" works pretty much the same way, except that I don't call FreeLibrary (for obvious reasons). This won't work, however, if you do scary stuff inside DllMain!
Nightblizard is offline  
Thanks
1 User
Old 03/02/2013, 15:50   #5
 
iCraziE's Avatar
 
elite*gold: 0
Join Date: Jan 2010
Posts: 456
Received Thanks: 218
I havent really done anything inside dll main. Here is my dll main..

Code:
BOOL APIENTRY DllMain(HMODULE hModule, DWORD _reason, LPVOID lpReserved)
{
	if(_reason == DLL_PROCESS_ATTACH)
	{
		CreateThread(0, 0x1000, &Main_Thread, 0, 0, NULL);
	}

	return TRUE;
}
iCraziE is offline  
Old 03/02/2013, 17:15   #6
 
elite*gold: 5
Join Date: Sep 2006
Posts: 385
Received Thanks: 218
That's already too much for my way of doing things.
Nightblizard is offline  
Old 03/02/2013, 17:43   #7
 
iCraziE's Avatar
 
elite*gold: 0
Join Date: Jan 2010
Posts: 456
Received Thanks: 218
So what do you suggest?

I create my own Injector, and also include your code snippet to unload the dll.

But what should happen with DLLMain?
iCraziE is offline  
Old 03/02/2013, 18:20   #8


 
MrSm!th's Avatar
 
elite*gold: 7110
Join Date: Jun 2009
Posts: 28,902
Received Thanks: 25,407
You leave it empty.
Without Nightblizard's includes that snippet won't work btw
MrSm!th is offline  
Old 03/03/2013, 03:01   #9
 
Master674b's Avatar
 
elite*gold: 0
Join Date: Dec 2012
Posts: 255
Received Thanks: 110
Quote:
Originally Posted by Nightblizard View Post
Well, you shouldn't execute any code within DllMain to begin with (yea I know, kernel32 stuff is okay to some degree, but it is still bad practise).

What I've done in a library of mine is the following:
I've exported two functions (Start and End) inside the dll. My injector looks for these functions, injects the dll, recalculates the procedures addresses (injector space to the other programs space) and then calls Start.
Upon unloading I call "End" inside the process which cleans everything up and then I call FreeLibrary (via. CreateRemoteThread).

Works pretty well that way and isn't that hacky.
You should also use DONT_RESOLVE_DLL_REFERENCES when loading a dll only for export lookups if you're not doing that already. Also you don't need to do a module lookup because you can simply get the return value of LoadLibrary in the remote process with GetExitCodeThread =)

Some Code:
Code:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;

#if WIN32
using DWORD_PTR = System.UInt32;
#elif WIN64
using DWORD_PTR = System.UInt64;
#endif

namespace supdoodcoolparty
{
    public static class Memory
    {

        #region Constants
        private const int MaxStringLength = 512;
        #endregion

        #region Helper functions
        public static uint Reverse( uint uData )
        {
            byte[] bNewBytes = new byte[4];
            bNewBytes[0] = (byte)( uData << 24 >> 24 );
            bNewBytes[1] = (byte)( uData << 16 >> 24 );
            bNewBytes[2] = (byte)( uData << 08 >> 24 );
            bNewBytes[3] = (byte)( uData << 00 >> 24 );

            return BitConverter.ToUInt32( bNewBytes, 0 );
        }
        #endregion

        #region Open/Close
        public static IntPtr OpenProcess( int nProcessId )
        {
            return WinAPI.OpenProcess( ProcessAccessFlags.CreateThread | ProcessAccessFlags.VMOperation |
                                       ProcessAccessFlags.VMRead | ProcessAccessFlags.VMWrite |
                                       ProcessAccessFlags.QueryInformation, false, nProcessId );
        }

        public static IntPtr OpenThread( int nThreadId )
        {
            return WinAPI.OpenThread( ThreadAccessFlags.AllAccess, false, (uint) nThreadId );
        }
        #endregion

        #region Write
        public static unsafe bool Write<T>( IntPtr hProcess, DWORD_PTR dwAddress, T tData )
        {
            Type tParamType = typeof( T );
            if( tParamType == typeof( string ) )
                return Write( hProcess, dwAddress, (string)(object) tData, CharSet.Ansi );
            
            byte[] bBuffer;
            uint uTypeSize = (uint) Marshal.SizeOf( typeof( T ) );

            if( tParamType == typeof( bool ) )
                bBuffer = BitConverter.GetBytes( (bool)(object) tData );
            else if( tParamType == typeof( byte ) )
                bBuffer = BitConverter.GetBytes( (byte)(object) tData );
            else if( tParamType == typeof( char ) )
                bBuffer = BitConverter.GetBytes( (char)(object) tData );
            else if( tParamType == typeof( short ) )
                bBuffer = BitConverter.GetBytes( (short)(object) tData );
            else if( tParamType == typeof( ushort ) )
                bBuffer = BitConverter.GetBytes( (ushort)(object) tData );
            else if( tParamType == typeof( int ) )
                bBuffer = BitConverter.GetBytes( (int)(object) tData );
            else if( tParamType == typeof( uint ) )
                bBuffer = BitConverter.GetBytes( (uint)(object) tData );
            else if( tParamType == typeof( long ) )
                bBuffer = BitConverter.GetBytes( (long)(object) tData );
            else if( tParamType == typeof( ulong ) )
                bBuffer = BitConverter.GetBytes( (ulong)(object) tData );
            else if( tParamType == typeof( float ) )
                bBuffer = BitConverter.GetBytes( (float)(object) tData );
            else if( tParamType == typeof( double ) )
                bBuffer = BitConverter.GetBytes( (double)(object) tData );
            else
                throw new Exception( "Memory.Write Exception: Invalid type!" );

            bool bResult = false;
            uint dwBytesWritten = 0;

            fixed( byte* bMemoryBuffer = bBuffer )
                bResult = WinAPI.WriteProcessMemory( hProcess, dwAddress, (IntPtr) bMemoryBuffer, uTypeSize, out dwBytesWritten );

            return bResult && dwBytesWritten == uTypeSize;
        }

        public static unsafe bool Write( IntPtr hProcess, DWORD_PTR dwAddress, string sString, CharSet sCharacterSet )
        {
            byte[] bBuffer;
            if( sCharacterSet == CharSet.None || sCharacterSet == CharSet.Ansi )
                bBuffer = Encoding.ASCII.GetBytes( sString );
            else
                bBuffer = Encoding.Unicode.GetBytes( sString );

            bool bResult = false;
            uint dwBytesWritten = 0;
            uint dwStringLength = (uint) bBuffer.Length;

            fixed( byte* bMemoryBuffer = bBuffer )
                bResult = WinAPI.WriteProcessMemory( hProcess, dwAddress, (IntPtr) bMemoryBuffer, dwStringLength, out dwBytesWritten );

            return bResult && dwBytesWritten == dwStringLength;
        }
        #endregion

        #region Read
        public static T Read<T>( IntPtr hProcess, DWORD_PTR dwAddress )
        {
            if( typeof( T ) == typeof( string ) )
                return (T)(object) Read( hProcess, dwAddress, CharSet.Ansi );

            IntPtr lpBuffer = IntPtr.Zero;
            bool bResult = false;
            uint dwSize = 0;
            uint dwBytesRead = 0;

            try
            {
                dwSize = (uint) Marshal.SizeOf( typeof( T ) );
                lpBuffer = Marshal.AllocHGlobal( (int) dwSize );
                
                bResult = WinAPI.ReadProcessMemory( hProcess, dwAddress, lpBuffer, dwSize, out dwBytesRead );

                if( bResult && dwBytesRead == dwSize )
                    return (T) Marshal.PtrToStructure( lpBuffer, typeof( T ) );
            }
            catch { }

            if( lpBuffer != IntPtr.Zero )
                Marshal.FreeHGlobal( lpBuffer );

            return default( T );
        }

        public static string Read( IntPtr hProcess, DWORD_PTR dwAddress, CharSet sCharacterSet )
        {
            if( sCharacterSet == CharSet.None || sCharacterSet == CharSet.Ansi )
            {
                // One byte character set
                uint uCurrentPosition = 0;
                uint uMaxLength = MaxStringLength;

                byte[] bStringBuffer = new byte[uMaxLength];
                byte bCurrentByte = Read<byte>( hProcess, dwAddress );

                while( bCurrentByte != 0 && uCurrentPosition < uMaxLength )
                {
                    bStringBuffer[uCurrentPosition++] = bCurrentByte;
                    bCurrentByte = Read<byte>( hProcess, dwAddress + uCurrentPosition );
                }

                return Encoding.ASCII.GetString( bStringBuffer );
            }
            else
            {
                // Two byte character set
                uint uCurrentPosition = 0;
                uint uMaxLength = MaxStringLength * 2;

                byte[] bStringBuffer = new byte[uMaxLength];
                byte bFirstByte = Read<byte>( hProcess, dwAddress );
                byte bSecondByte = Read<byte>( hProcess, dwAddress + 1 );

                while( bFirstByte != 0 && bSecondByte != 0 && uCurrentPosition < uMaxLength )
                {
                    bStringBuffer[uCurrentPosition++] = bFirstByte;
                    bStringBuffer[uCurrentPosition++] = bSecondByte;

                    bFirstByte = Read<byte>( hProcess, dwAddress + uCurrentPosition );
                    bSecondByte = Read<byte>( hProcess, dwAddress + uCurrentPosition + 1 );
                }

                return Encoding.Unicode.GetString( bStringBuffer );
            }
        }

        public static byte[] Read( IntPtr hProcess, DWORD_PTR dwAddress, uint dwLength )
        {
            byte[] bBuffer = new byte[dwLength];
            IntPtr lpBuffer = IntPtr.Zero;
            bool bResult = false;
            uint dwBytesRead = 0;

            try
            {
                lpBuffer = Marshal.AllocHGlobal( (int) dwLength );
                bResult = WinAPI.ReadProcessMemory( hProcess, dwAddress, lpBuffer, dwLength, out dwBytesRead );

                if( bResult && dwBytesRead == dwLength )
                    Marshal.Copy( lpBuffer, bBuffer, 0, (int) dwLength );
            }
            catch { }

            if( lpBuffer != IntPtr.Zero )
                Marshal.FreeHGlobal( lpBuffer );

            return bBuffer;
        }
        #endregion

        #region Allocate/Free
        public static DWORD_PTR Allocate( IntPtr hProcess, uint dwSize )
        {
            return WinAPI.VirtualAllocEx( hProcess, 0, dwSize,
                    AllocationType.Commit | AllocationType.Reserve, MemoryProtection.ExecuteReadWrite );
        }

        public static bool Free( IntPtr hProcess, DWORD_PTR dwAddress )
        {
            return WinAPI.VirtualFreeEx( hProcess, dwAddress,
                    0, FreeType.Release );
        }
        #endregion

        #region DLL Injection/Loading
        public static IntPtr LoadLibraryEx( IntPtr hProcess, string sModule )
        {
            uint dwResult = 0;
            IntPtr hKernel32 = WinAPI.GetModuleHandleW( "kernel32.dll" );
            if( hKernel32 != IntPtr.Zero )
            {
                DWORD_PTR dwLoadLibrary = WinAPI.GetProcAddress( hKernel32, "LoadLibraryW" );
                if( dwLoadLibrary != 0 )
                {
                    byte[] bBuffer = Encoding.Unicode.GetBytes( sModule );
                    uint dwBufferLength = (uint) bBuffer.Length + 2;
                    DWORD_PTR dwCodeCave = Memory.Allocate( hProcess, dwBufferLength );
                    if( dwCodeCave != 0 )
                    {
                        if( Memory.Write( hProcess, dwCodeCave, sModule, CharSet.Unicode ) )
                        {
                            uint dwThreadId = 0;
                            IntPtr hThread = WinAPI.CreateRemoteThread( hProcess, 0, 0,
                                    dwLoadLibrary, dwCodeCave, 0, out dwThreadId );

                            if( hThread != IntPtr.Zero )
                            {
                                uint dwWaitResult = WinAPI.WaitForSingleObject( hThread, 0xFFFFFFFF );
                                if( dwWaitResult == 0 )
                                    WinAPI.GetExitCodeThread( hThread, out dwResult );

                                WinAPI.CloseHandle( hThread );
                            }
                        }

                        Memory.Free( hProcess, dwCodeCave );
                    }
                }
            }
            
            return (IntPtr) dwResult;
        }

        public static IntPtr Import( string sModule )
        {
            return WinAPI.LoadLibraryW( sModule );
        }
        #endregion

        #region DLL Ejection/Unloading
        public static bool FreeLibraryEx( IntPtr hProcess, IntPtr hRemoteModule )
        {
            uint dwResult = 0;
            IntPtr hKernel32 = WinAPI.GetModuleHandleW( "kernel32.dll" );
            if( hKernel32 != IntPtr.Zero )
            {
                DWORD_PTR dwFreeLibrary = WinAPI.GetProcAddress( hKernel32, "FreeLibrary" );
                if( dwFreeLibrary != 0 )
                {
                    uint dwThreadId = 0;
                    IntPtr hThread = WinAPI.CreateRemoteThread(hProcess, 0, 0,
                            dwFreeLibrary, (DWORD_PTR) hRemoteModule, 0, out dwThreadId );

                    if( hThread != IntPtr.Zero )
                    {
                        uint dwWaitResult = WinAPI.WaitForSingleObject( hThread, 0xFFFFFFFF );
                        if( dwWaitResult == 0 )
                            WinAPI.GetExitCodeThread( hThread, out dwResult );

                        WinAPI.CloseHandle( hThread );
                    }
                }
            }

            return dwResult != 0;
        }
        #endregion

        #region Internal calls
        public static string Call( IntPtr hProcess, CallingConvention cCallingConvention, CharSet cCharacterSet, DWORD_PTR dwAddress, params object[] oParams )
        {
            return Read( hProcess, Call<DWORD_PTR>( hProcess, cCallingConvention, dwAddress, oParams ), cCharacterSet );
        }

        public static T Call<T>( IntPtr hProcess, CallingConvention cCallingConvention, DWORD_PTR dwAddress, params object[] oParams )
        {
            Type tManagedType = typeof( T );

            DWORD_PTR dwExecuteCave = Allocate( hProcess, 1024 );
            DWORD_PTR dwReturnCave = Allocate( hProcess, 12 );
            uint uByteIndex = 0;

            List<object> lsParams = new List<object>( oParams );

            if( cCallingConvention == CallingConvention.ThisCall ||
                cCallingConvention == CallingConvention.FastCall ||
                cCallingConvention == CallingConvention.StdCall )
            {
                // MOV ECX, lsParams[0]
                Write<byte>( hProcess, dwExecuteCave + uByteIndex++, 0xB9 );
                Write<DWORD_PTR>( hProcess, dwExecuteCave + uByteIndex, Reverse( (DWORD_PTR) lsParams[0] ) );
                uByteIndex += sizeof( DWORD_PTR );
                lsParams.RemoveAt( 0 );
            }

            lsParams.Reverse();
            foreach( object oParam in lsParams )
            {
                // PUSH oParam
                Type tParamType = oParam.GetType();
                int nSize = Marshal.SizeOf( tParamType );

                if( nSize == 1 )
                    Write<byte>( hProcess, dwExecuteCave + uByteIndex++, 0x6A );
                else
                    Write<byte>( hProcess, dwExecuteCave + uByteIndex++, 0x68 );

                if( tParamType == typeof( bool ) )
                     Write<bool>( hProcess, dwExecuteCave + uByteIndex, (bool) oParam );
                else if( tParamType == typeof( byte ) )
                    Write<byte>( hProcess, dwExecuteCave + uByteIndex, (byte) oParam );
                else if( tParamType == typeof( char ) )
                    Write<char>( hProcess, dwExecuteCave + uByteIndex, (char) oParam );
                else if( tParamType == typeof( short ) )
                    Write<short>( hProcess, dwExecuteCave + uByteIndex, (short) oParam );
                else if( tParamType == typeof( ushort ) )
                    Write<ushort>( hProcess, dwExecuteCave + uByteIndex, (ushort) oParam );
                else if( tParamType == typeof( int ) )
                    Write<int>( hProcess, dwExecuteCave + uByteIndex, (int) oParam );
                else if( tParamType == typeof( uint ) )
                    Write<uint>( hProcess, dwExecuteCave + uByteIndex, (uint) oParam );
                else if( tParamType == typeof( long ) )
                    Write<long>( hProcess, dwExecuteCave + uByteIndex, (long) oParam );
                else if( tParamType == typeof( ulong ) )
                    Write<ulong>( hProcess, dwExecuteCave + uByteIndex, (ulong) oParam );
                else if( tParamType == typeof( float ) )
                    Write<float>( hProcess, dwExecuteCave + uByteIndex, (float) oParam );
                else if( tParamType == typeof( double ) )
                    Write<double>( hProcess, dwExecuteCave + uByteIndex, (double) oParam );

                uByteIndex += (uint) nSize;
            }

            // MOV EAX, dwAddress
            Write<byte>( hProcess, dwExecuteCave + uByteIndex++, 0xB8 );
            Write<DWORD_PTR>( hProcess, dwExecuteCave + uByteIndex, Reverse( dwAddress ) );
            uByteIndex += sizeof( DWORD_PTR );

            // CALL EAX
            Write<byte>( hProcess, dwExecuteCave + uByteIndex++, 0xFF );
            Write<byte>( hProcess, dwExecuteCave + uByteIndex++, 0xD0 );

            if( cCallingConvention == CallingConvention.Cdecl )
            {
                // ADD ESP, lsParams.Count * 4
                Write<byte>( hProcess, dwExecuteCave + uByteIndex++, 0x83 );
                Write<byte>( hProcess, dwExecuteCave + uByteIndex++, 0xC4 );
                Write<byte>( hProcess, dwExecuteCave + uByteIndex++, (byte)( lsParams.Count * 4 ) );
            }

            if( tManagedType == typeof( float ) )
            {
                // FSTP DWORD [dwReturnCave]
                Write<byte>( hProcess, dwExecuteCave + uByteIndex++, 0xD9 );
                Write<byte>( hProcess, dwExecuteCave + uByteIndex++, 0x1D );
                Write<DWORD_PTR>( hProcess, dwExecuteCave + uByteIndex, Reverse( dwReturnCave ) );
                uByteIndex += sizeof( DWORD_PTR );
            }
            else
            {
                // MOV DWORD [dwReturnCave], EAX
                Write<byte>( hProcess, dwExecuteCave + uByteIndex++, 0xA3 );
                Write<DWORD_PTR>( hProcess, dwExecuteCave + uByteIndex, Reverse( dwReturnCave ) );
                uByteIndex += sizeof( DWORD_PTR );

                // MOV DWORD [dwReturnCave + 4], EDX
                Write<byte>( hProcess, dwExecuteCave + uByteIndex++, 0x89 );
                Write<byte>( hProcess, dwExecuteCave + uByteIndex++, 0x15 );
                Write<DWORD_PTR>( hProcess, dwExecuteCave + uByteIndex, Reverse( dwReturnCave + 4 ) );
                uByteIndex += sizeof( DWORD_PTR );
            }

            // RET
            Write<byte>( hProcess, dwExecuteCave + uByteIndex, 0xC3 );

            uint dwThreadId = 0;
            IntPtr hThread = WinAPI.CreateRemoteThread( hProcess, 0, 0,
                    dwExecuteCave, 0, 0, out dwThreadId );

            if( hThread == IntPtr.Zero )
                throw new Exception( "Memory.Call Exception: Could not call function!" );
            
            WinAPI.WaitForSingleObject( hThread, 0xFFFFFFFF );
            WinAPI.CloseHandle( hThread );

            T tReturn = default( T );
            if( tManagedType == typeof( bool ) )
                tReturn = (T) (object) Read<bool>( hProcess, dwReturnCave );
            if( tManagedType == typeof( byte ) )
                tReturn = (T) (object) Read<byte>( hProcess, dwReturnCave );
            if( tManagedType == typeof( char ) )
                tReturn = (T) (object) Read<char>( hProcess, dwReturnCave );
            if( tManagedType == typeof( short ) )
                tReturn = (T) (object) Read<short>( hProcess, dwReturnCave );
            if( tManagedType == typeof( ushort ) )
                tReturn = (T) (object) Read<ushort>( hProcess, dwReturnCave );
            if( tManagedType == typeof( int ) )
                tReturn = (T) (object) Read<int>( hProcess, dwReturnCave );
            if( tManagedType == typeof( uint ) )
                tReturn = (T) (object) Read<uint>( hProcess, dwReturnCave );
            if( tManagedType == typeof( long ) )
                tReturn = (T) (object) Read<long>( hProcess, dwReturnCave );
            if( tManagedType == typeof( ulong ) )
                tReturn = (T) (object) Read<ulong>( hProcess, dwReturnCave );
            if( tManagedType == typeof( float ) )
                tReturn = (T) (object) Read<float>( hProcess, dwReturnCave );
            if( tManagedType == typeof( double ) )
                tReturn = (T) (object) Read<double>( hProcess, Read<DWORD_PTR>( hProcess, dwReturnCave ) );

            Free( hProcess, dwReturnCave );
            Free( hProcess, dwExecuteCave );

            return tReturn;
        }
        #endregion

        #region External Calls
        public static T CallExport<T>( IntPtr hProcess, IntPtr hImportModule, IntPtr hExportModule, string sExportFunction, uint dwParam = 0 )
        {
            uint dwExitCode = 0;
            DWORD_PTR dwAddress = WinAPI.GetProcAddress( hImportModule, sExportFunction );
            if( dwAddress == 0 )
                throw new Exception( "Memory.CallExport Exception: Export function was not found in import module!" );

            uint dwThreadId = 0;
            dwAddress = dwAddress - (DWORD_PTR) hImportModule + (DWORD_PTR) hExportModule;
            IntPtr hThread = WinAPI.CreateRemoteThread( hProcess, 0, 0,
                    dwAddress, dwParam, 0, out dwThreadId );

            if( hThread == IntPtr.Zero )
                throw new Exception( "Memory.CallExport Exception: Could not call export function!" );

            uint uWaitResult = WinAPI.WaitForSingleObject( hThread, 0xFFFFFFFF );
            if( uWaitResult == 0 )
                WinAPI.GetExitCodeThread( hThread, out dwExitCode );

            WinAPI.CloseHandle( hThread );
            if( uWaitResult != 0 )
                throw new Exception( "Memory.CallExport Exception: Export function never returned!" );

            if( typeof( T ) == typeof( string ) )
                return (T)(object) Read( hProcess, (DWORD_PTR) dwExitCode, CharSet.Ansi );
            else if( typeof( T ) == typeof( byte ) )
                return (T)(object)(byte) dwExitCode;
            else if( typeof( T ) == typeof( char ) )
                return (T)(object)(char) dwExitCode;
            else if( typeof( T ) == typeof( short ) )
                return (T)(object)(short) dwExitCode;
            else if( typeof( T ) == typeof( ushort ) )
                return (T)(object)(ushort) dwExitCode;
            else if( typeof( T ) == typeof( int ) )
                return (T)(object)(int) dwExitCode;
            else if( typeof( T ) == typeof( uint ) )
                return (T)(object)(uint) dwExitCode;
            else if( typeof( T ) == typeof( long ) )
                return (T)(object)(long) dwExitCode;
            else if( typeof( T ) == typeof( ulong ) )
                return (T)(object)(ulong) dwExitCode;
            else if( typeof( T ) == typeof( bool ) )
                return (T)(object) Convert.ToBoolean( dwExitCode );

            throw new Exception( "Memory.CallExport Exception: Could not identify return type!" );
        }

        public static void CallExport( IntPtr hProcess, IntPtr hImportModule, IntPtr hExportModule, string sExportFunction, uint dwParam = 0 )
        {
            DWORD_PTR dwAddress = WinAPI.GetProcAddress( hImportModule, sExportFunction );
            if( dwAddress == 0 )
                throw new Exception( "Memory.CallExport Exception: Export function was not found in import module!" );

            uint dwThreadId = 0;
            dwAddress = dwAddress - (DWORD_PTR) hImportModule + (DWORD_PTR) hExportModule;
            IntPtr hThread = WinAPI.CreateRemoteThread( hProcess, 0, 0,
                    dwAddress, dwParam, 0, out dwThreadId );

            if( hThread == IntPtr.Zero )
                throw new Exception( "Memory.CallExport Exception: Could not call export function!" );

            WinAPI.CloseHandle( hThread );
        }
        #endregion

    }
}
Master674b is offline  
Old 03/03/2013, 13:04   #10
 
elite*gold: 5
Join Date: Sep 2006
Posts: 385
Received Thanks: 218
Quote:
Originally Posted by MrSm!th View Post
You leave it empty.
Without Nightblizard's includes that snippet won't work btw
Yea, of course not as this is just a snippet from my library to show what I've meant. But it should be pretty obious what's going on under the hood, since my functions names are pretty close to those from the WinAPI.

Quote:
Originally Posted by Master674b View Post
You should also use DONT_RESOLVE_DLL_REFERENCES when loading a dll only for export lookups if you're not doing that already.
Nah, I guess it is pretty obvious that I don't want you to do anything inside DllMain. And loading a module without setting said flag will simply fuck your program up, if still decide to do so and put all your Code inside DllMain.
And afterall my library is open source so you can change it, if you really want to do hacky shit.

Quote:
Originally Posted by Master674b View Post
Also you don't need to do a module lookup because you can simply get the return value of LoadLibrary in the remote process with GetExitCodeThread =)
I'm not so sure about that. Is it guaranteed that your Dll will be loaded < 0x100000000 inside an x64 environment? I don't know for sure, so I'll stick with the safe way.
Nightblizard is offline  
Old 03/03/2013, 15:42   #11
 
link's Avatar
 
elite*gold: 1
Join Date: Jul 2005
Posts: 553
Received Thanks: 454
Quote:
Originally Posted by Nightblizard View Post
I'm not so sure about that. Is it guaranteed that your Dll will be loaded < 0x100000000 inside an x64 environment? I don't know for sure, so I'll stick with the safe way. ;)
Only if your Dll is a x86 binary, otherwise your Dll might get any imagebase if its default one is taken and GetExitCodeThread would only return the lower dword of it. Means your code is both x64- and x86-compliant.

DONT_RESOLVE_DLL_REFERENCES will make the Dll-loader not resolve any imports, so you won't be able to call any code inside your Dll unless you do the resolving yourself.

Btw. you could also call FreeLibraryAndExitThread from within your Dll and implement some quit-switch with it.

@Nightblizard:
There is nothing wrong with creating a thread inside DllMain, it will work.
It's just not recommended as putting code into DllMain may tempt to use more and more code in DllMain, even communication, loading or synchronizing stuff which might result in a deadlock or race conditions, if you're careless.
If you know what you're doing and what you can and cannot do, there won't be a problem.

Also if you clean up your stuff in End by creating it in a thread without pausing/synchronizing the rest, you could create race conditions depending on what you're doing in your End.
link is offline  
Old 03/03/2013, 15:47   #12
 
iCraziE's Avatar
 
elite*gold: 0
Join Date: Jan 2010
Posts: 456
Received Thanks: 218
this is starting to go a little too far over my head. i think i willl try a different approach to get what i need done
thanks for all your help anyway.
iCraziE is offline  
Old 03/04/2013, 11:54   #13
 
Mi4uric3's Avatar
 
elite*gold: 405
Join Date: Dec 2007
Posts: 6,615
Received Thanks: 6,358
What about ""? You can call this from your DLL, make sure all other threads which belong to the dll have exited before
Mi4uric3 is offline  
Reply




All times are GMT +1. The time now is 22:21.


Powered by vBulletin®
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2025 elitepvpers All Rights Reserved.