It's the anti telemetry thread, and i've come bearing gifts.
Let me preface this by saying i made a similar thread a good while ago, but i brought new scripts. These scripts are mostly untested but i figured i'd post them here anyway in case they may be useful to you. I will debug them when i finish up some other scripts related to what we'll be discussing, but if you happen to see a bug feel free to point them out in the mean time.
Anyway, i aspire to be a full stack autist and so i want to be able to code in most modern programming languages. This includes the ones specific to Windows. Dotnet Core is great for developing Windows software on Linux and you get pretty far with the SDK and VS Code. However until the .NET suite is fully cross compatible it pays to have a Windows install handy, besides, on Windows you can Live Debug the kernel with the right tools, which helps with understanding the internal mechanics of the OS, and the Windows Driver Kit runs only on Windows as well. Being able to write firmware helps me understand how to write kernel mode anything, more generally.
Long story short, understanding Windows helps me develop software for Windows as well as malware and exploits.
What i really want is a VM lab with different versions of all kinds of OS' that i can just remote into, but that's quite the undertaking so when i saw a Windows10 laptop on sale i decided to pick it up for the reasons i stated above. Anyway, i got my Development environment set up and just remote into it from my Linux box.
There are a lot of things i dislike about Windows, but one of the more insidious aspects of the OS is what basically amounts to data mining user and usage information AKA Telemetry. There was a Batch script on Github that used to have all the telemetry associated domains in it that automated the process of blacklisting those domains with the Windows firewall. However it didn't take long for Microsoft to wise up to this, so now it will just ignore the rule set when applied IIRC. The best way to block those domains is to make a blacklist in your router. However i want to try something else and have it automated.
To that end i wrote a PAC Script, on the off chance you never heard of a PAC script, it's a Proxy Auto Configuration script and it's written in JS, what's neat is that it allows you to specify very specific proxy rules for very specific domains/hosts. The OS will read the script and apply the proxy rules you defined there. In the case of Windows it used to be that you could just write a PAC script and point to it's location on your HDD in your Network Settings. Since Win10 however you are obliged to serve the script over HTTP, what's more, you need to make sure legacy proxy config support is enabled. We do that by creating the proper subkey in the Windows registry.
Below is my PowerShell implementation of the HTTP server and registry operations.
# PowerShell RegEdit and HTTP Server
$registryPath = "HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\"
$Name = "EnableLegacyAutoProxyFeatures"
$value = "1"
# Check to see if an entry exists and set value
# If it doesn't create the appropriate subkey
if(!(Test-Path $registryPath)) {
New-Item -Path $registryPath -Force | Out-Null
New-ItemProperty -Path $registryPath -Name $name -Value $value `
-PropertyType DWORD -Force | Out-Null
}
else {
New-ItemProperty -Path $registryPath -Name $name -Value $value `
-PropertyType DWORD -Force | Out-Null
}
# Http Server
$http = [System.Net.HttpListener]::new()
# Listen at 8080
$http.Prefixes.Add("http://localhost:8080/")
# Start the Http Server
$http.Start()
# Confirm
if ($http.IsListening) {
write-host " HTTP Server Listening " -f 'gre'
write-host " Please direct Windows Auto Proxy Config to http://127.0.0.1/:8080 " -f 'gre'
}
# Server Loop
while ($http.IsListening) {
$context = $http.GetContext()
if ($context.Request.HttpMethod -eq 'GET' -and $context.Request.RawUrl -eq '/') {
# Log to terminal
write-host "$($context.Request.UserHostAddress) => $($context.Request.Url)" -f 'gre'
# Get proxy.pac data
[string]$data = Get-Content "C:\some\path\proxy.pac" -Raw
# Field the request
$buffer = [System.Text.Encoding]::UTF8.GetBytes($data)
$context.Response.ContentLength64 = $buffer.Length
$context.Response.OutputStream.Write($buffer, 0, $buffer.Length) # Data stream
$context.Response.OutputStream.Close() # Close
}
I'm no PS wizard but i think this should do it, like i said i haven't tested this yet so if anything stands out to you please let me know and i will remedy any issues. Same goes for the PAC Script i have below.
<script type="application/x-ns-proxy-autoconfig">
//Special PAC functions:
// Hostname:
// isPlainHostName(host)
// dnsDomainIs(host, domain)
// localHostOrDomainIs(host, hostdom)
// isResolvable(host)
// isInNet(host, pattern, mask)
// Utility:
// dnsResolve(host)
// myIpAddress()
// dnsDomainLevels(host)
// URL:
// shExpMatch(str, shexp)
// Time:
// weekdayRange(wd1, wd2, gmt)
// dateRange(...)
// timeRange(...)
// Declare vars
var normal = "DIRECT";
var torsocks = "PROXY 127.0.0.1:9050"
var blackhole = "PROXY 127.0.0.1:55555";
function FindProxyForURL(url, host) {
if (dnsResolve(host) || shExpMatch(host, '*.local')
|| isInNet(dnsResolve(host), '10.0.0.0', '255.0.0.0')
|| isInNet(dnsResolve(host), '172.16.0.0', '255.240.0.0')
|| isInNet(dnsResolve(host), '192.168.0.0', '255.255.0.0')
|| isInNet(dnsResolve(host), '127.0.0.0', '255.255.255.0')) {
return normal;
}
if (shExpMatch((url, "*oca.telemetry.microsoft.com*")
|| shExpMatch(url, "*telecommand.telemetry.microsoft.com*")
|| shExpMatch(url, "*oca.telemetry.microsoft.com.nsatc.net*")
|| shExpMatch(url, "*a-0001.a-msedge.net*")
|| shExpMatch(url, "*a-0002.a-msedge.net*")
|| shExpMatch(url, "*a-0003.a-msedge.net*")
|| shExpMatch(url, "*a-0004.a-msedge.net*")
|| shExpMatch(url, "*a-0004.a-msedge.net*")
|| shExpMatch(url, "*a-0005.a-msedge.net*")
|| shExpMatch(url, "*a-0006.a-msedge.net*")
|| shExpMatch(url, "*a-0006.a-msedge.net*")
|| shExpMatch(url, "*a-0007.a-msedge.net*")
|| shExpMatch(url, "*a-0008.a-msedge.net*")
|| shExpMatch(url, "*a-0009.a-msedge.net*")
|| shExpMatch(url, "*i1.services.social.microsoft.com")
|| shExpMatch(url, "*telecommand.telemetry.microsoft.com.nsatc.net*")
|| shExpMatch(url, "*sqm.df.telemetry.microsoft.com*")
|| shExpMatch(url, "telemetry.appex.bing.net*")
|| shExpMatch(url, "*settings-sandbox.data.microsoft.com*")
|| shExpMatch(url, "*pre.footprintpredict.com")
|| shExpMatch(url, "*aidps.atdmt.com*")
|| shExpMatch(url, "*aka-cdn-ns.adtech.de*")
|| shExpMatch(url, "*a-msedge.net*")
|| shExpMatch(url, "*b.rad.msn.com*")
|| shExpMatch(url, "*az361816.vo.msecnd.net*")
|| shExpMatch(url, "*b.ads1.msn.com*")
|| shExpMatch(url, "*b.ads2.msads.net*")
|| shExpMatch(url, "*watson.telemetry.microsoft.com*")
|| shExpMatch(url, "*wes.df.telemetry.microsoft.com*")
|| shExpMatch(url, "*bs.serving-sys.com*")
|| shExpMatch(url, "*redir.metaservices.microsoft.com*")
|| shExpMatch(url, "*reports.wes.df.telemetry.microsoft.com*")
|| shExpMatch(url, "*cs1.wpc.v0cdn.net*")
|| shExpMatch(url, "*corpext.msitadfs.glbdns2.microsoft.comt*")
|| shExpMatch(url, "*df.telemetry.microsoft.com*")
|| shExpMatch(url, "*services.wes.df.telemetry.microsoft.com*")
|| shExpMatch(url, "*watson.telemetry.microsoft.com.nsatc.net*")
|| shExpMatch(url, "*sqm.telemetry.microsoft.com*")
|| shExpMatch(url, "*sqm.telemetry.microsoft.com.nsatc.net*")
|| shExpMatch(url, "*watson.ppe.telemetry.microsoft.com*")
|| shExpMatch(url, "*telemetry.microsoft.com*")
|| shExpMatch(url, "*telemetry.urs.microsoft.com*")
|| shExpMatch(url, "*survey.watson.microsoft.com*")
|| shExpMatch(url, "*watson.live.com*")
|| shExpMatch(url, "*vortex-sandbox.data.microsoft.com*")
|| shExpMatch(url, "*settings-win.data.microsoft.com*")
|| shExpMatch(url, "*watson.microsoft.com*")
|| shExpMatch(url, "*db3aqu.atdmt.com*")
|| shExpMatch(url, "*diagnostics.support.microsoft.com*")
|| shExpMatch(url, "*statsfe2.update.microsoft.com.akadns.net*")
|| shExpMatch(url, "*fe2.update.microsoft.com.akadns.net*")
|| shExpMatch(url, "*schemas.microsoft.akadns.net*")
|| shExpMatch(url, "*feedback.microsoft-hohm.com*")
|| shExpMatch(url, "*feedback.search.microsoft.com*")
|| shExpMatch(url, "*statsfe1.ws.microsoft.com*")
|| shExpMatch(url, "*statsfe1.ws.microsoft.com*")
|| shExpMatch(url, "*c.atdmt.com*")) {
// More to be added, maybe check against
// _dnsDomainIs as well
return blackhole;
} else {
return torsocks;
}
}
</script>
As you can tell i have all the telemetry related domains null routed. I also kept the list of special PAC functions there as a reminder and to get you guys' opinion on which one seems the most appropriate to use. Futhermore every other connection is going to be routed through the Tor network.
In order to do so i will be adding operations to my powershell script to invoke a special Tor binary. This binary doesn't come with the browser bundle so we don't need to have the Tor Browser running in the background wasting resources.
The binary in question:
https://dist.torproject.org/torbrowser/9.0.4/tor-win64-0.4.2.5.zip
https://dist.torproject.org/torbrowser/9.0.4/tor-win64-0.4.2.5.zip.asc
We might also want to get rid of any updates that are related to telemetry by running the `wusa` utility from a Batch file, which could probably also be done in powershell but whatever.
@ECHO OFF
SETLOCAL
REM #-KILL IT WITH FIRE-#
echo Uninstalling updates relevant to telemetry ops
echo Delete KB2902907 (Microsoft Security Essentials)
start "title" /b /wait wusa.exe /kb:2902907 /uninstall /quiet /norestart
echo Delete KB3022345 (telemetry)
start "title" /b /wait wusa.exe /kb:3022345 /uninstall /quiet /norestart
echo Delete KB3068708 (telemetry)
start "title" /b /wait wusa.exe /kb:3068708 /uninstall /quiet /norestart
echo Delete KB3080149 (Telemetry)
start "title" /b /wait wusa.exe /kb:3080149 /uninstall /quiet /norestart
Finally to make sure the HTTP server and Tor binary start at logon we can add a scheduled task with these commands.
schtasks /create /tn 'StageProxyOps' /tr powershell %USERPROFILE%\HTTP-Proxy-Server.ps1 /sc onstart /ru System
But since we're on the topic of persistence allow me to indulge for a second. I happened upon C++ source that came from Microsoft where they were talking about starting a sub process from a service. So I took the liberty to cut out any irrelevant bits and substitute the appropriate values, where needed, and now, should we want to we could probably just compile this and start our PowerShell script as a subprocess from the service after installing it with the `sc` utility.
Anyway, that's turbo over kill but i thought it was pretty neat so i figured i'd include it. To conclude, feel free to point out that i'm a big dumb if and where i went astray with any of this, that last one was included for the lulz but i'll happily receive constructive criticism regarding that as well.