Professional Documents
Culture Documents
2018 - Automatic Heap Layout Manipulation For Exploitation PDF
2018 - Automatic Heap Layout Manipulation For Exploitation PDF
Over the past decade several researchers [5, 7, 9, 16] The order and contiguity of storage allocated
have addressed the problem of automatic exploit genera- by successive calls to the calloc, malloc, and
tion (AEG) for stack-based buffer overflows. These pa- realloc functions is unspecified.
pers describe algorithms for automatically producing a
control-flow hijacking exploit, under the assumption that 1 Henceforth,when we refer to the ‘source’ and ‘destination’ we
an input is provided, or discovered, that results in the mean the source or destination buffer of the overflow or underflow.
1
1 typedef struct {
2 DisplayFn display;
3 char *n;
4 unsigned *id
5 } User;
6
2
display field of the User object. The control flow of the
application can then be hijacked by calling the display
function with the corrupted User object as an argument.
1.2 Contributions
Our contributions are as follows:
1. An analysis of the heap layout manipulation prob- Figure 2: The challenges in achieving a particular layout
lem as a standalone task within the context of auto- vary depending on whether the allocator behaves deter-
matic exploit generation, outlining its essential as- ministically or non-deterministically and whether or not
pects and describing the factors which influence its the starting state of the heap is known.
complexity.
2. SIEVE3 , an open source framework for construct-
ing benchmarks for heap layout manipulation and as the manipulation and exploitation of those allocators
evaluating algorithms. when embedded in applications [3, 19, 26].
3. A pseudo-random black box search algorithm for The process is complicated by the fact that – when
heap layout manipulation. Using SIEVE, we evalu- constructing an exploit – one cannot directly interact
ate the effectiveness of this algorithm on three real- with the allocator, but instead must use the API exposed
world allocators, namely dlmalloc, avrlibc and by the target program. Manipulating the heap state via
tcmalloc. the program’s API is often referred to as heap feng shui
4. An architecture, and proof-of-concept implementa- in the computer security literature [27]. Discovering the
tion, for a system that integrates automatic HLM relationship between program-level API calls and alloca-
into the exploit development process. The im- tor interactions is a prerequisite for real-world HLM but
plementation, SHRIKE4 , automatically solves heap can be addressed separately, as we demonstrate in sec-
layout constraints that arise when constructing ex- tion 4.2.
ploits for the PHP interpreter. SHRIKE also demon-
2.1 Problem Restrictions for a
strates a novel approach to integrating an automated
reasoning engine into the exploit development pro- Deterministic Setting
cess. There are four variants of the HLM problem, as shown
in Figure 2, depending on whether the allocator is
deterministic5 or non-deterministic and whether the
2 The Heap Layout Manipulation Problem starting state is known or unknown. In this paper we con-
in Deterministic Settings sider a known starting state and a deterministic allocator,
as it both corresponds to a set of real world exploitation
As of 2018, the most common approach to solving heap scenarios and provides a building block for addressing
layout manipulation problems is manual work by ex- the other three problem variants.
perts. An analyst examines the allocator’s implementa- In the ‘deterministic allocator, known starting state’
tion to gain an understanding of its internals; then, at run- problem variant there three restrictions:
time, they inspect the state of its various data structures
to determine what interactions are necessary in order to 1. The allocator’s behaviour is deterministic.
manipulate the heap into the required layout. 2. The starting state of the heap must be known or the
Heap layout manipulation primarily consists of two attacker must have a means by which to force the
activities: creating and filling holes in memory. A hole is heap into a known state.
a free area of memory of a particular size. Holes are filled 3. There are no other actors interacting with the
to force the positioning of an allocation of a particular heap, or if there are then their interactions are
size elsewhere, or the creation of a fresh area of memory deterministic and known, in terms of what the in-
under the management of the allocator. Holes are cre- teraction is and when it takes place.
ated to capture allocations that would otherwise interfere
with the layout one is trying to achieve. This process Local privilege escalation exploits are a scenario in
is documented in the literature of the hacking and com- which these restrictions are usually met, although some
puter security communities, with a variety of papers on 5 A deterministic allocator is one that does not utilise any ran-
the internals of individual allocators [1, 4, 20, 22], as well dom behaviour when servicing allocation requests. The majority of
allocators are deterministic but some, such as the Windows system al-
3 Source code to be released upon publication locator and jemalloc, do utilise non-determinism to make exploitation
4 Source code to be released upon publication more difficult
3
remote, and client-side, targets offer the ability for an at- in crafting the heap layout to ensure that the noisy id al-
tacker to force the creation of a heap in a known state location is placed out of the way and a name and User
and with which they are the only actor interacting (e.g. structure end up next to each other.
by the creation of a Web Worker in Firefox or Chrome).
2.2.2 Constraints on Allocator Interactions
When unknown starting states and non-determinism
must be dealt with, approaches such as allocating a large An attacker’s access to the allocator is limited by what
number of objects on the heap in the hope of corrupting is allowed by the program they are interacting with. The
one when the vulnerability is triggered are often used. interface available may limit the sizes that may be allo-
However, in the problem variant we address it is usually cated, the order in which they may be allocated and deal-
possible to position the overflow source relative to a spe- located, and the number of times a particular size may be
cific target buffer. Thus our objective in this variant of allocated or deallocated. Depending on the heap layout
the HLM problem is as follows: that is desired, these constraints may make the desired
layout more complex to achieve, or even impossible.
Given the API for a target program and a 2.2.3 Diversity of Allocator Implementations
means by which to allocate a source and desti-
nation buffer, find a sequence of API calls that The open ended nature of allocator design and imple-
position the destination and source at a spe- mentation means any approach that involves the produc-
cific offset from each other. tion of a formal model of a particular allocator is going
to be costly and likely limited to a single allocator, and
2.2 Challenges perhaps even a specific version of that allocator. While
avrlibc is a mere 350 lines of code, most of the other
There are several challenges to that arise when trying to allocators we consider contain thousands or tens of thou-
perform HLM and when trying to construct a general, sands of lines of code. Their implementations involve
automated solution. In this section we outline those that complex data structures, loops without fixed bounds, in-
are most likely to be significant. teraction with the operating system and other features
2.2.1 Interaction Noise that are often terminally challenging for semantics-aware
analyses, such as model checking and symbolic execu-
Before continuing we first must informally define the
tion. A detailed survey of the data structures and algo-
concept of an ‘interaction sequence’: an allocator in-
rithms used in allocators is available in [33].
teraction is a call to one of its allocation or dealloca-
tion functions, while an interaction sequence is a list 2.2.4 Interaction Sequence Discovery
of one or more interactions that result from the invo- Since in most situations one cannot directly interact with
cation of a function in the target program’s API. As an the allocator, an attacker needs to discover what interac-
attacker cannot directly invoke functions in the alloca- tion sequences with the allocator can be indirectly trig-
tor they must manipulate the heap via the available in- gered via the program’s API. This problem can be ad-
teraction sequences. As an example, when the create dressed separately to the main HLM problem, but it is a
function from Listing 1 is called the resulting interaction necessary first step. In section 4.2 we discuss how we
sequence consists of three interactions in the form of the solved this problem for the PHP language interpreter.
three calls to malloc. The destroy function also pro-
vides an interaction sequence of length three, in this case
consisting of three calls to free. 3 Automatic Heap Layout Manipulation
For a given interaction sequence there can be interac-
tions that are beneficial, and assist with manipulation of We now present our pseudo-random black box search al-
the heap into a layout that is desirable, and also interac- gorithm for heap layout manipulation, and two evalua-
tions that are either not beneficial (but benign), or in fact tion frameworks we have embedded it in to perform heap
are detrimental to the heap state in terms of the layout layout manipulation on both synthetic benchmarks and
one is attempting to achieve. We deem those interactions real vulnerabilities. The algorithm is theoretically and
that are not actively manipulating the heap into a desir- practically straightforward. There are two strong moti-
able state to be noise. vations for initially avoiding complexity.
For example, the create function from Listing 1 pro- Firstly, there is no existing prior work on automatic
vides the ability to allocate buffers between 2 and 8 HLM and a straightforward algorithm provides a base-
bytes in size by varying the length of the name param- line that future, more sophisticated, implementations can
eter. However, two other unavoidable allocations also be compared against if necessary.
take place – one for the User structure and one for the Second, despite the potential size of the problem mea-
id. As shown in Figure 1, some effort must be invested sured by the number of possible combinations of avail-
4
able interactions, there is significant symmetry in the so- Algorithm 1 Find a solution which places two alloca-
lution space for many problem instances. Since our mea- tions in memory at a specified distance from each other.
sure of success is based on the relative positioning of two g is the number of candidates to try, d the required dis-
buffers, large equivalence classes of solutions exist as: tance, m the maximum candidate size and r the ratio of
allocations to deallocations for each candidate.
1. Neither the absolute location of the two buffers, nor 1: function S EARCH (g, d, m, r)
their relative position to other buffers, matters. 2: for i ← 0, g − 1 do
2. The order in which holes are created or filled usu- 3: cand ← ConstructCandidate(m, r)
ally does not matter. 4: dist ← Execute(cand)
5: if dist = d then
It is often possible to solve a layout problem using sig- 6: return inst
nificantly differing input sequences. Due to these solu- 7: end if
tion space symmetries, we propose that a pseudo-random 8: end for
black box search could be a solution for a sufficiently 9: return None
large number of problem instances as to be worthwhile. 10: end function
To test this hypothesis, and demonstrate its feasibility 11: function C ONSTRUCT C ANDIDATE (m, r)
on real targets, we constructed two systems. The first, de- 12: cand ← InitCandidate(GetStartingState())
scribed in section 3.1 allows for synthetic experiments to 13: len ← Random(1, m)
be run against any allocator exposing the standard ANSI 14: f stIdx ← Random(0, len − 1)
interface for dynamic memory allocation. The second 15: for i ← 0, len − 1 do
system, described in section 3.2, is a fully automated 16: if i = f stIdx then
HLM system designed to work with the PHP interpreter. 17: AppendFstSequence(cand)
18: else if Random(1, 100) ≤ r then
3.1 SIEVE: An Evaluation Framework for
19: AppendAllocSequence(cand)
HLM Algorithms 20: else
To allow for the evaluation of search algorithms for HLM 21: AppendFreeSequence(cand)
across a diverse array of benchmarks we constructed 22: end if
SIEVE. There are two components to SIEVE: 23: end for
24: AppendSndSequence(cand)
1. The SIEVE driver which is a program that can 25: return cand
be linked with any allocator exposing the malloc, 26: end function
free, calloc and realloc functions. As input
it takes a file specifying a series of allocation and
deallocation requests to make, and produces as out- addrSnd, respectively. After the allocation direc-
put the distance from two particular allocations of tives for these buffers have been processed, the
interest. Allocations and deallocations are specified value of (addrFst − addrSnd) is printed.
via directives of the following forms: 2. The SIEVE framework which provides a Python
API for running HLM experiments. It has a vari-
(a) <malloc size ID> ety of features for constructing candidate solutions,
(b) <calloc nmemb size ID> feeding them to the driver and retrieving the result-
(c) <free ID> ing distance, which are explained below. This func-
(d) <realloc oldID size ID> tionality allows one to focus on creating search al-
(e) <fst size> gorithms for HLM.
(f) <snd size>
SIEVE allows for flexible and scalable evaluation of
Each of the first four directives are translated into an new search algorithms, or testing existing algorithms on
invocation of their corresponding memory manage- new allocators, new interaction sequences or new heap
ment function, with the ID parameters providing an starting states. The framework is made freely available
identifier which can be used to refer to the returned and can be used to test solutions to all variants of the
pointers from malloc, calloc and realloc, when HLM problem, not just the one we address here.
they are passed to free or realloc. The final We implemented a pseudo-random search algorithm
two directives indicate the allocation of the two for HLM on top of SIEVE, and it is shown as Algo-
buffers that we are attempting to place relative to rithm 1. The m and r parameters are what make the
each other. We refer to the addresses that result search pseudo-random. While one could potentially use
from the corresponding allocations as addrFst and a completely random search, it makes sense to guide it
5
away from candidates that are highly unlikely to be use-
ful due to extreme values for m and r. There are a few
points to note on the SIEVE framework’s API in order to
understand the algorithm:
6
to enable a variety of features including recording the 1 $image = imagecreatetruecolor(180, 30);
allocations that result from invoking a fragment of PHP 2 imagestring($image, 5, 10, 8, "Text",
code, monitoring allocations for the presence of inter- 0x00ff00);
esting data, and checking the distance between two allo- 3 $gaussian = array(
cations. We carefully implemented the functionality of 4 array(1.0, 2.0, 1.0),
this extension to ensure that it does not modify the heap 5 array(2.0, 4.0, 2.0)
layout of the target program in any way that would inval- 6 );
idate search results. However, all results are validated by 7 var_dump(imageconvolution($image, $gaussian,
16, 0));
executing the solutions in an unmodified version of PHP.
3.2.1 Identifying Available Interaction Sequences Listing 2: Source for a PHP test program.
To discover the available interaction sequences it is nec-
essary to synthesise self-contained fragments of PHP
code and determine the allocator interactions each frag- 1 imagecreatetruecolor(I, I)
ment triggers. Correlating code fragments with the re- 2 imagestring(R, I, I, I, T, I)
3 array(F, F, F)
sulting allocator interactions is straightforward: we mod-
4 array(R, R)
ify the PHP interpreter to record the allocator interactions
5 var_dump(R)
that result from executing a given fragment. This is done 6 imageconvolution(R, R, I, I)
in a manner that does not modify the heap layout in any
way, and so false positives are avoided. Synthesising Listing 3: The function fuzzing specifications produced
valid fragments of PHP code that trigger a diverse set of from parsing Listing 2. The letters replacing the function
allocator interactions is more involved. arguments indicate their types. ‘R’ for a resource, ‘I’ for
We resolve the synthesis problem by implementing a an integer, ‘F’ for a float and ‘T’ for text.
fuzzer for the PHP interpreter that leverages the regres-
sion tests that come with PHP, in the form of PHP pro-
grams. This idea is based on previous work that used a
similar approach for the purposes of vulnerability detec- As an example, lets discuss how the regression test
tion [17,18]. The tests provide examples of the functions in Listing 2 would be used to discover interaction
that can be called, as well as the number and types of sequences. From the regression test the fuzzing speci-
their arguments. The fuzzer then uses mutation and com- fication shown in Listing 3 is automatically produced.
bination to produce new fragments with new behaviours. Fuzzing specifications indicate the name of functions
To tune the fuzzer towards the discovery of fragments that can be called, along with the types of their argu-
that are useful for HLM, as opposed to vulnerability dis- ments. SHRIKE then begins to fuzz the discovered
covery, we made the following modifications: functions, using the specifications to ensure the correct
types are provided for each argument. For example,
• We use mutations that are intended to produce an the code fragments $x = imagecreatetruecolor(1,
interaction sequence that we have not seen before, 1), $x = imagecreatetruecolor(1, 2), $x =
rather than a crash. For example, fuzzers will often imagecreatetruecolor(1, 3) etc. might be cre-
replace integers with values that may lead to edge ated and executed to determine what, if any, allocator
cases, such as 0, 232 − 1, 231 − 1 and so on. We interactions they trigger.
are interested in triggering unique allocator inter- The output of this stage is a mapping from fragments
actions however, and so we predominantly mutate of PHP code to a summary of the allocator interaction
tests using integers and string lengths that relate to sequences that occur as a result of executing that code.
allocation sizes we have not previously seen. The summary includes the number and size of any allo-
• Our measure of fitness for a generated test is not cations, and whether the sequence triggers any frees.
based on code coverage, as is often the case with
3.2.2 Automatic Identification of Target Structures
vulnerability detection, but is instead based on
whether a new allocator interaction sequence is pro- In most programs there is a diverse set of dynamically
duced, and the length of that interaction sequence. allocated structures that one could corrupt or read to vi-
• We discard any fragments that result in the inter- olate some security property of the program. These tar-
preter exiting with an error. gets may be program-specific, such as values that guard
• We favour the shortest, least complex fragments a sensitive path; or they may be somewhat generic, such
with priority being given to fragments consisting of as a function pointer. Identifying these targets, and how
a single function call. to dynamically allocate them, can be a difficult manual
task in itself. To further automate the process we imple-
7
mented a component that, as with the fuzzer, splits the 1 <?php
PHP tests into standalone fragments and then observes 2 $quote_str = str_repeat("\xf4", 123);
the behaviour of these fragments when executed. If the 3 #X-SHRIKE HEAP-MANIP
fragment dynamically allocates a buffer and writes what 4 #X-SHRIKE RECORD-ALLOC 0 1
appears to be a pointer to that buffer, we consider it to be 5 $image = imagecreate(1, 2);
a potentially interesting corruption target and store the 6 #X-SHRIKE HEAP-MANIP
fragment. The user can indicate in the template which 7 #X-SHRIKE RECORD-ALLOC 0 2
of the discovered corruption targets to use, or the system 8 quoted_printable_encode($quote_str);
9 #X-SHRIKE REQUIRE-DISTANCE 1 2 0
can automatically select one.
10 ?>
3.2.3 Specifying Candidate Structure
Listing 4: Exploit template for CVE-2013-2110
Different vulnerabilities in PHP require different setup in
order to trigger e.g. the initialisation of required objects
or the invocation of multiple functions. To avoid hard-
coding vulnerability-specific information in the candi- executes PHP programs until a solution is found or the
date creation process, we allow for the creation of can- execution budget expires. Candidate creation is shown
didate templates that define the structure of a candidate. in the Instantiate function. Its first argument is a rep-
A template is a normal PHP program with the addition resentation of the template as a series of objects. The ob-
of directives starting with #X-SHRIKE7 . The template is jects represent either SHRIKE directives or normal PHP
processed by SHRIKE and the directives inform it how code and are processed as follows:
candidates should be produced and what constraints they
must satisfy to solve the HLM problem. The supported • The HEAP-MANIP directive is handled via the
directives are as follows: GetHeapManipCode function (line 15). The
database, constructed as described in section 3.2.1,
• <HEAP-MANIP [sizes]> Indicates a location is queried for a series of PHP fragments, where each
where SHRIKE can insert heap-manipulating fragment allocates or frees one of the sizes speci-
sequences. The sizes argument is an optional list fied in the sizes argument to the directive in the
of integers indicating the allocation sizes that the template. If no sizes are provided then all available
search should be restricted to. fragments are considered. If multiple fragments ex-
• <RECORD-ALLOC offset id> Indicates that ist for a given size then selection is biased towards
SHRIKE should inject code to record the address fragments with less noise. Between 1 and m frag-
of an allocation and associate it with the provided ments are selected and returned. The r parameter
id argument. The offset argument indicates controls the ratio of allocations to frees.
the allocation to record. Offset 0 is the very next • The RECORD-ALLOC directive is handled via the
allocation, offset 1 the one after that, and so on. GetRecordAllocCode function (line 17). A PHP
• <REQUIRE-DISTANCE idx idy dist> Indicates fragment is returned consisting of a call to a func-
that SHRIKE should inject code to check the dis- tion in our extension for PHP that associates the
tance between the pointers associated with the pro- specified allocation with the specified ID.
vided IDs. Assuming x and y are the pointers asso- • The REQUIRE-DISTANCE directive is handled via
ciated with idx and idy respectively, then if (x − y = the GetRequireDistanceCode function (line 19).
dist) SHRIKE will report the result to the user, A PHP fragment is returned with two components.
indicating this particular HLM problem has been Firstly, a call to a function in our PHP extension that
solved. If (x − y 6= dist) then the candidate will be queries the distance between the pointers associated
discarded and the search will continue. with the given IDs. Secondly, a conditional state-
A sample template for CVE-2013-2110, a heap-based ment that prints a success indicator if the returned
buffer overflow in PHP, is shown in Listing 4. In sec- distance equals the distance parameter.
tion 4.3 we explain how this template was used in the • All code that is not a SHRIKE directive is included
construction of a control-flow hijacking exploit for PHP. in each candidate verbatim (line 21).
3.2.4 Search The Execute function (line 5) converts the candidate
The search in SHRIKE is outlined in Algorithm 2. It into a valid PHP program and invokes the PHP interpreter
takes in a template, parses it and then synthesises and on the result. It checks for the success indicator printed
7 As the directives begin with a ‘#’ they will be interpreted by the by the code inserted to handle the REQUIRE-DISTANCE
normal PHP interpreter as a comment and thus can be run in both our directive. If that is detected then the solution program
modified interpreter and an unmodified one. is reported. Listing 5 in the appendix shows a solution
8
Algorithm 2 Solve the HLM problem described in the
provided template t. g is the number of candidates to try, Table 1: Synthetic benchmark results after 500,000 can-
d the required distance, m the maximum number of frag- didate solutions generated, averaged across all starting se-
ments that can be inserted in place of each HEAP-MANIP quences. The full results are in Table 4 in the appendix. All
directive, and r the ratio of allocations to deallocation experiments were run 10 times and the results presented
fragments used in place of each HEAP-MANIP directive. are an average.
1: function S EARCH (t, g, m, r) % % %
2: spec ← ParseTemplate(t) Allocator Noise Overall Natural Reversed
3: for i ← 0, g − 1 do Solved Solved Solved
4: cand ← Instantiate(spec, m, r) avrlibc-r2537 0 100 100 99
5: if Execute(cand) then dlmalloc-2.8.6 0 99 100 98
6: return cand tcmalloc-2.6.1 0 72 75 69
7: end if avrlibc-r2537 1 51 50 52
8: end for dlmalloc-2.8.6 1 46 60 31
9: return None tcmalloc-2.6.1 1 52 58 47
10: end function avrlibc-r2537 4 41 44 38
11: function I NSTANTIATE (spec, m, r) dlmalloc-2.8.6 4 33 49 17
12: cand ← NewPHPProgram() tcmalloc-2.6.1 4 37 51 24
13: while n ← Iterate(spec) do
14: if IsHeapManip(n) then
15: code ← GetHeapManipCode(n, m, r)
16: else if IsRecordAlloc(c) then
tcmalloc (v2.6.1), dlmalloc (v2.8.6) and avrlibc
17: code ← GetRecordAllocCode(n)
(v2.0) allocators for experimentation. These allocators
18: else if IsRequireDistance(n) then
have significantly different implementations and are used
19: code ← GetRequireDistanceCode(n)
in many real world applications.
20: else
An important difference between the allocators used
21: code ← GetVerbatim(n)
for evaluation is that tcmalloc (and PHP) make use of
22: end if
segregated storage, while dlmalloc and tcmalloc do
23: AppendCode(cand, code)
not. In short, for small allocation sizes (e.g. less than
24: end while
a 4KB) segregated storage pre-segments runs of pages
25: return cand
into chunks of the same size and will then only place
26: end function
allocations of that size within those pages. Thus, only
allocations of the same, or similar, sizes may be adjacent
produced from the template in Listing 4. to each other, except for the first and last allocations in
the run of pages which may be adjacent to the last or first
allocation from other size classes.
4 Experiments and Evaluation Secondly, to evaluate the viability of our search algo-
rithm on real world applications we ran SHRIKE on 30
The research questions we address are as follows: different layout manipulation problems in PHP. All ex-
periments were carried out on a server with 80 Intel Xeon
• RQ1: What factors most significantly impact the E7-4870 2.40GHz cores and 1TB of RAM, utilising 40
difficulty of the heap layout manipulation problem concurrent analysis processes.
in a deterministic setting?
• RQ2: Is pseudo-random search an effective ap- 4.1 Synthetic Experiments
proach to heap-layout manipulation? The goal of the synthetic experiments is to discover
• RQ3: Can heap layout manipulation be automated the factors which influence the difficulty of problem in-
effectively for real-world programs? stances and to highlight the capabilities and limitations of
our search algorithm in an environment that we precisely
We conducted two sets of experiments. Firstly, to in- control. The experiments were configured as follows:
vestigate the fundamentals of the problem we utilised
the system discussed in section 3.1 to conduct a set of • As mentioned, in real world scenarios it is often
synthetic experiments involving differing combinations the case that the available interaction sequences are
of heap starting states, interaction sequences, source noisy. We evaluated the effect of prefixing and suf-
and destination sizes, and allocators. We chose the fixing both the source and destination allocations
9
Figure 4: For an allocator that splits chunks from the
start of free blocks, the natural order, shown on the left,
of allocating the source and then the destination produces
the desired layout, while the reversed order, shown on the
right, results in an incorrect layout.
Figure 5: A solution for the reversed allocation order to
corruption direction relationship. A hole is created via a
with varying amounts of noise. placeholder which can then be used for the source.
• For each source and destination combination, we
made available to the analyser an interaction se-
more opportunities for the search algorithm to find solu-
quence which triggers an allocation of the source
tions but with 2592 total experiments to run, and 500,000
size, an interaction sequence which triggers an al-
executions taking in the range of 5-15 minutes depend-
location of the destination size, and interaction se-
ing on the number of interactions in the starting state,
quences for freeing each of the allocations.
this was the maximum viable value given our computa-
• We initialise the heap state prior to executing the in-
tional resources. The results of the experiments averaged
teractions from a candidate by prefixing each candi-
across all starting states can be found in Table 1, with the
date with a set of interactions. Previous work [33]
full results in the appendices in Table 4.
has outlined the drawbacks that arise when using
To understand the ‘% Natural’ and ‘% Reversed’
randomly generated heap states to evaluate alloca-
columns in the results table we must define the concept
tor performance. To avoid these drawbacks we cap-
of the allocation order to corruption direction relation-
tured the initialisation sequences of PHP8 , Python
ship. We refer to the case of the allocation of the source
and Ruby to use in our experiments. A summary
of an overflow first, followed by its destination, or the
of the relevant properties of these initialisation se-
allocation of the destination of an underflow first, fol-
quences can be found in the appendices in table 2.
lowed by its source as the natural relationship. This is
• As it is not feasible to evaluate layout manipulation
because most allocators split space from the start of free
for all possible combinations of source and destina-
chunks and thus for an overflow if the source and desti-
tion sizes, we selected 6 sizes which we deemed to
nation are both split from the same chunk and the source
be both likely to occur in real world problems and
is allocated first then it will naturally end up before the
to exercise different allocator behaviour. The sizes
destination, and the reverse holds for an underflow. We
we selected are 8, 64, 512, 4096, 16384 and 65536.
refer to the relationship as reversed in the case of the al-
For each pair of sizes (x, y) there are four experi-
location of the destination first followed by the source
ments to be run: x allocated first overflowing into
for an overflow, or the allocation of the source first fol-
y, x allocated first underflowing into y, y allocated
lowed by the destination for an underflow. We expect this
first overflowing into x, and y allocated first under-
case to be harder to solve for most allocators, as the so-
flowing into x. Thus from the six sizes selected we
lution is more complex than for the natural relationship.
end up with 72 experiments to run for each com-
A visualisation of this idea can be seen in Figure 4 and a
bination of allocator, noise and starting state (2592
solution for the reversed case is shown in Figure 5.
experiments in total).
From the experiments a number of points emerge:
The m and r parameters to Algorithm 1 were set to • When segregated storage is not in use, as with
1000 and .98 respectively, based on our intuition as to dlmalloc and avrlibc, and when there is no
the likely maximum length of a solution and the ratio of noise, 98% to 100% of the benchmarks are solved.
heap filling to hole creation required. The g parameter • Segregated storage significantly increases problem
was set to 500,000. A larger value would have provided difficulty. With no noise, the overall success rate
8 PHP makes use of both the system allocator and its own alloca- drops to 72% for tcmalloc.
tor. We captured the initialisation sequences for both, giving us four • With the addition of a single noisy allocation, the
different starting states in total. overall success rate drops to close to 50% across all
10
allocators. The ten target structures are described in the appendix
• The order of allocation for the source and destina- in Table 3 and the full details of all 30 experiments can
tion matters. A layout conforming to the natural be found in Table 5. As with the synthetic experiments,
allocation order to corruption direction relationship the m and r arguments to the Search function were set to
was easier to find in all problem instances. With 1000 and .98 respectively. Instead of limiting the number
four noisy allocations the success rate for problems of executions via the g parameter the maximum run time
involving the natural allocation order ranges from for each experiment was set to 12 hours. The following
44% to 51%, but drops to between 17% and 38% summarises the results:
for the reversed order. It is also worth noting that
the difference in success rate between natural and • SHRIKE succeeds in producing a PHP program
reversed problem instances is lower for avrlibc achieving the required layout in 21 of the 30 exper-
than for dlmalloc and tcmalloc. This is because iments run and fails in 9 (a 70% success rate).
in some situations avrlibc will split space from • There are 15 noise-free experiments of which
free chunks from the end instead of from the start, SHRIKE solves 100%, and 15 noisy experiments of
in effect swapping the natural and reversed orders. which SHRIKE solves 40%. This follows what one
• We ran each experiment 10 times, and if all 10 times would expect from the synthetic experiments.
500,000 executions are taken together then 78% of • In the successful cases the analysis took on average
the benchmarks are solved at least once. In other 571 seconds and 720,000 candidates.
words, only 22% of the benchmarks were never Of the nine experiments in which SHRIKE does not
solved by our approach, which is quite encouraging solve, eight involve CVE-2016-7126. The most likely
given the simplicity of the algorithm. reason for the difficulty of experiments using this vul-
nerability is noise in the interaction sequences involved.
4.2 PHP Experiments The source buffer for this vulnerability results from an
allocation request of size 1, which PHP rounds up to 8 –
To determine if automatic HLM is feasible in real world an allocation size that is quite common throughout PHP,
scenarios we selected three vulnerabilities that result in and prone to occurring as noise. There is a noisy al-
OOB memory access on the heap and ten dynamically al- location in the interaction sequence which allocates the
located structures that were identified by SHRIKE as be- source buffer itself, several of the interaction sequences
ing useful corruption targets (namely structures that have which allocate the target structures also have noisy al-
pointers as their first field). An experiment was then run locations, and all interaction sequences which SHRIKE
for each vulnerability paired with each target structure in discovered for making allocations of size 8 involve at
which SHRIKE was used to search for an input which least one noisy allocation. For example, the shortest se-
would place the source buffer and destination buffer ad- quence discovered for making an allocation of size 8 is
jacent to each other. a call to imagecreate(57, 1) which triggers an allo-
A successful outcome means the system can discover cation of size 7360, two allocations of size 8 and two
how to interact with the underlying allocator via PHP’s allocations of size 57. In contrast, there is little or no
API, identify how to allocate sensitive data structures noise involved in the experiments utilising CVE-2016-
on the heap, and construct a PHP program which places 5093 and CVE-2015-8865.
such a structure adjacent to the source of an OOB mem-
ory access. This saves an exploit developer a significant 4.3 Generating a Control-Flow Hijacking
amount of effort, allowing them to focus on how to lever- Exploit for PHP
age the resulting OOB memory access. To show that SHRIKE can be integrated into the devel-
We utilised the following vulnerabilities in our evalu- opment of a full exploit we selected another vulnerabil-
ation: ity in PHP. CVE-2013-2110 allows an attacker to write a
NULL byte immediately after the end of a heap-allocated
• CVE-2015-8865. An out-of-bounds write vulnera- buffer. One must utilise that NULL byte write to corrupt
bility in libmagic that is triggerable via PHP up to a location that will enable more useful exploitation prim-
version 7.0.4. itives. Our aim is to convert the NULL byte write into
• CVE-2016-5093. An out-of-bounds read vulnera- both an information leak to defeat ASLR and the ability
bility in PHP up to version 7.0.7, related to string to modify arbitrary memory locations.
processing and internationalisation. We first searched SHRIKE’s database for interaction
• CVE-2016-7126. An out-of-bounds write vulnera- sequences that allocate structures that have a pointer as
bility in PHP up to version 7.0.10, related to image their first field. This lead us to the imagecreate func-
processing. tion which creates a gdImage structure. This structure
11
uses a pointer to an array of pointers to represent a grid Without segregated storage, when there is no noise
of pixels in an image. By corrupting this pointer via the then 99% of problems were solved, with most experi-
NULL byte write, and then allocating a buffer we control ments taking 15 seconds or less. As noise is added the
at the location it points to post-corruption, an attacker can rate of success drops to 44% and 49% for a single noisy
control the locations that are read and written from when allocation, for dlmalloc and avrlibc respectively, and
pixels are read and written. then to 30% and 39% for four noisy allocations. The ex-
Listing 4 shows the template provided to SHRIKE. In tra constraints imposed on layout by segregated storage
less than 10 seconds SHRIKE finds an input that places present more of a challenge. On noise-free runs the rate
the source immediately prior to the destination. Thus the of success is 72% and drops to 57% and 51% as one and
pointer that is the first attribute of the gdImage structure four noisy allocations, respectively, are added. However,
is corrupted. Listing 5 in the appendices shows part of as noted in section 4.1, if all 30 runs of each experiment
the automatically generated solution. After the corrup- are considered together then 78% of the benchmarks are
tion occurs the required memory read and write primi- solved at least once.
tives can be easily achieved by allocating a controllable Overall, on the synthetic experiments it is clear that the
buffer into the location where the corrupted pointer now effectiveness of pseudo-random search varies depending
points. For brevity we leave out the remaining details of on whether segregated storage is in use, the amount of
the exploit, but it can be found in full in the SHRIKE noise, the allocation order to corruption direction rela-
repository. The end result is a PHP script that hijacks the tionship and the available computational resources. In
control flow of the interpreter and spawns a shell. the best case scenarios pseudo-random search can solve
problem instances in seconds, while in the more diffi-
4.4 Research Questions
cult ones it still attains a high enough success rate to be
RQ1: What factors most significantly impact the dif- worthwhile given its simplicity.
ficulty of the heap layout manipulation problem in a When embedded in SHRIKE, pseudo-random search
deterministic setting? approach also proved effective, with similar caveats re-
The following factors had the most significant impact lating to noise. 100% of noise-free problems were
on problem difficulty: solved, while 40% of those involving noise were. On av-
erage the search took less than 10 minutes and 750,000
• Noise. In the synthetic experiments noise clearly
candidates, for instances on which it succeeded.
impacts difficulty. As more noise is added, more
RQ3: Can heap layout manipulation be automated
holes typically have to be created. In the worst
effectively for real-world programs?
case (dlmalloc) we see a drop off from a 99%
overall success rate to 33% when four noisy allo- Our experiments with PHP indicate that automatic
cations are included. A similar success rate is seen HLM can be performed effectively for real world pro-
for avrlibc and tcmalloc with four noisy alloca- grams. As mentioned in RQ2, SHRIKE had a 70% suc-
tions. In the evaluation on PHP noise again played cess rate overall, and a 100% success rate in cases where
a significant role, with SHRIKE solving 100% of there was no noise.
noise-free instances and 40% of noisy instances. SHRIKE demonstrates that it is possible to automate
• Segregated storage. In the synthetic benchmarks the process in an end-to-end manner, with automatic dis-
segregated storage leads to a decline in the over- covery of a mapping from the target program’s API to in-
all success rate on noise-free instances from 100%- teraction sequences, discovery of interesting corruption
99% to 72%. targets, and search for the required layout. Furthermore,
• Allocation order to corruption direction rela- SHRIKE’s template based approach show that a system
tionship. For all configurations of allocator, noise with these capabilities can be naturally integrated into the
and starting state, the problems involving the natu- exploit development process.
ral order were easier. For the noise-free instances on 4.5 Generalisability
avrlibc and dlmalloc the difference is in terms
of solved problems is just 1%-2%, but as noise is Regarding generalisability, our experiments are not ex-
introduced the success rate between the natural and haustive and care must be taken in extrapolating to
reversed experiments diverges. For dlmalloc with benchmarks besides those presented. However, we be-
four noisy allocations the success rate for the natu- lieve that the presented search algorithm and architecture
ral order is 49% but only 17% for the reversed order, for SHRIKE are likely to work similarly well with other
a difference of 32%. language interpreters, for two reasons. Firstly, the search
algorithm has demonstrated its capabilities on a diverse
RQ2: Is pseudo-random search an effective ap- set of synthetic benchmarks. Secondly, the approach in
proach to heap-layout manipulation? SHRIKE of using regression tests to seed the generation
12
of new programs is based on previous work on vulner- specifically address the challenges of heap-based vul-
ability detection that has been shown to work on inter- nerabilities. Over the course of the CGC finals only
preters for Javascript and Ruby, as well as PHP [17, 18]. a single heap-based vulnerability was successfully ex-
ploited [11]. No details are available on how this was
4.6 Threats to Validity achieved but it would seem likely that this was an inad-
The results in our synthetic evaluation could be affected vertent success, rather than a solution which explicitly
by our choice of source and destination sizes. There attempted to reason about heap-based exploitation.
may be combinations of these that trigger pathological In [25] the authors present work on exploit generation
behaviour in the allocators we have evaluated that we for heap-based vulnerabilities that is orthogonal to ours.
are unaware of. A different set of starting sequences, or Using a driver program the system first builds a database
available interaction sequences may also impact the re- of conditions on the heap layout that, if met, would al-
sults. We have attempted to mitigate these issues by se- low for an exploit to be produced. Then, an exploit can
lecting a diverse set of sizes, capturing starting sequences be generated for a real program if an input is provided
from multiple programs and allowing the analysis engine that places the heap into the state that is found in the
to utilise only a minimal set of interaction sequences. database. For all but the most trivial of layout require-
Our non-synthetic results are affected by our choice of ments, and unhardened allocators, it is highly unlikely
vulnerabilities and target data structures, and we could this condition will be satisfied by a vulnerability trigger
have inadvertently selected for cases that are outliers. taken directly from a fuzzer, or similar tool. In this pa-
We have attempted to mitigate this possibility by util- per we have demonstrated an approach to producing in-
ising ten different target structures and vulnerabilities in puts that satisfy heap layout constraints, and thus could
three completely different sub-components of PHP. be used to process vulnerability triggers into inputs that
The limitation of our evaluation to a language inter- meet the requirements of their system.
preter also poses a threat, as the available interaction se- In Vanegue [32] defines a calculus for a simple heap
quences may differ when other classes of target program allocator and also provides a formal definition [31] of the
are considered. We have attempted to mitigate this threat related problem of automatically producing inputs which
by limiting the interaction sequences used to those that maximise the likelihood of reaching a particular program
contain an allocation of a size equal to one of the allo- state given a non-deterministic heap allocator.
cation sizes found in the sequences which allocate the
source and destination. 6 Conclusion
In this paper we have outlined the heap layout
5 Related Work manipulation problem as a distinct task within the con-
text of automated exploit generation. We have presented
The hacking and security communities have exten- a simple, but effective, algorithm for HLM in the case of
sively published on reverse engineering heap implemen- a deterministic allocator and a known starting state, and
tations [30, 34], leveraging weaknesses in those imple- shown that it can produce the required layout in a sig-
mentations for exploitation [21, 23, 24], and heap layout nificant number of synthetic experiments. We have also
manipulation for exploitation [19,22]. There is also work described an end-to-end system for HLM and shown that
on constructing libraries for debugging heap internals [8] it is effective when used with real vulnerabilities in the
and libraries which wrap an application’s API to pro- PHP interpreter.
vide layout manipulation primitives [27]. Manually con- Finally, we have demonstrated how a system for au-
structed solutions for heap layout manipulation in non- tomatic HLM can be integrated into the exploit develop-
deterministic settings are also commonplace in the liter- ment process. The directives provided by SHRIKE allow
ature of the hacking and security communities [6, 15]. the exploit developer to focus on the higher level con-
Several papers [5, 7, 16] have focused on the AEG cepts in the exploit, while letting SHRIKE resolve heap
problem. These implementations are based on sym- layout constraints. To the best of our knowledge, this is
bolic execution and exclusively focus on exploitation a novel approach to adding automation to exploit gen-
of stack-based buffer overflows. More recently, as part eration, and shows how an exploit developer’s domain
of the DARPA Cyber Grand Challenge [10] (CGC), a knowledge and creativity can be combined with auto-
number automated systems [13, 14, 28, 29] were devel- mated reasoning engines to produce exploits. Further re-
oped which combine symbolic execution and high per- search is necessary to expand on the concept, but we be-
formance fuzzing to identify, exploit and patch software lieve such human-machine hybrid approaches are likely
vulnerabilities in an autonomous fashion. As with ear- to be an effective means of producing exploits for real
lier systems, none of the CGC participants appear to systems.
13
References [16] S. Heelan, “Automatic Generation of Control Flow
Hijacking Exploits for Software Vulnerabilities,”
[1] Anonymous, “Once Upon a free(),” Master’s thesis, University of Oxford, 2009.
http://phrack.com/issues/57/9.html, Aug. 11
2001. [17] ——, “Ghosts of Christmas Past: Fuzzing Lan-
guage Interpreters using Regression Tests,” in In-
[2] ANSI X3.159-1989, American National Standard filtrate, 2014.
Programming Language C, Dec. 14 1990.
[18] C. Holler, K. Herzig, and A. Zeller, “Fuzzing
[3] argp, “OR’LYEH? The Shadow over Firefox,”
with Code Fragments,” in Proceedings of the 21st
http://phrack.com/issues/69/14.html, May 6 2016.
USENIX Security Symposium (USENIX Security
[4] argp and huku, “Pseudomonarchia jemallocum,” 12), 2012, pp. 445–458.
http://phrack.com/issues/68/10.html, Apr. 14 2012.
[19] huku and argp, “Exploiting VLC - A
[5] T. Avgerinos, S. K. Cha, B. L. T. Hao, and D. Brum- case study on jemalloc heap overflows,”
ley, “AEG: Automatic Exploit Generation,” in Net- http://phrack.com/issues/68/13.html, Apr. 14
work and Distributed System Security Symposium, 2012.
Feb. 2011.
[20] jp, “Advanced Doug Lea’s Malloc Exploits,”
[6] D. Blazakis, “Interpreter Exploitation. Pointer In- http://phrack.com/issues/61/6.html, Aug. 13 2003.
ference and JIT Spraying,” in Blackhat USA, 2010.
[21] T. Mandt, “Kernel Pool Exploitation on Windows
[7] D. Brumley, P. Poosankam, D. Song, and J. Zheng, 7,” in Blackhat DC, 2011.
“Automatic Patch-Based Exploit Generation is Pos-
sible: Techniques and Implications,” in Proceed- [22] MaXX, “Vudo Malloc Tricks,”
ings of the 2008 IEEE Symposium on Security and http://phrack.com/issues/57/8.html, Aug. 11
Privacy, ser. SP ’08. Washington, DC, USA: IEEE 2001.
Computer Society, 2008, pp. 143–157.
[23] J. McDonald and C. Valasek, “Practical Windows
[8] CENSUS, “Shadow,” XP/2003 Exploitation,” in Blackhat USA, 2009.
https://github.com/CENSUS/shadow.
[24] Phantasmal Phantasmagoria, “The Malloc Malefi-
[9] S. K. Cha, T. Avgerinos, A. Rebert, and D. Brum-
carum,” http://seclists.org/bugtraq/2005/Oct/118,
ley, “Unleashing Mayhem on Binary Code,” in Pro-
Oct. 11 2005.
ceedings of the 2012 IEEE Symposium on Security
and Privacy, ser. SP ’12. Washington, DC, USA: [25] D. Repel, J. Kinder, and L. Cavallaro, “Modular
IEEE Computer Society, 2012, pp. 380–394. synthesis of heap exploits,” in Proceedings of the
[10] DARPA, Cyber Grand Challenge, 2016. 2017 Workshop on Programming Languages and
[Online]. Available: http://archive.darpa.mil/ Analysis for Security, ser. PLAS ’17. New York,
cybergrandchallenge/ NY, USA: ACM, 2017, pp. 25–35.
[11] C. Eagle, “Re: DARPA CGC Recap.” [Online]. [26] Solar Designer, “JPEG COM Marker Processing
Available: http://seclists.org/dailydave/2017/q2/2 Vulnerability (in Netscape Browsers and Mi-
crosoft Products) and a generic heap-based buffer
[12] S. Esser, “State of the Art Post Exploitation in overflow exploitation technique,” Jul. 25 2000.
Hardened PHP Environments,” in Blackhat USA, [Online]. Available: http://www.openwall.com/
2009. articles/JPEG-COM-Marker-Vulnerability
[13] ForAllSecure, Feb. 9 2016. [Online]. Avail-
[27] A. Sotirov, “Heap Feng Shui in Javascript,” in
able: https://forallsecure.com/blog/2016/02/09/
Blackhat USA, 2007.
unleashing-mayhem/
[14] GrammaTech, http://blogs.grammatech.com/the- [28] N. Stephens, J. Grosen, C. Salls, A. Dutcher,
cyber-grand-challenge, Sep. 26 2016. R. Wang, J. Corbetta, Y. Shoshitaishvili,
C. Kruegel, and G. Vigna, “Driller: Augmenting
[15] R. Hay, “Exploitation of CVE-2009-1869,” Fuzzing Through Selective Symbolic Execution,”
https://securityresear.ch/2009/08/03/exploitation- in Proceedings of the Network and Distributed
of-cve-2009-1869/. System Security Symposium, 2016.
14
[29] Trail of Bits, https://blog.trailofbits.com/2015/07/15/how-
we-fared-in-the-cyber-grand-challenge/, Jul. 15
2015.
[30] C. Valasek and T. Mandt, “Windows 8 Heap Inter-
nals,” in Blackhat USA, 2012.
15
Appendix
# Allocator
Title # Allocs # Frees
Interactions
php-emalloc 571 366 205
php-malloc 15078 12714 2634
python-malloc 6160 3710 2450
ruby-malloc 70895 51827 19068
16
Table 4: Synthetic benchmark results. For each experiment the search was run for a
maximum of 500,000 candidates. All experiments were run 10 times and the results
below are the average of those runs. ‘% Solved’ is the percentage of the 72 experi-
ments for each row in which an input was found placing the source and destination
adjacent to each other. ‘% Natural’ is the percentage of the 36 natural allocation
order to corruption direction experiments which were solved. ‘% Reversed’ is the
percentage of the 36 reversed allocation order to corruption direction experiments
which were solved.
Allocator Start State Noise % Solved % Natural % Reversed
avrlibc-r2537 php-emalloc 0 100 100 100
avrlibc-r2537 php-malloc 0 100 100 100
avrlibc-r2537 python-malloc 0 100 100 100
avrlibc-r2537 ruby-malloc 0 99 100 98
dlmalloc-2.8.6 php-emalloc 0 99 100 99
dlmalloc-2.8.6 php-malloc 0 100 100 100
dlmalloc-2.8.6 python-malloc 0 99 100 97
dlmalloc-2.8.6 ruby-malloc 0 99 100 98
tcmalloc-2.6.1 php-emalloc 0 73 79 67
tcmalloc-2.6.1 php-malloc 0 77 80 75
tcmalloc-2.6.1 python-malloc 0 63 63 62
tcmalloc-2.6.1 ruby-malloc 0 75 78 71
avrlibc-r2537 php-emalloc 1 55 51 59
avrlibc-r2537 php-malloc 1 51 46 56
avrlibc-r2537 python-malloc 1 49 51 46
avrlibc-r2537 ruby-malloc 1 49 50 48
dlmalloc-2.8.6 php-emalloc 1 49 65 32
dlmalloc-2.8.6 php-malloc 1 49 62 37
dlmalloc-2.8.6 python-malloc 1 42 56 27
dlmalloc-2.8.6 ruby-malloc 1 43 58 27
tcmalloc-2.6.1 php-emalloc 1 52 59 45
tcmalloc-2.6.1 php-malloc 1 55 61 48
tcmalloc-2.6.1 python-malloc 1 50 52 48
tcmalloc-2.6.1 ruby-malloc 1 53 61 44
avrlibc-r2537 php-emalloc 4 43 44 42
avrlibc-r2537 php-malloc 4 40 41 40
avrlibc-r2537 python-malloc 4 42 47 37
avrlibc-r2537 ruby-malloc 4 39 45 33
dlmalloc-2.8.6 php-emalloc 4 34 51 16
dlmalloc-2.8.6 php-malloc 4 31 44 17
dlmalloc-2.8.6 python-malloc 4 33 50 16
dlmalloc-2.8.6 ruby-malloc 4 35 51 20
tcmalloc-2.6.1 php-emalloc 4 40 53 27
tcmalloc-2.6.1 php-malloc 4 39 53 25
tcmalloc-2.6.1 python-malloc 4 32 42 22
tcmalloc-2.6.1 ruby-malloc 4 38 54 22
17
Table 5: Results of heap layout manipulation for vulnerabilities in PHP. Experiments were run for a
maximum of 12 hours. All experiments were run 3 times and the results below are the average of these
runs. ‘Src. Size’ is the size in bytes of the source allocation. ‘Dst. Size’ is the size in bytes of the
destination allocation. ‘Src./Dst. Noise’ is the number of noisy allocations triggered by the allocation
of the source and destination. ‘Manip. Seq. Noise’ is the amount of noise in the sequences available
to SHRIKE for allocating and freeing buffers with size equal to the source and destination. ‘Initial
Dist.’ is the distance from the source to the destination if they are allocated without any attempt at
heap layout manipulation. ‘Final Dist.’ is the distance from the source to the destination in the best
result that SHRIKE could find. A distance of 0 means the problem was solved and the source and
destination were immediately adjacent. ‘Time to best‘ is the number of seconds required to find the
best result. ‘Candidates to best‘ is the number of candidates required to find the best result.
Src. Dst. Src./Dst. Manip. Seq. Initial Final Time to Candidates to
CVE ID
Size Size Noise Noise Dist. Dist. Best Best
2015-8865 480 7360 0 0 -16384 0 <1 106
2015-8865 480 16 0 0 -491424 0 170 218809
2015-8865 480 32 0 0 -96832 0 217 286313
2015-8865 480 8 0 1 -540664 0 642 862689
2015-8865 480 24 0 0 -151456 0 16 13263
2015-8865 480 160 0 0 -57344 0 <1 63
2015-8865 480 264 0 0 -137344 0 <1 84
2015-8865 480 64 1 0 -499520 0 12 13967
2015-8865 480 40 0 0 -128832 0 25 15113
2015-8865 480 232 0 0 -101376 0 <1 69
2016-5093 544 7360 1 0 84736 0 <1 640
2016-5093 544 16 0 0 -402592 0 4202 5295968
2016-5093 544 32 0 0 -7776 0 2392 3014661
2016-5093 544 8 0 1 -406776 8 6905 9049924
2016-5093 544 24 0 0 -62624 0 202 231884
2016-5093 544 160 0 0 80640 0 <1 104
2016-5093 544 264 0 0 -27712 0 <1 76
2016-5093 544 64 1 0 -410624 0 487 607824
2016-5093 544 40 0 0 -31648 0 15 458
2016-5093 544 232 0 0 77312 0 3 116
2016-7126 1 7360 4 2 495576 0 958 1181098
2016-7126 1 16 0 4 4360 88 4816 6260800
2016-7126 1 32 1 1 398808 64 5594 7272200
2016-7126 1 8 3 2 -32 0 2662 3356935
2016-7126 1 24 3 1 344152 56 4199 5458700
2016-7126 1 160 14 1 483288 24 3005 3864430
2016-7126 1 264 0 1 379064 24 5917 7615179
2016-7126 1 64 1 3 -3912 72 2752 3539072
2016-7126 1 40 5 1 375248 144 7980 10134600
2016-7126 1 232 0 1 439288 40 5673 7908162
18