Log in

View Full Version : Making progress...need a little asm clarification ???


Clandestiny
November 2nd, 2000, 21:33
Hi guys,

I have sucessfully registered the moving pix application and I think I've *almost* decoded its registration checking algorithm, but one thing is puzzling me.

I examined the parameters being passed to the GetVolumeInformationA function (as per mentioned in an earlier hint, the address of the volume serial number appears to be the relevant piece of information here)and looked at the return values. Maybe I am misunderstanding the function, but according to my API reference, the GetVolumeInformation function returns either a true or false value depending on whether or not the information is retrieved. From this I thought it only returns a 0 or 1 and nothing else. The 1 is returned in eax and makes sense, but there also seem to be some other values being returned as I step over the function in SoftIce. The return values are...

eax = 1
ecx = FF
edx = 4006
ss = 006AF8FC --> 224912F3

I don't quite get why it returns these other values when the api reference says the function only returns a 0 or 1.

Nevertheless, the stack segment value returned in this function appears to be the important piece of information, for this address pointed to by the stack segment holds a value crucial to the key calculation.
Looking back at the parameters being passed into the function, this stack segment address corresponds to the address of the volume serial number. When I displayed the contents of this memory location before the function was called, there was no relevent info in this location, but after the funcion call it contains a key piece of information... I guess the function returns more than just a 0 or 1 ???

Also, maybe someone could provide a little more explanation on this function than my API reference has given me. I've cracked several serial # protections and have never come across this approach before. In fact, were it not for the hint about the GetVolumeInformation, I would have probably stumbled around in the code for quite a while before I figured it out. Is this a common scheme ? In other words, if you had not seen this approach before, what would alert you to this tactic. Is GetVolumeInformation a common api call for programs and what does a program use this information for (other than generating a serial)??? I think it would be important to understand its use in a general sense in order to be able to tell if such a call would be "suspicious".

As soon a someone clarifies the return values of this function a little more, I will try to code a key gen for it.

I don't wan't to give too much away about the algorithm so others may have a chance to play with it, but I will give a general piece of advice... It can never hurt to look at your inputs and other given information in both hex and decimal since most calculations are performed in hex in the computer. Translating your decimal values into hex can give some clues about the origin of certain values...once I realized this it clarified quite a lot.

Cheers,
Clandestiny

hz
November 2nd, 2000, 23:11
hi,
take another look at kayaker's post
. Re:A Couple of Questions ??? Part II
and you may see things a little clearer.
regards
hz

goatass
November 2nd, 2000, 23:44
Hi Clandestiny, you misunderstood the API reference...here is what it says:
The GetVolumeInformation function returns information about a file system and volume whose root directory is specified.

BOOL GetVolumeInformation(
LPCTSTR lpRootPathName, // address of root directory of the file system
LPTSTR lpVolumeNameBuffer, // address of name of the volume
DWORD nVolumeNameSize, // length of lpVolumeNameBuffer
LPDWORD lpVolumeSerialNumber, // address of volume serial number
LPDWORD lpMaximumComponentLength, // address of system's maximum filename length
LPDWORD lpFileSystemFlags, // address of file system flags
LPTSTR lpFileSystemNameBuffer, // address of name of file system
DWORD nFileSystemNameSize // length of lpFileSystemNameBuffer
);

The key algorithm uses the serial number of your hard drive lpVolumeSerialNumber
so you won't have a generic serial and it will differ from computer to computer.
You tried looking at the lpVolumeSerialNumber using the D command in SoftIce but if you look at the parameters above this variable is not a string so D won't give you much, it's declared as LPDWORD so what you want to do is use the ? command to look at it.
? eax will show you the Hex/Dec/Ascii values in that register. In this case the hard drive serial number returned from the API is in Hex and that's the value that the key algo uses.

Return Values
If all the requested information is retrieved, the return value is nonzero. This doesn't mean much in this case you just have to look at the variables that are pushed to the stack before the CALL and see what they get filled with after the CALL executes.

eax = 1
ecx = FF
edx = 4006
ss = 006AF8FC --> 224912F3
224912F3 is the serial number of your C:\ drive in Hex this is what's used to generate your serial number to register the program.
EAX=1 just means that all the information was retrieved successfuly.

hope that gave you some insight into what this API does.

goatass

Kayaker
November 3rd, 2000, 00:03
Hi Clandestiny,

I can see the light bulb above your head already beginning to brighten

As you figured out, one of the parameter types passed to an API function before the call, besides constants, variables, etc. needed for the function, can simply be blank address locations which will be filled with some information on return.

The "Return Value" of zero or non-zero may simply be an error check of whether the call succeeded or not, as in this case. But for example, in the case of CreateFileA, which is used to create or open, among other things a file for reading, the Return Value will be a new open handle (Hwnd) to the file, if the call is successful.

