-
-
Save jcary741/19cc74c93a499f8c23ad7dd5a04faf86 to your computer and use it in GitHub Desktop.
# Version: 0.1 (2025-01-18) | |
# License: MIT, use at your own risk | |
# | |
# This script disables the Lenovo-installed "Tobii experience" software and "nahimic" software. | |
# Tested on a Lenovo Legion Pro 5 (82WM) with Windows 11 24H2. | |
# Run it with `powershell.exe -noprofile -executionPolicy Bypass -File badlenovo.ps1` | |
# Following this script, you should be able to uninstall the "Tobii experience" app from the control panel (appwiz.cpl) | |
# | |
# After major updates, you may need to re-run this script. | |
# Disable services (may be re-enabled on reboot) | |
Get-Service -Name "Tobii*" | Stop-Service -Force | |
Get-Service -Name "Tobii*" | Set-Service -StartupType Disabled | |
Get-Service -Name "Nahimic*" | Stop-Service -Force | |
Get-Service -Name "Nahimic*" | Set-Service -StartupType Disabled | |
# Get the service exe paths | |
$services = Get-WmiObject -Class Win32_Service | Where-Object {$_.Name -like "Tobii*" -or $_.Name -like "Nahimic*"} | Select-Object PathName | |
$services = $services.PathName -split "`n" | ForEach-Object { $_.Replace('"', '').Trim() } | |
$services = $services -replace '\.exe.*', '.exe' | |
## use icacls to deny access to the service exes, so that they can't be started | |
$services | ForEach-Object { | |
$servicePath = $_ | |
$acl = Get-Acl $servicePath | |
$denyEveryone = New-Object System.Security.AccessControl.FileSystemAccessRule("Everyone", "FullControl", "Deny") | |
$denySystem = New-Object System.Security.AccessControl.FileSystemAccessRule("SYSTEM", "FullControl", "Deny") | |
$acl.SetAccessRule($denyEveryone) | |
$acl.SetAccessRule($denySystem) | |
Set-Acl $servicePath $acl | |
} | |
# Find "devices" that are installed by the Tobii or nahimic software and disable them | |
$devices = Get-PnpDevice | Where-Object {$_.FriendlyName -like "Tobii*" -or $_.FriendlyName -like "Nahimic*"} | Select-Object FriendlyName,InstanceId | |
$devices | ForEach-Object { | |
$device = $_ | |
$instanceId = $device.InstanceId | |
$friendlyName = $device.FriendlyName | |
Disable-PnpDevice -InstanceId $instanceId -Confirm:$false | |
Write-Host "Disabled device: $friendlyName" | |
} |
Hi Jay!
Nice script and great that someone cares to take action and try to remove this spyware!
However, I would have preferred that you don't remove Nahimic, as I believe it is only sound card related, and may actually be useful. Unless you have other insight I may have missed? (Or make an option to keep it.)
Here are some of my own findings:
# ffind 'C:\' '*Tobii*'
# Driver File Locations
C:\Windows\INF\Tobii Interaction Engine\
C:\Windows\INF\oem150.inf
C:\Drivers\Tobii\Tobii.LenovoYX80.Offline.Installer_4.182.0.29391.msi
# Users Files Locations
%USERPROFILE%\AppData\Local\Tobii\
C:\Users\<username>\AppData\Local\Tobii\
C:\Users\Default\AppData\Local\Tobii\
C:\Users\admin\AppData\Local\Publishers\j9ea20k37yd2w
C:\Users\Administrator\.tobii\tobii.tsc.id
C:\Users\<username>\.tobii\tobii.tsc.id
# File Locations
C:\Program Files\Tobii\
C:\ProgramData\Tobii\
C:\Windows\Prefetch\TOBII.SERVICE.EXE-A921445A.pf
# Other OS File Locations:
C:\Windows\SysWOW64\config\systemprofile\AppData\Local\Tobii\
C:\Windows\System32\config\systemprofile\AppData\Local\Tobii\
C:\Program Files\WindowsApps\TobiiAB.TobiiEyeTrackingPortal_1.71.35880.0_x64__j9ea20k37yd2w\Tobii.EyeTracking.Portal.WPF\
C:\ProgramData\Microsoft\Windows\AppRepository\TobiiAB.TobiiEyeTrackingPortal_1.*.xml
- Uploads encrypted SQLite3 facial/eye pattern DB to their servers via API at:
https://api.statistics.ice.tobii.com/uploadSession - ⬆️ This need to be blocked in all levels. Using Windows Firewall (
WF.msc
or viaFirewall.cpl
) and/or inhosts
file:
C:\Windows\System32\drivers\etc\hosts
However, Windows hosts file is not very convenient as it is not possible to wildcard ranges, as you have to specify each URL exactly. You should really use the WF.
# Edit:
# C:\Windows\System32\drivers\etc\hosts
# and add:
127.0.0.1 api.statistics.ice.tobii.com # Tobii Malware API
::1 api.statistics.ice.tobii.com # Tobii Malware API
# After editing, reboot computer, or flush the DNS cache using:
# ipconfig /flushdns
Get the IP's used for the above API:
# Resolve-DnsName "api.statistics.ice.tobii.com"
Name Type TTL Section IPAddress
---- ---- --- ------- ---------
api.statistics.ice.tobii.com A 60 Answer 18.154.63.45
api.statistics.ice.tobii.com A 60 Answer 18.154.63.48
api.statistics.ice.tobii.com A 60 Answer 18.154.63.19
api.statistics.ice.tobii.com A 60 Answer 18.154.63.39
Important
It seem that the cloudfront.net
servers are dynamically rotating the IP addresses, making it nearly impossible to block based on raw IP address alone.
Some other useful powershell commands fore reference:
Resolve-DnsName "statistics.ice.tobii.com"
Resolve-DnsName "ice.tobii.com"
Resolve-DnsName "tobii.com"
# dig api.statistics.ice.tobii.com
# nslookup api.statistics.ice.tobii.com
# Create a FW rule:
# Be careful as you may block unrelated IP's if you use `/24`.
New-NetFirewallRule -DisplayName "Block Tobii Malware API IP addresses" -Direction Outbound -LocalPort Any -Protocol TCP -Action Block -RemoteAddress 18.66.122.1/24
Check out:
https://www.robtex.com/dns-lookup/tobii.com
and consider checking the similar domains.
Thanks @eabase for looking into this. I think leaving the files intact for the moment is probably best, since I don't know what other places Tobii registers them. I'm more interested in crippling it than full removal and cleanup. On that note, I think it is an awesome idea to block requests to tobii's domain(s), but if you're correct that they're using cloudflare, then it's unlikely it can be effectively blocked via IP-based blocking. DNS blocking could be effective here, and it may be possible to get them added to some of the common blocklists. I have reported it to one of the commonly used Pi-hole blocklists here. Would you mind seeing if you can report it in OpenDNS? If you do, and there's a way I can add support, I will do so.
Regarding Nahimic, I understand it's possibly only a PUP, but I'm suspicious of it and it's not required for the sound device to operate normally from what I was seeing. Do you have a specific need for it? Also, how did you learn about the tobii telemetry domain? Can you check that there's not something similar with Nahimic?
Thanks again for your help, I really appreciate it.
I have reported the endpoint to AWS as well, in the hope that they will find this use violates their ToS.
Hey! Sorry for delayed answer.
I see you filed a report to pi-hole repo, that they almost immediately implemented. Awesome!
The number of TLD's and other domains that Tobii AB
/ Tobii Technology AB
has registered is crazy. Doing a reverse DNS/WhoIs on registrar give about >285 related domains, and 193 different active TLDs.
Just from a few strings in the latest update (Middleware_Bundle_v4.74.1.35913_x64
) we also have:
https://api.readyplayer.me/v1/
https://eyetracking.mobalytics.gg/
https://gaming.tobii.com/downloadlatest/?bundle=ghost
Some of the files are encoded in UTF-16 so can be tricky to grep...
The SQLite3 DB's seem custom compiled and may be encrypted.
Also, how did you learn about the tobii telemetry domain?
I found it under a failed upload in a log file at:
C:\ProgramData\Tobii\Tobii Platform Runtime\RGB\pr_log0.txt
[W] Platmod runtime configuration not set
WARN- [PRSTATS---] "Failed to open file, error: 2" {FileName:"platform_runtimes/common/config/src/pr_config.cpp(95)",Function:"pr_config_get",Tags:["PRCONF"]}
INFO- [statistics] "Initialized statistics library API c1be9962-d447-4916-9b97-a92cb82055e4" {FileName:"external/statistics/src/tobii_statistics.cpp(240)",Function:"tstats_api_create",Tags:["statistics"]}
ERROR [statistics] "Failed to upload. (6) Couldn't resolve host name https://api.statistics.ice.tobii.com/uploadSession " {FileName:"external/statistics/src/uploader/src/uploader.cpp(233)",Function:"curl_init_t::post",Tags:["CURL"]}
ERROR [statistics] "Failed to upload. Server response code was: (0) " {FileName:"external/statistics/src/uploader/src/uploader.cpp(237)",Function:"curl_init_t::post",Tags:["CURL"]}
ERROR [statistics] "Failed to upload 0" {FileName:"external/statistics/src/upload_flow.cpp(326)",Function:"upload_flow_verify_payload_status",Tags:["FLOW"]}
ERROR [statistics] "Failed to upload. (6) Couldn't resolve host name https://api.statistics.ice.tobii.com/uploadSession " {FileName:"external/statistics/src/uploader/src/uploader.cpp(233)",Function:"curl_init_t::post",Tags:["CURL"]}
ERROR [statistics] "Failed to upload. Server response code was: (0) " {FileName:"external/statistics/src/uploader/src/uploader.cpp(237)",Function:"curl_init_t::post",Tags:["CURL"]}
ERROR [statistics] "Failed to upload 0" {FileName:"external/statistics/src/upload_flow.cpp(326)",Function:"upload_flow_verify_payload_status",Tags:["FLOW"]}
[I] [MODULE] [ThreadID=2684] module.cpp(269) "Device manager thread started" in function "device_changes_processing_thread_proc"
ERROR [statistics] "Didn't manage to upload everything Total 2 != Successfull 0" {FileName:"external/statistics/src/internal.cpp(195)",Function:"database_restore::callback_t::callback",Tags:["statistics"]}
[W] [PLATMOD] [ThreadID=da8] pmm.cpp(330) "setman_init: Failed to load face id db file." in function "pmm_t::init::<lambda_xxx>::operator ()"
[W] [PLATMOD] [ThreadID=da8] pmm.cpp(330) "setman_init: Failed to read calibration file." in function "pmm_t::init::<lambda_xxx>::operator ()"
[W] [PLATMOD] [ThreadID=da8] pmm.cpp(330) "setman_init: Failed to read camera info file." in function "pmm_t::init::<lambda_xxx>::operator ()"
Finally, I seem that the update was force installed! I did not run the update, so after latest windows-11 24H2 update, it auto updated while I was not present.
There is a tool that is supposed to disable the pending Windows Updates.
It's written in powershell, but it's old with outdated syntax and scattered over dozen files, so I'm looking to rewrite it in one file...
It would also be useful to write a registry scan function that searches for all Tobii related Registry keys.
And also check Task Scheduler.
Yeah, some of the conversations on Reddit mentioned using wushowhide to prevent the "driver" from being reinstalled, but MS had previously indicated the tool would stop working in a future update and, I guess, 24H2 is it. So, with that ineffective, I think trying to attack it at the update-level may be rather difficult. I've been wondering if there's a way to remove the virtual device that Windows is detecting as requiring the driver, but I'm not sure where to start. In attempting to remove Tobii, I tried a full system wipe and re-install, but the Tobii was reinstalled as soon as Windows update ran. I suspect this will require the same techniques as fighting a firmware rootkit, but that's beyond my experience.
@eabase Can you upload / share C:\Drivers\Tobii\Tobii.LenovoYX80.Offline.Installer_4.182.0.29391.msi
, since I previously wipe my device, I don't seem to have that installer file, but realize now that it may be important for further investigation.
Can you upload ...
*.msi
You can find the Download here:
https://help.tobii.com/hc/en-us/articles/5278376717329-Driver-downloads-for-Lenovo
MS had previously indicated the tool would stop working in a future update...
You can't trust anything MS says, even their own engineers use Windows Key hacks to fix issues...
But you can disable automatic updates, using the registry:
# To Disable Windows-11 (24H2) Auto-update:
# Open an Admin shell and use:
HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU
$LP = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU\"
# OK
Get-ItemProperty -Path $LP -Name "NoAutoUpdate"
Set-ItemProperty -Path $LP -Name "NoAutoUpdate" -Value 1 -Force | Out-Null
Or alternatively by setting group policy gpedit.msc
.
See:
- https://learn.microsoft.com/en-us/windows/deployment/update/waas-wu-settings
- https://admx.help/HKLM/Software/Policies/Microsoft/Windows/WindowsUpdate/AU
I also found this Search-Registry script, which you can use to pry out Tobii
related items from the registry. Use like this:
Search-Registry -Path 'HKCU:\SOFTWARE\*' -Recurse -ValueNameRegex "Tobii" -ValueDataRegex "Tobii" -KeyNameRegex "Tobii" -ErrorAction SilentlyContinue -Verbose | Select Reason,Details, Key | ft
# OR
Search-Registry -Path 'HKCU:\SOFTWARE\*' -Recurse -SearchRegex "Tobii" -ErrorAction SilentlyContinue | Select Reason,Details,Key | fl
Awesome, thank you. I'm hopeful for non-gpedit based solutions so Win 11 home users can benefit also. So here's a new idea: a noop driver that can be installed for the "device" so that Windows stops trying to install the tobii one. I suspect this would survive anything but a system restore. One thing I'm unsure of is if the driver would need to be signed. @eabase any experience with this?
If you look in the Tobii device driver file, you will find the following cameras:
vid:pid 04F2:B7B6 # Chicony Electronics #
vid:pid 04F2:B7B8 # Chicony Electronics #
vid:pid 174F:246A # Syntek #
vid:pid 30C9:00A6 # Luxvisions Innotech Limited # Lenovo Legion
vid:pid 30C9:00AC # Luxvisions Innotech Limited # Lenovo Legion [Windows-11 reports as: SunplusIT]
vid:pid 5986:118A # Bison Electronics # Lenovo Legion
So it seem that Tobii is only used on a few (built-in) cameras.
I think at this point it should be enough to:
- Report all Tobii executables & some of their API collecting websites to Virustotal as malware/distributors.
- Registry Disable Win automatic updates (manually click to get new, and then close pending garbage updates)
- Registry corrupt Tobii keys
- Disable Tobii services
- Disable Tobii tasks in Task scheduler
- Rename Tobii executables
- Corrupt Tobii HW drivers (
oem150.inf
,oem51.inf
etc.) - Block all Tobii related executables (and API URL's) in windows firewall.
BTW. To get the Tobii related drivers you can use the following:
# Open admin shell
dism /online /get-drivers /format:table | findstr "Tobii"
#oem147.inf | lenovoyxx0extension.inf | No | Extension | Tobii AB | 2024-06-19 | 1.164.0.35934
#oem150.inf | lenovoyxx0.inf | No | SoftwareComponent | Tobii AB | 2024-06-19 | 1.164.0.35934
#oem51.inf | lenovoyxx0.inf | No | SoftwareComponent | Tobii AB | 2023-10-13 | 1.152.0.33335
# Backup them up, and then remove them with
pnputil.exe /d oemXX.inf
Deleting these drivers seems to only be possible if the host device is removed or disabled. I have removed with
# Open admin shell # navigate to a directory like documents or tmp then pnputil /enum-devices > devices.txt # open devices.txt file and ctrl+f for "Tobii" # there should be a device listed, with a driver inf matching what you are trying to remove # now copy that device Instance ID and remove the device, for example: pnputil /remove-device "USB\VID_045E&PID_00DB\6&870CE29&0&1" # now you should be able to remove the driver inf with pnputil.exe /d oemXX.inf
Time will tell if this needs to be repeated or not for me.
I'd be very careful with actually removing a device. If you accidentally get it wrong...that's a PITA to fix.
You can always remove a driver with the /force
switch, so read the help from pnputil.exe --help
.
/delete-driver <oem#.inf> [/uninstall] [/force] [/reboot]
Delete driver package from the driver store.
/uninstall - uninstall driver package from any devices using it.
/force - delete driver package even when it is in use by devices.
/reboot - reboot system if needed to complete the operation.
Examples:
Delete driver package:
pnputil /delete-driver oem0.inf
Force delete driver package:
pnputil /delete-driver oem1.inf /force
Instead disable the device, in case something goes wrong.
/disable-device [<instance ID> | /deviceid <device ID>] [/class <name | GUID>]
[/bus <name | GUID>] [/reboot] [/force]
Disable devices on the system.
/deviceid <device ID> - disable all devices with matching device ID.
/class <name | GUID> - filter by device class name or GUID.
/bus <name | GUID> - filter by bus enumerator name or bus type GUID.
/reboot - reboot system if needed to complete the operation.
/force - disable even if device provides critical system functionality.
Examples:
Disable device:
pnputil /disable-device "USB\VID_045E&PID_00DB\6&870CE29&0&1"
Disable all devices with specific hardware/compatible ID:
pnputil /disable-device /deviceid "USB\Class_03"
Disable all devices of a specific class on a specific bus:
pnputil /disable-device /class "USB" /bus "PCI"
I've only had this device for a few days, so will expand / update this script as needed.