A New Toy reversing the different 'modes' of a target

by Swann
30 October 1998


Well, well, well... welcome back Swann! For those of you that don't know nothing, Swann is practically the FOUNDER of the whole +HCU Database. And if you give a look at aca100.htm you'll see why. This essay is both well written and well explained. Interesting for any reverser or protector. A little too much code maybe (you'll notice that this is IDA dumping) but the explanations make the effort of following it well worth. The two tools that are here targeted have some fairly easy protection schemes. You'll find and download an (uncracked) copy of the Customizer on my own tools.htm page. My copy is 226304 bytes long, apparently version 1.10 and has a ridicolous Cinderella type protection, so I guess it's not the same version that Swann encountered. Anyway, enjoy this good essay and enjoy both tools. You'll be able to see a very simple (and funny) use of customizer in my Scarecrow license agreements and how to defeat them, btw.

A New Toy
reversing the different 'modes' of a target 

by swann  30 October 1998

Level: intermediate
Tools: standard

Recently on one of those message boards, someone mentioned two tools
I had never heard of. The person and the context were somewhat obscure,
so I was a little reluctant checking them out. Eventually I did, however,
and methinks these tools are worth taking a look at. Their purpose is
runtime editing of Windows windows. Ever had a problem with greyed out
check-boxes? Well, these programs ungrey them so you can give them
the check mark they deserve. You can also send messages to windows,
and with Customiser-- yes, that's an "s", they're from Oz-- you can
even save the changes you've made at runtime (For this purpose,
Customiser leaves shortcuts in the application directory). I tried
these programs with warfare.exe, a cute little strategy game I
had cracked years ago with a lot of effort. With Magic Mouse, this
is just a blast. You select the window, choose "enable," click, and
it's enabled. It's so easy it almost takes the fun out of it.      

The programs in question are:

Magic Mouse Demo  mm32.exe  137728 bytes
Customiser Demo   cust.exe  215552 bytes

Magic Mouse is widely available as mm32demo.exe, Customiser seems to
be available only at the publisher Wanga International's website:
(Download was terribly slow).

Customiser is the more advanced program, it seems to contain all the
functionality of MagicMouse, plus the ability to save the changes. So
this is probably the one you want to get. It is also, from a reversing
point of view, less interesting, since the protection scheme is
trivial: a simple combination of time limit and a nag screen --
patching a "ret" in the beginning of the nag call takes care of both
-- and a limit to the amount of changes you an save, easily located
through string references. This is a five-minutes-crack and not in
need of further elaboration. So, in line with Frav's new policy, I
will not deal with this newer and more powerful tool, but with the
older one.

Magic Mouse, in addition to the nag-and time limit protection, also
has a feature-disabling restriction that is a little more challenging,
and an annoying switch from enabled to disabled at random intervals.

Let's take the obstacles in the order of occurrence. When I first
started the demo up, it was already expired. The usual suspect, the
call to getlocaltime cum subsequent check turns out to be guilty

00401DB5 E8 D6 2F 01 00		 call	 j__getdate
00401DBA 59			 pop	 ecx
00401DBB 81 7D F8 CE 07	00 00	 cmp	 dword ptr [ebp-8], 7CEh
00401DC2 7F 2B			 jg	 short loc_401DEF
00401DC4 81 7D F8 CE 07	00 00	 cmp	 dword ptr [ebp-8], 7CEh
00401DCB 75 09			 jnz	 short loc_401DD6
00401DCD 0F BE 4D FD		 movsx	 ecx, byte ptr [ebp-3]
00401DD1 83 F9 04		 cmp	 ecx, 4
00401DD4 7F 19			 jg	 short loc_401DEF  ;my problem was 							 ;here
00401DD6  loc_401DD6:		                           ; CODE XREF: .text:00401DCBj
00401DD6 81 7D F8 CE 07	00 00	 cmp	 dword ptr [ebp-8], 7CEh
00401DDD 75 27			 jnz	 short loc_401E06
00401DDF 0F BE 45 FD		 movsx	 eax, byte ptr [ebp-3]
00401DE3 83 F8 04		 cmp	 eax, 4
00401DE6 75 1E			 jnz	 short loc_401E06
00401DE8 0F BE 55 FC		 movsx	 edx, byte ptr [ebp-4]
00401DEC 4A			 dec	 edx
00401DED 7E 17			 jle	 short loc_401E06

