Stringutils.c

For the past few months I’ve been thinking of starting this, plainly out of boredom, but it might actually turn out to be useful. 3ld3r and me have worked a bit on it already, and I think it’s something worth taking a look at. If you’re active on hackerthreads, you’ve seen me asking for suggestions there. Well, I accepted some of them, and so I’d like to thank the guys who made them.

So what is it really? Well, it’s a set of functions designed for string manipulation in C. Eventually, while coding, you might spend a considerable amount of time trying to work out functions for string input/output/etc, and this project’s objective is to end that, or at least make the lives of bunches of coders a bit easier.

The project is still not hosted anywhere on the Internet, and this is merely its introduction. So here’s a bit of the commentary already on it:

combinestring() will take two strings, append one to the other,
and return the base address of the newly created string.
The new string is null-terminated.

countoccurrences() will take as arguments a sequence of characters,
a target string, and a starting and ending indeces, and count the number
of times in which the [sequence] occurs within the [target] string.
The resulting integer is returned.

justifyright() will take in a string [str], its length (size in bytes,
passed through [strsize]), and a filler character. The function will
shift the contents of the character string to the right, justifying it,
and then fill the initial (and now unused) bytes of the string, with
the character passed to it through the [filler] character.

justiftyleft() can be used to reverse the effects of justitfyright().
it receives the string to be justified to the left, the string’s size,
the length of valid characters within the string (so it can know,
starting from the last byte, where the first valid letter is), and the
filler character, with which all the remaining bytes to the right of
the resulting left-justified string will be filled.

strsubst() will take as parameters a target string, its size in bytes,
and two other strings: srcsequence and newsequence. It will then look for
occurrences of [srcsequence] inside [target], and substitute it with [newsequence].
The resulting string, which is null-terminated, is returned.


I would personally love to have more people participate in this. I think it’s a good learning opportunity, for all of us. As soon as I open the project officially I’ll let everyone know.

A Beginner’s Introduction to Debuggers

Coding is a complicated task, and as such, is very error prone.  Even the most experienced programmers out there have to face bugs. The secret to getting rid of them fast and easy is to master the use of debuggers. I hope this article helps people who are being introduced to programming so that they can program more easily and effectively

