Log in

View Full Version : Project # 3 TASKS 3 & 4


Kayaker
November 20th, 2000, 14:50
TASK 3 - Describe and/or keygen the registration algorithm. I'm not a big one on keygens, a verbal/codal description is better and probably more instructive for others. The algorithm is not *too* complicated


TASK 4 - This one's for fun. Change the image that's on the large button from a yellow "Men Working" sign to the red "Stop" sign that's in the file Resources.


BONUS TASK - Pretend at this point you don't know the exact structure of the program's licensing information. Can you re-create from first principles what is needed for the program to be validly registered? i.e. you knew where the info was kept, but not exactly what that info was. This falls under the realm of generating a registry structure/inifile/keyfile.

Task 2d) should've told you that some clues are in the exe file. This task is made even more difficult because of the presence of a CRC check which takes into account your specific user information, so maybe a combination of license reconstruction and CRC patch in the program might work.

Kayaker
November 23rd, 2000, 04:59
Hi All,

Thought I'd say a few words about Task 4 in case anyone is wondering "Where the hell do I start?"

You can find the image Resources that I want swapped with Exescope. The Resource ID's given are in decimal but any reference to them in Wdasm or SoftIce are in hex, so you need to convert. The APIs used to load image resources from a file are LoadIconA, LoadCursorA, LoadBitmapA and LoadImageA (which can be used for all 3 types). CopyImageA, FindResourceA, UpdateResourceA and some others should also be kept in mind for certain contexts. For Icon (and maybe Cursor) resources, there may be more than 1 listed under a Resource ID. Windows apparently chooses whichever pixel size is appropriate.

As an example if a program wants to load a cursor:

HCURSOR LoadCursor(

HINSTANCE hInstance, // handle of application instance
LPCTSTR lpCursorName // name string or cursor resource identifier

The 2nd stack parameter passes the Resource ID as seen in Exescope (but in hex). A few ways of attacking this might be to do a string search in W32dasm for LoadCursorA and set a breakpoint on that address(es). Or do a string search for "PUSH 0000xxxx" where xxxx is the Resource ID PUSHed as a DWORD. Or you could set a BPX LoadCursor do "dd esp+8" which will break and display the 2nd stack parameter, or Resource ID, in the Data window in SoftIce.

Once you find where the Resource ID representing the yellow image is PUSHed in the file, you simply need to replace it with the one of the red image.

Hope this helps,

Kayaker

Clandestiny
November 24th, 2000, 12:58
Greetings Kayaker and fellow reversers...

I have not yet done tasks 1 & 2 because I jumped right in to task 3 after examining Happy Icon's code a little bit in SICE. I registered it first by forcing the jz after the eax,ecx comparison. Then I decided to key gen Happy Icon since the algorithm didn't look too bad :-)

I'll explain what I found out about the algorithm first and then I'll include the source to my key gen (written in C).

I found that this algorithm computes a value based upon the name the user enters and this value (converted to decimal) is the key. The entry form asks for both the full name and the first name of the user.

Name:
First Name:
Key:

These strings are then concatnated into a single new string consisting of:

"first_name""happyicon""full_name"

The ascii codes for each character in this new string are then fed sequentially into the algorithm in a loop that terminates with the end of the string.

The algorithm essentially consists of 2 XOR operations.

i=0
key = 0xFFFFFFFF

while (name[I] != NULL)
{
key = name[I] xor key;
key = key xor 0x13579ACE;
i++;
}

key = key xor 0x2468BDF0;

The final result of this algorithm stored in the variable key is your key when it is output in decimal.

******************************************