You make the appropriate changes, it's all fairly obvious. After this
modification, you're treated to the startup nagscreen, which also
turns up frequently during normal program execution. Breaking at
messageboxexa will take you to this beauty:

00401108			 ;   S u b r o u t i n e
00401108			 ; Attributes: bp-based	frame
00401108 sub_401108 proc near; CODE XREF: .text:00401DFCp
00401108 	         	       ; .text:00401E13p
00401108			       ; .text:00401E8Cp
00401108			 push	 ebp
00401109 8B EC			 mov	 ebp, esp
0040110B 81 C4 2C FF FF	FF	 add	 esp, 0FFFFFF2Ch
00401111 53			 push	 ebx
00401112 56			 push	 esi
00401113 57			 push	 edi
00401114 8B 75 0C		 mov	 esi, [ebp+arg_4]
00401117 8B 5D 08		 mov	 ebx, [ebp+arg_0]
0040111A B8 E0 50 41 00		 mov	 eax, offset unk_4150E0
0040111F E8 AC 33 01 00		 call	 @__InitExceptBlockLDTC
00401124 33 D2			 xor	 edx, edx
00401126 89 15 CC 50 41	00	 mov	 dword_4150CC, edx
0040112C 6A 00			 push	 0
0040112E 53			 push	 ebx
0040112F E8 20 3A 01 00		 call	 j_EnableWindow
00401134 66 C7 85 3C FF	FF FF 14+mov	 [ebp+var_C4], 14h
0040113D 56			 push	 esi
0040113E 6A 00			 push	 0
00401140 8D 8D 50 FF FF	FF	 lea	 ecx, [ebp+var_B0]
00401146 51			 push	 ecx
00401147 E8 74 29 01 00		 call	 sub_413AC0
0040114C 83 C4 0C		 add	 esp, 0Ch
0040114F 8B F8			 mov	 edi, eax
00401151 83 85 48 FF FF	FF 04	 add	 [ebp+var_B8], 4
00401158 57			 push	 edi
00401159 8B 47 0C		 mov	 eax, [edi+0Ch]
0040115C FF 50 14		 call	 dword ptr [eax+14h]
0040115F 59			 pop	 ecx
00401160 8B F8			 mov	 edi, eax
00401162 83 AD 48 FF FF	FF 04	 sub	 [ebp+var_B8], 4
00401169 6A 02			 push	 2
0040116B 8D 95 50 FF FF	FF	 lea	 edx, [ebp+var_B0]
00401171 52			 push	 edx
00401172 E8 70 2A 01 00		 call	 sub_413BE7
00401177 83 C4 08		 add	 esp, 8
0040117A 66 C7 85 3C FF	FF FF 08+mov	 [ebp+var_C4], 8
00401183 4F			 dec	 edi
00401184 75 03			 jnz	 short loc_401189
00401186 4E			 dec	 esi
00401187 75 0C			 jnz	 short loc_401195
00401189	 loc_401189:		       ; CODE XREF: sub_401108+7Cj
00401189 6A 00			 push	 0
0040118B 6A 00			 push	 0
0040118D 6A 10			 push	 10h
0040118F 53			 push	 ebx
00401190 E8 13 3A 01 00		 call	 j_PostMessageA
00401195	 loc_401195:		       ; CODE XREF: sub_401108+7Fj
00401195 6A 01			 push	 1
00401197 53			 push	 ebx
00401198 E8 B7 39 01 00		 call	 j_EnableWindow
0040119D 8B 8D 2C FF FF	FF	 mov	 ecx, [ebp+var_D4]
004011A3 64 89 0D 00 00	00 00	 mov	 large fs:0, ecx
004011AA 5F			 pop	 edi
004011AB 5E			 pop	 esi
004011AC 5B			 pop	 ebx
004011AD 8B E5			 mov	 esp, ebp
004011AF 5D			 pop	 ebp
004011B0 C3			 retn	
004011B0			 sub_401108 endp

As you can see from the Xrefs, it's called from three different
locations. You can either cure this at the points of origin, or here
inside the call. No stack complications, just return without executing
-- should take care of this nagging problem.

