how to dll Inject Topic is solved

Ask for help, how to use AHK_H, etc.
HotKeyIt
Posts: 1697
Joined: 29 Sep 2013, 18:35
Contact:

Re: how to dll Inject

24 Aug 2017, 16:26

The problem is that you don't change the GWL_WNDPROC back to pWndProcOld, so when dll exits the function is dead and obviously can't be executed.
Add following code before freeing the rThread variable and you will see it does not crash:

Code: Select all

vScript = ;continuation section
(
DllCall("SetWindowLong%vSfx%", Ptr,hWnd, Int,-4, Ptr,pWndProcOld, Ptr) ;GWL_WNDPROC := -4
)
rThread.Exec(vScript)
If you don't want to unload the dll, simply remove __Delete key in base or set it empty or set base empty before freeing rThread:
rThread.base.Remove("__Delete") or
rThread.base.__Delete:="" or
rThread.base:=""
User avatar
jeeswg
Posts: 5146
Joined: 19 Dec 2016, 01:58
Location: UK

Re: how to dll Inject

20 Sep 2017, 15:12

Thanks again for your help HotKeyIt.

I've written a variant of InjectAhkDll which does not require _Struct.ahk, this means that if you copy and paste the function to the bottom of your script, all you need to run it is the appropriate dll file.

Code: Select all

;[original version of InjectAhkDll]
;[SOLVED]get other process's working dir - Page 3 - Ask for Help - AutoHotkey Community
;https://autohotkey.com/board/topic/85304-solvedget-other-processs-working-dir/page-3#entry544650

;[get x64 and x32 versions of AutoHotkeyMini.dll]
;GitHub - HotKeyIt/ahkdll-v1-release: AutoHotkey_H v1 release
;https://github.com/HotKeyIt/ahkdll-v1-release

