mirror of
https://github.com/DynamoRIO/dynamorio.git
synced 2026-10-12 02:02:04 +00:00
Updates all the "FIXME" comments in the repository to instead use "TODO" (for those about missing implementations: "NYI" or "ASSERT_NOT_IMPLEMENTED") or "XXX" (everything else). This matches our style guide which discourages "FIXME" as its connotations are too negative and too easily mis-interpreted by readers and in code audits to imply that the current state of things is broken in some way instead of just meaning something could be improved.
533 lines
20 KiB
Perl
Executable File
533 lines
20 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
|
|
# **********************************************************
|
|
# Copyright (c) 2005-2007 VMware, Inc. All rights reserved.
|
|
# **********************************************************
|
|
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions are met:
|
|
#
|
|
# * Redistributions of source code must retain the above copyright notice,
|
|
# this list of conditions and the following disclaimer.
|
|
#
|
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
|
# this list of conditions and the following disclaimer in the documentation
|
|
# and/or other materials provided with the distribution.
|
|
#
|
|
# * Neither the name of VMware, Inc. nor the names of its contributors may be
|
|
# used to endorse or promote products derived from this software without
|
|
# specific prior written permission.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
# ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE
|
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
# DAMAGE.
|
|
|
|
## bugtitle.pl
|
|
## by Derek Bruening
|
|
## March 2005
|
|
##
|
|
## produces a bug title from a forensic file
|
|
## uses address_query.pl and wld.pl as helpers
|
|
##
|
|
## by default does an explicit glob if input filename as a * in it
|
|
## (since we have users in shells and perls that don't glob!)
|
|
## -noglob disables that; -glob causes explicit glob of all input filenames
|
|
##
|
|
## if updated copy to \\10.1.5.11\QA-Shares\QA\tools
|
|
###########################################################################
|
|
## Examples of type of output:
|
|
##
|
|
## > bugtitle.pl bug_4106_dllhost/dllhost.exe.2964.00000000.html
|
|
## CRASH 7100d818 (21113 dllhost.exe) place_fragment:fcache.c(1476)
|
|
##
|
|
## > bugtitle.pl bug_3749_connon/CanoScan_N650U_N656U_CSUv571a.exe.3424.00000000.html
|
|
## VIOLATION NZHB.5166.B (21131 CanoScan_N650U_N656U_CSUv571a.exe) symcjit.dll ---> HEAP section
|
|
##
|
|
## > bugtitle.pl SmaService.exe.2104.00000000.xml
|
|
## VIOLATION NGSU.4493.B (30216 SmaService.exe) 0x7c2e4e8d (ADVAPI32.dll .text rx) => 0x0017b356 (heap rw)
|
|
##
|
|
## > bugtitle.pl codemod.exe.1416.00000000.xml
|
|
## VIOLATION QXMA.5800.A (custom codemod.exe) 0x004013ee (codemod.exe .text rx) => 0x0012ff60 (stack rw)
|
|
##
|
|
## > bugtitle.pl /work/studies/dgc/detectmode-nonativeexec/dotnet-serialization.exe/serialization.exe.136.00000172.xml
|
|
## VIOLATION QKNR.0769.C (custom serialization.exe) 0x791d721e (mscorwks.dll .text rx) => 0x7999cb28 (NULL|mscorlib.dll .text rx)
|
|
##
|
|
## > bugtitle.pl bug_4243_deadlock/inetinfo.exe.2020.00000000.html
|
|
## TIMEOUT (21129 inetinfo.exe)
|
|
##
|
|
## > bugtitle.pl sqlservr.exe.3048.00000000.xml
|
|
## OUT OF MEMORY (30118 sqlservr.exe) MB: 2047 RAM, 8 avail, 2169(^2215)/3940 commit
|
|
##
|
|
## > bugtitle.pl bug_3749_connon/build_21132/CanoScan_N650U_N656U_CSUv571a.exe.4064.00000000.html
|
|
## ASSERT (21132 CanoScan_N650U_N656U_CSUv571a.exe) win32/os.c:3263 is_native_thread_state_valid(trec->dcontext, (app_pc)cxt->Eip, (byte *)cxt->Esp)
|
|
##
|
|
###########################################################################
|
|
## Examples showing that type of slash doesn't matter (though backslashes
|
|
## must be doubled within cygwin):
|
|
##
|
|
## > bugtitle.pl \\\\10.1.5.10\\bugs\\bug_3978_w3wpcrash\\w3wp.exe.1124.00000000.html
|
|
## CRASH 7001588e (21102 w3wp.exe) vm_area_add_fragment:vmareas.c(4466)
|
|
##
|
|
## > bugtitle.pl //10.1.5.10/bugs/bug_3978_w3wpcrash/w3wp.exe.1124.00000000.html
|
|
## CRASH 7001588e (21102 w3wp.exe) vm_area_add_fragment:vmareas.c(4466)
|
|
##
|
|
###########################################################################
|
|
## Examples from cmd shell:
|
|
##
|
|
## C:\derek\dr\tools>perl bugtitle.pl \\10.1.5.10\bugs\bug_3978_w3wpcrash\w3wp.exe.1124.00000000.html
|
|
## CRASH 7001588e (21102 w3wp.exe) vm_area_add_fragment:vmareas.c(4466)
|
|
##
|
|
## c:\>perl c:/derek/dr/tools/bugtitle.pl \\10.1.5.10\bugs\bug_3749_connon\CanoScan_N650U_N656U_CSUv571a.exe.3424.00000000.html
|
|
## VIOLATION NZHB.5166.B (21131 CanoScan_N650U_N656U_CSUv571a.exe) symcjit.dll ---> HEAP section
|
|
###########################################################################
|
|
|
|
$tools = $ENV{'DYNAMORIO_TOOLS'};
|
|
if ($tools eq "") {
|
|
# use same dir this script sits in
|
|
$tools = $0;
|
|
if ($tools =~ /[\\\/]/) {
|
|
$tools =~ s/^(.+)[\\\/][\w\.]+$/\1/;
|
|
$tools =~ s/\\/\\\\/g;
|
|
} else {
|
|
$tools = "./";
|
|
}
|
|
# address_query needs DYNAMORIO_TOOLS set to find DRload.exe
|
|
$ENV{'DYNAMORIO_TOOLS'} = $tools;
|
|
}
|
|
# may not be on cygwin, so explicitly invoke perl
|
|
$addrquery = "perl $tools/address_query.pl";
|
|
$vioquery = "perl $tools/wld/wld.pl -security_violation";
|
|
|
|
# parameters
|
|
$usage = "Usage: $0 [-b <build_dir_base>] [-d <path-to-dynamorio.dll>] [-v] [-a] [-q] [-glob] [-noglob] <forensic_file>\n";
|
|
|
|
$verbose = 0;
|
|
$quiet = 0;
|
|
$DRdll = "";
|
|
$builddir = "";
|
|
$globall = 0;
|
|
$noglob = 0;
|
|
$analyze = 0;
|
|
|
|
while ($#ARGV >= 0) {
|
|
if ($ARGV[0] eq '-v') {
|
|
$verbose = 1;
|
|
} elsif ($ARGV[0] eq '-q') {
|
|
$quiet = 1;
|
|
} elsif ($ARGV[0] eq '-a') {
|
|
$analyze = 1;
|
|
} elsif ($ARGV[0] eq '-glob') {
|
|
$globall = 1;
|
|
} elsif ($ARGV[0] eq '-noglob') {
|
|
$noglob = 1;
|
|
} elsif ($ARGV[0] eq '-b') {
|
|
die $usage if ($#ARGV <= 0);
|
|
shift;
|
|
$builddir = $ARGV[0];
|
|
$builddir =~ s|\\|/|g; # normalize
|
|
unless (-d "$builddir") {
|
|
die "$err No directory $builddir\n";
|
|
}
|
|
} elsif ($ARGV[0] eq '-d') {
|
|
die $usage if ($#ARGV <= 0);
|
|
shift;
|
|
$DRdll = $ARGV[0];
|
|
$DRdll =~ s|\\|/|g; # normalize
|
|
unless (-f "$DRdll") {
|
|
die "$err No file $DRdll\n";
|
|
}
|
|
} elsif ($ARGV[0] =~ /^-/) {
|
|
die $usage;
|
|
} else {
|
|
# rest should be forensic file names
|
|
last;
|
|
}
|
|
shift;
|
|
}
|
|
|
|
die $usage if ($#ARGV < 0);
|
|
$multiple = ($#ARGV > 0);
|
|
while ($#ARGV >= 0) {
|
|
my $filearg = $ARGV[0];
|
|
# make it easy for users w/ non-globbing shell and non-globbing perl to
|
|
# pass *, w/o double-globbing and messing up escaped chars for other users
|
|
if (!$noglob && ($globall || $filearg =~ /\*/)) {
|
|
# XXX: must convert from \ to / BEFORE the glob -- yet don't
|
|
# want to ruin escaped chars! It's a tradeoff: is \* a directory delimiter
|
|
# followed by metachar *, or is it an escaped * trying to be literal?
|
|
# In everyday usage we assume no escaped *'s!
|
|
# If we didn't care for \* directory delim we might do:
|
|
# $filearg =~ s|\\\\|//|g; # next rule won't get both slashes so need this rule
|
|
# $filearg =~ s|\\([\w\d])|/\1|g; # \ to / only if before a normal char
|
|
$filearg =~ s|\\|/|g; # assume \ is dir delim, no support for \ as escape char
|
|
@files = glob($filearg);
|
|
print "globbing: \"$filearg\" => \"@files\"\n" if ($verbose);
|
|
if ($#files < 0) {
|
|
# if glob comes up empty, don't use its results (to get error msg)
|
|
@files = ($filearg);
|
|
}
|
|
} else {
|
|
@files = ($filearg);
|
|
}
|
|
$multiple = $multiple || $#files > 0;
|
|
foreach $file (@files) {
|
|
print "processing \"$file\"\n" if ($verbose);
|
|
$file =~ s|\\|/|g; # normalize
|
|
unless (-f "$file") {
|
|
die "Error: No forensic file $file\n";
|
|
}
|
|
if ($multiple) {
|
|
print "\n$file:\n";
|
|
}
|
|
process_file($file);
|
|
}
|
|
shift;
|
|
}
|
|
|
|
sub process_file($) {
|
|
my ($file) = @_;
|
|
my $prefix = "<unknown type>";
|
|
my $suffix = ""; # ok to be empty
|
|
my $build_num = "<unknown build>";
|
|
my $app = "<unknown app>";
|
|
|
|
open(IN, "< $file") || die "Error: couldn't open $file\n";
|
|
while (<IN>) {
|
|
# Handle CR
|
|
s/\r//;
|
|
# Type of bug
|
|
if (/^Execution security violation/) {
|
|
$prefix = "VIOLATION";
|
|
if ($file =~ /\.html/) {
|
|
# use wld for html files
|
|
$vioinfo = `$vioquery $file`;
|
|
# example: Security violation detected from symcjit.dll ---> HEAP section
|
|
$vioinfo =~ /Security violation detected from (.+)/m;
|
|
$suffix = $1;
|
|
# wld.pl likes to put extra spaces in!
|
|
$suffix =~ s/(\s)\s+/\1/g;
|
|
$suffix =~ s/^\s+//;
|
|
} # else we hit the source and target-properties below
|
|
}
|
|
elsif (/Threat ID:\s*([^\s\<]+)/) {
|
|
$threat = $1;
|
|
$prefix .= " $threat";
|
|
if ($threat =~ /c0000017/) {
|
|
$prefix .= " V";
|
|
}
|
|
elsif ($threat =~ /c0000012d/) {
|
|
$prefix .= " P";
|
|
}
|
|
}
|
|
elsif (/<dll\s+range=\"0x(\w+)-0x(\w+)\"\s*name=\"([^\"]+)\"/) {
|
|
$dll_name[$num_dlls] = $3;
|
|
$dll_start[$num_dlls] = hex($1);
|
|
$dll_end[$num_dlls] = hex($2);
|
|
$num_dlls++;
|
|
}
|
|
elsif (/<source-properties/) {
|
|
# for hot patch violations, source isn't relevant; see case 7686
|
|
if (!($threat =~ /[PH]$/)) {
|
|
$suffix = &address_properties();
|
|
}
|
|
}
|
|
elsif (/<target-properties/) {
|
|
# for hot patch violations, target isn't relevant; see case 7686
|
|
if (!($threat =~ /[PH]$/)) {
|
|
$suffix .= " => " . &address_properties();
|
|
}
|
|
}
|
|
elsif (/^Unrecoverable error at PC 0x([0-9A-Za-z]+)/) {
|
|
# w/ multiple files, need local here so we look at each
|
|
# crash separately
|
|
my $symdll;
|
|
$addr = $1;
|
|
if ($addr =~ /^15/) {
|
|
$lib = "debug";
|
|
} else {
|
|
$lib = "release";
|
|
}
|
|
if ($DRdll eq "") {
|
|
$symdll = &findDRdll($builddir, $build_num, $lib);
|
|
} else {
|
|
# if dr dll passed to us, use it for every file
|
|
$symdll = $DRdll;
|
|
}
|
|
$prefix = "CRASH $addr";
|
|
$suffix = "[error acquiring line number]";
|
|
if ($symdll ne "") {
|
|
my $query = "$addrquery";
|
|
$query .= " -raw" if ($verbose);
|
|
print "invoking \"$query $symdll $addr\"\n" if ($verbose);
|
|
$sym = `$query $symdll $addr`;
|
|
print "addrquery returned: $sym\n" if ($verbose);
|
|
if ($sym =~ m|([\w\./]+\(\d+\))|m) {
|
|
$line = $1;
|
|
$sym =~ /dynamorio!(.+)\+/m;
|
|
$func = $1;
|
|
$suffix = "$func:$line";
|
|
} else {
|
|
print "Unable to find address in $symdll\n";
|
|
# We found the dll, but couldn't find the address.
|
|
# Is likely an exception in generated code.
|
|
$suffix = "<exception in generated code>";
|
|
}
|
|
} else {
|
|
print "Error locating dynamorio.dll $build_num\n";
|
|
}
|
|
}
|
|
elsif (/^Internal SecureCore Error: (.*)/) {
|
|
$prefix = "ASSERT";
|
|
$suffix = $1;
|
|
}
|
|
elsif (/^CURIOSITY : (.*)/) {
|
|
$prefix = "CURIOSITY";
|
|
$suffix = $1;
|
|
}
|
|
elsif (/^Timeout expired/) {
|
|
$prefix = "TIMEOUT";
|
|
}
|
|
elsif (/^Out of memory/) {
|
|
$prefix = "OUT OF MEMORY";
|
|
}
|
|
elsif (($analyze || $prefix =~ /MEMORY/) && /<basic-information>/) {
|
|
$_ = <IN>;
|
|
/\d+ \d+ \d+ (\d+) \d+ \d+ \d+/;
|
|
$ram = $1 * 4/1024;
|
|
$suffix .= sprintf("%u RAM, ", $ram);
|
|
}
|
|
elsif (($analyze || $prefix =~ /MEMORY/) && /num_threads:/) {
|
|
/num_threads: (\d+)/;
|
|
$ThreadCount = $1;
|
|
$suffix .= sprintf(", %d Thr", $ThreadCount);
|
|
if ($ThreadCount > 1000) {
|
|
$suffix .= "ead PILE!";
|
|
}
|
|
}
|
|
elsif (($analyze || $prefix =~ /MEMORY/) && /<vm-counters>/) {
|
|
$_ = <IN>;
|
|
($PeakVirtualSize,
|
|
$VirtualSize,
|
|
$PageFaultCount,
|
|
$PeakWorkingSetSize,
|
|
$WorkingSetSize,
|
|
$QuotaPeakPagedPoolUsage,
|
|
$QuotaPagedPoolUsage)
|
|
= split / /, $_;
|
|
|
|
$_ = <IN>;
|
|
($QuotaPeakNonPagedPoolUsage,
|
|
$QuotaNonPagedPoolUsage,
|
|
$PagefileUsage,
|
|
$PeakPagefileUsage)
|
|
= split / /, $_;
|
|
|
|
# matching drview names (e.g. PagefileUsage is Priv) */
|
|
print "KB: " .
|
|
$PeakVirtualSize/1024 . " PVSz," .
|
|
$VirtualSize/1024 . " VSz," .
|
|
$PeakPagefileUsage/1024 . " PPriv," .
|
|
$PagefileUsage/1024 . " Priv," .
|
|
$PeakWorkingSetSize/1024 . " PWSS," .
|
|
$WorkingSetSize/1024 . " WSS," .
|
|
$PageFaultCount/1 . " Fault," .
|
|
$QuotaPeakPagedPoolUsage/1024 . " PPage," .
|
|
$QuotaPagedPoolUsage/1024 . " Page," .
|
|
$QuotaPeakNonPagedPoolUsage/1024 . " PNonP," .
|
|
$QuotaNonPagedPoolUsage/1024 . " NonP" .
|
|
"\n" if ($verbose);
|
|
|
|
# note that pre 4.3 core writes these counters as %d (case 10481)
|
|
# whlie we want to convert them to uint's here
|
|
if ($VirtualSize < 0) {
|
|
$VirtualSize += 0x100000000; # 2^32
|
|
}
|
|
if ($PagefileUsage < 0) {
|
|
$PagefileUsage += 0x100000000; # 2^32
|
|
}
|
|
if ($PeakWorkingSetSize < 0) {
|
|
$PeakWorkingSetSize += 0x100000000; # 2^32
|
|
}
|
|
|
|
# all in MB
|
|
$suffix .= sprintf("MB: %u VSz, %u Priv, %u PWSS; ",
|
|
$VirtualSize/1024/1024,
|
|
$PagefileUsage/1024/1024,
|
|
$PeakWorkingSetSize/1024/1024);
|
|
}
|
|
elsif (($analyze || $prefix =~ /MEMORY/) && /<performance-information>/) {
|
|
# skip 1st line
|
|
<IN>;
|
|
# this line has what we want
|
|
$_ = <IN>;
|
|
/-?\d+ -?\d+ -?\d+ (\d+) (\d+) (\d+) (\d+)/;
|
|
# don't expect these to be negative
|
|
$avail = $1 * 4/1024;
|
|
$commit = $2 * 4/1024;
|
|
$limit = $3 * 4/1024;
|
|
$peak = $4 * 4/1024;
|
|
$suffix .= sprintf("%u avail, %u(^%u)/%u commit",
|
|
$avail, $commit, $peak, $limit);
|
|
}
|
|
|
|
# Build version
|
|
elsif (/^Generated by SecureCore [^,]+,\s*(.+)/) {
|
|
$build_string = $1;
|
|
if ($build_string =~ /build ([0-9]+)/) {
|
|
$build_num = $1;
|
|
} else {
|
|
# XXX: grab path from reg keys and try that path on local host?
|
|
$build_num = "custom";
|
|
}
|
|
|
|
}
|
|
|
|
# Process Name
|
|
#
|
|
# violation
|
|
elsif (/^Short[\s\-]Qualified[\s\-]Name[:=]\s*\"?([^\"\n]+)\"?/i) {
|
|
$app = $1; # short qualified name
|
|
}
|
|
# crash
|
|
elsif (/^\s*Name\s?=\s*\"?([^\"\n]+)\"?/i) {
|
|
$app = $1; # full qualified name
|
|
$app =~ s/.*[\\\/]//; # remove path
|
|
}
|
|
# 2.1 compatibility, let better name finding (above) override since we make
|
|
# assumptions (that may not always hold) about name mangling here
|
|
elsif ($app =~ /^<unknown app>$/) {
|
|
if (/^Command Line:\s*(.+)/) {
|
|
$app = $1; # full cmdline
|
|
if ($app !~ /svchost.exe/) {
|
|
# remove args
|
|
$app =~ s/(\.exe)\W+.*$/\1/;
|
|
# remove quotes
|
|
$app =~ s/\"//g;
|
|
}
|
|
$app =~ s/.*[\\\/]//; # remove path
|
|
}
|
|
}
|
|
}
|
|
close(IN);
|
|
|
|
print "$prefix ($build_num $app) $suffix\n";
|
|
}
|
|
|
|
sub findDRdll($,$,$) {
|
|
my ($builddir, $build_num, $lib) = @_;
|
|
# would be nice to use symbol server, but cannot locate
|
|
# based solely on build number w/o querying every dll, or having
|
|
# a symlink set up externally or something.
|
|
my @try = ( "//10.1.5.15/nightly",
|
|
"//10.1.5.15/nightly_archive" );
|
|
if ($builddir ne "") {
|
|
unshift @try, $builddir;
|
|
}
|
|
print "searching these bases: @try\n" if ($verbose);
|
|
# match ver_2_1, ver_2_5, etc., as well as the new dist
|
|
# we avoid {ver*,dist} since that gives two entries regardless of existence
|
|
my $ver = "[vd][ei][rs]*";
|
|
my $missed_at_all = 0;
|
|
foreach $base (@try) {
|
|
my $glob_path = "$base/$build_num/$ver/lib/$lib/dynamorio.dll";
|
|
my @wildcard = glob($glob_path);
|
|
if (@wildcard == 0) {
|
|
print STDERR "couldn't find $glob_path\n" if (!$quiet);
|
|
$missed_at_all = 1;
|
|
}
|
|
foreach $w (@wildcard) {
|
|
print "looking for $w\n" if ($verbose);
|
|
if (-f $w) {
|
|
# avoid found message if did it 1st try
|
|
print STDERR "found $w\n" if (!$quiet && $missed_at_all);
|
|
return $w;
|
|
}
|
|
print STDERR "couldn't find $w\n" if (!$quiet);
|
|
$missed_at_all = 1;
|
|
}
|
|
}
|
|
return "";
|
|
}
|
|
|
|
sub unixpath2win32($) {
|
|
my ($p) = @_;
|
|
# use cygpath if available, it will convert /home to c:\cygwin\home, etc.
|
|
$cp = `cygpath -wi \"$p\"`;
|
|
chomp $cp;
|
|
if ($cp eq "") {
|
|
# do it by hand
|
|
# add support for /x => x:
|
|
$p =~ s|^/([a-z])/|\1:/|;
|
|
# forward slash becomes backslash since going through another shell
|
|
$p =~ s|/|\\|g;
|
|
} else {
|
|
$p = $cp;
|
|
}
|
|
# make single backslashes doubles
|
|
$p =~ s|\\{1}|\\\\|g;
|
|
return $p;
|
|
}
|
|
|
|
# examples:
|
|
# 0x04932af4 (stack rx)
|
|
# 0x003b2f76 (heap rw)
|
|
# 0x79b99773 (NULL|mscorlib.dll .data rwx)"
|
|
sub address_properties() {
|
|
my $address = "";
|
|
my $module = "";
|
|
my $section = "";
|
|
my $protect = "";
|
|
my $type = "";
|
|
while (<IN>) {
|
|
# Handle CR
|
|
s/\r//;
|
|
if (/address=.*\"([^\"]+)\"/) {
|
|
$address = $1;
|
|
} elsif (/module=.*\"([^\"]+)\"/) {
|
|
$module = $1;
|
|
} elsif (/sec_name=.*\"([^\"]+)\"/) {
|
|
$section = $1;
|
|
} elsif (/State=.* FREE/) {
|
|
$protect = 'free';
|
|
} elsif ($protect ne 'free' && /Protect=.*\"\w+ ([^\"]+)\"/) {
|
|
$protect = $1;
|
|
$protect =~ s/-//g;
|
|
} elsif (/Type=.*\"\w+ ([^\"]+)\"/) {
|
|
$type = $1;
|
|
if ($type =~ /IMAGE/i) {
|
|
# if no export name get file name from module list
|
|
if ($module =~ /\(none\)/) {
|
|
# brute force
|
|
# XXX: use nice interval data structure
|
|
$address =~ /0x(\w+)/;
|
|
my $addrval = hex($1);
|
|
for ($i=0; $i<$num_dlls; $i++) {
|
|
if ($addrval >= $dll_start[$i] &&
|
|
$addrval < $dll_end[$i]) {
|
|
$module = "NULL|" . $dll_name[$i];
|
|
}
|
|
}
|
|
}
|
|
$module .= " $section";
|
|
} else {
|
|
if ($threat =~ /\.A$/) {
|
|
$module = "stack";
|
|
} else {
|
|
$module = "heap";
|
|
}
|
|
}
|
|
# we assume we'll see a Type line else we'll loop to the end!
|
|
last;
|
|
}
|
|
}
|
|
return "$address ($module $protect)";
|
|
}
|