Debuggers are usually included with most compilers and IDE’s. The first thing you’ll usually need to do is activate the debugger. After activating the debugger, you’ll have to recompile your code (if you’re compiling on a Shell, you’ll probably have to set a “debugging option”, this is necessary because the compiler will then generate data about your code for the debugger to use. You’re now all set-up to begin debugging.

In a standart IDE, your debugger will usually present the following tools:

Breakpoint insertion: This marks a point in your program where the execution will pause and wait for the user to take action on the debugger.

Step-by-step execution: After pausing the execution, you can proceed with it one line at a time. This way you can find out exactly when the bug happens. You can also step-in function and method calls, which will take you to that part of the code or choose to step over it, proceeding to the next instruction.

Variable watches: You can select a variable in your program and assign a watch to it. This way you can see, while running, what values it is storing. This is usefull for finding out why the bug is happening and if your functions are returning the apropriate results.

This are basic tools that most debuggers have. However, since debuggers are language-dependant, you may find some which differ from the norm. So, with those tools in mind, you can follow these steps to find the bugs in your code:

  1. Define a breakpoint, if this is your first time debugging, you may want to choose one right at the beggining of the program.
  2. Run it step-by-step. You can step over function/method calls. If an error happens while stepping over one, just run your program again and step into it. Do this untill you find the bug you’re looking for. (In many cases you’ll have to reproduce the bug, that is, supply input to your program so that the bug you’re looking to solve happens.) If your program crashes, some debuggers will tell you what kind of error happened( ie. buffer overflow, segmentation fault, etc.). Now, you know WHEN the bug happens.
  3. After finding the line where the bug happens, examine it and assign watches to the variables in use. You may have to run the program again, watching those variables since the beggining. If you’re dealing with pointers, you can see the contents of that memory location by putting a * next to the variables name when assigning the watch.
  4. After that, the only thing left to do is figure out WHY the bug happens. This is sometimes tricky, and you’ll have to debug the program several times, and if that doesn’t help, you should try doing some table-testing (running the program yourself, step-by-step, on paper-and-pencil). If you’re using functions from other packages/libraries/etc , research about those functions to find out exactly what they do and known bugs related to them.
  5. This step depends on the kind of bug you’re facing. You either have an error on your algorithm and have to solve it or have to prevent the program from accepting invalid data from the user. Sometimes this involves heavy tweaking, sometimes a simple “if-then-else” statement will suffice and then, in some utterly annoying scenarios, you’ll end up having to rewrite most of your code. It happens, but eventually you’ll start to screw up less.
  6. Testing to see if the bug is fixed and if no other bugs have been created in the process.
  7. Repeat until your code is bug-free.

In the past, programmers had to figure out bugs the hard way, printing checkpoint messages everywhere. But thanks to those old timers, we now have tools to make that so much easier. Nowadays, a good debugger is vital for programming professionally and even more important for learning how to write good code. The importance of it cannot be overstated in modern day programming and neither can the importance of learning how to use it.

More info on debuggers:

Solid State Hard Drives Breakthrough

Regular HDs nowadays ally mechanical work and electromagnetic fields to store non-volatile data. They’re just a bunch of disks piled together, containing thin magnetic surfaces which interact with electro-magnetic needle-heads. Now if you program or have considerable knowledge of computer programs, then you know that accessing data located in the hard drive is about the costiest thing you can do (both time and energy-wise). That stands true because the needle head needs to move up to a specific location and wait for a specific disk to rotate so that you can read exactly what you want.

Well, it just so happens that there are other ways of storing data. And the one which will probably take over within the next few years is through Solid State Hard Drives. If you’ve never heard of them, all you need to know is that they’re different than our hard drive disks because they don’t store bits using magnetic fields on disks, but semiconductors built upon integrated circuitry (thus eliminating the need for all the mechanical action upon I/O requests). The idea isn’t new; in fact, we’ve been using solid state devices for a few years now (pendrives). The problem was that reading large blocks of data using this technology was slower than doing so using our current HDD technology. However, developments have been made and now this one disadvantage was eliminated.

Consequently, we’re left with only advantages: SSHDs are silent, dont heat up as much (even though they can work at temperatures regular HDs can’t), faster (no waiting for rotation and needle positioning… they even boot faster) and don’t break as easily (because of the lack of tiny mobile mechanic parts).

As expected, SSHDs are still way more expensive than magnetic disk-based ones, but the prices have been going downhill. Just recently, Sony released the Vaio FW series, which includes a 256 SSHD, and pureSilicon, an actual 1TB SSHD (Nitro N1).

Whether you can afford them or not isn’t really important. The point is, in the near future, there’s a great chance these drives will be as cheap as our current ones, and that’s something we can look forward to.

Alternate Data Stream Utility

If you’re familiar with Alternate Data Streams, then you’ve probably already run into a few utilities the objective of which is to locate and manipulate ADS’s in your NTFS-formatted drive. Well, this is one I coded. It’s C-based, and works for Windows Vista & 7.

Whether or not ADS’s are a security risk or not is debatable, and there’s a relatively vast amount of information on it. Roughly speaking, NTFS drive partitions support multiple data streams within the same file. The alternate streams’ contents aren’t usually visible, and in Windows, a file may contain many bytes of data which aren’t shown within that file’s properties. The ADS isn’t shown with regular DIR commands either. Here are some links explaining what ADS’s are and how they may be used:

http://www.ntfs.com/ntfs-multiple.htm
http://www.irongeek.com/i.php?page=security/altds
http://www.windowsecurity.com/articles/Alternate_Data_Streams.html (a bit sensationalist)
http://www.securityfocus.com/infocus/1822
http://support.microsoft.com/kb/105763/en-us/

Well, my piece of software enables you to search either the current directory or the whole drive for ADS’s, lets you create files within files (which will therefore stay hidden), extract ADS contents (after you provide their relative path) and save them to files, and clean files which might contain ADS’s.

You can download it here. Please note that ADS’s aren’t necessarily “evil” (they usually aren’t). Windows and other software pieces use such streams for, amongst other things, meta data.

Mozilla Firefox

Is it me or has Firefox turned into the new IE? I remember when I first used FF, I was positively impressed: the browser was light, fast, practical (IE still hadn’t implemented tabbed browsing, and I had come straight from it), secure… However, with every new version it seems to stray farther and farther away from all these qualities and get closer to IE.

Maybe their project got too big. As a result of their gains on the markey share, FF is now being targeted more often, so more vulnerabilities are being found in it. The browser was elected the least secure of all 4 major web browsers in 2009. Don’t believe me? Check out the report. However, what really puts me off is the fact that they’re making the browser heavier and slower with every update. Sure, every website you run into today will be fully compatible with Firefox, but you know what? I’d rather have it be as light as before, and just use IE whenever I needed to access a single website that didn’t comply with its protocols.

Google Chrome seems to be playing the role of the new, lightweight, practical browser nowadays. And to my surprise, the vast majority of websites are compatible with it and work just fine. Eventually you’ll meet some malfunctioning features on smaller websites, but Google’s doing a good job so far. Hopefully, they won’t follow the tendency and will keep away from whatever it is that makes browsers get worse as they become more widely used.

Proxy List Checker & Updater

Heya. This is another perl project, and it might be handy. If you use the internet a lot, you may eventually build and save huge proxy lists. The problem is, and this is especially true if your list consists of free proxy servers, the number of servers going on and offline all the time is really high, so sometimes it can be annoying to find a good working one. This is what this tool’s for. It’ll read a proxy list containing IP:PORT pairs and try a connection on each of them, for a specified number of seconds. If the timeout is reached, the proxy is considered temporarily dead and isn’t logged. If it connects, the program prints out the pair and logs it to the updated list. The list contains the date and time of execution within its file name. The bigger the proxy list the better, for obvious reasons, but you shouldn’t delete the original one after running a check. Proxy servers may spring back to life after a little while, so it can’t hurt to just leave them all there in the original list.

The Code

Modify this to your liking, it’s simple and straightforward. It’ll spawn 1000 (woot!) threads per “round”, which will each try to connect to a server socket (the proxy server). Change this if you like. Here it is:

#!/usr/bin/perl

use IO::Socket;
use Threads;

#-----------------------------------+
# guidjos' Proxy List Checker v1.1  |
#-----------------------------------+

if (@ARGV < 1){

	print "\n\n\n   Failed. Usage: $0 [proxylisttxtfile] [timeout(seconds)].  \n\n";
	print "         If no timeout is specified, default == 4 will be used.\n\n\n guidj0s\n";
	exit;
}

@hora = localtime;
$nomelista = "proxylist_$hora[3]-$hora[4]--$hora[2]h$hora[1]m.log";
open(novalista, ">>$nomelista");     # I know, I know.

if ($ARGV[1])
{
	$tout = $ARGV[1];
}
else
{
	$tout = 4;
}

sub testaservidor
{

	my($ip, $falha) = @_;

	my $sockteste = IO::Socket::INET->new(
		PeerAddr => $ip,
		Proto => 'tcp',
		Timeout => $falha,
		Reuse => 1
	);

	if ($sockteste)
	{
		$sockteste->close();
		print "    $ip responded.\n\n";
		print novalista "$ip";
		return 1;
	}
	else
	{
		print "  $ip is dead.\n\n";
		return 0;
	}
}

open(dados, $ARGV[0]) || die("\n\n    proxy list file specified was invalid\n\n\n");
@proxies = <dados>;
close dados;

my $atual = 1;
my $vivos;

print "\n\n Starting to check proxy servers...\n\n\n ";

while ($atual <= $#proxies)
{
	for my $quantas (1..1000)
	{
		if ($atual <= $#proxies)
		{
			my $crianca = threads->new(\&testaservidor, $proxies[$atual-1], $tout);
			$atual++;
		}
	}

	foreach (threads->list)
	{
		$resultado = $_->join;
		if ($resultado)
		{
			$vivos++;
		}
	}
}

close novalista;
print "\n\n Done.\n\n $vivos out of $#proxies servers responded and were\n  logged to $nomelista\n\n\n";

Multithreaded Perl Portscanner

While learning sockets in Perl (to put it more acurately, while learning the IO::Socket module), I came across a few implementations of Perl portscanners which, even though functional, were far from practical. I know, I know, you can just get Nmap if you’re looking for a good portscanner, but hey, you can build your own scanner and make it decent.

The implementations I often found (there were also some php versions) were too slow because they worked by looping through the port numbers and trying them sequentially. All I did was create some threads to speed things up, and the resulting speed is actually acceptable. The following code loops through the port range specified, creating rounds of 30 threads to test the ports by calling the “testarporta()” sub routine on the current iteration’s port.

On to the code:

#!/usr/bin/perl
use IO::Socket;
use Threads;

#+---------------------------------------------------------+
#|                                                         |
#|               Fanatic Port Scanner v 1.0                |
#|                  coded by guidj0s                       |
#|                                                         |
#+---------------------------------------------------------+

sub testarporta
{
  my $tentar = new IO::Socket::INET (
  	PeerAddr => $_[0],
  	PeerPort => $_[1],
  	Proto => 'tcp',
	Timeout => '1'
  );

  if ($tentar)
  {
  	print "$_[1] ";
  	$portaberta = $_[1];
  	open(logar, '>>fanatic_scanresults.txt');
  	print logar "$portaberta ";
  	close logar;
	close $tentar;
  }

}

if (@ARGV < 3)
{
	die "\n\n\n    Failed. Usage: $0 [ip] [startport] [endport]\n\n\n";
}

my ($ip, $pi, $pf) = @ARGV;

print "\n\n -------------------------------:: Fanatic Port Scanner by guidj0s ::-------\n\n";
print " Working...\n\n\n  Open Ports: ";

open(scanlog, '>>fanatic_scanresults.log');
print scanlog "\n\n\n-----------:: Last Scan Results for $ip ::--------------\n\n";
print scanlog "\nPort Range Selected: $pi-$pf";
print scanlog "\n\n\nOpen Ports: ";
close scanlog;

while ($pi <= $pf)
{
	for my $controle (1..30)
	{
		my $agente = threads->new(\&testarporta, $ip, $pi);
		$pi++;
	}
	foreach (threads->list)
	{
		$_->join;
	}
}

	print "\n\n\t\t\tScan finished.\n\n";

As you can see, the ports found open are logged to fanatic_scanresults.log. If you looked at the code you realized a port is considered “open” only when a connection can be established on it.

The Win32 GUI version
I did make one. I coded it using the Win32::GUI module. I know TK would have been a better option (as I found out quite soon), but that’s what I went with and I really don’t think it’s worth the hassle to migrate (I’m not working on it again any time soon).
As you may know, Win32::GUI isn’t thread safe. In this case, whenever I tried to access a Win32::GUI object from within a child thread, the program crashed. I solved the problem by creating a shared variable ($aberta), which is updated everytime an open port is found. I also created a control variable ($ultima), which is used to check whether the last value printed out/logged was already printed or if the value currently stored in $aberta has already been handled (so I only need to print it when $aberta != $ultima. After doing so, I update $ultima with the current value stored in $aberta), and then access the Win32::GUI element from the main thread.
I added a functionality to the program, which is the option of providing a portlist plain-text file to scan for specific ports only. Enough talking, here’s the code: http://guidjos.justfree.com/fntcgui.txt
Now that I look at my code again, I see there’s a silly mistake. You should never access files like I did here:

open(scanlog, ">>$logto");

But I’ll leave this for another post, as this one’s long enough. The handling of user-input related mistakes isn’t really thorough either, so feel free to improve the code (sharing the new version would be cool, I might give you some space to talk about it and share your code here on the blog ;) ).

Clearing the input buffer in C

First off, since I see many people get here because they have trouble with left-over trash in stdin, I need to say that this isn’t a solution for that. To read strings with undefined length, and guarantee you won’t have garbage left back, refer to the post “Reading Strings With Undefined Length in C”. That’s what you should do (you won’t even need to clear the buffer). This here is just some playing around I did, and shouldn’t be used as a solution.

Reading from the keyboard (stdin) in C might be tricky, for various reasons. One very common issue you might go through is that the input buffer might be dirty from stuff that remained there from a previous reading. To make things easier for me, I’ll call the input buffer “IB” from now on. Let’s start with some code:

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

int main()
{
char readinput1,readinput2;

	printf("\n\n\t Type a character to be stored into \"readinput1\": ");
	readinput1 = getchar();
	printf("\n\n\t Type a character to be stored into \"readinput2\": ");
	readinput2 = getchar();

	printf("\n\n\n\t You've typed: %c (readinput1) and %c (readinput2)", readinput1, readinput2);

	return 0;
}

Ok, so what this code apparently does is ask the user to type in one character twice, storing each of them into a different variable of the appropriate type. In fact, though, when you run this code and test it, you’ll see that readinput2 ends up with the newline character (‘\n’). That’s there because when the user presses the “enter” key (carriage return) to finalize the typing, two character codes are sent to the OS: ‘\r’ (carriage return) and ‘\n’ (“enter” is the same key used whenever you wanna add a new line on text input).

What happens then is the \n stays in the IB, and then when we call getchar() again, it will do just what it’s supposed to, which is to take one character from the IB and return it. That’s how readinput2 gets messed up.

On a more interesting example:

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

int main()
{
char readinput1[10],readinput2[10];

	printf("\n\n\t Type 9 characters to be stored into \"readinput1\": ");
	fgets(readinput1, sizeof(readinput1), stdin);
	printf("\n\n\t Type 9 characters to be stored into \"readinput2\": ");
	fgets(readinput2, sizeof(readinput2), stdin);

	printf("\n\n\n\t You've typed: %s (readinput1) and %s (readinput2)", readinput1, readinput2);

	return 0;
}

Notice this code isn’t vulnerable to buffer overflows on readinput1 and readinput2, because we’ve specified we want to read up to and no more than sizeof(readinput1) and sizeof(readinput2) into each one, but here’s how we’re gonna do this: run the code, then type in “12345678901234567″ when it asks for the first input. Press ENTER and watch what happens. Here it is:

So what happened there? Well, we threw 18 bytes into the IB, and it looks like this: 12345678901234567\n. The first call to fgets() takes 9 bytes from it, throws into readinput1 (indeces 0..8), then finalizes readinput1 with the null byte character (”). Then there’s a second call to fgets(), but at this point the IB looks like this: 01234567\n, and look, there’s a \n at the end of it. fgets() will stop reading whenever it reaches a newline character, and that’s why the user doesn’t even get a chance to type anything. readinput2 then ends up with 01234567\n, as shown in the screen shot.

All right, so how do we solve this?

Well, if you think about it, we have functions in C that will pop characters off the IB, and that’s really all we need. In the first example, as you could have guessed, you could add a getchar(); after the first reading so as to get rid of the \n that’s left in stdin, but that’s hardly an efficient solution, because, as we’ve just demonstrated, we may have any amount of bytes left there, depending on what the user types. But coming up with a solution is simple enough, all we need to do is keep popping characters off stdin until we reach a \n or a nullbyte ;)

So here’s my code for that:

void clearib()
{
    char c;
    for(c = getc(stdin); c != '\n'; c = getc(stdin));
}

So all you need to do is, whenever you think there might be trash left out there, call this function before reading anything in. So our example could be fixed like this:

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

void clearib()
{
    char c;
    for(c = getc(stdin); c != '\n'; c = getc(stdin));
}

int main()
{
char readinput1[10],readinput2[10];

	printf("\n\n\t Type 9 characters to be stored into \"readinput1\": ");
	fgets(readinput1, sizeof(readinput1), stdin);
	clearib();

	printf("\n\n\t Type 9 characters to be stored into \"readinput2\": ");
	fgets(readinput2, sizeof(readinput2), stdin);
	clearib();

	printf("\n\n\n\t You've typed: %s (readinput1) and %s (readinput2)", readinput1, readinput2);

	return 0;
}

Sure enough, if you give the same input you did for readinput1 the first time, you’ll see it’s fixed. Here I typed in “12345678901234567″ again, pressed enter, and got asked to type in the input for readinput2. I gave it “aaaaaaaaaa” (10 times ‘a’), and both strings contained what they were supposed to at the end. Notice how I called clearib() after the second fgets(), so even though there is one ‘a’ left in stdin after this (because fgets() reads 9 bytes + terminates the string with the null byte), the buffer is cleared with the given function and all is well. Here’s the output:

And that’s that. If anyone has any ideas/thoughts/comments/better solutions, please speak up. Otherwhise, enjoy ;)