;by HotKeyIt (modified version by jeeswg to not require _Struct.ahk)
InjectAhkDll(PID,dll="AutoHotkey.dll",script=0)
{
	static PROCESS_ALL_ACCESS:=0x1F0FFF,MEM_COMMIT := 0x1000,MEM_RELEASE:=0x8000,PAGE_EXECUTE_READWRITE:=64
	,hKernel32:=DllCall("LoadLibrary","Str","kernel32.dll","PTR"),LoadLibraryA:=DllCall("GetProcAddress","PTR",hKernel32,"AStr","LoadLibraryA","PTR")
	,base:={__Call:"InjectAhkDll",__Delete:"InjectAhkDll"},FreeLibrary:=DllCall("GetProcAddress","PTR",hKernel32,"AStr","FreeLibrary","PTR")
	static TH32CS_SNAPMODULE:=0x00000008,INVALID_HANDLE_VALUE:=-1
	,MAX_PATH:=260,MAX_MODULE_NAME32:=255,ModuleName:="",init:=VarSetCapacity(ModuleName,MAX_PATH*(A_IsUnicode?2:1))

	if IsObject(PID)
	{
		if (dll!="Exec" && script)
			return DllCall("MessageBox","PTR",0,"Str","Only Exec method can be used here!","STR","Error","UInt",0)

		hProc := DllCall("OpenProcess", "UInt", PROCESS_ALL_ACCESS, "Int",0, "UInt", PID.PID,"PTR")
		if !hProc
			return DllCall("MessageBox","PTR",0,"Str","Could not open process for PID: " PID.PID,"STR","Error","UInt",0)

		if (!script) ; Free Library in remote process (object is being deleted)
		{
			; Terminate the thread in ahkdll
			hThread := DllCall("CreateRemoteThread", "PTR", hProc, "PTR", 0, "PTR", 0, "PTR", PID.ahkTerminate, "PTR", 0, "UInt", 0, "PTR", 0,"PTR")
			DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)
			,DllCall("CloseHandle", "PTR", hThread)

			; Free library in remote process
			hThread := DllCall("CreateRemoteThread", "PTR", hProc, "UInt", 0, "UInt", 0, "PTR", FreeLibrary, "PTR", PID.hModule, "UInt", 0, "UInt", 0,"PTR")
			DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)
			,DllCall("CloseHandle", "PTR", hThread),DllCall("CloseHandle", "PTR", hProc)
			return
		}

		nScriptLength := VarSetCapacity(nScript, (StrLen(script)+1)*(A_IsUnicode?2:1), 0)
		,StrPut(script,&nScript)

		; Reserve memory in remote process where our script will be saved
		if !pBufferRemote := DllCall("VirtualAllocEx", "Ptr", hProc, "Ptr", 0, "PTR", nScriptLength, "UInt", MEM_COMMIT, "UInt", PAGE_EXECUTE_READWRITE, "Ptr")
			return DllCall("MessageBox","PTR",0,"Str","Could not reseve memory for process.","STR","Error","UInt",0)
		,DllCall("CloseHandle", "PTR", hProc)

		; Write script to remote process memory
		DllCall("WriteProcessMemory", "Ptr", hProc, "Ptr", pBufferRemote, "Ptr", &nScript, "PTR", nScriptLength, "Ptr", 0)

		; Start execution of code
		hThread := DllCall("CreateRemoteThread", "PTR", hProc, "PTR", 0, "PTR", 0, "PTR", PID.ahkExec, "PTR", pBufferRemote, "UInt", 0, "PTR", 0,"PTR")
		if !hThread
		{
			DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nScriptLength,MEM_RELEASE)
			,DllCall("CloseHandle", "PTR", hProc)
			return DllCall("MessageBox","PTR",0,"Str","Could not execute script in remote process.","STR","Error","UInt",0)
		}

		; Wait for thread to finish
		DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)

		; Get Exit code returned by ahkExec (1 = script could be executed / 0 = script could not be executed)
		DllCall("GetExitCodeThread", "PTR", hThread, "UIntP", lpExitCode)
		if !lpExitCode
			return DllCall("MessageBox","PTR",0,"Str","Could not execute script in remote process.","STR","Error","UInt",0)

		DllCall("CloseHandle", "PTR", hThread)
		,DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nScriptLength,MEM_RELEASE)
		,DllCall("CloseHandle", "PTR", hProc)
		return
	}
	else if !hDll:=DllCall("LoadLibrary","Str",dll,"PTR")
		return DllCall("MessageBox","PTR",0,"Str","Could not find " dll " library.","STR","Error","UInt",0),DllCall("CloseHandle", "PTR", hProc)
	else
	{
		hProc := DllCall("OpenProcess","UInt", PROCESS_ALL_ACCESS, "Int",0,"UInt", DllCall("GetCurrentProcessId"),"PTR")
		DllCall("GetModuleFileName","PTR",hDll,"PTR",&ModuleName,"UInt",MAX_PATH)
		DllCall("CloseHandle","PTR",hProc)
	}
	; Open Process to PID
	hProc := DllCall("OpenProcess", "UInt", PROCESS_ALL_ACCESS, "Int",0, "UInt", PID,"PTR")
	if !hProc
		return DllCall("MessageBox","PTR",0,"Str","Could not open process for PID: " PID,"STR","Error","UInt",0)

	; Reserve some memory and write dll path (ANSI)
	nDirLength := VarSetCapacity(nDir, StrLen(dll)+1, 0)
	,StrPut(dll,&nDir,"CP0")

	; Reserve memory in remote process
	if !pBufferRemote := DllCall("VirtualAllocEx", "Ptr", hProc, "Ptr", 0, "PTR", nDirLength, "UInt", MEM_COMMIT, "UInt", PAGE_EXECUTE_READWRITE, "Ptr")
		return DllCall("MessageBox","PTR",0,"Str","Could not reseve memory for process.","STR","Error","UInt",0),DllCall("CloseHandle", "PTR", hProc)

	; Write dll path to remote process memory
	DllCall("WriteProcessMemory", "Ptr", hProc, "Ptr", pBufferRemote, "Ptr", &nDir, "PTR", nDirLength, "Ptr", 0)

	; Start new thread loading our dll

	hThread:=DllCall("CreateRemoteThread","PTR",hProc,"PTR",0,"PTR",0,"PTR",LoadLibraryA,"PTR",pBufferRemote,"UInt",0,"PTR",0,"PTR")
	if !hThread
	{
		DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nDirLength,"Uint",MEM_RELEASE)
		,DllCall("CloseHandle", "PTR", hProc)
		return DllCall("MessageBox","PTR",0,"Str","Could not load " dll " in remote process.","STR","Error","UInt",0)
	}
	; Wait for thread to finish
	DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)

	; Get Exit code returned by thread (HMODULE for our dll)
	DllCall("GetExitCodeThread", "PTR", hThread, "UInt*", hModule)

	; Close Thread
	DllCall("CloseHandle", "PTR", hThread)

	if (A_PtrSize=8)
	{ ; use different method to retrieve base address because GetExitCodeThread returns DWORD only
		hModule:=0,VarSetCapacity(me32, (A_PtrSize=8?48:32)+(A_IsUnicode?1032:516), 0) ;W:1080:1064, A:564:548
		;  Take a snapshot of all modules in the specified process.
		hModuleSnap := DllCall("CreateToolhelp32Snapshot","UInt", TH32CS_SNAPMODULE,"UInt", PID, "PTR" )
		if ( hModuleSnap != INVALID_HANDLE_VALUE )
		{
			; reset hModule and set the size of the structure before using it.
			NumPut((A_PtrSize=8?48:32)+(A_IsUnicode?1032:516), &me32, 0, "UInt") ;dwSize  ;W:1080:1064, A:564:548
			;  Retrieve information about the first module,
			;  and exit if unsuccessful
			if ( !DllCall("Module32First" (A_IsUnicode?"W":""),"PTR", hModuleSnap,"PTR", &me32 ) )
			{
				; Free memory used for passing dll path to remote thread
				DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nDirLength,MEM_RELEASE)
				,DllCall("CloseHandle","PTR", hModuleSnap ) ; Must clean up the snapshot object!
				return false
			}
			;  Now walk the module list of the process,and display information about each module
			while(A_Index=1 || DllCall("Module32Next" (A_IsUnicode?"W":""),"PTR",hModuleSnap,"PTR", &me32 ) )
				if (StrGet(&me32+(A_PtrSize=8?48:32)+(A_IsUnicode?512:256))=dll) ;szExePath ;W:560:544, A:304:288
				{
					hModule := NumGet(me32, A_PtrSize=8?40:28, "Ptr") ;hModule
					break
				}
			DllCall("CloseHandle","PTR",hModuleSnap) ; clean up
		}
	}

	hDll:=DllCall("LoadLibrary","Str",dll,"PTR")

	; Calculate pointer to ahkdll and ahkExec functions
	ahktextdll:=hModule+DllCall("GetProcAddress","PTR",hDll,"AStr","ahktextdll","PTR")-hDll
	ahkExec:=hModule+DllCall("GetProcAddress","PTR",hDll,"AStr","ahkExec","PTR")-hDll
	ahkTerminate:=hModule+DllCall("GetProcAddress","PTR",hDll,"AStr","ahkTerminate","PTR")-hDll

	if script
	{
		nScriptLength := VarSetCapacity(nScript, (StrLen(script)+1)*(A_IsUnicode?2:1), 0)
		,StrPut(script,&nScript)
		; Reserve memory in remote process where our script will be saved
		if !pBufferScript := DllCall("VirtualAllocEx", "Ptr", hProc, "Ptr", 0, "PTR", nScriptLength, "UInt", MEM_COMMIT, "UInt", PAGE_EXECUTE_READWRITE, "Ptr")
			return DllCall("MessageBox","PTR",0,"Str","Could not reseve memory for process.","STR","Error","UInt",0)
		,DllCall("CloseHandle", "PTR", hProc)

		; Write script to remote process memory
		DllCall("WriteProcessMemory", "Ptr", hProc, "Ptr", pBufferScript, "Ptr", &nScript, "PTR", nScriptLength, "Ptr", 0)
	}
	else
		pBufferScript:=0

	; Run ahkdll function in remote thread
	hThread := DllCall("CreateRemoteThread","PTR",hProc,"PTR",0,"PTR",0,"PTR",ahktextdll,"PTR",pBufferScript,"PTR",0,"UInt",0,"PTR")
	if !hThread
	{ ; could not start ahkdll in remote process
		; Free memory used for passing dll path to remote thread
		DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nDirLength,MEM_RELEASE)
		DllCall("CloseHandle", "PTR", hProc)
		return DllCall("MessageBox","PTR",0,"Str","Could not start ahkdll in remote process","STR","Error","UInt",0)
	}
	DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)
	DllCall("GetExitCodeThread", "PTR", hThread, "UIntP", lpExitCode)

	; Release memory and handles
	DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nDirLength,MEM_RELEASE)
	DllCall("CloseHandle", "PTR", hThread)
	DllCall("CloseHandle", "PTR", hProc)

	if !lpExitCode ; thread could not be created.
		return DllCall("MessageBox","PTR",0,"Str","Could not create a thread in remote process","STR","Error","UInt",0)

	return {PID:PID,hModule:hModule,ahkExec:ahkExec,ahkTerminate:ahkTerminate,base:base}
}
User avatar
jeeswg
Posts: 5146
Joined: 19 Dec 2016, 01:58
Location: UK