Key Generator Source Code in C:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void main()
{
char first_name[30];
char last_name[30];
const char blank_space[] = " ";
const char string[] = "happyicon";
char string2[50];
int i=0;
int key = 0xFFFFFFFF;


//Get first and last names from user
printf("Enter first name: ";
scanf("%s",&first_name);
printf("Enter last name: ";
scanf("%s",&last_name);

//Put names in form "first""happyicon""first"" ""last"
strcpy (string2, first_name);
strcat (first_name,string);
strcat (first_name,string2);
strcat (first_name,blank_space);
strcat (first_name,last_name);

//Generate key
while (first_name[I] != NULL)
{
key = first_name[I] ^ key;
key = key ^ 0x13579ACE;
i++;
}

key = key ^ 0x2468BDF0;

//Output key
printf("
key = %d

",key);
}

Cheers :-)
Clandestiny

Clandestiny
November 24th, 2000, 19:46
Hi again,

I think I need a little help with task 4...A couple of things are confusing me ???

1)There is no red "stop" sign in the resources I'm seeing in Exescope...I can see the "men working" sign...but no stop sign. I suppose I can always use one of the other images if necessary ?

2)I wrote down what I believed to be the resource name for the men working sign (275 decimal)...there also was an offset 2D3D8 and size 1160. Then I fired up my api moniter and had it to look for all calls like LoadIconA, LoadBitmapA, LoadCursorA. It logged several calls to LoadIconA, but none of the parameters passed in these calls matched my resource identifier! I know it must load these images so I must be doing something wrong

3)Also, my user32.fnl seems not to have the LoadImageA function ? Could this be a problem ?

Many Thanks :-)

Clandestiny

Kayaker
November 24th, 2000, 22:46
Hey man,

Things aren't always as they seem

The red stop sign IS there, it's just not a bitmap.

And you're right, LoadImageA isn't part of the user32.fnl library and yes could be a problem if you rely too heavily on a API monitor (even though I keep touting it ^_^ )

cya

Clandestiny
November 25th, 2000, 18:12
Kayaker,

Wow! That was pretty cool...I've never done anything like this before...ExeScope is definately an interesting little toy that brings up many more interesting reversing possibilites...

You were absolutely right! It was not a bitmap... which goes to show I should *look* a little more closely before I *leap* into something new!

And the function does not show up in my api moniter which is a little puzzling...I finally found it in Wdasm!

Cheers
Clandestiny

Kayaker
November 27th, 2000, 04:25
Hi Clandestiny,

Fun huh?

I figured LoadImageA was probably a useful one to have APISpy32 monitor so I decided to add it to the library. What I did was to open a (copy) of user32.fnl with the APISpy program Libedit.exe and Add a function. I entered the following in the edit box:

LoadImageA(HANDLE,LPSTR,DWORD,DWORD,DWORD,DWORD)

to correspond to the 6 parameters of the function:

HANDLE LoadImage(

HINSTANCE hinst, // handle of the instance that contains the image
LPCTSTR lpszName, // name or identifier of image
UINT uType, // type of image
int cxDesired, // desired width
int cyDesired, // desired height
UINT fuLoad // load flags


Then I ran APISpy on HappyIcon again and got a successful result:

0040A2D7:LoadImageA(HANDLE:00400000, LPSTR:00000113, DWORD:00000001, DWORD:00000030, DWORD:00000030, DWORD:00000000)
0040A2DD:LoadImageA = 35DF

You probably recognize the parameters being pushed as the correct ones...

Cheers,

Kayaker

ThRaX
November 29th, 2000, 23:43
Heh, yay I got tasks 1 done and 2 done, learned a good deal from both, and now on to 3. After looking at the algorythm, I found the *loop*...The great thing about this program (er, the thing that makes it rather simple anyway) is that it has *all* the code a cracker could want for any patch, serial fishing, or keygenning in a compact block of code about 10 lines long...no calls, no jumping around, its all *right* there. Quite conveniant
Anyhow, essentially how this program calculates is it concatinates the Firstname string, with the string "HappyIcon", followed by the Lastname string. So the string will be "FirstnameHappyIconLastname"....Alright, so heres how it is in pseudocode

var a=pointer to "firstnameHappyIconlastname"
var b=FFFFFFFFh
var c=0
while (name string is not finished cycling through) {
c=current char of a
key=key xor c
key=key xor 13579ACEh
increment a to point to next char
}
key=key xor 2468BDF0h

Anyway, I've attached my keygen in .zip format to this post...written in win32asm
no ripped code either even though i called my calc function "Rip" ACtually I was planning on ripping code, but the damn prog wouldnt disassemble under IDA, so that plan was scratched...Just wrote it from the bottom up.

mersenne
November 30th, 2000, 17:42
Also have completed Tasks 3 and 4. My keygen was in win32asm but I won't bother to post it since Thrax has already put an asm one up.

Task 4 was quite good fun The thinking took the biggest chunk of time, once I sorted out what was going on, the actual changes were very easy. I've had a brief look at the bonus task at the moment but am a little confused on the aim/outcome? Is the aim to come up with a way of contructing a keyfile so that it will register an unregistered copy of the program?

mersenne

Kayaker
November 30th, 2000, 18:27
Hi Mersenne,

That was sort of the original idea, to simulate how to reconstruct a keyfile if there was no serial entry routine in a program. I later gave another option to simply change 1 byte in the existing keyfile, which will give a "corrupt keyfile" message, and see if you can trace and patch the CRC check causing it.

I made a few comments which might help (or likely confuse in the 3 threads

Project #3 - Question to Kayaker
Project # 3
Task 4 CRC hints (all right, so I meant the Bonus task)

Let me know which of the 2 Bonus tasks you're attempting and I'll try to help. I didn't actually DO the 1st one BTW, just figured it COULD be done. Especially with knowing WHAT the keyfile was supposed to look like, I thought it would be a good exercise to pretend you didn't and go through the routine of trying to reconstruct it. Filemon would tell you that the program is looking for a file called happyicon.lic, so you create one and try to fill in the correct structure, as you normally would with a keyfile. Luckily in this program, there is hard-coded the skeleton of the structure in the exe file, so theoretically you should be able to create a valid keyfile. The CRC check just throws in a nasty little quirk to it all.

Kayaker

mersenne
November 30th, 2000, 22:02
Hi Kayaker,

Thanks for the explanations, much clearer on how to proceed and I'll get back after I've:

a) Done some work
b) Confused myself totally
c) Decided I've got no idea what the heck is going on
d) All of the above

Cheers
mersenne

ThRaX
November 30th, 2000, 22:21
I think I'm on to *something* here at last..
Looking up the API GetPrivateProfileString and WritePrivateProfile string seems to have given me *SOME* insight here on how to create a valid keyfile.

BOOL WritePrivateProfileString(

LPCTSTR lpszSection, // address of section name
LPCTSTR lpszKey, // address of key name
LPCTSTR lpszString, // address of string to add
LPCTSTR lpszFile // address of initialization filename
);

Anyhow, I searched for "WritePrivateProfileStringA" in the dead listing, and only found ONE. That means that it is only called once, obviously upon registration. Now, of course I searched a bit above the call for any paramaters being pushed, knowing that this would tell me exactly how to construct the keyfile...

:00413FA6 68C8E84500 push 0045E8C8
:00413FAB 50 push eax

* Possible StringData Ref from Data Obj ->"CRCKM"
|
:00413FAC 6888484200 push 00424888

* Possible StringData Ref from Data Obj ->"END"
|
:00413FB1 6884484200 push 00424884

* Reference To: KERNEL32.WritePrivateProfileStringA, Ord:031Bh
|
:00413FB6 FF15F0004200 Call dword ptr [004200F0]


now looking at this (in soft ice of course), I found the value at 0045E8C8 to be the file name, happyicon.lic as expected (consulting the trusty win32 api manual), the next paramater was in eax, and when I displayed the contents of EAX I found a VERY strange string, a sequence of numbers "287804711"....No clue what this is, all i know is previously in code i remember seeing something done with the value '04711', I don't remember where I saw it before though...After that the string 'CRCKM', and then the string 'END' were pushed, which is the section ([END]), and the key (CRCKM).

