Jump to content

Recommended Posts

  • 1 month later...
Posted

Hi Ward, Hope you don't mind this post but I did a little rewrite on your older version so it could be used with new dllcalladdress and make quite a bit smaller. Plus with new static vars, I was able to make it all into one function with no globals so easy to pop into any script. The 3 other short functions for public are just wrappers. And not that your newest version isnt awesome and very educational, I just don't use that many 64bit dlls. As always thanks for your incredible udfs and knowledge Ive learned from them.
 
MemoryDll_Short.au3
 

(Note: Opcodes removed for preview)

_Example()

Func _Example()

    Local $MD5Dll = 'Opcode removed for preview'

    Local $String = "The quick brown fox jumps over the lazy dog"
    Local $Digest = DllStructCreate("byte[16]")

    Local $hMD5 = MemoryDllOpen($MD5Dll)
    Local $iMD5 = MemoryDllGetFuncAddress($hMD5, 'md5')
    DllCallAddress("str", $iMD5, "str", $String, "uint", StringLen($String), "struct*", $Digest)
    MemoryDllClose($hMD5)

    ConsoleWrite('MD5 Hash = ' & DllStructGetData($Digest, 1) & @LF)

EndFunc   ;==>_Example


; ============================================================================================================================
;  Functions : MemoryDllOpen(), MemoryDllGetFuncAddress(), MemoryDllClose()
;  Purpose   : Embedding DLL In Scripts to Call Directly From Memory
;  Author    : Ward
;  Modified  : Brian J Christy (Beege) - Wrapper Functions
; ============================================================================================================================
Func MemoryDllOpen($DllBinary)
    Local $Call = __MemoryDllCore(0, $DllBinary)
    Return SetError(@error, 0, $Call)
EndFunc   ;==>MemoryDllOpen

Func MemoryDllGetFuncAddress($hModule, $sFuncName)
    Local $Call = __MemoryDllCore(1, $hModule, $sFuncName)
    Return SetError(@error, 0, $Call)
EndFunc   ;==>MemoryDllGetFuncAddress

Func MemoryDllClose($hModule)
    __MemoryDllCore(2, $hModule)
EndFunc   ;==>MemoryDllClose

Func __MemoryDllCore($iCall, ByRef $Mod_Bin, $sFuncName = 0)

    Local Static $_MDCodeBuffer, $_MDLoadLibrary, $_MDGetFuncAddress, $_MDFreeLibrary, $GetProcAddress, $LoadLibraryA, $fDllInit = False

    If Not $fDllInit Then

        If @AutoItX64 Then Exit(MsgBox(16, 'Error - x64', 'x64 Not Supported! ' & @LF & @LF & 'Download newest version for x64 support'))

        Local $Opcode = 'Opcode removed for preview'

        $_MDCodeBuffer = DllStructCreate("byte[" & BinaryLen($Opcode) & "]")
        DllCall("kernel32.dll", "bool", "VirtualProtect", "struct*", $_MDCodeBuffer, "dword_ptr", DllStructGetSize($_MDCodeBuffer), "dword", 0x00000040, "dword*", 0) ; PAGE_EXECUTE_READWRITE

        DllStructSetData($_MDCodeBuffer, 1, $Opcode)

        Local $pMDCodeBuffer = DllStructGetPtr($_MDCodeBuffer)
        $_MDLoadLibrary = $pMDCodeBuffer + (StringInStr($Opcode, "59585A51") - 1) / 2 - 1
        $_MDGetFuncAddress = $pMDCodeBuffer + (StringInStr($Opcode, "5990585A51") - 1) / 2 - 1
        $_MDFreeLibrary = $pMDCodeBuffer + (StringInStr($Opcode, "5A585250") - 1) / 2 - 1

        Local $Ret = DllCall("kernel32.dll", "hwnd", "LoadLibraryA", "str", "kernel32.dll")
        $GetProcAddress = DllCall("kernel32.dll", "uint", "GetProcAddress", "hwnd", $Ret[0], "str", "GetProcAddress")
        $LoadLibraryA = DllCall("kernel32.dll", "uint", "GetProcAddress", "hwnd", $Ret[0], "str", "LoadLibraryA")

        $fDllInit = True
    EndIf

    Switch $iCall
        Case 0; DllOpen
            Local $DllBuffer = DllStructCreate("byte[" & BinaryLen($Mod_Bin) & "]")
            DllCall("kernel32.dll", "bool", "VirtualProtect", "struct*", $DllBuffer, "dword_ptr", DllStructGetSize($DllBuffer), "dword", 0x00000040, "dword*", 0) ; PAGE_EXECUTE_READWRITE
            DllStructSetData($DllBuffer, 1, $Mod_Bin)
            Local $Module = DllCallAddress('uint', $_MDLoadLibrary, "uint", $LoadLibraryA[0], "uint", $GetProcAddress[0], "struct*", $DllBuffer)
            If $Module[0] = 0 Then Return SetError(1, 0, 0)
            Return $Module[0]
        Case 1; MemoryDllGetFuncAddress
            Local $Address = DllCallAddress("uint", $_MDGetFuncAddress, "uint", $Mod_Bin, "str", $sFuncName)
            If $Address[0] = 0 Then Return SetError(1, 0, 0)
            Return $Address[0]
        Case 2; DllClose
            Return DllCallAddress('none', $_MDFreeLibrary, "uint", $Mod_Bin)
    EndSwitch

