²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²
    ²²    ____                     __       __           ²²ßÛ
    ²²   /  _/_ _  __ _  ___  ____/ /____ _/ /           ²² ÛßÛ
    ²²  _/ //  ' \/  ' \/ _ \/ __/ __/ _ `/ /            ²² Û Û
    ²² /___/_/_/_/_/_/_/\___/_/  \__/\_,_/_/             ²² Û Û
    ²²   ____                          __          __    ²² Û Û     
    ²²  / __ \___ ___ _______ ___  ___/ /__ ____  / /____²² Û Û 
    ²² / /_/ / -_|_-</ __/ -_) _ \/ _  / _ `/ _ \/ __(_-<²² Û Û
    ²²/_____/\__/___/\__/\__/_//_/\_,_/\_,_/_//_/\__/___/²² Û Û
    ²²                                                   ²² Û Û
    ²²      Web: http://www.ImmortalDescendants.org      ²² Û Û
    ²²      Author: Lord Soth                            ²² Û Û
    ²²      Date:  06/08/2000   (mm/dd/yy)               ²² Û Û
    ²²      Topic: VB reversing, SmartCheck  	         ²² Û Û
    ²²      Level: Beginner/Intermediate                 ²² Û Û
    ²²                                                   ²² Û Û
    ²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²² Û Û
      ÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛ Û
        ÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛ

============================================================================
INTRODUCTION
============================================================================
Hello, folks. Yet another target is being used by us crackers to demonstrate
how easily some reversing feats are accomplished :) OK, in this short essay 
I'll try to explain some basic stuff on how to reverse parts of VB programs. 
It seems many newbies are often very confused when it comes to VB. The main 
reason is probably because VB code is a lot more bloated than normal C/C++ 
code. Delphi also has the "feature" of bloatness as well. This bloatness is 
not only meant to save the programmer many things, it is also meant to make 
our lives harder, by making layer after layer of programs' and engines' 
code. 

An example for this is VB. Visual Basic is not only a comfortable
development environment that beginning programmers find easy to learn and 
use, it is also a sort of an engine. This engine for programs goes a long 
way to save work for the programmer, leaving the "boring" stuff to the 
engine. This is done using a very big DLL with many functions and services, 
and also thousands of lines of code added to the program. This in effect 
makes our cracking lives harder.

The more code there is, it is supposedly harder to reverse. In effect, 
sometimes this is true, but usually only for newbies. Experienced
crackers are well.. experienced enough to know how to look for the 
important things in a program, and cut straight to the protection code.
However, those without an abundance of experience are overwhelmed by the VB 
code. Not only its size, but also its form. Things are done very 
differently in VB. For this end, Numega wrote SmartCheck.

OK, maybe this is somewhat incorrect. They didn't write SmartCheck for us
crackers, they just wrote it to help speed the development and debugging of
VB applications. This is done using, among other things, a sophisticated 
type of logging that SC does. This logging and reporting is what helps us 
understand what the program is doing. In effect, that's reversing, isn't 
it?

What disassemblers such as W32dasm, and IDA pro are doing for us, is giving 
us some sort of a sense for the bigger picture. The details are unimportant, 
and can usually be fished out easily with a debugger such as our beloved SI.
However, understanding of the great scheme of things is so important in this
"line of work", and since VB is so bloated and different from normal code, 
then SmartCheck (SC) is our last best refuge.

So, in this essay I'll show, very easily I might add, how incredibly easy 
it is to locate important pieces of code of an application.
Without too much blabbering, lets get down to it then!!

============================================================================
TOOLS NEEDED
============================================================================
SmartCheck (of course, that's the whole point!)
SoftIce (ver 3.2x will do)
W32dasm (or IDA if you feel you need to, I think its a waste of time for 
this protection)
HexWorkShop (my fav. hex editor, just love it!! :)

============================================================================
THE TARGET - CONVERT VERSION 1.5
============================================================================
This is a small program, and I got it from a friend of mine, so I have no 
idea how to get it from the Internet. My bet is a search might find it, 
eheh :)

============================================================================
ANALYZING THE PROTECTION
============================================================================
Well, after installing the app, and running it, we get the pleasure of 
seeing a nag screen. The nag screen says some unimportant stuff, and has a 
timer that is counting down from 10 to 0 (in seconds of course).

Another thing to see is that the OK button is grayed, so it can't be 
clicked. Yep, you guessed it, when the counter reaches 0, the OK button will 
probably be enabled again. This is nice. In usual programs, this shouldn't 
be too much trouble to take care of.

Another thing to look at is that when exiting the application, the same nag
appears. In fact, this is the About dialog box for this program, however, if
you were to click the About button in the main window app, which is opened
by double-clicking the tray icon btw, you'll see that the About box is fully
functional, with no timer. This means that the program is using the About box 
as a nag screen in startup and exit, but with some changes. Several ways to 
crack this comes to mind. One can manipulate the timer, one can enable the OK 
button, and one can even remove the nag altogether (the best option).

Now, let me clarify something. this is the first time I've used SC to 
actually crack a program. I haven't cracked MANY VB apps, but I cracked a 
few, without the use of SC. What I usually did is to find some imports from 
the DLL that are incriminating, that is, somehow related to the type of 
protection. Other methods are breaking on windows API functions that you 
know are used by the VB DLL, hoping somehow to return back to the calling 
program.

Other methods are available of course. One such approach is to look for
interesting string refs using W32dasm. I must emphasize that if you don't 
have the patch for W32Dasm that enables you to view the string refs, you 
might as well forget this method. Get the patch, it can shed some light 
into the app :)

What we'll do here is to mainly use SmartCheck to locate where events 
happen inside the VB program. We'll need a disassembly as well just in order 
to verify that the code locations we enter are actually valid, otherwise 
we'll waste our time trying to break on them with SI. We won't need to use SI 
a lot, but we'll go in with it in order to see if the code locations we get 
from SC are actually related to the protection.

Ok, now, disassemble the program using W32Dasm like the good boy/girl that 
you are and save the project file. Open it in SC and run the program. When 
the nag ends, exit the program, and exit it also on the tray, cause its one 
of those annoying programs that wanna stay minimized forever in your 
system :)

After this is done, have a look at the report generated by SC. You can also
save the report/log into a SCE file. This is handy, you won't need to run 
the app again. I suggest doing it, unless circumstances show that it would 
not be a good idea.

Lets have a look then. The first part we see is called Initialize, and it 
has a plus sign next to it, as it can be expanded. Lets expand it and see 
what's going on. A few lines down into this part, we see something called 
"Form1_Load". This is interesting. Form1 is usually the main Form used by 
VB apps. This is somehow equivalent to the main window in a normal program. 
In design time, VB programmers create the forms, and controls inside them, 
or at least that's what I was told :)

So, its safe to assume in that part we can find interesting stuff about 
the creation of the windows and controls inside the program. Lets have a 
look inside it, and peek into it. Click the plus sign next to it to reveal 
some nice looking wonders. These are all actions performed by the program, 
and were 'recorded' by SC.

Now, scroll down, looking for anything interesting. I did this search only
because I needed to. No special thought process lead me to search this 
place, it was just an attempt to locate some important stuff. Sure enough, 
after quite a few lines, you get to another interesting part, now called: 
"frmAbout (Form) Created". What does it mean?

Well, it probably means that another child form has been created, and 
well, look at it's name, frmAbout. This is the hint we need. This seems 
like the place the program is creating the About dialog. Look at the right 
pane, and you'll see where in the program this event happened, along with 
any parameters it might effect. In effect, creating forms does not require 
changes to parameters, unlike conversion from a number to a string or 
something similar.

When looking at the code location, I saw this : MSVBVM50.DLL!00028FAD.
Below was the ID of the form. Well now, this doesn't look like a good 
thing, or rather it doesn't look like a useful thing in our eyes. The 
creation is done inside the VB DLL, therefore it's not interesting. We need 
code specific to the program.

A line below we see this : "frmAbout_Load". This tells us that the designed 
form is loaded into memory, prepared to go. What does LOAD mean? Well, if 
you're interested, click the plus sign to see what goes on in there. What 
you'll see is some strings and stuff handled around. I think you can
understand that this part initializes most of the controls (yes, even static
text controls) inside the About box. Notice however that there is no 
reference here to the OK button or the timer used. This probably is NOT what 
we need to deal with then.

Collapse the frmAbout_Load part click the minus sign, and lets move on. 
Looking at the next few lines, we see some interesting stuff indeed. An 
integer with a value of 10 is converted into a string (VB strings are wide 
char btw), and then that string is used to initialize a label (in normal 
programming concepts, this is referred to as a static text control).

Right after this, we see another interesting thing: 
cmdOK.Enabled <-- False (Boolean)

What does that mean? Well, most likely this is the disabling of the OK 
button in the About box. The type of parameter is a boolean false, which is 
passed to what is probably a method (class function) called Enabled. Not 
sure about this as I never programmed in VB, but it seems that way.

Now, we have the integer 10, which is probably related to the 10 seconds 
counter and we have the OK command disabled, this alone is interesting 
enough to warrant diving into SI and looking for some stuff to trash.
Before we do this though, I suggest using W32Dasm to go to these code 
offsets.

We find the integer is initialized at CONVERT.EXE!0003C845. Well, this can 
mean more than one code location. As you know, disassemblers often refer to 
code locations as offsets from the beginning of the EXE file in question, so 
it's safe to assume that this is the case. I found it to be the case only on 
rare occasions. In order to find such a code location in the disassembly, 
we'll need to go the location, and then move down or up untill we see in the 
bottom of the W32Dasm screen that we're exactly at the offset we got from SC, 
but in the EXE file. As I said, this usually is not the case.

What IS usually the case, is that SC reports events as the DLL is being 
called into. It logs the address of the instruction that invoked the service, 
and it removes from it the ImageBase for the code section. Don't ask me why, 
but that's how it is. Probably so you have an offset from the beginning of 
the code, instead of having an absolute address. This is good because on rare 
occasions, code blocks are being transferred to other parts in memory.

Ok, great, we saw that the offset for the integer loading with 10 is 
0003C845. Let's add the ImageBase, which I found to be 400000h (not 401000 as 
most will guess, or the program reports). Even if the IBase was at 401000h, 
the code location in question is an offset from the application instance, 
which is 400000h (normally). I won't go into any detail about the hInstance, 
but it should be familiar to any windows programmer.

Now, adding the two I got 0043C845h. Now let's load the program with the 
symbol loader, and SI pops, we're at the entry point. Now lets BP on that 
location, either using G, or using BPX:

bpx 43c845

Now hit F5 to let it run, and we've stopped at this location :

* Reference To: MSVBVM50.__vbaFreeObj, Ord:0000h
                                  |
:0043C83E E8DB53FCFF              Call 00401C1E
:0043C843 6A0A                    push 0000000A

* Reference To: MSVBVM50.__vbaStrI2, Ord:0000h
                                  |
:0043C845 E89253FCFF              Call 00401BDC		;<<< we're HERE!!!
:0043C84A 8945E0                  mov dword ptr [ebp-20], eax
:0043C84D A110314400              mov eax, dword ptr [00443110]
:0043C852 85C0                    test eax, eax

Now look at what's going on. The function __vbaStrI2 is being called here.
This is also the exact location reported in SC that we found. Now, see what 
is being pushed ?? the parameter is in fact 0Ah, which is 10. Then the CALL 
is executed, and from its name I bet it takes an integer and converts it 
into a VB string (wide char of course).

Confirm this by stepping over the funtion call, then EAX will contain a 
pointer to the new string. This is common in VB. The return value is often 
a pointer to the "result" of the operation being done. To verify this, 
display the memory contents at the address pointed to by EAX: d eax

In the data window you'll see 1.0.. and some other stuff next to it. This 
is a wide char string. It stands for 10. Now we know where the integer gets 
converted into a string. Now, in an app that respects its protection, this 
would only be the text displayed, not the REAL counter that is probably 
initialized earlier and in a different location. But, wonders never cease, 
and we should check the option of this being the REAL counter. Rerun the 
program and break in the same place, now, you see that the push was already 
executed, so display the contents in ESP: d esp, then edit the 0a into 00.
Or you could just change the BPX to 43C843, to catch it before pushing the 
10 to the stack.

Once you change it, continue execution (F5), and woa!!! the counter is 
initialized with 0 !!! WOW we think, this guy actually used the label's 
integer as a counter. How it's done is usually not important, but if you're 
interested, a few lines down you can find this: frmAbout.Show. This just 
looks to me as calling of the Show method, which will probably make the
form visible.

Now, inside the Show event, we find many timer events. Open a few of them, 
poke around and you'll probably get to the same conclusion I have, which is 
the guy that coded this app used the label's text (the counter text, the 
number itself) in order to update it's value. This means that if the counter 
shows 10, it'll convert the "10" string into a decimal 10, decrease one, and 
shove it back into the About box. That's a pretty lame way of doing it, but 
we're not gonna get mad at this guy, cause we're nice :)

OK, close the Show event down, and lets move on. We managed to make the 
counter start at 0, which will cause the OK button to almost immediately be 
enabled, thus allowing us to continue past the nag. However, we also found 
out where the button is initially diabled, which is not too far away if I 
recall. It was at offset 0003C8D9, which is in SI's language, equal to 
0043C8D9. So put a bpx there, and lets move on. I pasted the relevant lines 
of code in here:

:0043C8D1 8BF0                    mov esi, eax
:0043C8D3 6A00                    push 00000000
:0043C8D5 56                      push esi
:0043C8D6 8B06                    mov eax, dword ptr [esi]
:0043C8D8 FF908C000000            call dword ptr [eax+0000008C]
:0043C8DE 85C0                    test eax, eax
:0043C8E0 7D11                    jge 0043C8F3
:0043C8E2 688C000000              push 0000008C
:0043C8E7 68BC984100              push 004198BC
:0043C8EC 56                      push esi
:0043C8ED 50                      push eax

* Reference To: MSVBVM50.__vbaHresultCheckObj, Ord:0000h
                                  |
:0043C8EE E8A353FCFF              Call 00401C96

One thing to notice here is that the PUSH at address 43C8D3 is actually 
viewed in SI as: PUSH 00, which fits the opcode 6A00 that comes along with 
it. Now, how is this important? Well, if you've seen boolean params passed 
on the stack, you'll know that FALSE is 00, and TRUE is 01. So my bet is 
that the PUSH 00 is the FALSE parameter passed to the Enable method of the 
form object. Again you can change the passed param on the stack as I 
described earlier, or you could rerun the program, putting a new BPX at 
address 0043C8D3.

Another thing to notice, and this is very important, is that SC reported 
this event occured at address 0043C8D9, which *SHOULD* be the function call 
that generated the event, however, as you can see, the actual address of the 
CALL instruction is at 0043C8D8, so SC missed it by a byte. This is why we 
need a disassembly. With it, we can make sure where exactly to put our BP in 
SI so that we actually break, and not just gaze at the screen when program 
execution continues without popping our debugger.

OK, so now try to run the program again, but at 0043C8D3, assemble a new 
instruction, either by being on it and typing 'a', or whatever. As you 
guessed by now, this new instruction is going to be: push 01.

Now continue execution and you'll see the OK button enabled from the start, 
and even if you neglected to change the counter to 0 again, this will let 
you continue ignoring the counter.

So we found another nice way to crack this app, we don't even need to bother 
with the timer, we can just enable a button, which is a 1 byte patch!!! 
HOW COOL!!! But we are aiming for perfection, if we can, so we will 
typically want a nag to be completely REMOVED (or killed as I like to say!).
After all, nag screens were MEANT to be killed!!! hehe

Let's try to find out where exactly the program is popping this nag up. My 
first guess is that the Show method is what is used to make the About box 
come to life. I must admit, at first I did not think of this. I wanted it 
to NOT even create the About form, but then I was told by Golem that in 
order to invoke the form, a method has to be called, and its usually easy 
to disable these calls. So I went in again, stepping over calls from my last 
known code location, which was the preparation of the OK button. After a 
few dozen lines of code, I've stumbled upon this:

* Reference To: MSVBVM50.__vbaNew2, Ord:0000h
                                  |
:0043C958 E8FD52FCFF              Call 00401C5A

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0043C954(C)
|
:0043C95D 8B1D10314400            mov ebx, dword ptr [00443110]
:0043C963 83EC10                  sub esp, 00000010
:0043C966 8D75B8                  lea esi, dword ptr [ebp-48]
:0043C969 8BFC                    mov edi, esp
:0043C96B 8B03                    mov eax, dword ptr [ebx]
:0043C96D C745C004000280          mov [ebp-40], 80020004
:0043C974 C745B80A000000          mov [ebp-48], 0000000A
:0043C97B 83EC10                  sub esp, 00000010
:0043C97E A5                      movsd
:0043C97F A5                      movsd
:0043C980 A5                      movsd
:0043C981 A5                      movsd
:0043C982 8D75C8                  lea esi, dword ptr [ebp-38]
:0043C985 8BFC                    mov edi, esp
:0043C987 C745D001000000          mov [ebp-30], 00000001
:0043C98E C745C802000000          mov [ebp-38], 00000002
:0043C995 A5                      movsd
:0043C996 A5                      movsd
:0043C997 A5                      movsd
:0043C998 53                      push ebx
:0043C999 A5                      movsd
:0043C99A FF90B0020000            call dword ptr [eax+000002B0]
:0043C9A0 85C0                    test eax, eax
:0043C9A2 7D11                    jge 0043C9B5
:0043C9A4 68B0020000              push 000002B0

There is a reason why this part I pasted is so big. When stepping, I noticed 
it continually checks the object in question, and if somehow it's invalid, 
it calls the __vbaNew2 function. This is probably a safe check mechanism 
either put there by VB, or by the application. My bet goes to the VB engine, 
that probably is doing endless checks to see if everything is valid all the 
time. Most of these checks are redundant.

Now, if the object is created and is OK, we jump to address 0043C95D, which
in turn puts the handle of the object (or what I assume to be the handle of
the object), into EBX. The stack is then used to allocate some more space,
and some stuff are being done, and eventually we get to 0043C99A. I stepped 
through this function call, and saw the About box come to life on my screen. 
I waited patiently for the counter to finish, to see if I'm returning to SI 
after it's destroyed, and indeed I returned into SI and was put right after 
that function call. It was obvious to me what I needed to do in order to 
kill this nag. I needed to jump over the call. This also means jumping over 
all the parameters and stack space allocated for this call.

We'll need to jump over the SUB ESP,00000010h then, at address 43C963h, and
all of the other code that lies afterwards. This can easily be done like 
this: a 43c95d

Now I'm entering the following instructions:

XOR EAX,EAX
XOR EAX,EAX
JMP 43C9A0

The XOR EAX, EAX will zero out eax, and I need it to be 0 to signal the 
app so the right condition in the JGE at 43C9A2 will be met. This will 
ensure that the result for the form object is not checked as you can see a 
few lines down a call to __vbaHresultCheckObj function. This probably checks 
the result of an operation done on an object. We want it to believe that the 
operation is the closing of the About box, after the timer has elapsed.

Modifying these bytes in memory gives me the opcodes I need to use in my
patch. Those are a totoal of 6 bytes in memory, and it was designed to be
this way because the instruction which I'm overwriting at 0043C95D is 6
bytes long.

Now, back in W32Dasm, go to the code location 43c95d, and you'll see at the
bottom that the offset in the EXE file for this instruction is 3BD5Dh. Open 
the EXE in HexWorkShop and edit the bytes from whatever they were to 
33,C0,33,C0,EB,3D (if I'm not mistaken).

Close stuff and rerun the program, and you'll see it works without the nag
both in startup and in shutdown. Now click the About button in the main
application window and you'll see the NORMAL About box is still working
properly :)

OK, now there is another way to reach the even at 0043C99A that we found.
In SC, you can easily see that the Show method is at 3C99Bh. Looks 
somewhat suspicious?? They are almost identical!! This means that SC missed 
the CALL by a byte, but that is exactly where we need to break with SI to 
enable the About box, and thus if I was paying more attention, I would have 
seen this without stepping through a few dozen lines of code. The patching is 
left for you I bet, from here it's trivial, like most math professors say :)

============================================================================
CLOSING WORDS - SUMMARY
============================================================================
Well, I hope this kinda short tutorial showed you how EASY it is to find 
just the right important stuff inside a VB app to quickly crack it. Now I'm 
not saying that ALL VB apps can be cracked so easily, but I am saying that 
SmartCheck goes a LOOOOONNNGGGG way of making our work easier. It just makes 
all the real work of the program visible to our eyes in a comfortable list 
(almost) for us to search in. I bet it's actually a pretty good VB debugging 
tool when coupled with VB and the program's source code :)

Once again, the boys at Numega have proven they know what it takes to debug,
reverse and analyze running stuff, even if we don't have the sources ready
for our inspection. The only people that actually managed to come close to 
this IMO are the boys from DataRescue with their mighty IDA disassembler.

In any case, I hope this tutorial helped you understand SOME of what is 
going on inside VB applications, and make the boogy man not so BOOGY, or 
evil :)

This is it, cya all next time!

For comments, contact me at : 

lordsoth8@hotmail.com
LordSoth@ImmortalDescendants.org

or via ICQ : # 5178515

Happy cracking!

============================================================================
GREETINGS
============================================================================
Greetings go to ALL the Immortal Descendants members, all the +HCU members, 
the +Sandman (I owe him special thanks , since because of him I am what I am 
today), The Snake (my dear friend), The Hobgoblin (just love that guy :), 
Lazarus (love him too, loved the Laz_Calc.. hehe), and Jeff of course, all 
those that visit the Newbies Forum, +Fravia, +Frog's print, +tsehp, DQ, 
_mammon, and all those gods of knowledge that roam the cyberspace and 
occasionally rear their heads either at +fravia's forum or the newbies 
forum... Of course, Ghirrizibo (not sure how to type it) for his wonderful 
IceDump util, and many other I probably forgot, if I did, I apologize!!