Ward

Embed DLLs in script and call functions from memory (MemoryDll UDF)

75 posts in this topic

#1 ·  Posted (edited)

Thanks to Joachim Bauch's tutorial about Loading a DLL from memory.
Here comes the easiest way to run the codes written in other language.
All you need to do are make a DLL, convert it to HEX format, and embed into your script.

For now, only stdcall is supported (up to four parameters) (There is no limit now, see update note).
BTW, this script is only tested on Windows XP SP3. If you can run it in other systems, please let me know, thanks.

Demo how to use:
(this 3k md5.dll is written by myself and anyone is welcome to use it. But the machine code version of MD5 should be better choice in AutoIt)

; -------------------------------------------------------------
;
; 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 !
;
; -------------------------------------------------------------------------

MemoryDll.zip (4.67K)
Number of downloads: 253

08/08/03 Update Note:

  • Rearrange the return array of MemoryDllCall, now it's return should just like DllCall.
  • Add support to accept more than four parameters, but in this case, some return value will be destoryed.
  • Add a little Tutorial.

MemoryDll.zip (9.17K)
Number of downloads: 251


08/08/18 Update Note:

  • I finally found a perfect trick to call a function in memory. So this UDF now supports DLL functions in both stdcall and cdecl mode with any number of parameters. In theory, DllCall now can be fully replaced by MemoryDllCall.
  • There is a new func called MemoryFuncCall in this version. It is a new way to call a memory address. Compared to CallWindowProc (old method), MemoryFuncCall is flexible (supports cdecl, etc. ), but a bit slower.
  • There are also two new utility scripts in attachment. AESFile uses the dll downloaded from http://adeil.com. It encrypt/decrypt files by a key of 32, 48 or 64 bytes long. SHA2 is written by Brian Gladman and compiled to DLL by me. It generates SHA2 hash of 224, 256, 384, or 512 bits long.

    Thanks to -Ultima- and ProgAndy's suggestion.

MemoryDll.zip (50.27K)
Number of downloads: 441


08/12/06 Update Note:

  • Improves compatibility. Now MemoryDllCall should work better under Vista.
  • Example of AESFile and SHA512 are removed. Please see my other post about AES and Hashes.

MemoryDll.zip (8.95K)
Number of downloads: 1118


2010/10/18 Update Note:

  • Avoiding DEP issue.
  • Improves compatibility. Now BASS.DLL is supported.

MemoryDll.zip

2011/04/03 Update Note:

  • Rewritten all code in AutoIt. Now both x86 and x64 DLL are supported.
  • MemoryDllInit(), MemoryDllExit(), and old examples are removed.
  • Add new example, MemoryDll version of SQLite.au3.
  • Ps. I think old version are still good or even better when only used under x86 mode.
  • But this version support x64 and has better compatibility I guess.

MemoryDll.zip

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.

MemoryDll.zip

2015/01/23 Update Node:

  • Add ability to load a DLL that needs other DLLs. For example: libcurl.dll needs libeay32.dll and ssleay32.dll for https support. Now you can load all of them by MemoryDll UDF. Before this version, only libcurl.dll can loaded by MemoryDll, other files must store on the disk.
  • Add ability to call functions by ordinal value.
  • Add MemoryDllRun(). It run a EXE file from memory. Relocation table in EXE file is required. Most PE rebuilding tools remove the section to reduce the file size.
  • Add a script to demonstrate all the new features.
  • This version of MemoryDll can works together with BinaryCall UDF. Binary machine code can call functions in DLL loaded by MemoryDll.

 MemoryDll.zip

Edited by Ward
4 people like this

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

 

Share this post


Link to post
Share on other sites



This is cool... But the big prt is embedding the dll. I'm pretty sure a vast majority off the users here don't know how to do that.


[center][/center]Working on the next big thing.Currently Playing: Halo 4, League of LegendsXBL GT: iRememberYhslaw

Share this post


Link to post
Share on other sites

excellent !

can i know what compilator do you use to make dll ?

i use devcpp but i will throw it away since it makes me crazy with its no explicit messages and its huge exe or dll that it creates just for one function !!!


-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]

Share this post


Link to post
Share on other sites

excellent !

can i know what compilator do you use to make dll ?

i use devcpp but i will throw it away since it makes me crazy with its no explicit messages and its huge exe or dll that it creates just for one function !!!

I use Sphinx C--. The DLLs in the attachment are also written in C-- (including 3k md5.dll).

There is also the source of example.dll, you can see how sample it is.

By the way, if you use devcpp and get a huge exe or dll, maybe you forget to "strip" it.


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

 

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

it's strange.

with dev cpp i've a file of 6 ko after compiled.

I'm learning Sphink C-- and the result is a file of 1.5 Ko...

maybe i'm dooing something wrong with devcpp, tomorrox i'll try with vc++

sphink c-- is an amazing language. Thx for the information.

Edited by arcker

-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]

Share this post


Link to post
Share on other sites