Re: how to dll Inject

02 Oct 2017, 21:35

How can you communicate from the remote thread to the original script e.g. pass data (a number). I had problems with PostMessage/SendMessage, and I had problems with GetProp and SetProp.

I'm working on this, I believe it's working apart from passing the hFont from the remote thread (in an AutoHotkey instance) to the original script:
MsgBox/InputBox gets hidden under another window (+ InputBox custom font) - Page 2 - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 71#p166471

This GetProp/SetProp example worked between two scripts launched normally. But I had trouble trying to do this with a remote thread.

Code: Select all

;script 1
#Persistent
hFont := 1234
DllCall("user32\SetProp", Ptr,A_ScriptHwnd, Str,"AhkInputBoxHFont", Ptr,hFont, Ptr)
MsgBox, % hFont " " DllCall("user32\GetProp", Ptr,A_ScriptHwnd, Str,"AhkInputBoxHFont", Ptr)

;==================================================

;script 2
DetectHiddenWindows, On
SetTitleMatchMode, 2
WinGet, hWnd, ID, script 1.ahk
WinGetTitle, vWinTitle, % "ahk_id " hWnd
MsgBox, % vWinTitle
MsgBox, % DllCall("user32\GetProp", Ptr,hWnd, Str,"AhkInputBoxHFont", Ptr)
HotKeyIt
Posts: 1697
Joined: 29 Sep 2013, 18:35
Contact:

Re: how to dll Inject

03 Oct 2017, 03:16

What is the error you get?
MSDN wrote:SetProp is subject to the restrictions of User Interface Privilege Isolation (UIPI). A process can only call this function on a window belonging to a process of lesser or equal integrity level. When UIPI blocks property changes, GetLastError will return 5.
User avatar
jeeswg
Posts: 5146
Joined: 19 Dec 2016, 01:58
Location: UK

Re: how to dll Inject

03 Oct 2017, 09:59

I didn't get any error. Thanks for the quote, I noticed it at MSDN but I don't know what its significance is, when I tried GetProp between two scripts in the example above it worked fine. I've provided some example code below of trying to do it in a remote thread.

I managed to get PostMessage/SendMessage to work, from remote thread to main script. I suppose that would be the best way to communicate in that direction. (To communicate from main script to remote thread, you just put information into the script string that you execute via Exec.)

Are there any other good methods for communication from remote thread to main script other than XXXProp and XXXMessage? Cheers.

Code: Select all

;contests of 'test getprop.ahk':
;#Persistent

;==================================================

;[get x64 and x32 versions of AutoHotkeyMini.dll]
;GitHub - HotKeyIt/ahkdll-v1-release: AutoHotkey_H v1 release
;https://github.com/HotKeyIt/ahkdll-v1-release