EndFunc   ;==>__MemoryDllCore
; ============================================================================================================================
  • 4 months later...
Posted (edited)

Hi.

I'm trying to use your MemoryDll.au3.

This is the guide in the 1st post of this thread:

; -------------------------------------------------------------
;
; Step 1: Try to use the DLLs in the normal method (by DllCall)
;
; -------------------------------------------------------------

$String = "The quick brown fox jumps over the lazy dog"
$Digest = DllStructCreate("byte[16]")
DllCall("md5.dll", "str", "md5", "str", $String, "uint", StringLen($String), "ptr", DllStructGetPtr($Digest))
$Hash = DllStructGetData($Digest, 1)
$Digest = 0
MsgBox(0, 'MD5 Hash', $Hash)


; ----------------------------------------------------------------------------
;
; Step 2: Use MemoryDllGen.au3 to convert the DLL to script form and paste it.
;
; ----------------------------------------------------------------------------

Dim $DllBinary = ''; this line is too long to omit, check the attachment

; --------------------------------------------------------------------------------
;
; Step 3: Replace DllCall to MemoryDllCall, and use $DllBinary instead of dll name
;
; --------------------------------------------------------------------------------

#Include "MemoryDll.au3"
MemoryDllInit()

$String = "The quick brown fox jumps over the lazy dog"
$Digest = DllStructCreate("byte[16]")
MemoryDllCall($DllBinary, "str", "md5", "str", $String, "uint", StringLen($String), "ptr", DllStructGetPtr($Digest))
$Hash = DllStructGetData($Digest, 1)
$Digest = 0
MsgBox(0, 'MD5 Hash', $Hash)

MemoryDllExit()


; -------------------------------------------------------------------------
;
; Step 4: Finally, you have the functions in Pure AutoIt Scirpt. Have fun !
;
; -------------------------------------------------------------------------

Step 1: Use DLLCall() to use the original DLL file - success.

Step 2: Create the AU3 converted File of "my" DLL - success. That one was included in the main script, the variable "$MyDLL" is available in the main script.

 

Step 3: Use "MemoryDLLCall()" instead of "DLLCall()", this doesn't work.

Your 3-Step-examle shows to use the function "MemoryDllInit()", which doesn't seem to exist in MemoryDLL.AU3 file?

Hm...

Could you give a brief example, how to make use a AU3 converted DLL, that was created using your "MemoryDllGen.AU3"?

I couldn't get this even from the other files included in your ZIP archive:

MemoryDll.au3
MemoryDllGen.au3
MemoryDllTest.au3
MemoryFuncCallTest.au3
MemorySQLite.au3
MemorySQLiteTest.au3

Thanks, Rudi.

Edited by rudi

Earth is flat, pigs can fly, and Nuclear Power is SAFE!

  • 2 months later...
Posted

Hi.

I'm trying to use your MemoryDll.au3.

This is the guide in the 1st post of this thread:

; -------------------------------------------------------------
;
; Step 1: Try to use the DLLs in the normal method (by DllCall)
;
; -------------------------------------------------------------

$String = "The quick brown fox jumps over the lazy dog"
$Digest = DllStructCreate("byte[16]")
DllCall("md5.dll", "str", "md5", "str", $String, "uint", StringLen($String), "ptr", DllStructGetPtr($Digest))
$Hash = DllStructGetData($Digest, 1)
$Digest = 0
MsgBox(0, 'MD5 Hash', $Hash)


