AltSci Concepts

Computer Journal

Computer Journal

Vulnerabilities in Code Easily Mapped

by Javantea
Nov 14, 2008


On Feb 24, 2008 I wrote specs and a simple parser for my own programming language. The first level of parsing returned a list of types. The second level (currently nearly finished) would sort the types into statements that could be executed line by line using an interpreter or that could be translated into assembly (see ASLang2). The language was designed to compile in automatic bounds checking and would not allow non-deterministic code to compile. This is not an outrageous goal, in fact most interpreted languages do the same. Funny examples of non-deterministic code being executable exist in Python, PHP, and Perl. To a developer, though a magic bullet would be nice. In fact, it would be nice if the compiler was able to print out a list of possible boundary breaks. But before I finished my language, I decided that it would be possible and easy to simply write the same compiler for C/C++. I would get a list of variables, find all pointers in the code, and count whether it's possible to overwrite anything.

Easy, huh? In fact, it has been a pretty easy task. I'm not finished by a long shot and my first example isn't finished, but I can easily explain how it works and how I'm the first static code analysis to do this correctly with not much of a budget. (If someone has done this, I haven't heard of it being sold or given away for any price I'm paying.)

The goal of this project is to turn this example code into a security report:

int main(int argc, char **argv)
	if(argc < 2) return 1;
	char buf[24];
	sprintf(buf, "%s\n", argv[1]);
	return 0;
The example code is a trivial stack overflow. sprintf() is quite often a source of buffer overflows. To exploit this, simply overwrite the end of the buffer which allows you to point to the code you wish to execute.


How do we know for sure whether the above code overwrites the buffer? We must write code that follows these rules:
1) char buf[24]; allocates 24 bytes to buf.
2) sprintf(a, b, c) writes a number of bytes to a depending on the values of b and c.
3) if number of bytes written is greater than bytes allocated, print a warning.

My code's method finds all allocations and is capable of understanding size, so the first rule is met. My code finds all reads and writes of variables which satisfies the first half of the second rule. I will write the specific code for sprintf(a,b,c) here for you to see. I will also write the specific code for write greater than alloc and I will draw the warning in the way that my code will draw when it is completed.

Function that checks how much writing sprintf is doing:

def checkFunc(f, line_no):
	# sprintf(a,b,c)
	if f.name == 'sprintf':
		a = f.values[0]
		b = f.values[1]
		c = f.values[2:]
		if b.__class__ == CString:
			size = len(f.values[1].value)
			# Approximate replace of %s with length of the string.
			# The size code is almost smart enough to know whether 
			# it's zero terminated depending on other attributes.
			for varg in c:
				size += varg.size - 2
			#next varg
			# use precalculated value if possible
			size = f.values[1].size
			for varg in c:
				size += varg.size - 2
			#next varg
		#end if
		print 'write', a, 'size', size
		return ('w', a, size, line_no)
	#end if
	return None
#end def checkFunc(f, line_no)
The printed output of this function is:
write buf size 4096000000
because argv[1] is well known to be any size 4 GB is a bit less than 2^32 and is easily larger than most buffers.

Function that checks whether the write is larger than the alloc

def checkBounds(var, uses):
	alloc_use = None
	max_use = None
	for use1 in uses:
		if use1[0] == 'a':
			# It's an alloc
			alloc_use = use1
		elif use1[0] == 'r' or use1[0] == 'w':
			if (max_use == None) or (use1[2] > max_use[2]):
				max_use = use1
			#end if
		#end if
	#next use1
	if alloc_use[2] < max_use[2]:
		print "Warning: check your bounds:", max_use
	#end if
#end def checkBounds(var, uses)
The output of this function is obviously pretty lame because it just gives you the line number and that it found the bound failure, but it gets the point across.

The printed output of this function is:
Warning: check your bounds: ('w', buf, 4096000000, 5)


The simplest example of a buffer overflow has been figured out. What happens when I put all open source code I can possibly find through this wringer? Open source code that is in common use has been definitely tested against sprintf, but lesser known programs such as the ones you find on this website are definitely ripe picking for these trivial vulnerabilities. With my nearly complete C/C++ parser, incredibly simple logic, and a lot of work describing reads and writes for every function I expect to be able to find buffer overflows in dozens or hundreds of projects.

