First a few notes about Mac apps in general. Most of the more modern apps are compiled for both x86 and PPC chips, and the resultant output files are stuffed into a single file together for distribution. So, I did both versions. Now, not being a PPC hacker, that took a few minutes, but the mistakes that they made in the x86 version were also present in the PPC version, so it was a lot easier than it should have been.
In this particular case, (and I hope all others!), the way that the Mac compiler generates executables, and probably the whole underlying architecture of OSX makes reversing MUCH simpler. It's almost like there's an API for everything! To wit, this code looks odd enough, nothing really to see here, right?
__text:000DB4CB mov eax, ds:off_1D2514
__text:000DB4D0 mov [esp], eax
__text:000DB4D3 call _objc_msgSend
If you checkout off_1D2514, you discover that it's a pointer to NSConditionLock. So, spend a few minutes labeling all these "pointers to message names", and the disassembly starts to look VERY different!
Of course, if the particular program that you're working on uses a license file protection technique, and offers a demo version, then it could be even easier. It could have a function like this:
char __cdecl _XXApplication_isDemo_()
{
return *pTrialByte == 3;
}
Variable name was supplied by me, function name was left in the executable by them. Don't get me wrong, I certainly APPRECIATE it! ;-)
So with this function telling me not only what variable in memory was responsible for determining the trial/registered status of the app, but also what the value was that was interpreted as being a trial, it allowed me to make a simple fix. Just locate all the places in memory where this memory location was set. I.E.
__text:000E0453 mov ds:TrialByte, 3
A little more tracing showed me that a value of "1" in TrialByte meant that the app was registered, and happy. So a simple search revealed 3 places where a value other than "1" was being placed in this location. A simple change of "2" to "1", and a couple of "3" to "1" changes, and we were done.
I heard that! You said "What about the PPC version?". Well, I found much the same code there:
__text:0000B470 __XXApplication_isDemo_:
__text:0000B470 lis %rtoc, ((pTrialByte+0x10000)@h)
__text:0000B474 lwz %rtoc, pTrialByte@l(%rtoc)
__text:0000B478 lwz %r3, 0(%rtoc)
__text:0000B47C xori %r3, %r3, 3
__text:0000B480 subfic %r0, %r3, 0
__text:0000B484 adde %r3, %r0, %r3
__text:0000B488 blr
__text:0000B488 # End of function __XXApplication_isDemo_
This is our handy function for locating the variable, and what do you know? A quick search shows that there are 3 places that need to be patched to make it work. The same as the x86 version.
1 comment:
And here we are, over 5.5 years later, and this app is STILL the same. Only NOW, I know more about the values.
0 = No license
1 = Valid license
2 = Demo license
3 = Trial license
I have no idea what the distinctions are between a demo, and a trial, but I know they're there now. How do I know this you ask? Simple! They have accessor functions for the values that tell me. There is a function that returns a bool named IsDemo that checks the in-memory value against 2. And, there is ANOTHER one called IsTrial that checks it against 3. *sigh*
Post a Comment