WinRing0 - Send keys in Hardware-Level (update on 2017-01-18)

Post your working scripts, libraries and tools for AHK v1.1 and older
tmplinshi
Posts: 1604
Joined: 01 Oct 2013, 14:57

WinRing0 - Send keys in Hardware-Level (update on 2017-01-18)

25 Jul 2015, 11:15

What's WinRing0
WinRing0 is a hardware access library for Windows.

Features
This library allows x86/x64 Windows applications to access
- I/O port
- MSR (Model-Specific Register)
- PCI bus
etc...
I have only wrapped a few functions that I need. Most of the code (like KeyDown function) is translated from other language, I have no knowledge about it, so don't ask me if you don't understand.

Functions:
  • KeyDown(chr, delay := 5)
  • KeyUp(chr, delay := 1)
  • KeyPress(chr)
  • SendStr(string)
  • KeyCombine(arr*)
Examples: (Note: The script needs to be compiled and run as admin)

Code: Select all

#Include Class_WinRing0.ahk

WinRing0.KeyDown("a")
WinRing0.KeyUp("a")
WinRing0.KeyPress("a") ; Same as KeyDown + KeyUp
WinRing0.SendStr("autohotkey")
WinRing0.KeyCombine("Ctrl", "A")
Downloads: Note: WinRing0.dll and WinRing0.sys are for 32-bit AHK,
WinRing0x64.dll and WinRing0x64.sys are for 64-bit AHK.

Code: Select all

WinRing0.dll    => 32-bit AHK
WinRing0x64.dll => 64-bit AHK

WinRing0.sys    => 32-bit OS
WinRing0x64.sys => 64-bit OS
Limitation: WinRing0 doesn't support USB keyboard.
Change Log:
v1.12 (2017-01-18) - Fixed OnExit not exiting
v1.11 (2017-01-17) - Added an internal function Ensure_Admin_And_Compiled()
v1.10 (2015-10-22) - Added support for sending characters that needs to press {shift} key, such as "@" or "A".
v1.00 (2015-07-25)
Last edited by tmplinshi on 17 Jan 2017, 16:52, edited 9 times in total.
JJohnston2
Posts: 204
Joined: 24 Jun 2015, 23:38

Re: WinRing0 - Send keys in Hardware-Level

21 Oct 2015, 23:00

I am interested in getting this to work, but so far no luck.

Below are a few questions and improvements that could be made if you so choose.
  1. It appears the dll and sys files need to be in the path of the compiled exe (Do they have to be? wondering if they could be referenced somewhere else, which I'm guessing is possible)
  2. GetDllStatus() returns null for me when the program is not compiled, which is not handled (i.e., null results in a blank dialog--not too helpful)
  3. Is there a possibility of running this without having it compiled? Other programs make DLL calls just fine without having to be compiled--I wonder what's going on here.
  4. Are there any other debugging features that could be used if behavior is not as expected? I have a compiled program that should send a key and/or string (anything would be nice for starters), but when it runs, nothing happens. I can add status messages before/after the keys should send, but that doesn't help me figure out what's working or not working right--any troubleshooting code or ideas would be helpful
As far as platform, I'm on Win7x64 but when the program compiles it loads the 32-bit DLL, which may just be a function of the compiler defaulting to 32-bit... I don't get any errors, but nothing happens. If I force it to 64-bit then I get an initialization error.

Thanks.
tmplinshi
Posts: 1604
Joined: 01 Oct 2013, 14:57

Re: WinRing0 - Send keys in Hardware-Level

22 Oct 2015, 04:33

@JJohnston2:
1. You can specify the dll path in Class_WinRing0.ahk.

Code: Select all

Init() {
		this.dll := "YourPath\" ((A_PtrSize = 4) ? "WinRing0.dll" : "WinRing0x64.dll")
But the sys files need put in the same directory of the compiled exe.

Question 2~4, I don't know..
I just noticed that WinRing0x64.sys is not used for 64-bit AHK, but for 64-bit OS.
alwayswhy2014
Posts: 1
Joined: 22 Oct 2015, 12:02

Re: WinRing0 - Send keys in Hardware-Level

22 Oct 2015, 12:15

is it posible use with controlsend?
tmplinshi
Posts: 1604
Joined: 01 Oct 2013, 14:57

Re: WinRing0 - Send keys in Hardware-Level

22 Oct 2015, 19:56

alwayswhy2014 wrote:is it posible use with controlsend?
You mean send to inactive window? I don't think so.
User avatar
joedf
Posts: 8940
Joined: 29 Sep 2013, 17:08
Location: Canada
Contact:

Re: WinRing0 - Send keys in Hardware-Level

25 Oct 2015, 09:15

Impressive! :)
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]
JJohnston2
Posts: 204
Joined: 24 Jun 2015, 23:38