So looking at the keyfile it looks like this in happyicon.lic

[END]
CRCKM=287804711

any insight as to what this means would be appreciated

one more thing, why dont I find anything about writing the
[ENREGISTREMENT]
licence=********
first name=ThRaX
last name=CINARA

portion of the keyfile? I Found no reference to it whatsoever... Oh by the way I got the french version of this program, so thats why the headers are bit strange ; )

Cya later
--ThRaX

Kayaker
November 30th, 2000, 22:43
Hiya Thrax,

Cool, sounds like you're getting somewhere. The CRCKM=287804711 is the calculated CRC value of the .lic file which the program stores into the .lic with WritePrivateProfileStringA as you found out.

As to how the rest of the stuff is written, try a string search in the .exe file with a hex editor, or a string search in Wdasm for '[ENREGISTREMENT]' and you'll find where the rest of the .lic structure comes from.

ThRaX
December 1st, 2000, 17:29
Hey Kayaker...one thing, what exactly do you mean by the "CRC Calculated value of the licence file"?? Does this mean that the value represents the contents of the file in some encrypted manner?? (So a change of it can be detected)

Kayaker
December 1st, 2000, 18:05
Quote:
ThRaX (12-01-2000 06:29):
Hey Kayaker...one thing, what exactly do you mean by the "CRC Calculated value of the licence file"?? Does this mean that the value represents the contents of the file in some encrypted manner?? (So a change of it can be detected)


Yes.

Interestingly, it does a nifty trick in that the CRC value that is in the file INCLUDES the CRC value itself. i.e., if the algorithm was to sum all the bytes as hex in the file and write that value under [CRCKM], then that would include the number itself, but before it's actually written to the file. So it has to know what this value is before it finishes calculating the CRC!

Sorry, that probably just muddies up the idea, it doesn't really matter. If you change the CRC number or any string or add a space etc., the calculated CRC changes and you get an error message. At this point it doesn't matter what the CRC algorithm is (sum the bytes, divide by pi, whatever), the idea is to bypass it.

Kayaker

mersenne
December 3rd, 2000, 17:24
Quote:
Kayaker (11-30-2000 07:27):

Let me know which of the 2 Bonus tasks you're attempting and I'll try to help. I didn't actually DO the 1st one BTW, just figured it COULD be done. Especially with knowing WHAT the keyfile was supposed to look like, I thought it would be a good exercise to pretend you didn't and go through the routine of trying to reconstruct it. Filemon would tell you that the program is looking for a file called happyicon.lic, so you create one and try to fill in the correct structure, as you normally would with a keyfile. Luckily in this program, there is hard-coded the skeleton of the structure in the exe file, so theoretically you should be able to create a valid keyfile. The CRC check just throws in a nasty little quirk to it all.

Kayaker


Hi Kayaker,

I am trying the 1st approach, trying to create the .lic file from scratch. I'm trying to do it logically like I really didn't know what the program is looking for. I must admit it is hard not to make assumptions once you already know the answer

OK, it is easy enough to figure out that the program is looking for a keyfile. I created one of 100h bytes and filled it with 01. The readfile operation sorta chokes at this point and the task needs to be killed (via procdump) to try again. This makes sense as the keyfile is wrong. I guess at this point I would try to disassemble the file and look for some clues relating to the .lic file or trace the code after the readfile instruction.

mersenne

Kayaker
December 4th, 2000, 00:48
Hi Mersenne,

Yeah, it is hard to forget about preconceived notions of what the license file is supposed to look like. In fact, a valid .lic file can be just 2 lines long! Faking amnesia, here's one way to go about it.

Filemon or APISpy tells you that it's looking for a Happyicon.lic file. Create one and put a bit of junk in it. Now Filemon says it wants to read 4096 (1000h) bytes of this file, but the program gets locked up in a loop somewhere. CTRL-ALT-DEL kill the program and try creating a file of the correct size. Same problem.