Alright, now we're free to enjoy the pleasures of the program, only to
be interrupted by the program switching back from enabled to disabled
mode without asking us. Here we should be a bit careful, since we
don't want to patch away our own opportunity for disabling magic
mouse. We only want to get rid of the unmotivated switches executed by
the program without asking our permission. String references take you
to the neutral "call to switch,"
where it all comes together. It has "good" and "bad" callers. Stack
analysis shows that the good caller, i.e.: us, when we voluntarily
disable Magic Mouse, is 405a0a, while the bad, unvoluntary caller is
401e7a. This is the one we want to take care of. (The other callers
listed here by IDA didn't call while I monitored the program, they
might call later and you can then handle them accordingly).      

00401ECB			 ;   S u b r o u t i n e
00401ECB			 ; Attributes: bp-based	frame
00401ECB sub_401ECB proc near	;BAD caller ; CODE XREF: .text:00401E7Ap
00401ECB 				       ; .text:00401EA5p
00401ECB				       ; sub_401F6A+4Ap
00401ECB				       ; .text:00401FE2p
00401ECB	                ;GOOD caller   ; .text:00405A0Ap
00401ECB				       ; .text:00405AB6p
00401ECB	     ; DATA XREF: .data:004152B8o
00401ECB		                       ; .data:004154B0o
00401ECB			 arg_0=	dword ptr  8
00401ECB			 push	 ebp
00401ECC 8B EC			 mov	 ebp, esp
00401ECE 53			 push	 ebx
00401ECF 8B 5D 08		 mov	 ebx, [ebp+arg_0]
00401ED2 83 7B 21 00		 cmp	 dword ptr [ebx+21h], 0
00401ED6 74 0F			 jz	 short loc_401EE7
00401ED8 6A 01			 push	 1
00401EDA 8D 43 21		 lea	 eax, [ebx+21h]
00401EDD 50			 push	 eax
00401EDE 53			 push	 ebx
00401EDF E8 93 1B 00 00		 call	 sub_403A77
00401EE4 83 C4 0C		 add	 esp, 0Ch
00401EE7	 loc_401EE7:		       ; CODE XREF: sub_401ECB+Bj
00401EE7 33 D2			 xor	 edx, edx
00401EE9 89 53 21		 mov	 [ebx+21h], edx
00401EEC 80 7B 4B 00		 cmp	 byte ptr [ebx+4Bh], 0
00401EF0 74 0E			 jz	 short loc_401F00
00401EF2 C6 43 4D 00		 mov	 byte ptr [ebx+4Dh], 0
00401EF6 53			 push	 ebx
00401EF7 E8 41 47 00 00		 call	 sub_40663D  ;neutral switch call
00401EFC 59			 pop	 ecx
00401EFD 5B			 pop	 ebx
00401EFE 5D			 pop	 ebp
00401EFF C3			 retn	
00401F00			 ;

Further inspection of bad_caller shows this situation::

00401E64			       ;  bad_switch_caller
00401E64    loc_401E64:		       ; DATA XREF: .data:00415270o
00401E64 55			 push	 ebp
00401E65 8B EC			 mov	 ebp, esp
00401E67 8B 45 08		 mov	 eax, [ebp+8]
00401E6A 83 3D CC 50 41	00 0F	 cmp	 dword_4150CC, 0Fh
00401E71 7C 21			 jl	 short loc_401E94
00401E73 80 78 4B 00		 cmp	 byte ptr [eax+4Bh], 0
00401E77 74 07			 jz	 short loc_401E80;make unconditional
00401E79 50			 push	 eax
00401E7A E8 4C 00 00 00		 call	 sub_401ECB	;unmotivated switch
00401E7F 59			 pop	 ecx
00401E80 loc_401E80:		       ; CODE XREF: .text:00401E77j
00401E80 6A 00			 push	 0
00401E82 A1 F0 B9 41 00		 mov	 eax, dword_41B9F0
00401E87 8B 10			 mov	 edx, [eax]
00401E89 FF 72 0C		 push	 dword ptr [edx+0Ch]
00401E8C E8 77 F2 FF FF		 call	 sub_401108
00401E91 83 C4 08		 add	 esp, 8
00401E94 loc_401E94:		       ; CODE XREF: .text:00401E71j
00401E94 5D			 pop	 ebp
00401E95 C3			 retn	
00401E96			 ; 