Re: WinRing0 - Send keys in Hardware-Level

25 Oct 2015, 23:06

Still can't get this to work. Win7x64. I tried loading with x32 and x64 AHK, verified they were loading the x64 .sys file in both cases, and verified the Class_WinRing0 routines were being called correctly by putting tooltip indicators into the routines (i.e., simple confirmation that those routines were running). The keystrokes expected however never materialized.

Here's my test code:

Code: Select all

WinRing := new WinRing0

tooltip Sending in... 3...
sleep 1000
tooltip Sending in... 2...
sleep 1000
tooltip Sending in... 1...
sleep 1000

WinRing.KeyPress("a") ; Same as KeyDown + KeyUp
WinRing.SendStr("12345677890")

ExitApp

#Include Class_WinRing0.ahk
If anyone else is able to get this working please let me know.

I suspect (since the function calls go through) that it's a driver issue of some sort, either an incompatibility, or it's not working on my system, or possibly a system setup issue. I dumped the sys and dll files in the same folder as the script, compiled the script and then ran it from the command line. I also tried running it from an elevated command line. The 3 second countdown let me run the program and then switch to a number of different text input programs, so I did that to make sure it wasn't just not working on the command line. No luck.

I would love to have this working if I'm the only one with a problem... maybe I could try it on a different machine or something to see if that's the issue, but besides that not sure how else to debug this when simply nothing happens.
tmplinshi
Posts: 1604
Joined: 01 Oct 2013, 14:57

Re: WinRing0 - Send keys in Hardware-Level

26 Oct 2015, 00:30

@JJohnston2:
I have compiled your example code. Try if it works:
https://www.dropbox.com/s/ui9vhe28ru1lj ... t.7z?raw=1
JJohnston2
Posts: 204
Joined: 24 Jun 2015, 23:38

Re: WinRing0 - Send keys in Hardware-Level

27 Oct 2015, 00:35

Thank you for the compile. Still doesn't work for me (Win7x64). Does my example code work for you?

For your general code, what platforms have you tested on and shown it to work?

If I am able to test on other machines I'll post my results. Thanks.
JJohnston2
Posts: 204
Joined: 24 Jun 2015, 23:38

Re: WinRing0 - Send keys in Hardware-Level

27 Oct 2015, 01:32