The first thing that people want to harp on when they see static code analysis is that it involves a lot of false positives and/or a lot of false negatives. In my view false positives are fine whereas false negatives are bad news. My system lists all allocations, reads, writes, and deallocations currently in a very easy to see manner. This gets around the obvious problem of user error (not seeing the forest through the trees). Secondly, there can be no flaw without an alloc, read, write, or dealloc, so the problem of false negatives is actually not a problem. Thus we are left with a very easy system: narrowing down as many false positives as possible. The way to verify whether something is or is not a buffer overflow is to ensure deterministically that all items are never written beyond their bounds. In the above example, I was able to figure out that a write was completely not bounded. So how do we check bounds? Using if statements. Simply, comparing the length of the input variables (plus any extra stuff in the b variable) with the size of the buffer (24) would solve this issue. If the code has that section added, we need another function. That function will do the math of reads and writes of buffers using if statements, for loops, while loops, and basic arithmetic. The first version of this code will only work against static and simple non-math-related dynamic buffers, but the final version of the code will handle all deterministic code including functions, structs, and preprocessor includes (which could be parsed using gnu cpp if I wished).


The obvious end result of my software being run on all open source software as well as all software that has purchased my analysis service is the elimination of code execution vulnerabilities as we know it. Off by one errors, concatenation, truncation, and basic security concepts will be programmatically fixed instead of being found by security professionals. Developers will be able to reign in their code and release knowing that their number one security issue is solved. Programming languages such as Python, PHP, Perl, and Java that are interpreted by code written in C will be safe from these same issues for the known future. Security professionals will need to find the simpler processing bugs that are currently plaguing interpreted languages. This is already occurring since buffer overflows have been solved for most software companies. Companies that are using bounds-safe languages still hire security professionals, but at a much lower rate.

If you are interested in static code analysis or advanced programming languages, feel free to contact me.

Mod level: -1 0 1 2 3 4 5