vDir := "C:\Program Files\AutoHotkey"
if (A_PtrSize = 8)
	vPathDll := vDir "\AutoHotkeyMiniU64.dll"
else
	vPathDll := vDir "\AutoHotkeyMiniU32.dll"

;==================================================

OnMessage(0x5555, "MsgMonitor")

DetectHiddenWindows, On
WinGet, hWnd, ID, %A_Desktop%\test getprop.ahk ahk_class AutoHotkey
;WinGet, hWnd, ID, %A_Desktop%\script 1.ahk ahk_class AutoHotkey
MsgBox, % DllCall("user32\GetProp", Ptr,hWnd, Str,"AhkInputBoxHFont", Ptr)
WinGetTitle, vWinTitle, % "ahk_id " hWnd
MsgBox, % vWinTitle
WinGet, vPID, PID, % "ahk_id " hWnd
vScript1 = ;continuation section
(
hFont := 1234
DllCall("user32\SetProp", Ptr,A_ScriptHwnd, Str,"AhkInputBoxHFont", Ptr,hFont, Ptr)
)
vScript2 = MsgBox, `% hFont " " DllCall("user32\GetProp", Ptr,A_ScriptHwnd, Str,"AhkInputBoxHFont", Ptr)

rThread := InjectAhkDll(vPID, vPathDll)
rThread.Exec(vScript1)
rThread.Exec(vScript2)
;rThread := ""
vRet := DllCall("user32\GetProp", Ptr,hWnd, Str,"AhkInputBoxHFont", Ptr)
vErrorLevel := ErrorLevel
vLastError := A_LastError
MsgBox, % vRet " " vErrorLevel " " vLastError ;0 0 0

;no message received
vScript3 = ;continuation section
(
DetectHiddenWindows, On
PostMessage, 0x5555, 2345,,, `% "ahk_id " %A_ScriptHwnd%
)
rThread.Exec(vScript3)
;rThread := ""