Tested the same folder of stuff (dumped from the zip file) on WinXP SP3 (32-bit). Tooltip countdown appears but no output.
  • Any possibility the dll or sys files are registered in some way on your computer, but not mine?
  • Any possibility they are being blocked from execution on my computer but not yours?
  • Are there any dependencies in the .dll or .sys file that I possibly don't have?
  • Is there hardware-specific code (where I possibly don't have the same hardware)?
I'm doubtful half of those I threw out are even possible, but not sure what other configuration differences there can be. On the XP setup, I confirmed that both the 32-bit dll and sys file were being called by renaming them to .bak one at a time and confirming msgbox errors on program start each time, then renaming them back to .dll and .sys and having the program run ok and display a tooltip.

Still wondering if anyone else can get the test program to run successfully as well.
tmplinshi
Posts: 1604
Joined: 01 Oct 2013, 14:57

Re: WinRing0 - Send keys in Hardware-Level

27 Oct 2015, 02:26

Your example code is working for me. Have you tried Run As Administrator? Otherwise I've no idea what the problem is.
JJohnston2
Posts: 204
Joined: 24 Jun 2015, 23:38

Re: WinRing0 - Send keys in Hardware-Level

28 Oct 2015, 00:33

I downloaded the RealTemp 3.60 program shown in this video... it appears to start up just fine and display temperature information although I'm not sure which features it is using the hardware driver for and whether or not those are working. It has the same WinRing0.dll version though for all 4 files (v1.3.1.19)... binary comparison checks out the same.

Something interesting I see is that if I examine the values returned by ReadIoPortByteEx they are all zero. According to this page (Section 11.1) it should probably be 0x14. I also tried adjusting the IoPort address in a loop (1 to 1000) and still reading all zeros--not good. I doubt the keyboard register at 0x64 is ever 0 to start with.

That partially made me suspect a driver signing/certificate issue but supposedly WinRing0.sys is signed (you can see this by looking at file properties in Explorer--signed by "Noriyuki MIYAZAKI"). After looking at the certificate details and attempting to install in the default location it still doesn't work. Did you do anything special with the driver certificate or security settings?--guessing not, since the RealTemp program seems to run just fine.

One thing I did get working is not having to compile the program each time. If you would like to test in the development environment you need to copy the .sys file that's getting loaded by the DLL into the same folder location of the AutoHotkey executable (usually C:\Program Files\AutoHotkey\AutoHotkey.exe). The DLL can be referenced by path to where it is on disk, but apparently the .sys file is expected to be in the same folder as the main executable (which may not necessarily be where the DLL is). Once the ahk program is compiled those locations are always the same if the EXE, DLL and SYS file are in the same folder, but before that there needs to be a copy with AutoHotkey.exe in Program Files since that's the actual that's executing the uncompiled code.
catfish00
Posts: 3
Joined: 24 May 2016, 07:33

Re: WinRing0 - Send keys in Hardware-Level

24 May 2016, 07:47

use WinRing0.SendStr function,i want to input 111111, but only input 1 or 111, never be 111111, why?...........need help.
by the way , i want to input password in activeX embedded on browser, such as password control.
Last edited by catfish00 on 24 May 2016, 07:55, edited 1 time in total.
catfish00
Posts: 3
Joined: 24 May 2016, 07:33

Re: WinRing0 - Send keys in Hardware-Level

24 May 2016, 07:54

WinRing0.SendStr 111111

sometimes input 1
sometimes input 111
never be 111111
i input password in activeX embedded on browser, such as password control
tmplinshi
Posts: 1604
Joined: 01 Oct 2013, 14:57

Re: WinRing0 - Send keys in Hardware-Level

24 May 2016, 23:45

@catfish00

Try to increase the delay (default is 5 milliseconds): WinRing.SendStr("111111", 20)
If that doesn't work, then try adding more delay...

Code: Select all

SendStr(string, delay := 15) {
	Loop, Parse, string
	{
		WinRing0.KeyDown(chr, delay)
		WinRing0.KeyUp(chr, delay)
		Sleep, % delay
	}
}
catfish00
Posts: 3
Joined: 24 May 2016, 07:33

Re: WinRing0 - Send keys in Hardware-Level

25 May 2016, 20:43

i have done like what u said before

but 。。。。。。。 run in win7 64x , any suggestion?
qwerty12
Posts: 468
Joined: 04 Mar 2016, 04:33
Contact:

Re: WinRing0 - Send keys in Hardware-Level

06 Jun 2016, 03:31

Thanks for the work and for sharing, tmplinshi. I really needed a library like this. BTW, the last "Ptr" on the DllCall for WriteIoPortByte should be removed.

If anyone happens to have a(n X230) ThinkPad, here's a script using WinRing0 that makes the microphone button LED flash when caps lock is active. I've tested it on my laptop, and while it didn't cause it to blow up, I do have to state that this should be tried at your own risk. If you want to run the script without compiling it, put the DLLs from MinHook into the same folder as the script.

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
ListLines, Off
SetBatchLines, -1
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir, %A_ScriptDir%
#KeyHistory 0
#InstallKeybdHook
#UseHook On
#Persistent
#SingleInstance force

; Registers of the embedded controller
global EC_DATAPORT := 0x62
global EC_CTRLPORT := 0x66
 
;Embedded controller status register bits
global EC_STAT_OBF := 0x01 ; Output buffer full 
global EC_STAT_IBF := 0x02 ; Input buffer full 
global EC_STAT_CMD := 0x08 ; Last write was a command write (0=data) 
 
; Embedded controller commands
; (write to EC_CTRLPORT to initiate read/write operation)
global EC_CTRLPORT_READ  := 0x80
global EC_CTRLPORT_WRITE := 0x81
global EC_CTRLPORT_QUERY := 0x84

; If running uncompiled, the line "static _Init := WinRing0.Init()" must be changed to "static _Init := 0"
#Include Class_WinRing0.ahk

if not A_IsAdmin
{
	Run *RunAs "%A_ScriptFullPath%"
	ExitApp
}
 
if (!A_IsCompiled)
{
	FindFirstFileHook(lpFileName, lpFindFileData)
	{
		global FindFirstFileOrigPtr
		if (lpFileName)
		{
			strEncoding := A_PtrSize == 8 ? "UTF-16" : "CP0"
			SplitPath, % StrGet(lpFileName, strEncoding), driverName
			if (driverName ~= "WinRing0(x64)?\.sys")
				StrPut(A_ScriptDir . "\" . driverName, lpFileName, 260, strEncoding) ; fingers crossed I don't get a pointer to something located in .text or something < MAX_PATH during the time this hook is active, WinRing0 is initialised and the hook is removed...
		}
		return DllCall(FindFirstFileOrigPtr, "Ptr", lpFileName, "Ptr", lpFindFileData, "Ptr")
	}
 
	minhookDll     := "MinHook." . (A_PtrSize == 8 ? "x64" : "x86") . ".dll"
	minhookModule  := DllCall("LoadLibrary", "Str", minhookDll, "Ptr")
	if (!minhookModule || DllCall(minhookDll . "\MH_Initialize") != 0)
		ExitApp 1
	FindFirstFileHookPtr := RegisterCallback("FindFirstFileHook", "Fast")
	if (DllCall(minhookDll . "\MH_CreateHookApi", "WStr", "kernel32", "AStr", "FindFirstFile" . (A_PtrSize == 8 ? "W" : "A"), "Ptr", FindFirstFileHookPtr, "Ptr*", FindFirstFileOrigPtr) != 0)
		ExitApp 1
	if (DllCall(minhookDll . "\MH_EnableHook", "Ptr", MH_ALL_HOOKS := 0) != 0)
		ExitApp 1
}
 
if (!WinRing0.dll)
	WinRing0._Init := WinRing0.Init()
if (!A_IsCompiled) {
	DllCall(minhookDll . "\MH_DisableHook", "Ptr", MH_ALL_HOOKS), DllCall(minhookDll . "\MH_Uninitialize")
	DllCall("FreeLibrary", "Ptr", minhookModule), minhookModule := 0
	DllCall("GlobalFree", "Ptr", FindFirstFileHookPtr, "Ptr"), FindFirstFileHookPtr := 0
}
OnExit("AtExit")
 
; Thanks to https://gitlab.com/valinet/thinkpad-leds-control
SetMicrophoneLedState(off:=false)
{
	ec_offset := 0x0C
	led := 0x0E
	state := (off || !GetKeyState("CapsLock", "T")) ? 0x00 : 0xC0
 
	WriteByteToEC(ec_offset, (led | state))
}
 
; Thanks to http://tp4xfancontrol.cvs.sourceforge.net/viewvc/tp4xfancontrol/tp4xfancontrol/source/portio.cpp?view=markup for the EC writing code
 
waitportstatus(bits, wantedstate)
{
	port := EC_CTRLPORT
	timeout := 1000
	time_ := 0
	tick := 10
	ret := false
 
	while (time_ < timeout) {
		data := DllCall(WinRing0.dll . "\ReadIoPortByte", "UShort", port, "UChar")
 
		if (wantedstate == (data & bits)) {
			ret := true
			break
		}
		DllCall("Sleep", "UInt", tick)
		time_ := time_ + tick
	}
	return ret
}
 
writeport(port, data)
{
	WinRing0.WriteIoPortByte(port, data)
	return true
}
 
WriteByteToEC(offset, data)
{
	; wait for IBF and OBF to clear
	ret := waitportstatus(EC_STAT_IBF| EC_STAT_OBF, 0)
	if (!ret)
		return false
 
    ; tell 'em we want to "WRITE"
    ret := writeport(EC_CTRLPORT, EC_CTRLPORT_WRITE)
	if (!ret)
		return false
 
    ; wait for IBF to clear (command byte removed from EC's input queue)
    ret := waitportstatus(EC_STAT_IBF, 0)
	if (!ret)
		return false
 
    ; tell 'em where we want to write to
    ret := writeport(EC_DATAPORT, offset)
	if (!ret)
		return false
 
    ; wait for IBF to clear (address byte removed from EC's input queue)
    ret := waitportstatus(EC_STAT_IBF, 0)
	if (!ret)
		return false
 
    ; tell 'em what we want to write there
    ret := writeport(EC_DATAPORT, data)
	if (!ret)
		return false
 
    ; wait for IBF to clear (data byte removed from EC's input queue)
    ret := waitportstatus(EC_STAT_IBF, 0)
	return ret
}

AtExit(ExitReason, ExitCode)
{
	if ExitReason not in Shutdown
	{
		if (WinRing0.dll && WinRing0.GetDllStatus() == "No error")
			SetMicrophoneLedState(true)
	}
	WinRing0 := ""
}

~CapsLock::SetTimer, SetMicrophoneLedState, -100
	
User avatar
losongved
Posts: 1
Joined: 15 Aug 2016, 22:20
Location: Beijing,China

Re: WinRing0 - Send keys in Hardware-Level

15 Aug 2016, 22:29

tmplinshi wrote:@JJohnston2:
I have compiled your example code. Try if it works:
https://www.dropbox.com/s/ui9vhe28ru1lj ... t.7z?raw=1
ur dropbox is temporarily disabled...
cant download the nessecery files, i found some a WinRing0.dll and sys files but your winring cant work.
pls help me,my email is [email protected]
Hello,world.
vasili111
Posts: 747
Joined: 21 Jan 2014, 02:04
Location: Georgia

Re: WinRing0 - Send keys in Hardware-Level

16 Aug 2016, 14:32

What is the reason for sending keys from Ring 0 ? Not detected by games or any other reason?
DRAKON-AutoHotkey: Visual programming for AutoHotkey.

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 126 guests