I have a general distrust for Mcafee, as the maker of the world’s most poorly performing virus scanner / security suite. However, when I came across a Wired article about security holes in the Perforce version control system, I was lured in with interest. I don’t use Perforce, but the catchy headline of stealing Google source code via their source control system seemed intriguing.
After reading, the article, I knew I was going to be disappointed when got as far as:
The communication contained a link to a website hosted in Taiwan that downloaded and executed a malicious JavaScript, with a zero-day exploit that attacked a vulnerability in the user’s Internet Explorer browser.
This was in direct contradiction of dire warnings just above from Mcafee about SCMs being wide open for exploit. The attackers got in via an Internet Explorer vulnerability, not a Perforce one.
I read the Mcafee paper anyway, and found that the researchers had discovered a number of legitimate security weakness in Perforce to put its makers to shame:
- P4Web authentication can be bypassed by replay attack
- P4Web access levels implemented via hidden controls and can be bypassed by URL manipulation
- Session token not used for change password feature
It also mixes in some general security concerns that apply to every othr source control system in the world, or every other Windows service that exists, such as running with too high privileges, or the source code being stored in plaintext.
The complaint about the source code being stored unencrypted on the user’s local system seems particularly absurd. Given that the attacker has compromised the system and gained access (elevated privileges or not), it doesn’t matter how encrypted the files are, the attacker already has access to them so long as the user has authenticated and can decrypt them.
Mcafee goes on to make a number of recommendations, the most sensible, if impractical, one being to disable P4Web. But, the whitepaper leaves me wondering what its real purpose was. They gloss over the “zero-day exploit” in Internet Explorer to focus on vulnerabilities in Perforce that would not have otherwise been exposed beneath the corporate firewall.
Once a developer workstation is compromised and a pipe is available to the external internet, there’s really no stopping the attacker from obtaining the confidential source code, no matter how secure the SCM is. That is, unless, perhaps, the developer simply does no work on the source code. And that’s always an option if you want to be truly secure.







Visualizing the Heap on Embedded Systems – Part II
In the last article, I described a method to acquire heap allocation data from an embedded system. Next, I’ll describe how to visualize the data. First, though, to make things easier, I’ll acquire some real data from a regular Linux application.
For simplicity, I profiled a Linux application built with gcc, but the same principle applies to an embedded application. Using gcc, there is a useful shortcut to wrap the allocation function calls, which doesn’t require editing the code or modifying the objects directly. The linker ld provides a built-in option –wrap which will replace a symbol with __wrap_symbol which in turn can call __real_symbol to call the original function. You can pass this option through gcc to the linker as appropriate:
Next, just define your wrappers in a fashion similar to the previous article:
#include <stdio.h> void *__wrap_malloc(size_t size) { void *ret; ret = __real_malloc(size); fprintf(stderr, "m,%d,0x%8.8x\n", size, (unsigned int)ret); return ret; } void __wrap_free(void *ptr) { __real_free(ptr); fprintf(stderr, "f,,0x%8.8x\n", (unsigned int)ptr); return; } void *__wrap_realloc(void *ptr, size_t size) { void *ret = __real_realloc(ptr, size); fprintf(stderr, "f,,0x%8.8x\n", (unsigned int)ptr); fprintf(stderr, "m,%d,0x%8.8x\n", size, (unsigned int)ret); return ret; } void *__wrap_calloc(size_t nmemb, size_t size) { void *ret = __real_calloc(nmemb, size); fprintf(stderr, "c,%d,0x%8.8x\n", size*nmemb, (unsigned int)ret); return ret; }Now, I just ran the newly compiled program and directed stderr to a file, and then ran the malloc_analyze.py program as before.
Finally, we can produce something useful from this data to analyze our heap usage. First, it’s good to take a look at the overall heap usage over time (or in this case, over number of allocation calls). You can do this easily enough in a pylab session:
x = csv2rec('fetchorigin_analyzed.txt', names=('type','size','addr','total','count')) plot(x.total) xlabel('Number of allocations') ylabel('Heap Allocated (bytes)')Total Heap Usage
With this graph, you can now choose some points at which you’d like to visualize the heap usage and fragmentation. For this example, I chose three points: 400, 800 and 900. I wrote a short script to take the analyzed data and plot it as a bar, color-coded to based on how much space is in use at a given point in the memory space. The general idea is:
I wrote a simple script to do this. It’s certainly not very efficient, but it works just fine for small data sets that I was dealing with. The script needs to be adjusted for the start address and points in time at which to produce a graph.
import csv import sys import cPickle import numpy as N import matplotlib.pyplot as plt import matplotlib.cm as cm import matplotlib.colors as colors import time binsize = int(sys.argv[2]) fig = plt.figure() p = 1 for end in [400, 800, 900]: mem = csv.reader(open(sys.argv[1]), delimiter=',') ax = fig.add_subplot(9,1,p) p = p + 1 mmap = [] mmap.extend([0 for x in range(0,1024*160)]) mdata = [] for row in mem: mdata.append(row) for row in mdata[0:end]: size = long(row[1]) addr = long(row[2], 16) - 0x12c0010 if row[0] == 'm' or row[0] == 'c': for loc in range(addr, addr + size): mmap[loc] = 1 elif row[0] == 'f': for loc in range(addr, addr + abs(size)): mmap[loc] = 0 print str(len(mdata[0:end])) mmapbin = [] mmapbin.extend([0 for x in range(0,len(mmap) / binsize)]) for x in range(0, len(mmap)): mmapbin[x / binsize] = mmapbin[x / binsize] + mmap[x] patches = ax.bar(N.arange(len(mmapbin)), [1 for x in mmapbin], linewidth=0, width=1) fracs = [float(x) / binsize for x in mmapbin] norm = colors.normalize(0, max(fracs)) for thisfrac, thispatch in zip(fracs, patches): color = cm.jet(norm(thisfrac)) thispatch.set_facecolor(color) ax.set_yticks([0, 1]) ax.set_ylabel(str(end)) fig.show()And the result you get is a nice picture that can give you an intuitive view of how your heap is fragmented.
Visualization of the heap at three points in time
The graph could be cleaned up, but you can get a very good idea of what the heap looks like just from this graph. The x-axis units are in bin sizes, and could be converted to memory addresses to be more useful.