Mac vs PC: Flawed Arguments

Touchy subject, I know. I’ll go ahead and tackle some “classic” arguments thrown at PC users, as well as some aspects of the Mac vs PC discussion:


“Macs don’t get viruses”

It’s unacceptable to say that. It’s possible to say that it’s safer to use Mac OS X than it is to run Windows, for instance, but that’s because viruses, worms and the like are coded aiming for broader target ranges, and that comprehends PC-compatibility. So the fact that the most popular system out there is Windows makes PCs a far more valuable target for malware than Macs, and that’s why these bad boys are engineered to work on machines operating under Windows.


 

“In Macs, you don’t have stuff running in the background”

This contradicts the most fundamental theory behind the working of an operating system. An OS is designed to, amongst other things, coordinate the execution of a bunch of programs. Each program can be called while the execution of another process is still not finished. In fact, this is very natural and frequent, and is actually the motivation behind the construction of an OS. Such a system needs to have features, like say, a GUI, a file managing system, device drivers and other services, etc etc etc. All of that necessarily requires stuff to run in the background, so ANY operating system includes that. Period.


 

“Microsoft doesn’t innovate, only Apple does”

I can see where this comes from. Apple does have a very creative crew when it comes to looks and feel of their devices and systems. Also, Microsoft has implemented stuff that wasn’t their idea to begin with (i.e. tabbed browsing, if I’m not mistaken). However, this happens a lot in the industry, and if a functionality that enhaces usability can be added, I think it should be (so long as the ones who implement it later don’t pretend to be the creators of the idea). However, people tend to forget that Microsoft has brought perhaps the most significant innovation to computing ever seen: the GUI-based OS concept. Hell yeah.

