Page 1 of 2

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

Posted: 25 Jul 2015, 11:15
by tmplinshi
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)

Re: WinRing0 - Send keys in Hardware-Level

Posted: 04 Oct 2015, 16:10
by Array
Nice :lol:

Re: WinRing0 - Send keys in Hardware-Level

Posted: 21 Oct 2015, 23:00
by JJohnston2
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.

Re: WinRing0 - Send keys in Hardware-Level

Posted: 22 Oct 2015, 04:33
by tmplinshi
@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.

Re: WinRing0 - Send keys in Hardware-Level

Posted: 22 Oct 2015, 12:15
by alwayswhy2014
is it posible use with controlsend?

Re: WinRing0 - Send keys in Hardware-Level

Posted: 22 Oct 2015, 19:56
by tmplinshi
alwayswhy2014 wrote:is it posible use with controlsend?
You mean send to inactive window? I don't think so.

Re: WinRing0 - Send keys in Hardware-Level

Posted: 25 Oct 2015, 09:15
by joedf
Impressive! :)

Re: WinRing0 - Send keys in Hardware-Level

Posted: 25 Oct 2015, 23:06
by JJohnston2
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.

Re: WinRing0 - Send keys in Hardware-Level

Posted: 26 Oct 2015, 00:30
by tmplinshi
@JJohnston2:
I have compiled your example code. Try if it works:
https://www.dropbox.com/s/ui9vhe28ru1lj ... t.7z?raw=1

Re: WinRing0 - Send keys in Hardware-Level

Posted: 27 Oct 2015, 00:35
by JJohnston2
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.

Re: WinRing0 - Send keys in Hardware-Level

Posted: 27 Oct 2015, 01:32
by JJohnston2
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.

Re: WinRing0 - Send keys in Hardware-Level

Posted: 27 Oct 2015, 02:26
by tmplinshi
Your example code is working for me. Have you tried Run As Administrator? Otherwise I've no idea what the problem is.

Re: WinRing0 - Send keys in Hardware-Level

Posted: 28 Oct 2015, 00:33
by JJohnston2
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.

Re: WinRing0 - Send keys in Hardware-Level

Posted: 24 May 2016, 07:47
by catfish00
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.

Re: WinRing0 - Send keys in Hardware-Level

Posted: 24 May 2016, 07:54
by catfish00
WinRing0.SendStr 111111

sometimes input 1
sometimes input 111
never be 111111
i input password in activeX embedded on browser, such as password control

Re: WinRing0 - Send keys in Hardware-Level

Posted: 24 May 2016, 23:45
by tmplinshi
@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
	}
}

Re: WinRing0 - Send keys in Hardware-Level

Posted: 25 May 2016, 20:43
by catfish00
i have done like what u said before

but 。。。。。。。 run in win7 64x , any suggestion?

Re: WinRing0 - Send keys in Hardware-Level

Posted: 06 Jun 2016, 03:31
by qwerty12
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
	

Re: WinRing0 - Send keys in Hardware-Level

Posted: 15 Aug 2016, 22:29
by losongved
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]

Re: WinRing0 - Send keys in Hardware-Level

Posted: 16 Aug 2016, 14:32
by vasili111
What is the reason for sending keys from Ring 0 ? Not detected by games or any other reason?