I'm a pretty carefree guy, experimenting with all kinds of weird applications from dubious sources. The domain and the network is pretty well secured, but my virtual lab computers are like people in the old west; unregulated and easily killed off if they become to unwieldy.
Still, when something suspicious happens I wan't to know why, because of course I wan't.
Some time ago the following dialog suddenly popped up when I logged in to my work computer;
What? No, I would not like to allow Regedit.exe to make changes to my device. Searching through the startup locations with Sysinternals excellent Autoruns didn't reveal anything and concurrent logons did not start Regedit.exe. Probably, it was launched by the RunOnce registry key. Difficult to troubleshoot when the traces are gone.
Weeks later it appeared again! What program is causing this? Why does it want to start Regedit.exe? How do I find out when it only happens once every month or so? None of my coworkers have had the same experience and even though I have a black belt in Google-fu searching the web was hard, only resulting in how to use Regedit. I know this already!
Then it appeared on my clean virtual lab computer, not in any way related to my domain joined work computer. Luckily I had just done a snapshot of it and Regedit.exe wanted to start every time I restored. Finally some progress! Using my incredible skills I finally found the culprit using Procmon, the greatest tool of all time;
Indeed it was a RunOnce registry key and the name of it, "Application Restart #1" is the clue. Since some version ago (who knows which, versioning sucks) Windows restarts select applications that were running when the computer was shut down. Not only during forced restarts from updates, but when you manually shut down the computer. Apparently I am not very good at closing programs before shutting the PC down.
Not all programs are restarted and how Windows decides this is still a mystery to me. It's a badly documented feature with a badly thought through workaround. This is what Microsoft Answers says about it.
Regardless, Regedit.exe, or any program requiring elevation, should not be started automatically!
Or is it requireing? Require-ing? Reqiruing? My Google-fu might not be as advanced as I thought.
A diary of a frustrated application manager and the adventurous world of application testing, packaging and deployment.
tisdag 20 mars 2018
Application restart #1
Etiketter:
consent.exe,
google,
Microsoft,
Procmon,
regedit,
regedit.exe,
registry,
requireAdministrator,
restart,
security alert,
Sysinternals,
trouble shooting,
troubleshooting,
uac,
Windows,
windows security
onsdag 14 mars 2018
Mismanaged code
Managed code is all the rage. Once long ago we had either slow code that was interpreted during runtime or fast compiled code that was built into a binary which the processor could execute natively. Microsoft said fuck this shit and introduced a middle ground. Probably to combat their mess of an operating system. To be fair, Microsoft wasn't first, they were just the ones to come up with the name.
Managed code does compile, not into something that is understood by the hardware CPU, but by a virtual processor. This way the program can be made more secure and portable between different architectures among other things. Java and dotNet are the most common platforms for managed code.
One of the many many problems with Windows is the convoluted way it runs and separates the 32 and 64 bit environment. Adding a third architecture, code that compiles into something that is neither 32 nor 64 bit Intel instructions adds to the confusion.
I wrote earlier about how a 64 bit Windows is really two Windows in one, Windows On Windows. As you might remember in the unlikely case you read that post, 32 bit processes access the 32 bit operating system, and 64 bit processes access the 64 bit one.
So, which OS is accessed by a program written in managed code?
It depends.
Lets say you need to deploy a program that requires some third party database client for an ODBC connection. The supplier tells you it needs the 64 bit version, "or it wont work". You have the 32 bit one installed sitewide already and you know they don't play well together. You know this, because you are an ORACLE.
Luckily, the program you need to deploy is written in C#. If a dotNet program utilize the 32 or 64 bit environment is decided by the programmer at compile time by setting the target platform. If he does not, it compiles to AnyCPU which chooses the 64 bit platform if available.
With the Microsoft tool corflags this can be changed after the fact! Flags in the file header tells the runtime environment if 32 bit is preferred or required and voila the program works well with the already installed 32-bit ODBC, saving me a lot of future work and headaches.
Java programs can be launched with either a 32 or 64 bit javaw.exe. Most Java programs can be launched with a specific client, bundled with the program itself. This is useful since most Java versions are incompatible with anything. But that's a different blog post.
Right now I'm working on something that is going to bring a different kind of headache. Cheers!
Managed code does compile, not into something that is understood by the hardware CPU, but by a virtual processor. This way the program can be made more secure and portable between different architectures among other things. Java and dotNet are the most common platforms for managed code.
One of the many many problems with Windows is the convoluted way it runs and separates the 32 and 64 bit environment. Adding a third architecture, code that compiles into something that is neither 32 nor 64 bit Intel instructions adds to the confusion.
I wrote earlier about how a 64 bit Windows is really two Windows in one, Windows On Windows. As you might remember in the unlikely case you read that post, 32 bit processes access the 32 bit operating system, and 64 bit processes access the 64 bit one.
So, which OS is accessed by a program written in managed code?
It depends.
Lets say you need to deploy a program that requires some third party database client for an ODBC connection. The supplier tells you it needs the 64 bit version, "or it wont work". You have the 32 bit one installed sitewide already and you know they don't play well together. You know this, because you are an ORACLE.
Luckily, the program you need to deploy is written in C#. If a dotNet program utilize the 32 or 64 bit environment is decided by the programmer at compile time by setting the target platform. If he does not, it compiles to AnyCPU which chooses the 64 bit platform if available.
With the Microsoft tool corflags this can be changed after the fact! Flags in the file header tells the runtime environment if 32 bit is preferred or required and voila the program works well with the already installed 32-bit ODBC, saving me a lot of future work and headaches.
Java programs can be launched with either a 32 or 64 bit javaw.exe. Most Java programs can be launched with a specific client, bundled with the program itself. This is useful since most Java versions are incompatible with anything. But that's a different blog post.
Right now I'm working on something that is going to bring a different kind of headache. Cheers!
fredag 2 mars 2018
Different minds, different worlds. A case study.
The giants in the new world are called Google, Apple or Microsoft. In the old ages, they were called Siemens or Asea Brown Boveri.
Lets compare their philosophy when it comes to deliver software products. I've made an easy to understand table comparing a typical Google program, such as Google Earth, with software from ABB or Siemens, such as ABB Automation Builder or Siemens Totally Integrated Automation Portal (say it quickly five times).
Lets compare their philosophy when it comes to deliver software products. I've made an easy to understand table comparing a typical Google program, such as Google Earth, with software from ABB or Siemens, such as ABB Automation Builder or Siemens Totally Integrated Automation Portal (say it quickly five times).
| ABB and Siemens | |
|---|---|
| Small msi or single file setup. | Ginormous installer, dozens or even hundreds of smaller setups, wrapped in a launcher, difficult or impossible to install without the wrapper. |
| Installs in under 1 minute. | Takes hours. Often takes a different amount of time to install each time, even on the same clean computer. Fails unpredictably. |
| Silent install with simple parameters. | Nope, never in a million years. Even autoclicking through the install is difficult, because the control IDs change or buttons are not real buttons. |
| Just works. | Doesn't work. Drivers bluescreen! Actually crashes regsvr32! Has issues with UAC and Credential Guard, can't install in Console 0, and even has problems with long filenames. I mean, long filenames, seriously? |
| Seamless automatic updates. | Requires elevation for updates nobody is asking for, and also for add on modules you are asking for but are not included in the offline install. |
| Secure. | Requires full permission in its many many Program Files folders and can't be installed elsewhere, breaking AppLocker security. Confusing number of processes requiring firewall exceptions. |
| Distinctly different programs each with a clear purpose. | Several identical looking programs with no description of what they are for or what the differences are. |
| Just download. | After registering an account and finally finding the correct program using a horrible search engine, you are told you don't qualify to download their precious software. |
| Just install and run. | After finally installing you are told you need to apply for a license or to put a hardware dongle into the USB. Who pirates engineering software? |
| Usually a free version, the paid version costs a few dollars. | Costs a fortune. |
| Program is contained in one folder. | Installs everywhere, including the root of the drive. Computer is never the same again. |
| Modern look and feel. | GUI like it's 1999. |
| Explore the entire world. | Automates something something, except itself. |
| Steals your soul. | Forces you to slowly descend into madness. |
Etiketter:
abb,
deploy,
deployment,
google,
msi,
siemens,
silent install,
uac,
unattended,
windows installer
torsdag 15 februari 2018
Prepare deployment by reading these two thousand pages
Some companies think their product is the best. It's da bomb as they might say, if bombing was a positive thing for software to do.
They think their product is such a gift to humanity they expect you to read through dozens or hundreds of pages even to just get past the EULA.
This might be fine for the user who purchased the application who then spend days excitingly exploring this new wonderous program.
It is not fine at all for the application deployer who has 550 other applications to manage and can't spend his full time job just on your special snowflake and don't give a shit about how great it is, or even what it does or why. Yes, 550 is the actual number of applications that I manage.
This is the Oracle Database Client Installation Guide. Also available as PDF it is 84 painfully boring pages, and yet when it comes to the most critical part of the installation, what components to include or not include, all it says is;
They think their product is such a gift to humanity they expect you to read through dozens or hundreds of pages even to just get past the EULA.
This might be fine for the user who purchased the application who then spend days excitingly exploring this new wonderous program.
It is not fine at all for the application deployer who has 550 other applications to manage and can't spend his full time job just on your special snowflake and don't give a shit about how great it is, or even what it does or why. Yes, 550 is the actual number of applications that I manage.
This is the Oracle Database Client Installation Guide. Also available as PDF it is 84 painfully boring pages, and yet when it comes to the most critical part of the installation, what components to include or not include, all it says is;
If you selected Custom as the type of installation in step 4, then the Available
Product Components screen is displayed. Select the products that you want to
install and click Next.
What? How the fuck am I supposed to know what "Product Components" that "I want"? I don't want to install anything, I have to. What I want is to know what the fuck I have to install and why. Do my clients need "Oracle SQLJ"? How am I supposed to know that?
What I want. Apparently.
This is the Deployment guide for Office 365 ProPlus. Who on Earth has the time to read that through? Does it say anything about how licensing works on shared computers? I don't know because there is too much text.
The Overview: Deploying Creative Cloud for enterprise starts with a seven and a half minute long video. That is the overview. The full guide is found here with more pages than I care to count.
A deployment guide should consist of a single page. This is what I need to know:
- Prerequirements. Do your program require some other program?
- What the components are for and which are required.
- How to configure the install. If it's an MSI, use properties.
- What the error codes mean. ALL of them.
What do these companies think I do at work all day long?
Not working, that's what.
fredag 9 februari 2018
Globally Unique Identifier
Globally Unique Identifier is a genious thing when you need a globally unique identifier! They are not as brilliant when they are used everywhere you would need a human-readable name, because of laziness.
If you've ever been troubleshooting a Windows program, and you have if you are reading this blog, you are fully aware of the frustration you feel trying to find the associated file from a class identifier in the registry or when figuring out which program C:\Windows\Installer\{136688F1-EF42-414E-92D6-BFF4D25EE688}\ARPPRODUCTICON.exe belongs to.
Usually you just copy the GUID into the clipboard and paste it into an appropriate search box. Isn't obvious that {25336920-03F9-11cf-8FD0-00AA00686F13} is the CLSID for "Browse in place"?
It doesn't help then, at all, that there are two ways of storing the GUID, either normally or compressed. And by "compressed" I mean "not really compressed, just a little different to annoy people and make their life harder".
How to convert between a standard and a compressed GUID:
Have you seen anything dumber than this, lately?
Also note that the "Browse in place" GUID, usually found under keys such as HKCR\htmlfile or HKCR\jpegfile, have two lowercase letters for no reason. It's likely true on your Windows too. To be truly globally unique, GUIDs should be generated by an algorithm standardized by ISO, IEC or someone with power to standardize. I am not sure, but I doubt the algorithm is inconsistent with upper and lower case.
Sometimes it is obvious the GUID is not random, as in the case with Microsoft Office;
The product code for Office consists of it's version and language and such, ending in "0FF1CE" as Microsoft describes here. My Office 2016 Pro has a GUID of {90160000-0011-0000-0000-0000000FF1CE}.
Older Java clients had class IDs starting with "CAFE"; {CAFEEFAC-0013-0000-0003-ABCDEFFEDCBA}, or maybe it should read "Café fuck", because that is how I read it.
Finding the product code for an msi install is trivial when the program is already installed, but often you would like to avoid littering your computer, even your virtual one, with garbage unless you really have to.
I wrote a tool to list the product codes of all msi files in a folder, and also put them in the clipboard for easy pasting into your uninstall-script. Download it here.
If you don't dare to download unknown programs and run them on your computer you are not an application deployer.
If you've ever been troubleshooting a Windows program, and you have if you are reading this blog, you are fully aware of the frustration you feel trying to find the associated file from a class identifier in the registry or when figuring out which program C:\Windows\Installer\{136688F1-EF42-414E-92D6-BFF4D25EE688}\ARPPRODUCTICON.exe belongs to.
Usually you just copy the GUID into the clipboard and paste it into an appropriate search box. Isn't obvious that {25336920-03F9-11cf-8FD0-00AA00686F13} is the CLSID for "Browse in place"?
How to convert between a standard and a compressed GUID:
Have you seen anything dumber than this, lately?
Also note that the "Browse in place" GUID, usually found under keys such as HKCR\htmlfile or HKCR\jpegfile, have two lowercase letters for no reason. It's likely true on your Windows too. To be truly globally unique, GUIDs should be generated by an algorithm standardized by ISO, IEC or someone with power to standardize. I am not sure, but I doubt the algorithm is inconsistent with upper and lower case.
Sometimes it is obvious the GUID is not random, as in the case with Microsoft Office;
The product code for Office consists of it's version and language and such, ending in "0FF1CE" as Microsoft describes here. My Office 2016 Pro has a GUID of {90160000-0011-0000-0000-0000000FF1CE}.
Older Java clients had class IDs starting with "CAFE"; {CAFEEFAC-0013-0000-0003-ABCDEFFEDCBA}, or maybe it should read "Café fuck", because that is how I read it.
Finding the product code for an msi install is trivial when the program is already installed, but often you would like to avoid littering your computer, even your virtual one, with garbage unless you really have to.
I wrote a tool to list the product codes of all msi files in a folder, and also put them in the clipboard for easy pasting into your uninstall-script. Download it here.
If you don't dare to download unknown programs and run them on your computer you are not an application deployer.
onsdag 31 januari 2018
What version is this?
Everybody hates versioning. Everybody.
You can easily tell this by the fact that nobody does it unless forced to do so, and mostly not even then.
There is a long and very boring Wikipedia-page about versioning but let me sum it up for you without ever having read it. Your software should have a version number in a format like this:
Swap build and revision if you like, or disregard them altogether, but keep your major and minor versions consistent! However, there have never been a program that follows this scheme successfully over several versions during it's existence. Let me give some examples:
Windows 10 Version 1709 is version 10.0.16299.192. Windows 8 is version 6.
Java Development Kit 7 for Java 7 is not version 7 but 1.7.0.0.
This office plugin is either version 10 or version 1.0.10 depending on who you ask. About Office; Office 2003 is version 11, Office 2007 is version 12, 2010 is version 14. I see what you did there, Microsoft, you don't want any bad luck! But how the hell am I supposed to remember that version 15 is Office 2013? Finally version 16 is actually Office 2016, but then again, Office 365 is ALSO version 16!
Some of the many, many, many vc-redists required, it quickly becomes ridiculous. When you get an error and the Event viewer tells you that Microsoft.VC80.MFC is missing, you immediately know you need to install Microsoft Visual C++ 2005 Redistributable, don't you?
I think I got my point across.
Happy versioning!
You can easily tell this by the fact that nobody does it unless forced to do so, and mostly not even then.
There is a long and very boring Wikipedia-page about versioning but let me sum it up for you without ever having read it. Your software should have a version number in a format like this:
major.minor.build.revision
Swap build and revision if you like, or disregard them altogether, but keep your major and minor versions consistent! However, there have never been a program that follows this scheme successfully over several versions during it's existence. Let me give some examples:
Windows 10 Version 1709 is version 10.0.16299.192. Windows 8 is version 6.
Java Development Kit 7 for Java 7 is not version 7 but 1.7.0.0.
Two different and incompatible ocx-files with the same name and version, from the last century but somehow still in use in some programs today. That is good work, mr McMahon, but you obviously hate versioning as much as everyone else!
Some of the many, many, many vc-redists required, it quickly becomes ridiculous. When you get an error and the Event viewer tells you that Microsoft.VC80.MFC is missing, you immediately know you need to install Microsoft Visual C++ 2005 Redistributable, don't you?
I think I got my point across.
Happy versioning!
Etiketter:
Microsoft,
microsoft office,
office,
version,
versioning,
Windows
torsdag 28 december 2017
Installation failed because reasons
Sometimes installations fail. Often, the reason for failure is logical and easily found in a log file, sometimes you just get an 1603 with no indication whatsoever what went wrong.
And sometimes the install fails by design. A retarded design.
Solid Works 2016 installs Microsoft SQL Server 2008, Microsoft SQL Server 2012 and Microsoft SQL Server 2014.
I think most people see a probable cause for disaster right there. But surprisingly it usually works.
Unless your organisation has done the rare but sensible and rational thing and set a password policy:
As it happens, Microsoft SQL Server adheres to the group policy dictating the password policy for the domain.
There are workarounds found when googleing, but they either require disabling the password policy or modifying the way the database is created. Neither of these methods might be possible for an unattended install from a third party vendor.
Mostly because I don't feel like talking to the vendor, nor to my collegues managing the domain.
So here is how you install an SQL instance without supervision, without modifying the install and without modifying the domain:
; Removing password-requirements with secedit:
RunWait('secedit.exe /export /cfg "' & @TempDir & '\sectmporg.cfg" /quiet',"",@SW_HIDE)
FileCopy(@TempDir & '\sectmporg.cfg', @TempDir & '\sectmpcpy.cfg',1)
IniWrite(@TempDir & '\sectmpcpy.cfg',"System Access","MinimumPasswordLength","0")
IniWrite(@TempDir & '\sectmpcpy.cfg',"System Access","PasswordComplexity","0")
RunWait('secedit.exe /configure /db secedit.sdb /cfg "' & @TempDir & '\sectmpcpy.cfg" /quiet',"",@SW_HIDE)
RunWait("gpupdate.exe","",@SW_HIDE)
; **********************
;
; THE INSTALL GOES HERE!
;
; **********************
; Restoring password-requirements:
RunWait('secedit.exe /configure /db secedit.sdb /cfg "' & @TempDir & '\sectmporg.cfg" /quiet',"",@SW_HIDE)
RunWait("gpupdate.exe","",@SW_HIDE)
And sometimes the install fails by design. A retarded design.
Solid Works 2016 installs Microsoft SQL Server 2008, Microsoft SQL Server 2012 and Microsoft SQL Server 2014.
I think most people see a probable cause for disaster right there. But surprisingly it usually works.
Unless your organisation has done the rare but sensible and rational thing and set a password policy:
As it happens, Microsoft SQL Server adheres to the group policy dictating the password policy for the domain.
There are workarounds found when googleing, but they either require disabling the password policy or modifying the way the database is created. Neither of these methods might be possible for an unattended install from a third party vendor.
Mostly because I don't feel like talking to the vendor, nor to my collegues managing the domain.
So here is how you install an SQL instance without supervision, without modifying the install and without modifying the domain:
; Removing password-requirements with secedit:
RunWait('secedit.exe /export /cfg "' & @TempDir & '\sectmporg.cfg" /quiet',"",@SW_HIDE)
FileCopy(@TempDir & '\sectmporg.cfg', @TempDir & '\sectmpcpy.cfg',1)
IniWrite(@TempDir & '\sectmpcpy.cfg',"System Access","MinimumPasswordLength","0")
IniWrite(@TempDir & '\sectmpcpy.cfg',"System Access","PasswordComplexity","0")
RunWait('secedit.exe /configure /db secedit.sdb /cfg "' & @TempDir & '\sectmpcpy.cfg" /quiet',"",@SW_HIDE)
RunWait("gpupdate.exe","",@SW_HIDE)
; **********************
;
; THE INSTALL GOES HERE!
;
; **********************
; Restoring password-requirements:
RunWait('secedit.exe /configure /db secedit.sdb /cfg "' & @TempDir & '\sectmporg.cfg" /quiet',"",@SW_HIDE)
RunWait("gpupdate.exe","",@SW_HIDE)
Code is AutoIt, but I'm sure you figure it out in any language.
Etiketter:
deploy,
deployment,
exit code,
exit codes,
install,
installation,
Microsoft,
password,
password policy,
policy,
silent install,
sql,
sql server,
trouble shooting,
troubleshooting,
unattended,
windows security
tisdag 28 november 2017
Did you find this article helpful
Etiketter:
article,
help page,
helpful,
troubleshooting
torsdag 23 november 2017
Information is key
You are the greatest application manager and the best security supervisor in the IT industry! Your clients are Applocked and secure, your users lack any higher level of permissions, the firewall blocks anything even remotely suspicious and the antivirus catches everything and then some.
You sit back and sip your cup of coffee.
Suddenly your boss storms in! He's been "offered" to pay a million bucks or all your secrets will be sold to the highest bidder! A stack of pdf-files shows they mean business.
How the hell did somebody get their hands on all your documents when your environment is so secure?
Wait, what is this at the bottom of every page?
Oh. A user gave away all the secret documents willingly.
Maybe somebody ought to inform the users they have a local pdf-converter installed on the computer.
Information is the key.
Unfortunately, it's hard to find.
You sit back and sip your cup of coffee.
Suddenly your boss storms in! He's been "offered" to pay a million bucks or all your secrets will be sold to the highest bidder! A stack of pdf-files shows they mean business.
How the hell did somebody get their hands on all your documents when your environment is so secure?
Wait, what is this at the bottom of every page?
Oh. A user gave away all the secret documents willingly.
Maybe somebody ought to inform the users they have a local pdf-converter installed on the computer.
Information is the key.
Unfortunately, it's hard to find.
fredag 20 oktober 2017
Windows on Windows action
If you are running a 64 bit Windows, and you are aren't you, you are actually running two operating systems, one 64 bit, and one 32 bit. While this is an extreme simplification, it is for all intents and purposes true enough, while at the same time maybe not true at all. But it is.
Anyway, an Intel processor runs 16, 32 or 64 bit code in different modes, thus a process can only run in either mode, not several. If I designed a CPU I would make sure future modes could run current code, but I don't design CPUs, probably because I don't have a clue. To Intels defense, the x86 range of CPUs are backwards compatible back into a different century. Hilariously it was AMD, not Intel, who designed the 64 bit mode and thus it is sometimes called AMD64.
The consequence of these modes is that 32 bit binaries and 64 bit binaries are pretty incompatible. 32 bit processes cannot load 64 bit binaries and vise versa. To run both kind of programs, Windows therefor has an almost full set of both 32 and 64 bit components.
The system files of Windows have since Windows 95 been stored in the "System32" folder. In 32-bit Windows, which can natively run 16 bit code, there is also a "System" folder, pretty much containing a Windows 3.11 set of 16 bit files. But 64 bit Windows dropped the 16 bit support, so the "System" folder is no longer present. Well, it's there, but pretty much empty.
For stupid reasons Microsoft decided to keep the name of the system folder as "System32" even on a 64 bit Windows.
The System32 folder contains the 64 bit system files.
I can see why, but I believe it's stupid because we are going to run 64 bit for much longer than the 20 years we used 32 bit operating systems. Then again, the future plans for Windows executables are uncertain.
But as you've figured out, 32 bit programs can't use these 64 bit system files, how does that work? Misdirection! Or rather, redirection. Or virtualization, if you prefer.
A 32 bit program trying to access System32 will be redirected to the "SysWOW64" folder. The program believes it loads from System32, but it isn't. It's running a 32 bit System Windows On Windows 64. SysWOW64.
The SysWOW64 contains the 32 bit system files.
There are ways to get around this if your program needs to for some reason, but this is the default behaviour. You can access the true System32 folder from a 32 bit process by the alias C:\Windows\Sysnative.
The registry is divided in much the same way. 32 bit programs accessing HKLM\Software are redirected to HKLM\Software\Wow6432Node. They couldn't choose a consistent name such as RegWOW64, because why would they. Also note that HKEY_CLASSES_ROOT is actually a mirror of HKLM\Software\Classes and HKCU\Software\Classes, therefor 32 bit and 64 bit class registrations can exist at the same time, the 32 bit under HKLM\Software\Wow6432Node\Classes.
The Program Files folders are not redirected, you can install a 64 bit program in Program Files (x86) and a 32 bit program in Program Files without much trouble. However, the environment variables are different for each architecture, the %ProgramFiles% points to a different folder depending on the process.
You can try all this by launching one 64 bit CMD from C:\Windows\System32 and one 32 bit CMD from C:\Windows\SysWOW64.
I made a tool, CheckArch, that shows the architecture of a file, sometimes needed for troubleshooting. How you managed so far without it, I don't know.
Download CheckArch.exe
Anyway, an Intel processor runs 16, 32 or 64 bit code in different modes, thus a process can only run in either mode, not several. If I designed a CPU I would make sure future modes could run current code, but I don't design CPUs, probably because I don't have a clue. To Intels defense, the x86 range of CPUs are backwards compatible back into a different century. Hilariously it was AMD, not Intel, who designed the 64 bit mode and thus it is sometimes called AMD64.
The consequence of these modes is that 32 bit binaries and 64 bit binaries are pretty incompatible. 32 bit processes cannot load 64 bit binaries and vise versa. To run both kind of programs, Windows therefor has an almost full set of both 32 and 64 bit components.
The system files of Windows have since Windows 95 been stored in the "System32" folder. In 32-bit Windows, which can natively run 16 bit code, there is also a "System" folder, pretty much containing a Windows 3.11 set of 16 bit files. But 64 bit Windows dropped the 16 bit support, so the "System" folder is no longer present. Well, it's there, but pretty much empty.
For stupid reasons Microsoft decided to keep the name of the system folder as "System32" even on a 64 bit Windows.
The System32 folder contains the 64 bit system files.
I can see why, but I believe it's stupid because we are going to run 64 bit for much longer than the 20 years we used 32 bit operating systems. Then again, the future plans for Windows executables are uncertain.
But as you've figured out, 32 bit programs can't use these 64 bit system files, how does that work? Misdirection! Or rather, redirection. Or virtualization, if you prefer.
A 32 bit program trying to access System32 will be redirected to the "SysWOW64" folder. The program believes it loads from System32, but it isn't. It's running a 32 bit System Windows On Windows 64. SysWOW64.
The SysWOW64 contains the 32 bit system files.
There are ways to get around this if your program needs to for some reason, but this is the default behaviour. You can access the true System32 folder from a 32 bit process by the alias C:\Windows\Sysnative.
The registry is divided in much the same way. 32 bit programs accessing HKLM\Software are redirected to HKLM\Software\Wow6432Node. They couldn't choose a consistent name such as RegWOW64, because why would they. Also note that HKEY_CLASSES_ROOT is actually a mirror of HKLM\Software\Classes and HKCU\Software\Classes, therefor 32 bit and 64 bit class registrations can exist at the same time, the 32 bit under HKLM\Software\Wow6432Node\Classes.
The Program Files folders are not redirected, you can install a 64 bit program in Program Files (x86) and a 32 bit program in Program Files without much trouble. However, the environment variables are different for each architecture, the %ProgramFiles% points to a different folder depending on the process.
You can try all this by launching one 64 bit CMD from C:\Windows\System32 and one 32 bit CMD from C:\Windows\SysWOW64.
I made a tool, CheckArch, that shows the architecture of a file, sometimes needed for troubleshooting. How you managed so far without it, I don't know.
Download CheckArch.exe
måndag 16 oktober 2017
Virtual or virtual
-"I wan't a virtual app", my client says. "I wan't my app to be virtual!".
-"Fine", I reply not feeling like arguing about why and such, and I deploy his stupid program as an AppV.
-"How do I start this on my paddle?" he comes back asking.
-"Your paddle?"
-"Yes, my iPaddle!". His face is getting red.
-"You didn't say you wanted to have your program published to your tablet. I can do that, but it'll be a cost associated with it, licenses and stuff".
-"What do you mean? It's my program and it's my paddle!"
-"Yes, but it doesn't run your program, a program you have developed in Visual Basic, now does it?"
-"No, but I told you I wan't you to make it virtual!". The shade of my clients cheeks are now turning into a blueish color and his forehead is sweating. "Virtualize it!"
-"I did. But I now understand what you really want is a published remote application. I can do that too, but as I said, it needs an infrastructure that costs money. I can still do it, but I need one or a few servers and software that costs more or less money, depending on how many people are going to run the program among other things".
-"It's just me, on my paddle! And I don't care how you do it, I don't know the mumbo jumbo, that's YOUR job!"
-"If you don't know the jargon, why did you specifically order a virtual application, instead of just telling me what you want?"
True story.
-"Fine", I reply not feeling like arguing about why and such, and I deploy his stupid program as an AppV.
-"How do I start this on my paddle?" he comes back asking.
-"Your paddle?"
-"Yes, my iPaddle!". His face is getting red.
-"You didn't say you wanted to have your program published to your tablet. I can do that, but it'll be a cost associated with it, licenses and stuff".
-"What do you mean? It's my program and it's my paddle!"
-"Yes, but it doesn't run your program, a program you have developed in Visual Basic, now does it?"
-"No, but I told you I wan't you to make it virtual!". The shade of my clients cheeks are now turning into a blueish color and his forehead is sweating. "Virtualize it!"
-"I did. But I now understand what you really want is a published remote application. I can do that too, but as I said, it needs an infrastructure that costs money. I can still do it, but I need one or a few servers and software that costs more or less money, depending on how many people are going to run the program among other things".
-"It's just me, on my paddle! And I don't care how you do it, I don't know the mumbo jumbo, that's YOUR job!"
-"If you don't know the jargon, why did you specifically order a virtual application, instead of just telling me what you want?"
True story.
Etiketter:
appv,
deploy,
deployment,
tablet,
virtual
onsdag 11 oktober 2017
Self Repair
There are things that probably had good intentions early in its developement but eventually didn't turn out as great as one had hoped. Communism. The DeLorean DMC-12. MSI Self Repair.
An msi normaly register itself into the system during the end of the installation, running actions such as "PublishFeatures". With an msi you don't actually have to install the program, you only need to "publish" it. Some files and registry entries in the msi is set as keys, and if one of those is missing when the program needs it, Windows Installer will perform a Self Repair.
I don't know anyone who has ever published a program instead of installing it. But then again, I don't know that many people.
However, Self Repair has effect even when a program is fully installed, because the keys always have to be present. An msi usually applies source resiliency. In the rare case of an install that becomes corrupt it will try to reinstall the broken feature, but the more common scenario is that a user is launching the program for the first time and files and registry keys that are supposed to be in the user space are missing. When this works, it is ok. Not great, but ok.
This brings us to when it doesn't work, which is probably where a vast majority of people encounter Self Repair:
This was a very common problem during the days of removable media, but thankfully most computers don't even have a CD reader anymore. It's still a problem though, because users don't always have access to the company network, or the cache that used to contain the install has been purged. The latter is typical of an environment running the later versions of Microsoft System Center.
Some deployers seem to think Self Repair is the greatest thing since sliced bread, but it isn't. A proper program does NOT rely on Windows Installer for user files and a proper configured computer does NOT need to constantly repair broken installs.
Worse, many badly authored msi triggers unnecessary and sometimes repeating Self Repairs not only for itself but for features belonging to other, completely unrelated, programs. And for the love of God, don't set key paths to any startup locations! Do you hear me, Citrix?
There are a couple of work-arounds if you want to avoid actually solving the problem. The first and easiest is to create a new shortcut to the offending program and see if it launches correctly. Normally, the repair is triggered when the program is called by its advertised shortcut, a special lnk that goes to a launcher i C:\Windows\Installer. Repair is triggered by more events than launching the advertised shortcut though, so this might not always work.
The cause of the Self Repair should be noted in the Event Viewer in the Application Event log with an ID of 1004, and a quick fix could be to create a dummy file or registry key in place of the one missing.
The most brutal one is to use MsiZap to simply clean all the installer metadata, leaving only the program itself, completely unaware about any published features or components. This is a last resort solution that might cause new problems that are hard to troubleshoot further down the road, try to avoid it!
How to deploy an application that needs data in the user space will be covered, I promise.
An msi normaly register itself into the system during the end of the installation, running actions such as "PublishFeatures". With an msi you don't actually have to install the program, you only need to "publish" it. Some files and registry entries in the msi is set as keys, and if one of those is missing when the program needs it, Windows Installer will perform a Self Repair.
I don't know anyone who has ever published a program instead of installing it. But then again, I don't know that many people.
However, Self Repair has effect even when a program is fully installed, because the keys always have to be present. An msi usually applies source resiliency. In the rare case of an install that becomes corrupt it will try to reinstall the broken feature, but the more common scenario is that a user is launching the program for the first time and files and registry keys that are supposed to be in the user space are missing. When this works, it is ok. Not great, but ok.
This brings us to when it doesn't work, which is probably where a vast majority of people encounter Self Repair:
This was a very common problem during the days of removable media, but thankfully most computers don't even have a CD reader anymore. It's still a problem though, because users don't always have access to the company network, or the cache that used to contain the install has been purged. The latter is typical of an environment running the later versions of Microsoft System Center.
Some deployers seem to think Self Repair is the greatest thing since sliced bread, but it isn't. A proper program does NOT rely on Windows Installer for user files and a proper configured computer does NOT need to constantly repair broken installs.
Worse, many badly authored msi triggers unnecessary and sometimes repeating Self Repairs not only for itself but for features belonging to other, completely unrelated, programs. And for the love of God, don't set key paths to any startup locations! Do you hear me, Citrix?
There are a couple of work-arounds if you want to avoid actually solving the problem. The first and easiest is to create a new shortcut to the offending program and see if it launches correctly. Normally, the repair is triggered when the program is called by its advertised shortcut, a special lnk that goes to a launcher i C:\Windows\Installer. Repair is triggered by more events than launching the advertised shortcut though, so this might not always work.
The cause of the Self Repair should be noted in the Event Viewer in the Application Event log with an ID of 1004, and a quick fix could be to create a dummy file or registry key in place of the one missing.
How to deploy an application that needs data in the user space will be covered, I promise.
tisdag 10 oktober 2017
The requested execution level require administrator!
Executables that make changes to the system requires higher privilegies. Users will normally be asked to give admin credentials, and even members of the local administrator group will be asked for consent before elevating to a higher level of privilegies.
This is great!
However, some applikations require administrative privilegies even though they do NOT make or need to make any system changes.
That is retarded!
It actually lowers the overall security because if you don't know how to handle it users will have to be given, or some users might even have the balls to demand, administration rights.
An hilariously ironic example is InstallShield, one of the most common msi-editors. I can imagine some tools like the Response Transform Wizard might need admin rights, but otherwise there is no need. Another trouble maker is mmc.exe even though the snap-in you wan't does not. This makes it difficult to save a folder view and give to users to administer groups, for instance. Add to this various third party programs that only need to run as admin because the developer is lazy. Nothing wrong with laziness, unless it gives ME more work.
A program might ask for elevation for various reasons, where the correct and common reason is requestedExecutionLevel in the programs manifest is set to Level=requireAdministrator.
There are other reasons, some of which you can force. You can make a shortcut where you specify Advanced - Run As Administrator. This setting is in the lnk-file and will remain if copied. You can set the executable compability mode to Run As Administrator. This is stored in HKCU or HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers and includes the full path. Therefor it will break if the file is renamed or copied.
If the file lacks a manifest you can just rename the file as setup.exe and Windows will force consent on you. That didn't come out right.
The other way around, running a program that requires admin rights without admin rights, is slightly more convoluted.
There are a couple of ways to do it, where the easiest way is to set the environment variable __COMPAT_LAYER = RunAsInvoker. Note the initial double underscore.
Using a script or by coding it is trivial to make a launcher. In AutoIt:
#NoTrayIcon
#AutoIt3Wrapper_Icon=Some icon preferably same icon as the program this is supposed to launch.ico
$RunAsInvoker_command = 'set __COMPAT_LAYER=RunAsInvoker'
Run(@ComSpec & ' /c ' & $RunAsInvoker_command & ' & start "" /D "' & @ScriptDir & '" ' & $cmdlineraw, @ScriptDir, @SW_HIDE)
Another way to more permanently change the application is to edit its manifest and simply replace level="requireAdministrator" with level="asInvoker" using your preferred manifest editor that works. They don't always work. If the file is signed, not even a hex-editor works.
That is the easy part. Then you need to make sure the program actually works running with only user rights. For this task, you'll need Procmon, the greatest tool ever made. I said that already.
UAC and Admin Approval Mode can be turned off in various ways. DO NOT DO THIS. On the contrary, if it was up to me (it isn't) I would enable Prompt for credentials for ConsentPromptBehaviorAdmin, so that even admins have to enter a password before elevating.
This is great!
However, some applikations require administrative privilegies even though they do NOT make or need to make any system changes.
That is retarded!
It actually lowers the overall security because if you don't know how to handle it users will have to be given, or some users might even have the balls to demand, administration rights.
An hilariously ironic example is InstallShield, one of the most common msi-editors. I can imagine some tools like the Response Transform Wizard might need admin rights, but otherwise there is no need. Another trouble maker is mmc.exe even though the snap-in you wan't does not. This makes it difficult to save a folder view and give to users to administer groups, for instance. Add to this various third party programs that only need to run as admin because the developer is lazy. Nothing wrong with laziness, unless it gives ME more work.
A program might ask for elevation for various reasons, where the correct and common reason is requestedExecutionLevel in the programs manifest is set to Level=requireAdministrator.
There are other reasons, some of which you can force. You can make a shortcut where you specify Advanced - Run As Administrator. This setting is in the lnk-file and will remain if copied. You can set the executable compability mode to Run As Administrator. This is stored in HKCU or HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers and includes the full path. Therefor it will break if the file is renamed or copied.
If the file lacks a manifest you can just rename the file as setup.exe and Windows will force consent on you. That didn't come out right.
The other way around, running a program that requires admin rights without admin rights, is slightly more convoluted.
There are a couple of ways to do it, where the easiest way is to set the environment variable __COMPAT_LAYER = RunAsInvoker. Note the initial double underscore.
Using a script or by coding it is trivial to make a launcher. In AutoIt:
#NoTrayIcon
#AutoIt3Wrapper_Icon=Some icon preferably same icon as the program this is supposed to launch.ico
$RunAsInvoker_command = 'set __COMPAT_LAYER=RunAsInvoker'
Run(@ComSpec & ' /c ' & $RunAsInvoker_command & ' & start "" /D "' & @ScriptDir & '" ' & $cmdlineraw, @ScriptDir, @SW_HIDE)
Another way to more permanently change the application is to edit its manifest and simply replace level="requireAdministrator" with level="asInvoker" using your preferred manifest editor that works. They don't always work. If the file is signed, not even a hex-editor works.
That is the easy part. Then you need to make sure the program actually works running with only user rights. For this task, you'll need Procmon, the greatest tool ever made. I said that already.
UAC and Admin Approval Mode can be turned off in various ways. DO NOT DO THIS. On the contrary, if it was up to me (it isn't) I would enable Prompt for credentials for ConsentPromptBehaviorAdmin, so that even admins have to enter a password before elevating.
Etiketter:
asInvoker,
AutoIt,
consent.exe,
install,
installation,
Microsoft,
Procmon,
registry,
requestedExecutionLevel,
requireAdministrator,
RunAsInvoker,
security alert,
Sysinternals,
uac,
windows security
Procmon, the greatest tool of all time
If you don't use Procmon, you're not an IT professional. If you're not an expert at quickly sifting through the Procmon output you are definitely not a deployer!
Procmon is the greatest trouble shooting tool for PC ever made and you should be using it.
My work day is 25% Procmon and 25% other work.
Procmon is the greatest trouble shooting tool for PC ever made and you should be using it.
My work day is 25% Procmon and 25% other work.
måndag 9 oktober 2017
The system corrupts
An update is due again, as it always is. This time it is the digital signage program Dise. Previously deployed version is 1.6 and when I try on my lab computer both uninstalling this version and installing the new one works beautiful with just a /S switch. A good five minutes of work that I can charge $500 for. I can lean back, take a sip of coffee and browse the internet for "news".
I deploy the application but curiously I don't get any statistics in System Center, nothing seems to happen. Suddenly I hear screaming. The staff at the call center seem distressed. I find that after a restart the computers don't boot anymore, all thats left of our entire environment is this:
It turns out that uninstalling Dise 1.6 with the SYSTEM accound wipes the boot sector for no reason. The computer is now a brick.
Fortunately the above scenario didn't play out, because I actually spent more than five minutes and caught this before deploying.
Many installs behave differently when installing as SYSTEM as opposed to an ordinary administrator account. Every install MUST be tested with this account before being deployed sitewide. I recommend at least having a CMD shortcut on the desktop that uses psexec.exe to launch as SYSTEM.
Some old issetup.dll, a component in Installshield built setups, had a bug that launched the install as the currently logged on user, which of course failed with tons of access denied. Some installs deploy settings only to the running users profile, which in this case is C:\Windows\System32\config\systemprofile or might fail to write user settings altogether. Some installs get confused for other reasons when the environment is different from a standard user.
Few installs are as awful as Dise, but there are more ways to completely destroy a computer. More about that in a later post.
I deploy the application but curiously I don't get any statistics in System Center, nothing seems to happen. Suddenly I hear screaming. The staff at the call center seem distressed. I find that after a restart the computers don't boot anymore, all thats left of our entire environment is this:
It turns out that uninstalling Dise 1.6 with the SYSTEM accound wipes the boot sector for no reason. The computer is now a brick.
Fortunately the above scenario didn't play out, because I actually spent more than five minutes and caught this before deploying.
Many installs behave differently when installing as SYSTEM as opposed to an ordinary administrator account. Every install MUST be tested with this account before being deployed sitewide. I recommend at least having a CMD shortcut on the desktop that uses psexec.exe to launch as SYSTEM.
Some old issetup.dll, a component in Installshield built setups, had a bug that launched the install as the currently logged on user, which of course failed with tons of access denied. Some installs deploy settings only to the running users profile, which in this case is C:\Windows\System32\config\systemprofile or might fail to write user settings altogether. Some installs get confused for other reasons when the environment is different from a standard user.
Few installs are as awful as Dise, but there are more ways to completely destroy a computer. More about that in a later post.
onsdag 4 oktober 2017
Success fail
A successful installation should return an exit code of 0, but that is not always the case. These cases need to be handled properly, or I'll get a very red pie-chart in System Center.
The most common exception is 3010, a successfull install that needs a reboot, but there are others. Some more or less retarded.
Just now I needed to deploy an msi that returned 1638 if it was already installed. 1638 is documented as ERROR_PRODUCT_VERSION, "Another version of this product is already installed". This is stupid on many levels. First, if the same version is installed an msi should just install again. If an older version is installed, a proper msi should perform a major upgrade. The exit code might be useful if a newer program exists on the computer, but barely. I would say that installations which return 1638 should be documented as ERROR_MSI_SUCKS. The solution is to always uninstall before installing. This leads to the next problem.
Uninstalling an msi might return 1605, ERROR_UNKNOWN_PRODUCT, "This action is only valid for products that are currently installed." Yes, thank you. Already not there then. Success.
Sometimes you might need to deploy a patch for Windows, usually named kb-something with an msu extension, with your application. Unfortunately a shitload of your computers in your enterprise will report failure 2359302, 0x240006 in hex. This means WU_S_ALREADY_INSTALLED, "The update to be installed is already installed on the system". This is even dumber than 1638. If it is already installed, it is a success!
Related is the msu exit value of 2149842967, 0x80240017 in hex, "The update is not applicable to your computer". You'll get this result if you try to deploy a patch for Windows 7, and you happen to have a few Windows 10 among them, as an example. Not unlikely for many reasons, one of which is the update is included in a larger install where the application needs it on older Windows, but you don't feel like making two different packages for each OS or some other workaround. While the error might be interesting for some reasons, as a deployer I don't care. I filter it to success and I'm just as happy.
Deploying drivers with DPInst is an entire chapter of itself. The return value you get consist of three hexadecimal parts merged with OR like this:
0xYY0000 contains the number of drivers that failed to install.
0x00YY00 contains the number of drivers copied to the driver store.
0x0000YY contains the number of drivers successfully installed.
A return code of 66051 thus means 1 driver failed, two drivers copied to the driver store and 3 drivers installed, because it's 0x010203 in hex.
The simplest way to get a useful value is to do an AND FF0000. If it's zero, it's a success, otherwise you'll get the number of fails times 65536.
But so far the exit codes have at least been valid and have their reasons. Some badly written installers give all kinds of weird return values. Adobe was notorious for a while, returning 255 for a success.
But of all the moronic exit codes to indicate success there is one particularly stupid from msiexec;
1707 - Installation operation completed successfully.
The most common exception is 3010, a successfull install that needs a reboot, but there are others. Some more or less retarded.
Just now I needed to deploy an msi that returned 1638 if it was already installed. 1638 is documented as ERROR_PRODUCT_VERSION, "Another version of this product is already installed". This is stupid on many levels. First, if the same version is installed an msi should just install again. If an older version is installed, a proper msi should perform a major upgrade. The exit code might be useful if a newer program exists on the computer, but barely. I would say that installations which return 1638 should be documented as ERROR_MSI_SUCKS. The solution is to always uninstall before installing. This leads to the next problem.
Uninstalling an msi might return 1605, ERROR_UNKNOWN_PRODUCT, "This action is only valid for products that are currently installed." Yes, thank you. Already not there then. Success.
Sometimes you might need to deploy a patch for Windows, usually named kb-something with an msu extension, with your application. Unfortunately a shitload of your computers in your enterprise will report failure 2359302, 0x240006 in hex. This means WU_S_ALREADY_INSTALLED, "The update to be installed is already installed on the system". This is even dumber than 1638. If it is already installed, it is a success!
Related is the msu exit value of 2149842967, 0x80240017 in hex, "The update is not applicable to your computer". You'll get this result if you try to deploy a patch for Windows 7, and you happen to have a few Windows 10 among them, as an example. Not unlikely for many reasons, one of which is the update is included in a larger install where the application needs it on older Windows, but you don't feel like making two different packages for each OS or some other workaround. While the error might be interesting for some reasons, as a deployer I don't care. I filter it to success and I'm just as happy.
Deploying drivers with DPInst is an entire chapter of itself. The return value you get consist of three hexadecimal parts merged with OR like this:
0xYY0000 contains the number of drivers that failed to install.
0x00YY00 contains the number of drivers copied to the driver store.
0x0000YY contains the number of drivers successfully installed.
A return code of 66051 thus means 1 driver failed, two drivers copied to the driver store and 3 drivers installed, because it's 0x010203 in hex.
The simplest way to get a useful value is to do an AND FF0000. If it's zero, it's a success, otherwise you'll get the number of fails times 65536.
But so far the exit codes have at least been valid and have their reasons. Some badly written installers give all kinds of weird return values. Adobe was notorious for a while, returning 255 for a success.
But of all the moronic exit codes to indicate success there is one particularly stupid from msiexec;
1707 - Installation operation completed successfully.
Firewall rulez!
If your program needs to add firewall rules, your installer should provide the option.
DO NOT rely on the person installing your application to know what needs to be done.
DO NOT ignore it and let Windows pop up the Security Alert, this one:
Not the user nor the administrator knows or cares what firewall rules your application requires. The user probably, preferably, don't even have permission to allow access.
A lazy application manager, one like me for instance, might even consider turning off the local firewall altogether if it get complicated enough.
A prime example is the Flexera LMFlex, a pretty common manager for floating licenses used by a wide range of applications such as Autodesk AutoCAD, Pitney Bowes MapInfo and Safe Software FME.
LMFlex does not configure the rules for you, it requires a range of ports to be open, uses random ports as default, and every dependent application is managed by a separate LMgrd.exe process.
I could write an entire post about LMFlex, and probably will, but for now I'll just sigh and turn off the firewall.
I don't have time for this, I have porn to discover.
DO NOT rely on the person installing your application to know what needs to be done.
DO NOT ignore it and let Windows pop up the Security Alert, this one:
Not the user nor the administrator knows or cares what firewall rules your application requires. The user probably, preferably, don't even have permission to allow access.
A lazy application manager, one like me for instance, might even consider turning off the local firewall altogether if it get complicated enough.
A prime example is the Flexera LMFlex, a pretty common manager for floating licenses used by a wide range of applications such as Autodesk AutoCAD, Pitney Bowes MapInfo and Safe Software FME.
LMFlex does not configure the rules for you, it requires a range of ports to be open, uses random ports as default, and every dependent application is managed by a separate LMgrd.exe process.
I could write an entire post about LMFlex, and probably will, but for now I'll just sigh and turn off the firewall.
I don't have time for this, I have porn to discover.
Everybody writes to program files!
Now and then I am given a program to deploy that doesn't work. Just kidding, I get such programs all the time.
Actually, I am quite surprised when something works straight out of the box. I have a hard time fathoming how people without my amazing skills get anything to work on their computer at all.
Well, one of the reasons is that most people are using their home computers with an account that has administrative privilegies. Some people even turn off UAC to get rid of some annoying consent-dialogs.
In a corporate environment, this is a very very bad idea. Ask anyone working at an Iranian nuclear facility. (Full disclosure: I don't have a clue about the infrastructure at any nuclear facility, Iranian or otherwise).
A very common problem I face is programs that require write-permissions in its program folder. Older programs, binaries that does not include a manifest with a requested execution level, have their writes redirected by modern Windows to the users profile, to %localappdata%\VirtualStore. This, however, only works with UAC enabled.
But so far so good, these old crap program works somewhat, thanks to the pile of workarounds that is Windows.
New crap programs does not.
They are getting less and less common but I still get them.
Why not just give users write-permissions, you may ask. Because they don't deserve it I may answer, but that would be wrong. No, it's because it's a major security concern.
Having write access to program or system folders is different than having write access anywhere else, because a malicious program could replace files the user launches, and unlike executables saved on the desktop or the download folder, users don't have a clue what they are launching when starting an already installed program.
Also, it makes further security restrictions like AppLocker a pain to administer. Imagine you manage a restricted environment where users are only allowed to start prior approved programs, that you have tried, tested and deployed. The users are not local administrators, so they can't install anything, and you wan't to configure AppLocker so that they can't even start binaries but the programs you deploy.
Pretty much the only AppLocker rules you would need then are the default rules, like this one:
While this isn't entirely true if you use stuff like Click-to-Run, ClickOnce (stupid names, by the way) or AppV, it covers most of what you need.
However, if only ONE folder that fits within your Allow-rules are writable by users, it all falls apart! Any user or a malicious program can then launch whatever they want, and the added security AppLocker is supposed to provide is to no avail.
Microsoft has a tool, Sysinternals AccessChk that will help you after the fact, but you will need to be the person to avoid installing programs that changes permissions on folders.
If you absolutely MUST, install the program elsewhere. Not in the root directory, but maybe in C:\ProgramData or make a new folder called C:\Program Files Secure.
Or why not C:\Program Files That Suck!
Then you'll need to add new AppLocker rules separately. But it works.
Actually, I am quite surprised when something works straight out of the box. I have a hard time fathoming how people without my amazing skills get anything to work on their computer at all.
Well, one of the reasons is that most people are using their home computers with an account that has administrative privilegies. Some people even turn off UAC to get rid of some annoying consent-dialogs.
In a corporate environment, this is a very very bad idea. Ask anyone working at an Iranian nuclear facility. (Full disclosure: I don't have a clue about the infrastructure at any nuclear facility, Iranian or otherwise).
A very common problem I face is programs that require write-permissions in its program folder. Older programs, binaries that does not include a manifest with a requested execution level, have their writes redirected by modern Windows to the users profile, to %localappdata%\VirtualStore. This, however, only works with UAC enabled.
But so far so good, these old crap program works somewhat, thanks to the pile of workarounds that is Windows.
New crap programs does not.
They are getting less and less common but I still get them.
Why not just give users write-permissions, you may ask. Because they don't deserve it I may answer, but that would be wrong. No, it's because it's a major security concern.
Having write access to program or system folders is different than having write access anywhere else, because a malicious program could replace files the user launches, and unlike executables saved on the desktop or the download folder, users don't have a clue what they are launching when starting an already installed program.
Also, it makes further security restrictions like AppLocker a pain to administer. Imagine you manage a restricted environment where users are only allowed to start prior approved programs, that you have tried, tested and deployed. The users are not local administrators, so they can't install anything, and you wan't to configure AppLocker so that they can't even start binaries but the programs you deploy.
Pretty much the only AppLocker rules you would need then are the default rules, like this one:
While this isn't entirely true if you use stuff like Click-to-Run, ClickOnce (stupid names, by the way) or AppV, it covers most of what you need.
However, if only ONE folder that fits within your Allow-rules are writable by users, it all falls apart! Any user or a malicious program can then launch whatever they want, and the added security AppLocker is supposed to provide is to no avail.
Microsoft has a tool, Sysinternals AccessChk that will help you after the fact, but you will need to be the person to avoid installing programs that changes permissions on folders.
If you absolutely MUST, install the program elsewhere. Not in the root directory, but maybe in C:\ProgramData or make a new folder called C:\Program Files Secure.
Or why not C:\Program Files That Suck!
Then you'll need to add new AppLocker rules separately. But it works.
fredag 29 september 2017
PendingFilerenameOperations
Some installs require a reboot when finished, either by asking nicely or by forcefully restarting the computer like an asshole. Most, but not all, msi-installations respect the REBOOT=ReallySuppress flag.
Some installs however, require a reboot before the install begins.
I like to call these installs arrogant or pretentious. Also cocksure. I like that word.
These installs are so convinced about their own superiority that they refuse to install if a restart is pending for any reason.
Heck, I can upgrade my network drivers and my graphics drivers on the fly without restarting the computer, but YOUR program is so advanced and important that it cannot fathom to just copy the damn binaries unless the computer is perfectly clean.
The way to work around this is the registry entry PendingFilerenameOperations. Tucked away far down the path HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager this MULTI_SZ key containst files that supposedly could not be copied to their destination or deleted for some reason, locked files usually. They are now in TEMP limbo and needs to be renamed during the next boot.
If this key exists, at all, some installs refuse to run. It doesn't matter if the key contains nothing but crap files, installation becomes impossible. Unless you restart, of course, but that is the lame way.
Helpful pages on the web has the solution: Delete the damn key.
Well, I agree. But what if there is something important in there? Let's read it's content, remove the key, and then write everything back! This is somewhat easily done by using reg.exe in a script, if it's a simple before and after action.
I wan't to use AutoIt though, just because. First, my installer wrapper is written in AutoIt for obvious reasons. Laziness, if that wasn't obvious. Also, I wan't to clear it continously during long and complicated chains of dependent installs, many of which require restart inbetween.
It complicates things, because this key does not abide to standard MULTI_SZ rules, which does not allow empty rows, for instance.
The number of people caring about this, understanding it, having use for it and finally finding this page is propably fewer than the number of my Facebook friends (sobbing). Not even my mom reads this blog.
But here you go:
Some installs however, require a reboot before the install begins.
I like to call these installs arrogant or pretentious. Also cocksure. I like that word.
These installs are so convinced about their own superiority that they refuse to install if a restart is pending for any reason.
Heck, I can upgrade my network drivers and my graphics drivers on the fly without restarting the computer, but YOUR program is so advanced and important that it cannot fathom to just copy the damn binaries unless the computer is perfectly clean.
The way to work around this is the registry entry PendingFilerenameOperations. Tucked away far down the path HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager this MULTI_SZ key containst files that supposedly could not be copied to their destination or deleted for some reason, locked files usually. They are now in TEMP limbo and needs to be renamed during the next boot.
If this key exists, at all, some installs refuse to run. It doesn't matter if the key contains nothing but crap files, installation becomes impossible. Unless you restart, of course, but that is the lame way.
Helpful pages on the web has the solution: Delete the damn key.
Well, I agree. But what if there is something important in there? Let's read it's content, remove the key, and then write everything back! This is somewhat easily done by using reg.exe in a script, if it's a simple before and after action.
I wan't to use AutoIt though, just because. First, my installer wrapper is written in AutoIt for obvious reasons. Laziness, if that wasn't obvious. Also, I wan't to clear it continously during long and complicated chains of dependent installs, many of which require restart inbetween.
It complicates things, because this key does not abide to standard MULTI_SZ rules, which does not allow empty rows, for instance.
The number of people caring about this, understanding it, having use for it and finally finding this page is propably fewer than the number of my Facebook friends (sobbing). Not even my mom reads this blog.
But here you go:
Global $PendingFilerenameOperations
Func GetPendingFilerenameOperations()
local $tmp=_RegReadPendingFilerenameOperations()
RegDelete("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager","PendingFilerenameOperations")
if $tmp<>"" Then
$tmp=StringTrimLeft($tmp,2); Remove "0x" from string, so that we can add binary strings together.
if StringRight($tmp,8)="00000000" Then
$tmp=StringTrimRight($tmp,4) ; Remove last LF if there are two.
EndIf
StringReplace($tmp,"000000","")
local $linefeeds = @extended ; Find out the number of linefeeds in the binary string. All characters ends in 00, plus 00 00 for the linefeed.
if Mod($linefeeds,2) <> 0 Then
$tmp=$tmp & "0000" ; Add back the linefeed if there was an odd number of linefeeds.
EndIf
$PendingFilerenameOperations = $PendingFilerenameOperations & $tmp
EndIf
EndFunc
Func SetPendingFilerenameOperations()
GetPendingFilerenameOperations()
if $PendingFilerenameOperations<>"" Then
;~ Count trailing Zeroes. There should always be exactly 10 when everything is said and done. 00 for the last character, 00 00 for the linefeed after the last row, and then a final 00 00 linefeed.
local $trailingZeroes=0
for $i = StringLen($PendingFilerenameOperations)-3 to 1 step -4
if StringMid($PendingFilerenameOperations,$i,4)="0000" then
$trailingZeroes = $trailingZeroes+1
Else
ExitLoop
EndIf
Next
;~ AutoIt RegWrite (or maybe BinaryToString) will add the trailing zeroes for us, contrary to documentation (or I'm lost somehow), so lets remove them:
$PendingFilerenameOperations = StringTrimRight($PendingFilerenameOperations, $trailingZeroes*4)
; Convert to string, and write it all back:
$PendingFilerenameOperations = StringReplace(BinaryToString("0x" & $PendingFilerenameOperations, 2), ChrW(0), @LF) ; According to AutoIt doc it should be @CRLF here, but that gives incorrect result.
RegWrite("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager","PendingFilerenameOperations","REG_MULTI_SZ",$PendingFilerenameOperations)
EndIf
EndFunc
Func _RegReadPendingFilerenameOperations()
Local $hKey = 0x80000002 ; HKEY_LOCAL_MACHINE
local $lpSubKey = "SYSTEM\CurrentControlSet\Control\Session Manager"
local $lpValueName = "PendingFilerenameOperations"
;~ Open key:
$ret = DllCall("advapi32.dll", "long", "RegOpenKeyExW", "ulong_ptr", $hKey, "wstr", $lpSubKey, "dword", 0, "ulong", 0x20019, "ulong_ptr*", 0)
If @error Or ($ret[0] <> 0) Then
return ""
EndIf
local $hKey2 = $ret[5]
;~ Check type and size of PendingFilerenameOperations:
Local $ret2 = DllCall("advapi32.dll", "long", "RegQueryValueExW", "ulong_ptr", $hKey2, "wstr", $lpValueName, "ptr", 0, "dword*", 0, "ptr", 0, "dword*", 0)
If @error Or ($ret2[0] <> 0) Then
DllCall("advapi32.dll", "long", "RegCloseKey", "ulong_ptr", $hKey2)
return ""
EndIf
if $ret2[4]<>7 Then
;~ Not a REG_MULTI_SZ... Something strange is going on...
return ""
EndIf
;~ Read the damn data:
Local $keyLen = $ret2[6]
Local $keyData = DllStructCreate("byte[" & $keyLen & "]")
$ret3 = DllCall("advapi32.dll", "long", "RegQueryValueExW", "ulong_ptr", $hKey2, "wstr", $lpValueName, "ptr", 0, "dword*", 0, "ptr", DllStructGetPtr($keyData), "dword*", DllStructGetSize($keyData))
DllCall("advapi32.dll", "long", "RegCloseKey", "ulong_ptr", $hKey2)
If (Not IsArray($ret3)) Or ($ret3[0] <> 0) Then
return ""
EndIf
Return DllStructGetData($keyData, 1)
EndFunc
onsdag 13 september 2017
Your updater sucks!
You've released a new version of your awesome program, and you wan't everyone to upgrade! Unfortunately you are a Windows developer so you have to rely on your own wit and skill for automatic upgrades. Fortunately you have billions of investor dollars to spend, because you work at Spotify or whatever.
So you have made a mechanism on the client that checks for updates now and then and downloads them automatically. The massive amount of money you spent didn't make you God though:
You didn't consider that your program might be located somewhere on the computer where the user doesn't have permission to write. You didn't consider that because billions of dollars still can't make you think.
There are uncountable number of solutions to this problem, some of which are:
Humorously you might totally break your program if you can't even start it without upgrading once it downloaded a new version, unless you edit the registry or some stupid xml-file.
Breaking your own program, is that what you want? Is it?
So you have made a mechanism on the client that checks for updates now and then and downloads them automatically. The massive amount of money you spent didn't make you God though:
You need to ASK before you FUCK. It's called consent.exe.
You didn't consider that your program might be located somewhere on the computer where the user doesn't have permission to write. You didn't consider that because billions of dollars still can't make you think.
There are uncountable number of solutions to this problem, some of which are:
- Have settings to disable updates and let the admins (me) manage it.
- Check for write permissions and only upgrade if you know you're able to.
- Write a service or scheduled task, like Google does. A service means a service, not just a stupid user process. Lika Java does.
- DON'T update automatically! This is the best option.
Humorously you might totally break your program if you can't even start it without upgrading once it downloaded a new version, unless you edit the registry or some stupid xml-file.
Breaking your own program, is that what you want? Is it?
Prenumerera på:
Inlägg (Atom)


