it's strange.

with dev cpp i've a file of 6 ko after compiled.

I'm learning Sphink C-- and the result is a file of 1.5 Ko...

maybe i'm dooing something wrong with devcpp, tomorrox i'll try with vc++

do you if we can call winapi in sphink C-- ?

Compile without debug.

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Share this post


Link to post
Share on other sites

that's what i do. But the dll still weight 5.5ko.


-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]

Share this post


Link to post
Share on other sites

Quite interesting.


[center][u]WoW Machinima Tool[/u] (Tool for Machinima Artists) [/center]

Share this post


Link to post
Share on other sites

All you need to do are make a DLL, convert it to HEX format

if anyones interested heres a program i found that does that

HexConverter.rar

Share this post


Link to post
Share on other sites

if anyones interested heres a program i found that does that

Why not just use autoit to do the same thing?

Share this post


Link to post
Share on other sites

Why not just use autoit to do the same thing?

because i dont know how to

Share this post


Link to post
Share on other sites

$DllBinary = Hex(stringtobinary(fileread("yourdll.dll")))


-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]

Share this post


Link to post
Share on other sites

in the ZIP package, there is a generator included :P (MemoryDllGen.au3)


*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

@Ward: Perhaps you should create a function that accepts an array of parameters (2D?), then generates a single string representation of a DllCall() from that array to be passed to Execute()? It'd bypass the slightly awkward/unappealing Switch statement, would accept an arbitrary number of parameters, would require only one DllCall(), and would probably help with the return value thing (since Execute() would return whatever DllCall() returned, which would be an arbitrarily-sized array depending on the number of parameters dynamically passed to DllCall()).

It can be a separate function that people can choose to call manually, and then you can also wrap around the array/execute based function with your current MemoryDllCall() (generate an array based on the number of parameters, then pass into the array/execute version) for those users who prefer parameter list "identicalness" to DllCall() over unlimited parameter input (which should be the case for most users anyway).

Edited by -Ultima-

[ WinINet.au3 | Array.au3 (Optimized) | _UnixTimeParse() ]

Share this post


Link to post
Share on other sites

#15 ·  Posted (edited)

:P Never mind.... see next post.

Taking it a bit further, here is a simple script to help generate the $DllBinary variable from a source file.

Local $Source = FileOpenDialog("Open File to Inject", @ScriptDir, "All (*.*)")

If $Source = "" Then Exit

Local $Destination = FileSaveDialog("Save As AutoIt 3 File", @ScriptDir, "AutoIt 3 Script (*.AU3)")

If $Destination = "" Then Exit

Local $File = FileOpen($Destination, 2)

Local $DllBinary = Hex(StringToBinary(FileRead($Source)))

FileWriteLine($File, ';## This is a Dynamically Generated Script.')

FileWriteLine($File, ';## Source = ' & $Source)

FileWrite($File, @CRLF & @CRLF & 'Dim $DllBinary = "' & $DllBinary & '"')

FileClose($File)

Enjoy :P

Edited by Zinthose

--- TTFN

Share this post


Link to post
Share on other sites

#16 ·  Posted (edited)