Try a String Ref search in W32dasm and notice refs to suspicious entries like "DO NOT MODIFY", "[SOFTWARE]", "CRCKM=". Exescope doesn't show up any of these strings. Search for them in the exe file with a hex editor et viola,

00024728 5B45 4E44 5D0D 0A00 0A0D 0A0D 0A00 0000 [END]...........
00024738 7665 7273 696F 6E3D 0000 0000 6C6F 6769 version=....logi
00024748 6369 656C 3D00 0000 5B53 4F46 5457 4152 ciel=...[SOFTWAR
00024758 455D 0D0A 0000 0000 0D0A 0D0A 0000 0000 E]..............
00024768 6C61 7374 206E 616D 653D 0000 6669 7273 last name=..firs
00024778 7420 6E61 6D65 3D00 6C69 6365 6E63 653D t name=.licence=
00024788 0000 0000 5B45 4E52 4547 4953 5452 454D ....[ENREGISTREM
00024798 454E 545D 0D0A 0000 0D0A 0000 3B0D 0A00 ENT]........;...
000247A8 3B44 4F20 4E4F 5420 4544 4954 0D0A 0000 ;DO NOT EDIT....
000247B8 3B44 4F20 4E4F 5420 4D4F 4449 4659 0D0A ;DO NOT MODIFY..

Note that 0A stands for LineFeed LF and 0D for CarriageReturn CR. Try extracting this hex into a new file and save it. Hmmm, doesn't look quite right. Try removing all occurrences of "00". This gives a text file which looks like:

------------------------------------------------
[END]



version=logiciel=[SOFTWARE]


last name=first name=licence=[ENREGISTREMENT]

;
;DO NOT EDIT
;DO NOT MODIFY
-------------------------------------------------

Not bad, we can logically add CR's after the "=" signs and we KNOW that the key in square brackets in ini files are supposed to be first, so we can turn the whole thing upside down and get something pretty close to the correct structure. Program still hangs, so we need to get in there with SoftIce.

on to Part II...

Kayaker
December 4th, 2000, 00:49
OK, that's one way to start, but let's say we couldn't even figure out that much about the .lic file. Create a file of 1000h bytes, fill it with some byte and break on ReadFile. Do a 'BPM address R' on the 2nd stack parameter after ReadFile returns (for me it was 01594240), SI breaks and you can trace to a loop at:

:004167A9 DEC DWORD PTR [ESI+04]
:004167AC JS 004167B8
:004167AE MOV ECX,[ESI]
:004167B0 MOVZX EAX,BYTE PTR [ECX]
:004167B3 INC ECX
:004167B4 MOV [ESI],ECX
:004167B6 JMP 004167BF
:004167B8 PUSH ESI
:004167B9 CALL 00419ED1
:004167BE POP ECX
:004167BF CMP EAX,-01
:004167C2 JZ 004167DA
:004167C4 MOV [EDI],AL
:004167C6 INC EDI
:004167C7 CMP AL,0A
:004167C9 JZ 004167D0
:004167CB DEC DWORD PTR [EBP+0C]
:004167CE JNZ 004167A9

The 1st thing you should notice is the :004167C7 CMP AL,0A line, always important to keep an eye out for when reconstructing keyfiles. Since 0A stands for CR it seems the structure of the .lic file should have some line breaks rather than being one complete byte sequence. I usually create a file like this

Line1
Line2
Line3
etc.

so you have some idea of which line is being worked on. Modify .lic and the above code continues to

:00410F30 CALL 0041678C
:00410F35 PUSH 06
:00410F37 PUSH 004242C8
:00410F3C PUSH 00460580
:00410F41 CALL 0041F520
:00410F46 ADD ESP,18
:00410F49 TEST EAX,EAX
:00410F4B JZ 00410FA9