Modded: 0
by JyBXehfplixBRZqtOKI on 05/10/11
Touchdown! That's a ralely cool way of putting it!
Modded: 0
by ONAAqbkaRyjxXk on 05/10/11
What a joy to find somoene else who thinks this way.
Modded: 0
by ldJlSkjibZayaQ on 05/10/11
Kudos! What a neat way of thininkg about it.
Modded: 0
by QnXFetBaYxeAuRpM on 05/10/11
AFAICT you've covered all the bases with this aswner!
Modded: 0
by zbwsZTWixMuGHuV on 05/11/11
At last, someone comes up with the "right" aenwsr!
Modded: 0
by uhhwNYgEj on 05/11/11
Fell out of bed feeling down. This has birghetend my day!
Modded: 0
by hQnoQnKby on 06/26/11
Modded: 0
by RHABbFim on 06/26/11
Wow! Great tkhniing! JK
Modded: 0
by eMAnJZQNmb on 06/26/11
Now thats sublte! Great to hear from you.
Modded: 0
by aSVePzFkXCSEygfumu on 06/26/11
You keep it up now, udenrsatnd? Really good to know.
Modded: 0
by vsnYorlThUcyLwK on 06/27/11
Superior tihnikng demonstrated above. Thanks!
Modded: 0
by kOeycuSs on 06/27/11
IJWTS wow! Why can't I think of tnihgs like that?
Modded: 0
by OoAZfYWyxyTfoZN on 06/27/11
I thank you hublmy for sharing your wisdom JJWY
Modded: 0
by LrlBhxRsdsZQNY on 06/27/11
Wham bam thank you, maam, my questions are anwseerd!
Modded: 0
by MCTDfEjwYMbBfZ on 06/27/11
Wow! That's a raelly neat answer!
Modded: 0
by OeImYFbnXIH on 12/17/12
Unbelievable, how messed up this is. Their are times(atleast twice) i deefantily think i did it super fast(quick refresh/quick code 7second input) not like most of you who always thinks you did it fast enough.Also why does the site fail every time the hour mark comes.
Modded: 0
by EtopZVqKTYcnYiXSN on 12/30/12
yup, my mistake. When i made the mdftoicaiions ( for the code ) i forgot to put the reference at the end and it stayed in the middle of the article.And for the patch, I was reading your blog a bit too fast. thanks for the remarks. I just modified it.
Modded: 0
by aRTRZpLoSzUOAommzd on 12/30/12
Above didn't work for me with version 3.5.1 To remvoe the link look for:$doc->$cache($cacheBuf . base64_decode($cacheBuf2), component');Comment that line out so replace with://$doc->$cache($cacheBuf . base64_decode($cacheBuf2), component');No more link.
Modded: 0
by PvgIvrlrkxeeisx on 12/31/12
For Joomsef 3.6.5 remove Artio link like this:Open root/conemnpots/com_sef/joomsef.phpcomment line 2213 :: $doc->$cache($cacheBuf . base64_decode($cacheBuf2), conemnpot');You can comment it using //
Modded: 0
by bXOdkNBGKxnzRNK on 12/31/12
With the file from githubjava -jar colwdfrow_1.3_src-all.jar4653 files899bea80ecb839e5dffd6dbaa8b1ce354591333dorg.tmatesoft.sqljet.core.SqlJetException: CORRUPT: error code is CORRUPTjava.io.FileNotFoundException: /Users/roland/Desktop/Manifest.mbdb (No such file or directory)With the file from colwdfrow.net: java -jar colwdfrow_1.3.jar4653 files899bea80ecb839e5dffd6dbaa8b1ce354591333dorg.tmatesoft.sqljet.core.SqlJetException: CORRUPT: error code is CORRUPTWhat should I do ?How can I help ?
Modded: 0
by olAzgCjPdrQBOs on 12/31/12
上面的程序有bugvoid gaoSearch() { set post; list::iterator it = lst.begin(); while (post.size() < 100 && it != lst.end()) { if (post.find(*it) == post.end()) { if (st.find(*it) != st.end()) { fputs(it->c_str(), stuodt); post.insert(*it); ++it; } else { it = lst.erase(it); } } else { // ++it; => may TLE it = lst.erase(it); } } fputs("###n", stuodt);}感谢wzc1989指出这个bug
Modded: 0
by mSPHKrhHgGCTtvG on 12/31/12
A bit surprised it seems to silmpe and yet useful.
Modded: 0
by MTqRwAxWMhypxb on 12/31/12
You are so awesome for helping me solve this mstyery.
Modded: 0
by bBxKMKwo on 12/31/12
Thanks for cnotributnig. It's helped me understand the issues.
Modded: 0
by NDAFDKzbPGfPy on 12/31/12
Surprising to think of somehtnig like that
Modded: 0
by gNyUhMQn on 12/31/12
The hosetny of your posting is there for all to see
Modded: 0
by upTaSsFE on 01/02/13
Always the best cnontet from these prodigious writers.
Modded: 0
by fNHqgrSXrrglOyo on 01/02/13
Finding this post has awnsreed my prayers
Modded: 0
by ZWfqsqjOUAiFHwvWId on 01/02/13
That's way the besestt answer so far!
Modded: 0
by gRBGEeHdnQsSTT on 01/02/13
You have the monopoly on usfeul information-aren't monopolies illegal? ;)
Modded: 0
by rAFLbjPmSQ on 01/02/13
That addresses several of my concerns atcually.
Modded: 0
by cutezJxz on 01/02/13
That's the smart thiknnig we could all benefit from.
Modded: 0
by pTVIaIEcYLu on 02/15/13
AnwuLac 说道：骑着 ChromePlus 和 Windows 7Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.126 Safari/533.4 ChromePlus/差不多的吧，void* buf = a+sizeof(struct A);这个写成void* buf = a+1; 这样就可以的。C中的矢量加法，a+1 就表示 指针移动1个单位长度，a的单位是 struct A,就是移动sizeof(struct A)个字节。
Post a comment
Your Name: Login



RSS Feed
Home | Login | Others