;no message received
vScript4 = ;continuation section
(
DetectHiddenWindows, On
SendMessage, 0x5555, 2345,,, `% "ahk_id " %A_ScriptHwnd%
)
rThread.Exec(vScript3)
;rThread := ""

;PostMessage, 0x5555, 2345,,, % "ahk_id " A_ScriptHwnd
return

;==================================================

MsgMonitor(wParam, lParam, uMsg, hWnd)
{
	MsgBox, % Format("{} {} {} {}", wParam, lParam, uMsg, hWnd)
}

;==================================================

;[original version of InjectAhkDll]
;[SOLVED]get other process's working dir - Page 3 - Ask for Help - AutoHotkey Community
;https://autohotkey.com/board/topic/85304-solvedget-other-processs-working-dir/page-3#entry544650

;[get x64 and x32 versions of AutoHotkeyMini.dll]
;GitHub - HotKeyIt/ahkdll-v1-release: AutoHotkey_H v1 release
;https://github.com/HotKeyIt/ahkdll-v1-release

;by HotKeyIt (modified version by jeeswg to not require _Struct.ahk)
InjectAhkDll(PID,dll="AutoHotkey.dll",script=0)
{
	static PROCESS_ALL_ACCESS:=0x1F0FFF,MEM_COMMIT := 0x1000,MEM_RELEASE:=0x8000,PAGE_EXECUTE_READWRITE:=64
	,hKernel32:=DllCall("LoadLibrary","Str","kernel32.dll","PTR"),LoadLibraryA:=DllCall("GetProcAddress","PTR",hKernel32,"AStr","LoadLibraryA","PTR")
	,base:={__Call:"InjectAhkDll",__Delete:"InjectAhkDll"},FreeLibrary:=DllCall("GetProcAddress","PTR",hKernel32,"AStr","FreeLibrary","PTR")
	static TH32CS_SNAPMODULE:=0x00000008,INVALID_HANDLE_VALUE:=-1
	,MAX_PATH:=260,MAX_MODULE_NAME32:=255,ModuleName:="",init:=VarSetCapacity(ModuleName,MAX_PATH*(A_IsUnicode?2:1))

	if IsObject(PID)
	{
		if (dll!="Exec" && script)
			return DllCall("MessageBox","PTR",0,"Str","Only Exec method can be used here!","STR","Error","UInt",0)

		hProc := DllCall("OpenProcess", "UInt", PROCESS_ALL_ACCESS, "Int",0, "UInt", PID.PID,"PTR")
		if !hProc
			return DllCall("MessageBox","PTR",0,"Str","Could not open process for PID: " PID.PID,"STR","Error","UInt",0)

		if (!script) ; Free Library in remote process (object is being deleted)
		{
			; Terminate the thread in ahkdll
			hThread := DllCall("CreateRemoteThread", "PTR", hProc, "PTR", 0, "PTR", 0, "PTR", PID.ahkTerminate, "PTR", 0, "UInt", 0, "PTR", 0,"PTR")
			DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)
			,DllCall("CloseHandle", "PTR", hThread)

			; Free library in remote process
			hThread := DllCall("CreateRemoteThread", "PTR", hProc, "UInt", 0, "UInt", 0, "PTR", FreeLibrary, "PTR", PID.hModule, "UInt", 0, "UInt", 0,"PTR")
			DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)
			,DllCall("CloseHandle", "PTR", hThread),DllCall("CloseHandle", "PTR", hProc)
			return
		}

		nScriptLength := VarSetCapacity(nScript, (StrLen(script)+1)*(A_IsUnicode?2:1), 0)
		,StrPut(script,&nScript)

		; Reserve memory in remote process where our script will be saved
		if !pBufferRemote := DllCall("VirtualAllocEx", "Ptr", hProc, "Ptr", 0, "PTR", nScriptLength, "UInt", MEM_COMMIT, "UInt", PAGE_EXECUTE_READWRITE, "Ptr")
			return DllCall("MessageBox","PTR",0,"Str","Could not reseve memory for process.","STR","Error","UInt",0)
		,DllCall("CloseHandle", "PTR", hProc)

		; Write script to remote process memory
		DllCall("WriteProcessMemory", "Ptr", hProc, "Ptr", pBufferRemote, "Ptr", &nScript, "PTR", nScriptLength, "Ptr", 0)

		; Start execution of code
		hThread := DllCall("CreateRemoteThread", "PTR", hProc, "PTR", 0, "PTR", 0, "PTR", PID.ahkExec, "PTR", pBufferRemote, "UInt", 0, "PTR", 0,"PTR")
		if !hThread
		{
			DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nScriptLength,MEM_RELEASE)
			,DllCall("CloseHandle", "PTR", hProc)
			return DllCall("MessageBox","PTR",0,"Str","Could not execute script in remote process.","STR","Error","UInt",0)
		}

		; Wait for thread to finish
		DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)

		; Get Exit code returned by ahkExec (1 = script could be executed / 0 = script could not be executed)
		DllCall("GetExitCodeThread", "PTR", hThread, "UIntP", lpExitCode)
		if !lpExitCode
			return DllCall("MessageBox","PTR",0,"Str","Could not execute script in remote process.","STR","Error","UInt",0)

		DllCall("CloseHandle", "PTR", hThread)
		,DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nScriptLength,MEM_RELEASE)
		,DllCall("CloseHandle", "PTR", hProc)
		return
	}
	else if !hDll:=DllCall("LoadLibrary","Str",dll,"PTR")
		return DllCall("MessageBox","PTR",0,"Str","Could not find " dll " library.","STR","Error","UInt",0),DllCall("CloseHandle", "PTR", hProc)
	else
	{
		hProc := DllCall("OpenProcess","UInt", PROCESS_ALL_ACCESS, "Int",0,"UInt", DllCall("GetCurrentProcessId"),"PTR")
		DllCall("GetModuleFileName","PTR",hDll,"PTR",&ModuleName,"UInt",MAX_PATH)
		DllCall("CloseHandle","PTR",hProc)
	}
	; Open Process to PID
	hProc := DllCall("OpenProcess", "UInt", PROCESS_ALL_ACCESS, "Int",0, "UInt", PID,"PTR")
	if !hProc
		return DllCall("MessageBox","PTR",0,"Str","Could not open process for PID: " PID,"STR","Error","UInt",0)

	; Reserve some memory and write dll path (ANSI)
	nDirLength := VarSetCapacity(nDir, StrLen(dll)+1, 0)
	,StrPut(dll,&nDir,"CP0")

	; Reserve memory in remote process
	if !pBufferRemote := DllCall("VirtualAllocEx", "Ptr", hProc, "Ptr", 0, "PTR", nDirLength, "UInt", MEM_COMMIT, "UInt", PAGE_EXECUTE_READWRITE, "Ptr")
		return DllCall("MessageBox","PTR",0,"Str","Could not reseve memory for process.","STR","Error","UInt",0),DllCall("CloseHandle", "PTR", hProc)

	; Write dll path to remote process memory
	DllCall("WriteProcessMemory", "Ptr", hProc, "Ptr", pBufferRemote, "Ptr", &nDir, "PTR", nDirLength, "Ptr", 0)

	; Start new thread loading our dll

	hThread:=DllCall("CreateRemoteThread","PTR",hProc,"PTR",0,"PTR",0,"PTR",LoadLibraryA,"PTR",pBufferRemote,"UInt",0,"PTR",0,"PTR")
	if !hThread
	{
		DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nDirLength,"Uint",MEM_RELEASE)
		,DllCall("CloseHandle", "PTR", hProc)
		return DllCall("MessageBox","PTR",0,"Str","Could not load " dll " in remote process.","STR","Error","UInt",0)
	}
	; Wait for thread to finish
	DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)

	; Get Exit code returned by thread (HMODULE for our dll)
	DllCall("GetExitCodeThread", "PTR", hThread, "UInt*", hModule)

	; Close Thread
	DllCall("CloseHandle", "PTR", hThread)

	if (A_PtrSize=8)
	{ ; use different method to retrieve base address because GetExitCodeThread returns DWORD only
		hModule:=0,VarSetCapacity(me32, (A_PtrSize=8?48:32)+(A_IsUnicode?1032:516), 0) ;W:1080:1064, A:564:548
		;  Take a snapshot of all modules in the specified process.
		hModuleSnap := DllCall("CreateToolhelp32Snapshot","UInt", TH32CS_SNAPMODULE,"UInt", PID, "PTR" )
		if ( hModuleSnap != INVALID_HANDLE_VALUE )
		{
			; reset hModule and set the size of the structure before using it.
			NumPut((A_PtrSize=8?48:32)+(A_IsUnicode?1032:516), &me32, 0, "UInt") ;dwSize  ;W:1080:1064, A:564:548
			;  Retrieve information about the first module,
			;  and exit if unsuccessful
			if ( !DllCall("Module32First" (A_IsUnicode?"W":""),"PTR", hModuleSnap,"PTR", &me32 ) )
			{
				; Free memory used for passing dll path to remote thread
				DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nDirLength,MEM_RELEASE)
				,DllCall("CloseHandle","PTR", hModuleSnap ) ; Must clean up the snapshot object!
				return false
			}
			;  Now walk the module list of the process,and display information about each module
			while(A_Index=1 || DllCall("Module32Next" (A_IsUnicode?"W":""),"PTR",hModuleSnap,"PTR", &me32 ) )
				if (StrGet(&me32+(A_PtrSize=8?48:32)+(A_IsUnicode?512:256))=dll) ;szExePath ;W:560:544, A:304:288
				{
					hModule := NumGet(me32, A_PtrSize=8?40:28, "Ptr") ;hModule
					break
				}
			DllCall("CloseHandle","PTR",hModuleSnap) ; clean up
		}
	}

	hDll:=DllCall("LoadLibrary","Str",dll,"PTR")

	; Calculate pointer to ahkdll and ahkExec functions
	ahktextdll:=hModule+DllCall("GetProcAddress","PTR",hDll,"AStr","ahktextdll","PTR")-hDll
	ahkExec:=hModule+DllCall("GetProcAddress","PTR",hDll,"AStr","ahkExec","PTR")-hDll
	ahkTerminate:=hModule+DllCall("GetProcAddress","PTR",hDll,"AStr","ahkTerminate","PTR")-hDll

	if script
	{
		nScriptLength := VarSetCapacity(nScript, (StrLen(script)+1)*(A_IsUnicode?2:1), 0)
		,StrPut(script,&nScript)
		; Reserve memory in remote process where our script will be saved
		if !pBufferScript := DllCall("VirtualAllocEx", "Ptr", hProc, "Ptr", 0, "PTR", nScriptLength, "UInt", MEM_COMMIT, "UInt", PAGE_EXECUTE_READWRITE, "Ptr")
			return DllCall("MessageBox","PTR",0,"Str","Could not reseve memory for process.","STR","Error","UInt",0)
		,DllCall("CloseHandle", "PTR", hProc)

		; Write script to remote process memory
		DllCall("WriteProcessMemory", "Ptr", hProc, "Ptr", pBufferScript, "Ptr", &nScript, "PTR", nScriptLength, "Ptr", 0)
	}
	else
		pBufferScript:=0

	; Run ahkdll function in remote thread
	hThread := DllCall("CreateRemoteThread","PTR",hProc,"PTR",0,"PTR",0,"PTR",ahktextdll,"PTR",pBufferScript,"PTR",0,"UInt",0,"PTR")
	if !hThread
	{ ; could not start ahkdll in remote process
		; Free memory used for passing dll path to remote thread
		DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nDirLength,MEM_RELEASE)
		DllCall("CloseHandle", "PTR", hProc)
		return DllCall("MessageBox","PTR",0,"Str","Could not start ahkdll in remote process","STR","Error","UInt",0)
	}
	DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)
	DllCall("GetExitCodeThread", "PTR", hThread, "UIntP", lpExitCode)

	; Release memory and handles
	DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nDirLength,MEM_RELEASE)
	DllCall("CloseHandle", "PTR", hThread)
	DllCall("CloseHandle", "PTR", hProc)

	if !lpExitCode ; thread could not be created.
		return DllCall("MessageBox","PTR",0,"Str","Could not create a thread in remote process","STR","Error","UInt",0)

	return {PID:PID,hModule:hModule,ahkExec:ahkExec,ahkTerminate:ahkTerminate,base:base}
}

;==================================================
HotKeyIt
Posts: 1697
Joined: 29 Sep 2013, 18:35
Contact:

Re: how to dll Inject

03 Oct 2017, 12:49

Any IPC should work, pipe, FileMapping, ini ...
User avatar
jeeswg
Posts: 5146
Joined: 19 Dec 2016, 01:58
Location: UK

Re: how to dll Inject

03 Oct 2017, 13:01

Hadn't come across the term IPC before, I guess you meant:
Inter-process communication - Wikipedia
https://en.wikipedia.org/wiki/Inter-pro ... munication

I was curious as to whether, since the script and remote thread are connected in some way, there might be a more direct method. General methods might be a good topic for a new thread.

If anyone can work out why GetProp wasn't working that would be great.

Return to “Ask For Help”

Who is online

Users browsing this forum: No registered users and 3 guests