Display 4242C8 and you see the string "CRCKM=". After the Call 41F520, EAX = 1. If you were to R FL Z the jz you'd get the "License file has been modified" MessageBox. NOW we're getting somewhere. So change "Line1" to "CRCKM=", enter a value for it (numbers or letters doesn't matter because you don't know this is a value for a CRC check at this point). Now EAX = 0 and the program continues to the next step.

If you've tried the CRC check task you'd recognize the next code by its calls to the FPU registers. At this point you don't really know this though so you trace on. There will be an obvious Jump which you'd probably do a R FL Z on at some point while trying different things and you'd find this brings you to a GetPrivateProfileStringA call where the key it's looking for is [END]. Either a leap of faith or a few other clues tell you that - "Aha, so 'CRCKM=' must be under an '[END]' key", so update the .lic file to show this.

Continuing, you find a comparison between your value of CRCKM and some other value. You enter this value instead and whaddya know, a valid license file!

So, being dumb as to what was really going on, we can come up with a valid .lic file, though it doesn't have any of our reg info in it as the About box shows. I suppose one could trace from selecting the About menu item and see where it gets the info from and perhaps relate that back to the .lic file. If one cared

Hope this makes some sense,

Kayaker

mersenne
December 4th, 2000, 17:19
Hi Kayaker,

Yes, it makes perfect sense. I have had a go and made it some way down the path you just described. In summary; I created a 100 byte file which of course doesn't read it properly. Set breakpoint on CreateFileA and the call to the lic file is the sixth one in. Breakpoint on ReadFile and then trace will show that the file contents are processed under it find the linefeed character 0A (yeah I found it too ) It then compares what it just found to the string CRCKM=. So add that to the start of the lic file and rerun. The file will now read in and we get the "modified lic file" message. We get to the GetPrivateProfileString call and find out that it is looking for the section name END in the lic file. Add it to the file in the manner you described and we get down to the checksum calculation, check the comparison and put that value as a checksum in the file.

This bit didn't work for me but I also didn't have the rest of the structures in the file the way you added them. I'll need to examine this a bit closer but I'm pretty happy that I got to where I did.

I noticed there is some another keyfile practice in session, so I'll have a go at that too.

Thanks Kayaker for your help and patience

mersenne

Clandestiny
December 11th, 2000, 14:15
Hi,

Been really busy this past week, but I finally got a chance to start working on the keyfile part of Kayaker's project. I found much help / advice in the above posts, but I still seem to be having a few problems. I have created the happicon.lic file and filled it with 4096 bytes after examination in filemon. Also, as was per mentioned in an above post, the program hangs up and must be killed. Looking in Wdasm, I find the reference to WritePrivateProfileStringA...and proceed to try to examine it in SICE. Here is my puzzlement and problem...

1) Examination in API spy does not list a WritePrivateProfileStringA or a GetPrivateProfileStringA call. It actually lists 2 other calls...a)CreateFileA -->happyicon.lic which makes sense and b)WritePrivateProfileStringW --> what exactly is the difference between the W and A version of these calls? Anyway, it seems strange that the function would show in Wdasm but not in APIspy (unless it is because the program gets locked up?).
2) SoftIce will not break on either these functions or the addresses shown in Wdasm (also presumably because the program gets locked up?)

Is there no way to examine this part of the program in SoftIce or am I just overlooking something???

Thanks in advance,
Clandestiny

Kayaker
December 11th, 2000, 21:03
Hi Clandestiny,

You're right in that APISpy doesn't see the GetPrivateProfileStringA call because the program gets locked up in some loop trying to read the .lic file if it's not in some kind of correct format yet. You need to trace solely with SI in this case and figure out how to modify the file so it continues to the next step. When you have a couple of critical entries in the file, THEN you reach GetPrivateProfileStringA.

If you use the "real" .lic file produced earlier you should see the proper API calls. As for the "W", I believe that refers to Unicode strings. Don't know what that could have been. What ini file did it refer to?

Kayaker