Software Protection and Preventing Memory Modifications

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
StarHawk
User
User
Posts: 55
Joined: Sun Nov 02, 2003 7:27 am

Software Protection and Preventing Memory Modifications

Post by StarHawk »

In C++, memory safe guarding methods of programming are possible. For example, a common technique used by crackers is modify the memory in another running process after it has been loaded. For example, many programs may store in memory the number of days left remaining in a trial, the number of executions remain, or simply a value indicating if the software is running in trial / non-trial mode. By changing this value in memory after the process has been started, the cracker may be able to "upgrade" to a non-trial version. This technique is also very popular as used to cheat in video games, because it can allow a user to change their health points, ammo, etc.

How is attack preformed?

The typical technical used is to create small EXE file which:

1. Runs your protected application
2. Waits until the application reaches a specific point (or a certain amount of time has passed).
3. Locates a specific memory location where your license information is stored. Typically this is a fixed address like 0x401050
4. Writes to the license information location to change it

Can I stop another process from changing my memory?

Because it is impossible to prevent another process from reading or writing your memory, you should make your sensitive data hard to find, and also difficult to modify. Thinstall does not change the location of where your program data is stored in memory, so you will need to take your own steps to protect against loader based attacks.

The following C++ example demonstrates a simple program that has sensitive license information we wish to protect:

BAD - Easy to crack programming technique

struct license_infomation
{
enum { REGISTERED, TRIAL_MODE } current_mode;
int trial_days_left;
};

license_infomation license_info;

void main()
{
get_license_info(&license_info); // this function is written by you....

while (!quit())
{
if (current_mode==license_information::REGISTERED)
do_registered_features();
else
do_trial_features();
}

}

Why this is bad: Because this program stores the license information at the same location every time it runs, this information is easy to locate by comparing the memory contents of your program before and after the registration key has been entered. Also, the values stored in memory will always be consistent (0 or 1 for current_mode), and the values are not checked for changes by the program.

GOOD - Difficult to crack using loader technique

#include "secure_memory.hpp" // The bulk of the work is preformed in secure_memory.cpp

struct license_infomation
{
enum { REGISTERED, TRIAL_MODE } current_mode;
int trial_days_left;
};