So we want to avoid the unmotivated switch at 401e7a, and we do this
by reverting 401e77 into an unconditional jump.

Finally, time for peaceful inspection of the program. And time to take
a look at the most interesting part of the protection: the disabling
of the "exclude mode." The full version of Magic Mouse can exclude a
user defined set of windows, gathered in the file "exlude.lst." That
should help with the reduction of complexity and the focusing on
what's important. Let's see if we can find a way to reenable that.
When you try activating the exclude mode, you get a window telling you
that this feature is not available in the demo version. But we've been
lied to so many times, we're not quite ready yet to believe this. The
caller of this disappointing message is 40659b, and it's worth looking
at it -- and at its context, that's why the following listing is a
little longer than usual. 

004064CC	 loc_4064CC:		       ; DATA XREF: .data:004152D0o
004064CC 55				       ; .data:00415438o
004064CC			 push	 ebp
004064CD 8B EC			 mov	 ebp, esp
004064CF 51			 push	 ecx
004064D0 53			 push	 ebx
004064D1 8B 5D 08		 mov	 ebx, [ebp+8]
004064D4 33 C0			 xor	 eax, eax    ;0== NORMAL mode
004064D6 89 45 FC		 mov	 [ebp-4], eax
004064D9 8D 55 FC		 lea	 edx, [ebp-4]
004064DC 52			 push	 edx
004064DD 53			 push	 ebx
004064DE E8 C3 00 00 00		 call	 sub_4065A6
004064E3 83 C4 08		 add	 esp, 8
004064E6 80 7B 4B 00		 cmp	 byte ptr [ebx+4Bh], 0
004064EA 74 08			 jz	 short loc_4064F4
004064EC FF 73 19		 push	 dword ptr [ebx+19h]
004064EF E8 D2 E6 00 00		 call	 j_SetCursor
004064F4	 loc_4064F4:		       ; CODE XREF: .text:004064EAj
004064F4 5B			 pop	 ebx
004064F5 59			 pop	 ecx
004064F6 5D			 pop	 ebp
004064F7 C3			 retn	
004064F8			 ;

