This was more of a project than I was originally expecting, Microsoft prevents the Windows XP Powertoy Calculator from running in Vista or Windows 7 in 2 separate places, but in the end, it runs perfectly in Vista, all the limitations are false.
Don't feel like doing this yourself? No need!
Part 1: The Installer
PowerCalcPowertoySetup.exe, it complained that I'm not on Windows XP. Fair enough, but is that really important?
The exe installer dumped the MSI file at
C:\Windows\Downloaded Installations\Calculator Powertoy for Windows XP.msi which I ran MsiDiff on to dump the MSI script. This gave me
Calculator Powertoy for Windows XP.msi.MmDumpTxt which I searched for the above error in.
<$Row Condition="VersionNT = 501" Description="The powertoys require Windows XP or a service pack. They will not function on a version of Windows earlier or later than Windows XP." >
Perfect. 501 is the Windows XP kernel version. Lets change that to the Vista kernal version in the MSI...
Sweet! It worked!
Part 2: Oh... no...
PowerCalc.exe causes it to exit before ever giving us a GUI. Lets do a trace in OllyDbg and see what we can figure out.
01018405 Main JE SHORT PowerCal.0101840C 0101840C Main TEST BYTE PTR SS:[EBP-30],1 01018410 Main JE SHORT PowerCal.01018423 01018412 Main MOVZX ECX,WORD PTR SS:[EBP-2C] ECX=0000000A 01018416 Main JMP SHORT PowerCal.01018426 01018426 Main PUSH ECX Arg4 = 0000000A 01018427 Main PUSH EAX Arg3 = 001E1F33 01018428 Main PUSH EBX Arg2 = 00000000 01018429 Main PUSH PowerCal.01000000 Arg1 = 01000000 0101842E Main CALL PowerCal.01001FD3 EAX=00000000, ECX=D73F2C3E, EDX=7F68081A 01018433 Main MOV ESI,EAX 01018435 Main MOV DWORD PTR SS:[EBP-7C],ESI 01018438 Main CMP DWORD PTR SS:[EBP-60],EBX 0101843B Main JNZ SHORT PowerCal.01018444 0101843D Main PUSH ESI status = 0 0101843E Main CALL DWORD PTR DS:[<&msvcrt.exit>] ECX=0006FE28, EDX=00000000, EBP=0006FE84, ESI=00000001, EDI=00831BF0 Process terminated, exit code 0
The bottom of the trace-over isn't telling us much. Lets check out some of these offsets in IDA Pro and see what we can come up with.
All the stuff around
0101843B seems to exit the program, and none of these other offsets get us anywhere... lets run a trace-into and see what we get.
Aside from a 75mb text file, we get: (search from the bottom up for our programs address space! There's a lot of external code in there!).
010180E3 Main RETN 01001FD1 Main LEAVE EBP=0006FEE4 01001FD2 Main RETN 01001FDF Main TEST EAX,EAX 01001FE1 Main JE PowerCal.010020A0 010020A0 Main XOR EAX,EAX 010020A2 Main POP ESI 010020A3 Main LEAVE EBP=0006FF88 010020A4 Main RETN 10 01018433 Main MOV ESI,EAX 01018435 Main MOV DWORD PTR SS:[EBP-7C],ESI 01018438 Main CMP DWORD PTR SS:[EBP-60],EBX 0101843B Main JNZ SHORT PowerCal.01018444 0101843D Main PUSH ESI status = 0 0101843E Main CALL DWORD PTR DS:[<&msvcrt.exit>] exit Main MOV EDI,EDI
Now we're talking! It looks like a function returns and then the program exits. Lets check out the call to that function.
One path goes to the exit, the other... doesn't! Lets check out
sub_1001F60 to see what it does...
It's our evil Windows Version Checking function!
In OllyDbg lets goto the
jz loc_10020A0 after the function call, right click, and goto "nop" and press run. This causes the program to always follow the non-exiting code path.
Lets hex edit that into the executable so it's like this all the time.
We can now use our calculator!