wraithdu Posted November 25, 2008 Share Posted November 25, 2008 (edited) UPDATE 12/7/08: Bah, this method is broken by UPX, so it's pretty useless. Use Ward's UDF instead (now compatible with Vista) -http://www.autoitscript.com/forum/index.php?showtopic=77463Example -#include <MemoryDll.au3> #include <WinAPI.au3> $l = DllCall("kernel32.dll", "ptr", "GetProcAddress", "ptr", _WinApi_GetModuleHandle("user32.dll"), "str", "LockWorkStation") $l = $l[0] MemoryFuncCall("int", $l) MemoryFuncExit() Edited December 7, 2008 by wraithdu Link to comment Share on other sites More sharing options...
monoceres Posted November 25, 2008 Share Posted November 25, 2008 Great to see my functions already being used I guess I can use this as well for my D3D development Broken link? PM me and I'll send you the file! Link to comment Share on other sites More sharing options...
wraithdu Posted November 25, 2008 Author Share Posted November 25, 2008 (edited) Quick update for better type handling. Seems Execute() can handle variables just fine, so no sense is messing with Eval(). @monoceres If you're gonna write something so cool, it's bound to be exploited Edited November 25, 2008 by wraithdu Link to comment Share on other sites More sharing options...
wraithdu Posted November 25, 2008 Author Share Posted November 25, 2008 One more thing to add, this UDF creates and destroys the DllCallback and sets / resets the hook on each func call to avoid the need for an OnAutoItExit() function. Depending on your implementation, it might make more sense to take it apart a bit so some of these things are only done when absolutely necessary. Link to comment Share on other sites More sharing options...
monoceres Posted November 25, 2008 Share Posted November 25, 2008 (edited) One more thing to add, this UDF creates and destroys the DllCallback and sets / resets the hook on each func call to avoid the need for an OnAutoItExit() function. Depending on your implementation, it might make more sense to take it apart a bit so some of these things are only done when absolutely necessary.Good point. One thing you can do in the UDF is to find some way to only call _AddHookApi once each time the script runs and use _ChangeHookApi with the hook "handle" instead since it's hundreds times faster. Edited November 25, 2008 by monoceres Broken link? PM me and I'll send you the file! Link to comment Share on other sites More sharing options...
wraithdu Posted November 25, 2008 Author Share Posted November 25, 2008 Good idea. Done. I modified your _AddHookApi() function to be able to return only the hook structure so I can do just what you suggested. Then I call it once at the top and make it a global struct so I can use _ChangeHookApi() in _DllCallPtr(). Link to comment Share on other sites More sharing options...
wraithdu Posted November 25, 2008 Author Share Posted November 25, 2008 (edited) I was unhappy, so I rewrote some things In an effort to optimize the process, I modularized it. It is now broken down into the following functions, which include some better error checking - _DllCallPtr_Init() - initialization code _DllCallPtr_SetHook() - sets the GetProcAddress hook _DllCallPtr() - calls the function; will call _Init() and _SetHook() if not already done _DllCallPtr_UnSetHook() - unsets the GetProcAddress hook to return to normal functionality _DllCallPtr_Free() - frees the callback and kernel32 handle; will call _UnSetHook() if the hook is set I also slightly changed some of the HookApi functions to fit better with the overall structure - _AddHookApi() -> _HookApi_Get() Returns the hook structure for the given module / function. _ChangeHookApi() -> _HookApi_Set() Sets the hook The absolute minimum that must be done to use the UDF is - _DllCallPtr(); initializes and sets the hook if needed, then calls the function _DllCallPtr_Free(); unsets the hook if needed, and frees the resources @monoceres I hope you don't mind the changes, they just made more logical sense for the way I have the UDF set up. Edited November 25, 2008 by wraithdu Link to comment Share on other sites More sharing options...
wraithdu Posted December 3, 2008 Author Share Posted December 3, 2008 Updated, see first post. Link to comment Share on other sites More sharing options...
Christos Posted December 3, 2008 Share Posted December 3, 2008 It's working on Windows2000 Workstation and Server, XP and Vista. But why is this not working on Server2003 and Server 2008?! I get in the SciTE console this code 0x773DDD0D for the first example and this >Exit code: -1073741819 for the second example. After I have compiled the second example it's displaying the GUI and the msgbox but the "hide taskbar button" checkbox is doing nothing. Any idea how to get it working on the servers or how to find out what is wrong? Link to comment Share on other sites More sharing options...
monoceres Posted December 3, 2008 Share Posted December 3, 2008 It's working on Windows2000 Workstation and Server, XP and Vista. But why is this not working on Server2003 and Server 2008?!I get in the SciTE console this code 0x773DDD0D for the first example and this >Exit code: -1073741819 for the second example. After I have compiled the second example it's displaying the GUI and the msgbox but the "hide taskbar button" checkbox is doing nothing.Any idea how to get it working on the servers or how to find out what is wrong?Does the same hold true for my entire UDF (which this udf builts upon)?Oh and the Server editions aren't x64 are they? Broken link? PM me and I'll send you the file! Link to comment Share on other sites More sharing options...
Christos Posted December 3, 2008 Share Posted December 3, 2008 @monoceres I use 32bit server editions. I will try tomorrow your UDF. I discovered the same problem here http://www.autoitscript.com/forum/index.ph...55120&st=49 Link to comment Share on other sites More sharing options...
wraithdu Posted December 4, 2008 Author Share Posted December 4, 2008 (edited) I wonder if it's an issue with the DllCallback functions? That's about all the 2 UDFs have in common. Edited December 4, 2008 by wraithdu Link to comment Share on other sites More sharing options...
Christos Posted December 4, 2008 Share Posted December 4, 2008 LOL .... DEP was preventing the execution. I did some tests on the 2003/2008 Servers. The example below is working without deactivating DEP (I have use monoceres UDF and one of his examples) But it's only working if you use it with F5 in SciTE, It´s not working if you compile it (deactivated DEP). The Examples of wraithdu are working only if you deactivate DEP, and only if you used with F5 in SciTE. expandcollapse popup;~ #include <apihook.au3> #include <winapi.au3> Global $IMAGE_DIRECTORY_ENTRY_IMPORT = 1 Global $PAGE_READWRITE = 0x04 Global $IMAGE_IMPORT_DESCRIPTOR = "dword DUMMYUNIONNAME;dword TimeDateStamp;dword ForwarderChain;dword Name;dword FirstThunk" Global $IMAGE_THUNK_DATA = "dword u1" Global $MEMORY_BASIC_INFORMATION = "ptr BaseAddress;ptr AllocationBase;ptr AllocationProtect;ulong RegionSize;dword State;dword Protect;dword Type;" $GetProcAddress=DllCallbackRegister("GetProcAddress","ptr","ptr;ptr") $GetProcAddressPtr=DllCallbackGetPtr($GetProcAddress) $virtualprotect=_GetProcAddress(_WinAPI_GetModuleHandle("Kernel32.dll"), "VirtualProtect") $LockWorkStation=_GetProcAddress(_WinAPI_GetModuleHandle("user32.dll"),"LockWorkStation") $hook = _AddHookApi("Kernel32.dll", "GetProcAddress", $GetProcAddressPtr) DllCall("kernel32.dll","int",String($LockWorkStation)) Func GetProcAddress($ptr,$str) $string = DllStructCreate("char[255]", $str) if DllStructGetData($string,1)="VirtualProtect" Then Return $virtualprotect Elseif DllStructGetData($string,1)="VirtualQuery" Then Return $virtualquery Else Return DllStructGetData($string,1) EndIf Return 0 EndFunc Func _AddHookApi($ModuleName, $FunctionName, $NewProcAddress) ; Get base address of our app $hInstance = _WinAPI_GetModuleHandle(0) ;; Get module of the module that the function resides in $Module = _WinAPI_GetModuleHandle($ModuleName) ; Get the original function address $call = DllCall("Kernel32.dll", "ptr", "GetProcAddress", "ptr", $Module, "str", $FunctionName) $OrigAddress = $call[0] ;; Get the address of the Import directory $call = DllCall("Dbghelp.dll", "ptr", "ImageDirectoryEntryToData", "ptr", $hInstance, "int", 1, "ushort", $IMAGE_DIRECTORY_ENTRY_IMPORT, "ulong*", "") $ptrtoiid = $call[0] ; Create a struct from the pointer $iid = DllStructCreate($IMAGE_IMPORT_DESCRIPTOR, $ptrtoiid) ;; Loop through all loaded modules. While DllStructGetData($iid, "Name") ; get the name... $str = DllStructCreate("char[255]", $hInstance + DllStructGetData($iid, "Name")) ; If the name matches, we've found what we're looking for. If DllStructGetData($str, 1) = $ModuleName Then ExitLoop ; Move to the next directory item $ptrtoiid += DllStructGetSize($iid) $iid = DllStructCreate($IMAGE_IMPORT_DESCRIPTOR, $ptrtoiid) WEnd $ptrtoitd = $hInstance + DllStructGetData($iid, "FirstThunk") $itd = DllStructCreate($IMAGE_THUNK_DATA, $ptrtoitd) While DllStructGetData($itd, 1) ; We have found where the original address is stored If DllStructGetData($itd, 1) = $OrigAddress Then ;; Prepare the memory for writing $mbi = DllStructCreate($MEMORY_BASIC_INFORMATION) DllCall("Kernel32.dll", "ulong", "VirtualQuery", "ptr", DllStructGetPtr($itd, 1), "ptr", DllStructGetPtr($mbi), "ulong", DllStructGetSize($mbi)) DllCall("Kernel32.dll", "int", "VirtualProtect", "ptr", DllStructGetData($mbi, "BaseAddress"), "ulong", DllStructGetData($mbi, "RegionSize"), "dword", $PAGE_READWRITE, "ptr", DllStructGetPtr($mbi, "Protect")) ;; Here's where the magic happens DllStructSetData($itd, 1, $NewProcAddress) $randomdword = DllStructCreate("dword") DllCall("Kernel32.dll", "int", "VirtualProtect", "ptr", DllStructGetData($mbi, "BaseAddress"), "ulong", DllStructGetData($mbi, "RegionSize"), _ "dword", DllStructGetPtr($mbi, "Protect"), "ptr", DllStructGetPtr($randomdword, 1)) ExitLoop EndIf $ptrtoitd += DllStructGetSize($itd) $itd = DllStructCreate($IMAGE_THUNK_DATA, $ptrtoitd) WEnd Return $itd EndFunc ;==>_AddHookApi Func _GetProcAddress($hModule, $FunctionName) $call = DllCall("Kernel32.dll", "ptr", "GetProcAddress", "ptr", $hModule, "str", $FunctionName) Return $call[0] EndFunc ;==>_GetProcAddress Func _ChangeHookApi($ITDSTRUCT, $NewProc) ;; Prepare the memory for writing $mbi = DllStructCreate($MEMORY_BASIC_INFORMATION) DllCall("Kernel32.dll", "ulong", "VirtualQuery", "ptr", DllStructGetPtr($ITDSTRUCT, 1), "ptr", DllStructGetPtr($mbi), "ulong", DllStructGetSize($mbi)) DllCall("Kernel32.dll", "int", "VirtualProtect", "ptr", DllStructGetData($mbi, "BaseAddress"), "ulong", DllStructGetData($mbi, "RegionSize"), "dword", $PAGE_READWRITE, "ptr", DllStructGetPtr($mbi, "Protect")) ;; Here's where the magic happens DllStructSetData($ITDSTRUCT, 1, $NewProc) $randomdword = DllStructCreate("dword") DllCall("Kernel32.dll", "int", "VirtualProtect", "ptr", DllStructGetData($mbi, "BaseAddress"), "ulong", DllStructGetData($mbi, "RegionSize"), _ "dword", DllStructGetPtr($mbi, "Protect"), "ptr", DllStructGetPtr($randomdword, 1)) EndFunc ;==>_ChangeHookApi Link to comment Share on other sites More sharing options...
ProgAndy Posted December 4, 2008 Share Posted December 4, 2008 @Christos: could you check this one too: http://www.autoitscript.com/forum/index.ph...st&p=599174 ? I'd like to know if this will work with DEP *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 Link to comment Share on other sites More sharing options...
Christos Posted December 4, 2008 Share Posted December 4, 2008 @Christos: could you check this one too: http://www.autoitscript.com/forum/index.ph...st&p=599174 ? I'd like to know if this will work with DEP It's working with activated DEP, and is also working in compiled status. Link to comment Share on other sites More sharing options...
wraithdu Posted December 4, 2008 Author Share Posted December 4, 2008 Damn. I went back through monoceres' UDF with a compiled exe, and it's not calling the new _GetProcAddress callback, so the failure message is from DllCall() saying it can find the function in the DLL. I'm not sure what's up with this at the moment. Link to comment Share on other sites More sharing options...
wraithdu Posted December 4, 2008 Author Share Posted December 4, 2008 I can't figure it out. I did find a small unrelated bug though, which I've fixed in the original post. We'll have to wait and let monoceres weigh in on this. Link to comment Share on other sites More sharing options...
monoceres Posted December 4, 2008 Share Posted December 4, 2008 (edited) I can't figure it out. I did find a small unrelated bug though, which I've fixed in the original post. We'll have to wait and let monoceres weigh in on this.It's UPX's fault. I just tested and my sample fails when UPX is enabled but works as expected when turned off. My guess is that UPX itself uses some "tricks" (just like I do) on the PE format so it can use compression etc. Edited December 4, 2008 by monoceres Broken link? PM me and I'll send you the file! Link to comment Share on other sites More sharing options...
wraithdu Posted December 4, 2008 Author Share Posted December 4, 2008 LOL, cross-posted the answer Any thoughts on fixing it? Link to comment Share on other sites More sharing options...
monoceres Posted December 4, 2008 Share Posted December 4, 2008 (edited) LOL, cross-posted the answer Any thoughts on fixing it?Not really no. I added some debugging into the UDF and found out that the UDF successfully finds the address to GetProcAddress and overwrites it with our callback pointer. I also confirmed that autoit calls the real GetProcAddress as normal so clearly UPX does something to the AutoIt exe so it's not needing/using the Import directory anymore. Edited December 4, 2008 by monoceres Broken link? PM me and I'll send you the file! Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now