; ----------------------------------------------------------------------------
;
; Step 2: Use MemoryDllGen.au3 to convert the DLL to script form and paste it.
;
; ----------------------------------------------------------------------------

Dim $DllBinary = ''; this line is too long to omit, check the attachment

; --------------------------------------------------------------------------------
;
; Step 3: Replace DllCall to MemoryDllCall, and use $DllBinary instead of dll name
;
; --------------------------------------------------------------------------------

#Include "MemoryDll.au3"
MemoryDllInit()

$String = "The quick brown fox jumps over the lazy dog"
$Digest = DllStructCreate("byte[16]")
MemoryDllCall($DllBinary, "str", "md5", "str", $String, "uint", StringLen($String), "ptr", DllStructGetPtr($Digest))
$Hash = DllStructGetData($Digest, 1)
$Digest = 0
MsgBox(0, 'MD5 Hash', $Hash)

MemoryDllExit()


; -------------------------------------------------------------------------
;
; Step 4: Finally, you have the functions in Pure AutoIt Scirpt. Have fun !
;
; -------------------------------------------------------------------------

Step 1: Use DLLCall() to use the original DLL file - success.

Step 2: Create the AU3 converted File of "my" DLL - success. That one was included in the main script, the variable "$MyDLL" is available in the main script.

 

Step 3: Use "MemoryDLLCall()" instead of "DLLCall()", this doesn't work.

Your 3-Step-examle shows to use the function "MemoryDllInit()", which doesn't seem to exist in MemoryDLL.AU3 file?

Hm...

Could you give a brief example, how to make use a AU3 converted DLL, that was created using your "MemoryDllGen.AU3"?

I couldn't get this even from the other files included in your ZIP archive:

MemoryDll.au3
MemoryDllGen.au3
MemoryDllTest.au3
MemoryFuncCallTest.au3
MemorySQLite.au3
MemorySQLiteTest.au3

Thanks, Rudi.

I believe that function is called internally

What is what? What is what.

  • 2 weeks later...
Posted

@Ward, Beege: any idea why the DLL used in >Water Effects (waterctrl.dll) is crashing when I try to use it from the memory?

 

Br,

UEZ

No clue right now but its crashing for me as well at memorydllopen. Ill see if I can get a deeper look.
  • 9 months later...
Posted

2015/01/08 Update Note:

* Update the machine code version. Both x86 and x64 DLL are supported.

* TLS callback are supported.

* Remove all MemoryFuncXXX() related functions. Use build-in DllCallAddress instead.

* Add MemoryDllLoadString(), MemoryDllLoadResource() 

* Add _WinAPI_MemoryFindResource(), _WinAPI_MemoryFindResourceEx(), _WinAPI_MemorySizeOfResource(), _WinAPI_MemoryLoadResource(), _WinAPI_MemoryLoadString(), _WinAPI_MemoryLoadStringEx()

* Using BinaryCall.au3 to loading the machine code.

新版 _ArrayAdd 的白痴作者,不管是誰,去死一死好了

 

  • 1 year later...
Posted (edited)

First off all, this looks exactly like the solution to a problem of mine.
Thank you Ward, for building this.

Great to see, that so many different opinions were flowing into a single include.

i am unable to download the attachments from the first post. i am eager to test the include for use in one of my projects.

Does someone have the current version to re-upload it somewhere else, for me to get it?

thanks in advance.

Knut J.

Edited by KnutJ

rsRVpv.gif

Posted

@Ward: If you have any objection to my posting this, just let me know, and I'll take it down again a.s.a.p.

@KnutJ:  download link for the MemoryDll version dated 2015.01.08, with BinaryCall version dated 2014.07.24

 

Posted (edited)

Thank you RTFC,

could you (or someone else) by any chance upload  "MemoryDllGen.AU3" (or / and the rest of the original package) which was mentioned as a tool to generate the correctly converted representation of a given .dll - file?

Thanks in advance

Edited by KnutJ

rsRVpv.gif

Posted (edited)
; ============================================================================================================================
;  File     : MemoryDllGen.au3
;  Purpose  : Convert DLL files to HEX binary data
;  Author   : Ward
; ============================================================================================================================

Dim $VarName = StringStripWS(InputBox("MemoryDllGen", "Select a name of variable:", "DllBinary"), 3)
If $VarName = "" Then Exit

Dim $DllName = FileOpenDialog("Open dll file", @ScriptDir, "DLL file (*.*)")
If $DllName = "" Then Exit