void main()
{
license_infomation tmp;
get_license_info(&tmp); // this function is written by you....
store_secure_data(&tmp, sizeof(tmp);

while (!quit())
{
license_infomation secure_info;
get_secure_data(&secure_info);
if (secure_info.current_mode==license_information::REGISTERED)
do_registered_features();
else
do_trial_features();
}

}

Why this is good: This version of the same program stores license information in memory at a random location and uses encryption, checksums, and multiple data copies to prevent an outside program from tampering with the data.

The bulk of the work for the above example is contained in secure_memory.cpp. Let's dig into the details of this file.

First, this code makes sure memory is always allocated in a different location by using the Process ID (different each time your program is run), the System Time in milliseconds, and a separate counter. The code allocates a buffer of the size request plus an additional padding size. The padding size is random for each allocation, and the data is stored immediately after the padding:

void *allocate_at_random_location(int size)
{
SYSTEMTIME t;
GetSystemTime(&t);
unsigned int pad_size=t.wMilliseconds + GetCurrentProcessId() * key_counter;
key_counter++;
pad_size=(pad_size & 0xfff)+4;
void *v=malloc(size + pad_size);
void *ret=(char *)v+pad_size;
*((void **)ret-1)=v;
return ret;
}


The supplied code also uses the checksum algorithm to verify data has not been tampered with before it is used. The checksum algorithm is very simple to implement and very fast to execute.

unsigned int calc_checksum(void *data, int size)
{
unsigned char a=0,b=0,c=0,d=0;
for (int i=0; i<size; i++)
{
a+=*((unsigned char *)data+i);
b+=a;
c+=b;
d+=c;
}
return a | (b<<8) | (c<<16) | (d<<24);
}


We also encrypt the data in memory using a simple byte-by-byte xor. The values being xor'ed against the data will also be different each time the program runs, this mean each time your program is run the data in memory will look completely different (and be located at different memory addresses).

void xor_block(void *src, void *dst, int size, encryption_key &key)
{
for (int i=0; i<size; i++)
((unsigned char *)dst) = ((unsigned char *)src) ^ (key.key_data[i % (sizeof(key.key_data))] + i);
}

Secure_memory.cpp also stores to copies of your data and makes sure both versions decrypt and have the same checksum value. If the checksum values do not match, it will cause your program to crash in a subtle way:

// Eventually the program should crash or have a stack overflow
// We avoid showing a dialog box or quiting immediately to make it hard to
// locate this code
inline void subtle_crash_program()
{
IMAGE_DOS_HEADER *dh=(IMAGE_DOS_HEADER *)GetModuleHandle(0);
IMAGE_OPTIONAL_HEADER *oh=(IMAGE_OPTIONAL_HEADER *)((char *)dh+dh->e_lfanew+4+sizeof(IMAGE_FILE_HEADER));
unsigned long entry=oh->AddressOfEntryPoint + (unsigned int)dh;
_asm jmp [entry]
}

The XORing is not a problem, but it seems that the main feature request I would like to see in Purebasic is the ability to location certain sections/functions of code at random memory locations. A PureBasic equivalent of declaring a function like this in C++:

void *allocate_at_random_location(int size)
{
SYSTEMTIME t;
GetSystemTime(&t);
unsigned int pad_size=t.wMilliseconds + GetCurrentProcessId() * key_counter;
key_counter++;
pad_size=(pad_size & 0xfff)+4;
void *v=malloc(size + pad_size);
void *ret=(char *)v+pad_size;
*((void **)ret-1)=v;
return ret;
}

An equivalent in PureBasic using Procedures, maybe like this:

Procedure.l Maximum(nb1.l, nb2.l) * randomlocation
If nb1>nb2
Result.l = nb1
Else
Result = nb2
Endif
ProcedureReturn Result
EndProcedure

I know some of you are thinking about responding with, well you can do this using bank/memory allocations and peek and pokes etc... But I'm not talking about a hack n slash double back flip work around. I'm talking about a professional solution that anyone can implement simply by adding "* randomlocation" at the end of a line in which they declare a procedure.

Source: Jonathan Clark. Security Expert. Secure White Paper: How to prevent runtime memory modifications of your sensitive information. July 2, 2004. Thinstall.com
User avatar
GedB
Addict
Addict
Posts: 1313
Joined: Fri May 16, 2003 3:47 pm
Location: England
Contact:

Post by GedB »

Isn't there protection to ensure that one process can overwrite the code of another process, to prevent malicous programs overwriting others with there own code?

I'm sure this is so, and if it is aren't you better off storing the data actually inside your code?

Code: Select all

Procedure value()
  DataSection
  value_in_code:
  Data.l 0
  EndDataSection
  
  ProcedureReturn PeekL(?value_in_code)
EndProcedure

Procedure SetValue(value)
  PokeL(?value_in_code, value)
EndProcedure

Debug value()
SetValue(5)
Debug value()
SetValue(10)
Debug value()
freak
PureBasic Team
PureBasic Team
Posts: 5940
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Post by freak »

The code memory section of a program is readonly for everybody, so even the
program itself can't change it.

All PB datasections (no matter were you place them) end up in one big
data section which (being no code section) is readable and writeable.

Timo
quidquid Latine dictum sit altum videtur
jack
Addict
Addict
Posts: 1358
Joined: Fri Apr 25, 2003 11:10 pm

Post by jack »

freak
PureBasic Team
PureBasic Team
Posts: 5940
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Post by freak »

Well, Rings is the expert. I'm not :D
(I just trusted MS when they say that code is readonly)

It is true that a DataSection is not located in the code section though.
Just look at the code by GedB with /COMMENTED and you'll see.

Timo
quidquid Latine dictum sit altum videtur
User avatar
GedB
Addict
Addict
Posts: 1313
Joined: Fri May 16, 2003 3:47 pm
Location: England
Contact:

Post by GedB »

:cry:

Oh well, it was a nice idea.
StarHawk
User
User
Posts: 55
Joined: Sun Nov 02, 2003 7:27 am

Hmmm...

Post by StarHawk »

When a hacker has a tool like SoftIce, and knows where to set a memory break, there's pretty much nothing you can do to stop him. For educational purposes, I hacked a security scheme that protected over $5,000 worth of software in 2 days using SoftIce.

You can put something through the ringer, XOR, bitch slap (bit shift) it, on and on, but if you set the memory break right while the program is loaded and running in memory, and view the EAX or other registers (and there's not that many of them so it's really easy), you can catch either the key, license, or password everytime.

So a main process in making this more difficult for the hacker, as Security Expert/Lecturer Jonathan Clark accurately writes, is to have the memory address change that stores your protection routine section of code. This way it's hard to set a break point on a certain memory address. Anyone who has used SoftIce or other similar programs knows that if you can't place a break point in the correct spot, or know the memory address range of the code you are hacking, it's extremely difficult to search through every memory address in memory viewing lines and lines of ASM and not knowing if the XOR statement you are looking at is from Windows, from the program that is running, and from the precise section that is comparing a license key. It is so time consuming to search through an entire computers memory in ASM statements and viewing the registers after each ASM command is executed, looking for what you think is the author's protection scheme, that most hackers say screw it, and move on to the next author's software program to hack that is much easier than your own.

A command like C++:
*allocate_at_random_location(int size)

such as:

Procedure.l Maximum(nb1.l, nb2.l) *allocate_at_random_location(int size)
If nb1>nb2
Result.l = nb1
Else
Result = nb2
Endif
ProcedureReturn Result
EndProcedure

Of course the .exe would need to be slightly larger to contain the code that put the procedure at a random location each time it was executed on a clients machine. But that is no different than an .exe being slightly larger to contain the code that displays a .jpg, the UseJPG command.

Plus, it brings Purebasic a little closer to having the low level power of C++ which gives it further advantage over the competition.

Finally, at the opening of the 21st Century and the events of 911, and rogue terror cells operating in all major countries around the world, the trend for security will continue to rise. This has been evidenced in Security related companies, computer software and hardware, imaging, survellience, etc.... rising strongly on both domestic and international markets. It is also evidenced in products like Jonathan Clark's Thinstall, that have soared in popularity and sales since the turn of the century.

This trend will continue and so "security related" commands in programming languages will continue to increase. I would venture to say that security related commands will continue to increase in major programming languages over the next several years as programmers desire greater security features to offer their clients.

While an *allocate_at_random_location(int size) seems a little extravegant and strange now, I suspect it, and security related commands like it, will become common programming techniques/tasks in the years ahead.
Codemonger
Enthusiast
Enthusiast
Posts: 384
Joined: Sat May 24, 2003 8:02 pm
Location: Canada
Contact:

Post by Codemonger »

it's extremely difficult to search through every memory address in memory viewing lines and lines of ASM and not knowing if the XOR statement you are looking at is from Windows, f
That's the problem extremely difficult doesn't mean impossible, it just means that its a little harder. And if Fred is too internally implement a security system such as the one you are suggested (which is good no doubt), wouldn't that make it easier for someone to crack All purebasic programs that use the same security system. An 'educational' hacker such as yourself maybe ? Your ideas seem too sure, and i think would give PB users that don't know any better, a false sense of having a secure program.
Finally, at the opening of the 21st Century and the events of 911, and rogue terror cells operating in all major countries around the world, the trend for security will continue to rise.


This seems more like a capitalist propaganda marketing scheme as opposed to a really solid 3rd party software protection implementation. No offense.

My suggestion would be to create a third party program to handle this situation as it can progress and develop and is a big job.
<br>"I deliver Justice, not Mercy"

    - Codemonger, 2004 A.D.
MadMax
Enthusiast
Enthusiast
Posts: 237
Joined: Mon Oct 06, 2003 11:56 am

Post by MadMax »

Can't see the relation between hacking and terrorism, surely if terrorist need some software made with PB or other, they could just buy it if they can't hack it.
User avatar
NoahPhense
Addict
Addict
Posts: 1999
Joined: Thu Oct 16, 2003 8:30 pm
Location: North Florida

...

Post by NoahPhense »

MadMax wrote:Can't see the relation between hacking and terrorism, surely if terrorist need some software made with PB or other, they could just buy it if they can't hack it.
shh dont give away our secrets..

- np
oldefoxx
Enthusiast
Enthusiast
Posts: 532
Joined: Fri Jul 25, 2003 11:24 pm

Post by oldefoxx »

Not playing the hacker game myself, I may seem to be a bit dense
here. The fact is that every process is allocated a range of memory
locations consistent with its stated needs, and Windows strives to
limit your ability to go outside that range as a means of protecting
other programs from what your program is doing. A sure way to
trigger a GPF is to invade another program's memory space and
have Windows recognize that you did it.

Yes, you can tamper with a program's license, or you can simply
nullify the results of testing to see if a license is present or if it
matches. Instead of a JE (jump if equal), you could insert a JNE
(jump if not equal), and force the program to branch as though the
match were successful.

One solution is to make the program repeat the same test a number
of times, so that each branch would have to be found and altered
before you could successfully defeat the protection.

The main thing though, is to make the program unreadable, which
often means encrypting it on disk. The question then is, how do you
load an encrypted program and have it work correctly? Obviously
by having another program or a portion of the original program that
would do the unencrypting for you automatically. The license then
becomes the key to unencrypting the program.

Again, the problem is, how do I keep another program from copying the
loaded, unencrypted version in memory from being dumped to disk? The
answer might be to create two or more segments of one program
that all have to be loaded into memory at the same time, and each
segment hides the fact that it has to unencrypt the next segment in
memory before it passes control to it, and each segment has to
re-encrypt the previous segment when it is called, and all this while
keeping Windows from throwing a GPF.

The solution for bypassing Windows protection may involve stealing
control of the system from windows proper - you can modify or
replace key portions of the system files for instance, or you may be
able to use enough indirection and redirection with pointers to get
where you want to go, or you may be able to unmask operations that
windows has to perform and simply make those calls yourself with your
own set of parameters - or prevent windows from making them by
shutting them down.

The range of possibilities is vast, and it requires a lot of effort to find ways
to infiltrate a system. Unfortunately, the body of knowledge of how to do
this keeps growing. As does the number of places where you can find
cracks and posted serial numbers to most of the popular programs out
there. I can guarantee that no licensing process is immune to one attack
or another. Given time and reason, any system can be hacked.

I haven't used softice, and I don't intend to. I do note that you keep
pointing up that you need to know the right memory location to set a
breakpoint at in order to uncover the license information. And just how
do you know this? Because someone posted that information somewhere,
and with that information, you did a successful hack. Knowing which
register or registers then held the serial number or license code. So
what you really have is someone, somewhere, that knew enough and
was persistent enough to unravel some of the mystery. Challenged
enough, someone of that callibur is going to try and beat any other
system.

If you really want to establish a "random" area where you first place the
license, registration, or serial number, then you could use a memory
bank or even an oversized string and pick a random location along it.
You could prefill it with random characters if you want. You could even
scramble the order in which the serial number is placed there. None of
this makes any difference if:

(1) A hacker can identify the source you used for getting the serial
number in the first place, or

(2) Can examine your code and unravel the steps you are taking to hide
your "secret" location and method of using that validation code, or

(3) Can simply find a point to bypass your checks or defeat them by
replacing some of the code with his/her own, such as a JUMP statement
over a check, a NO-OP over a CALL to a check process, or a RETURN
statement inside a called SUB that would perform the check.

The fact is, there is literally no way to obtain total security when you
are dealing with software. You have to rely on some form of physical
security as well, to defend the outer layer. As pointed out, the best you
can hope for is to discourage hackers from succeeding with your code
and hope they go onto someone else's.

Many distributors today merely distribute a limited version of the program,
then negotiate with you to buy the full version, which has to be
downloaded through a different link. That gives them a degree of
physical security, since you do not have access to the full version until
you buy it. After that, they don't have control of how you use it or who
you distribute it to, but most people who pay for their software resent
those who get it for nothing, so it is not likely to travel too far from home.

And since software does not give you absolute protection, it follows that
any Operating System is going to be penetratable at some point and
defeated. Whether it is Windows, Unix, Linux, or the MacOS. Windows
seems to have more than its share of vulnerabilities, but any system
written in C/C++ is vulnerable because C/C++ provides no native
protection from problems like buffer overruns and the use/abuse of
pointers. In fact, any system where you can access the code of the
Operating System, either in RAM memory or on a hard drive, is
vulnerable to being hacked.
has-been wanna-be (You may not agree with what I say, but it will make you think).
Admins

Post by Admins »

oldefoxx: good write!
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Re: Software Protection and Preventing Memory Modifications

Post by PB »

> Can I stop another process from changing my memory?

Nope. As you've noticed, there are "trainers" which prove this.
StarHawk
User
User
Posts: 55
Joined: Sun Nov 02, 2003 7:27 am

Nuff said

Post by StarHawk »

@oldefox: You write: "The main thing though, is to make the program unreadable, which often means encrypting it on disk."

The white paper by Jonathan, and the points I've made have nothing to do with disk encryption, that's already solved by numerous programs available on the market such as Thinstall. The whole thrust of my message centers around after the decryption from disk happens and the program is running in memory.

You write: "I haven't used softice, and I don't intend to. I do note that you keep
pointing up that you need to know the right memory location to set a
breakpoint at in order to uncover the license information. And just how
do you know this? Because someone posted that information somewhere,
and with that information, you did a successful hack. Knowing which
register or registers then held the serial number or license code. So
what you really have is someone, somewhere, that knew enough and
was persistent enough to unravel some of the mystery. Challenged
enough, someone of that callibur is going to try and beat any other
system. "

When you answered your own question you were incorrect in your conclusions. I'm not going to go in length about how these processes are found. That is beyond the purpose of this thread. I will educate you a little though so you don't think I'm B.S.ing you. Certain operating systems function in certain ways. For example, Windows 98 swaps to HIMEM after input is received. By setting a break point with SoftIce when a HIMEM swap occurs, you effectively break into a program at the ASM level immediately before the compare with a register value occurs. You split the screen so that all the registers are visible and you step through each ASM command in a forward fashion while you view the contents of the registers at the same time. This is just one of thousands of easy tools/approaches a hacker stores in his tool box as he attempts to crack your code. That is methods of attack are developed and each hacker has his favorite tools and methods he uses. Seldom do hackers reveal their methods over the Internet as you suggest. It simply alerts the company to the vulnerability in their software protection scheme so that it makes it more difficult to hack software created at a future time by them.

You write: "You have to rely on some form of physical
security as well, to defend the outer layer." Yes, yes yes, but the physical outer layer is not what is being discussed. Thinstall and other programs have this feature. The security that the white paper by Jonathan discusses, and the feature request I'm making has nothing to do with this. I am concerned with modification by programs such as SoftIce that allow a hacker to see your code as it is executing in memory. The plain and simple fact is that code created with PureBasic is easier to hack when a implementation such as discussed above by Jonathan in C++ is not possible to implement with such ease. As I said before, I'm not looking for a bank peek/poke double back flip method but a professional solution such as the command provided in C++ that I requested above.

@Madmax you write: "Can't see the relation between hacking and terrorism, surely if terrorist need some software made with PB or other, they could just buy it if they can't hack it."
This comment is so far off from the point that was made in its context, it's just too stupid to respond to.

@Codemonger you write: "And if Fred is too internally implement a security system such as the one you are suggested (which is good no doubt), wouldn't that make it easier for someone to crack all purebasic programs that use the same security system."

Finally a most intelligent comment. The analogy then is to extend your logic and ask the question: Does the void *allocate_at_random_location(int size) in C++ make it easier for someone to crack all C++ programs? The answer is a resounding no and the logic for that answer comes from the fact that the solution is "random". Go back and read Jonathan Clark's white paper again. It specifically explains in very basic language why this code is more secure. Yes, if all Purebasic code stored the procedure at the same memory locations (which it currently does) with the void *allocate_at_random_location(int size) command (or C++ for that matter) then it wouldn't be random. Then you had to write: "This seems more like a capitalist propaganda marketing scheme as opposed to a really solid 3rd party software protection implementation. No offense" and I lost my faith in you. Thanks to the Patriot Act and other laws, security in the United States and England has filtered into every facet of our lives. Everyone wants security, to feel secure, to have their software secure from people who are prohibited by U.S. law to operate their software such as people in countries like Iraq, Iran, and to take reasonable steps to comply with this law to domestic terrorists/hackers who seek to do financial harm and destroy hard working entrepeneurs, many of which are Democrat/Liberal educational institutions who think all business is evil, all government is good, and who institutionally support (latest mIRC raids found the servers located and supported in such universities) the attack/hack of software created by those who they view as evil/greedy, to business competitors taking valuable sections of programming code rather than incurring research and development costs themselves and stealing programming routines to use in their own competitive products. 911 ushered in a general desire for security in a multitude of industries, across the board, in all facets of civilized societies. And if you don't think security related software companies have reaped the benefits of this new desire for security, then you haven't looked at the New York stock exchange recently, or at companies like Thinstall.com that have really taken off. It's not capitalist marketing propaganda, it's just plain fact, go and research it for yourself.

@All
The challenge is to understand the white paper by Jonathan Clark, and to explore deeper why this security expert would write such a thing. Rather than use your intellectual energy to try and down play the security vulnerabilities in all Purebasic code, choosing to think what may "feel good" if you convince yourself of it because you just don't have the time with all the other coding you are doing to elevate the security of your Purebasic created exes, the challenge more is to understand what has been written here if it interests you.

My request then, is to add a flag on the end of a procedure that enables a programmer in Purebasic to use this security procedure in their own code exactly as a programmer in C++ would. To enable a programmer in Purebasic to read Jonathan Clark's white paper above and to be able to easily and quickly duplicate this function/method in their own code.

In otherwords, I pay Jonathan Clark over $1300 this last year to handle the security related issues of my company. The reason I pay him is because he is great, perhaps the best in the world, at what he does (and I've been around a long time), and thanks to his security software and advice, I have made thousands of more dollars this year in sales by preventing duplication and hacking of my software and have a distinct advantage over my competitors and therefore have a good relationship with this man and his company. Now, when Jonathan publishes a paper, I'm interested in what this man has to say. If he tells me of a good method to use to protect my software (which he always does as that's what I pay him for) then I want to implement it. Why would I take some of the posts in this thread, as they suggest, as advice over my world renown security programmer Jonathan Clark? Who are you in the world of security/lecturing? Where's your big security business? Whose paying you over $1,300 a year to protect their software? I'm not. Some of you have heads that are way too big and I hope I've knocked you down a couple notches: humble yourself.

A feature request with reason was posted to Fred. I'm sure Fred or his company is not completely ignorant as to the vulnerabilities in Purebasic created code and the value of this feature in C++. If he chooses not to add this command or to add this command it is what he chooses or his company. I'm not sure why some of you are posting in this thread or in other feature requests for that matter. Who are you and what is it to you my request? Some of you who posted don't work for Purebasic so explain to me again why it's important that people have to defend their feature requests constantly to you? Simple. It's not.

Nuff said.
Codemonger
Enthusiast
Enthusiast
Posts: 384
Joined: Sat May 24, 2003 8:02 pm
Location: Canada
Contact:

Post by Codemonger »

Jonathan Clark, Jonathan Clark, Jonathan Clark ... it seems you've stumbled across a white paper that you feel is end all be all, to solve the worlds terrorism problems, hacking software, and even ending starvation in third world countries. Starhawk it's no doubt it sounds like you really know your stuff in this area. So, I would like to get your opinion on the downfalls to this method ? and what are some other alternatives ? What is the link to the software you wrote ? are you Jonathan Clark, or related to him ?
Codemonger Quote: "This seems more like a capitalist propaganda marketing scheme as opposed to a really solid 3rd party software protection implementation. No offense".

Starhawk Quote: "And if you don't think security related software companies have reaped the benefits of this new desire for security, then you haven't looked at the New York stock exchange recently, or at companies like Thinstall.com that have really taken off."
I think you just proved that yourself ... hmm care to argue, i know you will till your blue in the face ... oh don't get me wrong, i think this idea would help sales in the protection department, it's just using terrorism as an excuse to software protection is a little lame, considering most applications are related to every day use as opposed to something a terrorist is going to want to hack. PB users are programmers remember and not end users so you don't have to sell the terrorism thing to us, it's just kinda funny, it sounds so, uhm patriotic :). Doesn't mean your idea is bad though, you just sell it likes it's propaganda, that's all.
A feature request with reason was posted to Fred. I'm sure Fred or his company is not completely ignorant as to the vulnerabilities in Purebasic created code and the value of this feature in C++. If he chooses not to add this command or to add this command it is what he chooses or his company. I'm not sure why some of you are posting in this thread or in other feature requests for that matter. Who are you and what is it to you my request? Some of you who posted don't work for Purebasic so explain to me again why it's important that people have to defend their feature requests constantly to you? Simple. It's not.
Well your plainly wrong here. It's a community, your ideas are great, and its our job to punch holes in it. Besides the fact its fun, it really asks questions that fred asks ... Is this feature needed ? is it worth it ? are their potential problems ? what are the risks ? will people understand why, when, where and how to use it ?

Anyway point being is it makes a good read, everyone likes a good debate, and we are programmers we have to doubt everything even our existance :lol: BTW don't take things soo personally, it's all in good nature.
<br>"I deliver Justice, not Mercy"

    - Codemonger, 2004 A.D.
Locked