# A script for analyzing the output of NPSPY and merging data about streams. | |
import sys | |
def ReadFile(filename, flags='rb'): | |
"""Returns the contents of a file.""" | |
file = open(filename, flags) | |
result = file.read() | |
file.close() | |
return result | |
def WriteFile(filename, contents): | |
"""Overwrites the file with the given contents.""" | |
file = open(filename, 'w') | |
file.write(contents) | |
file.close() | |
# sample line: 'NPP_NewStream(0x645c898, 0x56ba900("application/x-shockwave-flash"), 0x64bb3b0 (http://weeklyad.target.com/target/flash/target/target.swf?ver=090326), TRUE, NP_NORMAL)' | |
class Stream: | |
def __init__(self, line): | |
split = line.split(', ') | |
self.mime_type = split[1].split('"')[1] | |
self.url = split[2].split(' ')[1].strip('()') | |
self.seekable = split[3] | |
self.type = split[4].strip(')') | |
self.size = 0 | |
self.status = '' | |
try: | |
self.address = split[2].split(' ')[0] | |
except: | |
print 'parsing error on ' + line | |
self.address = '' | |
if self.type != 'NP_NORMAL': | |
print 'line got unexpected type: ' + line | |
def main(argv=None): | |
if argv is None: | |
argv = sys.argv | |
streams = [] | |
if len(argv) != 2: | |
print 'need filename' | |
return | |
file = ReadFile(argv[1]) | |
for line in file.splitlines(): | |
if line.startswith('NPP_NewStream('): | |
if line.count('(') < 3: | |
print 'unknown format for line: ' + line | |
continue | |
s = Stream(line) | |
streams.append(s) | |
elif line.startswith('NPP_Write('): | |
# sample: NPP_Write(0x645c898, 0x64bb3b0, 0, 16384, 0x56c1000("CW"))) | |
split = line.split(', ') | |
address = split[1] | |
start = int(split[2]) | |
size = int(split[3]) | |
found = False | |
for stream in streams: | |
if stream.address == address: | |
if stream.size != start: | |
print 'error: starting at wrong place for write ' + stream.url + ' ' + str(stream.size) + ' ' + str(start) | |
stream.size += size | |
found = True | |
break | |
if not found: | |
print "couldn't find stream to match NPP_Write " + line | |
elif line.startswith('NPP_DestroyStream('): | |
# sample: NPP_DestroyStream(0x645c898, 0x64bb3b0, NPRES_DONE) | |
split = line.split(', ') | |
address = split[1] | |
status = split[2].strip(')') | |
found = False | |
for stream in streams: | |
if stream.address == address: | |
stream.status = status | |
stream.address = '' # address can be reused | |
found = True | |
break | |
if not found: | |
print "couldn't find stream to match NPP_DestroyStream " + line | |
output = [] | |
for stream in streams: | |
if stream.status != 'NPRES_DONE': | |
print 'error: no NPP_DestroyStream with success for ' + stream.url + ' ' + stream.status + '.' | |
output.append(', '.join([stream.url, stream.mime_type, str(stream.size), stream.seekable])) | |
output_file = argv[1].replace('.', '_analyzed.') | |
WriteFile(output_file, '\n'.join(output)) | |
if __name__ == "__main__": | |
sys.exit(main()) |