program that uses OpenProcess? Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
whynotregister
Posts: 147
Joined: 05 Nov 2016, 22:42

program that uses OpenProcess?

12 Mar 2017, 21:28

to protect my program I'd like to have a check that detects any program that executes OpenProcess with my PID? I want to prevent that other programs can get a handle to my program easily.

What options do I have? (WinAPI and so on) Does my program receive any notification as soon as another program uses OpenProcess?

Thanks
4GForce
Posts: 553
Joined: 25 Jan 2017, 03:18
Contact:

Re: program that uses OpenProcess?

13 Mar 2017, 02:22

whynotregister wrote:to protect my program I'd like to have a check that detects any program that executes OpenProcess with my PID? I want to prevent that other programs can get a handle to my program easily.

What options do I have? (WinAPI and so on) Does my program receive any notification as soon as another program uses OpenProcess?

Thanks
As far as I'm concerned, OpenProcess isn't an ahk function, it's acessible via DllCall thus this would be a MSDN Question ???
But maybe someone else in here has the answer ...
qwerty12
Posts: 468
Joined: 04 Mar 2016, 04:33
Contact:

Re: program that uses OpenProcess?

13 Mar 2017, 09:39

Google "detect OpenProcess": the consensus is you need to write a driver to do so. I don't play games myself, but it seems from a cursory read of forum posts, most anti-cheat solutions do just that.

What exactly are you trying to achieve? I'm far from an expert in this area, so I wouldn't take my opinion as gospel, but I know you can restrict users from reading the memory of your process / terminating it etc. by modifying the ACL of your process object, but that's easily bypassed by any process that has SeDebugPrivilege enabled...
whynotregister
Posts: 147
Joined: 05 Nov 2016, 22:42

Re: program that uses OpenProcess?

13 Mar 2017, 13:48

qwerty12 wrote:Google "detect OpenProcess": the consensus is you need to write a driver to do so. I don't play games myself, but it seems from a cursory read of forum posts, most anti-cheat solutions do just that.

What exactly are you trying to achieve? I'm far from an expert in this area, so I wouldn't take my opinion as gospel, but I know you can restrict users from reading the memory of your process / terminating it etc. by modifying the ACL of your process object, but that's easily bypassed by any process that has SeDebugPrivilege enabled...
I want to block the memory corruption of the process a little bit.
Is there any way I can protect my program memory a little easier?
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: program that uses OpenProcess?

13 Mar 2017, 16:30

whynotregister wrote:to protect my program I'd like to have a check that detects any program that executes OpenProcess with my PID? I want to prevent that other programs can get a handle to my program easily.

What options do I have? (WinAPI and so on) Does my program receive any notification as soon as another program uses OpenProcess?

Thanks
http://stackoverflow.com/questions/1718 ... penprocess

Mats Petersson answered the question pretty well 4 years ago.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
qwerty12
Posts: 468
Joined: 04 Mar 2016, 04:33
Contact:

Re: program that uses OpenProcess?  Topic is solved

13 Mar 2017, 18:56

whynotregister wrote: I want to block the memory corruption of the process a little bit.
Is there any way I can protect my program memory a little easier?
Try this:

Code: Select all

#NoEnv
#SingleInstance force

SetRestrictedDacl()
MsgBox fd

SetRestrictedDacl()
{
	allowCurrentUserQueryLimitedInformation := False
	if (LogonDesktop_OpenProcessToken(LogonDesktop_GetCurrentProcess(), TOKEN_QUERY := 0x0008, hToken)) {
		if (LogonDesktop_GetTokenUser(hToken, TOKEN_USER)) { ; get SID of user who created this process
			if (DllCall("advapi32.dll\ConvertSidToStringSidW", "Ptr", NumGet(TOKEN_USER,, "Ptr"), "Ptr*", StringSid)) { ; and convert it to string form
				EVERYONE_DACL := "(D;;0xc0fab;;;WD)" ; create ACE denying the following for Everyone: set information; set quotas; set session ID; creating threads; modifying, reading and writing memory; duplicating handles; port stuff; and termination of the process
				CURRENT_USER := allowCurrentUserQueryLimitedInformation ? StrReplace("(A;;0x1000;;;<2.7.Z.E.R.O>)", "<2.7.Z.E.R.O>", StrGet(StringSid,, "UTF-16")) : "" ; Place the SID into our SDDL string. I have no idea what SDDL notation is equivalent to CURRENT_USER
				SYSTEM := "(A;;0x1fffff;;;SY)" ; allow full control for SYSTEM
				BUILTIN_ADMIN := "(A;;0x1fffc7;;;BA)" ; allow full control for Admin accounts (comes into play when an elevated program is opening a handle to your process), minus the PROCESS_VM_* rights
				
				SDDL := "D:" . EVERYONE_DACL . CURRENT_USER . SYSTEM . BUILTIN_ADMIN ; ACE order is important!

				if (DllCall("advapi32.dll\ConvertStringSecurityDescriptorToSecurityDescriptorW", "WStr", SDDL, "UInt", SDDL_REVISION_1 := 1, "Ptr*", SEC_DESCRIPTOR, "Ptr", 0)) { ; get SD from SDDL string (given the amount of struct manipulations I'd have to do to do this in pure WinAPI, I'll stick with SDDL in AutoHotkey, TYVM)
					if (DllCall("Advapi32\GetSecurityDescriptorDacl", "Ptr", SEC_DESCRIPTOR, "Int*", DaclPresent, "Ptr*", NewDacl, "Int*", 0) && DaclPresent) ; get pointer to DACL structure from SD
						DllCall("Advapi32\SetSecurityInfo", "Ptr", LogonDesktop_GetCurrentProcess(), "UInt", SE_KERNEL_OBJECT := 6, "UInt", DACL_SECURITY_INFORMATION := 0x00000004, "Ptr", 0, "Ptr", 0, "Ptr", NewDacl, "Ptr", 0) ; set the new DACL
				}
				; purposely don't free the SD memory allocated by ConvertStringSecurityDescriptorToSecurityDescriptor - I'm not sure of the ownership rules, but I have seen crashes in the past when doing so
				DllCall("LocalFree", "Ptr", StringSid, "Ptr")
			}
		}
		LogonDesktop_CloseHandle(hToken)
	}
}