As ProgAndy pointed out, there's already a script to do exactly almost exactly that, included in the ZIP file... And it's more technically correct by opening/reading the file in binary mode rather than reading the DLL as a string (though I suppose that isn't too important :P). What's more important is the fact that AutoIt doesn't accept arbitrarily-long lines, so simply writing the entire string to a file would fail for "large" DLLs -- the included script takes care of that.

Edited by -Ultima-

[ WinINet.au3 | Array.au3 (Optimized) | _UnixTimeParse() ]

Share this post


Link to post
Share on other sites

I suppose to declare all Globals on top of the Script and the test $_MDCodeBuffer this way:

If Not IsDllStruct($_MDCodeBuffer) Then MemoryDllInit()


*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites

#18 ·  Posted (edited)

With this UDF, it is finally possible to call ANY function with a pointer, just removed the module pointer ans changed from functionname to functionpointer

#include <MemoryDLL.au3>
;Author(s): Ward, modified: Prog@ndy

Func MemoryFuncCall($RetType, $FunctionPointer, $Type1 = "int", $Param1 = 0, $Type2 = "int", $Param2 = 0, $Type3 = "int", $Param3 = 0, $Type4 = "int", $Param4 = 0, $Type5 = "int", $Param5 = 0, _

$Type6 = "int", $Param6 = 0, $Type7 = "int", $Param7 = 0, $Type8 = "int", $Param8 = 0, $Type9 = "int", $Param9 = 0, $Type10 = "int", $Param10 = 0, _

$Type11 = "int", $Param11 = 0, $Type12 = "int", $Param12 = 0, $Type13 = "int", $Param13 = 0, $Type14 = "int", $Param14 = 0, $Type15 = "int", $Param15 = 0, _

$Type16 = "int", $Param16 = 0, $Type17 = "int", $Param17 = 0, $Type18 = "int", $Param18 = 0, $Type19 = "int", $Param19 = 0, $Type20 = "int", $Param20 = 0 )

Local $Ret

Local Const $MaxParams = 20

If (@NumParams < 2) Or (@NumParams > $MaxParams * 2 + 2) Or (Mod(@NumParams, 2) = 1) Then

SetError(2)

Return 0

EndIf

If Not IsDllStruct($_MDCodeBuffer) Then MemoryDllInit()



If $FunctionPointer = 0 Then

SetError(1)

Return 0

EndIf



Local $Ret[1] = [$FunctionPointer]



Switch @NumParams

Case 13 To $MaxParams * 2 + 2

Local $DllParams = (@NumParams - 3) / 2, $i, $PartRet

$Ret = DllCall("user32.dll", $RetType, "CallWindowProc", "ptr", DllStructGetPtr($_MDCodeBuffer) + $_MDWarpN, _

"uint", $Ret[0], _

"uint", $DllParams, _

$Type1, $Param1, _

$Type2, $Param2)



$Ret[1] = $Ret[4]

$Ret[2] = $Ret[5]

ReDim $Ret[3]



For $i = 3 To $DllParams Step 3

$PartRet = DllCall("user32.dll", $RetType, "CallWindowProc", "ptr", DllStructGetPtr($_MDCodeBuffer) + $_MDWarpN, _

"uint", 0, _

Eval('Type' & $i), Eval('Param' & $i), _

Eval('Type' & ($i+1)), Eval('Param' & ($i+1)), _

Eval('Type' & ($i+2)), Eval('Param' & ($i+2)))

ReDim $Ret[$i + 3]

$Ret[$i + 2] = $PartRet[5]

$Ret[$i + 1] = $PartRet[4]

$Ret[$i] = $PartRet[3]

Next

$Ret[0] = $PartRet[0]

ReDim $Ret[$DllParams + 1]



Case 10

$Ret = DllCall("user32.dll", $RetType, "CallWindowProc", "ptr", $Ret[0], _

$Type1, $Param1, _

$Type2, $Param2, _

$Type3, $Param3, _

$Type4, $Param4)

$Ret[1] = $Ret[2]

$Ret[2] = $Ret[3]

$Ret[3] = $Ret[4]

$Ret[4] = $Ret[5]

ReDim $Ret[5]



Case 8

$Ret = DllCall("user32.dll", $RetType, "CallWindowProc", "ptr", DllStructGetPtr($_MDCodeBuffer) + $_MDWarp3, _

"uint", $Ret[0], _

$Type1, $Param1, _

$Type2, $Param2, _

$Type3, $Param3)

$Ret[1] = $Ret[3]

$Ret[2] = $Ret[4]

$Ret[3] = $Ret[5]

ReDim $Ret[4]



Case 6

$Ret = DllCall("user32.dll", $RetType, "CallWindowProc", "ptr", DllStructGetPtr($_MDCodeBuffer) + $_MDWarp2, _

"int", 0, _

"uint", $Ret[0], _

$Type1, $Param1, _

$Type2, $Param2)

$Ret[1] = $Ret[4]

$Ret[2] = $Ret[5]

ReDim $Ret[3]



Case 4

$Ret = DllCall("user32.dll", $RetType, "CallWindowProc", "ptr", DllStructGetPtr($_MDCodeBuffer) + $_MDWarp1, _

"int", 0, _

"int", 0, _

"uint", $Ret[0], _

$Type1, $Param1)

$Ret[1] = $Ret[5]

ReDim $Ret[2]



Case 2

$Ret = DllCall("user32.dll", $RetType, "CallWindowProc", "ptr", DllStructGetPtr($_MDCodeBuffer) + $_MDWarp0, _

"int", 0, _

"int", 0, _

"int", 0, _

"int", $Ret[0])



ReDim $Ret[1]

EndSwitch



SetError(0)

Return $Ret

EndFunc

//Edit: Added function + example as attachment

Edited by Jos
Fixed formatting

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites

With this UDF, it is finally possible to call ANY function with a pointer, just removed the module pointer ans changed from functionname to functionpointer:

//Edit: Added function + example as attachment

Thanks to your idea. I wrote a all new "MemoryFuncCall" and added your example to my project. Now, it supports both stdcall and cdecl, accepts any number of parameters, and won't destroy the return value. Enjoy!


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

 

Share this post


Link to post
Share on other sites

#20 ·  Posted (edited)

I love you, I've been looking for a SHA512 function for several days now. I only found SHA256 (shadeep) but it used a external file, now I can use SHA512 too and the best thing of all, I don't have to use any external files anymore.

BTW as far as I know AES use 16, 20, 24, 28, or 32 characters as a key, your uses 32, 48 or 64 so I'm not sure it's the "real" AES, could be extended AES.

But nvm, no bigger deal, I can still use SkinnyWhiteGuys CryptoSuite for AES.

Edited by Pain

Share this post


Link to post
Share on other sites

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