Dim $Handle = FileOpen($DllName, 16)
Dim $DllBinary = FileRead($Handle)
FileClose($Handle)

Dim $LineLen = 2050
Dim $DllString = String($DllBinary)

Dim $Script = "Dim $" & $VarName & " = '" & StringLeft($DllString, $LineLen) & "'" & @CRLF
$DllString = StringTrimLeft($DllString, $LineLen)

While StringLen($DllString) > $LineLen
    $Script &= "    $" & $VarName & " &= '" & StringLeft($DllString, $LineLen) & "'" & @CRLF
    $DllString = StringTrimLeft($DllString, $LineLen)
WEnd

If StringLen($DllString) <> 0 Then $Script &= "    $" & $VarName & " &= '" & $DllString & "'" & @CRLF
ClipPut($Script)


MsgBox(64, 'MemoryDll Generator', 'The result is in the clipboard, you can paste it to your script.')
; ============================================================================================================================
;  File     : MemoryDllTest.au3
;  Purpose  : Test MemoryDll In Both x86 And X64 Mode
;  Author   : Ward
; ============================================================================================================================

#Include "MemoryDll.au3"

Main()

Func Main()
    If @AutoItX64 Then
        Local $InstallDir = RegRead("HKLM\SOFTWARE\Wow6432Node\AutoIt v3\AutoIt", "InstallDir")
        Local $DllPath = $InstallDir & "\AutoItX\AutoItX3_x64.dll"
    Else
        Local $InstallDir = RegRead("HKLM\SOFTWARE\AutoIt v3\AutoIt", "InstallDir")
        Local $DllPath = $InstallDir & "\AutoItX\AutoItX3.dll"
    EndIf
    If Not FileExists($DllPath) Then
        MsgBox(16, "Error", "Cannot Find AutoItX DLL !")
        Return
    EndIf

    Local $DllFile = FileOpen($DllPath, 16)
    Local $DllBin = FileRead($DllFile)
    FileClose($DllFile)

    Local $DllHandle = MemoryDllOpen($DllBin)

    MemoryDllCall($DllHandle, "none", "AU3_ToolTip", "wstr", "Hello, world!" & @CRLF & "AutoIt is best, MemoryDll.au3 is easy and fun", "long", @DesktopWidth / 3, "long", @DesktopHeight / 3)
    MemoryDllCall($DllHandle, "none", "AU3_Sleep", "long", 5000)
    MemoryDllCall($DllHandle, "none", "AU3_ToolTip", "wstr", "", "long", 0, "long", 0)

    MemoryDllClose($DllHandle)
EndFunc
; ============================================================================================================================
;  File     : MemorydllTest.au3
;  Purpose  : Demonstration for MemoryFuncCall
;  Author   : ProgAndy
;  Modifier : Ward
; ============================================================================================================================

#Include "MemoryDll.au3"

Func TestFunc($Param)
    MsgBox(0, 'TestFunc', $Param)
    Return 23
EndFunc

Dim $CallBack = DllCallbackRegister("TestFunc", "int", "str")
Dim $Ret = MemoryFuncCall("int", DllCallbackGetPtr($CallBack), "str", "A string as parameter")
MsgBox(0, 'The return', $Ret[0])
DllCallbackFree($CallBack)

 

Edited by RTFC
Posted (edited)

Hello@all,

i tried this udf for some days now, but i am always facing the same problem when trying to call a cdecl-call .dll

Been testing under Win7Pro64bit and Win2k12R2(always 64bit) - the .dll is a 32bit cdecl-call-type-dll

if i run the autoit script, no matter if the .dll is a part of the source, definded as

$variable = '0x ...'

or if i load it via

$hfile=fileopen($File,16)
$variable=fileread($hfile)

every time i hit 

Local $DllHandle = MemoryDllOpen($variable)

i just get

AutoIt3.exe ended.rc:-1073741819

 

i would love to post a complete reproducer, but this specific .dll is not intended to be released to the public. therefore trying to call it from memory directly.

There is a post, where full compatibility is stated regarding stdcall & c-call .dll files.

To me, it looks like this isn't completely true at this moment in time.

anyone out there having an idea, where i could look at, modify something, need more input?

Edited by KnutJ

rsRVpv.gif

Posted

Stepped over to another solution - which works for me.

 

No need for MemoryDll.au3 anymore - solution of TranceXX works without opcodes, pure autoit, maintainable and good looking.

rsRVpv.gif

  • 2 years later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...