LogonDesktop_GetTokenUser(hToken, ByRef TOKEN_USER)
{
	ret := dwLengthNeeded := 0

	if (!_GetTokenInformation(hToken, TokenUser := 1, 0, 0, dwLengthNeeded))
		if (A_LastError == 122 && VarSetCapacity(TOKEN_USER, dwLengthNeeded)) ; ERROR_INSUFFICIENT_BUFFER
			ret := _GetTokenInformation(hToken, TokenUser, &TOKEN_USER, dwLengthNeeded, dwLengthNeeded)

	return ret
}

LogonDesktop_OpenProcessToken(ProcessHandle, DesiredAccess, ByRef TokenHandle) {
	static OpenProcessToken := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "OpenProcessToken", "Ptr")
	return DllCall(OpenProcessToken, "Ptr", ProcessHandle, "UInt", DesiredAccess, "Ptr*", TokenHandle)
}

LogonDesktop_CloseHandle(hObject) {
	static CloseHandle := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "kernel32.dll", "Ptr"), "AStr", "CloseHandle", "Ptr"), INVALID_HANDLE_VALUE := -1
	return (hObject && hObject != INVALID_HANDLE_VALUE) ? DllCall(CloseHandle, "Ptr", hObject) : False
}

LogonDesktop_GetCurrentProcess() {
	static hProc := DllCall("GetCurrentProcess", "Ptr") ; always -1
	return hProc
}

_GetTokenInformation(TokenHandle, TokenInformationClass, ByRef TokenInformation, TokenInformationLength, ByRef ReturnLength, _tokenInfoType := "Ptr") {
	static GetTokenInformation := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "GetTokenInformation", "Ptr")
	return DllCall(GetTokenInformation, "Ptr", TokenHandle, "UInt", TokenInformationClass, _tokenInfoType, TokenInformation, "UInt", TokenInformationLength, "UInt*", ReturnLength)
}
Bear in mind this is weak protection:
  • Admin accounts typically have the SeDebugPrivilege right granted - when enabled by a process, access checks are bypassed
  • If this is used in an unelevated script, your account is still the owner of the process object - granting access rights back to your account is probably trivial
