1cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// Copyright (c) 2010 Google Inc.
2cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// All rights reserved.
3cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org//
4cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// Redistribution and use in source and binary forms, with or without
5cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// modification, are permitted provided that the following conditions are
6cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// met:
7cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org//
8cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org//     * Redistributions of source code must retain the above copyright
9cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// notice, this list of conditions and the following disclaimer.
10cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org//     * Redistributions in binary form must reproduce the above
11cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// copyright notice, this list of conditions and the following disclaimer
12cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// in the documentation and/or other materials provided with the
13cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// distribution.
14cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org//     * Neither the name of Google Inc. nor the names of its
15cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// contributors may be used to endorse or promote products derived from
16cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// this software without specific prior written permission.
17cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org//
18cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org
30cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// exploitability_win.cc: Windows specific exploitability engine.
31cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org//
32cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// Provides a guess at the exploitability of the crash for the Windows
33cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// platform given a minidump and process_state.
34cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org//
35cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// Author: Cris Neckar
36cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org
372b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org#include <vector>
382b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
39cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org#include "processor/exploitability_win.h"
40cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org
412cc15ba4327831f917ff55b87e6d5fc3c7750085ted.mielczarek@gmail.com#include "common/scoped_ptr.h"
42cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org#include "google_breakpad/common/minidump_exception_win32.h"
432b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org#include "google_breakpad/processor/minidump.h"
442b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org#include "processor/disassembler_x86.h"
45cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org#include "processor/logging.h"
46cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org
472b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org#include "third_party/libdisasm/libdis.h"
482b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
49cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.orgnamespace google_breakpad {
50cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org
51cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// The cutoff that we use to judge if and address is likely an offset
522b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org// from various interesting addresses.
536162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comstatic const uint64_t kProbableNullOffset = 4096;
546162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comstatic const uint64_t kProbableStackOffset = 8192;
55cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org
56cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// The various cutoffs for the different ratings.
572b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.orgstatic const size_t kHighCutoff        = 100;
582b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.orgstatic const size_t kMediumCutoff      = 80;
592b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.orgstatic const size_t kLowCutoff         = 50;
60cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.orgstatic const size_t kInterestingCutoff = 25;
61cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org
62cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org// Predefined incremental values for conditional weighting.
63cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.orgstatic const size_t kTinyBump          = 5;
64cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.orgstatic const size_t kSmallBump         = 20;
65cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.orgstatic const size_t kMediumBump        = 50;
66cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.orgstatic const size_t kLargeBump         = 70;
67cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.orgstatic const size_t kHugeBump          = 90;
68cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org
692b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org// The maximum number of bytes to disassemble past the program counter.
702b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.orgstatic const size_t kDisassembleBytesBeyondPC = 2048;
712b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
72cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.orgExploitabilityWin::ExploitabilityWin(Minidump *dump,
73cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org                                     ProcessState *process_state)
74cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    : Exploitability(dump, process_state) { }
75cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org
76cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.orgExploitabilityRating ExploitabilityWin::CheckPlatformExploitability() {
77cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org  MinidumpException *exception = dump_->GetException();
782b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org  if (!exception) {
792b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org    BPLOG(INFO) << "Minidump does not have exception record.";
80cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    return EXPLOITABILITY_ERR_PROCESSING;
812b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org  }
82cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org
83cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org  const MDRawExceptionStream *raw_exception = exception->exception();
842b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org  if (!raw_exception) {
852b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org    BPLOG(INFO) << "Could not obtain raw exception info.";
86cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    return EXPLOITABILITY_ERR_PROCESSING;
872b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org  }
88cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org
892b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org  const MinidumpContext *context = exception->GetContext();
902b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org  if (!context) {
912b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org    BPLOG(INFO) << "Could not obtain exception context.";
922b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org    return EXPLOITABILITY_ERR_PROCESSING;
932b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org  }
942b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
952b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org  MinidumpMemoryList *memory_list = dump_->GetMemoryList();
962b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org  bool memory_available = true;
972b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org  if (!memory_list) {
982b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org    BPLOG(INFO) << "Minidump memory segments not available.";
992b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org    memory_available = false;
1002b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org  }
1016162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint64_t address = process_state_->crash_address();
1026162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t exception_code = raw_exception->exception_record.exception_code;
103cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org
1046162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint32_t exploitability_weight = 0;
105cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org
1066162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint64_t stack_ptr = 0;
1076162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint64_t instruction_ptr = 0;
1082b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
1092b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org  switch (context->GetContextCPU()) {
1102b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org    case MD_CONTEXT_X86:
1112b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org      stack_ptr = context->GetContextX86()->esp;
1122b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org      instruction_ptr = context->GetContextX86()->eip;
1132b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org      break;
1142b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org    case MD_CONTEXT_AMD64:
1152b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org      stack_ptr = context->GetContextAMD64()->rsp;
1162b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org      instruction_ptr = context->GetContextAMD64()->rip;
1172b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org      break;
1182b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org    default:
1192b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org      BPLOG(INFO) << "Unsupported architecture.";
1202b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org      return EXPLOITABILITY_ERR_PROCESSING;
1212b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org  }
1222b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
1232b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org  // Check if we are executing on the stack.
1242b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org  if (instruction_ptr <= (stack_ptr + kProbableStackOffset) &&
1252b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org      instruction_ptr >= (stack_ptr - kProbableStackOffset))
1262b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org    exploitability_weight += kHugeBump;
1272b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
128cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org  switch (exception_code) {
129cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    // This is almost certainly recursion.
130cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    case MD_EXCEPTION_CODE_WIN_STACK_OVERFLOW:
131cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org      exploitability_weight += kTinyBump;
132cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org      break;
133cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org
134cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    // These exceptions tend to be benign and we can generally ignore them.
135cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    case MD_EXCEPTION_CODE_WIN_INTEGER_DIVIDE_BY_ZERO:
136cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    case MD_EXCEPTION_CODE_WIN_INTEGER_OVERFLOW:
137cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    case MD_EXCEPTION_CODE_WIN_FLOAT_DIVIDE_BY_ZERO:
138cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    case MD_EXCEPTION_CODE_WIN_FLOAT_INEXACT_RESULT:
139cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    case MD_EXCEPTION_CODE_WIN_FLOAT_OVERFLOW:
140cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    case MD_EXCEPTION_CODE_WIN_FLOAT_UNDERFLOW:
141cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    case MD_EXCEPTION_CODE_WIN_IN_PAGE_ERROR:
142cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org      exploitability_weight += kTinyBump;
143cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org      break;
144cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org
145cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    // These exceptions will typically mean that we have jumped where we
146cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    // shouldn't.
147cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    case MD_EXCEPTION_CODE_WIN_ILLEGAL_INSTRUCTION:
148cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    case MD_EXCEPTION_CODE_WIN_FLOAT_INVALID_OPERATION:
149cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    case MD_EXCEPTION_CODE_WIN_PRIVILEGED_INSTRUCTION:
150cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org      exploitability_weight += kLargeBump;
151cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org      break;
152cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org
153cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    // These represent bugs in exception handlers.
154cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    case MD_EXCEPTION_CODE_WIN_INVALID_DISPOSITION:
155cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    case MD_EXCEPTION_CODE_WIN_NONCONTINUABLE_EXCEPTION:
156cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org      exploitability_weight += kSmallBump;
157cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org      break;
158cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org
159cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    case MD_EXCEPTION_CODE_WIN_HEAP_CORRUPTION:
160cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    case MD_EXCEPTION_CODE_WIN_STACK_BUFFER_OVERRUN:
161cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org      exploitability_weight += kHugeBump;
162cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org      break;
163cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org
164cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    case MD_EXCEPTION_CODE_WIN_GUARD_PAGE_VIOLATION:
165cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org      exploitability_weight += kLargeBump;
166cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org      break;
167cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org
168cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    case MD_EXCEPTION_CODE_WIN_ACCESS_VIOLATION:
169cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org      bool near_null = (address <= kProbableNullOffset);
1702b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org      bool bad_read = false;
1712b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org      bool bad_write = false;
172cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org      if (raw_exception->exception_record.number_parameters >= 1) {
173cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org        MDAccessViolationTypeWin av_type =
174cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org            static_cast<MDAccessViolationTypeWin>
175cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org            (raw_exception->exception_record.exception_information[0]);
176cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org        switch (av_type) {
177cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org          case MD_ACCESS_VIOLATION_WIN_READ:
1782b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org            bad_read = true;
179cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org            if (near_null)
180cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org              exploitability_weight += kSmallBump;
181cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org            else
182cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org              exploitability_weight += kMediumBump;
183cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org            break;
184cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org          case MD_ACCESS_VIOLATION_WIN_WRITE:
1852b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org            bad_write = true;
186cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org            if (near_null)
187cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org              exploitability_weight += kSmallBump;
188cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org            else
189cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org              exploitability_weight += kHugeBump;
190cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org            break;
191cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org          case MD_ACCESS_VIOLATION_WIN_EXEC:
192cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org            if (near_null)
193cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org              exploitability_weight += kSmallBump;
194cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org            else
195cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org              exploitability_weight += kHugeBump;
196cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org            break;
197cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org          default:
1982b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org            BPLOG(INFO) << "Unrecognized access violation type.";
199cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org            return EXPLOITABILITY_ERR_PROCESSING;
200cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org            break;
201cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org        }
2022b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        MinidumpMemoryRegion *instruction_region = 0;
2038b2e6865e54d52fcd45514e12e90ee425b82cb52cdn@chromium.org        if (memory_available) {
2048b2e6865e54d52fcd45514e12e90ee425b82cb52cdn@chromium.org          instruction_region =
2058b2e6865e54d52fcd45514e12e90ee425b82cb52cdn@chromium.org              memory_list->GetMemoryRegionForAddress(instruction_ptr);
2068b2e6865e54d52fcd45514e12e90ee425b82cb52cdn@chromium.org        }
2072b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        if (!near_null && instruction_region &&
2082b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org            context->GetContextCPU() == MD_CONTEXT_X86 &&
2092b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org            (bad_read || bad_write)) {
2102b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org          // Perform checks related to memory around instruction pointer.
2116162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com          uint32_t memory_offset =
2128b2e6865e54d52fcd45514e12e90ee425b82cb52cdn@chromium.org              instruction_ptr - instruction_region->GetBase();
2136162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com          uint32_t available_memory =
2148b2e6865e54d52fcd45514e12e90ee425b82cb52cdn@chromium.org              instruction_region->GetSize() - memory_offset;
2152b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org          available_memory = available_memory > kDisassembleBytesBeyondPC ?
2162b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org              kDisassembleBytesBeyondPC : available_memory;
2172b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org          if (available_memory) {
2186162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com            const uint8_t *raw_memory =
2198b2e6865e54d52fcd45514e12e90ee425b82cb52cdn@chromium.org                instruction_region->GetMemory() + memory_offset;
2208b2e6865e54d52fcd45514e12e90ee425b82cb52cdn@chromium.org            DisassemblerX86 disassembler(raw_memory,
2218b2e6865e54d52fcd45514e12e90ee425b82cb52cdn@chromium.org                                         available_memory,
2228b2e6865e54d52fcd45514e12e90ee425b82cb52cdn@chromium.org                                         instruction_ptr);
2232b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org            disassembler.NextInstruction();
2242b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org            if (bad_read)
2252b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org              disassembler.setBadRead();
2262b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org            else
2272b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org              disassembler.setBadWrite();
2282b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org            if (disassembler.currentInstructionValid()) {
2292b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org              // Check if the faulting instruction falls into one of
2302b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org              // several interesting groups.
2312b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org              switch (disassembler.currentInstructionGroup()) {
2322b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                case libdis::insn_controlflow:
2332b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                  exploitability_weight += kLargeBump;
2342b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                  break;
2352b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                case libdis::insn_string:
2362b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                  exploitability_weight += kHugeBump;
2372b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                  break;
238361f24eac7fb452a795709479fc48fd59b04bc1fSiyangXie@gmail.com                default:
239361f24eac7fb452a795709479fc48fd59b04bc1fSiyangXie@gmail.com                  break;
2402b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org              }
2412b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org              // Loop the disassembler through the code and check if it
2422b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org              // IDed any interesting conditions in the near future.
2432b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org              // Multiple flags may be set so treat each equally.
2442b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org              while (disassembler.NextInstruction() &&
2452b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                     disassembler.currentInstructionValid() &&
2462b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                     !disassembler.endOfBlock())
2472b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                continue;
2482b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org              if (disassembler.flags() & DISX86_BAD_BRANCH_TARGET)
2492b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                exploitability_weight += kLargeBump;
2502b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org              if (disassembler.flags() & DISX86_BAD_ARGUMENT_PASSED)
2512b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                exploitability_weight += kTinyBump;
2522b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org              if (disassembler.flags() & DISX86_BAD_WRITE)
2532b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                exploitability_weight += kMediumBump;
2542b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org              if (disassembler.flags() & DISX86_BAD_BLOCK_WRITE)
2552b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                exploitability_weight += kMediumBump;
2562b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org              if (disassembler.flags() & DISX86_BAD_READ)
2572b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                exploitability_weight += kTinyBump;
2582b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org              if (disassembler.flags() & DISX86_BAD_BLOCK_READ)
2592b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                exploitability_weight += kTinyBump;
2602b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org              if (disassembler.flags() & DISX86_BAD_COMPARISON)
2612b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org                exploitability_weight += kTinyBump;
2622b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org            }
2632b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org          }
2642b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        }
2658b2e6865e54d52fcd45514e12e90ee425b82cb52cdn@chromium.org        if (!near_null && AddressIsAscii(address))
2668b2e6865e54d52fcd45514e12e90ee425b82cb52cdn@chromium.org          exploitability_weight += kMediumBump;
267cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org      } else {
2682b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org        BPLOG(INFO) << "Access violation type parameter missing.";
269cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org        return EXPLOITABILITY_ERR_PROCESSING;
270cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org      }
271cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org  }
272cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org
273cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org  // Based on the calculated weight we return a simplified classification.
2742b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org  BPLOG(INFO) << "Calculated exploitability weight: " << exploitability_weight;
2752b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org  if (exploitability_weight >= kHighCutoff)
276cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    return EXPLOITABILITY_HIGH;
2772b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org  if (exploitability_weight >= kMediumCutoff)
278cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    return EXPLOITABLITY_MEDIUM;
2792b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org  if (exploitability_weight >= kLowCutoff)
280cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    return EXPLOITABILITY_LOW;
2812b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org  if (exploitability_weight >= kInterestingCutoff)
282cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org    return EXPLOITABILITY_INTERESTING;
283cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org
284cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org  return EXPLOITABILITY_NONE;
285cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org}
286cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org
287cec12872c403314261e151cf2fa4505ae1affaf6cdn@chromium.org}  // namespace google_breakpad
288