004064F8 004064F8 loc_4064F8: ; DATA XREF: .data:00415300o 004064F8 55 ; .data:00415450o 004064F8 push ebp 004064F9 8B EC mov ebp, esp 004064FB 51 push ecx 004064FC 53 push ebx 004064FD 8B 5D 08 mov ebx, [ebp+8] 00406500 C7 45 FC 02 00 00 00 mov dword ptr [ebp-4], 2; 2== MOVE mode 00406507 8D 45 FC lea eax, [ebp-4] 0040650A 50 push eax 0040650B 53 push ebx 0040650C E8 95 00 00 00 call sub_4065A6 00406511 83 C4 08 add esp, 8 00406514 80 7B 4B 00 cmp byte ptr [ebx+4Bh], 0 00406518 74 08 jz short loc_406522 0040651A FF 73 19 push dword ptr [ebx+19h] 0040651D E8 A4 E6 00 00 call j_SetCursor 00406522 00406522 loc_406522: ; CODE XREF: .text:00406518j 00406522 5B pop ebx 00406523 59 pop ecx 00406524 5D pop ebp 00406525 C3 retn 00406526 ;
00406526 00406526 loc_406526: ; DATA XREF: .data:00415330o 00406526 55 ; .data:00415468o 00406526 push ebp 00406527 8B EC mov ebp, esp 00406529 51 push ecx 0040652A 53 push ebx 0040652B 8B 5D 08 mov ebx, [ebp+8] 0040652E C7 45 FC 04 00 00 00 mov dword ptr [ebp-4], 4; 4==SEND mode 00406535 8D 45 FC lea eax, [ebp-4] 00406538 50 push eax 00406539 53 push ebx 0040653A E8 67 00 00 00 call sub_4065A6 0040653F 83 C4 08 add esp, 8 00406542 80 7B 4B 00 cmp byte ptr [ebx+4Bh], 0 00406546 74 08 jz short loc_406550 00406548 FF 73 19 push dword ptr [ebx+19h] 0040654B E8 76 E6 00 00 call j_SetCursor 00406550 00406550 loc_406550: ; CODE XREF: .text:00406546j 00406550 5B pop ebx 00406551 59 pop ecx 00406552 5D pop ebp 00406553 C3 retn 00406554 ;
00406554 00406554 loc_406554: ; DATA XREF: .data:00415318o 00406554 55 ; .data:00415480o 00406554 push ebp 00406555 8B EC mov ebp, esp 00406557 51 push ecx 00406558 53 push ebx 00406559 8B 5D 08 mov ebx, [ebp+8] 0040655C C7 45 FC 03 00 00 00 mov dword ptr [ebp-4],3 ;3=PREVIEW mode 00406563 8D 45 FC lea eax, [ebp-4]; we're gonna jump ; there later 00406566 50 push eax 00406567 53 push ebx 00406568 E8 39 00 00 00 call sub_4065A6 0040656D 83 C4 08 add esp, 8 00406570 80 7B 4B 00 cmp byte ptr [ebx+4Bh], 0 00406574 74 08 jz short loc_40657E 00406576 FF 73 19 push dword ptr [ebx+19h] 00406579 E8 48 E6 00 00 call j_SetCursor 0040657E 0040657E loc_40657E: ; CODE XREF: .text:00406574j 0040657E 5B pop ebx 0040657F 59 pop ecx 00406580 5D pop ebp 00406581 C3 retn 00406582 ;
00406582 00406582 loc_406582: ; DATA XREF: .data:004152E8o 00406582 55 ; .data:00415498o 00406582 push ebp 00406583 8B EC mov ebp, esp 00406585 53 push ebx 00406586 8B 5D 08 mov ebx, [ebp+8] 00406589 53 push ebx 0040658A E8 FD FC FF FF call sub_40628C 0040658F 59 pop ecx 00406590 A1 F0 B9 41 00 mov eax, dword_41B9F0 00406595 8B 10 mov edx, [eax] 00406597 FF 72 0C push dword ptr [edx+0Ch] 0040659A 53 push ebx 0040659B E8 CA B9 FF FF call sub_401F6A; EXCLUDE mode doesn't ; work; 004065A0 83 C4 08 add esp, 8 004065A3 5B pop ebx 004065A4 5D pop ebp 004065A5 C3 retn 004065A6 What you can observe here are some strikingly similar pieces of code for the different "modes" you can work MagicMouse in. The first four sections are identical, except for the value that is being moved to [ebp-4]. Further inspection shows that it's 0 for the normal mode, 2 for move, 4 for send, and 3 for preview. It all comes together in location [41b9e4] which holds the code for the mode of operation. Obviously, the value that is conspicuously missing here is 1. And our last, failing, exclude mode section is the only one that has a different code -- leads us to the demo limit screen instead of the desired mode of operation. So I guess it couldn't hurt to try the code of the other sections with our missing value, especially since there are data references to the exclude mode. The only operational problem being that there isn't enough space in our section for the length of code in the other sections. So we'll have to be a little creative, but that should be worth it. We could, for instance, patch the first part of the code, up to the decisive line "mov dword ptr [ebp-4], 1" in our original location, and then jump to one of the other locations to finish the rest of the code which is identical in all sections. 00406582 ; activated EXCLUDE section 00406582 loc_406582: ; DATA XREF: .data:004152E8o 00406582 55 ; .data:00415498o 00406582 push ebp 00406583 8B EC mov ebp, esp 00406585 51 push ecx 00406586 53 push ebx 00406587 8B 5D 08 mov ebx, [ebp+8] 0040658A C7 45 FC 01 00 00 00 mov dword ptr [ebp-4], 1; "magic" value 00406591 EB D0 jmp short loc_406563; jmp to Preview-- 00406593 ; continue there
00406593 90 nop 00406594 90 nop And, what can I tell you, it works :) The program creates a file named "exclude.lst" in which it gathers all the windows you want to exclude from your operations. There are two restrictions remaining: the opportunity to specifically exclude hidden windows and system windows. I doubt that the code for these options is in the program. If it is, I couldn't locate it. But, of course, you can achieve the same effect with your exclude list. And you'll probably want to use the Customiser program anyway, instead of Magic Mouse, since its functionality is extended. And we're only in it for the reversing anyway.

redhomepage red links red anonymity +ORC redstudents' essays redacademy database redbots wars
redantismut redtools redcocktails redjavascript wars redsearch_forms redmail_reverser
redIs reverse engineering illegal?