For proper protection, you need to write a driver to properly intercept OpenProcess, it seems. (Or make your process a protected one, which, barring access to MS' platform certificate, seems to be only possible to do from a driver ;-))

EDIT: You're welcome :-) I've edited this slightly to remove PROCESS_VM_* rights from the admin ACE - again, this doesn't really make things more secure, but it does add another step to perform before elevated applications can read the memory of your process
Last edited by qwerty12 on 15 Mar 2017, 08:23, edited 2 times in total.
whynotregister
Posts: 147
Joined: 05 Nov 2016, 22:42

Re: program that uses OpenProcess?

13 Mar 2017, 23:32

qwerty12 wrote:
whynotregister wrote: I want to block the memory corruption of the process a little bit.
Is there any way I can protect my program memory a little easier?
Try this:

Code: Select all

#NoEnv
#SingleInstance force

SetRestrictedDacl()
MsgBox fd

SetRestrictedDacl()
{
	allowCurrentUserQueryLimitedInformation := False
	if (LogonDesktop_OpenProcessToken(LogonDesktop_GetCurrentProcess(), TOKEN_QUERY := 0x0008, hToken)) {
		if (LogonDesktop_GetTokenUser(hToken, TOKEN_USER)) { ; get SID of user who created this process
			if (DllCall("advapi32.dll\ConvertSidToStringSidW", "Ptr", NumGet(TOKEN_USER,, "Ptr"), "Ptr*", StringSid)) { ; and convert it to string form
				EVERYONE_DACL := "(D;;0xc0fab;;;WD)" ; create ACE denying the following for Everyone: set information; set quotas; set session ID; creating threads; modifying, reading and writing memory; duplicating handles; port stuff; and termination of the process
				CURRENT_USER := allowCurrentUserQueryLimitedInformation ? StrReplace("(A;;0x1000;;;<2.7.Z.E.R.O>)", "<2.7.Z.E.R.O>", StrGet(StringSid,, "UTF-16")) : "" ; Place the SID into our SDDL string. I have no idea what SDDL notation is equivalent to CURRENT_USER
				SYSTEM := "(A;;0x1fffff;;;SY)" ; allow full control for SYSTEM
				BUILTIN_ADMIN := "(A;;0x1fffff;;;BA)" ; allow full control for Admin accounts (comes into play when an elevated program is opening a handle to your process)
				
				SDDL := "D:" . EVERYONE_DACL . CURRENT_USER . SYSTEM . BUILTIN_ADMIN ; ACE order is important!

				if (DllCall("advapi32.dll\ConvertStringSecurityDescriptorToSecurityDescriptorW", "WStr", SDDL, "UInt", SDDL_REVISION_1 := 1, "Ptr*", SEC_DESCRIPTOR, "Ptr", 0)) { ; get SD from SDDL string (given the amount of struct manipulations I'd have to do to do this in pure WinAPI, I'll stick with SDDL in AutoHotkey, TYVM)
					if (DllCall("Advapi32\GetSecurityDescriptorDacl", "Ptr", SEC_DESCRIPTOR, "Int*", DaclPresent, "Ptr*", NewDacl, "Int*", 0) && DaclPresent) ; get pointer to DACL structure from SD
						DllCall("Advapi32\SetSecurityInfo", "Ptr", LogonDesktop_GetCurrentProcess(), "UInt", SE_KERNEL_OBJECT := 6, "UInt", DACL_SECURITY_INFORMATION := 0x00000004, "Ptr", 0, "Ptr", 0, "Ptr", NewDacl, "Ptr", 0) ; set the new DACL
				}
				; purposely don't free the SD memory allocated by ConvertStringSecurityDescriptorToSecurityDescriptor - I'm not sure of the ownership rules, but I have seen crashes in the past when doing so
			}
		}
		LogonDesktop_CloseHandle(hToken)
	}
}

LogonDesktop_GetTokenUser(hToken, ByRef TOKEN_USER)
{
	ret := dwLengthNeeded := 0

	if (!_GetTokenInformation(hToken, TokenUser := 1, 0, 0, dwLengthNeeded))
		if (A_LastError == 122 && VarSetCapacity(TOKEN_USER, dwLengthNeeded)) ; ERROR_INSUFFICIENT_BUFFER
			ret := _GetTokenInformation(hToken, TokenUser, &TOKEN_USER, dwLengthNeeded, dwLengthNeeded)

	return ret
}

LogonDesktop_OpenProcessToken(ProcessHandle, DesiredAccess, ByRef TokenHandle) {
	static OpenProcessToken := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "OpenProcessToken", "Ptr")
	return DllCall(OpenProcessToken, "Ptr", ProcessHandle, "UInt", DesiredAccess, "Ptr*", TokenHandle)
}

LogonDesktop_CloseHandle(hObject) {
	static CloseHandle := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "kernel32.dll", "Ptr"), "AStr", "CloseHandle", "Ptr"), INVALID_HANDLE_VALUE := -1
	return (hObject && hObject != INVALID_HANDLE_VALUE) ? DllCall(CloseHandle, "Ptr", hObject) : False
}

LogonDesktop_GetCurrentProcess() {
	static hProc := DllCall("GetCurrentProcess", "Ptr") ; always -1
	return hProc
}

_GetTokenInformation(TokenHandle, TokenInformationClass, ByRef TokenInformation, TokenInformationLength, ByRef ReturnLength, _tokenInfoType := "Ptr") {
	static GetTokenInformation := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "GetTokenInformation", "Ptr")
	return DllCall(GetTokenInformation, "Ptr", TokenHandle, "UInt", TokenInformationClass, _tokenInfoType, TokenInformation, "UInt", TokenInformationLength, "UInt*", ReturnLength)
}
Bear in mind this is weak protection:
  • Admin accounts typically have the SeDebugPrivilege right granted - when enabled by a process, access checks are bypassed
  • If this is used in an unelevated script, your account is still the owner of the process object - granting access rights back to your account is probably trivial
For proper protection, you need to write a driver to properly intercept OpenProcess, it seems. (Or make your process a protected one, which, barring access to MS' platform certificate, seems to be only possible to do from a driver ;-))


Driver creation seems to be a difficult task. Your script is what I want. Thank you. :superhappy:

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: No registered users and 313 guests