Now, just as people say Microsoft copies stuff off other companies, people could say Apple copied Microsoft when they decided to make their system present itself through graphical windows other than just a terminal ;)


 

“Apple software is less flawed”

Another misconception. Just because crackers don’t target Macs and other Apple products, it doesn’t mean they can’t get in if they try. Windows systems are actually a lot stronger in this aspect than MacOS versions, for example, but since there’s not nearly as many people interested in hacking Macs, most people just assume the system is “safer”. Don’t believe me? Here you go:
http://www.zdnet.com.au/news/security/soa/Mac-OS-X-hacked-under-30-minutes/0,130061744,139241748,00.htm
You might also wanna check this out: http://www.tomshardware.com/news/hack-windows-security-snow-leopard,8704.html
Oh, and why not look into this one? http://www.net-security.org/article.php?id=1322&p=1


 

Teh RehvolushonZ

Apple uses the term “revolutionize” a bit too often. One of their most recent products, the “Magic Mouse”, is supposed to “revolutionize” the concept of mice. Right. The thing is, the mouse not only has limited features (the two-finger swipe can’t be set to perform other actions than flicking through pages/pictures/whatever, while extra buttons can be set to do anything at all), it also lacks ergonometry. The iPod did give mp3 players a big twist though, so props to them. The iPhone? Arguable.


 