As for how you would "know" that GetVolumeInformationA was used here, well, unless Goatass pulled that bit of info out of his...er, hat, then he either made a shrewd guess as to what generated that number that comes up in the reg box, or he used an API monitor to confirm it.

Hope this helps a bit.

goatass
November 3rd, 2000, 11:45
HI Kayaker,
I didn't pull anything out of my ... I simply traced the program and saw where the key was generated and I saw that GetVolumeInformation was used in the key generation algorithm, it's pretty simple and there is no need for an API monitor.
All you have to do is set a BPX GetDlgItemTextA, enter a serial and start tracing until you get to where GetVolumeInformation is called and see what it does.

When a program does calculations on a returned value from an API in a keygen algorithm you can be pretty sure it's gonna have something to do with the final serial number, there is no need to guess anything.

goatass

Kayaker
November 3rd, 2000, 18:01
Hiya goatass,

I was just kidding about you pulling ideas out of...wherever My reply was more just to stress the usefulness of an API monitor in giving clues to a protection scheme, as well as to getting a feel for the overall program flow, without using SoftIce. Of course the tried and true method of tracing the s/n can work just as well in some situations.

I haven't actually traced the program yet, but I'm curious about the Kernel32 API logs. GetVolumeInformationA is actually called twice, once at 0040C3F9 and once at 004225A8. After the 1st calling there are many calls to QueryPerformanceCounter and after the 2nd calling many calls to GetTickCount. I'm wondering what's actually going on here. Are both GetVolumeInformationA calls being used in the protection scheme? If not, why is the 2nd one called? And what are QueryPerformanceCounter and GetTickCount doing? I've seen GetTickCount being used before to transfer a random value into a CMP routine in order to make it fail, if a previous check on s/n validity also failed. I think there's other ways to use GetTickCount in protections as well (would make a good random seed generator).

As for QueryPerformanceCounter, I've never seen it being used before. Perhaps this might make a good advanced Task. What ARE these weird calls doing, even if they're not part of the specific protection algorithm itself? This might give a bigger picture of how the program actually works.

Can anyone come up with some other good intermediate/advanced Tasks for this program? How about patching it so that it writes lpVolumeSerialNumber to the ini file rather than the s/n you input? From a quick look at the code it seems that your hex s/n is transferred from [EBP-80] into a register before WritePrivateProfileStringA is called and code could be changed to point to the address containing your VolumeSerialNumber instead.

Just some ideas.

Regards,

Kayaker

Clandestiny
November 3rd, 2000, 22:46
Thanks for the input guys :-)

I think I figured out where my thinking was going wrong...I was looking at the function prototype and seeing that it should only return one value while *completely* forgeting that half of my parameters being pushed on the stack are pass by reference values (ie addresses whose contents may be changed during the course of the function). It is just amazing how many times I confuse myself on these concepts when I try to apply them to assembly !

Thanks to all for your patient help :-)

Cheers,
Clandestiny

goatass
November 4th, 2000, 01:09
Kayaker my friend you are making this waaaaaay too complicated, I have no clue what that second call to GetVolumeInformation does but it has NOTHING to do with the key algo and neither do the other APIs you mentioned. Check out the program and you will see it's sooo simple. This is a newbies project, I made sure there is nothing complicated in it.

goatass

Kayaker
November 4th, 2000, 04:46
Sorry goatass, I'm only trying to encourage people to think 'outside of the box'. Yes, I know it's simple, I looked at it, and it's a fine introduction to a s/n trace/algorithm/keygen and you've done a great job kicking off this Project area.

Maybe I shouldn't be bringing these things up in a Newbie project, but I figured some may want to extend the challenge beyond the "Yahoo, it's registered" concept. I know the initial lessons are important and dealing with protection schemes are the easiest way to go, but I for one would like to see the attitude develop that this is only one part of Reverse Engineering. There's no reason why we can't go beyond what one of a thousand other tuts already teach. There's a multitude of other interesting things to be learned from the rest of a program's code and certainly other opportunities for reversing, limited only by imagination.

In no way does this mean excluding or leaving behind the Newbie of any level, far from it. That's the last thing we should be trying to do. I just don't want to see "the Crack" being the ultimate narrow goal. I don't have all the answers. I consider myself a Newbie learning by the seat of his pants as much as anyone. But I figure we have a great chance here for a "new beginning" if you will and I'm sure if we tried we could develop a true Reversing community we'd be proud to part of. I know that sounds really corny and I don't know if it's even truly feasible, but I think it would be a nice goal to strive for. I'm not criticizing please understand, just trying to get across my thoughts.

Signing off,

Kayaker