Stability

I don’t know much about this one, since I’ve never spent relevant time using a Mac, so I usually just believe it when they say Macs run “smoother” than Windows. That’s fine by me. If anyone has actual facts, they’re welcome to comment informing me.


 

Just to make it clear that I don’t have Gates’ picture tattooed across my chest, I’m gonna say “shame on MS for releasing Vista and Longhorn before they were completely done”.Then again, they might have had a good reason for that (XP had been around for a long time, and they might just have “had to do something”). Oh yeah, and I don’t use IE, I think it’s slow, too square-ish and the work-arounds aren’t very intuitive for me. Also, more flaws have been found for it, etc etc etc.

If you think about it though, there doesn’t seem to be a great number of PC diehard fans like the ones Apple has converted. PC users aren’t ashamed (that’s right, the word is “ashamed”) when someone says something bad about PCs. Try that out on an Apple fanboy. You’ll get the classic arguments (read above) thrown at you before you can blink twice.

 

But let’s forget about that. Everyone should use what they think works best for them, and you know, if prettier design along with stability are features you MUST have, and you’re willing to pay for, then by all means go with that. If you choose to go with compatibility and are ok with dealing with crashes more oftenly, then that’s ok too. Just don’t come up to me or anyone else with lines from the company’s advertisement campaign and an arrogant look, because just eventually you might get a lecture and end up with a dumb look on your face.


 

Anyways, if you guys have any relevant comments and/or views on this, please speak up. If you’re a Mac user who’s up to pointing out a few relistic and measurable advantages you think are important or if you noticed I said something that’s untrue about your system, do say so.